using System.Text.Json.Serialization; namespace ClawdDotNet.Core.Backup; /// Wie mit Zugangsdaten in der Sicherung verfahren wird. public enum SecretMode { /// /// Zugangsdaten werden entfernt. Die Sicherung ist gefahrlos ablegbar, die /// Wiederherstellung aber unvollständig — Schlüssel und Passwörter müssen /// danach neu eingetragen werden. /// Exclude, /// /// Zugangsdaten werden mit einer Passphrase geschützt. Nur so überstehen sie /// einen Rechner- oder Benutzerwechsel. /// Passphrase, /// /// Die ganze Sicherung wird mit dem Lizenzschlüssel verschlüsselt /// (), die Zugangsdaten reisen mit. /// /// Der Weg, den der Instanzmanager nimmt. Er übersteht einen Maschinenwechsel, /// ohne dass eine Passphrase gespeichert oder eingetippt werden müsste — der /// Lizenzschlüssel ist ohnehin da. Deshalb darf auch die tägliche Sicherung jetzt /// Zugangsdaten enthalten. /// License } public sealed record BackupOptions { public SecretMode Secrets { get; init; } = SecretMode.Exclude; /// Erforderlich bei . public string? Passphrase { get; init; } /// Erforderlich bei . public string? LicenseKey { get; init; } /// Protokolle sind groß und selten nötig. public bool IncludeLogs { get; init; } /// Chatverläufe gehören zum Arbeitsstand, können aber umfangreich sein. public bool IncludeChatHistory { get; init; } = true; } public sealed record RestoreOptions { public string? Passphrase { get; init; } /// /// Für verschlüsselte Sicherungen: der Lizenzschlüssel der Installation, von der sie /// stammt. Passt er nicht, kommt . /// public string? LicenseKey { get; init; } /// Nur prüfen und berichten, nichts schreiben. public bool DryRun { get; init; } /// Vorhandene Dateien im Ziel überschreiben. public bool Overwrite { get; init; } } public sealed record BackupEntry( [property: JsonPropertyName("path")] string Path, [property: JsonPropertyName("size")] long Size, [property: JsonPropertyName("sha256")] string Sha256); public sealed record BackupManifest { /// Erlaubt es späteren Fassungen, ältere Sicherungen zu erkennen. [JsonPropertyName("formatVersion")] public int FormatVersion { get; init; } = 1; [JsonPropertyName("createdAt")] public DateTime CreatedAt { get; init; } [JsonPropertyName("instanceId")] public string InstanceId { get; init; } = ""; [JsonPropertyName("instanceName")] public string InstanceName { get; init; } = ""; [JsonPropertyName("secrets")] public string Secrets { get; init; } = nameof(SecretMode.Exclude); /// Wie viele Zugangsdaten enthalten bzw. entfernt wurden. [JsonPropertyName("secretCount")] public int SecretCount { get; init; } [JsonPropertyName("files")] public List Files { get; init; } = new(); /// /// Enthält die Sicherung Zugangsdaten, die beim Zurückspielen auf den Schlüssel der /// Zielmaschine umgeschlüsselt werden müssen? /// [JsonIgnore] public bool HasSecrets => Secrets is nameof(SecretMode.Passphrase) or nameof(SecretMode.License); } public sealed record BackupResult(string ZipPath, BackupManifest Manifest, long SizeBytes); public sealed record RestoreResult( IReadOnlyList Written, IReadOnlyList Skipped, IReadOnlyList WouldOverwrite) { public bool HasConflicts => WouldOverwrite.Count > 0; } /// Nicht versiegelt: ist ein Sonderfall davon. public class BackupException(string message, Exception? inner = null) : Exception(message, inner);