NK-WP-0049: T33 attempt assembly requires secrets-engine selector --admission; T35/T36 owner prep
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Bind secrets-engine selector/source pins and founder-signed attempt admission
(d1ab097d) as T33's required pre-key step; record kc-tls owner (RCLUSTER-WP-0018)
and public served-chain metadata; add founder gates T39 (TLS disposition,
decision 9f9d0d88) and T40 (attempt signature). Preparation only.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 809600@bnt-lap001
Assistant-Session: 40ba228f-c8a0-4ec9-bb29-3129951afdc4
This commit is contained in:
tegwick 2026-10-21 01:04:19 +02:00
parent d2d1dbcd36
commit f890760176
4 changed files with 175 additions and 3 deletions

View file

@ -286,6 +286,8 @@
| task | NK-WP-0049-T36 | progress | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T37 | done | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T38 | done | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T39 | wait | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0049-T40 | wait | — | workplans/NK-WP-0049-bootstrap-secret-free-recovery-handoff.md |
| task | NK-WP-0050-T01 | done | — | workplans/NK-WP-0050-playwright-consumer-registration.md |
| task | NK-WP-0050-T02 | progress | — | workplans/NK-WP-0050-playwright-consumer-registration.md |
| task | NK-WP-0050-T03 | wait | — | workplans/NK-WP-0050-playwright-consumer-registration.md |

View file

@ -535,3 +535,52 @@ T20/T31 are done. Safe evidence and source/ciphertext/target bindings are in
This accepts internal readback and stored-row signature continuity. Existing-token
MFA, Authelia and KeyCape authentication remain separate; event completeness is
not claimed. The published Storage Share kit remains its recorded version.
## KeyCape original attempt assembly (NK-WP-0049-T33) — 2026-10-21
This is the attended order for the original KeyCape attempt. It is preparation and
authorizes nothing. T18 owns the actual run. Abort at any non-zero step, before the
hidden key prompt.
1. **Founder attempt admission (surviving offline authorization).** The founder
signs a `secrets-engine.recovery-attempt-admission.v1` document with namespace
`secrets-engine-recovery-attempt`, case `secrets15-nk49-readiness`, a window of
at most 24 h, issuer `https://kc.coulomb.social`, and the exact hashes below
(secrets-engine `docs/founder-admission.md`; approved in principle by hub decision
`d1ab097d-cc79-4612-9c17-bb9b364081ac`, not yet signed). The verifier anchor
`/etc/secrets-engine/admission/allowed_signers` (root-owned, runtime-unwritable)
must exist on the attempt host. It is absent on the workstation today.
2. **Selector preflight with admission. This step is required.** From a secrets-engine checkout at
`0f44fbeea18147e65f379632621f2f29ded5f310` (or a replacement the owner names):
```sh
python3 -I tools/check-keycape-recovery-selector.py \
--selector docs/keycape-recovery-selector.json \
--source-sha256 sha256:c0ade429edf452ad17f05d690b7ebef091db7f1a42b5ac350f1e40955c8586c0 \
--admission <attempt.json>
```
Proceed only with exit 0 and status `founder_admitted_attempt_not_native_acceptance`.
The selector bytes must hash to
`sha256:02077af3c18b24f5e4a85992a3d4d0df51a8e458de1e48b48f7eb5f482257012`. The
NK49 admission's consumer block must equal the selector's eight fields
(`secrets-engine-openbao`, `KEYCAPE_SECRETS_ENGINE_OPENBAO_CLIENT_SECRET`,
audience `secrets-engine-openbao`, scope `openbao:login`, subject
`service:secrets-engine`, tenant `tenant:platform`, roles `secrets-engine`,
deny `openbao:admin`). A pass shows founder authority for this one attempt. It
is not native acceptance and not single use. The NK49 execution keeps single-use
consumption and cleanup.
3. **TLS/trust input per T35 disposition** (founder decision
`9f9d0d88-837a-433c-8a11-d30b633b0073`). Under reissue, record the public chain
with railiance-cluster `tools/public-tls-metadata.py` at attempt time and compare
it to the admission. Under original recovery, use only the custody path that
RCLUSTER-WP-0018-T03/T04 delivers. No self-signed substitute is allowed. The TLS
key stays in the owner's own terminal.
4. **Existing six-argument launcher** `tools/bootstrap-recovery/run-isolated-keycape.sh`
with the reviewed admission digest. Its T34 source closure and abort/cleanup
behaviour are unchanged. The private manifest is derived and the archive
registration is compared to the selector inside custody only.
Still open before T33 can close: T35 owner metadata (RCLUSTER-WP-0018-T02) and
the founder disposition; the execution deadline, safe receipt location and
independent receipt verifier fixed in the packet; the anchor installed on the
attempt host. Public observations are in
`docs/evidence/2026-10-21-nk49-t33-readiness/readiness-observation.json`.

