-- 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;