docs: WORM audit design spec #5

Merged
KofTwentyTwo merged 2 commits from feature/design-spec into develop 2026-10-14 00:27:12 +00:00
KofTwentyTwo commented 2026-10-14 00:19:10 +00:00 (Migrated from github.com)

Summary

Design spec for qbit-worm-audit (docs/DESIGN.md), answering the owner's request for WORM audits, with HIPAA §164.312(b)/(c)(1) and six-year retention in mind. Owner decisions (2026-10-12): all recommendations accepted.

  • Append-only in the database: Postgres triggers reject UPDATE, DELETE and TRUNCATE on audit, audit_detail and every worm_audit_* table, and protect the lookup tables' ids and names. The runtime role gets only INSERT and SELECT. The only removal is worm_audit_purge(), a SECURITY DEFINER function run by a separate worm_audit_purger role, after retention, on a chain prefix only, and recorded (refusals too). Changesets ship as a rendered template.
  • Tamper evidence: a single asynchronous chainer (advisory lock, settle horizon, contiguous link ids, late-arrival and late-detail links) builds link_hash = SHA-256(prev || 0x00 || JCS(audit + details)) in the sidecar table worm_audit_chain. Hourly signed Ed25519 checkpoints carry Merkle roots. "Verify audit chain" is a standard streamed-ETL table action that names the exact break. A daily job alerts through the core QAlerts SPI.
  • Sealed copies: daily contiguous JSONL exports with a manifest and hashes go through qbit-object-storage with Object Lock COMPLIANCE (six years); the exports form their own manifest chain. "Verify sealed export" is the restore and verify tool.
  • PHI: the canonical format is agreed with the qbit-secured-data agent (qqq#1161, §14.2). Only the stored tokens (hmac:v1:, shred:v1:, ...) and value-free messages are hashed and sealed. secured_data_audit_key is never read or exported. A canary test checks there is no plaintext.
  • Assistant wall: worm_audit_* is denied to the assistant channel.
  • App home, tables, permissions, tests (Testcontainers Postgres and MinIO, concurrency), phases (a)/(b)/(c), and the kof22 infra proposal (an Object Lock bucket, a signing key, off-site replication).

🤖 Generated with Claude Code

## Summary Design spec for qbit-worm-audit (`docs/DESIGN.md`), answering the owner's request for WORM audits, with HIPAA §164.312(b)/(c)(1) and six-year retention in mind. **Owner decisions (2026-10-12): all recommendations accepted.** - **Append-only in the database:** Postgres triggers reject UPDATE, DELETE and TRUNCATE on `audit`, `audit_detail` and every `worm_audit_*` table, and protect the lookup tables' ids and names. The runtime role gets only INSERT and SELECT. The only removal is `worm_audit_purge()`, a SECURITY DEFINER function run by a separate `worm_audit_purger` role, after retention, on a chain prefix only, and recorded (refusals too). Changesets ship as a rendered template. - **Tamper evidence:** a single asynchronous chainer (advisory lock, settle horizon, contiguous link ids, late-arrival and late-detail links) builds `link_hash = SHA-256(prev || 0x00 || JCS(audit + details))` in the sidecar table `worm_audit_chain`. Hourly signed Ed25519 checkpoints carry Merkle roots. "Verify audit chain" is a standard streamed-ETL table action that names the exact break. A daily job alerts through the core `QAlerts` SPI. - **Sealed copies:** daily contiguous JSONL exports with a manifest and hashes go through qbit-object-storage with Object Lock COMPLIANCE (six years); the exports form their own manifest chain. "Verify sealed export" is the restore and verify tool. - **PHI:** the canonical format is agreed with the qbit-secured-data agent (qqq#1161, §14.2). Only the stored tokens (`hmac:v1:`, `shred:v1:`, ...) and value-free messages are hashed and sealed. `secured_data_audit_key` is never read or exported. A canary test checks there is no plaintext. - Assistant wall: `worm_audit_*` is denied to the assistant channel. - App home, tables, permissions, tests (Testcontainers Postgres and MinIO, concurrency), phases (a)/(b)/(c), and the kof22 infra proposal (an Object Lock bucket, a signing key, off-site replication). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.