View file

@ -0,0 +1,63 @@
{
"schema": "nk49.t35-t36-readiness-observation.v1",
"observed_at": "2026-10-21",
"status": "preparation_only_not_recovery_or_owner_assent",
"t35_public_tls": {
"source": "currently served chain at kc.coulomb.social:443 (public), projected by railiance-cluster tools/public-tls-metadata.py @ a594840; trust file = Mozilla ISRG Root X1",
"originality_proven": false,
"schema": "nk49.public-tls-metadata.v1",
"status": "public_metadata_only_not_originality_or_owner_assent",
"tls_cert_sha256": "f14c928a51b3cf98b0c0964b9bf9a33f4b37e9f30b5c3e949f819fe120ebd15a",
"trust_sha256": "22b557a27055b33606b6559f37703928d3e4ad79f110b407d04986e1843543d1",
"leaf_public_spki_sha256": "sha256:236fa4dcf1ce1d58be398dd01ab067157281e54356a550be35a157527b464b6d",
"leaf_dns_sans": [
"kc.coulomb.social"
],
"leaf_not_before": "2026-09-25T17:57:22+00:00",
"leaf_not_after": "2026-12-24T17:57:21+00:00",
"server_chain_certificates": 3,
"trust_certificates": 1,
"network_contacted": false,
"private_key_argument_supported": false,
"issuer_source": "net-kingdom sso-mfa/k8s/cert-manager/issuers.yaml: ClusterIssuer letsencrypt-prod, ACME HTTP-01, ingressClassName traefik, account key secret letsencrypt-prod-account-key",
"credential_routing": "warden route find returned only SSH-certificate lanes; no TLS lane. Not evidence of absence of an owner.",
"owner": "railiance-cluster (cert-manager, Traefik, cluster backup posture); live work RCLUSTER-WP-0018 T02 todo, T03/T04 wait, T05 todo"
},
"t36_selector": {
"owner_repo": "secrets-engine",
"commit": "0f44fbeea18147e65f379632621f2f29ded5f310",
"selector_path": "docs/keycape-recovery-selector.json",
"selector_sha256": "sha256:02077af3c18b24f5e4a85992a3d4d0df51a8e458de1e48b48f7eb5f482257012",
"source_path": "src/secrets_engine/service_auth.py",
"source_sha256": "sha256:c0ade429edf452ad17f05d690b7ebef091db7f1a42b5ac350f1e40955c8586c0",
"consumer": {
"client_id": "secrets-engine-openbao",
"secret_env": "KEYCAPE_SECRETS_ENGINE_OPENBAO_CLIENT_SECRET",
"audience": "secrets-engine-openbao",
"scope": "openbao:login",
"subject": "service:secrets-engine",
"tenant": "tenant:platform",
"roles": "secrets-engine",
"deny_scope": "openbao:admin"
},
"preflight_cases": [
{
"case": "exact selector + source hash, no admission",
"rc": 0,
"status": "source_selector_matches_not_native_assent"
},
{
"case": "wrong source hash",
"rc": 1,
"status": "source_selector_refused"
},
{
"case": "unsigned admission document",
"rc": 1,
"status": "source_selector_refused"
}
],
"admission_anchor_on_workstation": "absent (/etc/secrets-engine/admission)",
"builder_tests": "net-kingdom tests/test_private_manifest_binding.py + tests/test_prepare_isolated_keycape.py: 27 passed (synthetic inputs; positive bindings, archive/size/transfer/source/issuer/consumer-overlap/symlink/mode/digest negatives)"
}
}

View file

