SPB Git

Repository Public MIT

0006-immutability-and-revocation.md 1.8 KB 25 lines markdown

1# ADR-0006 — Immutable releases enforced by the database, with a separate revocation state23Status: accepted, 2026-11-09.45## Decision67- A release row is written once. The trigger `releases_immutable` rejects any `UPDATE` that changes the artifact, version, manifest, object key, checksum, sizes, file count, source commit, README, publisher, publication time or scan status, and rejects every `DELETE`.8- Only three things can change afterwards: `state` (`published`, `quarantined`, `revoked`), the revocation fields, and `release_notes`.9- `release_files`, `release_dependencies` and `audit_events` are append-only by the `append_only` trigger.10- `(artifact_id, version)` is unique. Publishing an existing version returns 409 `version_exists`.11- The blob is content-addressed and read-only on disk (ADR-0003).12- A compromised version is **revoked**: downloads return 410 with the public reason, the record and its audit trail stay, and `latest` moves to the best remaining version (highest stable, otherwise highest prerelease).13- The API maps trigger violations to 409 `release_immutable`.14- The scope `releases:update` permits editing release notes and nothing else.1516## Why triggers1718Application-level checks protect against honest mistakes in one code path. Triggers also cover future code, the admin console, and ad hoc SQL by an operator. The tests update and delete rows directly with SQL and assert that PostgreSQL refuses.1920## Consequences2122- There is no "unpublish". Removing content requires revocation (version) or takedown (artifact); erasing bytes for legal reasons is a manual operator procedure that must itself be recorded.23- Release notes are mutable metadata; edits are audited with before/after lengths, not content.24- Approval of a quarantined release changes `state` only. The advisory scan status recorded at publication never changes.25
Files main
Menu

Theme