package models import "time" type BackupMethod string const ( MethodRsync BackupMethod = "rsync" MethodRestic BackupMethod = "restic" MethodExternal BackupMethod = "external" ) type BackupTarget struct { ID string `json:"id"` Name string `json:"name"` Method BackupMethod `json:"method"` Remote string `json:"remote"` // destination: rsync target path (e.g. "user@host:/path") or restic repository string (e.g. "/mnt/backup/repo", "s3:s3.amazonaws.com/bucket/path", "sftp:user@host:/path") Params map[string]string `json:"params,omitempty"` Schedule string `json:"schedule,omitempty"` // cron expression (5-field, standard). Empty = manual-only. LastRun *time.Time `json:"last_run,omitempty"` NextRun *time.Time `json:"next_run,omitempty"` } type BackupExecution struct { ID string `json:"id"` Timestamp time.Time `json:"timestamp"` Success bool `json:"success"` Duration int64 `json:"duration_seconds"` Message string `json:"message"` TargetID string `json:"target_id,omitempty"` } type BackupConfig struct { SourcePath string `json:"source_path,omitempty"` Targets []BackupTarget `json:"targets"` NextRun *time.Time `json:"next_run,omitempty"` // aggregate: earliest NextRun across Targets LastRun *time.Time `json:"last_run,omitempty"` // aggregate: latest LastRun across Targets History []BackupExecution `json:"history"` } type UpdateRecord struct { ID string `json:"id"` Timestamp time.Time `json:"timestamp"` Success bool `json:"success"` Packages []string `json:"packages,omitempty"` Message string `json:"message"` } type NodeInfo struct { Hostname string `json:"hostname"` Description string `json:"description,omitempty"` UpdateHistory []UpdateRecord `json:"update_history"` Backup BackupConfig `json:"backup"` ResticPassword string `json:"restic_password,omitempty"` // repository password used to encrypt/decrypt all restic backup targets on this node } type RemoteNode struct { ID string `json:"id"` Name string `json:"name"` URL string `json:"url"` Status string `json:"status"` Description string `json:"description,omitempty"` Tags []string `json:"tags,omitempty"` LastSeen *time.Time `json:"last_seen,omitempty"` } type Service struct { ID string `json:"id"` Name string `json:"name"` ComposeFile string `json:"compose_file"` ComposeType string `json:"compose_type,omitempty"` BackupFolder string `json:"backup_folder,omitempty"` Status string `json:"status,omitempty"` // "up", "down", "unknown" StopOnBackup bool `json:"stop_on_backup,omitempty"` ExternalBackupStopMinutes int `json:"external_backup_stop_minutes,omitempty"` ExternalBackupStartMinutes int `json:"external_backup_start_minutes,omitempty"` Backup *BackupConfig `json:"backup,omitempty"` } type ScanResult struct { ScannedPaths []string `json:"scanned_paths"` Found int `json:"found"` Created []ServiceScanInfo `json:"created"` Updated []ServiceScanInfo `json:"updated"` Errors []string `json:"errors,omitempty"` } type ServiceScanInfo struct { Name string `json:"name"` ComposeFile string `json:"compose_file"` BackupFolder string `json:"backup_folder,omitempty"` Status string `json:"status"` } type AppConfig struct { Node NodeInfo `json:"node"` Nodes []RemoteNode `json:"nodes"` Services []Service `json:"services"` }