Files
ModelForge/docs/architecture/adr/0042-immutable-verified-backup-sets.md

36 lines
1.8 KiB
Markdown

# ADR-0042: Immutable verified backup sets
## Status
Accepted in M15 on 2026-08-27.
## Decision
Make `BackupSet` immutable recovery identity, sealed by `immutable_at` once written, carrying the
ModelForge version and commit, the canonical repository and reference, the Alembic revision, the
PostgreSQL server identity and tool version, the destination, the hashed manifest and payload, the
included and excluded asset classes and the encryption identity.
Treat verification, not creation, as the gate. Only `VERIFIED` is restore eligible, and verification
checks the manifest hash, manifest-to-journal agreement, the presence of a database payload, every
object's size and hash at an allowlisted path, decryption against the recorded plaintext hash, and
archive readability. Anything else fails closed with a typed code.
Protect the last known-good backups from retention unconditionally, and reconcile any backup
interrupted mid-write to `FAILED`.
## Consequences
A backup cannot look usable because a file exists. A single flipped byte in a 5.4 MB encrypted
payload, a one-integer edit to a manifest entry, a wrong encryption key and a mid-write interruption
were each caught in live rehearsal with `HASH_MISMATCH`, `MANIFEST_HASH_MISMATCH`,
`DECRYPTION_FAILED` and `MANIFEST_INCOMPLETE`, and none of them could become a restore plan.
Immutability across several flushes required loosening the immutability guard to permit exactly the
sealing flush — a backup is planned, written and only then stamped — while still rejecting every
later change to identity fields.
The platform can never retain zero recovery points because a timer expired, and a backup can never
contain a record of itself as complete, so a restored plane consistently reports the backup it came
from as not restore eligible.