audit-core/workplans/AUDIT-WP-0013-cross-repo-sender-admission.md
tegwick d46e89ee21
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 4s
AUDIT-WP-0013-T06: independent full-scope readers may count any source (NK-WP-0035-T04)
GET /v1/reconciliation now admits may_read + tenants ["*"] identities for
any source, marked basis: independent_reader. Scoped readers get 403
full_tenant_scope_required; writers keep 403 source_not_allowed. Counts only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 308701@bnt-lap001
Assistant-Session: 5548e447-444c-4dcc-bed1-05c16eebfe56
2026-10-28 09:49:10 +01:00

12 KiB

id type title domain repo status owner topic_slug created updated state_hub_workstream_id
AUDIT-WP-0013 workplan Complete flex-auth and Qonto sender admission infotech audit-core blocked codex audit-evidence-dependencies 2026-10-04 2026-10-28 9e400de2-6ba1-520e-9b25-94aa2470e528

AUDIT-WP-0013 — Complete flex-auth and Qonto sender admission

All independent local receiver work in this plan is complete. Remaining tasks require named owner inputs or attended custody delivery; the workplan is blocked. Requirements are metadata-only and do not authorize deployment, credentials or bank traffic.

Review current owners and publish admission requirements

id: AUDIT-WP-0013-T01
status: done
priority: high
state_hub_task_id: "6f9505d8-81ea-5406-b693-0781b254b38d"

Reviewed AUDIT-IN-0006, FLEX-WP-0031, QONTO-WP-0006 and RAPP-QONTO-WP-0003. Accepted bounded custody/mapping commitments in docs/cross-repo-evidence-admission.md. Flex-auth T03 outbox is already done; transport registration must not wait on it or on downstream drain/observer completion. Exact prefixed heartbeat classes, source-owned rate thresholds and mixed Qonto class semantics are recorded.

Admit six flex-auth pin identities and verify custody

id: AUDIT-WP-0013-T02
status: wait
priority: high
blocking_reason: "flex-auth must return final per-pin cadence/scope/selector payloads; ops-warden routing catalog and railiance-platform attended seed/delivery are not supplied."
blocked_on: message-from:flex-auth
state_hub_task_id: "fff70081-0d6e-5e16-917a-c7cc3204ad53"

AUDIT-IN-0006 / FLEX-WP-0031-T02. Unblock with the six exact source registrations, explicit tenant/secret policies, emission_cadence including source-chosen allow thresholds, namespace/pod selectors, a governed usable catalog lane and attended custody receipts. The current audit-core-senders route is draft/unresolvable and describes an old ops-mason path; correct or replace that owner routing before attended mint. Then prepare scoped overlays and verify acceptance/retry/refusal/count/heartbeat/revocation behavior. may_read stays false. Requirements and owner split are in docs/cross-repo-evidence-admission.md; nothing is activated by this task.

Resolve the load-bearing failure-path declaration

id: AUDIT-WP-0013-T03
status: done
priority: high
state_hub_task_id: "310e28d2-849d-549a-8c4b-d82c23ebad93"

Message 715cf1f2-55dd-4d2d-9b7b-c5dffa0181e5 is a reading, expressly not a ruling. Keep restrictive released_uncommitted classes non-atomic/non-conformant under current text. Do not treat attributive completeness_trade as an exception. This blocks conformance/exception declaration, not custody preparation in T02. Require the decision ID, applicable text/schema revision, classes, failure condition and detection obligations before implementing a new field.

Resolved 2026-10-10 by GH-DEC-2026-024 (gate-house@0192273, message 8b375579): the §9.6 failure-path release is refused. A load-bearing source gets no declared, detectable, direction-limited release, and §11 gets no declaration for one, so no new field is introduced. completeness_trade keeps its attributive-only meaning. That is already enforced: SenderIdentity rejects a completeness_trade on a load-bearing source (audit_core/senders.py, tests/test_senders.py::test_a_load_bearing_source_cannot_be_given_a_completeness_trade). A released_uncommitted class stays non-conformant. audit-core's evidence-source status is no (GH-DEC-2026-018, AUDIT-IN-0005). Registering the AUDIT-IN-0006 senders is still this repo's job, under T02/T05.

