SPB Git

Repository Public MIT

0006-immutability-and-revocation.md 1.8 KB

# ADR-0006 — Immutable releases enforced by the database, with a separate revocation state

Status: accepted, 2026-11-09.

# Decision

  • 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.
  • Only three things can change afterwards: state (published, quarantined, revoked), the revocation fields, and release_notes.
  • release_files, release_dependencies and audit_events are append-only by the append_only trigger.
  • (artifact_id, version) is unique. Publishing an existing version returns 409 version_exists.
  • The blob is content-addressed and read-only on disk (ADR-0003).
  • 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).
  • The API maps trigger violations to 409 release_immutable.
  • The scope releases:update permits editing release notes and nothing else.

# Why triggers

Application-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.

# Consequences

  • 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.
  • Release notes are mutable metadata; edits are audited with before/after lengths, not content.
  • Approval of a quarantined release changes state only. The advisory scan status recorded at publication never changes.
Files main
Menu

Theme