# Factory audit senders: concrete custody review CCR-2026-0021 and CCR-2026-0022 are **proposed**. RPF-WP-0035-T08 owns the platform work; AUDIT-WP-0009-T09/T11 retain receiver admission. This packet requires the named platform operator, Audit Core owner and each producer owner to approve its request before native credential mutation. ## Scope to approve | Request | Producer / exact source | OpenBao path | Producer Secret / key | | --- | --- | --- | --- | | CCR-2026-0021 | approval-engine | platform/workloads/approval-engine/audit-sender | approval-engine/approval-engine-audit / audit-token | | CCR-2026-0022 | informed-decision | platform/workloads/informed-decision/audit-sender | informed-decision/informed-decision-audit / token | Each sender is limited to `tenant:platform`, write true, read false, `evidence_kind: load-bearing`, `secret_policy: redact`. The producer receives only its own `AUDIT_TOKEN`. `CUSTODY_REQUEST` is a non-secret provenance marker stored beside that token, enabling an interrupted first provision to identify its own version-1 value. It is not projected to the producer. Each lane has its own exact-path policy, Kubernetes auth role and namespace- restricted ClusterSecretStore. Only `external-secrets/external-secrets` may log in to the reader role (15-minute session). Neither producer can read the full sender registry or its sibling's token. The coding-agent boundary gains exact denies on the two new data/metadata paths; existing rules are preserved. The approved first-provision operation would generate two independent values in the attended platform process, store them with CAS=0, and append the exact identities to `platform/workloads/audit-core/senders` with compare-and-set on its observed KV version. That process necessarily reads the existing registry in memory; it never emits its credentials or gives it to a producer. No token passes through Git, a Hub record, command arguments or stdout/stderr. ## Blocking receiver finding On 2026-09-11 the native receiver is 1/1 Ready on `forgejo.coulomb.social/coulomb/audit-core@sha256:c2fe39a0185b99be3fc0cb14d2de69772b8e66e20490097c9d11d90cc39719a6`. Its `SenderIdentity` has **no evidence_kind support**. A synthetic registration probe in the native pod fails the load-bearing contract; the same probe against current Audit Core source passes. Readiness did not detect this contract gap. `factory_audit_custody.py receiver-check` now enforces that contract before any credential access. An approved CCR alone cannot bypass it. Audit Core must build, publish, admit and roll out its current implementation and source scope first. Its existing AUDIT-WP-0009-T09/T11 tasks retain that work; no completed source task is reopened. No receiver restart or deployment was done here. Approval Engine's namespace is also absent. Three of four ESO objects passed server dry-run in their intended namespaces; its ExternalSecret was refused because that namespace does not exist. This packet creates no namespace, workload or network permission. Its owner must supply that prerequisite. ## Executable sequence Review the source and exact policies: ```sh python3 scripts/credential-change.py render CCR-2026-0021 python3 scripts/credential-change.py render CCR-2026-0022 python3 scripts/factory_audit_custody.py plan ``` After a compatible receiver release, the credential-free check is: ```sh python3 scripts/factory_audit_custody.py receiver-check \ --kubeconfig /operator/railiance-kubeconfig \ --expected-receiver-image forgejo.coulomb.social/coulomb/audit-core@sha256:ADMITTED_DIGEST \ --receipt /operator/unique-receiver-receipt.json ``` The seed command requires approved CCR files with all named owner reviews, the expected image, exact Railiance cluster UID, ready/current pod, both target namespaces and the Warden attended platform-admin login envelope. Route via `warden route show openbao-platform-admin-login --json` before arranging access. Use its installed attended wrapper; do not copy a token into the command. Inside that envelope, invoke: ```sh python3 scripts/factory_audit_custody.py seed \ --kubeconfig /operator/railiance-kubeconfig \ --expected-receiver-image forgejo.coulomb.social/coulomb/audit-core@sha256:ADMITTED_DIGEST \ --confirm 'PROVISION CCR-2026-0021 CCR-2026-0022' \ --receipt /operator/unique-custody-receipt.json ``` A successful seed deliberately reports `custody_seeded_pending_delivery_and_receiver_reload`. It applies the exact reader metadata and seeds custody, but does not apply ESO objects, reload the shared receiver or claim live ingestion. Preserve that receipt. After an interruption, review it and use `--resume` with a new receipt: only exact request-owned version-1 custody is reused. Changed tokens, source scopes, provenance, unknown duplicate identities and concurrent registry writes refuse. No automatic deletion or rotation is attempted on failure. Under the same reviewed lane, the subsequent attended delivery uses `manifests/factory-audit-senders.yaml`; verify both stores/ExternalSecrets and exact token equality inside the protected process. Sync the existing registry ExternalSecret, verify its update, and reload Audit Core through its owner runbook. Then run each real producer's accepted/duplicate and wrong-source, wrong-tenant/read-refusal checks and retrieve evidence with the independent operator reader. The script does not yet automate these owner acceptance steps. Do not mark either CCR verified/active until those receipts exist. ## Revocation and limits ESO login expiry does **not** expire an audit bearer. Stop the affected producer, remove only its token from the receiver registry using CAS, reload the receiver and prove refusal, then disable its reader/projection. Retain stored events and KV provenance. Rotation is separately reviewed and overlap-first. Existing senders and reader permissions remain intact. `warden route show audit-core-senders` still points to the older Mason bootstrap. The receiver runbook records the later OpenBao migration; this packet uses that current authority and the platform's existing attended custody mechanics. It creates no second registry or generic credential broker. Factory policy/caller admission, registered human binding, CCR-2026-0019's operator group, native runtime delivery and spending/operating acceptance stay with their existing records. Sender approval does not admit any of those acts.