SC-A13 Audit Archiver Runbook
Issue: #1493 | Job: backend_v2/jobs/audit_archiver.py
Overview
The SC-A13 archiver job exports audit rows to S3 on a monthly (or on-demand)
schedule and prepares the legacy audit_log tables for the Phase 4 drop:
- Unified archival —
customer_audit_eventsrows older than the retention threshold (default 7 years, SOC-2) are exported to S3 Glacier and then deleted from Postgres, using theaudit_archiverrole (SELECT + DELETE only — seebackend_v2/alembic/versions/0056_audit_archiver_grants.py). - Legacy archival — all rows from Raptor and Console
audit_logare exported to S3 Standard storage (immediately queryable) as a backup, ahead of the Phase 4 legacy-table drop. Legacy rows are not deleted by this job.
Prerequisites
AUDIT_ARCHIVER_DATABASE_URLset to a DSN authenticated as theaudit_archiverPostgres role (production). Without this, the job falls back to the default Raptor engine and logs a warning — acceptable in dev/test only.CONSOLE_DATABASE_URLset for Console legacy archival (optional — skipped with a warning if absent).S3_BUCKET_AUDIT_ARCHIVEset (defaultraxx-audit-archive).- The
audit_archiverPostgres role must already exist with the grants from migration 0056 applied.
Running the job
# One-time bucket bootstrap (idempotent; Object-Lock eligible, WORM NOT activated)
python -m jobs.audit_archiver --create-bucket --tables unified --dry-run
# Full monthly run
python -m jobs.audit_archiver
CLI flags:
| Flag | Default | Effect |
|---|---|---|
--dry-run |
off | Compute batches/metadata; no S3 upload, no DELETE, no manifest row |
--tables |
unified legacy_raptor legacy_console |
Subset to process |
--batch-size |
10000 | Rows per S3 export batch |
--retention-years |
7 | Unified-table cutoff (SOC-2) |
--create-bucket |
off | Idempotently create the S3 bucket first |
S3 path structure
Unified (Glacier): s3://<bucket>/unified/customer_audit_events/<year>/<month>/<run_id>-batch<NNNN>.json
Legacy (Standard): s3://<bucket>/legacy/<table>/<year>/<month>/<run_id>-batch<NNNN>.json
<table> for legacy exports is audit_log_raptor or audit_log_console.
Objects are newline-delimited JSON (application/x-ndjson).
Object Lock (WORM)
--create-bucket creates the bucket with ObjectLockEnabledForBucket=True
(eligible), but applies no default retention or legal-hold configuration.
WORM activation for SOC-2 audit readiness is a Phase 2 follow-up card — do not
activate it as part of this job.
Manifest
Every table processed in a run writes one row to audit_archival_runs with
run_type = 'cold_export' (the value reserved for SC-A13 by migration 016).
manifest_path holds the S3 prefix for that table; error_detail is a JSON
blob with table, date_range_start, date_range_end, and error (null on
success).
SELECT run_type, status, rows_exported, rows_deleted, manifest_path, error_detail
FROM audit_archival_runs
WHERE run_type = 'cold_export'
ORDER BY started_at DESC
LIMIT 10;
Operator test query (post legacy-archival sign-off)
After a legacy archival run, confirm the S3 archive is queryable before proceeding toward the Phase 4 drop. Using the AWS CLI:
# List objects written by the run
aws s3 ls s3://raxx-audit-archive/legacy/audit_log_raptor/ --recursive
# Fetch one object and spot-check a row
aws s3 cp s3://raxx-audit-archive/legacy/audit_log_raptor/<year>/<month>/<key> - | head -n 1 | python3 -m json.tool
Legacy exports use STANDARD storage class specifically so this query works immediately — no Glacier restore delay. Sign off in the SC-A13 issue/PR comment once a spot-checked row matches the source table.
Retrieval SLA (unified / Glacier)
Unified rows are exported to Glacier and then deleted from Postgres. Retrieval
for an audit investigation requires an S3 Glacier restore request, which can
take hours. Prefer customer_audit_events for recent data (last 7 years, still
live) — Glacier retrieval is a break-glass path for investigations that predate
the retention window.
Related
- Issue: #1493 (SC-A13)
- Depends on: SC-A9 back-fill (#1489, closed) —
docs/ops/runbooks/sc-a9-audit-backfill.md backend_v2/alembic/versions/0056_audit_archiver_grants.py—audit_archiverrole grantsbackend_v2/db/migrations/016_unified_audit_v2_schema.sql—audit_archival_runsschema