syncova-backup/SYNCOVA_DATABASE.md
Jerrit Fritzsche 610719c316
Some checks failed
CI / Backend (Go) (push) Failing after 3m7s
CI / Frontend (React/TypeScript) (push) Successful in 37s
CI / Sicherheitsprüfungen (push) Successful in 44s
Syncova Backups V1
Enterprise-Backup-, Recovery-, Verification-, Security- und
Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme.

Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als
vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit
nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem
tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes
geht in keine Bewertung als "gut" ein.

Umfang (Phasen 0-23):

- Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll,
  Katalogaufbau allein aus den Manifesten — ohne Datenbank
- Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz
  Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck
- Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell)
- Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive
- Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit
- Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center,
  Ransomware-Heuristik (meldet, handelt nie)
- Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing
- Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository
- Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64

Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup
Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs.

Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die
systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine
wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md
und docs/release-candidate.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 09:10:54 +02:00

9.8 KiB

Syncova Backups V1 — PostgreSQL Database Design

1. Database Rules

  • PostgreSQL is the control-plane database.
  • Backup payloads are never stored in PostgreSQL.
  • UUIDs are preferred for public identifiers.
  • All timestamps are UTC.
  • Foreign keys are mandatory for relationships.
  • Use soft deletion where audit/history requires it.
  • Never store passwords or raw encryption keys.
  • Every schema change uses a migration.

2. Core Tables

users

id UUID PRIMARY KEY
username TEXT UNIQUE NOT NULL
email TEXT UNIQUE
password_hash TEXT
status TEXT NOT NULL
mfa_enabled BOOLEAN NOT NULL DEFAULT FALSE
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL
last_login_at TIMESTAMPTZ

user_mfa_methods

id UUID PRIMARY KEY
user_id UUID REFERENCES users(id)
type TEXT NOT NULL
secret_ciphertext BYTEA
enabled BOOLEAN NOT NULL
created_at TIMESTAMPTZ NOT NULL

roles

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
description TEXT

permissions

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
description TEXT

role_permissions

role_id UUID REFERENCES roles(id)
permission_id UUID REFERENCES permissions(id)
PRIMARY KEY(role_id, permission_id)

user_roles

user_id UUID REFERENCES users(id)
role_id UUID REFERENCES roles(id)
PRIMARY KEY(user_id, role_id)

3. Agents

agents

id UUID PRIMARY KEY
name TEXT NOT NULL
hostname TEXT
platform TEXT NOT NULL
version TEXT
status TEXT NOT NULL
last_heartbeat_at TIMESTAMPTZ
registered_at TIMESTAMPTZ NOT NULL
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

agent_certificates

id UUID PRIMARY KEY
agent_id UUID REFERENCES agents(id)
fingerprint TEXT UNIQUE NOT NULL
not_before TIMESTAMPTZ
not_after TIMESTAMPTZ
status TEXT NOT NULL
created_at TIMESTAMPTZ NOT NULL

4. Proxmox

proxmox_clusters

id UUID PRIMARY KEY
name TEXT NOT NULL
api_endpoint TEXT NOT NULL
credential_ref TEXT NOT NULL
status TEXT NOT NULL
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

proxmox_hosts

id UUID PRIMARY KEY
cluster_id UUID REFERENCES proxmox_clusters(id)
node_name TEXT NOT NULL
status TEXT NOT NULL
last_seen_at TIMESTAMPTZ
created_at TIMESTAMPTZ NOT NULL

virtual_machines

id UUID PRIMARY KEY
cluster_id UUID REFERENCES proxmox_clusters(id)
host_id UUID REFERENCES proxmox_hosts(id)
provider_vm_id TEXT NOT NULL
name TEXT NOT NULL
status TEXT
cpu_count INTEGER
memory_bytes BIGINT
config_json JSONB
last_discovered_at TIMESTAMPTZ
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL
UNIQUE(cluster_id, provider_vm_id)

5. Repositories

