docs(audit): hash-chain tamper evidence shipped, default off (ScadaBridge#41)

Component-AuditLog Security & Tamper-Evidence describes the per-month chain,
the chaining job and its lock, both purge paths (checkpoint anchor,
tombstones), pre-existing rows, verification and what an unsigned chain does
not prove. alog.md §11.4/§16, CLAUDE.md, HighLevelReqs AL-11/12,
Component-CLI, Component-ManagementService, docs/components/CLI.md and the
CLI README drop the "no-op placeholder" wording.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 16:28:54 -05:00
parent 548bb9a725
commit dd99a9f5a5
8 changed files with 109 additions and 36 deletions
+12 -7
View File
@@ -493,12 +493,17 @@ Audit Log page **Export** button streams CSV (current filter) server-side. Defau
### 11.3 Payload redaction at write
See §8.2. Contract: unredacted secrets never persist. Safety net over-redacts on misconfiguration.
### 11.4 Tamper-evidence hash chain (deferred, v1.x)
- Each row gains a `RowHash` column.
- `RowHash = SHA-256(prev.RowHash || canonical(row))` per partition.
- Computed by a chaining job that runs after each monthly partition closes.
- Verifiable offline via `scadabridge audit verify-chain --month YYYY-MM`.
- Default **off** in v1 to avoid operational burden. Flag for v1.x.
### 11.4 Tamper-evidence hash chain (shipped, ScadaBridge#41 — default off)
- Each row gains a `RowHash` column, plus a `ChainSeq` (position in its partition's chain).
- `RowHash = SHA-256(prev.RowHash || canonical(row))` per partition (UTC calendar month).
- Computed by a chaining job — implemented incrementally (every minute, both central
nodes, serialised by a SQL application lock) rather than only after the month closes.
- Purges keep the chain verifiable: the partition switch records a checkpoint anchor on
the month's chain head; the per-channel DELETE leaves a tombstone per chained row.
- Verifiable via `scadabridge audit verify-chain --month YYYY-MM` (first break reported
with partition, `ChainSeq`, `EventId`). Unsigned; signing / external anchoring are open.
- Default **off** (`AuditLog:HashChain:Enabled`). Full design: Component-AuditLog.md,
Security & Tamper-Evidence.
### 11.5 Site SQLite security
- File permissions: read/write by the ScadaBridge service account only.
@@ -607,7 +612,7 @@ A monthly job dumps the closing partition to Parquet on operator-configured obje
|---|---|---|
| 1 | Component number | **#23 Audit Log** (README matrix + HighLevelReqs). |
| 2 | Nav placement | New top-level **Audit** nav group in Central UI. |
| 3 | Hash-chain tamper evidence (§11.4) | Deferred to v1.x. v1 enforces append-only via DB grants only. |
| 3 | Hash-chain tamper evidence (§11.4) | Deferred to v1.x; shipped by ScadaBridge#41 (unsigned SHA-256 chain, default off). |
| 4 | Parquet archival to object storage (§15.2) | Deferred to v1.x. |
| 5 | Per-channel retention overrides (§12.1) | Deferred to v1.x. v1 uses a single global `RetentionDays`. |
| 6 | Default payload cap | **8 KB** for `RequestSummary` / `ResponseSummary`; **64 KB** on error rows (`Status IN ('Failed', 'Parked', 'Discarded')`). |