Implement receiver process-instance accepted counts

id: AUDIT-WP-0013-T04
status: done
priority: high
state_hub_task_id: "cd7133db-7ce9-5e83-9914-b0e8ecf044a3"

Optional stream_instance_id on GET /v1/reconciliation selects exact retained details.data.stream_instance_id on both backends, preserving source/tenant permissions and bounded acceptance-time windows. Duplicate retries count once; empty/repeated filters are refused. Aggregate response is unchanged without the filter. API and both-backend regressions pass. This addresses one receiver gap for QONTO-WP-0006-T02, not runtime or observer acceptance.

Admit the Qonto collector and verify accepted-class mapping

id: AUDIT-WP-0013-T05
status: done
priority: high
state_hub_task_id: "76b59808-abc3-5b8d-b31a-e3fb611f2cbe"

QONTO-WP-0006-T02. Audit-core owns admission and review of accepted mapping; rapp-qonto owns runtime delivery. Required inputs and proposed audit.allow/audit.deny/audit.heartbeat mapping are in docs/cross-repo-evidence-admission.md. Retain original stream instance, sequence and source counts. Approve deterministic retry IDs, heartbeat vouched-for class, authoritative tenant and acceptance-time/sequence-window comparison. Supply pinned collector/runtime artifacts, sanitized success/failure receipts and actual accepted records. Neither source stdout nor finished RAPP-QONTO-WP-0003 closes this gate. KG-WP-0005-T03 observer acceptance follows sender proof, never precedes it.

NK-WP-0035 receiver readiness, 2026-10-15

Prepared credential-preserving Approval Engine cadence transformation and silent attended CAS wrapper; default f=3600, class waits7200, effective10800. Ten focused preservation/refusal/idempotence tests pass. Prepared exact Qonto collector ingress (namespace AND pod selector), contingent on source-owner tenant/mapping acceptance. Read-only native metadata proves deployed ec15f63d artifact lacks cadence module and process-instance filtering; database migration ledger is0006, source adds additive0007-import-receipts. Current-source receiver release/migration is therefore required before registration acceptance. See docs/cadence-registration.md for execution gates. No protected registry was fetched or changed, no sender token was minted and no live resource was mutated by this readiness work. The readiness note above describes the initial state; the native admission follow-up below supersedes that T05 waiting state.

Native Qonto receiver admission accepted, 2026-10-15

T05 is done for sender-native custody and mapping admission. Independent KG-WP-0005-T03 operational acceptance is deliberately separate and remains open. The protected registry CAS advanced15→16 with exact readback, preserving every existing sender/credential/scope and unrelated KV field. Approval Engine's full source declaration SHA256cc58c8d53ebf50acf540d73b7607d579942bda7734c3e8722108e9c9204af655 and issuance/use/supersession/revocation waits7200 are delivered and loaded after receiver reload. Effective deadline is10800 with grace1.5; this registration receipt is not yet evidence of four fresh Approval heartbeat observations.

Receiver b479801b (built from5227fb1) is ready with native cadence/heartbeat and both-backend process-instance capabilities verified. Migration0007 completed after the narrow DNS/PostgreSQL migration egress repair (source1269a0e). The complete local PostgreSQL suite passed333 tests with no skips or failures.

Actual collector image82bfd410 captured source qonto-assistant in approved tenant tenant:friendly:binky. Instanceb351fa6b-e0d6-4f88-b7c9-6bacb1a112b7 has original sequence1 audit.heartbeat mapped one-to-one to audit-core.heartbeat covering audit.deny and sequence2 audit.deny; both accepted202. Same-instance own reconciliation returns one of each, duplicate200, wrong source400, wrong tenant400, archive read403 and invalid bearer401. Pending queue0; first202 receipts survived collector pod replacement using its persistent outbox. Audit.allow mapping/classification remains source-tested; no native allow record or bank operation is claimed by this bounded receipt.

