Parquet audit archive: destination/object storage, share + permissions, retention, signing, stale-archive cleanup (#42) #109
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Owner decisions for the Parquet cold archive (#42, off by default):
AuditLog:Archivesection to DEV/QA configs when enabling.Also: the deferred-work register / stillpending.md still describe Parquet as deferred (left untouched per the backlog rule).
Owner decision 2026-11-09: keep the directory/UNC destination (no native object-storage client); configurable retention, default never-delete until compliance names a period; parquet-tools-only reading accepted (no re-import); add cleanup of superseded stale archives; signing follows #107 (head export, no signing). Share name + permissions to be named when it is enabled on DEV/QA.
Done —
b95ee5a6(main). Closing; the share name + permissions are named when the archive is enabled on DEV/QA (#107 item 2 / enablement), no code needed for that.Owner decisions implemented / recorded (Component-AuditLog.md, Retention & Purge; CLAUDE.md):
AuditLog:Archive:RetentionDays— default0= never delete; when set must exceedAuditLog:RetentionDays(startup validation,AuditLogArchiveRetentionValidator), counted from the archived month's end. Expired archives are deleted whenPurged, orArchivedwith no rows left in the partition.verify-headsexposes a rewritten anchor for exported months).AuditLog:Archive:DeleteSupersededStaleArchives(default true), run by the purge actor after every tick: a retried purge'sArchivedarchive is deleted only when a later, verifying,Purgedarchive of the same partition provably holds every row — same prior anchor and the stale chain-end hash at its chain-end sequence (row or tombstone), every unchained row present by EventId. Otherwise reportedKeptStale(e.g. an unchained row a per-channel purge removed in between leaves no tombstone → the stale archive is its only copy). An archive left atArchivedby a crash between switch and manifest update has no later purged archive and is never touched.{Directory}/{YYYY}folder, manifest first, never a path from the manifest; failures surface as purge failures.scadabridge audit archive cleanup [--dry-run]= newCleanupAuditArchivesmanagement command (Administrator only).Evidence:
AuditLogArchiveCleanupTests(MSSQL): retried purge → stale deleted / later kept + still verifies, dry run deletes nothing; stale with a missing row kept; sole copy untouched; retention 0 / not-yet-expired / expired / partition-still-live; tampered manifest path (../../outside.parquet) cannot delete outside. Mutations — dropping the unchained-row proof, following the manifest path, dropping the partition-live check — each fail their test. Plus purge-actor (cleanup every tick incl. no-boundary ticks, failure contained, off when archiving off), validator, management (role gate, dry-run flag, not-configured) and CLI tests.Totals: AuditLog 479, ConfigurationDatabase 531, ManagementService 790, CLI 592, Host 671 — green; build 0 warnings. No migration.
Follow-ups filed: #114 (orphan files of an interrupted archive write), #113, #115.