@ -559,7 +559,7 @@ id: NK-WP-0049-T18
status: wait
priority: high
assignee: codex
depends_on: [NK-WP-0049-T15, NK-WP-0049-T16, NK-WP-0049-T19, NK-WP-0049-T32, NK-WP-0049-T33]
depends_on: [NK-WP-0049-T15, NK-WP-0049-T16, NK-WP-0049-T19, NK-WP-0049-T32, NK-WP-0049-T33, NK-WP-0049-T40]
blocking_reason: "Source and synthetic KeyCape lifecycle proof are delivered in T32; await exact owner-held recovery attempt preparation T33, selected consumer acceptance and retained-token MFA for the selected flow."
state_hub_task_id: "141dd773-c1fa-56c1-a852-bbe2372e5125"
```
@ -961,8 +961,8 @@ id: NK-WP-0049-T33
status: wait
priority: high
assignee: codex
depends_on: [NK-WP-0049-T32, NK-WP-0049-T34, NK-WP-0049-T35, NK-WP-0049-T36]
blocking_reason: "Source custody/preflight preparation is evidenced in T34; await original TLS/trust recovery disposition T35 and selected original registration/private-admission metadata T36 before final reviewed command and existing owner process."
depends_on: [NK-WP-0049-T32, NK-WP-0049-T34, NK-WP-0049-T35, NK-WP-0049-T36, NK-WP-0049-T39]
blocking_reason: "Attempt order is assembled with the secrets-engine selector preflight --admission step required (2026-10-21). Still waiting on: T35 owner metadata (RCLUSTER-WP-0018-T02); founder TLS disposition T39; attempt-host admission anchor; fixed deadline/receipt location/verifier."
state_hub_task_id: "56c8d469-7a10-5d50-a30e-95cbf3cd4756"
```
@ -1084,6 +1084,20 @@ publication action remain live; do not bypass the historical identity guard.
Evidence: Custodian October17 `cluster-integration.json`, `coordinator-checkpoint.json`
and October16 `cluster-historical-publication-r1/actual-source-allocator-preview.json`.
2026-10-21: the publication blocker above is superseded. RCLUSTER-WP-0018 is
published (c562d71) and active. The owner is railiance-cluster (cert-manager,
Traefik, backup posture). Its live owner work records are T02 (custody metadata,
todo), T03/T04 (extraction or reissue, owner-attended verify, wait) and T05
(future archive coverage, todo). `warden route find` has no TLS lane. Source:
letsencrypt-prod with ACME HTTP-01 via Traefik, auto-renewing. Served public
chain today: leaf valid 2026-09-25..12-24, cert sha256 f14c928a...d15a, SPKI
sha256:236fa4dc...6b6d, ISRG Root X1 trust 22b557a2...43d1. That is current, not
proven original. The only owner-path disposition today is reissue. Original-key
recovery is an unavailable capability, owned under RCLUSTER-WP-0018-T02, and
unblocks when the owner records independent custody of the kc-tls key.
Owner message dae2e1bb requests T02 metadata. Founder disposition gate is T39.
T35 stays progress.
## Prepare selected original service registration and private admission bindings
```task
@ -1140,6 +1154,50 @@ T33 continues to require the complete reviewed TLS/custody/admission packet.
This extraction records one source outcome rather than counting it again as
original registration validation or consumer continuity.
2026-10-21: selector bound to secrets-engine `0f44fbe`. Selector
sha256:02077af3...7012, `service_auth.py` sha256:c0ade429...86c0. Offline preflight
passes. A wrong source hash and an unsigned admission each refuse with rc=1. The
builder suite passes 27 (synthetic positive and negative
source/archive/selector cases). The founder-signed attempt admission (decision
d1ab097d, SECRETS-WP-0015-T04) is the surviving offline authorization, and T33
now requires `--admission` to pass. Owner message 0fec1113 asks secrets-engine to
confirm the pins, attempt-host anchor coverage (absent on the workstation) and
T04 consumption. Exact archive-to-selector equality is only checkable inside
custody, at attempt time. Evidence:
`docs/evidence/2026-10-21-nk49-t33-readiness/readiness-observation.json`.
T36 stays progress until the owner confirms.
## Founder disposition of original KeyCape TLS recovery
```task
id: NK-WP-0049-T39
status: wait
priority: high
assignee: founder
needs_human: true
decision_id: "9f9d0d88-837a-433c-8a11-d30b633b0073"
depends_on: [NK-WP-0049-T35]
blocking_reason: "Founder decides: accept ACME letsencrypt-prod reissue as the kc.coulomb.social TLS disposition, or require original key custody via RCLUSTER-WP-0018."
```
Founder gate for T35. Approves no mutation and no attempt.
## Founder signs the exact KeyCape attempt admission
```task
id: NK-WP-0049-T40
status: wait
priority: high
assignee: founder
needs_human: true
decision_id: "d1ab097d-cc79-4612-9c17-bb9b364081ac"
depends_on: [NK-WP-0049-T33]
blocking_reason: "Approved in principle (d1ab097d); founder signs the <=24h secrets-engine-recovery-attempt admission only once T33's packet is ready."
```
The signed document is T33's required `--admission` input and T18's surviving
offline authorization. The signature does not run the attempt.
## Verify actual SOPS compatibility and sealed-descriptor read/write custody
```task