Exact metadata receipts and SHA256 index are retained in docs/evidence/2026-10-15-cadence-admission/. These are native sender receipts, not independent receiver readback. Real elapsed hourly observation, independent active-instance/class-silence/sequence/count/lag assessment and Approval lifecycle acceptance remain with NK-WP-0035/KG-WP-0005. Source-global receiver findings must not misclassify intentional Qonto scale-to-zero as an active-instance omission.

First protected pin admission preparation — 2026-10-16

T02 remains wait. Prepared docs/flex-auth-secrets-engine-admission.md against Access0a05383195213e7eaacd08388ce1d7892ce756df and Audit2e97f37. Existing wire contracts need no adapter. Seven local tests cover all five decision classes, retry/conflict, independent fixture readback, writer-read and wrong-scope refusal, half-open acceptance-time accounting and rare-class silence. This does not grant or admit a sender. Per-pin source/cadence/policy/selectors, usable attended custody route, source deployment/PVC and independent native readback remain owner gates. Generic source cadence remains daily and cannot stand in for admitted hourly runtime. Source outbox sequence is not on the wire; exact event-ID/accepted_at comparison is the bounded readback method, not cumulative-time-window equality.

Cross-owner follow-up: Access confirms auditDelivery remains disabled in the initial signer slice. The packet now requires independently retained complete producer JSONL with contiguous sequence/high-water and lifetime identity, not a selected-ID list. Existing exact-ID reads plus all-class accepted-time count comparison support bounded full-ledger reconciliation; correlation search is capped and cannot serve as complete export. Operational repeated ledger custody, per-pin source cadence/runtime adoption and independent observation still wait. The canonical sibling-owner fixture check passed1, resolving the isolated checkout's expected skip without modifying foreign source.

Sanction independent cross-source reconciliation counts

id: AUDIT-WP-0013-T06
status: done
priority: high

NK-WP-0035-T04 (State Hub message 6ed5cafc, receipt net-kingdom docs/evidence/2026-10-15-cadence-adoption/receiver-readback-20261023.json): the operator reader is registered for source user-engine, so GET /v1/reconciliation?source=qonto-assistant returned 403 source_not_allowed while exact-id reads succeeded 3/3.

Decided: option (a). GET /v1/reconciliation admits a second caller class, an independent reader holding may_read: true and tenants: ["*"], for any source. Such a reader may already read every event by id or correlation, so per-class counts disclose strictly less. A tenant-scoped reader gets 403 full_tenant_scope_required (counting a whole window enumerates existence beyond a tenant-filtered id lookup); a writer without may_read still gets 403 source_not_allowed. Own-source behaviour and response shape are unchanged. Independent answers carry basis: "independent_reader" so a receipt cannot be mistaken for the source's own §9.6 reconciliation. No new role, endpoint or registry field: the existing operator identity is the sanctioned reader.

Response: source, tenant (null if omitted), since, until (normalized, half-open on accepted_at), counts [{class, count}], optional stream_instance_id, basis, means. Counts only; sequence and lag are not aggregated and stay with the exact-id reads (accepted_at, observed_at, details.data). Source: audit_core/ingestion.py _reconciliation; tests: tests/test_independent_reconciliation.py (7). Runbook and section-4 docs updated.

id: AUDIT-WP-0013-T07
status: wait
priority: high
blocking_reason: "Founder-run: build/publish an image from the T06 commit, pin its digest in deploy/audit-core.yaml, roll out, then NetKingdom reruns its readback."
blocked_on: founder

No registry or Secret change is expected: the operator identity already reads by id across tenants. Value-safe precheck with the operator token: GET /v1/stats returns 200 only for a full-scope reader (403 full_tenant_scope_required otherwise, which would need a registry scope change instead). The deployed b479801b receiver predates T06 and will keep returning source_not_allowed until the new image runs.