Evidence retention classification
The Evidence family retains captured evidence, signing material, custody rules and verification outcomes as source records. Re-evaluating against current trust material does not reconstruct an earlier observation. RFC-8 adds lifecycle enforcement for alert suppression state and completed re-timestamp mechanics.
Reclamation
| State | Bound and caller | Preserved state |
|---|---|---|
| Identity alert deduplication | Evidence web registers AlertDedupRetentionService; an immediate pass and hourly passes remove at most ten batches of 1,000 rows. A row must exceed both seven days and the current watchlist’s suppression window. | Recent suppression, windows longer than seven days, refreshed rows, watchlist definitions and all evidence. Orphaned suppression rows retain the seven-day floor. |
| Rekor submission queue (RFC-17) | Evidence worker’s RekorRetryWorker runs an hourly retention pass whether or not work is waiting. Submitted and dead-letter rows are removed after 30 days on updated_at each, and terminal rows beyond the newest 10,000 per tenant. RekorQueueOptions carries all three bounds under attestor:rekorQueue. | Pending, submitting and retrying rows at any age. The transparency log each submitted row was sent to remains the durable record. |
| Timestamp trust snapshots and their authentication (RFC-15) | Evidence worker registers CounselRetentionReclamationService; hourly passes visit active tenants and remove at most ten batches of 1,000 per tenant through evidence.reclaim_timestamp_trust_snapshots. A snapshot is reclaimed once the longest R its tenant’s timestamp retention profiles declare has elapsed since it was retrieved. Its authentication rows go in the same pass. | Every snapshot a qualification result references, at any age. Every snapshot whose payload or authentication object an unreleased hold pins, and everything while an unreleased tenant-wide hold exists, including one whose expires_at has passed. Every snapshot of a tenant with no retention profile. The shared content-addressed objects are never deleted by this pass. Every other UPDATE or DELETE still raises EL012. |
| Regulatory artifact ledger map (RFC-15) | The same service tombstones at most ten batches of 1,000 maps per tenant through evidence_locker.reclaim_regulatory_artifact_ledger_maps. A map is due once the latest of its retention record’s retain_until, its created_at plus retention_years, the ledger row’s own created_at plus retention_years, and legal_hold_until has passed. The source references, signature reference, signer key and audit-event links are cleared, and map_reclaimed_at is set. | The row itself, its id, regime, artifact type, content hash, schema pins and retention link. Any map a bundle or decision capsule names, any map under an active legal hold or an unreleased hold, any map with no retention record, and any map whose record is dora-roi-snapshot or tlpt-evidence-pack. A later filing of the same artifact restores the map. |
| Re-timestamp queue | Evidence worker registers RetimestampQueueRetentionService; immediate and hourly passes visit active tenants from the converged local tenant replica. Completed, fully released work retains 90 days or the newest 10,000 eligible rows per tenant. Each pass removes at most ten batches of 1,000 per tenant. | Pending, leased, failed, cancelled and incomplete terminal rows. Every unreleased tenant-wide or bundle hold blocks disposal, including one whose expires_at has passed. Original execution audit, approvals, tokens and successor evidence remain intact. |
The re-timestamp budgets are explicit code constants in PostgresRetimestampQueueRetention; they apply to completed work mechanics, not the governing evidence-retention period. The database rechecks completion time, state and lease fields after selecting candidates. Hold insertion/release and cleanup serialize through the hold table lock. Both cleanup and measurement use a tenant RLS session; neither disables RLS or uses a privileged bypass.
doctor.evidence.retention.retimestamp-queue-budget reports outstanding age/row-budget debt and incomplete terminal metadata. Tenant-replica failure is unhealthy, not a zero-row success. Held rows are excluded from the cleanup budget. Inactive tenants remain the tenant-lifecycle workflow’s responsibility; this keeper does not discover or sweep them through a cross-tenant table scan.
Retained records
The forward classification migration covers these original records:
- Attestor: bulk verification requests and captured item outcomes, accepted entries, configured external transparency targets and authored identity watchlists.
- Timestamp Assurance: exact validation objects, runs and check results, qualification results, reissues, retention profiles, object/snapshot references and legal-hold pins.
- Evidence Locker: decision capsules, bundles, artifacts, signatures, gate material, holds, packs and their ordered membership, regulatory retention records and verdict attestations.
- ProofChain: signed envelopes, SBOM subjects, trust anchors, predicate registry and accepted graph nodes/edges. The graph API accepts metadata and relationships that the entry projection alone cannot reconstruct.
The original assurance-run/result comments called them rebuildable. Their current writer records evaluation time, code/configuration digests and observed check evidence; there is no production path that recreates every original observation. They are now classified as source records. Bulk verification similarly keeps each returned result and failure detail; its verification service does not independently persist the full response in the verdict ledger.
These classes do not grant a generic deletion right. Existing immutability triggers, hash chains, hold restrictions, capsule tombstones and the timestamp retention formula continue to govern custody. R remains the longest applicable parent-evidence, statutory, contractual, dispute and investigation period, extended by active holds. Shared validation objects need both zero references and zero active holds before deletion. Counsel-pinned claim wording is unchanged.
Five separate review subjects remain outside RFC-8: timestamp trust snapshots and authentication plus regulatory artifact-ledger reconstruction (RFC-15), the unqualified verdict-ledger declaration (RFC-16), and Rekor submission transport (RFC-17).
RFC-15 (2026-09-23) closed its three under the owner’s ruling on counsel’s R. 011_evidence_counsel_retention_reclamation.sql resolves periods that are already declared and chooses none. For the two timestamp trust tables that is R, from timestamp_retention_profiles.effective_retention_period. For the ledger it is regulatory_retention_records.retention_years. The refusal is counsel’s truth table evidence.timestamp_assurance_object_may_delete: a nonzero reference count or hold count keeps a row at any age. The sweep and each table’s row trigger apply it. The trust tables stay append-audit. The ledger is source-of-truth, because its writers upsert the map in place and add source references that no audit event carries, so the map cannot be recomputed. Its reclamation therefore tombstones the map and keeps the row. doctor.evidence.retention.counsel-retention-backlog reports reclaimable rows as the backlog. It also reports, without going unhealthy, the rows a reference or hold keeps past their horizon. Re-verify with tools/scripts/test-targeted-xunit.ps1 -Project src/Evidence/__Tests/StellaOps.Evidence.WebService.Tests/StellaOps.Evidence.WebService.Tests.csproj -Class "*CounselRetentionReclamationTests" -BuildProjectReferences.
RFC-17 (2026-09-23) closed the Rekor submission queue. 010_evidence_rekor_queue_retention.sql records operational-state in place of the out-of-vocabulary operational label, and doctor.evidence.retention.rekor-queue-backlog measures the terminal backlog. Re-verify with tools/scripts/test-targeted-xunit.ps1 -Project src/Evidence/__Tests/StellaOps.Evidence.WebService.Tests/StellaOps.Evidence.WebService.Tests.csproj -Class "*RekorSubmissionQueueRetentionTests" -BuildProjectReferences.
Verification
Verified against source commit d67f4ef0391d6587fe7879f795a3d90dc858513d. The dated verification receipt records the executed tests and census. Re-run the focused integration suites with tools/scripts/test-targeted-xunit.ps1 -BuildProjectReferences -Restore: the Watchlist project’s AlertDedupRetentionTests, the Evidence web project’s RetimestampQueueRetentionTests and EvidenceDoctorAdoptionTests, and the Evidence persistence schema suites. tools/scripts/validate/check-p13-retention.py --repo-root . provides the source-inventory gate; --tables, --owners, --owners --strict and --self-test are separate checks.
Acceptance is against isolated PostgreSQL databases and the composed runtime services. It does not claim a live deployment or a completed production sweep.
Owner capacity monitoring (DIP-17)
Evidence web runs the leased capacity probe on its explicit Evidence owner pool. Migration 016_capacity_probe_receipt.sql creates evidence.capacity_probe_receipt and bounds it to the latest 90 measurements. The probe covers the 18 registered entries across Evidence-owned schemas; the other 28 identity declarations remain a separate review subject. doctor.evidence.capacity.budget fails on missing/stale receipts, missing required measurements and stop-line breaches. It reports aggregate capacity, never evidence payloads.
The capacity guide states the initial monitoring envelope and its measurement limitations. No hold, counsel period, immutable evidence or writer admission changes follow from a receipt. A writer-pause flag means pause required; adoption must be proved at the actual writer. EvidenceCapacityAdoptionTests starts the real host on a fresh isolated database and checks the registered probe and Doctor; run it with the targeted wrapper and -BuildProjectReferences.