repositories

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
type TEXT NOT NULL
endpoint TEXT NOT NULL
status TEXT NOT NULL
capacity_bytes BIGINT
used_bytes BIGINT
free_bytes BIGINT
immutable BOOLEAN NOT NULL DEFAULT FALSE
encryption_required BOOLEAN NOT NULL DEFAULT TRUE
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

repository_health

id UUID PRIMARY KEY
repository_id UUID REFERENCES repositories(id)
health_status TEXT NOT NULL
latency_ms DOUBLE PRECISION
error_count BIGINT DEFAULT 0
checked_at TIMESTAMPTZ NOT NULL
details JSONB

6. Backup Jobs

backup_jobs

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
description TEXT
status TEXT NOT NULL
priority TEXT NOT NULL
schedule_type TEXT NOT NULL
schedule_config JSONB NOT NULL
retention_policy_id UUID
repository_id UUID REFERENCES repositories(id)
encryption_policy_id UUID
verification_policy_id UUID
notification_policy_id UUID
rpo_seconds BIGINT
rto_seconds BIGINT
bandwidth_limit_bps BIGINT
max_concurrency INTEGER
created_by UUID REFERENCES users(id)
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

backup_job_sources

id UUID PRIMARY KEY
job_id UUID REFERENCES backup_jobs(id)
source_type TEXT NOT NULL
source_id UUID
include_patterns JSONB
exclude_patterns JSONB
created_at TIMESTAMPTZ NOT NULL

7. Backup Runs

backup_job_runs

id UUID PRIMARY KEY
job_id UUID REFERENCES backup_jobs(id)
status TEXT NOT NULL
started_at TIMESTAMPTZ
completed_at TIMESTAMPTZ
bytes_processed BIGINT DEFAULT 0
bytes_written BIGINT DEFAULT 0
bytes_transferred BIGINT DEFAULT 0
throughput_bps BIGINT
error_code TEXT
error_message TEXT
correlation_id UUID NOT NULL
created_at TIMESTAMPTZ NOT NULL

8. Backups and Chains

backup_chains

id UUID PRIMARY KEY
source_id UUID NOT NULL
status TEXT NOT NULL
created_at TIMESTAMPTZ NOT NULL

backups

id UUID PRIMARY KEY
job_run_id UUID REFERENCES backup_job_runs(id)
chain_id UUID REFERENCES backup_chains(id)
repository_id UUID REFERENCES repositories(id)
parent_backup_id UUID REFERENCES backups(id)
backup_type TEXT NOT NULL
consistency_level TEXT
status TEXT NOT NULL
manifest_ref TEXT NOT NULL
logical_bytes BIGINT
unique_bytes BIGINT
compressed_bytes BIGINT
encrypted_bytes BIGINT
started_at TIMESTAMPTZ
completed_at TIMESTAMPTZ
integrity_status TEXT
verified_at TIMESTAMPTZ
immutable_until TIMESTAMPTZ
created_at TIMESTAMPTZ NOT NULL

9. Chunks

The database stores references/index information, not chunk payloads.

chunks

id UUID PRIMARY KEY
repository_id UUID REFERENCES repositories(id)
content_hash TEXT NOT NULL
size_bytes BIGINT NOT NULL
compressed_size_bytes BIGINT
encryption_version TEXT
storage_ref TEXT NOT NULL
created_at TIMESTAMPTZ NOT NULL
UNIQUE(repository_id, content_hash)

chunk_references

backup_id UUID REFERENCES backups(id)
chunk_id UUID REFERENCES chunks(id)
sequence_no BIGINT NOT NULL
logical_offset BIGINT
length_bytes BIGINT
PRIMARY KEY(backup_id, sequence_no)

10. Restore

restore_jobs

id UUID PRIMARY KEY
backup_id UUID REFERENCES backups(id)
source_type TEXT NOT NULL
target_type TEXT NOT NULL
target_ref TEXT
status TEXT NOT NULL
started_at TIMESTAMPTZ
completed_at TIMESTAMPTZ
bytes_restored BIGINT
error_code TEXT
error_message TEXT
created_by UUID REFERENCES users(id)
created_at TIMESTAMPTZ NOT NULL

restore_sessions

