From 7cbd4e53284786373468c49688c5c7e5c614e21b Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 27 Oct 2026 22:35:31 +0100 Subject: [PATCH] NK-WP-0055-T11: plan audit sender payloads, chain correlation id, core PDP readiness FLEX-WP-0031 gains T10 (final per-pin payloads for AUDIT-WP-0013-T02) and T11 (cross-stream correlation id, FLEX-WP-0024 relation); T02 no longer waits on the settled failure-path ruling. New proposed FLEX-WP-0039 covers ADR-0018 readiness surface, per-consumer fail-closed receipts and policy import options. SCOPE.md: secrets-engine pin enforces caller auth since 6e3dfae. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 4515@bnt-lap001 Assistant-Session: 0bf96127-6e04-41be-bfda-d11717c3f354 --- SCOPE.md | 3 +- WORK-RECORDS.md | 7 ++ .../FLEX-WP-0031-decision-record-emission.md | 85 ++++++++++++- ...X-WP-0039-core-pdp-production-readiness.md | 112 ++++++++++++++++++ 4 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 workplans/FLEX-WP-0039-core-pdp-production-readiness.md diff --git a/SCOPE.md b/SCOPE.md index 80c972c..be4dd64 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -122,7 +122,8 @@ secret-catalog-lane`, twelve actions delivered by secrets-engine rather than inferred, `destroy` gated on a dual-control approval claim, and a dedicated `flex-auth-secrets-engine` pin at `http://flex-auth-secrets-engine.flex-auth.svc.cluster.local.:8080` — -trailing dot required, in-cluster only — with `callerAuth.mode: warn`. Adoption is not complete: secrets-engine is a CLI +trailing dot required, in-cluster only — with `callerAuth.mode: enforce` (since +2026-09-06, `6e3dfae`, verified operator caller identity). Adoption is not complete: secrets-engine is a CLI rather than a workload, and the pin's default-deny ingress admits a pod, so an operator-run access path is still undecided. diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 13d6487..1618daf 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -48,6 +48,7 @@ | workplan | FLEX-WP-0036 | active | — | workplans/FLEX-WP-0036-runtime-rename-access-engine.md | | workplan | FLEX-WP-0037 | finished | — | workplans/FLEX-WP-0037-ops-warden-agt-custodian-actor.md | | workplan | FLEX-WP-0038 | active | — | workplans/FLEX-WP-0038-wave2-resource-right-sizing.md | +| workplan | FLEX-WP-0039 | proposed | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md | | task | FLEX-WP-ADHOC-2026-10-03-T01 | done | — | workplans/ADHOC-2026-10-03.md | | task | FLEX-WP-ADHOC-2026-10-03-T02 | wait | — | workplans/ADHOC-2026-10-03.md | | task | FLEX-WP-ADHOC-2026-10-11-T01 | done | — | workplans/ADHOC-2026-10-11.md | @@ -204,6 +205,8 @@ | task | FLEX-WP-0031-T07 | done | — | workplans/FLEX-WP-0031-decision-record-emission.md | | task | FLEX-WP-0031-T08 | wait | — | workplans/FLEX-WP-0031-decision-record-emission.md | | task | FLEX-WP-0031-T09 | done | — | workplans/FLEX-WP-0031-decision-record-emission.md | +| task | FLEX-WP-0031-T10 | todo | — | workplans/FLEX-WP-0031-decision-record-emission.md | +| task | FLEX-WP-0031-T11 | wait | — | workplans/FLEX-WP-0031-decision-record-emission.md | | task | FLEX-WP-0032-T01 | done | — | workplans/FLEX-WP-0032-informed-decision-list-action.md | | task | FLEX-WP-0032-T02 | done | — | workplans/FLEX-WP-0032-informed-decision-list-action.md | | task | FLEX-WP-0032-T03 | done | — | workplans/FLEX-WP-0032-informed-decision-list-action.md | @@ -231,6 +234,10 @@ | task | FLEX-WP-0037-T02 | done | — | workplans/FLEX-WP-0037-ops-warden-agt-custodian-actor.md | | task | FLEX-WP-0037-T03 | done | — | workplans/FLEX-WP-0037-ops-warden-agt-custodian-actor.md | | task | FLEX-WP-0038-T01 | wait | — | workplans/FLEX-WP-0038-wave2-resource-right-sizing.md | +| task | FLEX-WP-0039-T01 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md | +| task | FLEX-WP-0039-T02 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md | +| task | FLEX-WP-0039-T03 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md | +| task | FLEX-WP-0039-T04 | todo | — | workplans/FLEX-WP-0039-core-pdp-production-readiness.md | | intake | FLEX-IN-0001 | closed | — | intakes/intakes.md | | intake | FLEX-IN-0002 | closed | — | intakes/intakes.md | | intake | FLEX-IN-0003 | open | — | intakes/intakes.md | diff --git a/workplans/FLEX-WP-0031-decision-record-emission.md b/workplans/FLEX-WP-0031-decision-record-emission.md index 266dff5..cbd1b80 100644 --- a/workplans/FLEX-WP-0031-decision-record-emission.md +++ b/workplans/FLEX-WP-0031-decision-record-emission.md @@ -62,8 +62,8 @@ and the node disk is at 84 %. ```task id: FLEX-WP-0031-T02 status: wait -blocked_on: message-from:audit-core -blocking_reason: "GH-WP-0004-T12 refused the load-bearing failure-path exception (GH-DEC-2026-024). AUDIT-IN-0006 sender rows and governed token delivery remain pending." +blocked_on: task:FLEX-WP-0031-T10 +blocking_reason: "Failure-path ruling settled (GH-DEC-2026-024, implemented in T09). AUDIT-WP-0013-T02 now waits on our final per-pin payloads (T10); ops-warden mint lane and railiance-platform attended custody remain external." priority: high state_hub_task_id: "89661908-ca9a-5e4a-a0a5-62d1a9e02568" ``` @@ -343,3 +343,84 @@ and integer boundary rendering passed. Original stage retained; no native change > critical path (identity → authz → secrets → SecurityCase execution). Tasks are unchanged; > promote back when demand or risk appears. See the-custodian > `history/20261011-netkingdom-security-progress-assessment.md`. + +## 10. Return final per-pin registration payloads to AUDIT-WP-0013-T02 + +```task +id: FLEX-WP-0031-T10 +status: todo +priority: high +depends_on: [FLEX-WP-0031-T09] +``` + +Added 2026-10-27 for NetKingdom NK-WP-0055-T11. audit-core's +`AUDIT-WP-0013-T02` is `blocked_on: message-from:flex-auth`: it needs our +non-secret, final registration payloads, not another intake. The failure-path +question that held T02 is settled (`GH-DEC-2026-024`, source enforced in T09), +so nothing on our side waits on a ruling any more. + +Per release unit, one file under `docs/contracts/audit-senders/.json`: + +- `source: flex-auth.` (exact, no wildcard), write true, `may_read: false`, + `tenants: ["*"]` with the deny-before-tenant-creation justification, + `secret_policy: redact`, load-bearing; +- `heartbeat_classes`: `flex-auth.decision.deny`, `.redact`, `.not_applicable`, + `.audit_only` at 86400 s (the stored `ClassPrefix` names, not shorthand); +- a canonical `emission_cadence` (wire schema 0.1) naming that exact source, + with **our** chosen `allow` expected rate, window and threshold, derived from + each pin's observed decision volume, not invented; +- the pin's namespace/pod ingress selector as rendered by `charts/flex-auth`. + +Open scope question to settle first: audit-core lists six pins +(ops-warden, tenant-engine, user-engine, secrets-engine, informed-decision-t03, +informed-decision-sitting). `registry/release-units/` now declares nine; the +newer `ops-warden-fetch`, `application-readback` and +`informed-decision-lifecycle` units also answer load-bearing decisions. Either +register all nine or record why a unit emits nothing. Source names keep the +`flex-auth.` prefix: release units were not renamed by `FLEX-DEC-2026-020`. + +Gate: payloads committed, validated against the cadence profile checker, and +sent to audit-core on thread `6044ed35`. Token mint stays founder-attended +(ops-warden lane, railiance-platform custody) under T08. + +## 11. Carry the cross-stream correlation id in the decision envelope + +```task +id: FLEX-WP-0031-T11 +status: wait +priority: high +blocked_on: message-from:net-kingdom +blocking_reason: "NetKingdom owns the onboarding-chain correlation-id contract (NK-WP-0055-T11); field name, format and propagation rule are not yet defined." +``` + +Added 2026-10-27. Today the emitted event's `correlation_id` is the decision +id, a content digest that two identical checks share. That joins a record to +its decision, but not to the identity, OpenBao, Kubernetes and workload records +of the same onboarding chain that NK-WP-0055-T11 needs. + +Plan, once NetKingdom publishes the contract: + +1. Accept the chain id from the caller in the check request (beside the + request `id`, and like it excluded from `request_digest`, so the id never + changes a decision or its replay). +2. Echo it in `flex-auth.decision-record.v1` as a named field and, when present, + use it as the audit event's `correlation_id`; the decision id stays in + `data`. Absent: keep today's behaviour. Heartbeats keep their own ids. +3. FLEX-WP-0024 relation: the signed envelope must cover the chain id, or a + relaying responder could re-attribute a decision to another chain. Until + 0024 signs, the id is caller-asserted correlation, never evidence of who + asked; record it as such in `docs/decision-record-contract.md`. +4. Tests: digest invariance with and without the id; outbox and drain carry it; + explain returns it. + +Gate: contract field merged, tests pass, and an NK onboarding-chain test shows +one id across at least the identity and authorization records. + +## What remains for durable decision records (2026-10-27) + +Source is complete: durable outbox, mandatory commit (T09), heartbeat and +drain (T05), chart PVC and delivery wiring (T07, T08 prep). Open: T10 payloads +(ours, now), T11 correlation (waits on NetKingdom), T02 sender rows and +attended token mint (audit-core, ops-warden, railiance-platform, founder), T08 +approved rollout and native 202/silence proof, T06 reconciliation (audit-core +time basis), T04 G2 closure. diff --git a/workplans/FLEX-WP-0039-core-pdp-production-readiness.md b/workplans/FLEX-WP-0039-core-pdp-production-readiness.md new file mode 100644 index 0000000..ff63b68 --- /dev/null +++ b/workplans/FLEX-WP-0039-core-pdp-production-readiness.md @@ -0,0 +1,112 @@ +--- +id: FLEX-WP-0039 +type: workplan +title: "Core PDP production readiness: per-pin readiness surface and policy import path" +domain: infotech +repo: access-engine +status: proposed +flavor: implementation +owner: access-engine +created: "2026-10-27" +updated: "2026-10-27" +related: [NK-ADR-0018, NK-WP-0055, FLEX-WP-0031, FLEX-WP-0024, FLEX-WP-0011] +--- + +# FLEX-WP-0039 — Core PDP production readiness + +NetKingdom ADR-0018 (accepted 2026-10-27) makes the access-engine Go core the +production PDP and runs the PDP readiness checks against it: health, data +freshness, policy load status, and per-consumer fail-closed behaviour +(NK-WP-0055-T12). It moves the policy import gap to NK-WP-0055-T14. + +Current state, from source: `/healthz` returns a static `{"status":"ok"}` and +says nothing about what was loaded. Each pin loads its policy package and +registry snapshot from a path baked into the image +(`/opt/flex-auth/examples//...`), so every policy change is an image +rebuild and rollout. `/v1/emission` already reports outbox state. + +## 1. Readiness surface per pin + +```task +id: FLEX-WP-0039-T01 +status: todo +priority: medium +``` + +Add `GET /v1/readiness` (and make `/readyz` fail when it fails), no secrets, +caller-auth exempt like `/healthz`: + +- `policy`: package id, version, `policy_package_digest`, source path, + `loaded_at`, load result (`ok` or the refusal reason); +- `registry`: `registry_snapshot_digest`, snapshot `generated_at`, age in + seconds against a per-pin `maxSnapshotAge` (data freshness); +- `caller_auth`: mode (`enforce`/`warn`/`off`) and audience; +- `emission`: recorder attached, pending depth, lag-bound exceeded (from + `/v1/emission`); +- `release_unit` and image digest. + +A pin is not ready when the policy failed to load, the snapshot is older than +its bound, or caller auth is not `enforce` on a production unit. Gate: tests +for each not-ready cause; chart wires `readinessProbe` to `/readyz`. + +## 2. Per-consumer fail-closed receipt + +```task +id: FLEX-WP-0039-T02 +status: todo +priority: medium +depends_on: [FLEX-WP-0039-T01] +``` + +A read-only script `tools/readiness-receipt` that, for each release unit in +`registry/release-units/`, reads `/v1/readiness` through the operator access +path and joins it with the consumer's `pep-stance.yaml` (ops-warden, +tenant-engine, user-engine, secrets-engine, informed-decision). Output is a +dated, non-secret receipt per consumer: readiness fields, declared stance on +PDP unavailable / 503 / malformed envelope, and whether that stance is closed +for the scope. An open-for-scope stance is reported as a finding, not +corrected here (FLEX-WP-0031-T09: a 503 only denies if the consumer closes). +Live runs are founder-run; the script is tested on fixtures. Gate: receipt for +all nine units feeds NK-WP-0055-T12. + +## 3. Decide the policy import path + +```task +id: FLEX-WP-0039-T03 +status: todo +priority: medium +needs_human: true +``` + +NK-WP-0055-T14 accepts either option; the founder picks one: + +- **A. Rebuild-and-deploy is the import path.** Keep policies in the image; + require digest-pinned images, a recorded `policy_package_digest` per release, + and `explain` receipt after rollout. No new runtime surface. Cost: a release + per policy change. +- **B. Mounted policy bundle.** Chart mounts a ConfigMap (or OCI artifact + pulled by an init container) holding the policy package and registry + snapshot; the pin loads it at start (restart on change, no hot reload in + v1). Requires a digest pin in values so the loaded package is the reviewed + one, and the readiness surface (T01) to prove which digest is live. +- **C. Signed bundle pull.** As B, but the bundle is signed and verified + before load. Pairs with FLEX-WP-0024's signer custody; heavier, and blocked + where 0024 is. + +Recommendation: B now with digest pinning, C when FLEX-WP-0024 custody exists. +Gate: founder decision recorded as a `FLEX-DEC`. + +## 4. Split tenant:coulomb platform and tenant packages + +```task +id: FLEX-WP-0039-T04 +status: todo +priority: medium +depends_on: [FLEX-WP-0039-T03] +``` + +Separate the platform-owned package (guardrails, protected-system actions) +from a `tenant:coulomb` package so tenant policy changes do not touch platform +rules, per NK-WP-0055-T14. Produce one production `explain` receipt +(founder-run) against the split. Gate: both packages validate, tenant-scope +tests pass, receipt recorded.