Closes DEPRECATE-003 in SPRINT_20260408_005. Pre-release status means the 30/90-day compat windows in the original Decision #5 are moot — no external consumers. Decision #5 amended twice during session. Drop migrations (embedded resources, auto-applied on startup per §2.7): - authority.audit / authority.airgap_audit / authority.offline_kit_audit (002_drop_deprecated_audit_tables.sql) - policy.audit (013; policy.gate_bypass_audit PRESERVED as domain evidence) - notify.audit (008) - scheduler.audit + partitions via CASCADE (009) - proofchain.audit_log (004) Kept by design: - release_orchestrator.audit_entries + audit_sequences (hash chain, Decision #2) - policy.gate_bypass_audit (domain evidence, unique query patterns) - authority.login_attempts (auth protocol state, not audit) Repository neutering — local DB write removed, Timeline emission preserved: - PolicyAuditRepository.CreateAsync → Timeline-only; readers [Obsolete] - NotifyAuditRepository.CreateAsync → Timeline-only; readers [Obsolete] - PostgresSchedulerAuditService → removed INSERT, Timeline-only - PostgresAttestorAuditSink.WriteAsync → no-op (endpoint-level .Audited() filter carries the audit signal) Attestor cleanup: - Deleted AuditLogEntity.cs - Removed DbSet<AuditLogEntity> from ProofChainDbContext - Removed LogAuditAsync / GetAuditLogAsync from IProofChainRepository - Removed "audit_log" from SchemaIsolationService Reconciliation tool substitutes for the 30-day wall-clock window: - scripts/audit-reconciliation.ps1 joins each per-service audit table to timeline.unified_audit_events via the dual-write discriminator (details_jsonb.localAuditId / localEntryId) for deterministic pairs, tuple-matches Authority. Test-Table/to_regclass guards handle post-drop vacuous-pass. Overall PASS across pre/post/final runs. - 4 reports under docs/qa/. Sprint archivals: - SPRINT_20260408_004 (Timeline unified audit sink) — all 7 tasks DONE - SPRINT_20260408_005 (audit endpoint filter deprecation) — all 12 tasks DONE Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2.4 KiB
Audit Dual-Write Reconciliation Report
-
Generated: 2026-04-22T14:33:45.9276840+03:00
-
Overall status: PASS
-
Container:
stellaops-postgres -
Database :
stellaops_platform -
Purpose : substitute for the 30-day wall-clock observation window described in SPRINT_20260408_004 (AUDIT-005) and SPRINT_20260408_005 (DEPRECATE-001). Each per-service audit table is reconciled against
timeline.unified_audit_eventsusing the discriminator the repository-level dual-write mapper puts intodetails_jsonb(localAuditId/localEntryId).
Headline counts
| Table | Rows |
|---|---|
authority.audit |
dropped (DEPRECATE-003) |
authority.login_attempts |
0 |
policy.audit |
dropped (DEPRECATE-003) |
notify.audit |
dropped (DEPRECATE-003) |
scheduler.audit |
dropped (DEPRECATE-003) |
release_orchestrator.audit_entries |
0 |
timeline.unified_audit_events |
610 |
policy.audit <-> timeline(module=policy, localAuditId)
Local table policy.audit is dropped (SPRINT_20260408_005 / DEPRECATE-003). Timeline is the sole audit store; reconciliation is vacuous.
| Metric | Value |
|---|---|
| Status | PASS (dropped) |
notify.audit <-> timeline(module=notify, localAuditId)
Local table notify.audit is dropped (SPRINT_20260408_005 / DEPRECATE-003). Timeline is the sole audit store; reconciliation is vacuous.
| Metric | Value |
|---|---|
| Status | PASS (dropped) |
scheduler.audit <-> timeline(module=scheduler, localAuditId)
Local table scheduler.audit is dropped (SPRINT_20260408_005 / DEPRECATE-003). Timeline is the sole audit store; reconciliation is vacuous.
| Metric | Value |
|---|---|
| Status | PASS (dropped) |
release_orchestrator.audit_entries <-> timeline(module IN (release,jobengine), localEntryId)
| Metric | Value |
|---|---|
| Local rows | 0 |
Timeline dual-write rows (details_jsonb ? 'localEntryId') |
0 |
| Missing in Timeline (data loss) | 0 |
| Orphan in Timeline (local cleared post-emission) | 0 |
| Status | PASS |
authority.login_attempts <-> timeline(module=authority) [tuple-match]
AuthorityAuditSink assigns a fresh GUID for the Timeline id, so reconciliation falls back to tuple matching on (action=event_type, timestamp +/- 5s).
| Metric | Value |
|---|---|
authority.login_attempts rows |
0 |
Timeline authority-* rows |
4 |
| Local rows with no Timeline twin | 0 |
| Status | PASS |