Release Orchestrator retention and custody
Release Orchestrator’s consolidated persistence chain owns its runtime schema. RFC-5 reviews the ordinary tables attributed solely to that family. The separate RFC-15 repairs cover domain events, signed audit checkpoints and agent-task cleanup. The nine release.topology_* inventory tables were a copy of Platform’s projection that nothing in Release Orchestrator writes or reads. Under the owner ruling of 2026-09-23 (RFC-14), 009_release_orchestrator_retire_topology_inventory_projection.sql retires that copy. It refuses with SQLSTATE 55000 while any of the nine holds a row, so an estate whose copy still holds rows stops at 009 until an operator has confirmed those rows are a stale copy of Platform’s projection and removed them. release.topology_point_status is not affected. shared.tenants remains the X-new-1 exception.
The source classes and their hash-bound proofs are recorded in the retention inventory. These classifications describe custody; a table declaration alone does not establish that a product feature has a working writer or a complete replay path.
Before an image carrying 009 starts
Check the copy on the target estate first, read-only, in Release Orchestrator’s own database:
SELECT 'region' AS t, count(*) FROM release.topology_region_inventory
UNION ALL SELECT 'watermarks', count(*) FROM release.topology_sync_watermarks;
SELECT max(last_synced_at) FROM release.topology_sync_watermarks;
All nine at zero rows: 009 drops them and startup continues. Any row: 009 stops startup with SQLSTATE 55000 and names the table. Compare the copy’s newest last_synced_at with the same query in Platform’s database; a copy that stopped syncing while Platform’s is current is the stale database-split copy this migration exists to retire. Removing its rows is an operator decision taken before the redeploy, never an automatic step; the procedure (verify, then TRUNCATE the nine in RO’s database only) is the topology copy retirement runbook. Measured on 2026-09-23, the lab estate’s copy held 68 rows last synced 2026-08-22, while Platform’s copy was synced that day.
Audit cleanup
The host registers AuditRetentionService after its startup migration registration. It calls the owned PostgresAuditRetentionStore, which invokes release_orchestrator.cleanup_audit_entries. The forward migration replaces the old unwired routine without changing applied migration files.
ReleaseOrchestrator:AuditRetention setting | Default |
|---|---|
Enabled | true |
RetentionDays | 365 |
BatchSize | 10000 |
MaxBatchesPerSweep | 10 |
SweepInterval | 1.00:00:00 |
StartDelay | 00:05:00 |
Days, batch limits and interval must be positive; the initial delay cannot be negative. Configuration is validated at startup. Each sweep has a finite batch budget and logs its deleted row count; failures retry at the next interval.
For each tenant, cleanup removes only an expired prefix in sequence order. It retains the first in-window entry and every later entry, including backdated entries. If every entry is old, it retains the last entry. Batches preserve that ordering, and a database advisory lock serializes concurrent cleanup calls. The current head remains available for the next append and checkpoint signature.
Sequence allocation state and signed checkpoints are not deleted by this routine. Verification after cleanup covers the retained suffix; it cannot recover expired payloads or certify that the complete historical payload range remains available. Tenant offboarding continues to archive the retained audit data.
Outbox, checkpoint and agent-task cleanup
RFC-15 adds three routines to the same registered AuditRetentionService cycle. Each has its own batch budget, so a backlog in one cannot starve another. Every value is a routine parameter with the default shown, so a correction is a setting, not a migration.
ReleaseOrchestrator:AuditRetention setting | Default | Routine |
|---|---|---|
DomainEventRetentionDays | 365 | release_orchestrator.cleanup_domain_events |
CheckpointRetentionDays | 365 | release_orchestrator.cleanup_audit_chain_checkpoints |
AgentTaskRetentionDays | 90 | release_orchestrator_agent.cleanup_agent_tasks |
AgentTaskMaxTerminalRowsPerTenant | 10000 | release_orchestrator_agent.cleanup_agent_tasks |
- Domain events. Rows older than the window on
occurred_atare removed, but only as a contiguous id prefix perevent_type, and the highest id of every type is kept. The Scanner Worker bridges poll by ascending id and keep their cursor in memory only, so a consumer never steps over a surviving older row. A consumer stopped for longer than the window loses the events it did not read. - Signed checkpoints. Rows older than the window on
signed_atare removed, except each tenant’s current anchor, whichVerifyLatestAsyncreads and which is kept at any age.CheckpointRetentionDaysmust be at leastRetentionDays: the options refuse a shorter value at startup, and the routine refuses it with SQLSTATE22023. - Agent tasks. Only
succeededandfailedrows are removed, after the window onCOALESCE(completed_at, updated_at)or beyond the newest terminal rows per tenant. Queued and assigned tasks are never removed. The table isoperational-state.
The Doctor check doctor.release-orchestrator.retention.backlog counts the rows these three routines would remove now, with the same predicates. A healthy host reports zero within one sweep interval.
Captured records and projections
Release definitions, selected component digests, deployment execution results, authorization decisions, script versions and operator configuration remain records of authority. A terminal status does not make original command output, approval attribution or a dispatch’s deduplication identity safe to erase.
The following former projection labels now preserve captured records on tenant offboarding by archiving them:
- Target readiness status, including the observation timestamp and diagnostics.
- Deployment share-grant approvals, including the approving subject and time.
- Accepted estate drift observations.
- Captured estate verdicts and their input hashes.
- First-signal snapshots: the current RO service stores upstream payloads and has no run/job recomputation path. Explicit invalidation and corrupt-payload removal remain distinct from an asserted ability to rebuild a deleted snapshot.
deployed_estate remains rebuildable through DeployedEstateProjector from retained terminal deployment and release-component data. The static tenant-disposal catalog is checked against the current embedded forward chain, not only the baseline.
release.releases remains a retained parent referenced by freeze-window exemptions. The review found no current production writer for that old parent; its existence must not be presented as a working release-write path. Fixing that dependency is separate from retention classification and does not authorize dropping its child data.
Verification
Verified against source commit e513c2198e03cd13ffcbfcc1092196ca06696911. The verification receipt records executed checks, negative controls and source census scope.
Re-run AuditRetentionIntegrationTests, DomainEventRetentionIntegrationTests, AuditChainCheckpointRetentionIntegrationTests, AgentTaskRetentionIntegrationTests and ReleaseOrchestratorTenantDisposalConformanceTests with the repository’s targeted xUnit helper, plus the consolidated persistence suite. The PostgreSQL tests exercise the registered worker, finite batching, nonmonotonic timestamps, retained chain heads, unchanged checkpoint bytes, later append/verification and invalid routine parameters.
The source commit, exact counts and five P13 gate results are recorded in the Program sprint. RFC-5 does not itself build or deploy a production image.
Owner capacity monitoring (DIP-17)
The web host’s capacity probe uses its explicit Doctor owner pool for measurement, receipt storage and PostgreSQL leases. It does not inherit the ambient KEK pool. Migration 014_capacity_probe_receipt.sql creates release_orchestrator.capacity_probe_receipt; each insert retains the newest 90 receipts. doctor.release-orchestrator.capacity.budget measures the 28 registered entries and fails on absent required measurements, missing/stale receipts or stop-line breaches. This does not complete the family’s 44 identity-declaration reviews.
The capacity guide records the monitoring envelope and dated measurements. Deployment, approval, script and custody records gain no new disposal rule; the probe does not intercept their writers. A pause flag is a required action rather than observed enforcement. ReleaseOrchestratorDoctorAdoptionTests includes an actual owner-versus-ambient database control and verifies the owner’s migration, receipt and fenced lease. Run it with the targeted xUnit wrapper and -BuildProjectReferences.
