qonto-assistant/workplans/QONTO-WP-0005-audit-deny-stream-completeness.md
tegwick b9349782f4 feat(audit): publish sequenced heartbeat and reconciliation evidence
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06ec5-7e2b-7743-ac08-719e1b0f42e2
2026-09-05 01:39:48 +02:00

107 lines
4.7 KiB
Markdown

---
id: QONTO-WP-0005
type: workplan
title: "Establish audit.deny stream completeness evidence"
domain: infotech
repo: qonto-assistant
status: finished
owner: codex
topic_slug: qonto-audit-deny-stream-completeness
created: "2026-09-04"
updated: "2026-09-05"
state_hub_workstream_id: "8a1bc02c-00fc-5400-af1f-10af562b9782"
---
# Establish `audit.deny` stream completeness evidence
Closes the qonto-assistant-owned remediation from `RISK-F-0011` and the
King's Guard message received on 2026-09-01. A received deny event is already
useful, but observers cannot currently distinguish a quiet stream from an
incomplete one. The source therefore needs to publish its cadence, emit a
positive heartbeat carrying source-side counts, and expose a reconciliation
snapshot that makes missing events and sequence gaps visible.
The implementation stays local to the structured audit stream. State Hub is
not placed on the request hot path, and the existing in-process deny escalation
loop remains independent from estate observation.
## Task: Declare cadence and reconciliation semantics
```task
id: QONTO-WP-0005-T01
status: done
priority: high
state_hub_task_id: "e846d42b-d9e0-587e-874b-0ad8c1d5c471"
```
Publish the `audit.deny` load-bearing classification next to the security
genome. Declare heartbeat behavior, active-instance lifecycle semantics,
source-side counters, sequence-gap detection, and what an observer must compare.
Done when the declaration is machine-readable and the operator documentation
does not imply that a received event alone proves stream completeness.
**Done 2026-09-04:** Added `specs/audit-emission-cadence.yaml` and linked it
from the security genome. It declares the per-process sequence boundary,
`audit.deny` as low-volume/load-bearing, the 24-hour active-process cadence,
scale-to-zero lifecycle semantics, cumulative/window counters, and observer
comparison rules. The architecture, security practice, and operator runbook
now carry the same semantics.
## Task: Emit heartbeat and reconciliation evidence
```task
id: QONTO-WP-0005-T02
status: done
priority: high
state_hub_task_id: "cdb6576a-f606-57c9-94b2-923f23c2044b"
```
Add process-instance identity, monotonic stream sequence, per-class transition
counts, periodic/startup/shutdown heartbeat events, and a read-only local
reconciliation view. Enrich request events with their identity binding and
declared egress destination so observers no longer substitute genome constants.
Done when the source emits enough information to detect a missing deny or
heartbeat without introducing State Hub or another network dependency.
**Done 2026-09-04:** `AuditLogger` now serializes publication under one lock,
assigns a UUID process instance and monotonic sequence, counts allow/deny
source transitions, and emits startup/periodic/best-effort-shutdown heartbeats
with reconciliation counters. `GET /v1/audit/reconciliation` returns the same
non-secret local state without incrementing it. REST/MCP request records carry
`identity_binding` (`self_asserted` or `key_cape_jwt`) and
`egress_destination: qonto-thirdparty-api`. The app rejects split injected
audit loggers so request events and heartbeat evidence cannot silently land in
different streams.
## Task: Verify and hand back the finding
```task
id: QONTO-WP-0005-T03
status: done
priority: high
state_hub_task_id: "e5ed80bd-f0aa-5473-a185-ecb9f87ab21c"
```
Cover sequencing, counts, heartbeat windows, reconciliation output, REST/MCP
parity, identity binding, and secret redaction in tests. Run the full local
suite, sync the workplan to State Hub, and notify Risk Nexus and King's Guard
with the source-owned evidence and any remaining deployment observation gate.
**Done 2026-09-04:** Full suite passed (`85 passed`); changed-file Ruff checks,
YAML parsing, `compileall`, `git diff --check`, REST smoke, and MCP smoke all
passed. Both smoke runs visibly emitted startup/shutdown heartbeats with
contiguous sequences and matching counts. Source implementation is complete;
deployment and independent observer acceptance remain with the runtime owner,
King's Guard, and Risk Nexus rather than as unfinished source work here.
**Review 2026-09-05:** Reviewed the pending implementation against its cadence
contract. Fixed client cleanup when shutdown audit publication fails, added
regressions for cleanup and split stream rejection, and verified concurrent
heartbeat/request publication ordering. Replaced timing-sensitive periodic test
sleep with an explicit event. Final verification: 88 tests passed, full-source
Ruff, compileall, YAML parsing, and REST/MCP fixture smoke checks passed. Runtime
deployment and independent observer acceptance remain external gates. No new
cross-repo messages were sent during this review.