syncova-backup/migrations/000010_ransomware_signals.up.sql
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

58 lines
2.8 KiB
SQL

-- Signale der Ransomware-Erkennung (Phase 16).
--
-- Der Implementierungsplan (§18) nennt sechs Groessen. Zwei davon berechnet die
-- Anlage bereits bei jedem Lauf und wirft sie weg:
--
-- * Die Zahl der Bloecke, die sich **nicht verkleinern** liessen. Sie ist der
-- Entropie-Indikator: Normale Nutzdaten — Dokumente, Datenbanken,
-- Quelltext — lassen sich fast immer verkleinern, verschluesselte nie.
-- * Die Zahl geloeschter und geaenderter Objekte. Der Agent stellt sie beim
-- Vergleich mit dem Elternbackup fest und protokolliert sie nur.
--
-- Beide nachtraeglich zu ermitteln hiesse, Millionen Bloecke erneut zu lesen.
-- Sie entstehen dort, wo die Daten ohnehin durchlaufen — sie muessen nur
-- abgelegt werden.
ALTER TABLE backups
-- incompressible_chunks ist die Zahl nicht verkleinerbarer neuer Bloecke.
--
-- Gezaehlt werden nur **neue**: Ein deduplizierter Block stammt aus einem
-- frueheren Lauf und sagt nichts ueber die Daten von heute.
ADD COLUMN incompressible_chunks BIGINT,
-- new_chunk_count ist die Zahl neu geschriebener Bloecke.
--
-- Der Nenner zum Entropie-Indikator. Ohne ihn liesse sich aus „500
-- inkompressible Bloecke" nichts ableiten — bei 500 neuen Bloecken ist das
-- alarmierend, bei 500 000 nicht.
ADD COLUMN new_chunk_count BIGINT,
-- changed_file_count ist die Zahl geaenderter oder neuer Objekte.
ADD COLUMN changed_file_count BIGINT,
-- deleted_file_count ist die Zahl seit dem Elternbackup verschwundener Objekte.
--
-- Eine hohe Loeschrate zusammen mit hoher Entropie ist das Muster, das
-- Schadsoftware hinterlaesst: Sie ersetzt Dateien durch verschluesselte
-- Fassungen mit neuer Endung, die alten verschwinden.
ADD COLUMN deleted_file_count BIGINT,
-- extension_distribution haelt die haeufigsten Dateiendungen des Laufs.
--
-- Als JSON und nicht als eigene Tabelle: Die Verteilung wird immer als
-- Ganzes gelesen und nie einzeln abgefragt.
ADD COLUMN extension_distribution JSONB,
ADD CONSTRAINT backups_signal_counts_not_negative CHECK (
COALESCE(incompressible_chunks, 0) >= 0
AND COALESCE(new_chunk_count, 0) >= 0
AND COALESCE(changed_file_count, 0) >= 0
AND COALESCE(deleted_file_count, 0) >= 0
),
-- Es kann nicht mehr inkompressible als neue Bloecke geben. Der Verstoss
-- waere ein Zaehlfehler in der Pipeline, und er faellt sonst nie auf.
ADD CONSTRAINT backups_incompressible_within_new CHECK (
incompressible_chunks IS NULL OR new_chunk_count IS NULL
OR incompressible_chunks <= new_chunk_count
);
-- Fuer die Bildung des Basiswerts: die letzten Laeufe je Kette.
CREATE INDEX backups_baseline_idx ON backups (chain_id, completed_at DESC)
WHERE status = 'complete' AND deleted_at IS NULL;