NK-WP-0055-T01: production readiness ledger; gaps become T10-T15
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4515@bnt-lap001
Assistant-Session: 0bf96127-6e04-41be-bfda-d11717c3f354
This commit is contained in:
tegwick 2026-10-27 22:11:57 +01:00
parent 15574a5518
commit c8f44fa614
3 changed files with 287 additions and 5 deletions

View file

@ -0,0 +1,187 @@
# Production readiness ledger — 2026-10-27
**Task:** NK-WP-0055-T01. This is a read-only assessment.
**Sources:**
- the net-kingdom repository and State Hub;
- read-only owner assessments from railiance-platform, access-engine and audit-core, each
made from its own repository files and git history the same day;
- founder-run admin checks recorded in NK-WP-0049.
A check is **met** only if it was observed on the estate that serves production traffic.
Builder-mode acceptances count as **partial**. The definition is in
[NK-WP-0055](../../workplans/NK-WP-0055-security-platform-production-readiness.md).
## Summary
| # | Area | Status | Gap carried by |
|---|---|---|---|
| 1 | Platform root custody | partial | T10 (decisions), NK-WP-0054-T07 |
| 2 | MFA and identity | partial | RPF-WP-0065-T04 (SI-X4), NK-WP-0054-T04/T05/T06, T12 |
| 3 | Bootstrap and recovery | partial | T02–T04, T07 (NK-WP-0053), T08 |
| 4 | OpenBao runtime secrets | partial | T10, T07 (RPF-WP-0036-T03), T12 |
| 5 | Secret rotation | partial | T06, T15, RPF-WP-0035, RPF-WP-0055-T01 |
| 6 | flex-auth (access-engine) policy state | partial | T14, FLEX-WP-0031, FLEX-WP-0024 |
| 7 | Topaz runtime | open | T10 (is Topaz required?), then T14 |
| 8 | Tenant onboarding | partial | T11, T12 |
| 9 | Audit sink | open | T11, AUDIT-WP-0013-T02, AUDIT-WP-0015-T01 |
| 10 | Break-glass | open | T13 |
None of the ten areas is met. Three are open.
## Per area
### 1. Platform root custody: partial
**Evidence.**
- The custody model and records are in `docs/platform-root-custody.md` and ADR-0017.
- The non-secret root-grant record is NK-WP-0045, and railiance-platform keeps its own
custody record in RPF-WP-0049.
- The crisis custody list is `docs/crisis-custody-list.md`.
**Missing.**
- The two-of-three escrow holders are not named. The custody doc's stage S6 is not reached,
so custody is still single-operator, which the architecture allows only before production.
- The OpenBao unseal share holders are `TO CONFIRM` (crisis list item 3).
- The offline king path that works with SSO down is `TO CONFIRM` (item 4).
### 2. MFA and identity: partial
**Evidence.**
- KeyCape issues tokens on the IAM Profile v0.3 contract.
- Privileged-action MFA guards are delivered for the portal and Vergabe clients (NK-WP-0042).
- The retained-MFA restore is proven (NK-WP-0049-T19).
**Missing.**
- The `aal2` binding on OpenBao `platform-admin` is not applied. SI-X4 is still open in
`tools/service-identity/declarations/openbao.yaml` and RPF-WP-0065-T04 is waiting.
- No recorded `tools/iam-profile-conformance/` run against the live issuer (NK-WP-0054-T04
is waiting).
- The bind account is still the human `admin` (NK-WP-0054-T05/T06).
- Validation runs still lean on `platform-root`.
### 3. Bootstrap and recovery: partial
**Evidence.** NK-WP-0049 is finished:
- secret-free bootstrap output;
- daily off-host encrypted backup;
- retrieval that works with OpenBao and SSO down;
- isolated owner restores of all four identity services and of OpenBao.
**Missing.**
- The joint live consumer drill (T02–T04).
- A recurring drill: NK-WP-0053-T02 waits on its first run, and T04 for an `admin`-operated
drill.
- Undrilled crisis items: `pi-admin` (item 7), the ops bundle location (item 8) and operator
access with SSO down (item 9).
- Receipt custody (T08).
### 4. OpenBao runtime secrets: partial
**Evidence.**
- Per-workload scoped Kubernetes and JWT auth and policies (`railiance-platform/openbao/policies/`).
- A file audit device, checked by `make openbao-verify-post-unseal`.
- Operator-only access (RPF-WP-0025).
- The isolated original restore (RPF-WP-0064-T07/T08).
**Missing.**
- Manual Shamir unseal is in use, but it is not recorded as the *approved* production
mechanism. Auto-unseal was never verified.
- No scheduled snapshot job. RPF-WP-0064-T08 says that one restore is not recurring
assurance (RPF-WP-0036-T03).
- No dated live check of the auth methods and mounts against the committed policies.
### 5. Secret rotation: partial
**Evidence.**
- Dynamic database credentials exist for core-hub.
- The rotation lanes are designed in RPF-WP-0035 (blocked; T12 in progress).
- The backup credential default was removed (RPF-WP-0029).
**Missing.**
- Rotation of the exposed material, held by founder decision `1591daa1` and CUST-WP-0073-T05.
- KeyCape client-secret rotation (RPF-WP-0055-T01, backlog).
- No per-lane register of blast radius and verification steps.
### 6. flex-auth (access-engine) policy state: partial
**Evidence.**
- Policy-as-code with check, list-allowed and explain.
- Versioned packages: a fail-open fix ships as a new version (FLEX-DEC-2026-008).
- Tenant-scope coverage (FLEX-WP-0022).
- Nine declared release units.
**Missing.**
- Policies are not imported through a pipeline: a change needs a new image plus a helm
upgrade.
- No platform/tenant package split for `tenant:coulomb`.
- No production explain receipt.
- Decision-record emission is declared but not delivered (FLEX-WP-0031).
- The decision envelope is unsigned (FLEX-WP-0024-T07 waits on a founder gate).
### 7. Topaz runtime: open
**Evidence.** Topaz exists only as an adapter shape (`internal/adapters/topaz/`, FLEX-WP-0004).
Nothing deploys it, and every live decision comes from the Go core.
**Correction to the table.** Fail-closed is declared per consumer (`pep-stance.yaml`), not in
the PDP.
**Decision needed (T10).** Is a delegated Topaz PDP required for production, or does the Go
core satisfy this area?
### 8. Tenant onboarding: partial
**Evidence.**
- The onboarding portal, self-registration and first-login provisioning (NK-WP-0023, 0025,
0036).
- Tenant-scoped identity lifecycle (NK-WP-0038).
- Tenant-scoped authorization (FLEX-WP-0022).
**Missing.**
- The architecture's completion test has not been run end to end for `tenant:coulomb`: a
workload authenticates, gets a scoped decision, obtains only its secret, enforces locally
and produces an auditable record.
- Its audit and correlation leg depends on area 9.
### 9. Audit sink: open
**Evidence.**
- audit-core runs on durable PostgreSQL (AUDIT-WP-0005), with a hash chain (AUDIT-WP-0007).
- A single restore walk on 2026-08-13.
- Registered senders: user-engine, tenant-engine, approval-engine and informed-decision.
The Qonto collector is the only workload source.
**Missing.**
| Source | Status | Owner |
|---|---|---|
| Identity providers (KeyCape, Authelia, LLDAP, privacyIDEA) | not senders | — |
| access-engine | not a sender | AUDIT-WP-0013-T02 waits on access-engine |
| Topaz | not a sender | — |
| OpenBao | audit only on a PVC; the docs say "not a durable audit sink" | — |
| Kubernetes API audit | absent | — |
- No cross-stream correlation id.
- No recurring restore drill.
- No offsite chain head (AUDIT-WP-0015-T01).
**Side finding.** The NK-WP-0031 prerequisite (owner and E2 freshness metadata) has been met
since audit-core commit ca9708e, so NK-WP-0031 can be unblocked.
### 10. Break-glass: open
**Evidence.** The crisis custody list exists, and the king OTP was validated against a
restored privacyIDEA (isolated, 2026-10-24).
**Missing.**
- No recorded or drilled path that works when normal identity (SSO) is down: crisis list
items 4 and 9 are `TO CONFIRM`.
- No post-event review record format.
## Stale statements found
These are for their owners to fix. Nothing was changed here.
- access-engine `SCOPE.md:125` says secrets-engine uses `callerAuth.mode: warn`, but
`values/secrets-engine.yaml` says `enforce`.
- The readiness table row "MFA and identity" names IAM Profile v0.2. The accepted contract is
v0.3.