X1 — Document-level tombstoning. The disposal unit is the document (all versions). Rows
survive with ids/states/audit references intact; content is severed: content_part rows deleted,
part + manifest blobs deleted via ContentStore.delete(hash) (manifest-aware: a part blob is
deleted only when no live manifest still references it), draft_content/title nulled,
document_version.disposed_at stamped (attribute — ADR-0003's state set unchanged). The UI
renders tombstones.
X2 — Single authorized actor, hard re-checks.DISPOSE_RECORDS (effective in the scope)
executes directly; the one transaction re-verifies legal hold clear, all versions closed, and
retention actually elapsed — refusing otherwise (the task's existence is never trusted). The
open DISPOSAL_DUE task resolves via a DocumentDisposed event. A two-person/e-sig ceremony can
layer on later via the review-policy pattern.
X3 — SearchPurge hook, no-op today: the interface is called inside the disposal transaction
(ADR-0025's synchronous-purge contract anchored); the real implementation lands with search.
X4 — Minimal disposal record: retained, append-only disposal_record — document ref +
human-id snapshot, scope, actor, timestamp, retention basis applied (period + closure date),
version and blob counts. Plus the normal audit event.
First destructive path in the system: blob deletion is irreversible in the live system;
backups age out per the ADR-0025 window (operational residual documented there).
Derived copies are unaffected by disposing their source (independent blobs, REQ-DOC-018).
Disposed versions stay visible as tombstones in lists/history (auditable existence, no content).