id UUID PRIMARY KEY
restore_job_id UUID REFERENCES restore_jobs(id)
state TEXT NOT NULL
checkpoint JSONB
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

11. Verification

verification_jobs

id UUID PRIMARY KEY
backup_id UUID REFERENCES backups(id)
type TEXT NOT NULL
status TEXT NOT NULL
started_at TIMESTAMPTZ
completed_at TIMESTAMPTZ
created_at TIMESTAMPTZ NOT NULL

verification_results

id UUID PRIMARY KEY
verification_job_id UUID REFERENCES verification_jobs(id)
check_name TEXT NOT NULL
status TEXT NOT NULL
details JSONB
created_at TIMESTAMPTZ NOT NULL

12. Alerts and Events

alert_rules

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
enabled BOOLEAN NOT NULL DEFAULT TRUE
severity TEXT NOT NULL
condition JSONB NOT NULL
actions JSONB NOT NULL
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

alerts

id UUID PRIMARY KEY
rule_id UUID REFERENCES alert_rules(id)
severity TEXT NOT NULL
status TEXT NOT NULL
title TEXT NOT NULL
message TEXT NOT NULL
entity_type TEXT
entity_id UUID
created_at TIMESTAMPTZ NOT NULL
acknowledged_at TIMESTAMPTZ
resolved_at TIMESTAMPTZ

events

id UUID PRIMARY KEY
event_type TEXT NOT NULL
severity TEXT NOT NULL
entity_type TEXT
entity_id UUID
message TEXT NOT NULL
details JSONB
correlation_id UUID
created_at TIMESTAMPTZ NOT NULL

13. Audit

audit_events

id UUID PRIMARY KEY
user_id UUID REFERENCES users(id)
action TEXT NOT NULL
entity_type TEXT
entity_id UUID
result TEXT NOT NULL
ip_address INET
user_agent TEXT
details JSONB
correlation_id UUID
created_at TIMESTAMPTZ NOT NULL

Audit data should be append-oriented.

14. Metrics

metrics

id BIGSERIAL PRIMARY KEY
metric_name TEXT NOT NULL
entity_type TEXT
entity_id UUID
value DOUBLE PRECISION NOT NULL
unit TEXT
timestamp TIMESTAMPTZ NOT NULL
labels JSONB

Use indexes on:

(metric_name, timestamp)
(entity_type, entity_id, timestamp)

For large installations, introduce time partitioning and rollups.

15. Policies

retention_policies

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
rules JSONB NOT NULL
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

encryption_policies

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
algorithm TEXT NOT NULL
key_ref TEXT NOT NULL
rotation_policy JSONB
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

verification_policies

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
rules JSONB NOT NULL
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

notification_policies

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
channels JSONB NOT NULL
rules JSONB NOT NULL
created_at TIMESTAMPTZ NOT NULL
updated_at TIMESTAMPTZ NOT NULL

16. Certificates and Configuration

certificates

id UUID PRIMARY KEY
name TEXT UNIQUE NOT NULL
type TEXT NOT NULL
fingerprint TEXT UNIQUE NOT NULL
not_before TIMESTAMPTZ
not_after TIMESTAMPTZ
status TEXT NOT NULL
secret_ref TEXT
created_at TIMESTAMPTZ NOT NULL

system_settings

key TEXT PRIMARY KEY
value_json JSONB NOT NULL
updated_at TIMESTAMPTZ NOT NULL
updated_by UUID REFERENCES users(id)

Create indexes for:

  • backup_jobs(status)
  • backup_job_runs(job_id, started_at DESC)
  • backups(repository_id, completed_at DESC)
  • backups(chain_id, completed_at DESC)
  • backups(parent_backup_id)
  • virtual_machines(cluster_id)
  • agents(status)
  • alerts(status, severity, created_at DESC)
  • events(created_at DESC)
  • audit_events(created_at DESC)
  • metrics(metric_name, timestamp DESC)

18. Migration Strategy

Use a migration tool such as:

  • golang-migrate
  • Atlas

Every schema change must be versioned.

Production startup must never silently mutate the schema.