3355 lines
No EOL
686 KiB
JSON
3355 lines
No EOL
686 KiB
JSON
{
|
|
"railiance-platform": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0015",
|
|
"type": "workplan",
|
|
"title": "Coordinate audit-core temporary custody and recovery exercises",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "railiance",
|
|
"created": "2026-08-22",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"AUDIT-WP-0008",
|
|
"WH-ENG-20260822-AUDIT-E2-01",
|
|
"WH-ENG-20260822-AUDIT-E2-02",
|
|
"RAILIANCE-WP-0025"
|
|
],
|
|
"origin": "routed",
|
|
"origin_ref": "State Hub messages 10f80080-4c83-42ba-8590-f23c582d9f05 and a93fa88f-a9c5-4539-93ae-0c8f8490f53d",
|
|
"state_hub_workstream_id": "f4640325-e89c-591d-b58e-ec6b087900ac"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0015-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "1d0cd97e-bc65-5dfe-b57a-97649419a118",
|
|
"body": "Define the reviewed path for exactly two distinct bearer values with an\neffective lifetime of at most 900 seconds. Each identity is bound to\n`source=whitehat-security`, one exact synthetic tenant, `may_write=true`, and\n`may_read=true`; neither reuses a production sender identity.\n\nThe design must keep the full sender registry out of namespace `whitehat`.\nUse exact per-engagement KV paths and exact-key ExternalSecrets that project\nonly mounted token files. Define the readiness-gated audit-core rolling reload,\nthe audit-core `expires_at` prerequisite, the scheduled and attended cleanup,\nand value-safe positive/negative evidence.\n\nDone when audit-core and the engagement owner can review a complete path whose\nfailure mode is expiry or denial, not a long-lived accepted bearer.\n\n**Window update (2026-08-22):** engagement `WH-ENG-20260822-AUDIT-E2-01` is\noperator-approved and target-owner-acknowledged for 18:00Z\u201318:15Z. The task is\nwaiting for that attended window. Do not mint before approximately 17:59Z;\nboth identities must expire no later than 18:15Z and cleanup/reload must be\nattended. No unattended scheduler or background credential job is authorized\nby this record.\n\n**Procedure implementation (2026-08-22):**\n`scripts/audit-core-whitehat-e2-credentials.py` now provides fail-closed\n`preflight`, `project`, and idempotent `cleanup` commands. The projection uses\ntwo exact per-engagement OpenBao paths, an ephemeral least-privilege Kubernetes\nauth role, a Whitehat-only ClusterSecretStore, and an ExternalSecret that emits\nexactly `token-a` and `token-b`. Project is hard-gated to 18:00Z\u201318:03Z;\ncleanup remains callable after interruption and removes only the named\ntemporary identities and exact engagement resources. Four unit tests, a live\nvalue-safe preflight, policy formatting, and Kubernetes server-side dry-run\npassed. Live projection and cleanup remain waiting for the attended window.\n\n**Fresh-run readiness (2026-08-22):** the expired `-01` engagement is terminal\nand clean. Its replacement, `WH-ENG-20260822-AUDIT-E2-02`, is operator-approved\nand target-owner-acknowledged for 19:15Z\u201319:30Z. Commit `f135c0a` gives the new\nrun a dedicated `-02` policy, auth role, ClusterSecretStore, four exact KV\npaths, and fail-closed procedure; no `-01` projection reference remains. The\nprojection gate is 19:15Z\u201319:18Z and cleanup must finish by 19:30Z. Platform\ntests (114), Whitehat tests (53), both Kubernetes server-side dry-runs, and a\nlive value-safe preflight passed. At preflight there were no temporary token\npaths, projection resources, runner pod, or temporary sender identities, and\nno secret value was observed. At that pre-run point the task remained `wait`\nuntil an attended operator invoked projection and completed the cleanup receipt.\n\n**Terminal result (2026-08-22):** projection succeeded at 19:17:54Z with\nexactly two bounded identities and the two declared mounted keys. Whitehat\nfailed closed before traffic because its live broker could not consume the\nvalue-safe platform receipt; the runner sent zero target packets and was\ndeleted at 19:21:07Z. Exact cleanup completed at 19:21:39Z and independent\npreflight proved no temporary identity, KV path, ESO resource, mounted Secret,\nor runner remained; audit-core was `1/1` Ready and no secret value was\nobserved. The first attempt also proved automatic rollback when SSH shell\nexpansion corrupted a Go-template argument; commit `d239ed3` fixes that defect.\n\nT01 is done because the mount-only projection, application expiry, reload,\nabort, and cleanup lane is implemented and live-proven. The missing consumable\nbroker contract is not carried as prose in this completed task: versioned\nreceipts, the pre-projection broker gate, generic lifecycle, and future expired\ncleanup interface are implemented under `RAILIANCE-WP-0025`. The dated `-01`\nand `-02` procedures are terminal evidence/cleanup references and must not be\ncopied for another engagement.\n\n## T02 \u2014 Define the runtime database lease recovery exercise"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0015-T02",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:audit-core",
|
|
"blocking_reason": "Value-safe lease revoke/expire exercise must be coordinated with rapp-postgres and audit-core.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "fda4262a-56f6-5f06-a070-8fe7e1297209",
|
|
"body": "Coordinate with `rapp-postgres` and audit-core on a value-safe exercise for\n`database/creds/audit-core-runtime`: identify the lease only by handle, revoke\nor expire it under synthetic load, observe `/readyz` and 503 retry behavior,\nand prove ESO refresh plus mounted-file reread restores service without a pod\nrestart. Record preconditions, time bounds, abort conditions, and rollback.\n\nDone when the procedure proves the property claimed by audit-core's credential\nreader without exposing a username/password or affecting non-synthetic data.\n\n**Procedure implementation (2026-08-22):**\n`docs/audit-core-database-lease-recovery.md` fixes the exact consumer, lease,\ndatabase, synthetic-load, owner, time-bound, abort, and value-safe evidence\ncontract. It requires matching the current lease internally while retaining\nonly its non-usable handle, proving health 200/readiness 503/retryable request\n503 after revocation, forcing only the database ExternalSecret, and proving\nrecovery with the same pod UID and restart count. The read-only helper\n`scripts/audit-core-recovery-preflight.py database-lease` passed live automated\nchecks without observing Secret data. The live revocation still waits for an\napproved window, audit-core/rapp-postgres acknowledgement, a separately\napproved synthetic-load contract, and a named abort operator.\n\n**Harness hardening (2026-08-22):**\n`scripts/audit-core-database-lease-recovery.py` now implements the attended\norchestration but cannot run from repository access alone. It requires a\nvalue-safe approved receipt based on\n`docs/audit-core-database-lease-approval.example.json`, a revision-pinned\nsynthetic-load driver, exact confirmation, an open \u226415-minute window, all\nthree owner acknowledgements, and at least five minutes before the ordinary\nlease refresh. OpenBao metadata inspection corrected the selection contract:\nlease lookup exposes issue/expiry/TTL, not a database username. The harness\ntherefore aborts unless the exact runtime prefix has one live handle whose\nissue time coheres with the ExternalSecret refresh. A live read-only check\nobserved exactly one handle, 0.073 seconds of issue/refresh skew, and no secret\nvalues. It was not revoked.\nThe procedure's responsibility table now uses the same metadata-only selection\nrule; it no longer claims lease metadata exposes or matches a mounted database\nusername.\n\n**Owner receipts complete (2026-08-22):** the canonical direct-review contract\n`f86d418f951f829f075de04dd825c6e2e185e577019ee23d6da1fa9040302d62`\nis approved by audit-core (`0c0e3dff-c7fd-4fac-898b-1aec160f4753`),\nrapp-postgres (`e958f75a-4e41-4103-9261-a4393eb6f1ef`), and\nrailiance-platform (`52ab4c51-0950-45e8-a592-564dc2a450bb`). T02 no longer\nwaits on procedure review. Its remaining gates are a revision-pinned approved\nsynthetic-load driver, a named abort operator, and a non-overlapping \u226415-minute\nlive window after the Whitehat engagement cleanup.\n\n## T03 \u2014 Define the coordinated railiance01 reboot exercise"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0015-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "2fd5849c-240e-4d0a-bf07-5ebf8dfce3fd",
|
|
"blocked_on": "message-from:railiance-infra",
|
|
"blocking_reason": "Single-node outage exercise needs operator access and a declared restart order coordinated with railiance-infra, railiance-cluster, audit-core and the OpenBao package owner.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "ba729d18-f053-539f-86ef-5cb8ad4cce45",
|
|
"body": "Coordinate the single-node outage with `railiance-infra`,\n`railiance-cluster`, audit-core, and the OpenBao package owner. Require current\nbackup evidence, operator access, a declared restart order, OpenBao\nseal/readiness handling, ESO reconciliation, audit-core database and sender\nreadiness, synthetic end-to-end verification, notifications, and explicit\nabort/rollback conditions.\n\nDone when an operator-approved window can execute from one checklist without\nguessing or relying on credential values in the record.\n\n**Procedure implementation (2026-08-22):**\n`docs/railiance01-coordinated-reboot.md` now provides the single ordered\npreflight, hold point, reboot, recovery, escalation, and evidence checklist\nacross host, cluster, OpenBao/ESO, platform-pg, and audit-core owners. The\nread-only helper `scripts/audit-core-recovery-preflight.py node-reboot` passed\nall automated live checks: node/k3s, platform-pg 1/1, continuous archiving,\nfresh completed Barman backup, unsealed OpenBao, ESO Valid/SecretSynced, and\nthe reviewed audit-core digest 1/1 Ready. Live readiness remains fail-closed on\nthe intentionally non-automated gates: an approved window and owner set,\nprovider-console access, a current OpenBao Raft snapshot receipt, 2-of-3 Shamir\nquorum availability, and a named abort operator.\n\n**Snapshot gate hardening (2026-08-22):** reboot preflight no longer accepts a\nfile-existence assertion as snapshot evidence. A receipt based on\n`docs/openbao-reboot-snapshot-receipt.example.json` must be no more than 24\nhours old, match the live OpenBao cluster id and a possible Raft applied index,\ncarry distinct non-placeholder plain/encrypted hashes, and attest encryption,\noff-host persistence, verification, and absence of secret material. The\npending example intentionally fails. Creating the secret-bearing snapshot and\nits off-host copy remains an attended platform-custody action near the future\nreboot window; no snapshot was created in this implementation step.\n\n**Prior-evidence audit (2026-08-22):** rapp-postgres evidence from the\n2026-08-16 reboot proves the same PVC returned without re-bootstrap, original\naudit triples and the isolation fixture survived, platform-pg recovered, and\naudit-core readiness lagged by roughly 40 seconds. It remains a baseline, not\nT03 completion: that reboot was not driven by continuous synthetic accepts and\ndid not measure the complete post-unseal ESO, audit-chain, and accepted-event\nrecovery path required here. T03 therefore still needs one deliberate run, but\ndoes not need to rediscover the expected boot order.\n\n**Owner receipts complete (2026-08-22):** the same canonical contract is\napproved by audit-core (`0c0e3dff-c7fd-4fac-898b-1aec160f4753`),\nrapp-postgres (`e958f75a-4e41-4103-9261-a4393eb6f1ef`),\nrailiance-cluster (`f5919864-b7f1-40b5-b07e-d19055dffca8`),\nrailiance-infra (`9bbf986c-7385-42de-964f-9040eebdfee4`), and\nrailiance-platform (`52ab4c51-0950-45e8-a592-564dc2a450bb`). T03 no longer\nwaits on procedure review. Its remaining gates are the approved outage window,\nfresh encrypted off-host OpenBao snapshot receipt, provider-console access,\n2-of-3 Shamir quorum, and named abort operator.\n\n**WP0027 preparation gate (2026-08-23):** under preparation-only scenario\n`WARDEN-WP-0027-T02-DRILL-20260822-01`, platform-admin OIDC/MFA created a\nfresh Raft snapshot, encrypted it to the established age recovery recipient,\nverified a decrypt stream against the plaintext digest, and uploaded only the\nciphertext through the approved write-only off-host lane. The platform\nvalidator accepted metadata receipt\n`reviews/WARDEN-WP-0027-T02-DRILL-20260822-01-openbao-snapshot-receipt.json`\nagainst the live cluster id and a possible applied index; automated recovery\nchecks remained green and no secret value was observed. Both local snapshot\nfiles were securely deleted. The platform accepts the exact attended driver\nrole, but this receipt authorizes no seal, unseal, restore, reboot, or other\nlive execution; the final scenario still requires the independent quorum gate,\nfully parameterized green preflight, and an exact human GO.\n\n**WP0027 live attempt terminal NO-GO (2026-08-23):** State Hub decision\n`449a697a-5303-4582-aa9e-b0bc8b35ab2d` opened the bounded live window and the\nfully parameterized preflight reran green at `2026-08-22T22:55:11Z`. At the\nlive hold point, the governed attended-login adapter authenticated but could\nnot persist its token helper into the agent's read-only home and unexpectedly\nemitted the short-lived credential into captured output despite the no-print\ncontract. The token was immediately self-revoked and the drill stopped before\nseal. Post-abort status proved OpenBao remained initialized and unsealed with\nzero unseal progress; no seal, unseal, reboot, restore, policy, PVC, or general\nworkload mutation occurred. Metadata-only NO-GO receipts were sent to\nops-warden (`b04e92bc-4523-4c3e-8d14-78de5da4e67e`) and railiance-infra\n(`5264d499-0ee2-40b5-bffd-f1f875718153`). The decision is consumed and must not\nbe retried. A future window requires a login adapter that proves isolated\nwritable token-helper state and output suppression on persistence failure,\nfollowed by fresh owner receipts and a fresh human decision.\n\n2026-10-03: human gate routed to hub decision 2fd5849c-240e-4d0a-bf07-5ebf8dfce3fd (D5: Production risk acceptance and live-host authorizations) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## T04 \u2014 Route the contracts and approval gates"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0015-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "52f37fac-2449-5e65-ab5b-8c4889caee48",
|
|
"body": "Route the reviewed procedures to audit-core, `rapp-postgres`,\n`railiance-cluster`, and `railiance-infra`. Identify each live mutation and its\nowner, record outstanding approvals, and keep live tasks waiting until the\nengagement or recovery window is explicitly acknowledged.\n\nDone when every participant has the same value-safe procedure, responsibility\nmap, and stop conditions.\n\n**Routing package (2026-08-22):** the owner-review package consists of\n`docs/audit-core-whitehat-e2-credential-projection.md`,\n`docs/audit-core-database-lease-recovery.md`, and\n`docs/railiance01-coordinated-reboot.md`. T01's live credential window remains\nseparate from the new T02/T03 authorization gates. Outstanding approvals are\nstated in each procedure and enforced by the read-only preflight output rather\nthan inferred from repository access.\n\nRouted from immutable revision `bd25f7f` to audit-core\n(`5ef8f06b-76f4-48ae-a09e-ba4eb87e6906`), rapp-postgres\n(`8e80f166-267a-471e-ab1d-e0293e0781e7`), railiance-cluster\n(`268d64c0-4b3c-408f-bdfb-e07de588111d`), and railiance-infra\n(`3918db56-ca20-4cc7-8b63-001d840bc608`). Every participant received the same\nprocedure paths, responsibility boundary, stop conditions, passing automated\npreflight state, and explicit statement that no live mutation was requested.\n\n**Direct review interface (2026-08-22):**\n`interfaces/RPF-WP-0015-owner-reviews.json` and\n`scripts/wp0024-owner-review.py` replace follow-up prose-to-task translation\nwith owner-executable `show`, `verify`, `approve`, `request-changes`, and\naggregate `status` operations. Approvals are valid only for the canonical\ncontract digest and the owner's pinned artifact hashes, so a changed procedure\ninvalidates the old receipt. The interface runs only closed-set, read-only\nchecks and cannot perform any T02/T03 live mutation.\nThe task map requires audit-core, rapp-postgres, plus railiance-platform for\nT02, and audit-core, rapp-postgres, railiance-cluster, railiance-infra, plus\nrailiance-platform for T03; aggregate status is computed independently for\neach task.\n\n## Acceptance\n\n- [x] E2 cannot proceed without enforced sender expiry and exact-path projection.\n- [ ] Database recovery is restart-free and evidenced without credential values.\n- [ ] Reboot recovery has an ordered, owner-signed checklist and abort path.\n- [x] No live action is implied by completing this design workplan.\n\n## Portfolio review \u2014 2026-09-05\n\nINTENT binding: tested recovery and dependable custody. Procedure construction\nis complete; the two tasks were incorrectly left `progress` while their live\nwindows remained unavailable. They now explicitly wait. This does not claim\nthat the experiments passed or that prior expired approvals can be reused.\n\nT02 retains the S3 lease/ESO acceptance contribution. `audit-core` owns the\nsynthetic-load driver and application retry/readiness proof (AUDIT-WP-0008);\n`rapp-postgres` owns database acceptance. Unblock with a revision-pinned load\nreceipt, named abort operator and fresh bounded window.\n\nT03 retains only S3 snapshot, quorum/unseal, ESO and database-readiness gates.\nHost reboot execution belongs to `railiance-infra`, cluster recovery to\n`railiance-cluster`, application acceptance to audit-core. Existing owner\nprocedure receipts remain evidence of review, not fresh live GO. Unblock with\nfresh snapshot/quorum/access evidence, owner confirmations and an outage window.\nThe terminal NO-GO is not rerunnable. RPF-WP-0017 closed the local output\ncontainment defect; the next attempt still needs current acceptance evidence.\n\nDo not create another platform-owned whole-host drill or duplicate these live\ntasks in RPF-WP-0036; that plan owns recurring service assurance.\n\n## Blocker recheck \u2014 2026-09-05\n\nAUDIT-WP-0008-T07 already records the synthetic-load driver at `8c8bcf4`,\ncandidate receipt `7879bf65-06b7-4d0c-bbd1-873b6d20b7fc` and SHA-256\n`941ba251f638869626b06e9cbf430c70188c0bdf4715e3eff9c7610366f68662`.\nIt also records a local accepted/duplicate HTTP round trip. Driver construction\nis no longer missing. T02 waits on its separately approved sender identity,\nfresh bounded window, abort operator and live recovery receipt. Local driver\nsuccess does not prove lease revocation/ESO recovery. T03 remains a separate\noutage exercise; no historical window or terminal NO-GO may be reused.\n\n## Loose-end review \u2014 2026-09-27\n\nT02/T03 remain waiting on fresh attended execution windows, named abort operators, current custody/quorum evidence and owner execution. The implemented load driver and prior procedure approvals do not supply a fresh live recovery receipt. No expired window was reused."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0027-keycape-live-secret-exposure-recovery.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0027",
|
|
"type": "workplan",
|
|
"title": "Coordinate KeyCape live Secret exposure recovery",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "railiance",
|
|
"created": "2026-08-23",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"KEY-WP-0011"
|
|
],
|
|
"origin": "routed",
|
|
"origin_ref": "State Hub messages e88abb61-e393-4a82-817c-5ac378a2ee3d, acf98be3-ff6b-4270-bd21-0193bebd806b, aeb216b5-9f1b-404b-a483-fb08a00a49b1, and 71b1008a-7fd7-4500-85c6-e8893a6d80d4",
|
|
"state_hub_workstream_id": "b2c25a01-4a80-55c1-90cf-8538000f7e0e"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0027-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "53f47272-92ab-563b-9d69-5eafee733e6b",
|
|
"body": "Accepted the KeyCape/NetKingdom incident reports, stopped payload inspection,\nand routed custody through `warden route show openbao-api-key`. Metadata-only\npreflight pinned Secret UID/resource version, Deployment generation/image, and\nthe public JWKS digest/kid. The legacy value-printing rotation helper is banned.\n\n## T02 \u2014 Publish the governed bundle cutover"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0027-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "3c55b1cd-8f6b-5a48-b416-18ab711954e3",
|
|
"body": "`docs/keycape-live-secret-exposure-recovery.md` defines owners, required\nrevision/window/operator receipts, private-file handling, one guarded bundle\napply, provider/consumer ordering, forward-only abort, positive/negative proof,\npredecessor revocation, and sanitized evidence.\n\n## T03 \u2014 Collect exact owner acknowledgements"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0027-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocked_on": "message-from:net-kingdom",
|
|
"blocking_reason": "Attended resolver run: postchecks outstanding; NetKingdom asked to package the complete sequence as one receipt-producing command for the next attended session.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "714ae011-903d-55e2-ac47-801b8ef879d1",
|
|
"body": "KeyCape supplied source revision `93704fd2424503007c20b458b62a7f7d994bb288`,\npost-rotation JWKS SHA-256\n`c6faac5dfeef2453daf9cfc14671f62b535dd321befdf6014e3ee5c2cf1f1156`, and\nrollout/predecessor evidence (messages `05b49688-76a8-4be9-a00d-95408c798697`\nand `538046b9-2dbb-4704-b7b6-2dbf16c5e3bb`). NetKingdom pinned the value-safe\ndependency and provider sequence at `c24d67b` (message\n`71b1008a-7fd7-4500-85c6-e8893a6d80d4`). The persistent privacyIDEA\n`lldap-coulomb` resolver still requires an attended provider-admin update, so\nT04 remains blocked for that explicit follow-up. The digest-bound approval\ntemplate is published at\n`docs/keycape-exposure-rotation-approval.example.json`; no additional Secret\napply is authorized by this receipt.\n\nNetKingdom has now pinned the remaining attended resolver procedure at\n`eec7007` (procedure checkout `f2e578c`, owner receipt\n`45b236c8-052f-43d3-a472-44f8e9694da2`). It performs one resolver-only POST,\nprotected interactive inputs, boolean postchecks, replacement-success and\npredecessor-denial evidence, and forward-only abort. T03 is ready for the\nattended run; T04/T05 remain open until that run produces a sanitized receipt.\n\nThe operator completed the resolver-only update and received\n`privacyIDEA resolver update: PASS`. Postchecks were not yet run; the operator\nwas instructed to stop rather than improvise. NetKingdom has been asked to\npackage the complete sequence as one receipt-producing command for the next\nrun.\n\nThe Railiance-side custody contract is drafted at\n`docs/net-kingdom-credential-custody-contract.md`. It deliberately leaves the\nOpenBao path and field names unfilled pending owner confirmation; the routing\nlane remains unresolved and no credential fetch or retry is authorized.\n\n2026-10-03: human gate routed to hub decision 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1: Attended OpenBao provisioning window: one session clears the pending credential lanes) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## T04 \u2014 Execute the attended rotation"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0027-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "28b31e57-7a76-5100-8a61-9aa87339c5d7",
|
|
"body": "Requires a fresh exact human GO, an at-most-30-minute window, named driver and\nabort operator, approved revisions, provider access, private workspace cleanup,\nand all T03 acknowledgements. No value may enter captured output.\n\n## T05 \u2014 Prove predecessor denial and close"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0027-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "9cb5fa67-012a-58cf-bafb-e7c7d4f9782d",
|
|
"body": "Verify replacement operation and predecessor rejection for the signing key,\nLLDAP binding, Authelia client, and privacyIDEA token. Retain only safe\nfingerprints, resource versions, public JWKS metadata, boolean results, rollout\nstatus, timestamps, and cleanup receipts.\n\n## T06 \u2014 Publish the Railiance/OpenBao custody handoff"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0027-T06",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocking_reason": "Platform/OpenBao owner must publish the non-secret routing receipt for both lanes through the attended handoff; values are never inferred.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "3b9748c4-2906-5ba7-9d34-0a7067a59283",
|
|
"body": "The platform/OpenBao owner must publish a non-secret receipt for both routing\nlanes: canonical mount/path, field name, KV version semantics, least-privilege\npolicy and auth method, expiry/rotation/revocation semantics, and the approved\nattended handoff identifier. Do not infer or invent any of these values. After\npublication, update `docs/net-kingdom-credential-custody-contract.md`, ask\nops-warden to refresh lane resolvability, and pass only protected inputs to\nNetKingdom's minimal resolver reconciliation flow.\n\n**Operator decision, 2026-09-15:** leave both historical resolver lanes blocked.\nDo not invent mount/path/field names. The KeyCape factor service lane from\nRPF-WP-0040 remains the separate active custody; it does not close these\nincident lanes.\n\n2026-10-03: human gate routed to hub decision 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1: Attended OpenBao provisioning window: one session clears the pending credential lanes) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Portfolio review \u2014 2026-09-05\n\nINTENT binding: secure custody and incident closure. The goal above is historical;\nthe remaining platform scope is custody and acceptance of owner evidence.\n\n**T04 is complete by existing owner evidence, not by a new action here.**\n`key-cape/workplans/KEY-WP-0011-live-secret-exposure-recovery.md` T02/T03 and\n`net-kingdom/workplans/NK-WP-0033-keycape-secret-exposure-rotation.md` T04\nrecord the approved 2026-08-23 bundle replacement. Do not repeat that rotation\nmerely because this platform task previously remained `wait`.\n\nThe 2026-08-27 NK-WP-0033-T05 update is newer than the earlier notes above:\nthe resolver binding was reconciled, but there is no complete green receipt.\nThe predecessor value is unavailable; manual observations are not a recorded\nnegative proof. No one should recover or fabricate a predecessor just to make\na test pass. The incident owner must rule explicitly on the residual evidence\nand acceptable disposition. Overall incident closure remains open.\n\n- T03 waits for current NetKingdom/provider evidence disposition and the exact\n platform custody acknowledgements; old procedure acknowledgements exist.\n- T05 waits for the repaired owner command's sanitized receipt and the\n incident owner's explicit disposition of the unavailable predecessor.\n NetKingdom owns resolver/MFA execution (NK-WP-0033-T03/T05); this repo accepts\n custody-related results without taking over the identity provider.\n- T06 waits for confirmed mount/path/fields, writer/reader authority and the\n operator handoff. The existing draft leaves those facts intentionally blank.\n\nNo new owner acceptance or coordination message is asserted by this review.\nKeep this incident separate from the new-lane queue; broad lane approval cannot\nclose an exposure.\n\n## Loose-end review \u2014 2026-09-27\n\nT05 is now done by the newer owner record: NK-WP-0033 accepted the operator ruling on 2026-09-23 and recorded the green attended read-only resolver/MFA/health/cleanup receipt. Predecessor denial remains explicitly NOT-PROVEN, with the unavailable-predecessor disposition accepted by Bernd Worsch; it is not relabelled as a successful negative test. KEY-WP-0011 already closes the other credential-class rotation/recovery evidence. See `docs/evidence/2026-09-27-keycape-incident-owner-return.json`. T03/T06 still wait for the complete platform custody/routing handoff. The owner names operators/lldap/admin and operators/privacyidea/pi-admin, but does not supply the complete field/auth/expiry/handoff contract required by T06. The September 15 instruction to leave historical routing lanes blocked remains in force. No repeat rotation or predecessor recovery was attempted."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0035-credential-lane-implementation.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0035",
|
|
"type": "workplan",
|
|
"title": "Implement reviewed credential lanes with separate owner gates",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"created": "2026-09-05",
|
|
"updated": "2026-10-09",
|
|
"related": [
|
|
"RPF-WP-0032",
|
|
"RPF-WP-0033",
|
|
"RPF-WP-0034"
|
|
],
|
|
"state_hub_workstream_id": "975db491-5412-5e27-8e34-14a2417bb039"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0035-T01",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "0f3606bb-e95b-5484-8a57-bcdd6e3916fd",
|
|
"body": "Completed 2026-09-05. Preserved the three designs under\n`docs/credential-lane-designs/`, identified native owner responsibilities and\nlinked each superseded task below. Owners have not been sent new requests and\nno new external acceptance is claimed. STATE-WP-0085-T09 is already done;\nthe signing dependency belongs to the proposed FLEX-WP-0020-T05 cutover.\n\n## Accept and provision secrets-engine service JWT login"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T02",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"depends_on": [
|
|
"KEY-WP-0037-T02",
|
|
"KEY-WP-0037-T03",
|
|
"KEY-WP-0037-T04"
|
|
],
|
|
"blocking_reason": "CCR-2026-0038 applied 2026-10-08. The login proof passed 2026-10-10 (secrets-engine a963a77, message 0dba7e04), and the consumer contract is published at docs/contracts/secrets-engine-openbao-jwt-login.yaml. No-fallback check passed 2026-10-10 (secrets-engine 9ec4e0b). Still waits on the claim refusals (key-cape KEY-WP-0039 probe session, scripts/openbao_negative_probe.py bae9f85) and capabilities-self deny on the guarded paths, then ops-mason MASON-WP-0009-T05.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "e0c82ea9-05a5-537e-8fbf-67534263572e",
|
|
"body": "Supersedes RPF-WP-0032-T02. Design:\n`docs/credential-lane-designs/secrets-engine-service-jwt.md`.\n\nPlatform owns the exact JWT mount/role/policy, effective-policy negative tests\nand a metadata-only custody receipt. KeyCape owns issuer/JWKS and service\nregistration (KEY-WP-0009); secrets-engine owns service authentication and\nauthority consumption (SECRETS-WP-0008-T06, SECRETS-WP-0007-T04).\n\n**Unblock:** live registration and protected client custody, reviewed exact source\nand attended apply authority. Issuer/JWKS and consumer source claims now agree;\nsee the 2026-09-27 return below. A service login does\nnot grant lane mutation authority. Do not build another identity provider or\nlifecycle engine here.\n\n**Done when:** approved exact role succeeds for the intended service, wrong\nissuer/audience/subject/claims and unrelated secret access fail, bounded TTL\nand revocation are proven, the consumer explicitly opts into the verified\ncontract, and rollback/cleanup receipts contain no secret material.\n\n2026-10-09 (T03 source): founder ruled the tenant segment stays `coulomb`\n(ops-mason `b72ff77d`). New CCR request type `workload-kv-operator-matrix`\n(`scripts/operator_matrix_lane.py`): exact per-entry capabilities, OIDC role on\nthe existing `netkingdom` mount only, and exact agent denies on all four data\nand metadata paths appended to the live `agent-high-risk-boundary` (live content\npreserved; partial presence refused). `scripts/fluid_telegram_custody_move.py`\ncopies the four undocumented `infotech` entries with CAS 0, verifies all, then\nmetadata-deletes the sources. `scripts/kv_duplicate_retire.py` retires\n`activity-core/default/llm-connect-provider-secrets` only if no live non-admin\npolicy grants it. Founder session (each helper prints nothing; read the receipts):\n\n```bash\ncd ~/railiance-platform\nexport BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200\nW='warden access openbao-platform-admin-login --exec --'\n# 1. dry-runs (no value reads, no writes)\n$W python3 scripts/fluid_telegram_custody_move.py --dry-run --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move-dry.json\n$W python3 scripts/kv_duplicate_retire.py --dry-run --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire-dry.json\n# 2. lane: approve, confirm binding, apply\npython3 scripts/credential-change.py approve CCR-2026-0039 --reviewer \"platform-owner, fluid-telegram-owner, key-cape-owner (founder Bernd Worsch)\" --comment \"Approve ops-mason plan fluid-telegram-operator-credential-lane (spec 41a0ca27): four-entry matrix at coulomb/fluid-telegram/hall-of-helix, OIDC role on netkingdom, agent denies.\" \\\n && python3 scripts/credential-change.py confirm-binding CCR-2026-0039 --reviewer founder --comment \"groups=[fluid-telegram-operators] (LLDAP, member tegwick) and /assurance/level=aal2 match key-cape b2ed890f.\" \\\n && $W python3 scripts/credential-change.py applier-apply CCR-2026-0039 --confirm \"DELEGATED APPLY CCR-2026-0039\" --actor founder --record-state-hub --quiet\n# 3. custody move, then duplicate retirement\n$W python3 scripts/fluid_telegram_custody_move.py --confirm 'MOVE fluid-telegram hall-of-helix to coulomb' --receipt ~/ft-move.json\n$W python3 scripts/kv_duplicate_retire.py --confirm 'RETIRE activity-core/default/llm-connect-provider-secrets' --receipt ~/kv-retire.json\n```\n\n2026-10-09 (T03 founder session): CCR-2026-0039 applied at 10:30Z; readback\nmatched for the 8 boundary denies, policy and role. Custody move `moved`: all\nfour entries copied at coulomb v1 (operator-session from infotech v4) and the\ninfotech entries metadata-deleted. Duplicate\n`activity-core/default/llm-connect-provider-secrets` retired; its first dry-run\nrefused on mount-wide `platform/metadata/*` survey grants, after which the check\nwas narrowed to data-path grants (`64ae594`). Receipts:\n`docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json`.\n\n2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion.\n\n2026-10-03 (CUST-WP-0075): gate check. SECRETS-WP-0007-T04 is done (2026-09-27), so the gate named in the design is open. It is not the last one: the design says to confirm the exact live client registration and protected client-side custody before writing, and positive-login proof needs a real KeyCape service JWT. KeyCape's contract (`openbao-service-auth-contract.md`) and KEY-WP-0009 claim source registration only; the live registration of `secrets-engine-openbao` and its client-credential custody are \"a separate approved custody action\" that no workplan task owns yet (SECRETS-WP-0008-T06 waits on this task). Re-qualified with `blocked_on: message-from:key-cape`; key-cape was asked for the owning task id, which will replace it as `depends_on`. The design stays proposed and no child command was written. Not approvable in D1 yet.\n\n2026-10-04: Founder authorized the prepared coordination request. Sent\n`b4fc62ea-f92c-4410-919a-9f3cce2d406b` to key-cape on preparation thread\n`f84637fa-2355-4971-a2dc-7f1fd01710a8`, referencing platform source\n`6b91d510395215d178d60ee8884e7fc00930a0cf`. Requested actual registration and\nprotected-custody owning tasks/status/revisions and non-secret receipts. Source\nregistration is not live custody; no value fetch or live registration was\nrequested. T02 remains waiting on the owner return and separate execution gates.\n\n2026-10-04 blocked-task review: KeyCape returns 58826056/eb20a78c now identify\nKEY-WP-0037-T02/T03/T04, replacing the unowned-registration wait with real\ndependencies. Prepared proposed CCR-2026-0033 and exact-path issuer policy/auth,\nsso-only ESO and evidence checklist from the returned candidate coordinates.\nNo issuer/consumer value, registration or native issuance is supplied by them.\nsecrets-engine must return independent source acceptance of consumer host/path,\nprotected delivery and rotation/revocation ownership; awaiting that source phase\ndoes not depend on its full live service-login task. KeyCape's exact-primary sync\nremains pending its scoped historical identity repair. Requirements and acceptance\nboundaries: `docs/provisioning-windows/2026-10-04-1000/dependency-requirements.md`.\nThis workplan was already blocked and remains blocked on its open owner/live gates.\n\n2026-10-06: secrets-engine returned consumer custody source acceptance\n(message 680136e2, SECRETS-WP-0012, commit a3897c2). CCR-2026-0033 finalized as\n**proposed**: KV path corrected to `platform/workloads/keycape/secrets-engine-openbao`\n(applier scope), consumer copy coordinates with D1-D4 pending founder choice,\nrotation/revocation ownership, live order and rollback. Attended custody child\n`scripts/keycape_secrets_engine_openbao_custody.py` with fake-only tests\n(`tests/test_keycape_secrets_engine_openbao_custody.py`) refuses without an exact\nfounder decision id recorded in the approved CCR. Nothing executed, generated or\napplied; nothing added to active GitOps. The founder approval it needs is T09.\n\n2026-10-09: KEY-WP-0037 finished 2026-10-07 (registration live, issuance\nverified 10/10, key-cape e0b5fae); CCR-2026-0033/0034 applied. Source for this\nlane is now complete as **CCR-2026-0038** (proposed,\n`credential-change-requests/CCR-2026-0038-secrets-engine-service-jwt-login.yaml`).\nThe delegated applier gained a narrow `service-jwt-login` request type\n(`scripts/service_jwt_lane.py`): auth mount fixed to `keycape-services`, policy\nmust equal the generated login-self policy, role/config keys allow-listed,\nTTLs at most 15m, uses 1..16, `token_no_default_policy`, refusal if the mount\nexists with another type, and a value-free readback compare after the writes.\nPolicy `secrets-engine-login-self` now also carries explicit `deny` on\n`platform/{data,metadata}/workloads/keycape/secrets-engine-openbao` so\nops-mason invariant (ii) (no capability on the client-secret path) holds even\nif identity groups were ever attached. Tests: `tests/test_service_jwt_lane.py`\n(8) plus the updated contract test; full suite unchanged apart from 5\npre-existing failures unrelated to this lane.\n\nFounder apply (one line; approval, binding confirmation and silent apply):\n\n```bash\ncd /home/worsch/railiance-platform && python3 scripts/credential-change.py approve CCR-2026-0038 --reviewer \"platform-owner, key-cape-owner, secrets-engine-owner (founder Bernd Worsch)\" --comment \"Approve service-JWT login lane: mount keycape-services, role secrets-engine-openbao, policy secrets-engine-login-self (self endpoints + deny on the client-secret path).\" && python3 scripts/credential-change.py confirm-binding CCR-2026-0038 --reviewer founder --comment \"Bound claims match KeyCape registration: aud secrets-engine-openbao, sub service:secrets-engine, principal_type service, tenant tenant:platform, roles secrets-engine, scope openbao:login; issuer https://kc.coulomb.social RS256.\" && warden access openbao-platform-admin-login --exec -- python3 /home/worsch/railiance-platform/scripts/credential-change.py applier-apply CCR-2026-0038 --confirm \"DELEGATED APPLY CCR-2026-0038\" --actor founder --record-state-hub --quiet\n```\n\nDone after that: login proof with a real KeyCape service JWT\n(SECRETS-WP-0012-T03 probe-openbao; policies exactly\n[secrets-engine-login-self], capabilities-self deny on the guarded paths,\nrevoke-self), negative claim checks, then publish the consumer contract file\nand ops-mason MASON-WP-0009-T05 rechecks invariant (ii).\n\n## Implement the platform operator-write CCR contract and Fluid lane"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocking_reason": "Founder session done 2026-10-09: CCR-2026-0039 applied (readback matched), custody moved to coulomb, duplicate retired (docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json). Waits on ops-mason verification (MASON-WP-0005-T05: positive matrix, sibling/agent/non-member denial) and the owner salt CAS probe (FT-WP-0002).",
|
|
"priority": "high",
|
|
"state_hub_task_id": "f47e5bc5-6f3c-54bb-aa35-260ad03892ba",
|
|
"body": "Supersedes RPF-WP-0033-T02. Design:\n`docs/credential-lane-designs/fluid-telegram-operator-kv.md`.\n\nPlatform owns the per-path capability schema/validator, exact OpenBao policy\nand accepted custody coordinates. MASON-WP-0005 owns construction coordination\nand engine integration; KeyCape/NetKingdom own OIDC/MFA and group membership;\nFT-WP-0002 owns client CAS, prefix correction, output containment and Telegram\napplication acceptance. Retain the existing read-only CCR semantics.\n\n**Unblock:** accept tenant/path and per-entry field/capability matrix; confirm\nactual group/assurance and callbacks, reviewed construction contract and writer\nauthority. Contract review can proceed without a live credential; the final\nschema cannot be treated as accepted solely because a draft exists.\n\n**Done when:** validation rejects broad/unsupported grants, the consumer proves\nCAS=0 first-write behavior and no value output, approved identities can perform\nonly the exact matrix, negative/expiry/revocation checks pass, custody is seeded\nthrough the separate writer, and the verified route has a safe handoff receipt.\nThe unattended adapter remains a separate demand and gets no operator session.\n\n2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion.\n\n## Accept the needed signing lane and deliver it to the owning runtime"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "35a85846-61d5-54ce-8b18-ede45733d53c",
|
|
"body": "Supersedes RPF-WP-0034-T02. Design:\n`docs/credential-lane-designs/state-hub-preflight-signing.md`.\n\nPlatform owns signing-key custody, exact read policy/role and scoped delivery\nacceptance. State Hub owns API chart/env wiring, all-replica rotation fencing\nand health. FLEX-WP-0020-T05 owns the rename preflight/cutover dependency;\nSTATE-WP-0085-T09's adoption-plan delivery is already complete.\n\n**Unblock:** State Hub/repo-manager and the consuming migration owner confirm\nthat this transitional State Hub lane is still needed during retirement;\nrecord the target runtime, namespace/SA/auth audience and an executable\nrotation fence, plus approved writer and deployment window. Do not broaden the\nlane into a general repository-rename authority or provision for a stale demand.\n\n**Done when:** protected one-time generation, API-only ESO delivery, negative\naccess checks and a non-mutating signed preflight pass; every API replica uses\nthe accepted version; rotation/invalidation and recovery are evidenced. No\nrepository rename is part of S3 lane acceptance. If demand is withdrawn, record\nthe owning decision and cancel this task explicitly rather than provision it.\n\n2026-09-05 continuation: verified the live primary cluster identity and healthy\nsingle API replica; the signing ExternalSecret is still absent. Added a writer\nguard against wrong-cluster kubeconfigs before any OpenBao access. The default\nworkstation kubeconfig's local port-forward listener was unavailable. Activation\nstill needs the contained attended OIDC/MFA login and the acceptance evidence\nabove; source preparation is not live completion. See\n`history/2026-09-05-preflight-signing-activation-readiness.md`.\n\n\nCompleted 2026-09-05: user-led attended activation generated version 1 and\nrotated to version 2 with every API replica stopped. Exact access and negative\nidentity checks passed; ESO delivery and API-only exposure passed; the recovered\nsingle API replica accepts new signed preflight and rejects its predecessor by\nsignature, with healthy primary identity and no preflight blockers. State Hub\nchart commit `49e3182`, Helm revision 59. No repository rename executed.\nEvidence: `docs/evidence/RPF-WP-0035-T04-signing-activation-2026-09-05.json`;\nclosure: `history/2026-09-05-preflight-signing-activation-complete.md`.\n\n## Admit KeyCape approval-engine client custody and delivery"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T05",
|
|
"status": "done",
|
|
"needs_human": false,
|
|
"intervention_note": "",
|
|
"priority": "high",
|
|
"state_hub_task_id": "e15d62c9-e5da-5721-a135-87c050f7851c",
|
|
"body": "Answers KEY-WP-0013-T02 (State Hub message\n`278a3ebe-b529-49f6-bd1a-e3ebcf318260`). Admission:\n`docs/credential-lane-designs/keycape-approval-clients.md`; requests\n`CCR-2026-0017` (secrets-engine-approval) and `CCR-2026-0018`\n(approval-engine-operator).\n\nPlatform owns the two custody paths, exact-path read policies, Kubernetes auth\nroles and the KeyCape-side ESO delivery. KeyCape owns the client registrations,\nissuance, claim set and disablement; approval-engine owns approval semantics and\naudit of emitted actions.\n\n2026-09-08 admission response: both proposed KV paths confirmed unchanged; field\n`client_secret` corrected to `CLIENT_SECRET` for the uppercase KV convention and\nCCR validator. Kubernetes delivery references confirmed against the live `sso`\nnamespace, which already resolves `KEYCAPE_RAPP_QONTO_CLIENT_SECRET` through the\nsame `secretKeyRef{key: client-secret}` shape on image `main-153258b`. Attended\nauthority named as the governed `openbao-platform-admin-login` lane\n(`founder_required`); KeyCape's refusal to treat its generic `warden plan`\ndatabase match as authorization was correct. Rollout agreed as one attended\nsession with the KeyCape reading build pinned but undeployed, ordered after the\nAuthelia issuer precondition in message `c8b1ad10-dae8-48fb-a0ea-7e2a101c54bf`.\nPolicies, ClusterSecretStores and ExternalSecrets are written and validated,\nnone applied.\n\n**Unblock:** owner approval of both CCRs, a KeyCape image that reads both\nenvironment names, the settled Authelia `iss` pin, and a founder-attended window\ndate. Verifier-side custody only \u2014 no client-side read lane is admitted, and no\nscope beyond the two declared sets.\n\n**Done when:** both CCRs are approved, the attended window seeds both KV paths\nwith CAS=0, policies/roles/stores/ExternalSecrets apply and sync, the KeyCape\nbuild resolves both environment names, KeyCape evidences live JWKS signature and\nexact claim bindings with excess scopes denied (operator `consume`, human\n`consume`), platform evidences cross-path/wrong-identity/out-of-namespace denial,\nand every receipt is metadata-only. If either registration is abandoned, KeyCape\ndisables it before the KV version is destroyed.\n\n### 2026-09-08 actual upstream issuer returned\n\nThe admitted KeyCape one-shot probe verified the actual signed upstream issuer\nas **`https://auth.coulomb.social`** at 21:44:44 UTC. Signature, audience,\nvalidity window and nonce checks passed and the pinned Job exited 0. All\nfive temporary resources and the Pod were removed; normal KeyCape Deployment\nand config Secret metadata are unchanged. See\n`docs/evidence/2026-09-08-keycape-upstream-issuer-proof.json`.\n\nT05's unknown-issuer input is resolved. The configuration owner still ensures\n`authelia.issuer` equals that exact HTTPS value before the custody window.\nBoth CCRs remain proposed and await the named reviews; this probe grants no\ncustody mutation or client-side read. Keep the current authority preflight and\nthis signed-token proof as separate receipts. Live ESO/client/approval and\nseparate audit/client-side custody acceptance remain open.\n\n\n2026-09-09 configuration and review-queue return: NetKingdom pinned the verified\nHTTPS issuer, using an atomic UID/resourceVersion test and independent readback.\nSecret revision `58713343`; unrelated configuration and signing key unchanged;\nno Deployment rollout. Receipt: `docs/evidence/2026-09-09-keycape-upstream-issuer-pin.json`.\n\nThe two existing CCRs remain proposed. They now link to concrete pending review\ndecisions, with platform-operator and key-cape-owner named explicitly. See\n`docs/credential-lane-designs/keycape-approval-clients-review.md`. T05 owns this\nhuman dependency; HFACT consumes it without a duplicate approval request.\nCustody/ESO activation, client verification and the separate client-side/audit\nlanes remain open. Current CLI apply plans refuse the proposed requests.\n\n\n2026-09-09 admission: the user explicitly approved both CCRs in the named\nplatform-operator and key-cape-owner roles. Both source requests are approved\nand both linked Hub decisions are resolved. Receipt:\n`docs/evidence/2026-09-09-keycape-approval-admission.json`. The completed review\nintervention is cleared; T05 is progress while the contained first-provision\nprocedure is exercised and the admitted attended rollout is carried through.\nVerifier-side scope, separate client-side/audit lanes and live acceptance remain\nas defined in the reviewed requests.\n\n2026-09-09 verifier-side return: both CCRs are verified after recorded user approval,\nCAS=0 version-1 custody, native read/auth denials and revocation, Valid stores,\nSecretSynced delivery, compatible KeyCape rollout and live positive/negative\nservice checks. Existing human OpenBao login passed again on the new image.\nReceipt: `docs/evidence/2026-09-09-keycape-verifier-admission.json`. Failed attempts restored the compatible\nconfiguration/image and detached delivery; final resume reused version 1.\n\nT05 is done against its verifier-only acceptance criteria. Its former\n\"remains progress for client-side reads\" statement expanded the task past its\nreviewed scope; that residual now has the live owner task RPF-WP-0035-T06 below.\nNeither Warden fetch selector is resolvable through these verifier-only CCRs.\nDo not re-request the completed two named reviews or reseed these paths.\nRotation is a distinct, version-guarded operation.\n\n## Dispose of the ungoverned whynot-design npm duplicate"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T07",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa",
|
|
"blocking_reason": "Founder HOLD (2026-09-21) on the legacy whynot-design npm pointer; custody disposition is an attended decision.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0dd7c9a5-65a0-53fc-b6c3-5ad96ee56f7b",
|
|
"body": "Found by the attended session on 2026-09-10 while settling the npm field\nquestion. `secret/coulomb/whynot-design/npm/publish` exists at version 1,\ncreated 2026-07-03T15:00:44Z and never updated \u2014 five days after the governed\nlane at `platform/workloads/coulomb/whynot-design/npm-publish` was verified\n(CCR-2026-0001, 2026-06-28). It sits outside that lane's exact-path policy and\noutside any CCR here. Receipt:\n`docs/evidence/2026-09-10-npm-lane-field-resolution.json`.\n\nOnly metadata was read. Its field names were not enumerated, its value was not\nread, and nothing was deleted \u2014 a location holding real credential material is\ndisposed of deliberately, not tidied away in the session that found it.\n\nThe likely explanation, unconfirmed: secrets-engine reports the lane's field\nunder a lowercase name that is absent from the governed path, and their catalog\ndeclares this legacy location. If their proven pilot publish read from here,\nthen a working production lane has been running off an ungoverned duplicate,\nand the governed lane's acceptance evidence describes a path the consumer does\nnot use. That is worth establishing before anything is removed.\n\n**Operator decision, 2026-09-15:** destroy the legacy path after confirming the\ngoverned lane is the live consumer. Do not wrap `secret/coulomb/whynot-design/npm/publish`\nin a CCR. Value remains unread. Platform will ask secrets-engine which path\npublish actually reads before any attended destroy.\n\n**Unblock:** admit the governed exact-path AppRole policy and coordinated catalog\npath/field migration under SECRETS-WP-0006-T06; prove native delivery from the\ngoverned lane before the attended legacy destroy. secrets-engine confirmed the\nlegacy source path on 2026-09-21 (message `355424d4-17ab-435e-9e1d-6921775cb4a2`).\nNo comparison of values, fingerprints, lengths or shapes is needed or authorized.\n\n**Done when:** the legacy path's provenance and consumer are established, the\ngoverned lane is confirmed as the one in use or the consumer is moved to it as a\nreviewed lane change, the duplicate is destroyed under the September 15 operator decision and the\ndisposition is recorded. Do not bring the legacy duplicate under a CCR. If the value proves to be live and\nungoverned, treat it as an exposure with the same custody rules as RPF-WP-0027:\nnever record the value, fingerprint, length or shape.\n\n2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Admit the separate approval client-side readers"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T06",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocking_reason": "INFD-WP-0001-T07/T08 terminal; remaining gate is human approval of the scoped delivery proof; front door stays non-resolvable.",
|
|
"priority": "high",
|
|
"intervention_note": "",
|
|
"state_hub_task_id": "68bff751-e48b-548b-8fb4-dfb3b16210c2",
|
|
"body": "**Current return, 2026-09-10:** CCR-2026-0020 is cancelled on the requesting\nApproval Engine owner's explicit withdrawal, source\n`849c75bb094613ff6ac1a1d4cda56a745520c5a1:docs/keycape-service-registrations.md`.\nNo presenter exists and no reader is wanted. The validator now accepts terminal\ncancellation of an incomplete request only with owner/source/reason evidence,\nretained declared omissions and a disabled, non-resolvable front door. Apply\nremains refused. No live identity, policy, role, custody or verifier was changed.\nHuman approval follows existing INFD-WP-0001-T07/T08; future service requesters\nneed a separate narrow registration, not this withdrawn bundle.\n\n**Operator binding confirmed, 2026-09-14:** The user explicitly selected\n`net-kingdom-admins` and authorized applying CCR-2026-0019. Its OIDC role is\n`secrets-engine-approval-client-workload-kv-read`, aligned with the platform\napplier naming rule; policy and exact KV scope are unchanged. The metadata dry\nrun passes with no warnings. Attended apply and exact role/policy readback passed; the enclosing Warden\ncommand exited successfully after its self-revocation/cleanup. Receipt:\n`docs/evidence/2026-09-14-ccr0019-operator-binding.json`. Scoped delivery proof\nremains pending; the front door stays non-resolvable. Completed CCR-2026-0017/0018\nremain closed and T06 stays `wait`.\n\nConsumer procedure returned in source, 2026-09-10:\n`secrets-engine@98d72ceb1dbcff2d2a80fb8c3058d76777a0ac93:docs/approval-service-auth.md`\nspecifies the requested private 0700 runtime directory, 0600 file outside Git,\npath-only use, claim/consume lifetime and attended cleanup including hard-stop\nresidual inspection. CCR-2026-0019 retains this source-review comment without\nchanging admission status. Exact group, required-owner review, attended apply and\nnative positive/negative/cleanup evidence remain. No role or credential changed.\n\nSeparate retained owner decision: KeyCape's 2026-09-10 return\n`21427688-725f-4dea-aab4-7c78fd4328d2` identifies the already-live, unpresented\nCCR-2026-0018 registration. Approval Engine, KeyCape and Platform must explicitly\ndecide retention/expiry or coordinated disablement. Reader cancellation neither\ndisables that live registration nor accepts indefinite retention. Keep this\ndisposition in T06; it is separate from the wanted CCR-2026-0019 factory reader.\nNo unilateral issuer/config/Secret change is authorized by this closeout.\n\n**Operator decision, 2026-09-15:** coordinated disablement with KeyCape and\nApproval Engine. Platform will not disable the live registration or verifier\ndelivery unilaterally. T06 stays `wait` until both owners confirm the joint\ndisablement sequence.\n\nResidual handoff from RPF-WP-0035-T05; consumes the completed verifier custody\nwithout extending CCR-2026-0017/0018. Owner: railiance-platform with the named\nsecrets-engine and approval-engine operator consumers.\n\nPrepare separate exact-reader admissions for existing version-1 paths:\n`platform/workloads/secrets-engine/approval-client` and\n`platform/workloads/approval-engine/operator-client`, field `CLIENT_SECRET`.\nName each actual actor/placement, bounded authentication/reader policy, protected\nconsumer delivery, cleanup/revocation and rollback, then obtain the required\nowner reviews for those concrete requests. No reseeding, rotation, shared reader,\nreuse of the sso verifier Secret, or implicit operator consume grant.\n\n2026-09-09 preparation return: both exact-reader admissions are prepared as\n`CCR-2026-0019` (secrets-engine) and `CCR-2026-0020` (approval-engine-operator),\nwith their exact-path read policies written and committed. Design:\n`docs/credential-lane-designs/keycape-approval-client-side-readers.md`. Both\nreuse existing version-1 custody; no reseed, rotation, shared reader or verifier\nSecret reuse. Both are `in_flight` and unapproved; nothing is applied.\n\nRead-only survey findings that decided the two shapes. Namespace\n`secrets-engine` holds only ServiceAccount `secrets-engine` with no workload,\nand `flex-auth/flex-auth-secrets-engine` is that consumer's PDP, not the\nservice; secrets-engine consumes the client secret through an operator-run CLI\nreading `SECRETS_ENGINE_APPROVAL_CLIENT_SECRET_FILE` (SECRETS-WP-0009-T03,\nrevision `9eb07fd`). So reader 1 is an attended operator-workstation OIDC lane,\nnot an ESO lane. approval-engine has no namespace, workload or Service; its\nmanifest is unapplied, and no owner source names who presents the operator\nclient \u2014 approval-engine verifies these tokens and never holds them.\n\n**Unblock:** reader 1 needs the exact NetKingdom/KeyCape group claim for the\nauthorized operator, plus secrets-engine confirming the file mode and removal\nstep; `openbao.auth` is declared missing rather than filled with a placeholder\nthat would later read as a confirmed binding. Reader 2 needs its owner to name\nthe presenting actor and placement, or to record that no client-side reader is\nwanted so the request is cancelled. Naming a reader for the widest approval\nscope without that decision is the failure this task exists to avoid.\n\n**Done when:** each reader has a named actor and placement, a completed and\nreviewed auth binding, admitted delivery, and its owner approvals; positive and\nnegative checks pass, including cross-path, wrong-identity and parent-list\ndenial and operator `consume` denial; or the request is explicitly cancelled by\nits owner. Rotation stays a distinct version-guarded operation shared with\nCCR-2026-0017/0018.\n\n\nConsumer input supplied 2026-09-09: secrets-engine now implements per-request\n`secrets-engine-approval` exchange from a protected temporary client-secret file,\nwith exact approval-engine / tenant:platform / read-or-consume scope, no token\nfile and no fallback. The pinned KeyCape image and actual Approval Engine source\npassed its disposable component exercise; only the PDP was a sequencing double.\nSee `secrets-engine/docs/approval-service-auth.md` and the metadata receipt\n`secrets-engine/docs/evidence/2026-09-09-approval-identity-exercise.json`.\n\nRouting check: `warden route show keycape-secrets-engine-approval-client` is\nunknown; generic `openbao-api-key` routes ownership only and is not a delegable\nlane. Do not advertise a working fetch command before this task supplies its\nown accepted native delivery return. Client-side admission is not ready for a\nnew human decision until exact requests and contained execution/rollback checks\nare reviewable; the completed verifier reviews must not recur in that queue.\n\n**Done when:** each retained consumer admission is approved and implemented, or\nits requesting owner explicitly cancels it (CCR-2026-0020 now satisfies that branch);\nactual consumer authentication/delivery succeeds; sibling/listing/wrong-reader\nand scope refusals plus reader expiry/revocation/cleanup are evidenced; version-1\ncustody and verifier availability remain intact. Return the source and metadata\nreceipts to HFACT-WP-0001-T03, SECRETS-WP-0009-T03 and APPROVAL-WP-0002-T01/T05.\nAudit receiver/sender custody remains AUDIT-WP-0009-T09 and must not be folded\ninto this client-identity grant.\n\n2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion.\n\n## Admit the two factory audit-sender custody lanes"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T08",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "ab85ae8a-12a0-4945-ae64-1d3d86d5b26f",
|
|
"blocking_reason": "Provisioned and delivered 2026-09-11 (CCR-2026-0021/0022 applied); do not repeat. Receiver rollout with evidence_kind and native producer acceptance passed 2026-09-11. Remaining human acceptance: independent archive readback and revocation of the interim audit bearer tokens.",
|
|
"priority": "high",
|
|
"assignee": "railiance-platform",
|
|
"intervention_note": null,
|
|
"state_hub_task_id": "0ef52c26-2669-5cd1-8149-b1f6fcdda6cb",
|
|
"body": "2026-10-03 correction (CUST-WP-0075, informed-decision sitting draft `55fb078`): the D1 routing was wrong. First provision and delivery already ran on 2026-09-11, with seed and delivery receipts, and the review packet says not to repeat them. The task is not a provisioning-window act. It was taken off decision D1, and its blocking_reason now names what actually remains. railiance-platform should re-qualify it further if the receiver rollout has since happened.\n\n2026-10-03 (CUST-WP-0075): re-qualified. The receiver rollout already happened: Audit Core c82e0442de0f carries evidence_kind and native producer accepted/duplicate and scope/read-refusal checks passed 2026-09-11 10:42 UTC (`docs/credential-lane-designs/factory-audit-senders-review.md`, `factory-native-acceptance.md`). Remaining: independent archive readback and audit bearer-revocation acceptance. Still not a provisioning-window act.\n\nConsume AUDIT-WP-0009-T09/T11's exact declarations for approval-engine and\ninformed-decision: tenant:platform, write-only, load-bearing, redact. Source\npreparation supplies two approved CCRs, independent exact-path policies/ESO\nprojections, and the attended `factory_audit_custody.py` first-provision helper.\nIts CAS and request-provenance checks preserve unrelated senders and recover\ninterrupted writes without generating replacements. The user approved all named review roles on 2026-09-11. Native\nprovision/delivery/receiver-ingestion acceptance remains open.\n\nThe 2026-09-11 native read-only check found an additional deployment dependency:\nreceiver image c2fe39a is 1/1 Ready but does not support evidence_kind. The\nsynthetic native probe now refuses before any credential read. Current receiver\nsource passes. AUDIT T09/T11 retain compatible release/source-manifest rollout;\nApproval Engine's missing namespace remains its owner prerequisite.\n\n[Review packet](../docs/credential-lane-designs/factory-audit-senders-review.md).\n[Preparation evidence](../docs/evidence/2026-09-11-factory-audit-custody.json).\nDo not fold these senders into CCR-2026-0019 or the cancelled CCR-2026-0020.\n\n2026-10-03: the historical D1 routing was withdrawn because provision/delivery already completed. Owner routing now uses decision `ab85ae8a-12a0-4945-ae64-1d3d86d5b26f`, specifically independent archive readback and coordinated interim audit bearer revocation acceptance. `needs_human` and the wait remain; resolving a decision requires owner receipt re-check, not automatic completion.\n\n## Dependency review \u2014 2026-09-06\n\n### 2026-09-09 tenant question resolved \u2014 no change needed\n\nThe `tenant:coulomb` / `tenant:platform` discrepancy raised against T02 is not a\ndiscrepancy. KeyCape confirms decision `5ed3fb35-eca9-413a-82b9-95171ba85bf6`\nbinds the *approval chain* to the landlord zone and was applied to exactly two\nregistrations, `secrets-engine-approval` and `approval-engine-operator`.\n`codex-railiance-platform` is not in that chain and correctly stays\n`tenant:coulomb`, as do `secrets-engine-openbao` and the human directory default.\nKEY-WP-0013-T04 records this and their\n`TestServiceRegistrationTenantsAreExactPerDecision` pins every reviewed client's\ntenant against the real fixture, so a reintroduced alias fails their build.\n\n`docs/credential-lane-designs/secrets-engine-service-jwt.md` already says\n`tenant:coulomb` and is therefore correct as written. Bind the exact role to\n`tenant:coulomb`. Do not \"correct\" it to `tenant:platform` later; that would\nbreak the issued claim.\n\nSECRETS-WP-0008-T02 now records the local PIP claim/validation join implemented\nand tested. Its remaining gate is the unreachable approval-engine claim endpoint\nand access-engine Check (SECRETS-WP-0007-T04). Do not carry forward the old local\nstub as a blocker. T02 still needs the accepted service issuer/JWKS, claims,\naudience and consumer binding. T03 still needs confirmed operator group/tenant\nand consumer semantics; T04 is already complete. No new owner acceptance inferred.\n\n\n### 2026-09-08 attended capability preflight\n\nHFACT-WP-0001's continued execution verified the existing first-provision\nfront door without provisioning anything. `warden plan` selected\n`openbao-platform-admin-login` / founder_required / one oidc_login. The native\n`scripts/openbao-attended-exec.py` supplied the existing WSL browser launcher;\na direct attempt had no launcher and failed before handoff. Its first revocation\nresult was unconfirmed and is preserved in the receipt rather than silently\nreclassified. The two subsequent contained sessions completed self-revocation\nand helper cleanup.\n\n`scripts/keycape-approval-custody-preflight.py --receipt <new-private-file>` is\na silent, read-only command for that envelope. The installed Bao CLI supports\none path per `token capabilities` call; the final run used six single-path calls.\nCreate/update authority is present on both exact policy paths, both Kubernetes\nauth-role paths and both KV data paths from CCR-2026-0017/0018. This is authority\nmetadata, not a secret-data read or policy/role/KV mutation. Receipt:\n`docs/evidence/2026-09-08-keycape-approval-custody-preflight.json`.\n\nT05 remains wait: both CCRs are still proposed, the actual upstream ID-token\nissuer precondition remains open, and no verifier-side credential is provisioned.\nClient-side retrieval and audit-sender custody are still separate owner returns.\nThe capability receipt is not a review approval or service readiness proof.\n\n### Sender approval recorded \u2014 2026-09-11\n\nThe user replied \"good, go on\" to the explicit CCR-2026-0021/0022 question naming\nplatform-operator, audit-core-owner and both producer owners. Both exact requests\nare approved; their existing State Hub decisions are resolved. This clears the\nreview request only. Receiver rollout, namespace readiness, attended custody and\npositive/negative native evidence remain the execution gates.\n\n### Native receiver and attended execution return \u2014 2026-09-11\n\nAudit Core c82e0442de0f is deployed and passes the native synthetic contract.\nIts existing 32-event chain/head is unchanged. The owner Approval Engine\nnamespace now exists and all four ESO objects pass strict server dry-run.\nThe two exact ingress rules are applied; sender custody/ESO application is not.\n\nWarden selected founder_required/oidc_login and attempted the reviewed silent\nseed command through the contained wrapper. Login failed before command\nhandoff; no custody receipt was created. Warden could not confirm remote\nsession revocation. Await operator browser/MFA feedback and login/session\nresolution. Approvals remain valid; T08 waits for the identity act, not review.\n\nThe receiver check now selects component=receiver, so retained attestation-job\npods cannot falsely block a stable receiver. Eighteen custody tests pass.\n[Native return](../docs/evidence/2026-09-11-factory-receiver-live.json).\n\n### Attended custody retry succeeded \u2014 2026-09-11\n\nThe user requested a retry and completed the attended identity act. Both CCRs\nare applied: independent version-1 custody and registry CAS 7\u21928 succeeded,\npreserving other senders/fields. Warden exited 0 with self-revocation confirmed\nfor this session. This does not retrospectively attest the earlier failed\nlogin's remote session state. The old login wait is cleared; T08 is progress\nfor ESO delivery, exact native reader/namespace refusals, receiver reload and\nproducer acceptance. No token is reseeded or rotated on continuation.\n[Seed receipt](../docs/evidence/2026-09-11-factory-audit-sender-seed.json).\n\n### Delivery prepared; fresh login did not hand off \u2014 2026-09-11\n\nThe delivery helper and custody receipt are committed at `44314ca` and exactly\nprojected on primary/railiance01. Seven delivery tests and 18 custody tests\n(including 11 actual disposable OpenBao cases) pass. The fresh attended\ndelivery invocation exited 5 before command handoff; no native delivery\nreceipt exists, no ESO application or receiver restart ran. The receiver\nremains 1/1 Ready on c82e0442de0f. Warden could not confirm revocation for this\nfailed login; that is separate from the successful seed session. T08 now waits\nfor this delivery identity act. Neither CCR review nor first provision reopens.\n\n[Delivery return](../docs/evidence/2026-09-11-factory-audit-delivery-login.json).\nUse the reviewed delivery command with a new receipt after login feedback.\nActual producer ingestion/duplicate/refusal and bearer revocation acceptance\nremain open under AUDIT-WP-0009-T09/T11.\n\n### Native delivery accepted \u2014 2026-09-11 08:27 UTC\n\nThe user returned and requested another login attempt. It succeeded and the\nreviewed delivery command completed in 28 seconds. Both native ESO readers\npassed exact-path access and explicit sibling/registry/metadata/listing denials,\nwrong-SA/namespace refusal and the coding-agent deny check. Each 900-second\nreader session was revoked and lookup refusal verified. Both intended\nExternalSecrets are Ready; exact producer value and ESO ownership match. The\ndisallowed namespace produced an explicit store restriction and no Secret;\nthe uniquely owned namespace is now absent.\n\nRegistry version 8 matches the delivered receiver JSON. Audit Core reloaded\nand remains 1/1 Ready on c82e0442de0f; /readyz reports operational/durable with\ntamper_evidence=false, as bounded by AUDIT-WP-0009-T12. Warden exited 0 and\nconfirmed self-revocation for this successful session. Earlier failed login\nreceipts remain historical and are not retroactively attested.\n\nThe login wait is cleared. T08 remains progress and CCR21/22 remain applied\nfor native producer ingestion/duplicate/scope/read-refusal and bearer\nrevocation acceptance under AUDIT T09/T11. No credentials were reseeded or\nrotated. No producer was deployed and no factory attempt or paid call ran.\n[Native delivery receipt](../docs/evidence/2026-09-11-factory-audit-delivery-live.json).\n\n### Native producer return \u2014 2026-09-11 10:42 UTC\n\nBoth actual source adapters used their own ESO-delivered credential inside a\nbounded native Job. Each synthetic event received 202, retained its durable\noutbox after an injected lost receipt, and received duplicate 200 after a fresh\nprocess reopened the outbox. Each source's reconciliation reported exactly one\nrecord for its unique probe class. Wrong source/tenant, seven archive read\nroutes, sibling reconciliation and invalid-bearer requests were refused.\n\nThe first Informed Decision probe exposed a private-store startup defect:\nfsGroup volumes add inherited setgid to a newly created 0700 directory.\nInformed Decision `1a12223` corrects creation without repairing unsafe existing\ndata. The regression failed before the fix; the available suite now passes\n335 tests with 39 optional checks skipped. Native retry verifies the exact\ncorrected helper. Six probe tests and eleven rebuilt-container checks pass,\nincluding actual setgid-volume startup, restart/restore and cleanup.\n\nAll temporary probe Jobs, Pods, ConfigMaps and NetworkPolicies are verified\nabsent. Receiver c82e0442 remains operational/durable; tamper_evidence=false.\nProducer verification requires no operator registry read or new OpenBao login.\nIndependent readback is a separate attended command consuming the successful\nreceipt; it must not rerun the producer jobs. Both attended verification-login\nattempts this session ended before handoff (exit 5; remote revocation\nunconfirmed), so independent archive readback remains pending.\n\nThis proves synthetic outbox delivery/recovery with native sender credentials,\nnot domain-transaction atomicity, deployed producer services or human binding.\nAn invalid bearer is not a revoked formerly valid bearer. AUDIT T09/T11 and\nRPF T08 remain progress for independent readback and audit bearer-revocation\nacceptance; CCR21/22 remain applied. Service/policy/human admission and native\nruntime/spend gates remain separate. Factory attempts and paid calls remain 0.\n\n[Native producer receipt](../docs/evidence/2026-09-11-factory-native-producers.json).\n\n\n## Independent audit readback \u2014 2026-09-11 13:11 UTC\n\nThe existing attended readback command completed with exit 0 while the user\nwas present. Independent read-only identity `operator` found both retained\n`factory-audit-20260911104152-94aced` producer events with exact source and\n`tenant:platform`; receiver integrity is intact across 36 events. The wrapper\nconfirmed this session's self-revocation and private-helper cleanup. Prior\nfailed sessions' unconfirmed revocation remains historical unresolved evidence.\n\nThis supersedes the earlier readback-login wait. No producer jobs were rerun,\nno credentials were reseeded and no event was written by the reader. The\ninherited zero registry-read count belongs to the producer phase; the attended\nreader did consume registry version 8. CCR21/22 stay applied and owner tasks\nstay progress pending formerly-valid audit-bearer revocation acceptance.\nService/domain-transaction/human and factory runtime/spend admission remain\nseparate; factory attempts and paid model calls remain zero.\n\nReceipt: [native readback](../docs/evidence/2026-09-11-factory-native-readback.json).\n\n\n### T06 native reader acceptance \u2014 2026-09-14\n\nThe scoped Warden login lane `secrets-engine-approval-client-login` now routes\nto the applied OIDC reader and the platform's silent preflight. The installed\nWarden package still carries an older catalog; use the explicit source catalog\n`WARDEN_ROUTING_CATALOG=/home/worsch/ops-warden/registry/routing/catalog.yaml`\nuntil its next normal installation refresh. This lane authenticates the reader;\nit is not a raw secret fetch or retained-file delivery interface.\n\nLive effective-policy and capability checks passed: only exact data/metadata\nread, no sibling secret, parent listing, write or control-plane authority.\nA second contained session read existing version 1 into an operator-owned 0600\nfile in a private 0700 runtime tmpfs directory. The native consumer exchanged\nseparate read and consume scopes; Approval Engine verified the read token before\nreturning 404 for a fresh nonexistent approval, and refused the consume-only\ntoken's read request with 403. No approval was created, bound or consumed.\nBoth Warden sessions exited 0 after self-revocation/helper cleanup; temporary\ncredential file and directory were removed. Four refusal/path/redirect tests\npass. Receipts are in platform `docs/evidence/2026-09-14-ccr0019-{reader-preflight,delivery-check}.json`.\n\nRemaining: an actual nonmember login refusal, real approval claim/consume,\nseparate narrow requester admission and deployed Informed Decision review with\nan explicitly admitted human mandate. The reader group alone grants no review\nmandate. T03 and CCR delivery activation remain open; no OpenRouter key was read.\n\n\n### T03 scoped review deployment \u2014 2026-09-14\n\nThe operator explicitly admitted `net-kingdom-admins` as the human review group\nfor only the T03 apply, verify and read-only key-check records, separately from\nits credential-reader membership. The review service is live and ready at\nhttps://decisions.coulomb.social with verified KeyCape groups, fresh MFA and a\ndedicated caller-bound Flex Auth policy. Its mandate does not grant consumption.\n\nThe new `secrets-engine-requester` client has subject `secrets-engine`, tenant\n`tenant:platform`, role `secrets-engine-requester`, and only `approval:create`.\nCCR-2026-0024 and CCR-2026-0025 provide distinct verifier and attended reader\ncustody. Native signature, subject, scope and TTL checks passed; excess scopes\nand a wrong secret were refused. Existing consumer identity is unchanged.\nThree real requested approvals were created with human control, required count\none, and zero entries. Platform evidence is\n`docs/evidence/2026-09-14-t03-native-approval-requests.json`.\n\nReview image: sha256:8f55bcecf37a8d65f96e073510b1ffb4636c0a91d75e1ee7d582ad4bce8b953a.\nPolicy image: sha256:c9f028b49dfcede930a9cc48757ec8371ecc71d20b1bfee2733e55298dffcc7c.\nReview tests: 339 passed, 39 optional integration tests skipped; 11 container\nchecks and HIGH/CRITICAL image scan passed. Policy checks: 57 local and 6 native\ncaller checks passed, using synthetic subjects, not human binding evidence.\nApproval Engine CPU request was reduced from 25m to 10m after observing 1m use;\nreview requests 20m and its PDP 5m. Limits are unchanged. Native services ready.\n\nRemaining T03 gate: the operator's exact signed-in account is needed to address\nthree prepared immutable memos, followed by real acknowledgements and acceptance\nin Informed Decision. No human entry or consume has been generated by an agent.\nThen execute claim -> validated PDP Check -> CAS consume separately for apply,\nverify and exec using scoped attended authority, and capture native denial,\nrevocation, workload health and key-check evidence. No OpenRouter credential has\nbeen read and no inference or spend was performed. T03 remains waiting; this\nentry supersedes earlier statements that requester or group admission is missing.\n\n### 2026-09-27 T02/T07 source follow-up\n\nT02 now has the exact proposed RS256 configuration, bounded JWT role and\nself-only policy in `openbao/`. Operator correction: platform infrastructure\nbelongs to `tenant:platform`; KeyCape registration and consumer preflight are\ncorrected together. Existing live registrations must be migrated and verified.\nPublic discovery confirms issuer/JWKS/token endpoint. Registration/custody,\nattended provisioning and live rejection/cleanup evidence remain required;\nT02 stays wait. No service credential or backend entitlement was issued.\n\nT07 consumed the confirmed legacy consumer return. The stale value-comparison\nask is removed. WARDEN-WP-0037-T03's no-rotation hold stays in force until the\ngoverned native migration is evidenced. Legacy destruction follows migration;\nneither source reconciliation nor the historical pilot is that evidence.\n\n## Loose-end review \u2014 2026-09-27\n\nT08 now explicitly waits for formerly-valid audit-bearer revocation acceptance from AUDIT-WP-0009-T09/T11. Native delivery, producer checks and independent readback already passed; do not reopen login, seed or review gates. T02/T03/T06/T07 retain their latest exact service registration, signed-in human acceptance, owner delivery/disposition and governed-consumer migration dependencies. No credential value was read or changed.\n\n## Founder approval of the CCR-2026-0033 custody child"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T09",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"priority": "high",
|
|
"decision_id": "2ab717e1-7881-491e-aed4-28946550c289",
|
|
"depends_on": [],
|
|
"blocking_reason": "Waits for founder approvals: A1 ops-mason design (keycape-secrets-engine-openbao-client-custody, MASON-WP-0009); A2 revised CCR-2026-0033 plus sibling operator reader CCR-2026-0034 (platform-owner, key-cape-owner, net-kingdom-owner reviews; bound claims confirmed for both readers incl. groups=net-kingdom-admins and /assurance/level=aal2); A3 the exact custody-child decision id recorded in the CCR-2026-0033 review (not boundary decision 632a8893). secrets-engine D1-D4 are superseded (no consumer copy).",
|
|
"state_hub_task_id": "7c753be6-42f1-58a6-a4a4-a7ed686f461f",
|
|
"body": "Packets: `credential-change-requests/CCR-2026-0033.yaml` (custody child, KV\nmetadata, issuer ESO reader, live_order, rollback) and `CCR-2026-0034.yaml`\n(attended operator OIDC reader, in-memory, 5m/4 uses). Revised 2026-10-06 per\nfounder direction; the consumer file is removed. Exact founder commands:\n`docs/provisioning-windows/2026-10-04-1000/keycape/founder-runbook.md`. Live\norder: custody child \u2192 platform applies policies/roles/ESO (Secret\nsso/keycape-secrets-engine-openbao-client exists) \u2192 NetKingdom env patch\n(NK-WP-0046) \u2192 KeyCape registration merge (KEY-WP-0037-T03) \u2192 KeyCape restart\nimmediately \u2192 live issuance check (KEY-WP-0037-T04) \u2192 OpenBao JWT role/login\nproof (RPF-WP-0035-T02). Each live step after the custody run needs its own go.\n\n\n## Retire the approval-engine-operator client delivery and custody (CCR-2026-0018)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0035-T10",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"priority": "medium",
|
|
"state_hub_task_id": "af2d4dba-f83a-5819-9a8b-671bae799364",
|
|
"body": "key-cape proposed a joint disablement on 2026-10-10 (message `7f2128fb`).\nPrecondition: approval-engine reconfirms there is no presenter. The order is the\nreverse of provisioning, so KeyCape never starts with a client whose secret is\nmissing. key-cape removes the registration and restarts (1), checks that\n`invalid_client` is returned (2), and net-kingdom removes\n`KEYCAPE_APPROVAL_ENGINE_OPERATOR_CLIENT_SECRET` from Deployment `sso/keycape`\n(3). Platform steps, amended from the proposal:\n\n4. **Delivery.** In one commit, remove ExternalSecret\n `sso/keycape-approval-engine-operator-client` from\n `argocd/platform-addons/openbao-secretstore/keycape-approval-clients.externalsecrets.yaml`\n and ClusterSecretStore `openbao-keycape-approval-engine-operator` from\n `openbao-keycape-approval-clients.clustersecretstore.yaml`. Keep the\n secrets-engine-approval objects. Then bump `targetRevision` of\n `argocd/railiance01/applications/openbao-secretstore.application.yaml`.\n The app is pinned and has no automated sync, so nothing changes live until\n an attended `argocd app sync openbao-secretstore --prune` runs after step 3.\n Verify, value-free, that the ExternalSecret, the store and Secret\n `sso/keycape-approval-engine-operator-client` are gone. The target is\n `creationPolicy: Owner` and `deletionPolicy: Retain`, so the Secret should\n follow its owner; delete it explicitly if it does not. Then delete OpenBao\n role `auth/kubernetes/role/external-secrets-keycape-approval-engine-operator`\n and policy `workload-kv-read-keycape-approval-engine-operator`, and remove\n their source files. Also remove policy\n `workload-kv-read-approval-engine-operator-client` (CCR-2026-0020, cancelled)\n if it exists live.\n5. **Custody.** Run the metadata delete of\n `platform/workloads/approval-engine/operator-client`, the destruction\n foreseen in `docs/credential-lane-designs/keycape-approval-clients.md`. A\n disabled client's secret has no recovery value; a narrowed successor gets a\n fresh secret through the mint-secret lane at `platform/workloads/keycape/<client_id>`.\n Only after step 2's `invalid_client` receipt. Keep the agent boundary denies\n for that path until the delete is verified, then drop them.\n\n2026-10-10: key-cape agreed the amended steps 4 and 5 (message `59304e33`,\nKEY-WP-0013 c528daa). Waits on approval-engine confirming there is no presenter,\nand on the founder's window.\n\nThe manifest edits wait for the scheduled window, so a stray `targetRevision`\nbump cannot remove KeyCape's secret before step 3."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0036-platform-service-assurance.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0036",
|
|
"type": "workplan",
|
|
"title": "Close S3 service assurance and ownership gaps",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"created": "2026-09-05",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "ca639c3d-3a87-5fa4-ad13-6f2e014b0c84"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0036-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "9c6d0439-8a14-5921-9d88-95a10b303057",
|
|
"body": "Completed 2026-09-05. Assessed all 37 existing plans and their 168 task records,\ncorrected SCOPE, grouped the remaining obligations, consolidated the three\ndesign follow-ups under RPF-WP-0035, archived completed plans with identities\npreserved, and recorded owner handoffs and before/after inventory in history.\nThis certifies the source review, not live service health or external acceptance.\n\n## Publish achievable service guarantees and recovery ownership"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0036-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "eebcd5c7-4cfd-5084-9a21-ca1e4e748bdd",
|
|
"body": "For apps-pg, platform-pg, OpenBao and each supported backup delivery lane,\npublish a versioned service record: accountable S3/package/operator owners,\nconsumers, failure domain, availability objective, RPO/RTO, retention, recovery\nkey/quorum availability, maintenance/abort path and evidence freshness budget.\nSeparate measured results from accepted targets and unknowns. A 56-second\nscratch restore is not an RTO commitment; one replica on one host is not HA.\nReuse `docs/s3-consumer-interfaces.md` and existing package declarations.\n\n**Done when:** every supported service has owner-reviewed numeric targets or\nan explicit unsupported guarantee and decision owner; consumer requirements\nare compared to the current substrate; any HA/node-loss gap has an exact S1/S2\nand package dependency rather than a blanket new-cluster project here.\n\n## Make backup freshness and recurring recovery evidence checkable"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0036-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"depends_on": [
|
|
"ACTIVITY-WP-0042"
|
|
],
|
|
"blocking_reason": "activity-core replied (not accepted yet): role acceptance is the founder decision ACTIVITY-WP-0042-T01 (D2); then ACTIVITY-WP-0042 bounded operation, S3 OpenBao credential route, repaired openbao-activity-core store and per-run approval-engine approval.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "d64446fb-870b-5ae9-9628-f1fb9d06c5a4",
|
|
"body": "Inventory authoritative CNPG backup/PITR, OpenBao snapshot/isolated restore,\nencrypted off-host copy and custody-recovery receipts. Reuse existing validators\nand package status commands. Define cadence/expiry from T02; return distinct\nhealthy, stale, missing and unavailable states using metadata only. Schedule\nexecution only through the accepted execution owner and separately approved\nauthority. Keep RPF-WP-0015's pending database/reboot experiments as the sole\nlive tasks for those experiments; RPF-WP-0029 retains provider-key recovery.\n\n**Done when:** a current off-host backup and a current isolated restore receipt\nexist for each supported data service, the approved cadence is installed and\nits execution is evidenced, and missing/stale/failed evidence reaches a named\noperator. A template, dated successful snapshot, or same-PVC reboot does not\npass as restore proof. Record independent recovery-key access without values.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): activity-core replied (message 3b1bc698)\nthat the scheduling role is NOT accepted yet. It already runs\n`daily-cnpg-option-a-backup` (Nextcloud lane, three clusters, no restores), and a\nplatform run needs a new ACT-ADR-007-successor bounded operation, an S3-owned\nOpenBao credential route (the `openbao-activity-core` store has failed since\n2026-09-19), per-run approval-engine authority, and an S3-owned fixed restore\ntool. activity-core recorded the proposal as ACTIVITY-WP-0042, whose T01 is a\nfounder decision routed to hub decision 89f1058f (D2). railiance-platform's\n\"roles tie to the source repo\" note of 2026-10-02 does not resolve that founder\ngate. Changed: `blocked_on: message-from:activity-core` replaced by\n`needs_human` + `decision_id` D2 and `depends_on: [ACTIVITY-WP-0042]`;\nactivity-core stays the proposed owner. RPF-WP-0038-T04 was not changed here.\n\n## Produce S3 signals and prove their delivery to the evidence owner"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0036-T04",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"RTEL-WP-0002"
|
|
],
|
|
"blocked_on": "message-from:railiance-telemetry",
|
|
"blocking_reason": "Needs a concrete receiving contract from railiance-telemetry (RTEL-WP-0002) before health transport is accepted; unmonitored state retained meanwhile.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5351e0e4-6263-58f0-afb2-7c78c4cd6f68",
|
|
"body": "Define service-owned health semantics for backup/WAL age, restore age, seal\nstate, ESO freshness, connection/memory headroom and consumer ceiling. Reuse\npackage emitters and the Q2 owner's standard contract; retain an explicit\nunmonitored state and named manual checker until transport is accepted.\nRequest a concrete receiving contract from railiance-telemetry when routing is\nauthorized; do not implement a competing monitoring plane in S3.\n\n**Done when:** bounded metadata-only samples pass contract validation, a\ncontrolled stale/failure sample reaches a named recipient through the accepted\nQ2 route, and missing emission itself is detectable. Local fixture tests may\nfinish before the receiver, but end-to-end acceptance cannot.\n\n## Reconcile admission, placement and consumer interface drift"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0036-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5cded2e9-7edd-57bd-9f7e-7977b75004dc",
|
|
"body": "Join actual package declarations and authorized metadata to the S3 interface,\ntenancy and placement records. Correct stale platform-pg occupancy/co-residency\n(Core Hub admission versus older tenant-engine descriptions), distinguish\ndesired placement from observed placement, and verify the named overflow\ntargets remain provisionable. Add a bounded check for missing owners,\nunsupported retention requests, quota/ceiling drift and stale evidence; consume\npackage admission checks instead of reimplementing them.\n\n**Done when:** every admitted consumer has one authoritative placement/contract,\ncapacity and retention disclosures match package source and dated live proof,\nand synthetic invalid admissions fail before provisioning. No workload moves\nunder this task without its own owner-reviewed migration.\n\n## Obtain acceptance for compatibility assets and derived-record cleanup"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0036-T06",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:railiance-forge",
|
|
"blocking_reason": "Owner-ready handoffs to railiance-forge, rapp-openbao and the ArgoCD bootstrap owner await acceptance; S3 custody contracts stay here until then.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "3b74f79c-7366-5d00-bf0e-31c0464a8f33",
|
|
"body": "Prepare exact source/entry-point inventories and owner-ready handoffs for\nForgejo backup/pruning/image inventory (`railiance-forge`, activity-core\nexecution), retained OpenBao package wrappers (`rapp-openbao`), and ArgoCD\nbootstrap/application manifests (S2/S4/S5 according to artifact). Keep S3\ncustody contracts and the RPF-WP-0029 exposure obligation here until accepted\nclosure. No new framework or app-specific helper belongs here by default.\n\nSupply repo-manager/State Hub with the exact legacy alias/source identity map\nfrom the assessment. Their apparent duplicate active records and stale brief\nare derived-state defects, not additional workplans. Use scoped reconciliation;\nnever change managed UUIDs or blanket-acknowledge retirements to clean a view.\n\n**Done when:** each retained compatibility surface has an accepting owner,\ncanonical replacement and tested callers or a dated retention decision; the\nrepo-filtered projection and generated brief agree with source identities.\nUnaccepted transfer remains explicitly pending. No requests were sent during\nthe assessment and this task does not assert acceptance for another repo.\n\n## Decide demand and reuse for undeployed stateful capabilities"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0036-T07",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "b32709d2-581d-5750-a04c-e3494a42d27e",
|
|
"body": "Review cache, general object storage and messaging separately with potential\nconsumers. Inventory existing providers/contracts (including artifact-store\nand the external backup bucket) before selecting an engine. Record workload,\ndurability/latency/retention needs, capacity, tenancy, custody, package owner,\nrecovery cost and operating owner for any accepted demand. Ask railiance-master\nto resolve fleet Q3 ownership through its architecture process; do not assign\nit to S3 by implication.\n\n**Done when:** each capability has a dated decision to reuse, defer with a\nreview trigger, or start a bounded consumer-backed delivery plan with explicit\nacceptance criteria. \u201cNo accepted demand; keep deploy gated\u201d is a valid result.\nNo Valkey, MinIO, RabbitMQ or new provider purchase is authorized by this plan.\n\n## Implementation and remaining acceptance \u2014 2026-09-05\n\nT02 completed with `assurance/service-records.json` and ADR-0004: all three\nCNPG cells, OpenBao and both backup delivery surfaces disclose unsupported\navailability/RPO/RTO guarantees, existing evidence, retention and named decision\nowners. Numeric commitments have not been invented or approved for other owners.\n\nT05 completed with the owner-native admission checker, hash-bound baseline and\nplacement registry. It reuses local/package validators and rejects unowned\nconsumers, fifth consumers, unhonoured retention and source disclosure drift.\nCorrected tenant-engine's completed PostgreSQL cutover and the deployed SBOM\noverflow cell. Live metadata matches one instance, 1Gi limit, 100 connections\nand 30-day retention on all three deployed cells. Dated owner evidence remains\nthe authority for database/application cutover; this run moved no workloads.\n\nT07 completed with ADR-0005: reuse approved backup storage only for backup;\nevaluate artifact-store's existing S3 interface for artifact demand; defer\ncache, general object store and broker deployment with concrete demand/review\ntriggers. The fleet Q3 question is retained in T06's prepared master handoff;\nno external architecture assignment or provisioning occurred.\n\nT03/T04 have working read-only `assurance-capture`, `assurance-check` and\n`assurance-admission` entry points plus adversarial tests. The collector pins\nthe cluster UID and reads selected status, native aggregate connection counts,\nmetrics and unauthenticated seal status. It captures no Secrets, SQL text from\nsessions, application rows or logs. Healthy/stale/missing/unavailable/failed\nare distinct; unknown fields, future timestamps and wrong clusters fail closed.\nThe output explicitly says unmonitored and unsupported guarantees.\n\n- **T03 waits:** fresh owner-validated isolated restore/snapshot/offsite receipts,\n independent recovery access, approved cadence and execution evidence. Existing\n live experiments stay in RPF-WP-0015; offsite exposure stays in RPF-WP-0029.\n No restore, snapshot creation, upload, scheduler or seal/unseal was run.\n- **T04 waits:** accepted Q2 receiving contract and controlled failure/absence\n delivery to a named recipient. The local producer is not a ratified Q2\n contract. Live metadata also surfaced failed ESO resources: forgejo-mailer,\n reuse-surface-runtime and target-revenue-runtime. Their current/obsolete scope\n and exact repair require consumer/platform acceptance before lane mutation;\n failures remain visible rather than excluded.\n- **T06 waits:** ownership acceptance and scoped alias/brief repair. The exact\n path/hash/caller inventory, dated retention decision through 2026-10-05 and\n prepared owner requests are in `assurance/ownership-handoffs.json` and\n `docs/platform-ownership-handoffs.md`. The installed brief generator still\n includes open legacy aliases; rerunning it alone cannot satisfy acceptance.\n No messages or external handoff acceptance were fabricated.\n\nEvidence: `docs/evidence/RPF-WP-0036-assurance-2026-09-05.json`.\nThe plan is blocked on these explicit live/owner gates, not finished merely\nbecause its repository implementation and tests pass.\n\n\n2026-09-05 ESO recovery follow-up: RPF-WP-0037 resolved all three delivery\nfailures using exact Kubernetes authentication. Custody values were unchanged,\nnegative checks and repeated refresh passed, obsolete invalid delivery tokens\nwere removed, and all 27 ExternalSecrets now report Ready. The earlier dated\nassurance snapshot is retained as historical evidence. T04 still waits on the\naccepted Q2 receiver and controlled failure/absence transport proof.\n\n## Blocker closure review \u2014 2026-09-05\n\nFresh metadata capture verified all 15 collected signals healthy; seven recovery\nsignals remain absent from the evaluator. RPF-WP-0037 is archived. The completed\nBackup account fixture proof remains separate from a full backup/restore receipt.\nT03/T04 remain waiting on recovery evidence/cadence and Q2 delivery respectively.\nT06's source inventory hashes were refreshed; its dated retention decision is\nunchanged. A repo-filtered Hub read confirms three retired aliases still appear\nopen. The installed generator would reproduce them; exact UUID mapping and\nremaining owner requirements are persisted in\n`history/2026-09-05-blocked-workplan-closure-review.md`. No duplicate recovery,\nmonitoring or owner-transfer workplan was created.\n\n## Primary backup coverage \u2014 2026-09-06\n\nScaleway is the selected primary; Nextcloud is the independent secondary.\nFresh apps-pg recovery from Scaleway passed in 42.64 seconds with expected\nconsumer databases and limits, production Ready and scratch cleanup complete.\nEvidence: `docs/evidence/scaleway-primary-restore-2026-09-06.json`.\nT03 now has this fresh physical recovery receipt; recurring assurance cadence\nand the remaining recovery surfaces are still incomplete.\n\nThe source/live coverage inventory `docs/backup-provider-coverage.md` exposes\nremaining native primary configuration gaps on net-kingdom-pg/state-hub-db.\nForgejo native database recovery and full Scaleway archive recovery have since\npassed; independent Nextcloud essentials recovery also passed (WP-0038). Track primary coverage\nhere with forge/package/storage owners; do not silently claim the Nextcloud\naccount cutover filled it or weaken WP-0029's separate incident closure.\n\n## Recovery evidence adapter follow-up \u2014 2026-09-06\n\nT03 advanced: capture now consumes hash-pinned apps-pg and forgejo-db native\nScaleway restore receipts through `scripts/recovery_evidence.py`. Completion\ntimestamps survive every capture; wrong destination, drift, missing/naive/future\ntimes and unsuccessful cleanup cannot become passing samples. Forgejo database\nrestore is its own signal. Older application archive receipts lack completion\ntimestamps and remain outside the automatic adapter; essentials evidence never\nsubstitutes for full recovery. Six previous recovery signals still lack adapters\nor accepted evidence. Cadence, independent custody and Q2 transport gates remain.\n\nThe Forgejo service record now reflects the completed native/full/essentials\nproofs while retaining unsupported guarantees and the pending scheduled cutover.\n\nLive adapter verification: `docs/evidence/RPF-WP-0036-assurance-2026-09-06.json`\nreports 16 healthy, six missing and one stale ESO refresh signal. The aggregate\ncrossed the one-hour diagnostic boundary; subsequent metadata inspection found\nall 27 ExternalSecrets Ready with newer refreshes. Cadence/grace acceptance is\nstill needed; no outage or successful alert transport is inferred.\n\n## Archive receipt producer repair \u2014 2026-09-06\n\nT03 progressed further: primary/secondary transfer, primary decryption and\nisolated restore now emit their own start/finish timestamps, including failures.\nDecryption preserves its schema instead of inheriting the transfer's. Restore\nchecks receipt schema and decryption proof, hashes the exact input receipt and\nmarks failed cleanup as failed recovery. This closes the producer timestamp gap\nfor future runs; old evidence remains unchanged. Native adapters remain the only\nautomatic recovery adapters pending reviewed fresh archive receipts and adapter\nimplementation. Validation and residual gates are recorded in\n`history/2026-09-06-archive-receipt-review.md`; T03 remains waiting on its wider\ncadence/custody/acceptance gates.\n\n## Closure review \u2014 2026-09-06\n\nUser requested completion. Source review still finds T03/T04/T06 acceptance\nunmet; see `history/2026-09-06-WP-0036-closure-gates.md`. Telemetry's checkout has\nno receiver implementation, and the older platform-pg scratch MinIO drill does\nnot establish production off-host recovery. Added the verified August 22\nOpenBao snapshot to the hash-pinned evidence adapter: it reports stale using\nits original creation time, separately from the still-missing isolated restore.\nNo criteria were weakened, external acceptance inferred or live window reused.\n\n## Q2 owner implementation \u2014 2026-09-06\n\nThe user directed implementation in railiance-telemetry. RTEL-WP-0002 now owns\nits metadata contract, durable private reference receiver, platform report\nadapter and missing-emission semantics. Nine tests and a separate-process local\nCLI failure/absence proof pass. See telemetry `docs/signal-contract.md` and\n`history/2026-09-06-local-receiver-proof.json`. T04's next dependency is explicitly\nRTEL-WP-0002-T04: accepted package/runtime, authenticated execution, actual\noperator recipient, cadence/storage/retention and independent receiver watchdog,\nthen acknowledged controlled delivery. Local test-inbox visibility is not that\nlive receipt; S3 remains unmonitored until acceptance.\n\n## Loose-end review \u2014 2026-09-27\n\nCompleted the local full-primary archive assurance adapter under T03. It validates ordered transfer/decryption/restore receipts, exact provenance hashes, full profile, version-pinned verified download and application/database/repository/package/cleanup proof; historical undated receipts remain ineligible. Updated producer profile propagation and assurance documentation. Fresh live metadata reports 18 healthy signals, five missing recovery/upload signals and one stale OpenBao snapshot; transport remains unmonitored. T03/T04/T06 remain waiting on current recovery/cadence/custody proof, Q2 production delivery acceptance and owner/derived-record acceptance respectively. RTEL-WP-0002-T04 already selects rapp-telemetry; the stale claim that no receiver implementation/package exists is superseded. See `history/2026-09-27-loose-end-review.md`."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0038-forgejo-scaleway-primary-coverage.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0038",
|
|
"type": "workplan",
|
|
"title": "Close Forgejo primary backup coverage on Scaleway",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"created": "2026-09-06",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "7beec1a7-aa82-5a36-9a66-6b60008a2455"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0038-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4f5e594a-e731-5298-8ba4-5b1e0cd9e71d",
|
|
"body": "This repository owns helm/forgejo-db-cluster.yaml and its deploy target.\nReuse CCR-2026-0012's backup runtime identity and existing databases Secret.\nThe reviewed bucket policy permits platform-pg/*; choose the separate native\nBarman destination platform-pg/forgejo-db/. No bootstrap key, IAM mutation or\nnamespace expansion is required. Never write full archives into a Barman\nserver directory. Retention follows the existing 30-day primary contract.\n\n## Activate native database backup and prove fresh completion"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0038-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "b6960c2e-1ad3-5c23-bfb6-9f1f16d0f0c2",
|
|
"body": "Add exact Scaleway destination, HTTPS/DNS egress, continuous WAL and daily\nbase backup. Apply only the reviewed backup field with a resource-version\nguard, preserving unrelated live settings. Require a completed fresh Backup,\ncontinuous archiving and source readiness; record metadata only.\n\nCompleted: fresh backup `forgejo-db-daily-20260905225013`, backup ID\n`20260905T225115`, source Ready and continuous archiving healthy. Evidence:\n`docs/evidence/forgejo-scaleway-activation-2026-09-06.json`.\n\n## Prove isolated primary database recovery"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0038-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "b47b5905-83c8-5da8-9951-e8cb7b7459f9",
|
|
"body": "Recover a new scratch cluster from the native Scaleway base backup/WAL.\nVerify expected Forgejo database and nonempty repository/user/package metadata,\nsource readiness and scratch cleanup. This is database recovery, not combined\nForgejo blob/application recovery.\n\nCompleted: restored in 45.08 seconds, 142 repository records, six users and\n2,040 package blob records. Production remained Ready; scratch namespace\nremoved. Evidence: `docs/evidence/forgejo-scaleway-restore-2026-09-06.json`.\n\n## Establish primary full-archive delivery and application recovery"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0038-T04",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocking_reason": "Operator chooses the independent archive prefix and confirms retention/caller contract and bounded worker credential delivery before the primary archive retrieval.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "a4807df0-ec96-58f1-9cbd-42b1dcde0d6f",
|
|
"body": "Choose an independent archive prefix and confirm storage retention/caller\ncontract, bounded worker credential delivery and multipart transfer/abort.\nThen retrieve a primary full archive and execute isolated application recovery.\nThe existing 5.35 GB encrypted verified archive is available in private staging.\nKeep Nextcloud's 10 GiB secondary budget separate. The current helper still\nuploads only to Nextcloud until this task's full delivery is implemented and\nverified; native database backup alone cannot close the workplan.\n\nSecondary capacity observation (not a native-primary acceptance gate): after\nthe successful full recovery and rejected-fixture DELETE, immediate Nextcloud\nmetadata still reported 5,234,716,518 free bytes, below one current archive's\n5,353,024,293 bytes. Recheck quota and settle bounded archive retention/capacity\nwith the owning package; do not automatically delete retained good backups.\n\nUser-directed storage split assessment: `docs/backup-storage-tiers.md` and\n`history/2026-09-06-backup-capacity-and-essentials-assessment.md`. Keep full\narchives on Scaleway and design a measured essentials-only Nextcloud profile.\nT04 acceptance includes package/bootstrap audit, primary-independent essentials\nrecovery, quota preflight and separate bounded retention execution before\nchanging scheduled secondary scope. No blanket package exclusion is activated.\n\nImplementation evidence, September 6: full Scaleway multipart transfer, versioned\nGET, decryption and isolated application recovery passed (all 2,040 package\nblobs). Essentials capture is 273 MiB; real Nextcloud round trip and isolated\nsource/collaboration recovery passed with package service disabled. Retention\nplanner and separate attended owner executor are implemented and tested; no\nlive expiration or cron cutover performed. T04 remains in progress for durable\nscheduled caller/dependency binding, canonical verified inventory, fresh quota\nchecks and owner retention activation. See\n`history/2026-09-06-backup-tiers-implementation.md`.\n\nReceipt follow-up, September 6: new archive transfer/decryption/restore runs now\nrecord operation timestamps and provenance receipt hashes. Cleanup failure cannot\nleave a successful restore status. Historical primary decryption receipts remain\naccepted explicitly, while new decryption retains its own schema. No repeat\nupload, expiry or scheduled caller change was made; T04 remains in progress for\nthe existing durable caller, inventory, quota and retention gates.\n\n**Operator decision, 2026-09-15:** do not expire retained backups or cut over\nscheduled secondary delivery. The planner and attended executor stay idle until\ndurable caller/inventory/quota gates are closed.\n\n2026-10-03: human gate routed to hub decision 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1: Attended OpenBao provisioning window: one session clears the pending credential lanes) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Loose-end review \u2014 2026-09-27\n\nT04 now explicitly waits. Primary and essentials manual recovery are already proven. Durable scheduled caller/dependency binding, canonical verified inventory, quota/retention gates and owner activation are still absent. September 15 prohibits expiration and scheduled secondary cutover until those gates close; no retained backups or schedules were changed. New primary transfer receipts preserve archive_profile for the assurance adapter in WP-0036-T03."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0043-policy-nexus-argocd-onboarding.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0043",
|
|
"type": "workplan",
|
|
"title": "Onboard rapp-policy-nexus to the ArgoCD production lane",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "railiance-platform",
|
|
"topic_slug": "railiance",
|
|
"created": "2026-09-21",
|
|
"updated": "2026-10-05",
|
|
"due": "2026-12-21",
|
|
"related": [
|
|
"RPF-WP-0022"
|
|
],
|
|
"state_hub_workstream_id": "ec41a4bd-df18-5b07-9b63-ccb80d9f001c"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0043-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "d6a7a480-6251-504a-aa5f-ab9c04fe1e79",
|
|
"body": "This repository cannot confirm it; see `docs/argocd-gitops.md` \u00a7 Production\nChange Path. The only record of ArgoCD's health is from 2026-06 and predates\nthe correction of the railiance01/coulombcore naming. Later records call the\ncontroller \"coulombcore ArgoCD\", and all Applications target\n`kubernetes.default.svc`.\n\nAttended, read-only, against a kubeconfig whose server is verified to be\n92.205.62.239:\n\n1. `kubectl get nodes -o wide`: confirm the node IP.\n2. `kubectl -n argocd get deploy,sts` and `make argocd-status`.\n3. `kubectl -n argocd get application railiance-apps-root -o jsonpath='{.status.sync.status} {.status.health.status} {.status.sync.revision}'`.\n Compare the revision with Forgejo `main`.\n\nRecord the output as `docs/evidence/<date>-argocd-railiance01-status.json`.\nIf ArgoCD is absent or not syncing on railiance01, stop this plan. Report to the\nfounder and the-custodian that the production row has no working path. An\nArgoCD install belongs to the cluster layer and needs its own go-ahead.\n\n## Agree where policy-nexus's manifests live"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0043-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "49143c5e-a455-526e-a26f-403dc2fb075a",
|
|
"body": "Per the tenant contract, workload manifests stay in the tenant repository.\n`rapp-policy-nexus` owns that repository\n(`forgejo.coulomb.social/coulomb/rapp-policy-nexus`) and decides this itself.\nWe coordinate through the hub and do not decide it here.\n\nProposal to put to rapp-policy-nexus:\n\n- The source is the existing chart `helm/policy-nexus`.\n- A committed values file, for example `k8s/railiance/values-railiance01.yaml`,\n pins `image.digest`, `publicationManifestDigest`, `sourceInventoryDigest` and\n `sourceSetDigest`. Today they are passed as `--set-string` at deploy time.\n After adoption, a release is a commit that changes these pins.\n- `helm.releaseName: policy-nexus`, so that rendered names and the\n `app.kubernetes.io/instance` label match the live release.\n- Once adopted, `make deploy` / `helm upgrade` stops being a production path.\n It would fight self-heal. Whether to keep it for pre-production is for\n rapp-policy-nexus to decide.\n\nPlatform checks:\n\n- The chart renders Deployment, Service, ServiceAccount, Ingress and\n NetworkPolicy. All five are in the `railiance-tenants` whitelist.\n- Repository access: if the repository is private, it needs an ArgoCD\n repository credential at `platform/operators/argocd/repositories/rapp-policy-nexus`.\n That credential goes through its own CCR. No value is handled in this plan.\n\n**Unblock:** rapp-policy-nexus replies with the path, the values file, and\nwhether the repository is public.\n\n\n2026-10-03 (CUST-WP-0075 owner-return sweep): this task and\nRAPP-POLICY-NEXUS-WP-0002-T02 were waiting on each other. rapp-policy-nexus\nhas now answered railiance-platform's 2026-09-21 question (reply `41678d1f`):\nchart `helm/policy-nexus` pinned to a tag or commit, no `k8s/railiance/` copy;\nvalues owned by railiance-apps, so a multi-source Application named\n`policy-nexus`; the repository is private, so ArgoCD needs a repository\ncredential through its own CCR; `make deploy`/`make rollback` stop being\nproduction paths after adoption. The whole-workplan `depends_on` was removed\nbecause it made the wait circular. Next act is railiance-platform's: confirm\nthe shape back to rapp-policy-nexus and draft the Application.\n\n2026-10-05: railiance-platform confirms that shape. This is acceptance of the\ntenant's answer, not a new placement decision.\n\n- Chart `helm/policy-nexus`, pinned to a tag or commit. No `k8s/railiance/` copy.\n- Values stay owned by railiance-apps. The Application is multi-source and\n named `policy-nexus`.\n- The repository is private. The ArgoCD repository credential is a separate CCR.\n- After adoption, `make deploy` and `make rollback` stop being production paths.\n\nThe draft is `docs/drafts/policy-nexus-application.yaml`. Its pinned revisions\nare placeholders and must be filled from the attended read.\n\n## Prepare the Application and the dry-run evidence"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0043-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocking_reason": "Draft is prepared. The attended read-only helm history / kubectl diff remains. This session did not touch the cluster.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "2afb1aac-66dd-5e1e-92e1-fc020a59a927",
|
|
"body": "Draft the Application under `docs/`, **not** under `argocd/applications/` on\n`main`. The single-source sketch is superseded by the tenant's multi-source\nshape. The draft is `docs/drafts/policy-nexus-application.yaml`: chart\n`helm/policy-nexus` from rapp-policy-nexus, railiance-apps values as the second\nsource, `helm.releaseName: policy-nexus`, no `automated` block, no finalizers.\nPinned revisions are placeholders. They must be filled from the attended read.\nThe railiance-apps values path is still that owner's; the draft does not invent\nit. Decision 89f1058f-33bc-47a8-8a49-0b44d426c67e is still open and is not\nresolved here.\n\nRead-only evidence to collect before T04, in an attended session:\n\n1. `helm -n policy-nexus get values policy-nexus` and `helm history`: the live\n digests and the current revision number, which is the rollback target. Do\n not print anything else from the release.\n2. Render the chart with the agreed values file. Run `kubectl diff\n --server-side` of the render against the live namespace. Expected result:\n no spec change, and only label or annotation differences.\n3. List every object in `policy-nexus`. Mark which ones the render does not\n contain, for example Helm release Secrets `sh.helm.release.v1.*`. Only\n resources carrying ArgoCD's tracking label are pruned. Confirm that none of\n the unrendered objects carry it.\n\nStop conditions: any Deployment spec or image change, any object that the\nrender lacks but that carries the tracking label, or a digest mismatch.\n\n## Adopt policy-nexus (live, founder go-ahead)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0043-T04",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"depends_on": [
|
|
"RPF-WP-0043-T03",
|
|
"RPF-WP-0044-T07"
|
|
],
|
|
"blocking_reason": "Founder go-ahead: the merge is a live production change (CONSTRUCT @ railiance-platform, activation=APPROVED); also needs the root automation restored in RPF-WP-0044-T07.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8638fa73-439d-5dcd-85c7-81aa125170e1",
|
|
"body": "**Waits on the founder's go-ahead.** This is a `CONSTRUCT @ railiance-platform`\nchange with `activation=APPROVED`. The merge is the gate, and it is a live\nproduction change. Do not take it on the basis of this plan alone.\n\n1. Merge the Application exactly as in T03, with no `automated` sync.\n `railiance-apps-root` creates the Application object. It does not touch\n policy-nexus resources, because the child has no automated sync.\n2. `argocd app diff policy-nexus`, or read the UI diff. It must match T03\n step 2. Any other result means stop, then roll back (step R1).\n3. `argocd app sync policy-nexus` with pruning left off, which is the default\n for a manual sync. Then run rapp-policy-nexus `make verify-live` with the\n pinned digests.\n4. After the workload has been Synced and Healthy for at least 24 hours, a\n second merge adds `automated: {prune: true, selfHeal: true}`, matching the\n tenant contract. This needs a second go-ahead.\n5. Record evidence as `docs/evidence/<date>-policy-nexus-argocd-adoption.json`.\n Notify rapp-policy-nexus and ops-mason that policy-nexus is now in the\n production row. Its transition exception ends.\n\nRollback:\n\n- **R1, before step 4:** revert the merge commit. The root app prunes the\n child Application object. The child has no finalizer, so the deletion does\n not cascade and the workload keeps running unchanged.\n- **R2, after step 4:** revert the automated-sync commit first, then R1.\n Do not patch the child Application by hand, because the root app's\n self-heal restores it from git. A hand patch is a direct `ADMINISTER` under\n `BREAK_GLASS`. It is recorded and reconciled back into git.\n- **Workload restore:** only after ArgoCD no longer manages policy-nexus, run\n rapp-policy-nexus `make rollback REVISION=<revision from T03>`. Otherwise\n self-heal fights the rollback.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Declare the platform's own direct-apply gap"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0043-T05",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "91431560-79d4-5352-a6b5-f12850315dd2",
|
|
"body": "Under the decision, platform objects without a readiness state default to\nthe production tier. This repository still changes several of them through\ndirect Make targets. Examples are the railiance01 ClusterSecretStores,\nOpenBao configuration and the ArgoCD bootstrap. That is `target-audited`\nevidence only. Inventory those targets, declare the gap as not conforming,\nand propose to the founder which ones move to a reconciled lane and which\nstay direct under `APPROVED`. Do not change a target's behaviour as part of\nthe inventory.\n\n## Execution record \u2014 2026-09-22\n\n- **T01 done.** Read-only check over `ssh railiance01`. Node 92.205.62.239 is\n Ready. Argo CD Core runs 1/1 in `argocd`. `railiance-apps-root` is\n Synced/Healthy at `8a7ebce`, which equals Forgejo `main`. `openbao-secretstore`\n and `target-revenue` are Synced/Healthy. Evidence:\n `docs/evidence/2026-09-22-argocd-railiance01-status.json`. This supersedes\n the custodian's 2026-09-21 \"not installed\" reading, which predates the phase A\n install and the kubeconfig fix. The plan continues.\n- **T05 done.** Gap declared and inventoried in\n `docs/direct-apply-gap-inventory.md`, with a per-group proposal for the\n founder. No target changed.\n\n## Loose-end review \u2014 2026-09-27\n\nThe workplan is blocked on the source-owner agreement and its downstream adoption gates. RAPP-POLICY-NEXUS-WP-0002 proposes a multi-source Application: chart in rapp-policy-nexus and release values in railiance-apps. This supersedes the earlier platform-only suggestion to put production values in the package repository. The platform accepts that shape and the helm/policy-nexus path exception in principle; it still needs railiance-apps acceptance, an actual committed values path/revision, source access and a zero-diff render before T02/T03 can close. No owner acceptance or cross-repository change is inferred. T01 remains proven by current railiance01 Synced/Healthy evidence.\n\n## Confirmation \u2014 2026-10-05\n\nT02 is done. Platform accepts rapp-policy-nexus reply `41678d1f`. That is not a new placement decision. T03 stays `wait`: the draft is prepared at `docs/drafts/policy-nexus-application.yaml`, and the attended read-only helm history / kubectl diff remains. This session did not touch the cluster. T04 stays `wait`. The workplan stays blocked. Decision `89f1058f-33bc-47a8-8a49-0b44d426c67e` is still open and was not resolved."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0044-argocd-phase-b-adopt-existing-applications.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0044",
|
|
"type": "workplan",
|
|
"title": "ArgoCD phase B: adopt the four existing Applications on railiance01",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "railiance-platform",
|
|
"topic_slug": "railiance",
|
|
"created": "2026-09-21",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"RPF-WP-0043",
|
|
"RPF-WP-0022"
|
|
],
|
|
"state_hub_workstream_id": "98140775-3b9a-5cf9-9af6-722502d487dc"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0044-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "2d7230f5-50c8-5eee-a050-1501ce5af62a",
|
|
"body": "**Done 2026-09-21, commit `c3ebd6d`.** The founder chose **Option A**\n(`GOVERN @ estate`): a railiance01-only source path. Repository-only; nothing\napplied. `argocd/applications/` and `argocd/bootstrap/` are untouched, because\ncoulombcore's ArgoCD still reads `argocd/applications/` on `main` and its\nbootstrap may be re-applied from `argocd/bootstrap/`. coulombcore could not be\nread in this session, so the railiance01 bootstrap has its own path.\n\nDeclared (all under `argocd/railiance01/`):\n\n1. `bootstrap/`: the three AppProjects and `railiance-apps-root` with **no\n `automated` block**, path `argocd/railiance01/applications`,\n `targetRevision: main` (each sync pins its revision in the operation).\n2. `bootstrap/01-railiance-tenants-project.yaml`: `postgresql.cnpg.io/Cluster`\n added to `namespaceResourceWhitelist`. The other two AppProjects are copies\n of `argocd/bootstrap/`.\n3. `applications/` holds only `README.md`. A placeholder **is** needed: git does\n not keep an empty directory and a missing path is a `ComparisonError`.\n ArgoCD's directory source reads only `*.yaml`/`*.yml`/`*.json`, so it renders\n zero children (confirmed live by T02).\n4. `drafts/`: the four children, no `automated`, no finalizer, pinned:\n openbao-secretstore `d2dbc19` (railiance-platform), issue-core `a78f38c`\n (`rapp-issue-core.git`, path `manifests`), target-revenue `f1109d5`,\n external-secrets chart `0.16.1`. No root syncs `drafts/`.\n5. `argocd/repositories/rapp-issue-core.repository.sops.yaml.template` (no\n value); `issue-core.repository.sops.yaml.template` marked obsolete.\n\nOffline proof: `kubectl kustomize argocd/railiance01/bootstrap` renders exactly\n3 AppProjects and 1 Application with no `automated` field;\n`ssh railiance01 'kubectl apply --dry-run=server -f -'` of that render\nreturned rc=0 (all four \"created (server dry run)\").\n\nHazard kept as is: `make argocd-bootstrap-deploy` still defaults to\n`argocd/bootstrap` (automated root). Do not run it on railiance01.\n\n## Apply the AppProjects and the root app, automated sync off (live)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "7d97ee9c-b2fb-520f-8468-3ecf7eea6c01",
|
|
"body": "**Done 2026-09-21** (founder go-ahead; custodian session). 3 AppProjects + `railiance-apps-root` applied from the clean export of `c3ebd6d`; root Synced/Healthy, op Succeeded at `c3ebd6d`, zero children, 0 ArgoCD-managed namespaces. Repo-server reaches Forgejo. One `OrphanedResourceWarning` (project-level, informational).\n\n Applies the render of\n`argocd/railiance01/bootstrap` at commit `c3ebd6dddc830373c75144da178f829b47c3e5de`, from a clean export (not\nthe working tree), then syncs the root by hand at that commit.\n\n```bash\ncd ~/railiance-platform && git fetch origin && git merge-base --is-ancestor c3ebd6dddc830373c75144da178f829b47c3e5de origin/main && echo pinned-commit-on-main\nR=$(mktemp -d) && git -C ~/railiance-platform archive c3ebd6dddc830373c75144da178f829b47c3e5de argocd/railiance01/bootstrap | tar -x -C \"$R\"\nkubectl kustomize \"$R/argocd/railiance01/bootstrap\" > \"$R/bootstrap.yaml\" && grep -c '^kind: AppProject' \"$R/bootstrap.yaml\" && grep -c automated \"$R/bootstrap.yaml\" # expect 3 and 0\nssh railiance01 'kubectl apply --dry-run=server -f -' < \"$R/bootstrap.yaml\"\nssh railiance01 'kubectl apply -f -' < \"$R/bootstrap.yaml\"\nssh railiance01 'kubectl -n argocd patch application railiance-apps-root --type merge -p \"{\\\"operation\\\":{\\\"initiatedBy\\\":{\\\"username\\\":\\\"founder-approved\\\"},\\\"sync\\\":{\\\"revision\\\":\\\"c3ebd6dddc830373c75144da178f829b47c3e5de\\\",\\\"prune\\\":false}}}\"'\nssh railiance01 'kubectl -n argocd get appprojects,applications'\nssh railiance01 'kubectl -n argocd get application railiance-apps-root -o jsonpath=\"{.status.sync.status} {.status.operationState.phase} {.status.operationState.syncResult.revision} resources={.status.resources}{\\\"\\n\\\"}\"'\n```\n\nExpect three AppProjects and `railiance-apps-root` `Synced`, operation\n`Succeeded` at `c3ebd6d`, and no resources (zero children). A\n`ComparisonError` means the repo-server cannot reach Forgejo: stop and fix\negress before any app task. No repository Secret is needed;\n`coulomb/railiance-platform` is public.\n\nRollback: `kubectl -n argocd delete application railiance-apps-root` (no\nfinalizer, no children), then delete the three AppProjects. Nothing else is\ntouched.\n\n## Per-app procedure (T03\u2013T06)\n\nEvery adoption task follows the same steps. `<app>` and `<sha>` vary.\n\n1. **Diff.** Re-run the evidence render and `kubectl diff --server-side` at\n the commit or chart version being pinned. Any spec change, any missing\n whitelist kind, or a different image: stop.\n2. **Merge** the child Application (no `automated`) from\n `argocd/railiance01/drafts/` into `argocd/railiance01/applications/`, then sync the root by hand so it creates the child object only:\n ```bash\n ssh railiance01 'kubectl -n argocd patch application railiance-apps-root --type merge -p \"{\\\"operation\\\":{\\\"initiatedBy\\\":{\\\"username\\\":\\\"founder-approved\\\"},\\\"sync\\\":{\\\"revision\\\":\\\"<sha>\\\",\\\"prune\\\":false}}}\"'\n ```\n3. **ArgoCD's own diff:** read\n `kubectl -n argocd get application <app> -o jsonpath='{.status.sync.status} {.status.health.status}'`\n and `.status.resources`. Only metadata differences are acceptable.\n4. **Manual sync, prune off, hooks skipped** (`apply` strategy):\n ```bash\n ssh railiance01 'kubectl -n argocd patch application <app> --type merge -p \"{\\\"operation\\\":{\\\"initiatedBy\\\":{\\\"username\\\":\\\"founder-approved\\\"},\\\"sync\\\":{\\\"revision\\\":\\\"<sha>\\\",\\\"prune\\\":false,\\\"syncStrategy\\\":{\\\"apply\\\":{}}}}}\"'\n ```\n Then verify Synced/Healthy and run the owner's live check.\n5. **Prove it:** Synced and Healthy for at least 24 hours (7 days for\n external-secrets). Only then, with a **second** go-ahead, a merge adds\n `automated: {selfHeal: true}`; `prune: true` is a third step once the\n app's tracked set is confirmed complete.\n6. Record `docs/evidence/<date>-<app>-argocd-adoption.json`.\n\nRollback:\n\n- **R1, before automated sync:** revert the merge, then\n `kubectl -n argocd delete application <app>`. No finalizer, so nothing\n cascades; the workload keeps running. Tracking annotations stay and are\n harmless.\n- **R2, after automated sync:** revert the automated-sync commit first and\n sync the root by hand, then R1. Never hand-patch a child while the root\n self-heals; that is `BREAK_GLASS`, recorded and reconciled into git.\n- **Workload restore:** only once ArgoCD no longer manages the app, with the\n previous deploy method named in the task.\n\n## Adopt openbao-secretstore (lowest risk)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocking_reason": "Adopted 2026-09-21; the follow-on step (issue-core adoption, then automation) waits on the founder's go-ahead.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "6d5fc801-e361-579b-bcd8-6fe719a82e94",
|
|
"body": "**Adopted 2026-09-21** (founder go-ahead; custodian session): diff at `d2dbc19` rc=0; child merged in `182e788`; root synced at `182e788`; child manual sync (apply strategy, prune off) Succeeded at `d2dbc19`, Synced/Healthy, automated off. `ClusterSecretStore/openbao` Valid with tracking annotation; `issue-core-runtime` SecretSynced. Status `progress` = in the 24h proving period; `selfHeal` needs a second go-ahead. Evidence: `docs/evidence/2026-09-21-openbao-secretstore-argocd-adoption.json`.\n\nOne object,\n`ClusterSecretStore/openbao`, zero diff, public source. It is the store\nissue-core's `ExternalSecret` reads, so adopt it before issue-core. The 24\nother ClusterSecretStores on railiance01 are not in the kustomization and stay\nuntracked (declared gap, RPF-WP-0043-T05). Live check:\n`kubectl get clustersecretstore openbao` stays `Valid`, and\n`externalsecret/issue-core-runtime` stays `SecretSynced`. Workload restore:\n`kubectl apply -f argocd/platform-addons/openbao-secretstore/openbao.clustersecretstore.yaml`.\n\nExact commands (the root sync pins the merge commit `$SHA`; the child is\npinned to `d2dbc19`, the last commit touching its source path):\n\n```bash\n# 1. Diff at the pinned source commit (expect no output, rc=0)\ncd ~/railiance-platform && git fetch origin && git checkout main && git pull --ff-only\nR=$(mktemp -d) && git archive d2dbc19c254247652c49fda8721c80d53bca206a argocd/platform-addons/openbao-secretstore | tar -x -C \"$R\"\nssh railiance01 'kubectl diff --server-side -f -' < <(kubectl kustomize \"$R/argocd/platform-addons/openbao-secretstore\"); echo rc=$?\n# 2. Merge the child (drop the 3-line DRAFT header), push, sync the root at that commit\nsed '1,3d' argocd/railiance01/drafts/openbao-secretstore.application.yaml > argocd/railiance01/applications/openbao-secretstore.application.yaml\ngit rm -q argocd/railiance01/drafts/openbao-secretstore.application.yaml\ngit add argocd/railiance01/applications/openbao-secretstore.application.yaml\ngit commit -m \"Adopt openbao-secretstore on railiance01 (RPF-WP-0044-T03)\" && git push origin main\nSHA=$(git rev-parse HEAD) && echo \"$SHA\"\nssh railiance01 \"kubectl -n argocd patch application railiance-apps-root --type merge -p '{\\\"operation\\\":{\\\"initiatedBy\\\":{\\\"username\\\":\\\"founder-approved\\\"},\\\"sync\\\":{\\\"revision\\\":\\\"$SHA\\\",\\\"prune\\\":false}}}'\"\n# 3. ArgoCD's own diff (expect OutOfSync or Synced, one resource ClusterSecretStore/openbao, metadata-only)\nssh railiance01 'kubectl -n argocd get application openbao-secretstore -o jsonpath=\"{.status.sync.status} {.status.health.status} {.status.resources}{\\\"\\n\\\"}\"'\n# 4. Manual sync, prune off, apply strategy (hooks skipped)\nssh railiance01 'kubectl -n argocd patch application openbao-secretstore --type merge -p \"{\\\"operation\\\":{\\\"initiatedBy\\\":{\\\"username\\\":\\\"founder-approved\\\"},\\\"sync\\\":{\\\"revision\\\":\\\"d2dbc19c254247652c49fda8721c80d53bca206a\\\",\\\"prune\\\":false,\\\"syncStrategy\\\":{\\\"apply\\\":{}}}}}\"'\nssh railiance01 'kubectl -n argocd get application openbao-secretstore -o jsonpath=\"{.status.sync.status} {.status.health.status} {.status.operationState.phase}{\\\"\\n\\\"}\"'\nssh railiance01 'kubectl get clustersecretstore openbao; kubectl -n issue-core get externalsecret issue-core-runtime'\n```\n\nRollback (R1): `git revert` the merge commit and push, then\n`ssh railiance01 'kubectl -n argocd delete application openbao-secretstore'`\n(no finalizer; the ClusterSecretStore keeps running).\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Adopt issue-core (from rapp-issue-core)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T04",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocked_on": "message-from:rapp-issue-core",
|
|
"blocking_reason": "Founder go-ahead plus rapp-issue-core's agreement (hub message) that ArgoCD owns production and make deploy stops being a production path.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0e619658-0453-51ed-b9a0-bed28b5544fd",
|
|
"body": "**Waits on the founder's go-ahead**, and on two preconditions:\n\n- `rapp-issue-core` agrees (hub message) that ArgoCD owns production and its\n `make deploy` stops being a production path; it would fight self-heal.\n Image releases become commits to `manifests/30-runtime.yaml`.\n- A CCR for the ArgoCD repository credential, source at\n `platform/operators/argocd/repositories/rapp-issue-core`, read-only deploy\n token. Applied with `make argocd-repo-apply`; no value is handled in this\n plan.\n\nZero diff against live for both the raw `manifests/` and the rendered output\n(digest `sha256:a56c80cc\u2026b92cf`). All kinds are in the `railiance-tenants`\nwhitelist. Live check: `rapp-issue-core make verify-live`. Workload restore:\n`rapp-issue-core make rollback`.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Adopt target-revenue"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T05",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocking_reason": "Adopted 2026-09-21; remaining preconditions and the next step wait on the founder's go-ahead.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d418068a-6fb0-5416-aac5-d23c93924d9c",
|
|
"body": "**Adopted 2026-09-21** (founder go-ahead; custodian session). The *server-side* diff at `f1109d5` conflicted on `resources.limits.cpu` (live `1` owned by `kubectl-client-side-apply` vs declared `1000m`: the same quantity); the *client-side* diff, which is what the apply strategy uses, was rc=0 for all five non-hook objects. Child merged in `6eeb826`; manual sync with the `apply` strategy, prune off: Succeeded, Synced/Healthy, **0 Jobs created**, same pod (36d, no restart), CNPG healthy 1/1, ExternalSecret SecretSynced, `https://revenue.coulomb.social/healthz` 200 (the live check path is `/healthz`, not `/health`). Status `progress` = proving period. Automated sync still needs target-revenue's confirmation on the two hook Jobs (asked 2026-09-21). Evidence: `docs/evidence/2026-09-21-target-revenue-argocd-adoption.json`.\n\nOriginal preconditions: T01 item 2 (CNPG\n`Cluster` whitelisted) applied to the AppProject by hand, and `target-revenue`\nconfirms the two Sync-hook Jobs (`target-revenue-migrate`,\n`target-revenue-bootstrap-binky`) are safe to re-run against production. They\nare absent live and would run on every sync with the default hook strategy.\nThe adoption sync uses the `apply` strategy, which skips them. Once automated\nsync is enabled they run on each sync, so the second go-ahead depends on that\nconfirmation. Ask `target-revenue` to pin an image digest instead of `0.1.4`.\nLive check: `https://revenue.coulomb.social` health and the CNPG cluster\nhealthy. Workload restore: `kubectl apply -k k8s/railiance` from the previous\ntarget-revenue commit.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Adopt external-secrets (highest risk)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T06",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocking_reason": "Founder go-ahead for the ESO adoption after adding CRD Prune=false,Delete=false and re-running the diff.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "4ca54868-c31f-5e3d-b7d3-a15b84c15f80",
|
|
"body": "**Waits on the founder's go-ahead.** Zero diff, but ESO serves every\n`ExternalSecret` on the cluster (25 ClusterSecretStores). Before the merge,\nadd `crds.annotations: {argocd.argoproj.io/sync-options: \"Prune=false,Delete=false\"}`\nto the values and re-run the diff; pruning a CRD would delete every\n`ExternalSecret` and store. Adopt with `ServerSideApply=true` as declared.\nWatch for drift on `caBundle` fields injected by the cert-controller; if\nArgoCD shows it, add `ignoreDifferences` before enabling self-heal. After\nadoption, retire the stale `pending-upgrade` Helm release record (its\n`sh.helm.release.v1.external-secrets.v*` Secrets) under a separate go-ahead;\nArgoCD does not track them. Live check: all ClusterSecretStores keep their\ncurrent `Valid` state (two, `openbao-activity-core` and\n`openbao-email-connect`, are already `ValidationFailed`). Workload restore:\n`helm template` 0.16.1 with the same values, `kubectl apply --server-side`.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Turn the root back to the production lane"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T07",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"depends_on": [
|
|
"RPF-WP-0044-T03",
|
|
"RPF-WP-0044-T04",
|
|
"RPF-WP-0044-T05",
|
|
"RPF-WP-0044-T06"
|
|
],
|
|
"blocking_reason": "Founder go-ahead to restore automated prune/selfHeal on railiance-apps-root once T03-T06 are proven.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "844ff115-def2-55ca-ab01-413ba7e6857d",
|
|
"body": "**Waits on the founder's go-ahead.** After T03\u2013T06 are proven, restore\n`automated: {prune: true, selfHeal: true}` on `railiance-apps-root`, as the\nchange-gate decision's production row expects. From then on a merge to the\nrailiance01 path is a live production change, and `RPF-WP-0043-T04`\n(policy-nexus) can use it.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Plan phase C: retire coulombcore's ArgoCD"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0044-T08",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocking_reason": "Planning only; needs an operator read-only check of coulombcore's ArgoCD, outside agent session scope.",
|
|
"priority": "low",
|
|
"state_hub_task_id": "55d1382f-5862-5321-a1c9-96767764ba43",
|
|
"body": "Planning only. Needs a read-only check of coulombcore's ArgoCD, outside this\nsession's scope. Under Option A, retiring it also removes `argocd/applications/`.\nAlso hand back to the cluster layer: the phase A install is not declared in\nany repository and its pods have no resource requests (BestEffort).\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Loose-end review \u2014 2026-09-27\n\nT03/T05 passed their elapsed healthy observation gate: current ArgoCD status is Synced/Healthy with last healthy transitions on September 21; openbao is Valid and issue-core-runtime is SecretSynced. They now wait on the remaining automation go-aheads and, for target-revenue, hook-owner acceptance. T06 local preparation is complete: the inactive ESO draft protects all 20 CRDs from prune/delete. The pinned 0.16.1 chart renders 39 objects; server-side diff is exactly the 20 protective metadata annotations, with no spec changes. All 25 ClusterSecretStores are Valid. T04 still needs the repository credential/production-owner contract; T07 depends on the per-app gates. T08 has a concrete retirement procedure at `docs/argocd-coulombcore-retirement.md`, but its required live inventory is blocked: SSH works and Kubernetes rejects both default and explicit local k3s kubeconfigs. No controller or workload was changed. Evidence: `docs/evidence/2026-09-27-argocd-loose-end-status.json` and `docs/evidence/2026-09-27-eso-adoption-preparation.json`."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0048-activity-core-gitops-adoption.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0048",
|
|
"type": "workplan",
|
|
"title": "Adopt activity-core application runtime into railiance01 GitOps",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"owner": "codex",
|
|
"topic_slug": "railiance",
|
|
"created": "2026-09-27",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "b8cf2fc2-60c2-5d4e-a60a-55f1304d9f54"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0048-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "a8cafada-385f-58a5-9c05-20d447c40370",
|
|
"body": "New project permits only activity-core source, activity-core destination, and\nConfigMap/Service/Deployment kinds. No secrets, Jobs, databases, queues, Temporal,\nllm-connect, edge relay, storage or cluster-scoped resources enter this Application.\nApplication source is activity-core k8s/gitops at a pinned reviewed commit; no\nfinalizer, automated sync or pruning initially. Root sync must name this child\nonly; unrelated pending applications must not be changed. Verify ArgoCD's diff,\nhealth, resource inventory, schedules and original deployment generations.\n\n## Observe adoption and enforce bounded promotion readiness"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0048-T02",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"depends_on": [
|
|
"ACTIVITY-WP-0041"
|
|
],
|
|
"blocking_reason": "24h soak after adoption, then founder confirmation of the scoped identity and checks before automated sync; ACTIVITY-WP-0041 owns publication and the promotion guard.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "63b44949-39f8-52fd-ab63-e618b67ef992",
|
|
"body": "Keep automated sync off for at least 24 hours after successful adoption. Record\nstart and earliest eligibility in evidence. ACTIVITY-WP-0041 owns image publication,\nsource validation and the promotion/rollback guard. Root-wide automation is outside\nthis workplan. No unattended merge credential or release executor is assumed just\nbecause the Application exists. Confirm the scoped identity and checks before\nactivating bounded routine promotion. Destructive pruning remains disabled.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Make registry retention aware of digest-pinned releases"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0048-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "6c2650a2-5da8-5999-a6e7-b22eb7c655f4",
|
|
"body": "The package retention parser currently recognizes tags only; digest references\nmust resolve to protected registry versions before routine digest promotion can\nbe unattended. Cover live and rollback digests, preserve fail-closed behavior on\nincomplete registry/export coverage, and test the resulting deletion plan without\ndeleting packages. Coordinate admission with ACTIVITY-WP-0041-T03. Until this is\nimplemented, release evidence must include protected tag aliases for each digest.\n\nImmediate mitigation verified: all three activity-core baseline tags are present\nin the additive live-image union and recognized by the existing owner parser.\nNo retention deletion was run. Future releases must not assume a digest line alone\nprovides package protection.\n\n## Adoption evidence \u2014 2026-09-27\n\nAppProject bootstrapped; root selectively synced only activity-core. Initial\nnine-resource adoption changed tracking metadata only. Then the child pinned\n12e08878d19e61ce41c534cc10ca56acd0c3efc1 and rolled out registry digests of the\nsame binaries. All three deployments ready; ArgoCD Synced/Healthy; scheduled\nfrontend reporting smoke completed; all three recurring definitions stay enabled.\n\nSee docs/evidence/2026-09-27-activity-core-gitops.json. Conservative healthy soak\nstarts 2026-09-27T13:38:21Z, earliest eligibility 2026-09-28T13:38:21Z subject to\nhealthy observation. T02 stays waiting for this window and authenticated narrowly\nbound release-identity/rollback proof. Automation and pruning remain disabled.\nAuthorization decision: 78a4b859-dd00-4623-b95b-121b0e1c915d.\n\n## Digest retention implementation \u2014 2026-09-27\n\nImplemented conservative package-wide protection for live/exported sha256 refs,\nincluding tag@digest and retained rollback references. This avoids unsafe alias\nmapping assumptions; storage retention increases for those packages. Malformed\nreferences and incomplete cluster/package inventory refuse apply before deletion.\nSixteen focused tests pass. Live tool installation/readback remains required;\nexisting baseline aliases continue protecting production in the meantime.\n\nCredential routing inspection found no ready scoped unattended ArgoCD/Forgejo\nrelease lane. ACTIVITY-WP-0041-T03 remains the authority/admission owner; no broad\noperator token was copied or delegated. Its concrete executor contract is in\n`docs/activity-core-release-admission.md`.\n\nThe production worker currently mounts an older platform checkout's script\n(SHA256 0baacfd07b74ddd4317f79aa0de818c25186e15303a67c08d29edc73ad74a870).\nDeploy the new script as a pinned GitOps projection, verify worker readback and a\nnon-destructive planner fixture, then close T03. Do not silently overwrite the\nhost checkout: it is outside the newly adopted nine-resource projection. Current\nbaseline aliases remain protected; no prune was executed during verification.\n\nArgoCD Core has no API-server token/role lane. T02 admission must prove a broker\nthat restricts both the platform child revision update and Kubernetes Application\nsync operation; resource-name RBAC alone cannot restrict patch fields. This is\nconcrete implementation work retained here and in ACTIVITY-WP-0041-T03, not a\nreason to ask the founder to approve each release. Tests in the owner checkout:\n20 passed across retention and additive inventory suites.\n\n## Retention deployed and verified \u2014 2026-09-27\n\nT03 complete. Supersedes the earlier pending host-copy installation: the script\nis now pinned by source commit and SHA256 in activity-core's existing ConfigMap,\nprojected read-only over the worker tool path, and reconciled through ArgoCD.\nNo host checkout mutation, new resource adoption or manual prune was needed.\nThe pod annotation changes with the script hash to refresh subPath mounts.\nCI verifies source bytes against the platform commit. Live worker hash matches;\nreal additive inventory protects activity-core as a whole package. A synthetic\nrollback version is protected by the planner. No registry requests or deletion\nwere made by this probe. See docs/evidence/2026-09-27-digest-retention-release.json.\n\nNew healthy observation start is 2026-09-27T14:06:22Z after worker rollout;\nearliest eligibility is September 28 at 16:06:22 Europe/Berlin. Automation remains\noff. T02 still owns the scoped broker/admission and observation requirements.\n\n## Loose-end review \u2014 2026-09-27\n\nThe workplan is blocked on T02. Current activity-core remains Synced/Healthy at a12f1169f9d130058ce767f5b26de0606997916c, with health transition 2026-09-27T14:06:22Z. Earliest observation eligibility remains September 28 at 16:06:22 Europe/Berlin. The authenticated bounded broker/admission and rollback proof remain owned jointly with ACTIVITY-WP-0041-T03. Elapsed time is not release-identity admission. T01/T03 remain done; no root automation, pruning or credential delegation was enabled.\n\n## Approved grant-preserving reporting repair \u2014 2026-09-28\n\nUnder explicit user decision `abdea390-1039-4da1-b129-33aad00b4396`, platform\ncommit `986b002` pins activity-core `4bd07a4`. Root selectively synced only that\nApplication, then child selectively synced only the worker image to `afd8a7af\u2026`.\nNo automatic sync/pruning or unrelated resource mutation was enabled. The current\ngrant-aware base remains intact; frontend reporting and monthly review fields are\nrestored. ArgoCD is Synced/Healthy and live source/grant hashes match the tested\nimage. Three report-only Temporal smokes and their State Hub sinks pass; temporary\nschedules are removed, recurring schedules retained.\n\nThe September 27 healthy interval is invalidated by the missing-resolver failure\non the September 28 natural daily run. All repaired sink checks passed by\n2026-09-28T09:26:27Z; continuous sampled health and standing release authority are\nstill unproven. T02 remains wait and workplan blocked. Rollback target preserves\ngrants (`428f2d7` / `713bddad\u2026`); do not restore the older grant-unaware overlay.\nExact evidence: frontend-patterns/docs/evidence/2026-09-28-reporting-live.json."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0050-attended-provisioning-preparation.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0050",
|
|
"type": "workplan",
|
|
"title": "Prepare generated attended windows and explicit value-custody choice",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "blocked",
|
|
"owner": "codex",
|
|
"topic_slug": "platform-services",
|
|
"created": "2026-10-03",
|
|
"updated": "2026-10-04",
|
|
"flavor": "implementation",
|
|
"state_hub_workstream_id": "0c7e3b0c-1c36-568c-af51-b06f912a0f1d"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0050-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "43fac4d5-98de-5469-ac86-c8925ea3a31b",
|
|
"body": "Implemented `credential-change.py window-checklist` and `scripts/provisioning_window.py`. Reads authoritative open non-residual task blocks and explicit CCR/lane/receipt contracts. Missing/stale joins and non-approved/applied CCRs prevent a complete checklist. No execution, scheduling, credential reads or printing arbitrary CCR contents. Contract: `docs/attended-provisioning-window.md`. Synthetic regression suite verifies actual decision joins and replay refusal. This completes the bounded source renderer, not a real attended session.\n\n## Obtain exact founder value-custody choice"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0050-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"decision_id": "1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa",
|
|
"state_hub_task_id": "99b73b3f-66b1-57a9-9f68-43e3fe12bf26",
|
|
"body": "P3 options and required review boundaries are drafted in the contract. Existing attended custody remains in force. No delivery helper, delegated value role or policy change is admitted by preparation.\n\n2026-10-04: Bernd explicitly selected \"Batched attended custody (existing approach)\" in this session. T02 is done for that choice under the existing attended-login boundary, recorded in `docs/attended-provisioning-window.md`: founder OIDC/MFA, exact per-item reviewed CCR/actor/path/audience, contained silent child, existing TTL/revocation, compare-before-write, replay refusal and per-item abort/verification/rollback. No alternate delivery lane is adopted. Shared D3 has other unresolved subjects and is not resolved by this task completion. T03 still requires the dated scope and owner receipt mappings; no live command or schedule is authorized by this choice.\n\n## Bind a real dated window and owner receipt manifests"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0050-T03",
|
|
"status": "wait",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"RPF-WP-0051-T02",
|
|
"RPF-WP-0035-T02",
|
|
"USER-WP-0035-T02"
|
|
],
|
|
"blocking_reason": "Platform preparation and founder design choice are complete. Independent informed-decision runtime source/publication, KeyCape custody/registration/issuance, secrets-engine consumer custody coordinates and provider setup-link handoff remain; dependency-requirements.md names the exact owner deliveries.",
|
|
"state_hub_task_id": "1ae5a6b8-9c83-5813-982f-ca8ad24be8b5",
|
|
"body": "Generate a checklist from all named authoritative roots, verified Hub decision joins and owner CCR/lane/receipt mappings; revalidate each exact revision, upstream acceptance, native readiness and rollback. Applied custody such as RPF-WP-0035-T08 is excluded. Each session returns exact receipts for each owner; missing receipts leave waits intact. Do not activate schedules in this workplan.\n\n2026-10-04: Bernd directed \"Pick lanes by relevance for today 10am\". Prepared the one-time 10:00 Europe/Berlin (08:00 UTC) source packet in `docs/provisioning-windows/2026-10-04-1000/`. Priority scope: secrets-engine service JWT login (RPF-WP-0035-T02), informed-decision requester workload delivery (INFD-WP-0005-T05, separate decision), and user-engine transactional mail (USER-WP-0035-T02). The packet records per-owner required receipts, historical custody replay exclusions and the separate no-session RPF-WP-0035-T06 acceptance. Current D1 roots and exact Hub task joins are reviewed in the evidence inventory. No eligible reviewed new execution candidate is claimed; the generated checklist remains NOT READY. T03 stays wait for Custodian review and concrete owner contracts/commands/mappings, rather than the now-supplied date. No schedule or live command is executed.\n\n2026-10-04 continuation: Direct founder date/scope selection supplies the platform\ndate gate without requiring a repeated Custodian confirmation; its residual source\nremains its owner's record. Prepared concrete informed-decision reader artifacts\nand silent conflict-refusing metadata child under RPF-WP-0051-T01 (done). The\nseparate owner-decision checklist now has an explicit proposed CCR/lane/receipt\njoin, retaining approval/binding/runtime blockers. Corrected mail priority from\ncredential provisioning to the provider password-setup-link handoff: USER-WP-0035's\n2026-09-27 qualification confirms existing authenticated mail. `owner-returns.md`\nnames the actual three remaining owner acts. T03 depends on those returns rather\nthan an already-supplied date. No applied requester/mail custody is replayed.\n\n2026-10-04 blocked-task review: worker returns reconciled, platform issuer-reader\nCCR-2026-0033/policy/auth/ESO/receipt source implemented, and actual ESO controller\nTokenRequest authorization checked without minting a token. Required independent\nowner phases and reopen conditions are recorded in\n`docs/provisioning-windows/2026-10-04-1000/dependency-requirements.md`.\nT03 stays wait; the plan is blocked because remaining progress requires receiving\nrepo source/registration/custody/handoff evidence. Existing date/design approvals\nare retained. No source receipt is substituted for native acceptance.\n\n## Accept platform seam for catalog lane scaffold proposal"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0050-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "6475d924-92c6-504a-b9a1-4f035273f0e1",
|
|
"body": "P4 accepted for platform-side source review and bounded scaffolding after Warden returns its contract. Catalog entry/scaffold never supplies credentials, reviews, admission or live authority. Keep owner acceptance explicit before implementation.\n\n2026-10-03: Platform source review accepts the delivered Warden seam at `ops-warden/wiki/CatalogLaneScaffoldContract.md` (`ac112d8`). T04 is now a ready source implementation task for the platform-owned rendering and schema fixture. Warden T02 may progress independently; no mutual owner-return wait remains. This is source contract acceptance, not credential admission or production authorization.\n\n2026-10-04 T04 implementation: closed platform metadata schema and `credential-change.py scaffold-lane` authored with deterministic proposed CCR, existing exact-path policy/auth rendering, namespace-restricted draft ESO with annotation containment, and non-executed owner evidence checklist. Shared synthetic platform/Warden pointer fixtures retain unknown workload identity and unconfirmed auth claims. Fourteen focused offline tests pass in isolated prepared source; cross-owner staging fixture acceptance remains before marking T04 done. No admission, credentials, human answer or production execution.\n\n2026-10-04 T04 acceptance: actual applied-source scaffold tests 14/14 and existing window tests 7/7 pass, with CLI help and diff checks. Both actual owner CLIs produced matching cross-owner synthetic fixture drafts; platform independently verified Warden catalog/model loading, exact lane/owner/consumer/risk/CCR pointers and fixture digest, preserved unknown workload, unconfirmed prospective auth, proposed/unresolvable frontdoor, explicit ESO target annotations and non-executed evidence. Six platform artifacts match the independently generated second platform stage byte-for-byte. Receipt: `docs/evidence/2026-10-04-catalog-lane-scaffold-offline.json`. T04 is done for offline source/scaffold/fixture acceptance only. T02 remains the founder custody-choice wait; T03 remains the Custodian dated-window handoff. No admission, actual credentials, schedule or production execution was performed."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0053-coulomb-paired-backup-admission.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0053",
|
|
"type": "workplan",
|
|
"title": "Admit Coulomb paired archives and independent email-ledger recovery",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "proposed",
|
|
"owner": "codex",
|
|
"topic_slug": "coulomb-social",
|
|
"created": "2026-10-07",
|
|
"updated": "2026-10-08",
|
|
"state_hub_workstream_id": "cb55e474-c7a5-5c6f-bd72-ce65f853e3e3"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0053-T01",
|
|
"status": "progress",
|
|
"priority": "high",
|
|
"state_hub_task_id": "ceb58abf-77ef-5d75-a65b-fc67bfd9aa54",
|
|
"body": "Choose the platform execution owner: the prepared node systemd units or the\nexisting bounded activity-core execution lane. Review single-writer quiescence,\nlock, termination/resume behavior, exact cluster UID, app digest and data scope.\nNode systemd candidate uses root/k3s admin, guarded to coulomb-social and\ncoulomb_social_db; that authority is not a new credential grant and needs\nexplicit owner/founder admission before unattended operation. Prefer a scoped\nplatform identity where its execution contract supports coherent DB/PVC capture.\nDo not mark the warden offsite workload identity resolved without a declaration.\n\n## T02 \u2014 Admit offsite prefix, retention and caller custody"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0053-T02",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"needs_human": true,
|
|
"intervention_note": "Platform must admit the exact Scaleway primary archive caller/prefix, reconcile its current custody front door and retention/capacity, and deliver bounded credentials before activation.",
|
|
"state_hub_task_id": "b06f1a44-1a55-588c-9c6c-3c1e290544df",
|
|
"body": "The original Nextcloud overwrite-slot proposal is withdrawn; its current workload\nuploader is create-only and secondary. Reuse the platform primary contract:\ns3://railiance-platform-pg-backup/platform-pg/application-archives/coulomb-social/,\nStandard Multi-AZ nl-ams. Exact review package is\ndocs/credential-lane-designs/coulomb-paired-backup-primary.md.\n\nscripts/primary_application_archive.py implements conditional immutable multipart\ncompletion, own unfinished-upload abort, version-pinned GET and ciphertext hash\nverification. Independent retrieve needs only a retained public receipt, no\noriginal archive/node. requirements/backup-primary.lock pins seven packages with\nhashes in a dedicated backup-venv; SDK conditional-completion shape is verified.\nSynthetic provider tests cover uncertain completion, replay without new upload,\ncorrupted bytes, changed versions, caller scope and node-loss retrieval. No live\nprovider rights or custody are inferred from these tests.\n\nCCR-2026-0012 identifies existing primary custody coordinates and its approved\nrapp-postgres/databases delivery, not a new consumer. Its historical catalog id\nbackup-object-storage is unknown to the current local warden CLI. Owner must\nreconcile the front door, choose/admit appropriately prefix-scoped IAM authority\nand deliver AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY to root-owned mode 0600\n/etc/coulomb-social-backup/primary.env (parent mode 0700). Metadata-only node check found\nthat file absent. No Secret fetch/copy or namespace expansion occurred.\nNo bootstrap key or age identity belongs in the scheduled worker.\n\nSeparate non-mutating application_archive_retention_plan.py proposes 14 daily/4\nweekly distinct generations and protects newest plus the exact last application-\nrecovered version/hash. A missing/changed proof refuses; foreign/unverified points\nare ignored. This is a review, not a deletion executor or activated lifecycle.\nBind local/provider headroom, independently retained metadata receipts, protected\nrecovery and compatibility with the existing 30-day bucket lifecycle before\nactivation. No retained-object/version-delete rights belong in the publisher.\n\n## T03 \u2014 Activate and verify retrieval and application recovery"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0053-T03",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"needs_human": true,
|
|
"intervention_note": "Needs T01/T02 owner admission and founder go for the exact first quiescence/upload and schedule; independent offsite retrieval and recovery proof remain required.",
|
|
"state_hub_task_id": "871c14da-2940-5be6-8ce8-953973422064",
|
|
"body": "Founder ADMINISTER @ realm:kubernetes/railiance01, activation=APPROVED, plus\nexplicit primary archive creation/version-read authority. Proposed UTC daily03:15\n(+up to 5min jitter), RPO target24h, hourly stale threshold 26h, provisional\nRTO target60min for an admitted attended restore. These are proposal targets,\nnot measured promises. First capture/upload is bounded and app resumes before\nencryption/upload. Retrieve using the independently retained public receipt,\ncompare encrypted hash, decrypt through recovery\nescrow with consumer recover-paired-backup.py (strict three-file packet/hash and\ncapture/image binding), then run restore-paired-snapshot.py and compare\nrow/sequence/file hashes, actual rendering and denial. Record receipt paths,\ncounts/timing only; preserve the source recovery point on any failed check.\nNo production data restore is part of backup schedule activation.\n\n## T04 \u2014 Bind monitoring and recurring recovery custody"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0053-T04",
|
|
"status": "todo",
|
|
"priority": "high",
|
|
"state_hub_task_id": "687fd36d-98a9-5c10-833e-b6bda51fa07b",
|
|
"body": "Connect non-secret freshness/provider receipts and failed units to the\nestablished evidence owner (RPF-WP-0036-T03/T04), prove reception and failure\nresponse; local journald failure alone is not monitored acceptance. Name the\nrecovery custodian and approve a monthly isolated drill with offsite readback.\nVerify key recovery survives node/workstation loss. Record release-triggered\nbackup helper digest refresh and admitted generation/capacity/retention policy.\nCSOC-WP-0008-T02 stays progress until operating evidence and service contract are accepted.\n\n## Implementation evidence \u2014 2026-10-07\n\nNew primary/retention 30 cases and existing backup tier/archive lifecycle 23 cases\npass (53 total); no live provider/custody interaction. Consumer full make check\npasses 150 tests/mandatory browser journeys and Ruff; real synthetic age recovery\nroundtrip passes and all four systemd units verify. T01 is progress for the\nprepared execution package; owner identity acceptance remains open. T02/T03 remain\nwait for custody/admission and exact activation; no timer installed/enabled and\nno productive ciphertext uploaded. Email-connect's separate transport profile\nis not ledger capture/recovery coverage; CSOC-WP-0010-T04/T05 own that residual.\n\n## T05 \u2014 Admit the independent email-connect ledger archive caller"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0053-T05",
|
|
"status": "progress",
|
|
"priority": "high",
|
|
"needs_human": true,
|
|
"intervention_note": "email-connect primary.env is delivered from the accepted reader. Retention, capacity, independent receipts, escrow and the first capture remain open. Coulomb node delivery was not requested.",
|
|
"state_hub_task_id": "3f744ce6-28e4-5496-8d21-7231271a7bc8",
|
|
"body": "Consumer EMAIL-WP-0007 implements default-preview quiesced SQLite backup, stable\nage sealing, verified primary publication and attended isolated recovery. Its\nemail-connect profile is separate from Coulomb/Barman:\nplatform-pg/application-archives/email-connect/. Review packet:\nemail-connect/docs/ledger-backup-review-2026-10-08.md. No SMTP or ingest credential\nbelongs to the backup worker. Candidate delivery: root-owned mode 0600\n/etc/email-connect-backup/primary.env (parent mode 0700), only owner-delivered\nAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY. Metadata-only node check: file absent.\nDo not copy the databases backup Secret or Coulomb caller, widen ESO admission,\nor give publisher retained-object/version-delete or age escrow authority.\n\nBind appropriately prefix-scoped provider authority and current custody front\ndoor; existing CCR-2026-0012 is a coordinate, not this consumer's grant. Use the\nreviewed hash-locked platform backup runtime. Admit independent receipt/key/image\nrecovery and ledger growth/headroom, local/provider generation retention and\ncompatibility with existing 30-day lifecycle. Provisional daily 04:15 UTC, RPO 24h,\nstale 26h, RTO 60min need owner acceptance; they are not measured promises.\n\nThe SQLite snapshot preserves state only at capture. A later provider submission\nor challenge consume/cancel can be lost by restoring an older point. Production\nincident recovery must fence caller/outbox/challenge traffic and reconcile the\npost-capture window with user-engine/identity/provider owners before release;\nnever auto-enable a recovered receiver or resend an unknown outcome. Exact\nfirst pause/upload/schedule, actual offsite/recovery proof and failure reception\nremain EMAIL-WP-0007-T04/CSOC-WP-0010-T04/T05 obligations. Current receiver image\nand SMTP/sender/caller admission remain unchanged by source preparation.\n\n\n## T06 \u2014 Prepare atomic pair custody and its admitted front door"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0053-T06",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "ce950b3c-1ca6-5b01-bf2a-d958cafaed25",
|
|
"body": "2026-10-08 delivery preparation exposed a concrete custody gap: Warden's generic\npaste-once desk performs a single-field KV PUT, replacing the whole record. Two\nruns at one path discard the first field. Prepare a platform-owned pair-aware\ncustody procedure and reviewed writer identity/front door for the two new records,\ninitial CAS=0, both AWS fields in one atomic write, no secret argv/output/files,\nbounded auth/self-revocation and metadata-only KV-version evidence. Do not use\nthe read-only delivery role, the structure-only administration lane, a generic\nagent read grant, a retired ops-mason builder grant or two single-field desk PUTs.\nDesign/implementation can progress independently; actual provider key provisioning\nneeds its exact owner-reviewed attended custody act. This is a live handoff from\nWARDEN-WP-0043 and the credential-delivery preparation, not a hidden prose residual.\n\n## 2026-10-08 \u2014 Credential delivery preparation\n\nDraft CCR-2026-0036 and CCR-2026-0037 now bind separate application KV paths,\nfive-minute/four-use native readers, exact namespaces/ServiceAccount/audience and\nroot-owned private delivery files. Both remain draft/unconfirmed, with no reviews\nor native admission evidence. Their read policies match the existing generator;\nvalidator errors and delegated-applier scope violations are empty, with expected\nunconfirmed-binding warnings. Proposed ServiceAccounts disable automount and have\nno new RBAC grants. No existing credential, Secret or cluster object was read or\nchanged.\n\nscripts/application_backup_credentials.py previews without effects and performs\nonly admitted, source-hash/KV-version-pinned node reads; token revoked before atomic\nno-overwrite private publication, readback equality, metadata-only receipts. It\nrefuses source/scope/version drift, dangerous files, injection, unconfirmed revoke\nand a different existing file. A separate YAML-to-public-JSON exporter preserves\ncanonical source updates while keeping the node helper dependency-free. Thirty\nsynthetic delivery cases, four export cases and thirty primary/retention cases\npass; none establish live authorization. Review:\ndocs/credential-lane-designs/application-backup-delivery-2026-10-08.md.\n\nWARDEN-WP-0043 fixes administration/provisioning intent collisions with surveys;\ninstalled Warden was rebuilt, phase-memory retained, current catalog hash\n5e6b217aa1f6 verified. Surveys now point to ops-mason-survey per MASON-IN-0004.\nStructure requests require attended OIDC; pair provisioning is only a generic\nplatform pointer until T06 supplies the correct custody contract. T01/T02/T03/T05\nremain open; no credentials delivered, productive capture/upload or timer enabled.\n\n## 2026-10-08 \u2014 Pair writer preview\n\n`scripts/application_backup_pair_custody.py` previews both draft CCRs. The\nintended writer policy is `backup-pair-writer` and The founder admitted this writer on 2026-10-08, using the words\n\"bucket-pair-writer\". The policy name remains `backup-pair-writer`\n(`openbao/policies/backup-pair-writer.hcl`). The installed policy matches\nthat file, and `WRITER_ADMITTED` is true. Both backup-primary KV paths were absent. Version 2 is current on each path. Both pairs replaced the placeholder and\ndiffer from each other. The values were not read out. The bucket policy now keeps those three statements and adds the coulomb-social\nand email-connect publisher statements. Each new key aborted its own multipart\nupload and was denied the sibling prefix, the apps-pg prefix, and object\ndelete. No completed object was stored. The bootstrap key cannot list\nIAM applications (403). The live bucket\npolicy still names only application ee80333e-5bab-4a04-85a9-5bdb46b7b3c1 on\n`platform-pg/*`. No publisher key was created. T05 stays wait for the two\nconsole-created applications and their CAS=0 pairs. An admitted writer, covered\nonly by a synthetic transport, must present that one policy, TTL at most 5\nminutes and at most 2 uses, prove metadata absence, send both AWS fields in one\n`cas: 0` body, and revoke. Receipts contain no values. The delivery reader and\na one-field desk remain refused. No IAM application, provider key, OpenBao\nversion or node file was created. Review:\ndocs/credential-lane-designs/application-backup-pair-custody-2026-10-08.md.\nT05 stays wait for owner admission of the writer, prefix and escrow. T06 stays\nprogress until that attended act.\n\n## 2026-10-08 \u2014 Reader acceptance and email delivery\n\nFounder acceptance is recorded on CCR-2026-0036 and CCR-2026-0037 with both\nowner reviews, source ref founder-acceptance-2026-10-08, and confirmed\nKubernetes bindings. Attended platform-admin login installed both read policies\nand roles: one policy, backup-primary-delivery, matching namespace, ttl 300,\nfour uses, no default policy, service token. Both ServiceAccounts exist with\nautomount disabled. Live proof: each account read only its own version 2 pair\n(lengths 20 and 36), sibling read denied, email metadata/list/write denied,\ncross-namespace and wrong-audience login denied, tokens revoked. Email delivery\nadmission is true. Coulomb delivery admission stays false and\n/etc/coulomb-social-backup was not created. email-connect primary.env was\ncreated root:root 0600 under /etc/email-connect-backup mode 0700, outcome\ncreated, readback equal, KV version 2. No capture, upload, escrow or timer."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/railiance-platform/workplans/RPF-WP-0054-keycape-client-secret-generate-lane.md",
|
|
"meta": {
|
|
"id": "RPF-WP-0054",
|
|
"type": "workplan",
|
|
"title": "Broker lane keycape-client-secret-generate: generate KeyCape client secrets in custody",
|
|
"domain": "financials",
|
|
"repo": "railiance-platform",
|
|
"status": "active",
|
|
"owner": "claude-code",
|
|
"created": "2026-10-09",
|
|
"updated": "2026-10-10",
|
|
"state_hub_workstream_id": "73694adc-12a0-5226-a814-ee096d158f60"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "RPF-WP-0054-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "38f92db0-317e-5b2b-8bbd-b4af3272cc21",
|
|
"body": "Confirm with key-cape: client_id pattern (proposed `^[a-z0-9][a-z0-9-]{2,62}$`),\nfield name (`CLIENT_SECRET`, single field), secret length and alphabet (proposed\n48 random bytes, URL-safe base64 without padding, 64 characters), and that\nKeyCape reads it only through the ESO-delivered Secret. Confirm with ops-warden\nwhich identity calls the broker under its caller proxy, and how the accepted\ncase reference (case id + acceptance record digest) is passed. That reference\ngoes into the receipt and into OpenBao `custom_metadata` (non-secret).\n\n**Done when:** both replies are recorded here, with no open question about\nformat, field or caller.\n\n2026-10-09 ops-warden (`23985370`): the caller is the human operator who runs\n`warden case run`. Warden runs `credential.py generate` as a child process in\nthe caller's environment and holds no token or grant, so the caller's own OIDC\nsession is the acting identity. Warden refuses the step under `WARDEN_AGENT_ID`.\nThe case reference is `<case_id>@sha256:<hex64>` over the case file's exact\nbytes (`warden case plan` prints it). The platform must also take `--case-file`,\nre-derive the digest, and check that status is `materialized` and that\n`parameters.client_id` equals `--client-id`. The client_id pattern is taken from\nthe case type, `^[a-z0-9][a-z0-9-]{1,62}$` (authoritative; it replaces the\nproposal above). Still open: key-cape confirmation of length and alphabet,\nasked 2026-10-09.\n\n2026-10-10 key-cape (`4e0213b3`): format confirmed as proposed, 48 random bytes\nas URL-safe base64 without padding (64 characters) in the single field\n`CLIENT_SECRET`, read only through ESO Secret `sso/keycape-{client_id}-client`.\nKeyCape compares secrets as opaque strings in constant time and imposes no\nlength or alphabet limit. It requires only a non-empty clientId; the pattern\nbelongs to the case type. T01 is closed.\n\n## T02 \u2014 Decide the grant shape"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0054-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4183abc4-4acc-5937-9f27-005feb181025",
|
|
"body": "Two options, both create-only (ACL `create` without `update`, so an existing\nclient's secret can never be overwritten through this lane):\n\n- **A \u2014 one templated grant (recommended).** Grant `keycape/client-secret-generate`\n holds policy `keycape-client-secret-generate`: `create` on\n `platform/data/workloads/keycape/+`, `read` on\n `platform/metadata/workloads/keycape/+` (absence proof and version\n verification, no value), and explicit `deny` on existing reserved entries\n (today `keycape/secrets-engine-openbao`). The broker additionally refuses a\n client_id with no accepted case reference and refuses if metadata already\n exists. Each case needs no new policy or CCR; the reach is \"create any new\n KeyCape client path\", and the caller cannot read values.\n- **B \u2014 one exact grant per case.** Each case's `client-secret-path` artifact\n adds a create-only stanza for its own path, applied through a CCR before\n mint-secret. This keeps the tightest ACL, but every case needs an attended\n policy apply, which conflicts with `attended: false` for this step.\n\nRecommendation: A. Its widest misuse is creating an unused entry for a client\nthat does not exist. That cannot leak or overwrite a value, and metadata audit\nplus the case-reference check make it visible.\n\n**Done when:** the founder records the choice here (and on a State Hub decision\nif one is opened).\n\n**Decision 2026-10-09 (founder): option A**, one templated create-only grant\n`keycape/client-secret-generate` with the broker-side case-ref and\nabsence checks above. T04 implements it; per-case exact grants (B) are not\nbuilt.\n\n## T03 \u2014 Implement the broker generate operation"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0054-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"RPF-WP-0054-T01",
|
|
"RPF-WP-0054-T02"
|
|
],
|
|
"state_hub_task_id": "3e159e92-f5ee-5a92-b887-e06daf7dfbdb",
|
|
"body": "Add `credential.py generate --grant keycape/client-secret-generate --client-id\n<id> --case-ref <ref> [--receipt <file>] [--dry-run]`:\n\n1. Validate the grant, the client_id pattern, the reserved-entry denylist and the\n case-ref shape. Refuse wildcard, parent or extra segments.\n2. Obtain the grant's short-lived token through the existing lease path. The\n caller's identity is used, and the token is never printed.\n3. Prove absence: metadata read returns 404. Anything else refuses (exit 3 if\n present).\n4. Generate in process and write\n `{\"options\":{\"cas\":0},\"data\":{\"CLIENT_SECRET\":...}}` through stdin.\n5. Verify by metadata only: current_version 1, not deleted. Never read the data\n path. The case-ref goes in the receipt and the hub metadata, not in OpenBao\n `custom_metadata`: writing that needs metadata `update`, which would also let\n the token change `delete_version_after`/`max_versions` of other clients'\n entries (decided while doing T04, 2026-10-09).\n6. Revoke the lease. Write the receipt (0600, O_EXCL, versions, booleans and\n outcome only). stdout/stderr stay silent apart from the fixed outcome code.\n\nTests with a fake `bao`: success, already-present refusal, CAS-0 race loser,\nreserved path, bad client_id, missing case-ref, write failure, verify mismatch,\nsilence contract, and an assertion that no data-path read occurs. No secret\ntext appears in any receipt.\n\n2026-10-09 progress: `scripts/keycape_client_secret_generate.py`, reached as\n`credential.py generate --grant keycape/client-secret-generate --client-id <id>\n--case-file <case.yaml> --case-ref <ref> [--receipt f] [--dry-run]\n[--record-state-hub]`. It refuses agents, root, and callers without the issuer\npolicy. It verifies the case file as ops-warden specified, mints the 5m grant\ntoken, and makes every KV call with that token only. It proves absence, writes\nonce with CAS 0, verifies by metadata (version 1), revokes the token, and prints\nnothing. There are 8 offline tests. Remaining before done: key-cape's format\nconfirmation (`SECRET_BYTES` is the proposed 48 bytes, 64 URL-safe characters).\n2026-10-10: key-cape confirmed the format; `SECRET_BYTES` stays as is. T03 is done.\nThe live probe passed under T05. The first real run (Forgejo) needs the case\n`net-kingdom/security-cases/forgejo-netkingdom-oidc.yaml` to reach `materialized`\n(today `accepted`; ops-mason's step).\n\n## T04 \u2014 Grant, policy and token role source plus CCR"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0054-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"RPF-WP-0054-T02"
|
|
],
|
|
"state_hub_task_id": "74eb1309-df16-5163-9840-ffb88072d09e",
|
|
"body": "Add the grant to `credential-grants/catalog.yaml` (class per T02, TTL 5m, exec\ndelivery only, no response-wrap). Add the policy under `openbao/policies/`, the\nissuing token role, and a CCR for the attended apply. Agent boundary:\ncoding-agent identities keep `deny` on the keycape data paths. Check whether\nthe existing `agent-high-risk-boundary` lane entries need a `keycape/+` deny\nand run `make agent-high-risk-boundary-check`. `make credential-grants-validate`\nand the token-grant dry-runs must pass.\n\n2026-10-09 done: CCR-2026-0040 (request type `custody-generate-grant`,\n`scripts/broker_grant_lane.py`) writes the grant policy\n`keycape-client-secret-generate` (create on `keycape/+` data, read on `keycape/+`\nmetadata, deny on `keycape/secrets-engine-openbao`, revoke-self), the issuer\npolicy `credential-broker-keycape-client-secret-generate-issuer` and the token\nrole (5m, orphan, non-renewable, no default policy), then reads all three back.\nThe catalog grant is `pilot`/`approval-required`, exec-env only. The apply binds\nthe issuer policy to no identity, so it is inert until T01 names the caller.\nAgent boundary: no coding-agent policy grants any `keycape/` path, and the\ncreate-only grant is never attached to an agent identity. No new boundary deny\nis needed.\n\n## T05 \u2014 Attended apply and disposable probe"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0054-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"RPF-WP-0054-T03",
|
|
"RPF-WP-0054-T04"
|
|
],
|
|
"state_hub_task_id": "a21d1915-fee9-5c31-89e7-a4560c645950",
|
|
"body": "The CCR apply can run any time; it is inert until the issuer binding exists:\n\n```bash\ncd ~/railiance-platform\nexport BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200\npython3 scripts/credential-change.py approve CCR-2026-0040 --reviewer \"platform-owner, key-cape-owner (founder Bernd Worsch)\" --comment \"Approve create-only broker grant keycape/client-secret-generate (RPF-WP-0054-T02 option A).\" \\\n && warden access openbao-platform-admin-login --exec -- python3 scripts/credential-change.py applier-apply CCR-2026-0040 --confirm \"DELEGATED APPLY CCR-2026-0040\" --actor founder --record-state-hub --quiet\n```\n\n2026-10-09: CCR-2026-0040 applied by the founder at 17:19Z; readback matched for\nboth policies and the token role. The run then printed a traceback from the\nState Hub evidence step (KeyError on `openbao.auth` for a prefix lane), so warden\nrevoked the session. That was fixed and the hub event was posted afterwards. The\nOpenBao objects were complete before the crash.\n\n2026-10-10: the founder chose `net-kingdom-admins` + `aal2` for the caller.\nCCR-2026-0043 (request type `broker-issuer-binding`,\n`scripts/issuer_binding_lane.py`) adds OIDC role\n`credential-broker-keycape-client-secret-generate` on `auth/netkingdom`. It\ncarries only the issuer policy and has loopback callbacks, a 15m TTL, 8 uses and\nno default policy. The apply refuses unless the live issuer policy matches source.\n\nFounder session (probe uses a synthetic, founder-written case file; the real\nForgejo run waits for key-cape's format confirmation):\n\n```bash\ncd ~/railiance-platform\nexport BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200\n# 1. binding\npython3 scripts/credential-change.py approve CCR-2026-0043 --reviewer \"platform-owner, key-cape-owner (founder Bernd Worsch)\" --comment \"Approve issuer binding for keycape-client-secret-generate: net-kingdom-admins + aal2 (RPF-WP-0054).\" \\\n && python3 scripts/credential-change.py confirm-binding CCR-2026-0043 --reviewer founder --comment \"groups=[net-kingdom-admins] and /assurance/level=aal2, same binding as CCR-2026-0034.\" \\\n && warden access openbao-platform-admin-login --exec -- python3 scripts/credential-change.py applier-apply CCR-2026-0043 --confirm \"DELEGATED APPLY CCR-2026-0043\" --actor founder --record-state-hub --quiet\n# 2. probe case (synthetic, materialized, never registered in KeyCape)\nP=probe-secret-generate-20261010\ncat > ~/$P-case.yaml <<YAML\napiVersion: netkingdom.io/security-case/v0.1\nkind: SecurityCase\nspec:\n id: $P\n type: oidc-browser-relying-party@1.0\n status: materialized\n parameters:\n client_id: $P\n client_type: confidential\nYAML\nREF=\"$P@sha256:$(sha256sum ~/$P-case.yaml | cut -d' ' -f1)\"\n# 3. log in as the bound operator role (token goes to the bao token helper)\nbao login -no-print -method=oidc -path=netkingdom role=credential-broker-keycape-client-secret-generate\nG=\"python3 scripts/credential.py generate --grant keycape/client-secret-generate --client-id $P --case-file $HOME/$P-case.yaml --case-ref $REF\"\n$G --dry-run --receipt ~/$P-dry.json\n$G --receipt ~/$P-1.json # expect generated, kv_version 1\n$G --receipt ~/$P-2.json # expect exit 3, already_present\nbao token revoke -self\ncat ~/$P-dry.json ~/$P-1.json ~/$P-2.json\n# 4. remove the probe entry\nwarden access openbao-platform-admin-login --exec -- sh -c \"bao delete platform/metadata/workloads/keycape/$P >/dev/null 2>&1\"\n```\n\n2026-10-10 first probe: CCR-2026-0043 applied cleanly and the OIDC login\nsucceeded, but all three `generate` runs exited 4 (`grant_token_create_failed`)\nand the operator's `revoke-self` returned 403. Nothing was written. Causes: (1)\nthe role set `token_num_uses: 8`, and OpenBao refuses child-token creation from a\nlimited-use token. The role now uses 0, which the lane validator enforces. (2)\nThe issuer policy lacked `auth/token/revoke-self`; it is now added. Re-apply\nCCR-2026-0040 (issuer policy) before CCR-2026-0043 (role), because the binding\napply refuses unless the live issuer policy matches source.\n\n2026-10-10 second probe passed after re-applying both CCRs (09:15Z). The\ncaller token held only the issuer policy with num_uses 0. Results: dry-run\n`dry_run_would_generate`; generate `generated`, kv_version 1; second run exit 3\n`already_present`. The grant token was revoked every time, operator\n`revoke-self` succeeded, and no value was read. The probe entry was then\nmetadata-deleted. Receipts: `docs/evidence/2026-10-10-keycape-client-secret-generate-probe.json`.\n\nThe policy denials (data read, update, delete, other paths) were already proven\nby the CCR-2026-0040 readback and its policy tests. The probe proves the live\ncreate-once behaviour.\n\nRecord the receipts under `docs/evidence/`.\n\n## T06 \u2014 Hand the lane to ops-warden and net-kingdom"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0054-T06",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"RPF-WP-0054-T05"
|
|
],
|
|
"state_hub_task_id": "d7015584-3429-5f32-b4bc-0a9b64017c15",
|
|
"body": "Reply to ops-warden `d9f889b1` and ops-mason `789feb39` with the command, the\ngrant shape and the verification (metadata version plus capabilities, no value\nread). ops-warden catalogs the lane (pointer-only entry); net-kingdom can then\nplan NK-WP-0048-T06. Consider declaring the `c3.runtime-secrets` capability so\nthe case type can compose mint-secret instead of treating it as a follow-through\nstep (net-kingdom case README \"Known limits\").\n\n2026-10-10: ops-warden catalogued the lane as draft (ops-warden 0ae8a0e,\nplaybook `wiki/playbooks/keycape-client-secret-generate.md`) and activates it\nwhen platform confirms. Probe receipt sent. Activation is held until key-cape\nconfirms the secret format (T01/T03).\n\n2026-10-10: ops-warden activated the lane (ops-warden 6414252). The playbook\nleads with the issuer-role login, and `warden case check-type` reports\noidc-browser-relying-party 1.0 as plannable. WARDEN-WP-0044-T03 now waits only\non the Forgejo case reaching `materialized`. The `c3.runtime-secrets`\ncapability is left for a later declaration; mint-secret works as a\nfollow-through step. T06 is done.\n\n## T07 \u2014 Rotation lane (separate, later)"
|
|
},
|
|
{
|
|
"id": "RPF-WP-0054-T07",
|
|
"status": "wait",
|
|
"priority": "low",
|
|
"depends_on": [
|
|
"RPF-WP-0054-T05"
|
|
],
|
|
"state_hub_task_id": "d5f0beb6-54dc-502b-9c13-0cb6892ab87d",
|
|
"body": "Design `keycape-client-secret-rotate`: `update` with CAS = current version, an\nattended window coordinated with ESO refresh and the KeyCape restart, and\nrollback to the previous version. Only after one proven first-generation run.\nNot part of the mint-secret gate."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"net-kingdom": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0011-enterprise-federation-saml.md",
|
|
"meta": {
|
|
"id": "NK-WP-0011",
|
|
"type": "workplan",
|
|
"title": "Enterprise Federation & SAML \u2014 Expanded-Mode Keycloak Identity Broker",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "worsch",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-05-20",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "1075448f-d533-5f9e-94b7-c3adfe151a07",
|
|
"depends_on": [
|
|
"NK-WP-0003",
|
|
"NK-WP-0004",
|
|
"NK-WP-0006"
|
|
],
|
|
"supersedes_tasks": [
|
|
"NK-WP-0001-T05",
|
|
"NK-WP-0001-T06",
|
|
"NK-WP-0001-T07",
|
|
"NK-WP-0001-T08"
|
|
]
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0011-T01",
|
|
"state_hub_task_id": "a5807808-fb34-50de-8f67-9128011833d4",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"body": "**Decision record \u2014 expanded-mode adoption & federation topology.** Write\nan ADR (ADR-0009) capturing: the concrete trigger for switching a tenant\nfrom lightweight to expanded mode; whether Keycloak acts as an OIDC\nidentity broker, a SAML service provider, or both; the realm-per-tenant\ncandidate and its alternatives mapped onto `tenant:platform` /\n`tenant:coulomb`; how the Keycloak issuer\ncoexists with the KeyCape issuer (`kc.coulomb.social`) so applications\nstill target one IAM Profile contract; and the canonical hostname/issuer\nfor the broker. Resolve or supersede D2 from NK-WP-0001.\n\n## Admit the database consumer"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T02",
|
|
"state_hub_task_id": "2fe6f100-3a5d-563e-b033-7d7b846ae487",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"blocking_reason": "ADR-0009 adoption trigger absent; then railiance-platform/rapp-postgres must admit the database consumer and return backup/restore evidence.",
|
|
"needs_human": true,
|
|
"decision_id": "8a5d1eb8-b665-4d25-9742-a15ecfc87c0c",
|
|
"body": "**PostgreSQL `keycloak_db` on the existing operator.** Have railiance-platform\nand rapp-postgres admit a named Keycloak database consumer against the current\ndatabase catalog and isolation needs. Do not assume the historical NK-WP-0003\ninstance is the correct placement. Source credentials from OpenBao via ESO\ninto a K8s Secret. Confirm the existing backup schedule covers the new database and\nrun a restore drill for `keycloak_db` specifically.\n\n## Package the broker deployment"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T03",
|
|
"state_hub_task_id": "32d1411b-10a4-5a8b-8f43-99ac46d83908",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"blocking_reason": "ADR-0009 adoption trigger and named package/runtime owner absent; requires T02 database admission and governed OpenBao/ESO role plus immutable issuer assignment.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T02"
|
|
],
|
|
"body": "**Deploy expanded-mode Keycloak.** Build a custom image\n(`kc.sh build`, privacyIDEA provider JAR included only if T5 delegates MFA\nto privacyIDEA). Assign the package/runtime owner under ADR-0015 and deploy\nthrough its managed declaration on railiance01 behind Traefik +\ncert-manager at the issuer hostname from T1. Admin bootstrap secret and DB\nsecret come from OpenBao/ESO \u2014 never typed, never in git. Hostname\nstrictness + proxy headers configured for Traefik. Realm import is\nGitOps-friendly (realm JSON/CR in git).\n\n## Integrate an upstream identity provider"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T04",
|
|
"state_hub_task_id": "6697a994-7343-5ea8-8b37-bc3b921e5a9b",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"blocking_reason": "Named tenant/upstream IdP owner/federation need absent; requires admitted broker and owner-reviewed tenant-scoped claim mappings plus actual login evidence.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T03"
|
|
],
|
|
"body": "**Upstream federation.** Configure identity brokering for Entra ID (OIDC),\non-prem AD (LDAP user federation), and a generic SAML 2.0 IdP. Map each\nsource's claims/attributes into the NetKingdom IAM Profile shape: issuer,\naudience, subject, groups, **tenant**, and assurance evidence. Define the\nattribute/claim mappers and group\u2192role mapping. Verify a federated login\nend-to-end for at least the Entra ID path.\n\n## Define federated assurance"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T05",
|
|
"state_hub_task_id": "d845380d-3dbc-5e59-8f2b-5a4d1b32d89d",
|
|
"status": "wait",
|
|
"priority": "medium",
|
|
"blocking_reason": "Adoption trigger absent; requires per-IdP assurance trust mapping and reviewed privileged step-up delivery from issuer/package and access-engine owners.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T04"
|
|
],
|
|
"body": "**MFA / assurance source.** Decide and implement the assurance model: MFA\nenforced by privacyIDEA (via the Keycloak provider JAR + a \"privacyIDEA\nBrowser\" flow, carried over from NK-WP-0001) versus trusting upstream IdP\nMFA (e.g. Entra Conditional Access) and reflecting it as assurance\nevidence in the token. Require step-up for admin console and\nplatform-root-sensitive clients. Ensure assurance evidence is carried in\nthe IAM Profile token so flex-auth can gate privileged actions on it.\n\n## Verify IAM conformance and coexistence"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T06",
|
|
"state_hub_task_id": "9cb7fd93-c16e-5102-83ce-195b3aa87446",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"blocking_reason": "Requires admitted live broker, canonical tenant issuer selection and dedicated test-client conformance/coexistence evidence; adoption trigger absent.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T03",
|
|
"NK-WP-0011-T04",
|
|
"NK-WP-0011-T05"
|
|
],
|
|
"body": "**IAM Profile conformance & downstream coexistence.** Run IAM Profile\nconformance checks against the Keycloak issuer (discovery document, PKCE,\ntoken/claim shape, JWKS, userinfo). Verify an application configured for\nthe IAM Profile can authenticate against either the KeyCape or the\nKeycloak issuer per the T1 selection rule. Use the canonical\n`canon/standards/iam-profile_v0.3.md` contract and the executable suite in\n`tools/iam-profile-conformance/`. Document per-tenant issuer selection.\n\n## Enforce tenant and platform boundaries"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T07",
|
|
"state_hub_task_id": "38998c68-29bf-50d2-8c8d-0c75184d5833",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"blocking_reason": "Requires tenant-engine tier/issuer ownership and access-engine boundary/freshness enforcement evidence after adoption trigger and broker admission.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T03",
|
|
"NK-WP-0011-T04",
|
|
"NK-WP-0011-T05"
|
|
],
|
|
"body": "**Recursive tenancy & authorization boundary.** Implement T1's reviewed\nrealm/tenant topology with platform-root guardrails. If realm-per-tenant is\nselected, tenant admins manage only their realm; in every topology they\nmust not be able to alter IAM Profile semantics, the platform realm,\nfederation trust, OpenBao platform mounts, or audit retention (per the\nflex-auth/Topaz implications in the architecture doc). Confirm flex-auth +\nTopaz remains the PDP; if a Keycloak Authorization Services adapter is\nused at all, document it as a delegated, non-canonical adapter.\n\n## Prove recovery and audit delivery"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T08",
|
|
"state_hub_task_id": "e5f44ddc-9645-5f61-b84c-da5ab9cccb6d",
|
|
"status": "wait",
|
|
"priority": "medium",
|
|
"blocking_reason": "Requires admitted database/broker, named recovery and audit owners, off-host restore and observed audit/break-glass receipts; adoption trigger absent.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T02",
|
|
"NK-WP-0011-T03"
|
|
],
|
|
"body": "**Backups, DR, break-glass, monitoring, audit.** Only sanitized declarative\nrealm configuration belongs in git; keep credential-bearing exports in\nprotected backup custody; DB backup + restore drill (T2); break-glass admin path disabled-by-default\nwith alerting on use; Prometheus/Grafana for auth success/failure, MFA\nlatency, federation errors. Ship Keycloak events to the durable platform\naudit sink alongside flex-auth/Topaz/OpenBao records, with correlation\nids \u2014 satisfying the \"Audit sink\" and \"Break-glass\" rows of the\nproduction-readiness checklist.\n\n## Prove the isolation upgrade path"
|
|
},
|
|
{
|
|
"id": "NK-WP-0011-T09",
|
|
"status": "wait",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d9dc4292-6b66-5797-9ff9-a1a4a556278e",
|
|
"blocking_reason": "Requires named tenant and admitted package owner, canonical tier contract and isolated subject/issuer-preserving upgrade/rollback drill; adoption trigger absent.",
|
|
"depends_on": [
|
|
"NK-WP-0011-T03",
|
|
"NK-WP-0011-T07",
|
|
"NK-WP-0011-T08"
|
|
],
|
|
"body": "**Shared-realm to dedicated-instance upgrade (ADR-0009, decision 3).** Write\nthe owner-executed upgrade runbook and rehearse it in an isolated environment\nbefore any paid tier is offered. The drill must show issuer URL unchanged,\nevery user `sub` and federated link preserved, login working after cutover,\nrollback by re-routing during the retention window, and per-tier backup and\nrestore evidence. Coordinate with tenant-engine on deriving the tier from the\n`IAM` capability role; do not add an independent tier field.\n\n## Acceptance Criteria\n\n- A rehearsed shared-to-dedicated isolation upgrade preserves issuer and subjects.\n- An ADR records the expanded-mode trigger, federation topology,\n selected realm/tenant isolation model, and KeyCape/Keycloak issuer coexistence.\n- A federated user from at least one enterprise IdP (Entra ID) can log in\n and receive an IAM Profile-conformant token with tenant + assurance\n claims.\n- Keycloak secrets originate from OpenBao; none are bootstrapped from\n KeePassXC or committed to git.\n- flex-auth + Topaz remains the authorization decision point; Keycloak is\n not the canonical policy engine.\n- Tenant admins cannot cross the platform-root boundary.\n- Keycloak audit events land in the durable platform audit sink with\n correlation ids, and a DR/break-glass drill has passed.\n\n## Open Questions / Dependencies on Other Repos\n\n- **key-cape**: does coexistence require KeyCape changes, or can both\n issuers serve the same IAM Profile unchanged? (EP-NK-001 federation\n extension point.)\n- **flex-auth**: confirmed claim/decision-envelope contract for tenant +\n assurance evidence sourced from a federated token.\n- **railiance-platform**: OpenBao must expose a Keycloak auth role / ESO\n path before T3; unseal/break-glass story must be ready.\n- **IAM Profile spec**: resolved by NK-WP-0012. T6 consumes\n `canon/standards/iam-profile_v0.3.md` and\n `tools/iam-profile-conformance/`.\n\n## Infrastructure review \u2014 2026-09-28\n\nKeep in backlog until a named enterprise tenant, upstream IdP owner and\nconcrete federation need justify operating another issuer. No Keycloak\nDeployment appears in today's cluster inventory. Realm-per-tenant remains a\nproposal to evaluate in T01, not a requirement derived from current topology;\nprove its mapping to tenant-engine's canonical identity/lifecycle contract.\n\nThe live issuer is `https://kc.coulomb.social`; IAM v0.3 is accepted and v0.4\nstep-up is proposed. T01/T05/T06 must coordinate with NK-WP-0042 and preserve\nexisting issuer/subject account bindings, audiences and session/revocation\nbehavior. Do not infer equivalent assurance from an upstream MFA claim without\na reviewed trust mapping. The single-node cluster and single-instance database\nproviders offer no automatic HA guarantee. T02/T08 must name backup ownership,\noff-host custody and an isolated restore proof. OpenBao access is private via\nthe platform operator path. Resource placement, packaging and runtime\nexecution belong to their owners, not this canon repository.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md).\n\n## Dependency reconciliation \u2014 2026-10-03\n\nAccepted ADR-0009 decision1 prohibits starting T02\u2013T09 without the named\ntenant, upstream IdP owner and concrete unmet federation need. None is\nrecorded in this plan. Corrected active/todo to blocked/wait; T01 remains done.\nLocal preparation is complete in\n[expanded-mode admission requirements](../docs/architecture/expanded-mode-admission-requirements.md):\nowner deliverables, evidence gates, conformance limits and explicit resume criteria.\nNew federation owner task IDs await trigger and owner acceptance; no deployment\nor issuer selection is implied by this packet.\n\n## Machine-readable wait reconciliation \u2014 2026-10-03\n\nT02 is the adoption admission root: owner/sponsor Bernd Worsch must confirm\nall three accepted ADR-0009 triggers from real demand. The pending hub decision\n`8a5d1eb8-b665-4d25-9742-a15ecfc87c0c` records that demand is currently absent; it neither asks\nan agent to create demand nor grants a broker deployment. T02 also retains the\nsubsequent database-owner admission and backup/restore requirements. Once the\ntrigger exists, record actual owner task IDs before routing implementation.\n\nT03\u2013T09 now encode their concrete predecessor deliverables in `depends_on`.\nEvery path reaches T02; no terminal historical infrastructure plan substitutes\nfor adoption. Existing per-task owner commitments/evidence remain in the\nblocking reasons and admission requirements document. A deferred/declined\nadmission decision requires a deliberate retain/cancel review, not automatic\nresume. All eight tasks remain wait; the workplan remains blocked.\n\nKnowledge receipt: emergent-security 0.2.6 / start / verified-files /\norientation-only; digest\n`8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02`."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0022-railiance01-identity-cutover-and-coulombcore-retirement.md",
|
|
"meta": {
|
|
"id": "NK-WP-0022",
|
|
"type": "workplan",
|
|
"title": "Cut over NetKingdom identity to railiance01 and retire CoulombCore",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-07-27",
|
|
"updated": "2026-10-03",
|
|
"depends_on": [
|
|
"USER-WP-0020",
|
|
"NK-WP-0023",
|
|
"KEY-WP-0004"
|
|
],
|
|
"state_hub_workstream_id": "d76ddccc-00c8-548a-b141-2cd660fa38da"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0022-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "244ef874-8ee4-5969-bcbf-42a7cb47f246",
|
|
"body": "Capture secret-free inventories of deployments, image digests, configuration\nkeys, database schemas/counts, PVCs, ingress, certificates, backup schedules,\nDNS, and external consumers on both clusters. Identify the authoritative\nsource for every state set and record expected maintenance/write-freeze\nbehavior. Compare public JWKS fingerprints and all client registrations\nwithout printing private configuration.\n\nDone when every component and state owner has a source, destination,\nverification method, rollback source, and explicit decision on whether\nrailiance01 is already equivalent or requires migration.\n\n2026-07-28 DNS inventory: public resolvers show `auth.coulomb.social` and the\nnew `login.coulomb.social` alias at railiance01 (`92.205.62.239`). The\nfollowing names remain explicitly on CoulombCore (`92.205.130.254`):\n`bao`, `gitea`, `hub`, `lldap`, `pink-account`, and `pink` under\n`coulomb.social`. The last three are identity-cutover scope; Bao, Gitea, and\nHub must be handed to their owning workload cutovers before CoulombCore host\nretirement. Local resolver caches may temporarily retain the former\n`auth.coulomb.social` address.\n\nThe read-only comparison is recorded in\n`docs/railiance01-coulombcore-cutover-inventory-2026-07-28.md`. It confirms\nmatching public KeyCape JWKS fingerprints and matching declared\nAuthelia/LLDAP/privacyIDEA images, but independent PVCs and divergent LLDAP\ndatabase fingerprints. CoulombCore exposes PostgreSQL logical backups but no\nmatching LLDAP, Authelia, or privacyIDEA backup CronJobs; fresh protected\nsource backups remain a hard gate.\n\n2026-07-29 closure review: the subsequent backup, migration, dependency and\nconformance tasks used this inventory successfully. Every identity state set\nnow has an authority, protected rollback source and verification method; the\nremaining public names are tracked explicitly under T06 or their owning\nnon-identity cutovers. Inventory contract complete.\n\n## T02 - Prove recoverable backups before changing state"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "12658d0f-eee9-5553-92b6-956ccde094bf",
|
|
"body": "Create fresh, encrypted backups for CoulombCore LLDAP, Authelia,\nprivacyIDEA, `net-kingdom-pg`, KeyCape configuration/signing key, and required\nKubernetes Secrets. Preserve privacyIDEA encryption material with its\ndatabase. Validate backup manifests, checksums, custody, retention, and a\nnon-production restore drill. Never emit secret values into Git, State Hub,\nlogs, or chat.\n\nDone when restore evidence proves the migration can be reversed from\nindependent custody.\n\n2026-07-28: created the age-encrypted source set documented in\n`docs/railiance01-coulombcore-cutover-inventory-2026-07-28.md`. Checksums,\nage decryption, both SQLite integrity checks, PostgreSQL dump readability,\nprivacyIDEA archive readability, permissions, and plaintext cleanup passed.\nThe encrypted set was then copied to mode-`0700` independent custody on\nrailiance01 with mode-`0600` files and matching source hashes. A temporary,\nnon-networked PostgreSQL 16 pod restored the full dump and reproduced the\nexpected `interhub`, `privacyidea_db`, token, owner, realm, resolver, and policy\ncounts. The pod and transient restore log were removed automatically.\n\n## T03 - Reconcile persistent identity state onto railiance01"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "642cec3f-fd96-5c05-a37a-8696ed118811",
|
|
"body": "Under a bounded write freeze, compare and migrate the authoritative\n`net-kingdom-pg` data and any non-database LLDAP, Authelia, or privacyIDEA\nstate. Preserve user/group identifiers, password hashes, MFA token serials,\nrealms, resolver mappings, encryption keys, and audit-relevant timestamps.\nDo not blindly overwrite newer railiance01-only configuration such as the\n`rapp-qonto-client`; merge and verify it explicitly.\n\nDone when source/destination counts and semantic probes agree and restart\ntests pass on railiance01.\n\nPre-migration comparison proves this task is required: LLDAP is 4/7/7\nusers/groups/memberships on CoulombCore versus 3/7/3 on railiance01.\nCoulombCore privacyIDEA has one enrolled token, two realms, two resolvers, and\ntwo policies; railiance01 is empty. All privacyIDEA custody fingerprints\ndiffer, so its database and encryption/signing material must migrate together.\n\n2026-07-28: completed the bounded reconciliation documented in\n`docs/railiance01-coulombcore-cutover-inventory-2026-07-28.md`. Fresh encrypted\nsource and destination snapshots preceded all changes. LLDAP now contains the\nauthoritative `platform-root` identity and memberships plus preserved\nrailiance01-only users and tenant groups; disposable source lifecycle users\nwere excluded. privacyIDEA database counts and all matching custody\nfingerprints agree. Twelve nonempty interhub source-table digests agree while\nthe newer destination schema, migration ledger, and destination-only user were\npreserved. SQLite integrity, privacyIDEA HTTP, deployment rollout, and\npost-restart semantic probes passed. Transient artifacts were removed and\nCoulombCore writers remain frozen against divergence.\n\n## T04 - Align configuration, secrets, and internal dependencies"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8aab3b5d-ec9e-5bc0-a884-ee418e78d5f4",
|
|
"body": "Reconcile KeyCape, Authelia, LLDAP, and privacyIDEA configuration and secret\nreferences on railiance01 through approved custody lanes. Verify KeyCape uses\nonly railiance01 cluster-local dependencies, signing-key continuity is\npreserved, service clients remain registered, and no runtime dependency\npoints back to CoulombCore.\n\nDone when an automated dependency graph and negative search prove there are\nno hidden CoulombCore runtime dependencies.\n\n2026-07-28: added\n`sso-mfa/k8s/verify-identity-cutover-dependencies.sh`. Its live railiance01\nrun found no CoulombCore IP/host or public cross-cluster endpoint in decoded\nidentity Secrets, ConfigMaps, Deployments, or StatefulSets. It verified\ncluster-local KeyCape and privacyIDEA dependencies, retained user-engine and\nrapp-qonto clients, and Ready deployments. KeyCape signing fingerprints\nmatch. TLS-preserving direct resolution returned HTTP 200 with valid\ncertificates for `auth`, `login`, `lldap`, `pink`, and `pink-account`.\n\n## T05 - Run full pre-cutover identity conformance"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "a66acc29-33a7-5c20-8816-c3acedd6595d",
|
|
"body": "Using TLS-preserving direct resolution to railiance01, verify health,\ndiscovery/JWKS, authorization-code + PKCE login, MFA, tenant/group/role\nclaims, OpenBao OIDC login, `rapp-qonto` client credentials, wrong-secret and\nwrong-scope denial, logout/session behavior, and restart recovery. Include\nthe platform-root and Binky tenant paths without exposing tokens.\n\nDone when all critical human and service flows pass and rollback criteria are\nmachine-readable.\n\n2026-07-28 progress: the portal starts a KeyCape authorization-code flow with\nS256 PKCE, and KeyCape discovery/TLS is healthy at its canonical\n`kc.coulomb.social` issuer. `rapp-qonto-client` obtains a token only for\n`qonto:read`; a wrong secret returns 401 and excessive `qonto:write` returns\n400 without a token. The Binky administrator was created and provisioned\nthrough user-engine's deployed versioned API, producing a linked LLDAP\nidentity and `password_setup_required` state. This exposed and fixed newline\nnormalization for the portal's trusted proxy secret in user-engine\n`0ef2ae5`; 105 tests pass and the fixed image is live.\n\nThe missing SMTP dependency is now removed from the critical path by the\ndeployed NetKingdom-owned password setup surface. It issues 15-minute,\nsingle-use opaque links, revokes an older link on renewal, consumes before\ncalling LLDAP's official OPAQUE helper, and fails closed on restart. A\ndisposable-user conformance run proved renewal, validation, setup, LLDAP\nlogin, replay denial, and cleanup without emitting credentials. Human\nacceptance remains open only for Binky's user-chosen password, MFA enrollment,\nand final claim/denial checks; no operator-set password was substituted.\n\n2026-07-29 complete: platform-root completed password + OTP login and opened\nthe portal and OpenBao paths. Binky then completed reusable password setup,\nTOTP enrollment, and a fresh authorization-code login after the KeyCape\nrollout. The session verified the canonical issuer/audience, Binky tenant and\ngroups, tenant-admin role, AAL2 `pwd` + `otp`, and denial for platform and\nCoulomb administration. Together with the prior qonto positive/negative\nclient tests and TLS/discovery evidence, pre-cutover conformance passes.\n\n## T06 - Cut over remaining DNS with monitored rollback"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T06",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "fc9ed5fb-fd5c-5b04-990b-5a5b7f32fa0f",
|
|
"body": "Lower TTL where needed and move `auth.coulomb.social`,\n`lldap.coulomb.social`, `pink.coulomb.social`, and\n`pink-account.coulomb.social` to `92.205.62.239`. Confirm certificate,\ningress, resolver, and normal-DNS flows from multiple resolvers. Keep\nCoulombCore intact but prevent divergent writes during a defined observation\nwindow. Roll back DNS if critical authentication or MFA gates fail.\n\nDone when normal DNS consistently resolves to railiance01 and the observation\nwindow passes without fallback traffic or state divergence.\n\n2026-07-28: authoritative/public recursive DNS now returns railiance01 for\n`auth.coulomb.social`; `login.coulomb.social` was added as an Authelia ingress\nand trusted certificate alias. The complete portal \u2192 KeyCape \u2192 Authelia\nredirect reaches railiance01. LLDAP and both privacyIDEA names remain\nintentionally on CoulombCore pending the state and conformance gates above.\n\n2026-07-30 recheck: normal resolution now sends `auth`, `login`, `pink`,\n`pink-account`, and `kc` to railiance01 (`92.205.62.239`). Only\n`lldap.coulomb.social` still resolves to CoulombCore (`92.205.130.254`);\n`bao` remains there intentionally and is outside this identity-workload\ncutover. No automated DNS credential lane is registered: `warden route find`\nreturned generic OpenBao/login/SSH routes, not provider DNS authority.\nConsequently T06 remains in progress on one explicit operator DNS change and\nits observation window, rather than being closed cosmetically.\n\n2026-07-30 completion: the operator moved `lldap.coulomb.social` to\nrailiance01. Normal resolution now sends `auth`, `login`, `lldap`, `pink`,\n`pink-account`, and `kc` to `92.205.62.239`; only the explicitly retained\n`bao`, retired `gitea`, and `hub` names resolve to CoulombCore. HTTPS probes\nfor Authelia, LLDAP, both privacyIDEA surfaces, and KeyCape discovery pass on\nthe public path. Direct TLS-preserving requests to the old IP return 404 for\neach identity hostname, proving the stale ingress has no functioning backend.\nThe observation gate therefore passes without fallback traffic.\n\n## T07 - Retire CoulombCore identity workloads reversibly"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T07",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "2a6d4c0b-2565-5bf5-9c04-1b63e992ce99",
|
|
"body": "After T01-T06, scale the old KeyCape, Authelia, LLDAP, and privacyIDEA\ndeployments to zero and suspend old backup jobs/ingress. Preserve manifests,\nPVCs, database, Secrets, and encrypted final backup during a rollback\nretention period. Confirm no DNS, ingress, client, monitor, or traffic still\ntargets the old services.\n\nDeletion of old workloads, PVCs, database clusters, or secret material is a\nseparate destructive action permitted only after the retention period and an\nexplicit recorded approval.\n\nDone when CoulombCore serves no identity traffic and remains recoverable\nduring the retention window.\n\n2026-07-30 inventory: legacy KeyCape, LLDAP, and privacyIDEA are already scaled\nto zero with their resources retained; only CoulombCore Authelia remains at\none replica. It must not be scaled down until the final LLDAP DNS record and\nT06 observation gate pass. The reversible retirement is therefore reduced to\none remaining workload plus stale ingress/backup checks.\n\n2026-07-30 completion: after T06 passed, CoulombCore Authelia was scaled to\nzero. KeyCape, LLDAP, privacyIDEA, and Authelia are now all zero replicas.\nNo legacy identity backup CronJobs remain present. Services, Ingresses,\nConfigMaps, Secrets, PVCs, TLS material, and source manifests were deliberately\nretained. Public identity probes still reach healthy railiance01 endpoints,\nwhile direct old-IP identity requests return 404. The reversible rollback\nwindow begins 2026-07-30; no retained state may be deleted under this task.\n\n## T08 - Final deletion and closure"
|
|
},
|
|
{
|
|
"id": "NK-WP-0022-T08",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "5d8dcdb5-6d7b-463e-bb39-0a4737331403",
|
|
"blocking_reason": "Explicit approval, rollback retention window expiry and one successful railiance01 restore/restart drill before destructive CoulombCore cleanup.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "42a3b4c0-3481-5cfa-bdc2-66d05e751829",
|
|
"body": "After explicit approval, expiry of the rollback retention window, and one\nsuccessful railiance01 restore/restart drill, remove the retired CoulombCore\nidentity resources and stale DNS/monitoring/configuration. Record what was\ndeleted, backup retention, recovery limits, final topology, and operational\nrunbooks. Run `statehub fix-consistency`.\n\nDone when railiance01 is the sole authoritative identity stack, all evidence\nis reconciled, and the workplan is marked finished.\n\nRetention minimum: 2026-08-29 has passed. The plan is no longer date-blocked.\nT08 remains blocked on a scoped retained-resource inventory, a successful\nidentity restore/restart receipt, and explicit destructive approval.\nElapsed retention alone does not authorize deletion or completion: T08 still\nrequires a successful railiance01 restore/restart drill and new explicit\napproval for destructive deletion.\n\n2026-10-03: human gate routed to hub decision 5d8dcdb5-6d7b-463e-bb39-0a4737331403 (D4: Destructive cleanup after retention expiry: CoulombCore remnants, railiance-master retention, live recipient removal) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Safety gates\n\n- No retirement before a tested backup and restore path exists.\n- No database overwrite before authoritative-source and divergence analysis.\n- No privacyIDEA restore without its matching encryption material.\n- No normal-DNS cutover before direct-resolution end-to-end verification.\n- No PVC/database/Secret deletion as part of the reversible retirement step.\n- Final deletion always requires an explicit human approval distinct from DNS\n cutover approval.\n\n## Infrastructure review \u2014 2026-09-28\n\nLive read-only inventory confirms the identity services on railiance01 are\nready. CoulombCore was not inspected in this review; do not infer that its\nretained resources have been deleted. Recheck the exact retained identity\nresources and backup custody before preparing the T08 deletion list. A generic\nplatform-pg recovery drill is not a restore of LLDAP, Authelia, privacyIDEA\nwith its encryption material, and identity database state. Whole-host retirement\nand other owners' workloads remain outside this identity-only deletion gate.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0027-reef-placement-reconciliation.md",
|
|
"meta": {
|
|
"id": "NK-WP-0027",
|
|
"type": "workplan",
|
|
"title": "Reconcile reef placement and security-zone canon dependencies",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "net-kingdom",
|
|
"topic_slug": "netkingdom",
|
|
"planning_priority": "P1",
|
|
"created": "2026-08-19",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "965ad365-6b81-50a1-a2a3-2d0c1fcce0b4"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0027-T01",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d88714a4-0bcb-567e-8542-d5b4c556b8ec",
|
|
"body": "**Establish the boundary between a reef and the `P` ladder in canon text.** Say\nwhat each answers, why a reef is not a `P` level, and which of `P`'s couplings\n(\u00a73.2) a reef binding does and does not satisfy. Do not extend the `P` ladder.\n\n**Done 2026-08-22.** Tenancy Posture Decision 8.4.2 now says explicitly that a\nreef binding records compute substrate and accepted residual risk, satisfies no\n`P` coupling by itself, and participates only as a possible `V` ceiling across\nthe critical path.\n\n## T02 \u2014 Extend provider declarations to reefs"
|
|
},
|
|
{
|
|
"id": "NK-WP-0027-T02",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:repo-manager",
|
|
"blocking_reason": "Requires repo-manager acceptance of the reef provider carrier/schema, then railiance-infra authored ceilings, conditions and evidence in the authoritative reef declaration.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "5b35b646-a525-55da-852a-6005613d42ea",
|
|
"body": "**Extend Decision 5.5's provider declaration to substrate providers, and agree\nit with `repo-manager`.** A reef should state, per axis it bounds, the maximum\nlevel it makes reachable and what a consumer must do to reach it \u2014 the same\nsentence `apps-pg` now owes its consumers. `reef-railiance`'s first line is\nalmost certainly a `V` ceiling. This is a proposal to `repo-manager`, not a\ncanon fiat: it owns the reef vocabulary and the acceptance record.\n\n**In progress 2026-08-22.** The canon-side boundary and proposed provider shape\nare ready. Agreement and the authoritative reef declaration surface remain with\n`repo-manager`.\n\n**Contract proposal 2026-08-22.**\n`docs/reef-posture-provider-contract.md` now proposes a `posture_provider`\nblock inside authoritative `declarations/reef.yaml`, reusing Decision 5.5's\n`available`/`maximum`/conditions/evidence semantics. For `reef-railiance` it\nproposes V0 available and V1 maximum: no unconditional reusable recovery\nguarantee exists, while a named workload can evidence restart/recreate recovery\ninside the one failure domain. The field name and reef-schema adoption remain\nsubject to `repo-manager` agreement.\n\n**Waiting:** `repo-manager` must confirm or amend the `reef.yaml` carrier,\nfield name, and conservative V0/V1 values. NetKingdom cannot make that\nreef-vocabulary decision on its behalf.\n\n## T03 \u2014 Reconcile reef ceilings mechanically"
|
|
},
|
|
{
|
|
"id": "NK-WP-0027-T03",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"NK-WP-0027-T02"
|
|
],
|
|
"blocking_reason": "Mechanical join of reef ceilings to consumer V declarations waits on T02.",
|
|
"priority": "low",
|
|
"state_hub_task_id": "e3f0bb0f-0c85-5cb9-a5ab-75f668cd3447",
|
|
"body": "**Join reef ceilings to consumer `V` declarations mechanically.** Waits on T02.\nDecision 8.2's pattern applies \u2014 the requirer asserts, the declarer declares,\na machine reconciles. Until then a consumer bound to a reef declares `V` with\nthe reef named as a synchronous dependency, which is already required by\nDecision 4.6.1 and is not being done.\n\n**Design advanced 2026-08-22.** The proposal defines a three-valued join:\n`satisfied`, `unsatisfied`, or `unknown`. It rejects claims above the reef\nmaximum, requires condition evidence above its unconditional available level,\nand composes V across synchronous providers. Implementation still waits on the\nauthoritative reef field name from T02.\n\n## T04 \u2014 Rule on zone policy subject and absence"
|
|
},
|
|
{
|
|
"id": "NK-WP-0027-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "132658cb-5ea0-528c-86e2-095254c36cd7",
|
|
"body": "**Rule on the security-zone policy subject and absence semantics for\n`ZONE-WP-0001-T03`.** Keep workload as the sole subject, define it broadly\nenough to cover operational/control-plane execution, and state whether missing\nidentity or membership may inherit a zone.\n\n**Done 2026-08-22.** Decision 5.6.1 defines operational execution units as\nworkloads, rejects lanes/actors/patterns as substitute subjects, and requires\nunresolved membership to return `unknown` without inference. A control may\napply an explicit fail-safe stance to `unknown`; it may not relabel it.\n\n## T05 \u2014 Broaden workload declaration coverage"
|
|
},
|
|
{
|
|
"id": "NK-WP-0027-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "d60e209d-3090-59e7-afc4-0a3780507403",
|
|
"body": "**Broaden authoritative workload declaration coverage beyond managed `rapp`\napplications.** In the `security-zones_v0.1` publication review, require a\nstable workload identity and responsible party for operational/control-plane\nunits, and a machine-readable join from credential/control resources to the\nworkload they serve. Require the authoritative rapp declaration for managed\ndeployables, but do not invent a workload or rapp for native non-workload\nsubjects or independently governed units that are not managed deployables. Do\nnot infer the join from path strings or repository ownership. Coordinate the\ndeclaration boundary with `zone-engine`, `repo-manager`, and the affected\ncontrol owners.\n\n**Done 2026-08-22.** Tenancy Posture draft-12 Decision 5.6.2 and its schema now\nrequire `workload_identity` whenever a `zones:` block is present. The binding\nnames the stable workload id, kind, responsible repo, and one or more exact\nauthority/subject/principal-type tuples. Multi-service declarations carry both\nfields per service; top-level multi-service membership is rejected. Following\nRMGR-ADR-004, every managed deployable uses its authoritative rapp declaration\nand consumer references use `(rapp_id, workload_identity.name)` plus optional\n`deployable`. Only a non-managed operational execution unit declares locally;\nnative actions, actors, lanes, patterns, and resources are explicitly\n`not-applicable`, while omissions stay `unknown`. The published\n`canon/standards/security-zones_v0.1.md` proposal now has a closed schema shape\nfor its five memberships, admission context, evidence, and review dates. The\nvalidator rejects service/id mismatch, duplicate bindings, and invalid review\nwindows; tests cover missing identity and a valid operational workload.\n\n## T06 \u2014 Resolve the `DataClassification` mismatch"
|
|
},
|
|
{
|
|
"id": "NK-WP-0027-T06",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:info-tech-canon",
|
|
"blocking_reason": "Requires InfoTechCanon ruling on public disclosure classification versus synthetic provenance, then ops-warden authoritative dataclass_floor mapping and tests; no public-to-synthetic alias.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "bf8b3e1d-7ee0-5ad0-8705-5a580a9fb546",
|
|
"body": "**Resolve the `DataClassification` vocabulary mismatch surfaced by\n`ZONE-WP-0001-T03`.** `rapp-policy-nexus` declares `public`, while ops-warden's\n`dataclass_floor` maps only `synthetic`, `internal`, `confidential`, and\n`restricted`. Do not alias `public` to `synthetic`: public describes disclosure\npolicy, while synthetic describes data origin and whether values are real.\nRoute the vocabulary decision to `info-tech-canon`, which owns\n`DataClassification`, and then update the workload-maturity mapping with its\nruling. Until the mapping is authoritative, a compiler must report the maturity\nfloor as unresolved rather than guess.\n\n**Routed 2026-08-22.** The mismatch and non-equivalence are confirmed; owner\nconsultation is sent and the downstream mapping is pending.\n\n**Waiting:** `info-tech-canon` owns `DataClassification` and must rule its\nordering relative to synthetic-data provenance. The proposed downstream\n`public -> M1` mapping remains explicitly non-authoritative until that answer.\n\n## Current gate\n\nThe zone-engine publication candidate at `a510393` has been reviewed and\npublished as the proposed NetKingdom `security-zones_v0.1` standard. All\nlocally actionable canon and schema work is complete. The remaining chain\nis externally owned:\n\n1. `repo-manager` agrees or amends the `reef.yaml` provider carrier (T02).\n2. NetKingdom implements the mechanical reef ceiling join against that accepted\n carrier (T03).\n3. `info-tech-canon` rules the `public`/synthetic relationship, after which\n ops-warden can update `dataclass_floor` (T06).\n\nThe workplan is `blocked` rather than left nominally active with every open task\nat `wait`. No human intervention is required yet; owner responses are the\nordinary next input.\n\n## Related\n\n- `canon/standards/tenancy-posture_v0.1.md` Decisions 4.6.1, 5.5, 8.4.1, 8.4.2\n- `repo-manager/docs/RailianceAppDeploymentGuide.md` \u2014 reefs, `bound_reefs`\n- `railiance-master/docs/adr/ADR-0006-reef-production-admission.md` \u2014 topology\n is not readiness\n- `zone-engine/workplans/ZONE-WP-0001-security-zone-model.md` \u2014 where the\n question came from, and why it is not answered there\n- `zone-engine/docs/exception-lifecycle-2026-08-22.md` \u2014 already requires\n authoritative workload ids and fail-safe exception evaluation\n- `docs/reef-posture-provider-contract.md` \u2014 concrete T02/T03 carrier and join\n proposal awaiting reef-owner agreement\n\n## Infrastructure review \u2014 2026-09-28\n\nThe current `reef-railiance/declarations/reef.yaml` still has no\n`posture_provider` block. Its `ownership_repo` is `railiance-infra`: involve\nthat substrate owner alongside repo-manager (carrier/schema) in T02. The live\ncluster has one Ready node; all eight CNPG clusters report one instance. This\nsupports retaining the single-failure-domain constraint, not assigning a new\nV level from replica counts. T02/T03 stay `wait`.\n\nInfoTechCanon Data Model \u00a711.23 explicitly lists `public`; ops-warden\n`registry/policy/security-posture.yaml` still has no public maturity floor.\nThe missing artifact is an owner-agreed mapping separating disclosure class\nfrom synthetic provenance, not proof that public exists. T06 stays `wait`;\nno `public -> synthetic` alias or guessed M1 floor is permitted.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0031-deterministic-posture-feedback.md",
|
|
"meta": {
|
|
"id": "NK-WP-0031",
|
|
"type": "workplan",
|
|
"title": "Implement deterministic posture and evidence feedback",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "netkingdom",
|
|
"planning_priority": "P1",
|
|
"created": "2026-08-23",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "9d7b04f9-3803-5613-b7a5-8bd606c77f5a"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0031-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "917f8856-091e-59f9-b9e4-71a8c9a0d029",
|
|
"body": "Extend Tenancy Posture declarations with optional authoritative repository and\nevidence-freshness metadata. Define deterministic time, owner resolution,\nfinding severity, stable identity, and the proposal-only safety boundary.\n\nImplemented in Tenancy Posture draft-14, Posture Feedback v0.1, and their\nschemas. Missing authoritative ownership or freshness resolves to `unknown`;\nsource-path normalization never becomes owner inference.\n\n## Implement the posture feedback evaluator"
|
|
},
|
|
{
|
|
"id": "NK-WP-0031-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "63486c21-2ca2-5930-bc27-f8acde3eec8f",
|
|
"body": "Validate declarations and emit deterministic JSON findings for overdue/due-soon\nreviews, unknown/expired/due-soon evidence, implemented-but-unevidenced levels,\nand declared gaps. Require explicit `--as-of`; never perform external writes.\n\nImplemented under `tools/posture-feedback/`. The emitted report declares that\nexternal, policy, and declaration writes are all forbidden.\n\n## Publish reference workflow and tests"
|
|
},
|
|
{
|
|
"id": "NK-WP-0031-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0372c168-b34d-5ad5-8315-be3af74758de",
|
|
"body": "Provide an example declaration and cover freshness boundaries, missing owners,\nmulti-service inputs, stable digests, severity exit thresholds, and invalid\ndeclarations.\n\nThe checked-in expired-E2 example yields five deterministic proposals at its\nfixed evaluation time. Focused coverage includes every listed boundary plus\nportable source identity.\n\n## Obtain audit-core freshness adoption"
|
|
},
|
|
{
|
|
"id": "NK-WP-0031-T04",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:audit-core",
|
|
"blocking_reason": "audit-core tenancy.yaml must publish structured authoritative owner, observation/expiry and replacement-action metadata for WH-ENG-20260822-AUDIT-E2-03. Re-evaluate with explicit current as-of; later recovery prose does not renew E2.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "7d2029d2-db8d-526e-ab73-a0751becb193",
|
|
"body": "Ask `audit-core` to add authoritative owner and E2 freshness metadata for\n`WH-ENG-20260822-AUDIT-E2-03`. The evaluator must report its freshness as\nunknown until the source declaration supplies the exact timestamps and\nreplacement action; NetKingdom must not parse them from prose.\n\nRequested in State Hub message `874e5fa5-e05c-4b1a-a915-26c4dba07b87`.\nThe same estate baseline found pre-existing missing evidence entries for\n`railiance-platform` `apps-pg` current R2 and V1; that separate correction was\nrouted in `d65f8383-bdab-488e-a36f-f8cabd8a5f65`.\n\n## Verify and reconcile"
|
|
},
|
|
{
|
|
"id": "NK-WP-0031-T05",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "b646e6a0-20ba-5377-a3d1-7ae92eb9e936",
|
|
"body": "Run focused and repository regression tests, validate schemas and examples,\nreconcile State Hub, and publish the implementation evidence.\n\nVerification on 2026-08-23:\n\n- 28 focused posture-feedback and tenancy-validator tests passed;\n- 84 root tests passed with the independently packaged `local-identity`\n project excluded, then all 142 `local-identity` tests passed in its own\n environment;\n- both JSON schemas parsed, the fixed-time reference target succeeded, and\n `git diff --check` passed;\n- reuse-surface validated the capability registry entry; and\n- the read-only seven-declaration baseline is recorded in\n `history/2026-08-23-posture-feedback-estate-baseline.md`.\n\nLocal implementation is complete. The workplan remains blocked only on T04's\nexternally owned audit-core declaration adoption.\n\n## Infrastructure review \u2014 2026-09-28\n\n`audit-core/tenancy.yaml` still lacks machine-readable authoritative owner\nand E2 freshness metadata. Its E2 prose retains the August 22 receipt and\n24-hour replacement deadline; report freshness as `unknown` until the required\nfields exist, without renewing that evidence from prose. The September 24\nreceiver/database recreate evidence supports V1 only and cannot refresh E2.\nT04 remains `wait`; request the source declaration update and evaluate it with\nan explicit current `--as-of` before closure.\n\nThe same declaration still describes flex-auth as unauthenticated A0, whereas\ntoday all six live flex-auth Deployments pass `--caller-auth-mode enforce`.\nThe audit-core owner should reconcile that rationale against actual caller\nbindings and policy evidence; deployment flags alone do not prove a new A level.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0035-emission-cadence-security-profile.md",
|
|
"meta": {
|
|
"id": "NK-WP-0035",
|
|
"type": "workplan",
|
|
"title": "Publish the NetKingdom emission-cadence security profile",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "netkingdom",
|
|
"planning_priority": "P1",
|
|
"created": "2026-09-04",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"GH-DEC-2026-004",
|
|
"canon/standards/security-layer-model_v0.7.md"
|
|
],
|
|
"state_hub_workstream_id": "04685f94-1991-5e62-80d2-5669913e99fc"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0035-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "dc39bd1f-420d-55e9-b4d1-990c39dc251b",
|
|
"body": "Publish the NetKingdom MUST/SHOULD obligations over the generic contract:\nload-bearing classes declare cadence, attributive classes should, and rare\nload-bearing classes use heartbeat plus reconciliation with rate monitoring\nforbidden. Keep source classification owner-authored and preserve the residual\nthat cadence detects omission only after the fact.\n\nImplemented as proposed canon at\n`canon/standards/emission-cadence-security-profile_v0.1.md`. The profile accepts\nthe GH-DEC-2026-004 split, requires source-owned classification, distinguishes\nMUST from SHOULD coverage, and records that omission detection is after the\nfact rather than proof of completeness.\n\n## Implement mechanical profile validation"
|
|
},
|
|
{
|
|
"id": "NK-WP-0035-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0cdfbee7-f5cd-5a43-b27f-752cc72f56f6",
|
|
"body": "Validate a declaration against an explicitly supplied InfoTechCanon JSON\nSchema before applying the NetKingdom overlay. The checker must not ship a\nfallback generic schema, infer evidence class or rarity from event contents, or\ntreat a SHOULD finding as a MUST failure by default.\n\nImplemented at\n`tools/emission-cadence-profile/emission_cadence_profile.py`. It requires\n`--contract-schema`, performs generic validation first, then checks the\nNetKingdom overlay against caller-supplied source inventory assertions. No\ngeneric fallback schema or owner declaration instance was added here.\n\n## Verify the boundary and failure cases"
|
|
},
|
|
{
|
|
"id": "NK-WP-0035-T03",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "9cbfaed0-b827-58b3-a79d-2efebb69ed58",
|
|
"body": "Cover contract-first validation, missing and mismatched class declarations,\nthe allowed high-volume load-bearing rate form, the forbidden rare-event rate\nform, both positive controls for rare load-bearing classes, duplicate classes,\nand advisory attributive coverage.\n\nVerification on 2026-09-04: eight focused tests pass; the 81-test root\n`tests/` + `tools/` regression suite passes; Ruff lint and format checks pass;\nPython compilation and `git diff --check` pass.\n\n## Bind and hand off the published contract"
|
|
},
|
|
{
|
|
"id": "NK-WP-0035-T04",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:approval-engine",
|
|
"blocking_reason": "Approval Engine and Qonto owner declarations now pass the published schema and supplied-inventory profile; local-identity incompatibility is retained. Requires actual sender cadence mappings, lifecycle delivery/readback/reconciliation and Kings Guard operational feed evidence.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "e3fbc8b8-00d5-57ce-ba0c-19b58044c950",
|
|
"body": "When `info-tech-canon` publishes its versioned contract and schema, replace the\npending import locator with its canonical coordinates and digest, validate the\nowner-source instances, and notify `kings-guard` to replace its draft-shaped\nfixture. This task cannot be completed from NetKingdom without the upstream\nartifact and must not be worked around by copying the draft.\n\n2026-09-05 review: the upstream publication blocker is resolved by\nInfoTechCanon 0.7.0 / contract 0.1.0. Bound the profile to the schema coordinates,\nrevision and SHA-256; fixed the checker to read `extensions.netkingdom`, removed\ndraft reconciliation aliases, and enforced unique source IDs. Fifteen focused\ntests pass, including direct integration with the published owner schema and\nCLI exit-policy coverage.\n\nThe current owner instances (`approval-engine/cadence.yaml` and\n`qonto-assistant/specs/audit-emission-cadence.yaml`) were reviewed and checked;\nboth still fail generic contract validation because they use draft envelopes.\nNo source instance was rewritten by NetKingdom. T04 remains `wait` for each\nowner's migration and subsequent profile validation, followed by the King's\nGuard handoff. The profile remains proposed.\n\nValidation: `python3 -m pytest tests tools -q` passed 106 tests, including 18\nprivacyIDEA and 15 cadence cases. Ruff lint/format, shell syntax, embedded Python\ncompilation and `git diff --check` passed.\n\nState Hub reconciliation was attempted with both the installed CLI and current\ncheckout. Full reconciliation remains pending because API queries/writes timed\nout or returned connection-refused errors. Generated index/intake metadata was\nreviewed; the source files remain authoritative.\n\n### Import metadata reconciled \u2014 2026-09-28\n\nUpdated the importing profile to candidate document 0.2.0 / wire schema 0.1,\nreviewed contract revision `4d0851c3fca306538b53838421f4499baf352778`, and\nowner-published candidate bundle digest `b08b4d95fc4b0bd3`. Verified the schema\nSHA-256 remains `6d52692eb1e4d1325e0d6062d95acded98beddaae5bcfe24c6f0e91f1b6be6ae`.\nCorrected local-identity's current declaration pin and preserved the old pin\nwith its correction in the historical findings. No emission behavior changed.\n\nAll 15 focused cadence tests pass. Revalidation with the two source-owned\nrare-class assertions is generic-valid and still returns exactly two\n`rare-heartbeat-missing` findings. T04 remains `wait` for external source\nmigration, observer integration and the explicit local-identity incompatibility\nresolution; the profile remains proposed. Metadata repair is complete and does\nnot count as source/observer adoption.\n\n## Review the layer model's use of the profile"
|
|
},
|
|
{
|
|
"id": "NK-WP-0035-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8bcd9d33-0ffc-567e-96a3-b93dcd8059c7",
|
|
"body": "`gate-house` circulated `security-layer-model_v0.8.md` into this repository with\ntwo questions for the profile's owner: whether \u00a717's ownership paragraph says\nwhat NetKingdom would say in its own voice, and whether \u00a711's new\nemission-guarantee conformance item follows the profile or diverges from it.\n\n2026-09-07 review. \u00a717 is confirmed as written: it assigns the generic contract\nto `info-tech-canon` and to this repository the MUST/SHOULD split, the\nrare-class rate-monitoring prohibition, and the heartbeat-plus-reconciliation\nobligation \u2014 which is the profile's \u00a73, including the conjunction.\n\n\u00a711 diverged in both directions and was corrected in place. As first cut it\nrequired a detection surface of *\"heartbeat or reconciliation\"* of every\nload-bearing source: that withholds from a volume load-bearing class the\n`expected-rate` form the profile permits, and accepts for a rare class either\ncontrol alone where the profile and\n`tools/emission-cadence-profile/emission_cadence_profile.py` require both. It\nalso contradicted \u00a711's own following paragraph, which admits rate monitoring\nexcept where the class is rare. The item now defers the form to the governing\nprofile, carries the volume/rare split explicitly, and states that\nclassification is the source's to publish and never the checker's to infer.\nChange log item 6 and \u00a714 record the review; the standard remains `proposed` and\npublication waits on the close of the circulation round.\n\n## Infrastructure review \u2014 2026-09-28\n\nT04 remains `wait`, but upstream publication is no longer the blocker.\nThe current generic document is candidate 0.2.0 with wire schema 0.1;\nInfoTechCanon corrected the candidate bundle digest to `b08b4d95fc4b0bd3`\n(the wire schema was unchanged). Review and update the profile's old\ndraft/document/revision description and local-identity's stale bundle pin\nagainst the exact owner artifact before handoff; do not confuse a bundle digest\nwith the schema SHA-256.\n\nApproval Engine and Qonto still carry draft-shaped owner envelopes. In addition,\nNetKingdom now has its own source declaration at\n`local-identity/emission-cadence.yaml`: generic validation passed, but both\nrare load-bearing entries lack the required heartbeat. The source has no\naudit-core sender/feed; its findings also record dropped audit I/O errors and\nno completeness claim. Generic validity is not security-profile conformance\nor an operating observer result.\n\nExtend T04 acceptance to cover the local source explicitly: either implement\nand evidence activity-scoped heartbeat/reconciliation with its owners, or\nretain the documented incompatibility without claiming profile-wide adoption.\nResolve the declared heartbeat event class versus audit-core's registered\n`heartbeat_classes` mapping, migrate the two external owner instances, and\nobtain a real source/observer result before the King's Guard handoff. Keep\nthe profile proposed; no weakened rare-class conjunction is approved.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md).\n\n## Implementation follow-up \u2014 2026-10-03\n\nLocal audit I/O failures now emit a sanitized warning without interrupting\nbootstrap operations. All144 local-identity and27 cadence checker tests pass.\nThe source's missing heartbeat/feed remains an explicit incompatibility with\nno completeness claim; this diagnostic does not close operational adoption.\nSource-owner declaration migrations and King's Guard namespace integration are\ndelegated. Actual sender mappings and observed delivery/reconciliation/readback\nremain independently owned. T04 remains wait and plan blocked until these\nreceipts exist; the profile remains proposed.\nEvidence: [cadence adoption implementation](../docs/evidence/2026-10-03-cadence-owner-adoption.md).\n\nSource migrations applied and independently revalidated: Approval Engine and\nQonto are generic-valid and conformant for their explicit source inventories.\nLocal-identity remains generic-valid with exactly two rare-heartbeat-missing\nfindings. Retained reports: `docs/evidence/2026-10-03-cadence-owner-assessments.json`.\nOwner tests pass (Approval Engine169, Qonto90). These source checks remove the\nenvelope migration blocker, while actual operating observer acceptance remains\nunproved. Existing synthetic native Approval Engine delivery/readback receipts\nare retained; do not request identical synthetic checks as missing evidence."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0040-execution-attribution-receipt.md",
|
|
"meta": {
|
|
"id": "NK-WP-0040",
|
|
"type": "workplan",
|
|
"title": "Define an execution-attribution receipt for Railiance runs",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "claude-code",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-09-23",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"RCLK-WP-0002"
|
|
],
|
|
"state_hub_workstream_id": "e2533f3a-aa43-59b3-bff3-8e64b6149487"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0040-T01",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "9d02685a-a3d9-5b9f-b09e-aef1f196a97f",
|
|
"body": "Draft a v0.2 amendment that adds an execution-attribution receipt with these\nfields:\n\n- issuer and subject of the initiating actor\n- delegation reference (`actor_sub`/`act.sub`) when present\n- executing workload binding and runtime principal\n- tenant and environment\n- run ID\n- source commit and artifact digest\n- target inventory reference and action\n- decision and approval IDs\n- attributed time interval, with its clock source and bound when one exists\n\nThe receipt must never embed bearer credentials. Unknown attribution is kept\nexplicit, not inferred. Start from the field list in railiance-clock's review.\n\n**Done 2026-09-27.** Drafted as\n`canon/standards/playbook-capability-contract_v0.2.md` (status `proposed`,\nsupersedes v0.1, which stays `accepted` and normative until this is\naccepted). It adds an \"Execution Attribution Receipt (proposed)\" section\nwith every field above, explicit non-goals (no fourth IAM principal type,\nnot a decision record, not a substitute for responsibility claims), and the\nnever-embed-credentials / no-inferred-attribution rules. Emission, custody,\nschema, and validator are explicitly left to T02.\n\n## Agree the evidence holder and schema with audit-core and Railiance"
|
|
},
|
|
{
|
|
"id": "NK-WP-0040-T02",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:audit-core",
|
|
"blocking_reason": "Requires audit-core/Railiance owner agreement on emitter, evidence holder and receipt fields before local schema/validator implementation; then actual emission/readback and invalid attribution/clock/unknown-case evidence.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "963120c1-7c72-5806-942b-6f49e4c66e54",
|
|
"body": "audit-core holds evidence (layer model \u00a73.3, Evidence role). Railiance\nexecutes and emits. Agree who emits, who holds and how the receipt is\nvalidated. Add a schema under `canon/schemas/` and a validator beside the\nexisting playbook-capability tooling.\n\n**Waiting 2026-09-27.** Routed to audit-core (evidence-holder/schema\nagreement) and Railiance (emitter confirmation) via State Hub messages\n`48eb1101-a577-40c0-bbaa-39df02198155` and\n`4f1c67bc-8de2-483f-bcac-dbdf107ce95a`. NetKingdom adds the schema and\nvalidator once both reply; nothing here can be finished unilaterally\nwithout pre-empting their agreement.\n\n## Infrastructure review \u2014 2026-09-28\n\nUse accepted IAM Profile v0.3 and Playbook Capability Contract v0.1 as the\ncurrent baseline. Proposed IAM v0.4 and Playbook v0.2 are not deployed\ncapabilities. RCLK-WP-0002 still explicitly names this receipt as its dependency\non September 28. T02 remains `wait` for emitter and evidence-holder agreement.\n\nRequire the agreed schema to preserve unknown actor/delegation and clock\nbounds explicitly, correlate decision/approval/run/artifact identities, and\ndistinguish durable receipt ingestion from attribution proof. Reuse audit-core\nsender custody and reconciliation contracts rather than create another audit\nsink. Acceptance needs an actual Railiance-emitted receipt and audit-core\nreadback, plus invalid/missing attribution cases; schema validation alone\ncannot establish end-to-end attribution.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0042-workload-mfa-step-up.md",
|
|
"meta": {
|
|
"id": "NK-WP-0042",
|
|
"type": "workplan",
|
|
"title": "Let workloads require MFA for all or part of their features",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "claude-code",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-09-23",
|
|
"updated": "2026-10-09",
|
|
"related": [
|
|
"NK-ADR-0016",
|
|
"NK-WP-0037"
|
|
],
|
|
"state_hub_workstream_id": "3f702215-704b-5788-8ca0-b8b9ba2dd3f8"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0042-T01",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d66a6347-b714-5cca-aeb5-7121328f4dec",
|
|
"body": "Define how a workload requests AAL2: per client registration for the whole\nfeature set, or per request as a step-up when a protected feature is used.\nSpecify:\n\n- which OIDC parameter the request uses (`acr_values`, `max_age`, or both);\n- what KeyCape must return when a user has no factor (a clean refusal and an\n enrollment route, never silent AAL1);\n- how the resulting `assurance.level` reaches flex-auth.\n\nRecord it as an IAM Profile amendment. key-cape owns the implementation.\n\n**Done 2026-09-27.** Drafted as `canon/standards/iam-profile_v0.4.md`\n(status `proposed`, supersedes v0.3, which stays `accepted` and normative\nuntil this is accepted). The new \"Workload-Requested Step-Up (proposed)\"\nsection specifies `acr_values` carrying an `assurance.level` value\n(`aal2`/`aal3`) as the step-up request, `max_age` as an optional additive\nfreshness request that must never stand in for strength alone, the two\nconforming no-factor refusal shapes (inline enrollment detour or an\nexplicit `error=mfa_required`-class refusal, never silent AAL1), and that\nflex-auth keeps reading the issued `assurance.level` with no new claim.\nThe exact enrollment/recovery UX is left to T02, which this section names\nexplicitly.\n\n## Agree the user-facing step-up and enrollment journey"
|
|
},
|
|
{
|
|
"id": "NK-WP-0042-T02",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "cef97ccd-4ee7-40fe-859e-1df9c9360ecb",
|
|
"blocking_reason": "Founder decided the pilot (coulomb-social, MFA optional, no AAL2 switch-on); decision cef97ccd stays open for user-perspective acceptance in the attended U05-U08 session (USER-WP-0027-T04 / USER-WP-0028-T03).",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "4e51585d-2b57-56d4-84c1-314041d26bcf",
|
|
"body": "With user-engine (U06, factor recovery) and one pilot workload, agree what a\nuser sees when a feature needs MFA and they have none. That includes the\nenrollment detour, the return to the feature, and recovery. It must be\naccepted from a user's perspective before any workload turns the requirement\non.\n\n**Waiting 2026-09-27.** Routed to user-engine via State Hub message\n`892fd489-113d-4108-8048-727f4b0ed048`, referencing the T01 contract and\nasking for a proposed pilot workload and U06 touchpoints. This is a\nUX/product agreement across two repos and a pilot workload owner; NetKingdom\ncannot decide it unilaterally.\n\n2026-10-03: human gate routed to hub decision cef97ccd-4ee7-40fe-859e-1df9c9360ecb (D10: Identity record and MFA: accept NK-ADR-0017, choose the record read surface, agree the MFA user experience) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): gate re-checked, unchanged. The unread\nuser-engine message of 2026-10-03 (`db1b7d6e`, USER-WP-0026-T03) was about the\nworkload catalogue/admission and access-decision owner, not this journey; it\nwas answered (reply `19a0cbcd`: access-engine owns decisions, grants,\nrevocation and the protected-system registry; the catalogue is the onboarding\nbinding of access-engine protected system, key-cape OIDC client and user-engine\napplication record; NetKingdom only orchestrates). It does not settle T02. Our\n2026-09-27 request `892fd489` (pilot workload, U06 touchpoints) is still unread\nby user-engine, so `blocked_on: message-from:user-engine` stays real, and the\nfounder's acceptance under decision cef97ccd stays the human gate. The reply\nreminds user-engine of `892fd489`.\n\n2026-10-09: user-engine answered `892fd489` (message `a459e8a6`), as a proposal;\nthe pilot choice and the AAL2 switch-on stay founder decisions:\n\n- Pilot workload: `coulomb-social` (the current registration/onboarding client,\n owner of application action step-up). One non-privileged feature behind\n `acr_values=aal2`. Precedent: the user-engine portal's administration step-up\n (\"Verify with MFA\" -> `/login?recovery=1&return_path=...`, P06 recent-MFA\n guard, deployed).\n- Refusal shape: inline enrollment detour at the issuer; factor screens stay on\n the IdP and user-engine never collects an OTP or reads a seed. Fallback on an\n `mfa_required`-class refusal: link to the public user-engine `/security`\n page. Return means the workload re-requests with `acr_values`; a return URL is\n never proof of enrollment.\n- U06 touchpoints reused: `/security`; My account -> Sign-in security ->\n provider management (`USER_ENGINE_MFA_MANAGEMENT_URL`, deliberately unset\n until attended KEY-WP-0035 self-service checks pass); U07 lost device and U08\n replace/remove (replacement verified before removal, no bypass link; P04\n operator-assisted recovery); P06 policy preview/rollback so switching on does\n not lock out unenrolled users.\n- Constraint: user-engine's attended real-factor U05-U08 run\n (USER-WP-0027-T03 / USER-WP-0028-T03) is pending, and route\n `net-kingdom-privacyidea-admin-token` is still `resolvable: false`\n (railiance-platform). user-engine proposes running the pilot's\n user-perspective acceptance in that same attended session (enrollment detour\n -> return -> lost-factor recovery, end to end once).\n\nNetKingdom's reading: the proposal fits the T01 contract (issuer owns factor\nscreens, workload enforces issued assurance, return is not evidence). The\nmessage dependency is cleared; T02 stays `wait` on the founder under decision\ncef97ccd: choose the pilot, then accept the journey in the combined attended\nsession. Note that coulomb.social fits oidc-browser-relying-party 1.0 only partly\n(NK-WP-0048 README fit table), so the pilot's KeyCape `acr_values` handling is\nchecked on its existing registration.\n\n2026-10-09: founder decision, relayed by user-engine (message `60673e40`;\nrecorded in user-engine `docs/mfa-pilot-decision.md`):\n\n1. Pilot workload: `coulomb-social`.\n2. MFA stays in NetKingdom infrastructure: enrollment, verification,\n replacement, recovery and MFA-required policy live with KeyCape/issuer plus\n the provider factor and user-engine (`/security`, P04, P06). coulomb-social\n stays a plain OIDC relying party with no factor, enrollment, recovery or MFA\n policy code.\n3. MFA is optional for coulomb-social users: password-only stays valid (U05),\n enrollment is voluntary via U06, and the issuer enforces the factor once a\n user has enrolled (U07). No `acr_values=aal2` switch-on now.\n4. Admin-required MFA for coulomb-social users is deferred and not urgent; when\n wanted, it is an issuer-side client policy applied through the NetKingdom\n admin surface (P06 preview/apply/rollback), with a separate founder go.\n\nConsequence for this plan: the pilot proves the optional-after-enrollment\njourney, not workload-requested step-up. The T01 `acr_values` contract stays\nvalid but unexercised by this pilot. Not settled: decision `cef97ccd` stays\nopen for user-perspective acceptance, which runs in user-engine's attended\nU05-U08 session (USER-WP-0027-T04 / USER-WP-0028-T03) with a coulomb-social\nuser. T02 stays `wait` on that session.\n\n## Infrastructure review \u2014 2026-09-28\n\nBuild T02 on the already completed USER-WP-0033 and KEY-WP-0035 P06 work.\nTheir September 14 release evidence records optional-after-enrollment policy\nfor `user-engine-portal` and `vergabe-demo-company`, privileged MFA guards,\nconfirmed enrollment/cancellation and old-session checks. Do not rebuild\nthose capabilities or interpret this plan as the first delivery of MFA policy.\n\nThe residual is workload-level interoperability and an accepted pilot journey:\nagree the pilot owner, reuse U06 recovery, prove no-factor enrollment and\nreturn to the protected action, and test stale AAL1, refusal and provider\nunavailability. Existing scoped policy does not prove arbitrary-client\n`acr_values` support or acceptance of IAM v0.4. KeyCape owns issuer enforcement;\nuser-engine owns the journey; the workload and flex-auth enforce the issued\nassurance at the protected action. T02 remains `wait` for that agreement and\nactual-user acceptance, coordinated with KEY-WP-0034 / USER-WP-0028 /\nVERGABE-WP-0019, without reopening their completed provider work.\n\nEvidence and cross-plan priorities: [estate review](../history/2026-09-28-open-workplan-infrastructure-review.md)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/net-kingdom/workplans/NK-WP-0048-security-case-types.md",
|
|
"meta": {
|
|
"id": "NK-WP-0048",
|
|
"type": "workplan",
|
|
"title": "Establish SecurityCaseTypes so that known security cases are light",
|
|
"domain": "infotech",
|
|
"repo": "net-kingdom",
|
|
"status": "active",
|
|
"flavor": "implementation",
|
|
"owner": "claude-code",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-08",
|
|
"updated": "2026-10-09",
|
|
"depends_on": [],
|
|
"related_repos": [
|
|
"ops-mason",
|
|
"ops-warden",
|
|
"key-cape",
|
|
"railiance-platform",
|
|
"informed-decision"
|
|
],
|
|
"state_hub_workstream_id": "e31f3f9d-0748-5137-b0a3-7b3ca46a66eb"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "NK-WP-0048-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "930ac3e9-20ec-5473-98cd-3fe8fddb730f",
|
|
"body": "### T01 \u2014 Accept the terminology and the canon\n\nFounder review of `canon/standards/security-case-types_v0.1.md`, including its\nsection 10 open questions. On acceptance the canon status goes from `proposed`\nto `accepted`.\n\n2026-10-08: accepted by the founder (in session). Canon status `accepted`;\nsection 10's open questions are carried forward to the first type (T04, T05)."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "19c25d96-a55c-58f0-9168-3fdbc4955fc2",
|
|
"body": "### T02 \u2014 Inventory the de-facto types already built by hand\n\nRead-only. List every security integration built so far and group them by shape.\nKnown starting points:\n\n- browser OIDC relying parties on key-cape: informed-decision-approver,\n coulomb-social, user-engine portal, openbao-admin, and Forgejo (pending)\n- confidential service clients with `client_credentials`: secrets-engine\n approval, requester and openbao clients, approval-engine operator\n- workload KV read lanes on OpenBao: the railiance-platform credential lane\n designs and CCRs, for example `railiance-backup-offsite-lane`\n- short-lived SSH certificates through ops-warden (`warden sign`)\n- tunnelled operator access (ops-bridge)\n\nFor each: the repositories involved, the hand-built steps, attended human steps,\ncustody paths, verification evidence, and rollback (if any). Output\n`docs/security-case-type-inventory.md`, ranking candidate types by how often the\nshape recurs and how much manual work each instance costs today.\n\n2026-10-08: done, `docs/security-case-type-inventory.md`. 36 of 37 CCRs are\nalready `request_type: workload-kv-read`, a de-facto type reviewed each time as\nif it were new. Browser clients: 5 hand-built plus Forgejo, each with its own\nrollout script. Confidential service clients need a registration plus two or\nthree KV-read CCRs each. A forge read identity is needed in bulk by\nORGREF-WP-0002-T06. Recommendation: oidc-browser-relying-party first (unblocks\nthe forge), workload-kv-read second (largest payoff), then forge-read-identity."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T03",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"NK-WP-0048-T01"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "e487975b-73b1-516c-971d-da4cbbb93063",
|
|
"body": "### T03 \u2014 Schema, template and validator\n\n- `canon/schemas/security-case-type_v0.1.schema.json` and\n `security-case_v0.1.schema.json`\n- `security-case-types/_template/` with `type.yaml`, `README.md` and tests to copy\n- a validator, extending `tools/security-scenario-composer/`, that checks a type,\n checks a case against its type, and renders the case into the composer's\n deterministic plan (still `execution.permitted: false`)\n\nAcceptance: the validator rejects missing sections, secret-shaped parameter\nvalues, unpinned providers and cases against non-`implemented` types, with tests\nfor each.\n\n2026-10-08: done. `canon/schemas/security-case-type_v0.1.schema.json` and\n`security-case_v0.1.schema.json`; `tools/security-case-types/security_case_validator.py`\n(`validate-type`, `validate-case`, `render`, reusing the scenario composer);\n`security-case-types/_template/` (a valid, runnable example type over\n`net-kingdom.local-identity`, with README sections, an example case and tests that\ntravel with every copy). 31 tests pass, including the composer's existing suite."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T04",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"NK-WP-0048-T02",
|
|
"NK-WP-0048-T03"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "2fffe112-7d55-5680-9952-78d74f44f87f",
|
|
"body": "### T04 \u2014 Define the first type: browser OIDC relying party\n\n`security-case-types/oidc-browser-relying-party/`, version 1.0:\n\n- parameters: client id, display name, exact redirect URIs, scopes, client type\n (confidential or public), MFA pin, the groups the consuming service maps,\n custody path for the secret (confidential only), consuming service and its\n owner\n- composition: key-cape client registration (key-cape declares it as a playbook\n capability), secret minting into custody (railiance-platform), LLDAP group\n existence and membership (net-kingdom identity-provisioner), handover to the\n consuming service\n- materialization (ops-mason) and follow-through (ops-warden) sections\n- verification: discovery lists the redirect URI; a test sign-in returns the\n expected claims for one human; anonymous access to the custody path is denied\n- rollback: remove exactly this client and its custody path\n- README: threat model, MFA rationale, why redirect URIs are exact, which steps\n still need an attended login and how that is minimised\n- reference instances: informed-decision-approver, coulomb-social, user-engine\n portal, openbao-admin\n\nAcceptance: complete per canon section 3, tests green, status `proposed`.\n\n2026-10-08: done. `security-case-types/oidc-browser-relying-party/` 1.0 (proposed):\n`type.yaml` with 12 parameters (the custody reference is required only for\nconfidential clients), composition over key-cape's new\n`key-cape.oidc-client-registration` declaration (contract PASS, `maturity:\nplanned`), materialization and follow-through, verification and rollback, all\nconditional on client type where it matters. One attended step,\n`register-client`, justified by the live registry being a Kubernetes Secret.\nREADME with threat model, alternatives, an honest fit table (portal and vergabe\nfit; Forgejo is the first confidential case; openbao-admin, coulomb.social and\ninformed-decision-approver do not fit 1.0), and known limits. Examples: Forgejo\n(checked against the accepted request) and a public portal. The validator gained\n`when` / `required_when` conditions and provider discovery. 43 tests pass.\nops-mason's and ops-warden's sections are drafted in the type. Their owners\nreview them in MASON-WP-0010-T01 and WARDEN-WP-0044-T01 before acknowledgment\n(T05)."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T05",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"NK-WP-0048-T04",
|
|
"MASON-WP-0010-T01",
|
|
"WARDEN-WP-0044-T01"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "3d987d3d-0797-538b-86e4-51185a327ae2",
|
|
"body": "### T05 \u2014 Acknowledge the type through informed-decision\n\nPrepare the Decision Memo from the type's README and `type.yaml` and submit it\nthrough informed-decision's production intake. On acknowledgment the type\nmoves to `acknowledged`.\n\n2026-10-08: Decision Memo prepared. Hub decision `e418263e-a71f-4f01-a970-c87c9e187c09`.\n`security-case-types/oidc-browser-relying-party/decision/`: `packet.md` (question,\none act, what acknowledging does not do, the shape, alternatives, attended\nsteps, limits, evidence), `build_intake.py` and the built `intake.json` (memo\nclass `decision-record`, review group `net-kingdom-admins`, resolves the hub\ndecision on answer). The envelope passes informed-decision's own\n`validate_submission`. Queuing it is an attended operator step, a write inside\nthe production dispatcher pod:\n\n kubectl -n state-hub exec -i deploy/state-hub-memo-dispatch -- \\\n python -m api.services.memo_dispatch --queue /data/private enqueue --envelope /dev/stdin \\\n < security-case-types/oidc-browser-relying-party/decision/intake.json\n\nThe answer then appears for review in informed-decision.\n\n2026-10-08: queued by the founder (`pending`, `queued`) after one refusal: the\nfirst envelope's idempotency key was not State Hub's stable\n`state-hub.<decision>.<memo>` form, and the builder now validates against both\nsides. The dispatcher delivered it to informed-decision (ledger 7 \u2192 8\ndelivered). T05 waits for the founder's answer in informed-decision, which\nresolves hub decision `e418263e`.\n\n2026-10-08: ops-mason's review (MASON-WP-0010-T01) folded into the type, still\n1.0 `proposed`: `secret_ref` is no longer a parameter, the type derives\n`platform/workloads/keycape/{client_id}`; policies are\n`workload-kv-read-keycape-{client_id}-eso` and\n`workload-kv-read-keycape-{client_id}-{consuming_service}`, each with a templated\nbody (`read` on that one data path); new `openbao_role`\n`external-secrets-keycape-{client_id}` (Kubernetes auth, ESO service account,\n15m, no default policy); catalog entry `{consuming_service}-keycape-client`;\nthe two rollback steps on the KV path collapse into one metadata delete. The\nschema and validator now require a `body` on policy and role items. 105 tests\npass. Two consequences: the delivered memo describes the type before these\nchanges (a case-set custody reference, two differently named policies, no ESO\nrole), so the founder answers on a superseded shape unless the memo is\nre-sent; and Forgejo's custody path moves from the accepted request's proposed\n`platform/workloads/forgejo/netkingdom-oidc-client` to\n`platform/workloads/keycape/forgejo`, which key-cape (KEY-WP-0038) and\nrailiance-apps (RAPPS-WP-0016-T02) need to adopt in T06. ops-warden's review\n(WARDEN-WP-0044-T01) is still in progress.\n\n2026-10-08: revised memo `nk-wp-0048-t05-oidc-browser-relying-party-r2` built\n(`packet.md`, `intake.json`, packet `sha256:af6435e2\u2026`); it states that it\nsupersedes the first memo and passes informed-decision's and the dispatcher's\nvalidation. It needs a new memo id because the dispatcher refuses new content\nunder a delivered idempotency key (`idempotency_conflict`). Queuing it is the\nsame attended step as above. Both memos serve hub decision `e418263e`; the\nfirst answer resolves it, so the first memo must not stay open: an accept on it\nwould acknowledge the superseded shape, and a decline would resolve the\ndecision against r2. Close it with `return` (a reviewer verb that requests a\nnew revision and does not resolve the hub decision; only accept and decline\ndo), commenting that r2 supersedes it, then answer r2. `withdraw` exists in\nthe vocabulary but is not offered to reviewers, and lifecycle `revise` only\napplies to lifecycle-registered memos, not intake-delivered ones.\n\n2026-10-09: the founder reports r2 enqueued and the first memo returned. At\nclose, hub decision `e418263e` still showed `open` (not verified whether r2\nwas answered or the answer is still in transit; the dispatcher ledger was not\nread). ops-warden's review (WARDEN-WP-0044-T01, ops-warden\n`history/2026-10-08-oidc-rp-follow-through-review.md`, d470f2e) arrived at\n21:25, before r2 was built, and is not in r2. Required before WARDEN-WP-0044-T02:\nR1 a per-step `lane` (missing: identity-provisioner caller credential,\nrailiance-platform broker grant), R2 canon meaning of `warden_executes: true`\n(caller proxy, caller identity, no standing ops-warden token; ADR-0002), R3 a\nper-step `value_handling`. Refinements R4 (one type-level catalog lane instead\nof a per-case entry, which conflicts with ops-mason's item 5), R5 (ESO Ready gate\nbefore bind-env), R6 (exact accepted memberships), R7 (mfa-pinned and\nsecret-delivered checks). Next: if r2 was accepted, fold R1-R3 and R5-R7 in as\na follow-up and settle R4 between ops-warden and ops-mason before T06; if not,\nhold r2, fold them in and build r3.\n key-cape and railiance-apps were told about Forgejo's new custody\npath.\n\n2026-10-09: r2 was not answered (hub decision `e418263e` open; dispatcher 9\ndelivered), so r2 is held and r3 replaces it. ops-warden withdrew R4 for R4\u2032\n(message a66a9204): one catalog entry per case with its body templated in the\ntype. Folded in:\n\n- Canon section 3: a narrow meaning of `warden_executes: true` (caller proxy,\n caller identity, no standing credential; ops-warden ADR-0002), plus per-step\n `lane`, `value_handling` and an optional `ready_check`. A catalog entry body is\n now required, like policy and role bodies.\n- Schema and validator enforce all of these.\n- The type: lanes `identity-provisioner-groups` and\n `keycape-client-secret-generate` (both new) and `key-cape-oidc-login`;\n `mint-secret` is `generated_in_custody`; a Ready gate on `deliver-secret`;\n `ensure-groups` adds exactly the accepted case's memberships; new checks\n `secret-delivered` and `mfa-pinned`; the catalog-entry body follows R4\u2032.\n- 110 tests pass.\n\nMemo r3 (`nk-wp-0048-t05-oidc-browser-relying-party-r3`, packet\n`sha256:726dfc01\u2026`) passes informed-decision's and the dispatcher's validation.\nThe founder queues it with the same command, returns r2 with a comment that r3\nsupersedes it, then answers r3.\n\nPrerequisites for T06, not for T05:\n- the two new lanes, each through its owner;\n- a founder-approved rollout of an identity-provisioner image containing\n 630ebfd (the deployed one is main-6c4fcaf from 2026-09-24, without\n `/v1/groups/ensure`).\n\nops-mason's request to create LLDAP group `fluid-telegram-operators` (message\n259ec26d) was answered: not possible from here by that path; the founder creates\nit in the LLDAP admin UI.\n\n2026-10-09: ops-warden finished its side of WARDEN-WP-0044-T01 (message\n`58d33f40`, commit 0e7ceb8): the revised type conforms to `warden case\ncheck-type`, with no further changes asked of the type. This acknowledges that\nreview. Its later addendum R8 (message `af274783`, ops-warden\n`history/2026-10-08-oidc-rp-follow-through-review.md`) showed that lane\n`identity-provisioner-groups` cannot exist as declared: the provisioner's only\nHTTP credential is user-engine's runtime token, and its NetworkPolicy admits\nonly user-engine pods, so a caller-proxy lane would act as user-engine. Taken\noption 1 (ops-warden's recommendation): `ensure-groups` and its rollback are\nattended, in the `register-client` session on `key-cape-oidc-login`, run inside\nthe provisioner pod; no token is read. Option 2 (an operator credential of its\nown on the provisioner) stays open for a later version. `warden case\ncheck-type` now reports only `keycape-client-secret-generate`\n(railiance-platform) as missing. 89 tests pass.\n\nHub decision `e418263e` was still open, so memo r4\n(`nk-wp-0048-t05-oidc-browser-relying-party-r4`, packet `sha256:452ea421\u2026`)\nreplaces r3; it passes informed-decision's and the dispatcher's validation. The\nfounder queues it with the same command, returns r2/r3 if still open with a\ncomment that r4 supersedes them, then answers r4.\n\nPrerequisites for T06 are now: lane `keycape-client-secret-generate`\n(railiance-platform), and a founder-approved rollout of an identity-provisioner\nimage containing 630ebfd.\n\n2026-10-09: done. The founder queued r4 (`pending`, `queued`), returned r3 as\nsuperseded and accepted r4 in informed-decision. informed-decision's hub\nwrite-back is off in production (`INFD_HUB_WRITEBACK` unset), so net-kingdom\nresolved hub decision `e418263e` from the founder's report, naming memo r4 in\nthe rationale. The type is `acknowledged`; it becomes `implemented` with T06."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T06",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"NK-WP-0048-T05",
|
|
"NK-WP-0048-T08",
|
|
"NK-WP-0048-T09",
|
|
"MASON-WP-0010-T03",
|
|
"WARDEN-WP-0044-T03"
|
|
],
|
|
"blocking_reason": "Type 1.1, both light paths and the mint lane exist (RPF-WP-0054; CCR-2026-0040/0041/0043 applied). Waits on: CCR-2026-0042 consumer reader (in_flight, platform-owner review); the mint-secret run; ops-warden's run sheet (WARDEN-WP-0044-T03); then the founder's attended session (bind-env, ensure-groups, register-client with --check-config) in a quiet window.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "d9b26bcf-a7c6-59a2-92a0-f913d76a203c",
|
|
"body": "### T06 \u2014 First KnownSecurityCase: Forgejo\n\nWrite `security-cases/forgejo-netkingdom-oidc.yaml` from the parameters the\nfounder accepted in KEY-WP-0038-T01 (`key-cape/docs/forgejo-oidc-client-request.yaml`),\nso that acceptance carries over as the case acceptance. ops-mason materializes it;\nops-warden follows through and verifies it. The type becomes `implemented` once\nthis reference case is live.\n\nThis replaces the hand-built path proposed for KEY-WP-0038-T02.\n\n2026-10-09: case written, `security-cases/forgejo-netkingdom-oidc.yaml`, status\n`accepted`: the example's parameters plus the founder's 2026-10-08 acceptance of\nthe key-cape request (owner and founder), with the custody-path derivation\ncovered by the type's acknowledgment (memo r4). It validates and renders (plan\n`execution.permitted: false`; three attended steps on `key-cape-oidc-login`);\nit needs `--allow-unimplemented` until it is live, since it is the case that\nmakes the type `implemented`. A test keeps it equal to the type's example.\nStill open before it runs: ops-mason renders and builds it (MASON-WP-0010-T02,\nT03, unblocked by T05), ops-warden plans and runs it (WARDEN-WP-0044-T02, T03),\nrailiance-platform's `keycape-client-secret-generate` lane (asked by ops-mason\n`789feb39` and ops-warden `d9f889b1`, both unread), and a founder-approved\nidentity-provisioner rollout containing 630ebfd.\n\n2026-10-09: identity-provisioner rolled out, founder-approved in session:\n`main-630ebfd` (`sha256:bafb4860\u2026`, built by the image workflow) replaces\n`main-6c4fcaf` (`sha256:ffacd5d7\u2026`; only change: 630ebfd, additive). Applied\nwith `kubectl set image` on the Deployment only (generation 17 \u2192 18, 1/1 Ready);\nthe file's Service, NetworkPolicies and Ingress were not reapplied. Verified in\nthe pod: `ensure_service_groups` and `revoke_service_groups` present, `/readyz`\n200; no token used, no group changed. Rollback: `kubectl -n sso set image\ndeploy/identity-provisioner provisioner=forgejo.coulomb.social/coulomb/identity-provisioner@sha256:ffacd5d790a5b7800e0535f3aa95b7de52c7a68e4f575b9192c3e1622fa672c2`.\nThe pin in `sso-mfa/k8s/identity-provisioner/deployment.yaml` follows.\n\n2026-10-09: ops-warden closed WARDEN-WP-0044-T01 and shipped `warden case plan`\n(T02, message `06303d1d`); the accepted Forgejo case is refused until ops-mason\nmaterializes it, and a materialized copy plans cleanly once\n`keycape-client-secret-generate` exists. Its observation that `bind-env` carries\na literal `KEYCAPE_<CLIENT_ID>_CLIENT_SECRET`: the validator now renders a\n`{param:env}` format spec (upper case, `-` as `_`, as `keycape-client.py`\nderives the name) and rejects unknown specs, and follow-through and rollback\ntext is now checked for unknown placeholders too (patch-level, canon section 6).\nThe type keeps the literal until ops-warden's planner (`text.format`) renders the\nspec as well; asked of ops-warden. 53 tests pass.\n\n2026-10-10: ops-warden rendered `{param:env}` in `warden case plan`\n(23ba584, message `c1df14b7`; other specs and `!conversion` refused). The type\nadopts it as a 1.0 patch (canon section 6): `bind-env` and its rollback now read\n`KEYCAPE_{client_id:env}_CLIENT_SECRET`. ops-mason reports the Forgejo case\nrendered and built (message `1ebddae9`; CCR drafts handed to railiance-platform),\nso T06 now waits on the platform apply, the mint-secret lane and the attended\nregister-client session.\n\n2026-10-10: key-cape adopted the type's custody path (key-cape ab5cccd, message\n`88a4559c`): `docs/forgejo-oidc-client-request.yaml` and KEY-WP-0038-T02 name\n`platform/workloads/keycape/forgejo`, field `CLIENT_SECRET`, delivered as\n`sso/keycape-forgejo-client` through `external-secrets-keycape-forgejo`, and the\n`forgejo/netkingdom-oidc-client` proposal is withdrawn. This matches the type and\nthe Forgejo example; no change needed here.\n\n2026-10-10: key-cape's type-composition review (key-cape 6038483, message\n`8e5ed5f6`) found the composition sound with two blocking findings, taken as a\n1.0 patch (stricter validation and documentation, canon section 6):\nR1, redirect URIs now refuse `?` and `#` in the type pattern and in\n`keycape-client.py`'s `REDIRECT` (KeyCape refuses `?` at startup and the single\nreplica would stop); R2, `allowed_scopes` always includes `groups`, the renderer\nrefuses `access_groups` without it, and `access_groups` now says the consumer\nenforces the gate because KeyCape has none; R3, `mfa_required` \"false\" means the\nper-user privacyIDEA policy; R4, register-client's justification records the\nrestart for every client, the quiet window, and that the rendered registry must\npass KeyCape's client validation before it. The accepted Forgejo case and both\nexamples still validate; 116 tests pass.\nOpen, needs a decision: R2's verification step that the consumer enforces the\ngroup gate is a new verification step, hence 1.1 (minor), and the validator pins\ncases to the exact type version, so the accepted 1.0 Forgejo case would need\nre-pinning. Also open with key-cape: a KeyCape entry point that validates a\nrendered client registry without starting the server; until then\n`keycape-client.py` mirrors the redirect rule.\n\n2026-10-10: founder go for 1.1, so no 1.0 run overlaps. The type adds\nverification `consumer-enforces-groups`, and hand-over now requires the consumer\nto enforce `access_groups` (minor, canon section 6; risk class unchanged, no new\nacknowledgment; history in the type README). The accepted Forgejo case and both\nexamples are re-pinned to `oidc-browser-relying-party@1.1` before any apply; the\nacknowledgment intake keeps `@1.0` as the record of what was acknowledged.\nops-mason's build and ops-warden's case-ref digest predate this and need a\nre-render.\n\n2026-10-10: ops-mason re-rendered the Forgejo case from `@1.1` (message\n`22c6bba6`; plan digest `af1f4f81\u2026`, no collisions) and rebuilt the bundle. The\nrendered OpenBao objects are identical to 1.0, so the already applied\nCCR-2026-0041 stands; 1.1 changes only consumer-side steps. key-cape shipped\n`keycape check-config` (c528daa, message `a7b0aeff`): KeyCape's startup checks\nwithout secret values, including the new duplicate-clientId rule.\n`keycape-client.py --check-config <binary>` now runs it on the live and the\nproposed registry, fed on stdin, and apply refuses a proposed registry that\nfails; register-client's entry point names the option (1.1 patch). The deployed\nimage predates c528daa, so the binary is built from key-cape source for now.\nBefore the next KeyCape rollout (Forgejo register-client or the CCR-2026-0018\nwindow), the attended operator runs `inspect --check-config` so the live\nregistry is checked too."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T07",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"NK-WP-0048-T06"
|
|
],
|
|
"blocking_reason": "The next types follow once the first one is proven end to end.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "c3c9c3ae-4f23-5ba7-9e6f-e63bcf29b9f7",
|
|
"body": "### T07 \u2014 Queue the next types\n\nFrom the T02 ranking, open the next type drafts (likely the confidential service\nclient and the workload KV read lane), each to be acknowledged on its own.\nRecord which existing hand-built instances get adopted as cases, without\nrewriting them in place."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T08",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8e519082-dc8b-5e46-b660-03d03e55dcf6",
|
|
"body": "### T08 \u2014 identity-provisioner: ensure service-access groups\n\nThe type's `ensure-groups` step calls `identity-provisioner groups ensure --groups\n<list> --members <group=user+user;...>`. The provisioner already has idempotent\n`_ensure_group` and `_add_group`, but exposes only tenant-scoped operations. Add\nthe general operation (create if absent, add the listed memberships, never\nremove others), its rollback (remove only this case's memberships), tests, and\nthe ops-warden route for its service identity.\n\n2026-10-08: done. `identity-provisioner/provisioner.py` gained\n`ensure_service_groups` (`POST /v1/groups/ensure`) and `revoke_service_groups`\n(`POST /v1/groups/revoke`), behind the existing service-token check. Names\nmatching `tenant*`, `netkingdom-*` and `lldap_*` are reserved; members must\nalready exist; everything is validated before any change; memberships are read\nback before success; nothing else is ever removed; groups are deleted only when\nasked and empty. 7 new tests (39 in the provisioner suite). The type's\n`ensure-groups` step and its rollback now name these endpoints. The ops-warden\nroute for the provisioner's service token belongs to WARDEN-WP-0044-T01."
|
|
},
|
|
{
|
|
"id": "NK-WP-0048-T09",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0ee12dfc-8260-5038-bd39-cc7fb4113be0",
|
|
"body": "### T09 \u2014 The `keycape-client` entry point and its declaration\n\nPlanned first as key-cape KEY-WP-0038-T04. Moved here because the machinery a\nlive registration needs already lives in net-kingdom, where KeyCape is deployed\n(`sso-mfa/k8s/keycape/`): the contained kubectl, the cluster-identity pin and the\nissuer pin. A copy in key-cape would drift.\n\n2026-10-08: done. `sso-mfa/k8s/keycape/keycape-client.py` derives the KeyCape\nclient record from a case (`client-from-case`). It adds or removes exactly one\nclient with the existing safeguards (byte-preserving merge, exact match or\nrefuse, shared-reference refusal, compare-and-swap, read-back, contained errors),\nrequires the Deployment env binding first for confidential clients, and requires\nthe case acceptance record for `apply` instead of a per-client founder decision\nid. 15 tests, including a regression showing that the vergabe case reproduces\nits hand-built registration exactly; all 71 helper tests pass. Declaration\n`capabilities/playbooks/net-kingdom.keycape-client-registration.yaml` (contract\nPASS, `maturity: implemented`) replaces key-cape's draft. The type now pins it,\nand for confidential clients adds `deliver-secret` (delivery from custody into\nthe sso namespace) and `bind-env` (Deployment env), attended in the same session\nas `register-client`. The per-client helpers stay until their clients are\nadopted as cases."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"access-engine": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/access-engine/workplans/ADHOC-2026-10-03.md",
|
|
"meta": {
|
|
"id": "FLEX-WP-ADHOC-2026-10-03",
|
|
"type": "workplan",
|
|
"title": "2026-10-03 secret-read evaluator for ops-warden fetch checks",
|
|
"domain": "infotech",
|
|
"repo": "flex-auth",
|
|
"status": "blocked",
|
|
"owner": "claude",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-03",
|
|
"updated": "2026-10-04",
|
|
"state_hub_workstream_id": "60941288-d1f8-58fe-ad38-d508b7d5eac2"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "FLEX-WP-ADHOC-2026-10-03-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5c9ff3fa-7fb6-550a-862b-38aa7c0b5094",
|
|
"body": "Separate isolated pin `flex-auth-ops-warden-fetch` (one decision class per pin,\nFLEX-WP-0016):\n\n- `examples/ops-warden-fetch/`: package `ops-warden.secret.read` v1, registry,\n 15 fixtures, 6 Rego tests, check requests.\n- `values/ops-warden-fetch.yaml`: enforce; key-cape and railiance-platform bound\n to the ops-warden ServiceAccount.\n- `tools/gen_ops_warden_fetch.py`: generates the registry, `catalog_lanes` and\n the bindings from ops-warden's catalog; `--check` reports drift.\n- Chart `callerAuth.extraBindings`; `tests/stage1.sh` render and drift check.\n- `cmd/flex-auth/ops_warden_fetch_test.go`: decisions, caller bindings read from\n the values file, registry/policy parity.\n\n2026-10-03: `make ci` green; 12 lanes across 2 owner systems.\n\n## Deploy the pin (founder go required)"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-ADHOC-2026-10-03-T02",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"needs_human": true,
|
|
"blocked_on": "message-from:ops-warden",
|
|
"blocking_reason": "Pin is live (steps 1-5). Remaining: ops-warden token receipts and fetch URL (steps 6-7, WARDEN-WP-0039-T03); founder to resolve decision 877c268b for the install that already ran.",
|
|
"state_hub_task_id": "aa00b29f-fc1a-51e2-a373-0e3c72c1d6f4",
|
|
"decision_id": "877c268b-2089-42f1-a811-d98f549c1cb2",
|
|
"body": "Steps, none run yet:\n\n1. Push `main`; Forgejo `image.yaml` builds (trigger `examples/**`). Take the\n digest from \"Report immutable digest\" and set `image.digest` in\n `values/ops-warden-fetch.yaml` (the generator preserves it). Commit.\n2. Preflight on railiance01: CPU headroom\n (`kubectl describe node | grep -A4 \"Allocated resources\"`; the new pod\n requests 25m CPU / 32Mi), then a server dry-run of\n `helm template flex-auth-ops-warden-fetch charts/flex-auth -f values/ops-warden-fetch.yaml --namespace flex-auth`.\n3. Install on the node (`export KUBECONFIG=/etc/rancher/k3s/k3s.yaml`; chart and\n values copied with scp):\n `helm upgrade --install flex-auth-ops-warden-fetch charts/flex-auth -f values/ops-warden-fetch.yaml --namespace flex-auth --atomic`.\n `flex-auth-ops-warden` (signing) is not touched.\n4. Read the new Service ClusterIP (`kubectl -n flex-auth get svc flex-auth-ops-warden-fetch`).\n5. Workstation tunnel in ops-bridge (`~/.config/bridge/tunnels.yaml`), modelled on\n `flex-auth-ops-warden-railiance01`: name `flex-auth-ops-warden-fetch-railiance01`,\n host `92.205.62.239`, `remote_host: <ClusterIP>`, `remote_port: 8080`,\n `local_port: 19091`, health check `http://127.0.0.1:19091/healthz`; then\n `bridge up flex-auth-ops-warden-fetch-railiance01`.\n6. Probe with an ops-warden ServiceAccount token minted for audience `flex-auth`\n (as in FLEX-WP-0016-T03):\n `check_request_allow_forgejo_admin_api_token.json` \u2192 200 allow;\n `check_request_deny_unknown_need.json` \u2192 200 deny `unknown_need`;\n no token \u2192 401; `resource.system: ops-warden` \u2192 403.\n7. ops-warden points its fetch checks at `http://127.0.0.1:19091`, separate from\n the signing URL `:19090` (its side: WARDEN-WP-0039-T03).\n\nClose-down checklist row 1 (the-custodian) is updated by message, not by edit.\n\n2026-10-04 CUST-WP-0075 owner routing: `FLEX-WP-ADHOC-2026-10-03-T02` remains a human wait under open decision `877c268b-2089-42f1-a811-d98f549c1cb2`. Exact scoped human act and native receipts remain required; this metadata records no approval or execution.\n\n2026-10-04 blocked-task review: ops-warden message 26992e49 confirms its\nfetch/sign separation is implemented at 7d4381e (sync 88c22d4). The evaluator\ncode is already complete; do not repeat that implementation or fall back to\nthe signing URL. Remaining requirements are the exact CI digest/live install,\nops-bridge 19091 tunnel, configured policy.fetch_flex_auth_url and native\nhealth/positive/wrong-owner/fail-closed receipts under WARDEN-WP-0039-T03.\nDecision 877c268b-2089-42f1-a811-d98f549c1cb2 was checked and remains open.\nThis task and workplan stay blocked on the approved rollout; no live change was\nmade. Requirements are recorded in\n`docs/blocked-task-dependencies-2026-10-04.md`.\n\n2026-10-10 review: the earlier notes are stale. Steps 1-5 were done on\n2026-10-03 at 07:17 (`helm history`: `flex-auth-ops-warden-fetch` revision 1),\nyet the 2026-10-04 notes still say \"no live change was made\". Live image\n`sha256:419bc374\u2026` matches `values/ops-warden-fetch.yaml`. The Service has\nClusterIP `10.43.151.3`. Tunnel `flex-auth-ops-warden-fetch-railiance01` is\nconnected on 19091. From the workstation, `/healthz` returns 200 and an\nanonymous `/v1/check` returns 401. Nothing in this repo records who approved\nthe install, and decision `877c268b` is still open, so the founder must resolve\nit. Steps 6-7 belong to ops-warden: positive, wrong-owner and fail-closed\nreceipts with its own token, and `policy.fetch_flex_auth_url`. Its example\nconfig already names the in-cluster URL. The pin log has no decisions in 7\ndays, so ops-warden has not yet called it."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/access-engine/workplans/FLEX-WP-0020-repository-identity-migration.md",
|
|
"meta": {
|
|
"id": "FLEX-WP-0020",
|
|
"type": "workplan",
|
|
"title": "Repository identity migration from flex-auth to access-engine",
|
|
"domain": "infotech",
|
|
"repo": "flex-auth",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "codex",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-08-29",
|
|
"updated": "2026-10-04",
|
|
"reviewed_at": "2026-08-29",
|
|
"reviewed_by": "codex",
|
|
"reviewed_against_commit": "7d7b4531d15a2dde7aaa28b9360a13e77b28b2a9",
|
|
"reviewed_note": "Generated from live State Hub preflight 1243b1c9 and reviewed against the clean local checkout, matching origin/Forge head, Forge repository ID 42, FLEX-WP-0017/FLEX-WP-0019, three live NetKingdom deployments, and the repository-coordinate owners listed below. The plan remains proposed until State Hub preflight signing is provisioned and a fresh zero-blocker capture replaces this review baseline.",
|
|
"quality_dor": "DoR-Ok",
|
|
"quality_dor_at": "2026-08-29",
|
|
"quality_dor_by": "codex",
|
|
"quality_dor_note": "Tasks have explicit owners, gates, rollback boundaries, and verification evidence. DoR describes plan quality; it does not waive the captured signing blocker or the later human cutover gate.",
|
|
"state_hub_workstream_id": "99a661a8-b36c-5c1c-b78b-1e8930bcd0a9"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "FLEX-WP-0020-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "bb989019-50a7-5273-ba09-b2df2e2602a4",
|
|
"body": "Owner: `flex-auth`.\n\n- Require a clean target checkout and every branch/tag/change secured to Forgejo.\n- Record `git status`, branch, remote, source commit, default branch, Forge ID,\n visibility/readability, protected branches, releases, packages, hooks, deploy\n keys, Actions variables, and redirects.\n- Reconcile active work above: quiesce it or record an explicit concurrent-work\n decision. A moved source commit requires a new preflight.\n- If no registered path is visible, stop and register/verify a checkout; do not\n infer private Forge state from local Git.\n\nGate: repository UUID, Forge ID, branch, commit, and clean-state evidence are\nrecorded and match a fresh State Hub preflight.\n\n2026-09-15: captured in `docs/evidence/2026-09-15-repository-rename-baseline.md`.\nSigning is no longer a blocker. `safe_to_apply=true`, zero blockers, warning\n`active_work_present` disposed by `FLEX-DEC-2026-014`. A later commit still\nneeds a T05 preflight before `forge-renamed`.\n\n## 2. Prepare repository metadata and work-record frontmatter"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "102e9dc7-4724-5e80-84c4-092e6ecfbb2b",
|
|
"body": "Owner: `flex-auth`.\n\n- Prepare repository metadata, README/INTENT/SCOPE/AGENTS references, Forge\n description/topics, and canonical clone coordinates for `access-engine`.\n- Keep the established `FLEX-WP-` workplan/task prefix and all existing\n `state_hub_workstream_id` / `state_hub_task_id` values unchanged.\n- Do not mass-rewrite historical prose or old-slug provenance. New live\n frontmatter may adopt `repo: access-engine` only after State Hub rebind.\n- Commit preparatory source changes before the final preflight; record the new\n intended source commit.\n\nGate: work-record parsing succeeds and no existing UUID field was removed,\nreplaced, or invented.\n\n2026-09-15: README states the planned `access-engine` clone URL and that\nfrontmatter stays `repo: flex-auth` until rebind. No UUID fields rewritten.\n\n## 3. Decide product and runtime naming separately"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5095ddbc-b69c-5a52-b97f-08fca9b610c3",
|
|
"body": "Owner: `flex-auth`.\n\nThe reviewed initial decision is:\n\n| Surface | Initial decision |\n| --- | --- |\n| Forge repository name, canonical clone/web/raw URLs, local checkout, and current repository metadata | Rename to `access-engine` in the phased sequence. |\n| Workplan/task prefix and all State Hub UUID fields | Retain `FLEX-WP-` and every existing UUID. |\n| Go module/import path `github.com/netkingdom/flex-auth`, binary/CLI, and `FLEX_AUTH_*` variables | Retain. |\n| Kubernetes namespace, Deployments, Services/DNS, ServiceAccounts, RBAC, NetworkPolicies, Helm release/chart | Retain. |\n| Container package `forgejo.coulomb.social/coulomb/flex-auth`, immutable digests, and current CI `IMAGE_NAME` | Retain and verify publication after the repository rename. |\n| Policy/API vocabulary, audiences, dashboards, alerts, and telemetry service labels | Retain. |\n| Broader product rename | Defer to a separately reviewed workplan after soak; not authorized here. |\n\nAny change to a `retain` row expands the blast radius and returns this plan to\n`proposed` until the affected owner workplans, compatibility window, and\nrollback limits are reviewed.\n\nGate: every item has a decision record and independently deployable changes\nhave their own workplan or residual handoff.\n\n2026-09-15: accepted as `FLEX-DEC-2026-013` / hub `9f2dd7a4-6437-4e59-8403-ae56d9cc1d09`.\n\n## 4. Inventory consumers and create owned handoffs"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "9bb138e1-5edb-5714-8d89-3b1b7039a7ce",
|
|
"body": "2026-09-30: T04 closed. Every discovered external change has a named owning-repository handoff: net-kingdom replied (NK-WP-0039, message 92e9c4a5, deployments verified read-only, no runtime change); railiance-fabric RAIL-FAB-WP-0031, user-engine USER-WP-0034, ops-warden WARDEN-IN-0003, reuse-surface REUSE-WP-0023, and the intakes listed in the evidence file. Owners close their records after T06; that is their evidence, not this gate.\n\nOwner: `flex-auth` for inventory and handoff creation only.\n\n- Inventory CI includes/actions, package and image publishers, deployments,\n GitOps/Helm/Kubernetes references, credential routes (using `warden route`),\n authorization and NetKingdom policy consumers, fabric sources, SBOM scans,\n docs, badges, webhooks, mirrors, caches, dashboards, alerts, and local clones.\n- Start from the concrete owners and paths below. For each required source\n change, create a live residual/intake/workplan in that owner before T05.\n- Record each external work-record ID here and attach a\n `state-hub.repository-rename-handoff.v1` payload following\n `state-hub/docs/schemas/repository-rename-handoff-v1.schema.json`. It names\n the source repository, old/new slug, affected paths or graph IDs, required\n re-ingest and verification, owning workplan/task, and non-secret evidence.\n- Do not mark that external work done from this repository; completion evidence\n must come from its owner.\n- Include every row in the preflight risk register, even when it is only a\n warning or currently zero-count projection.\n\nGate: every discovered external change has one named owning repository and\ndurable handoff ID; unknown ownership blocks the live rename.\n\n2026-09-15: inventory in `docs/evidence/2026-09-15-repository-rename-handoffs.md`.\nOwner work-record IDs are requested, not invented. T06 stays blocked on those\nIDs plus the human confirm string.\n\n2026-09-20: first owner work-record returned. `reuse-surface` created\n`REUSE-WP-0023` (`65c03b24-4349-5a60-b7d6-79cf54931d06`, `active`) with\n`T01` `d97094d4-4cad-5b35-aa88-eb952215937a` and `T02`\n`77b1eb56-bbf6-5454-892f-bf60e32b864a`, both deliberately in `wait`. Recorded\nin the evidence file; not marked done from here. Verified independently: the\nhub record exists and is active, `access-engine` raw returns `404` while\n`flex-auth` returns `303`, so the rename has not landed and their refusal to\npre-rewrite the source URL is correct. It adds an ordering constraint this plan\nnow owns \u2014 the federation source rewrite follows T06 rather than preceding it,\nand `flex-auth` owes them a ping on message thread\n`82bfe60f-1258-4d5d-9b81-9596b5fedd9e` once `access-engine` serves\n`/raw/main/registry/indexes/capabilities.yaml`. Nine owners remain pending.\n\n2026-09-21: two more owner records acknowledged. `tenant-engine` returned\n`TEN-IN-0004` (hub intake `01a0c14b-b2f7-78f1-8f6c-e36c952fe004`) with the\nretained runtime contract verified; `secrets-engine` returned `SECRETS-IN-0002`\nwith one repository path held until the rename lands. Both are `open` by\ndesign and close on their side after T06; `flex-auth` owes each a\n\"rename landed\" notice. Recorded in the evidence file. Seven owners remain\npending.\n\n2026-09-27: `net-kingdom` confirmed `NK-WP-0039-T02` done (package coordinate\nunchanged, pins stay, no other coordinate reference found) and `runtime.yaml`\nnow declares current tenant-engine/user-engine digests. `NK-WP-0039-T03` waits\nonly on flex-auth's announcement that `access-engine` resolves, i.e. it is\ngated on T06 like the others. Separately, `net-kingdom` found\n`sso-mfa/k8s/tenant-engine/runtime.yaml` live-ahead-of-file beyond digests\n(missing `--caller-auth-mode enforce` and caller bindings) and proposed\nreplacing the flex-auth part of it with a pointer to `values/<consumer>.yaml`\nper their `ADR-0015`; flex-auth replied with no objection, since that matches\nthe pattern flex-auth already uses for other consumers and points at a file\nthat actually tracks caller-auth state. Six owners now confirmed acknowledged\nor resolved on their side; the remainder is still tracked in the evidence\nfile. This does not change T04's own gate \u2014 the external ownership ledger\nstill requires every discovered change to land its own owning-repository\nhandoff before T05/T06.\n\nReviewed inventory baseline:\n\n| Owner | Required source/verification surface |\n| --- | --- |\n| `railiance-fabric` | `registry/local-repos.yaml`, `registry/railiance-repos.yaml`, and live `fabric/**` declarations with `repo: flex-auth`; re-ingest repository/path graph nodes while retaining `flex-auth.*` runtime graph IDs. Historical discovery snapshots are evidence and are not rewritten. |\n| `ops-warden` | `registry/routing/catalog.yaml` owner repository field; verify credential routing still resolves without exposing or rotating a credential. |\n| `reuse-surface` | `registry/federation/sources.yaml`, `registry/federation/local-repo-roster.yaml`, and generated `registry/indexes/federated.yaml`; update raw URL/path, re-ingest, verify capability continuity. |\n| `policy-nexus` | `source-inventory.config.json` remote URL; re-ingest and verify the same publication lineage. |\n| `user-engine` | `wiki/ArchitectureBlueprint.md` absolute source path; separately verify its adapter and environment vocabulary remains `flex-auth`. |\n| `net-kingdom` | Three ready live Deployments (`flex-auth-ops-warden`, `flex-auth-tenant-engine`, `flex-auth-user-engine`) and `sso-mfa/k8s/**`; no runtime rename, image-coordinate change, or rollout is authorized. |\n| `tenant-engine` | Verify documentation and client configuration continue to use the retained product/runtime contract; no repository-coordinate source was found in the reviewed live paths. |\n| `sbom-nexus` | Re-ingest the new canonical checkout and prove historical/current snapshots remain related to State Hub UUID `fda8ad85-a7d7-4055-8f21-902a533e59df`. |\n| `repo-manager` | Reconcile the new canonical path and preserve file-backed identifiers; do not rewrite archived UUID-migration evidence. |\n| `railiance-platform`, `markitect-tool`, `gate-house`, `approval-engine`, `secrets-engine`, `zone-engine` | Named verification owners for semantic consumers found in the estate scan; confirm no live repository URL/path remains and retain product/runtime terminology. |\n| `flex-auth` + Forgejo operator | `.forgejo/workflows/image.yaml`, `charts/flex-auth/**`, `deploy/**`, releases, packages, hooks, Actions variables, deploy keys, branch protection, redirects, and clone URLs. Only repository coordinates change. |\n\n## 5. Renew State Hub preflight and record approval"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "86fecbb6-b008-5354-8d70-0f4ba5077a58",
|
|
"body": "Owner: `flex-auth`.\n\n```text\nstatehub repo rename preflight flex-auth access-engine \\\n --operation-id <operation-id> \\\n --output <private-preflight.json> --json\n```\n\nVerify zero blockers, immutable IDs/commit, active-work disposition, target\navailability, every risk-register row, and no queued edge writes. Record a\nhuman decision approving exact operation ID, source commit, target slug, owner,\nwindow, rollback limits, and confirmation `rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine`.\n\n2026-09-30: preflight re-run after T04 closed: ok, next safe action `start-operation` (requires confirmation; not started). Awaiting human approval.\n\nGate: a current private preflight and explicit human approval exist. Never\ncommit the private preflight file or its token.\n\n2026-09-15: signing is provisioned; a private preflight of `6fd3a0c` was\nzero-blocker. Re-run after this source commit. Human confirmation of\n`rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine` is still\nrequired before T06. Do not start the journal from this session.\n\n## 6. Execute the Forgejo repository rename"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T06",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "aa7ccd59-ddd3-5af0-a866-30e88552fc09",
|
|
"body": "Owner: `flex-auth`; human approval required.\n\nStart/retry the durable journal, then apply exactly the Forge phase:\n\n```text\nstatehub repo rename start flex-auth access-engine \\\n --operation-id <operation-id> --preflight-file <private-preflight.json> \\\n --actor <actor> --confirm 'rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine' --json\nstatehub repo rename apply <operation-id> --phase forge-renamed \\\n --confirm 'rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine' --json\n```\n\nConfirm Forgejo reports the same numeric repository ID and commit under\n`access-engine`. Stop on identity drift, unreadability, target conflict, or moved\nsource; do not create a second State Hub repository.\n\nGate: operation journal is `forge-renamed` with immutable identity evidence.\n\n## 7. Record the State Hub identity rebind"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T07",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "155041ed-8cba-5e5e-ac59-fc03ef6dd0ce",
|
|
"body": "Owner: `flex-auth` for coordination; `state-hub` owns the mutation.\n\n```text\nstatehub repo rename apply <operation-id> --phase statehub-rebound \\\n --confirm 'rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine' --json\nstatehub repo rename status <operation-id> --json\n```\n\nRecord State Hub's phase evidence. Verify both `flex-auth` and `access-engine`\nresolve to repository UUID `fda8ad85-a7d7-4055-8f21-902a533e59df`, `access-engine` is canonical, and the old\nslug is a protected alias. Do not manually update the database.\n\nGate: State Hub journal is `statehub-rebound`; IDs and historical relationships\nare unchanged.\n\n## 8. Establish and register a fresh canonical clone"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T08",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "c8afe078-41cf-5d8c-84d1-a49e4b618d34",
|
|
"body": "Owner: `access-engine` after rebind.\n\n- Preserve the old checkout until verification and rollback decisions finish.\n- Clone `access-engine` into a new path; verify origin and Forge numeric ID before\n trusting redirects.\n- Register the fresh path against the existing State Hub UUID, update canonical\n source metadata/frontmatter, commit the source-synchronization revision, and\n run `statehub fix-consistency` from the new clone.\n- Apply `source-synced` with mode-0600 evidence containing\n `fresh_clone: true`, Forge numeric `forge_repository_id`, exact `head_commit`,\n clone path, registration result, and consistency result. Remote coordinates\n contain no embedded credential.\n\nGate: no duplicate repository registration exists and the journal is\n`source-synced`.\n\n## 9. Verify identity, history, routes, builds, and deployments"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T09",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "fdb50a96-f7fa-5d4a-9efa-231750dcb2f1",
|
|
"body": "Owner: `access-engine` for aggregation; each external owner supplies its evidence.\n\nCompare relationship checksums\u2014not only counts\u2014for repository UUID, workplans,\ntasks, progress, decisions, token events/totals, SBOM snapshots, services,\ncapabilities, messages, aliases, bindings, and active dispatch. Verify old/new\nroutes, Forge ID/commit, clean builds/tests, package/image publication, policy\nand credential routes, fabric/SBOM projections, deployments, health, dashboards,\nalerts, and telemetry continuity.\n\n```text\nstatehub repo rename verify <operation-id> --json\nstatehub repo rename apply <operation-id> --phase consumers-verified \\\n --checks-file <private-checks.json> --evidence-file <private-evidence.json> \\\n --confirm 'rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine' --json\nstatehub repo rename apply <operation-id> --phase completed \\\n --confirm 'rename:fda8ad85-a7d7-4055-8f21-902a533e59df:flex-auth:access-engine' --json\n```\n\nGate: every required local check passes and every external handoff is `verified`\nwith evidence from its owning repository before completion.\n\n## 10. Exercise rollback decision points"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T10",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "3dc49eb4-1f39-5250-87c9-716a9a97790d",
|
|
"body": "Owner: `access-engine` for the decision; State Hub and Forge owners execute their\nown reversible phases.\n\nAt every phase decide continue, pause safely, or enter rollback preflight.\nRollback is allowed only if the old Forge slug remains available and named\nexternal effects are reversible. It never deletes aliases or history.\n\n```text\nstatehub repo rename rollback <operation-id> \\\n --confirm 'rollback:<operation-id>' --json\n# Execute only after reviewing safe_to_rollback and irreversible handoffs:\nstatehub repo rename rollback <operation-id> \\\n --confirm 'rollback:<operation-id>' --execute --json\n```\n\nGate: the forward completion or rolled-back terminal state is explicit; no\ngeneric error is treated as proof of rollback.\n\n## 11. Soak, hand off residuals, and clean up the old checkout"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0020-T11",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"blocked_on": "message-from:sbom-nexus",
|
|
"blocking_reason": "Needs SBOM-IN-0001 catch-up receipt, secrets-engine coordinate correction and railiance-fabric residual disposition, observed soak evidence, and exact checkout cleanup approval under e071b34e-c4d4-49d0-824d-2c58bb0ae496.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "46d8318b-d1fb-52e3-b632-52230ed1438f",
|
|
"decision_id": "e071b34e-c4d4-49d0-824d-2c58bb0ae496",
|
|
"body": "Owner: `access-engine`; destructive cleanup requires separate human approval.\n\n- Define and observe a soak window covering deployments, policy decisions,\n alerts, telemetry, packages, automation, and old-slug compatibility reads.\n- Convert every unresolved item into a live residual (`origin: residual`,\n `origin_ref: FLEX-WP-0020`) in its owning repository before finishing;\n retain its repository-rename handoff payload and owner work-record ID.\n- Retain the protected `flex-auth` alias. Alias retirement is out of scope.\n- Only after terminal verification, soak, residual handoff, and explicit cleanup\n approval may the old local checkout be removed. Record what was removed and\n whether recovery remains possible from Forgejo.\n\nGate: no actionable residual exists only in prose, the new clone is canonical,\nand old-checkout cleanup evidence is recorded.\n\n2026-09-30 (rename executed): founder approved operation `a15af186-6b98-47a4-9b53-79e131747d11`\n(preflight source `45bf036`). Forge renamed by the operator; journal phases `forge-renamed`,\n`statehub-rebound` applied; fresh clone `~/access-engine`, registered by fix-consistency;\n`source-synced` applied at head `b943d9a` after state-hub `cfb038d` (release rev 69) let the\nForge head advance past the baseline. `statehub repo rename verify`: all checks ok.\nT09 (consumer verification) waits on each owner's evidence; \"rename landed\" notices sent.\n\n2026-09-30 (completed): operation a15af186 reached `completed` (consumers-verified, then completed, with\nthe approved confirm string). Decision at T10: continue, no rollback. Named residuals: sbom-nexus\nSBOM-IN-0001 (closes on next catch-up ingest), secrets-engine docs/exec-owner-binding.md:89, and\nthe historical repo:flex-auth node in the railiance-fabric discovery snapshot. T11 (soak window;\ndestructive cleanup of old aliases/redirects needs separate human approval) remains.\n\n2026-10-04 CUST-WP-0075 owner routing: `FLEX-WP-0020-T11` remains a human wait under open decision `e071b34e-c4d4-49d0-824d-2c58bb0ae496`. Exact scoped human act and native receipts remain required; this metadata records no approval or execution. Completed predecessor edges removed: FLEX-WP-0020-T10; completed source evidence remains in the history and does not satisfy the human gate.\n\n2026-10-04 blocked-task review: owner source still records SBOM-IN-0001 open,\nand secrets-engine/docs/exec-owner-binding.md:89 still names ../flex-auth.\nNeither is closed by the rename's completed journal. The discovery snapshot\nresidual needs railiance-fabric's receiving record and disposition. No soak\nwindow or success is invented; no checkout or alias is removed. Exact owner\nreceipts and operator acceptance requirements are in\n`docs/blocked-task-dependencies-2026-10-04.md`. T11 and this workplan remain\nblocked until those returns and the still-open cleanup decision permit closure.\n\n2026-10-09 inbox review: secrets-engine closed SECRETS-IN-0002 (commit fda9708,\nmessage a56c27c5), but its re-survey searched for `~/flex-auth` only. The\nresidual named above is a relative path and is still present:\n`secrets-engine/docs/exec-owner-binding.md:89` reads `--flex-auth-source ../flex-auth`.\nReturned to secrets-engine; the T11 residual stays open. Owner evidence also\nreceived and recorded at T04/T09: user-engine USER-WP-0034 (34cdcde),\ntenant-engine TEN-IN-0004 (6c137c1), railiance-platform RPF-IN-0001 (d32baa9),\nreuse-surface REUSE-WP-0023-T01 (71abb3c), net-kingdom NK-WP-0039-T03,\nops-warden WARDEN-IN-0003 (e55fb8d)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/access-engine/workplans/FLEX-WP-0031-decision-record-emission.md",
|
|
"meta": {
|
|
"id": "FLEX-WP-0031",
|
|
"type": "workplan",
|
|
"title": "The decision record has a declared emission guarantee and nothing that delivers it",
|
|
"domain": "infotech",
|
|
"repo": "flex-auth",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "claude",
|
|
"topic_slug": "netkingdom",
|
|
"planning_priority": "P1",
|
|
"planning_order": 310,
|
|
"related_workplans": [
|
|
"FLEX-WP-0030",
|
|
"FLEX-WP-0019"
|
|
],
|
|
"created": "2026-09-21",
|
|
"updated": "2026-10-04",
|
|
"state_hub_workstream_id": "84f5d9fe-b4c9-584a-b964-efe3e48af095"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "FLEX-WP-0031-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "2dbc225f-d762-537b-9a24-ab2b17fc2fa2",
|
|
"body": "`GH-DEC-2026-018` left open whether decision-record emission must be atomic with\nthe decision (\u00a79.4), pending the class inventory. It exists now. Decide whether\na rare load-bearing decision (`deny`) may be returned before its record is\ncommitted to the outbox, and record the answer as a `FLEX-DEC`. Gate: decided,\nwith the latency cost stated.\n\nDone 2026-09-23: `FLEX-DEC-2026-018`. Every decision is released only after its\nrecord commits to the local outbox. When the commit fails, restrictive effects\n(`deny`, `redact`, `not_applicable`) are still released and counted as\n`released_uncommitted`, while `allow` and `audit_only` are withheld (503).\nWithholding a deny would turn it into an error that an open-stance consumer\ntreats as proceed. The measured cost is about 1.1 ms per durable append on\nrailiance01. The ruling puts two requirements on T03: the outbox needs a PVC,\nand the node disk is at 84 %.\n\n## 2. Register flex-auth as an audit-core sender"
|
|
},
|
|
{
|
|
"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.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "89661908-ca9a-5e4a-a0a5-62d1a9e02568",
|
|
"body": "Open an intake with `audit-core` (worked examples `AUDIT-IN-0002`,\n`AUDIT-IN-0003`): sender registration, `evidence_kind`, `heartbeat_classes` per\nclass exactly as `cadence.yaml` publishes them, and a token lane routed via\n`warden route find`. audit-core has said it accepts the classification as\nsupplied and will not infer it. Gate: sender registered; no secret in any file.\n\nRequested 2026-09-23 (hub message `6044ed35`). The request asks for six senders,\none per pin (`flex-auth.<pin>`), because each pin can only reconcile its own\ncount. It also asks for `tenants: [\"*\"]` with a justification,\n`may_read: true` for `GET /v1/reconciliation`, and per-class `heartbeat_classes`\nat 86400 s for the four rare classes. It asks audit-core to rule on whether\nFLEX-DEC-2026-018's failure-path exception counts as a `completeness_trade`,\nwhich `senders.py` forbids for a load-bearing source. warden route has no\ncatalog lane for audit-core sender tokens, and audit-core was asked to name one.\nWaiting on audit-core.\n\n2026-09-27: audit-core replied (`AUDIT-IN-0006`, thread `6044ed35`), accepted\nwith corrections: `may_read` must be `false`, not `true` (a writer already\ncounts its own sources without it); `tenants: [\"*\"]` accepted on the stated\njustification; per-class heartbeats and the `cadence.yaml` correction accepted\n(done, see T05); each registration must also carry an `emission_cadence`\ndeclaration (info-tech-canon wire schema 0.1, contract digest\n`b08b4d95fc4b0bd3`) with `allow` as expected-rate, or its rate is only\ndeclared and not evaluated. Two envelope corrections land before submission:\nthe heartbeat event needs its own `correlation_id` (no decision id exists for\nit), and `occurred_at` needs an explicit offset. The atomicity ruling\n(whether the `FLEX-DEC-2026-018` failure-path release is a `completeness_trade`)\nis referred to `gate-house` by audit-core, not decided here \u2014 flex-auth agreed\nin reply to wait for that referral. The token lane is an attended OpenBao mint\nin the founder's terminal (same path `tenant-engine` used,\n`AUDIT-WP-0010-T02`); `ops-warden` has no catalog lane for it yet and will add\none when registration opens. flex-auth acknowledged all of this in reply.\nStill `wait`: the mint needs the founder, and `ops-warden`'s catalog entry is\nnot yet in place.\n\n## 3. Durable outbox and the release rule"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0031-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "a59603d5-8954-5b05-b1a0-b143c82e439b",
|
|
"body": "Split on 2026-09-23 under the per-task budget. T05 and T06 carry the rest of\nthe original scope, and the original gate is divided between the three.\n\nDone 2026-09-23:\n\n- `internal/emission`: a durable outbox with one fsync per commit. A batch\n commits once. Each event carries exactly the eight fields audit-core's\n `normalize()` requires.\n- Event ids are random and the decision id travels as `correlation_id`.\n Decision ids are content digests, so two identical checks share one, and\n idempotency would merge them.\n- A torn tail is cut on open, and a failed commit is cut back to the last\n committed size. Committed counts per class are rebuilt on restart.\n- The engine applies `FLEX-DEC-2026-018` in `Check`, `BatchCheck` and\n `ListAllowed`. A withheld decision answers 503.\n- `serve --outbox-dir --emission-source` enables it, and `GET /v1/emission`\n reports committed and `released_uncommitted` counts per class.\n- `api.DecisionEffects()` lists the effect vocabulary. A source-parsing test\n fails on any constant it misses, and a second test fails unless the\n load-bearing classes in `cadence.yaml` equal that vocabulary.\n- `make test` (race) passes, and a local serve smoke test committed and counted\n one deny and one allow. Nothing is deployed and no chart changed.\n\n## 5. Implement heartbeat and drain to audit-core"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0031-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "14bd6648-11da-53d7-a512-027005bd4772",
|
|
"body": "2026-10-04: split implementation from native delivery acceptance (new T08).\n`internal/emission/delivery.go` implements daily per-class `audit-core.heartbeat`\nevents with independent correlation IDs and offset timestamps, persisted in\nour durable outbox. Restart rebuilds each class's last heartbeat from the log.\nHeartbeats expose committed and released-uncommitted counts; a known failure\nchanges the assertion to `released-uncommitted-finding`.\n\nThe asynchronous drain sends the eight-field envelope with event-ID\nidempotency, reads a mounted token file per event for rotation, refuses\nredirects, and advances a fsynced/renamed cursor only on 200 or 202. Every other\nresponse, transport failure or cursor-write failure retains the event. A\nbounded drain runs each minute, without holding the decision lock during HTTP.\n`GET /v1/emission` exposes pending depth, oldest pending timestamp and lag-bound\nexceedance (100 events / 1h). No response body or token is logged.\n\n`serve --audit-url <explicit /v1/events endpoint> --audit-token-file <mount>`\nenables the worker only with an outbox. Both default empty, and no pin enables\nit. Local tests cover per-class cadence, restart, rejection, stable replay,\nambiguous acceptance, token rotation and cursor durability. The current outbox\nretains acknowledged log entries; retention/compaction is not implemented, so\ncapacity planning must include cumulative log growth.\n\n## 6. Reconciliation, profile check, and storage"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0031-T06",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"FLEX-WP-0031-T02"
|
|
],
|
|
"blocked_on": "message-from:audit-core",
|
|
"blocking_reason": "Receiver counts use accepted_at, while local counts use commit time; audit-core must supply compatible window semantics or durable acceptance timestamps before a valid comparator can be implemented.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "bf92a951-3b69-59dd-8907-f6748c91a264",
|
|
"body": "2026-09-27: reconciliation compare needs `audit-core`'s `GET /v1/reconciliation`,\nwhich does not exist until T02's sender is registered. The profile checker\n(`net-kingdom/tools/emission-cadence-profile`) is runnable locally but needs a\n`--contract-schema` for the decision-record cadence contract that is not yet\npublished in this repo or referenced by any sibling's invocation found \u2014\ninventing one here would be exactly the kind of schema flex-auth should\npublish deliberately, not improvise for a validation run. The PVC chart change\nis explicitly a production change needing the founder's go-ahead and was left\nundone. Stays `wait`.\n\n- Compare committed counts per class and window with audit-core's\n `GET /v1/reconciliation`. Divergence is a finding, and undrained events count\n as lag, not divergence.\n- Validate `cadence.yaml` with the net-kingdom emission-cadence profile checker,\n supplying the inventory as `--rare-load-bearing`/`--load-bearing`.\n- Add an optional PVC to the chart for the outbox, sized against the node disk\n (84 % on 2026-09-23). Rolling it out to any pin is a production change and\n needs the founder's go-ahead.\n\n2026-10-04: storage/profile preparation is now complete as T07. The remaining\ncomparator is independently blocked by receiver time semantics, not just a\nmissing registration: audit-core counts accepted_at in half-open windows,\nwhile our log timestamps local commits. Ingest returns status/reference only.\nA receiver-approved matching basis or stable acceptance-time receipts (also\non duplicates) is required before implementing a comparison. Do not widen\nmay_read to fetch archive payloads as a workaround. T02 and T08 still gate\nnative custody/rollout evidence; see the dependency record for exact returns.\n\n## 4. Close G2"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0031-T04",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"FLEX-WP-0031-T08",
|
|
"FLEX-WP-0031-T06"
|
|
],
|
|
"blocking_reason": "G2 needs T08 native heartbeat/drain and silence-finding evidence plus T06 reconciliation; local tests cannot close the delivery gap.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "423b3090-1b72-58fd-9353-5c907c7683bb",
|
|
"body": "2026-09-27: closing G2 requires the silence-finding gate, which requires T05's\nsender and T06's reconciliation to actually exist. Both are blocked on T02\n(external, `audit-core`). Stays `wait`.\n\nChange `cadence.yaml` `state` to emitting, move G2 out of the gap table with the\nevidence, and tell `gate-house`, `audit-core` and `kings-guard`. Gate: a silence\nfinding is observed on a deliberately withheld heartbeat in a non-production\nrun.\n\n## 7. Prepare persistent storage and validate the cadence contract"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0031-T07",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "151fe609-ba68-506b-9c2c-9fdb0b149eef",
|
|
"body": "Split from T06 on 2026-10-04; its historical schema/storage blockers above are\nsuperseded by this implementation. `charts/flex-auth` has optional outbox PVC,\nmount, source and flags, defaults disabled, a one-replica constraint and\nRecreate strategy to avoid two writers during rollout. It supports an existing\nclaim. Rendering is tested with caller auth enabled and disabled. No values pin\nor live deployment is changed; 1Gi is a configurable preparation value, not an\nassertion of available node space.\n\nPublished `docs/contracts/decision-emission-cadence.json` against the actual\nInfoTechCanon wire schema and NetKingdom profile. All five decision classes\nare explicitly supplied; contract/profile assessment passes. The generic\nexpected-rate schema forbids reconciliation on that entry and the profile\nforbids duplicate classes, so allow's additional reconciliation guarantee is\nin the `extensions.flex-auth` namespace. Receiver acceptance of that mapping\nremains part of T02; a profile pass does not establish observer delivery.\n\n## 8. Admit and exercise native heartbeat/drain delivery"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0031-T08",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"FLEX-WP-0031-T02"
|
|
],
|
|
"needs_human": true,
|
|
"blocking_reason": "Needs admitted sender/token mounts, founder approval of exact image/PVC/network rollout, and audit-core observer evidence; no production delivery is enabled.",
|
|
"state_hub_task_id": "b3b52b30-c73d-5a90-9935-d98afe5a9eaf",
|
|
"body": "Remaining acceptance split from T05: audit-core's owner must return admitted\nexact per-pin sources, scope, heartbeat classes and cadence mapping under\nAUDIT-IN-0006. Platform must provide governed attended token custody and\nmount references, never values. The founder must approve exact immutable image,\nPVC capacity and rollout; network owners must admit the decision pins to the\nreceiver. Record native 202 and idempotent 200 delivery, restart cursor/lag\nbehaviour, and an audit-core silence finding from a separately authorized\nnon-production withheld-heartbeat exercise. No test engagement/window is\ncreated by this workplan. T06 still owns the compatible-time reconciliation\nimplementation and its native acceptance. See\n`docs/blocked-task-dependencies-2026-10-04.md` for the concrete dependency gates.\n\n2026-10-04 review: workplan stays blocked. Local heartbeat/drain and storage\npreparation no longer wait on another repository, but admission, statutory\nruling, valid reconciliation time basis and approved native acceptance do.\n`cadence.yaml` remains `declared-not-yet-emitting` and G2 remains open."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/access-engine/workplans/FLEX-WP-0035-per-identity-application-readback.md",
|
|
"meta": {
|
|
"id": "FLEX-WP-0035",
|
|
"type": "workplan",
|
|
"title": "Per-identity application access readback and readable protected-system registry for user-engine",
|
|
"domain": "infotech",
|
|
"repo": "access-engine",
|
|
"status": "active",
|
|
"owner": "claude",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-09",
|
|
"updated": "2026-10-09",
|
|
"related": [
|
|
"USER-WP-0026",
|
|
"USER-WP-0028"
|
|
],
|
|
"state_hub_workstream_id": "cb9755fa-6824-5288-81c4-3aa2fbff1a9f"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "FLEX-WP-0035-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0585a684-d462-5caa-937f-b1730efddbd8",
|
|
"body": "Decide the action that a readback evaluates per system: a declared\n`application.access` action each consumer package must opt into, versus a\nper-system mapping held in the registry. A system that declares nothing is\nreturned as `not_applicable`, never allow. State per input class the\nrevocation-visibility deadline the readback carries (\u00a79.7). Decide whether the\nreadback is a decision for audit purposes (decision record, emission) or an\nexplicitly non-enforcing advisory read. A displayed allow must not be usable as\na PEP decision by another system.\n\nGate: written contract in `docs/` plus an ADR or decision record; reviewed with\nuser-engine before code.\n\n2026-10-09: user-engine accepted the contract (message `f54df082`) with three\namendments, now folded in: the `/v1/check` subject shape with `tenant`, the\nrendering table, and a separate `USER_ENGINE_READBACK_TOKEN_FILE`. Also added: a\nrealm-level-claims-only rule. `FLEX-DEC-2026-019` is accepted.\n\n2026-10-09: activated by the founder. Draft contract\n`docs/application-access-readback.md` and `FLEX-DEC-2026-019` (proposed). Key\nfinding: each pin loads one consumer's package, so no existing pin can answer\nacross applications. The draft proposes a dedicated readback pin with\nmulti-package mode, a `purpose: \"readback\"` binding that keeps decisions\nnon-transferable, and a new optional `client_binding` manifest field. Sent to\nuser-engine with four review questions. The gate closes on their reply.\n\n## Caller authorization for cross-system readback"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0035-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"FLEX-WP-0035-T01"
|
|
],
|
|
"state_hub_task_id": "eb0b6a91-7750-553b-b87f-c4262eb9df07",
|
|
"body": "Add a distinct caller capability (readback scope) instead of widening the\n`flex-auth-user-engine` binding to other systems' check rights. The readback\ncaller must not be able to obtain a decision that another system's PEP would\naccept, and its decisions must say so in the binding.\n\nGate: tests prove a readback-scoped token gets 403 on `/v1/check` for a foreign\nsystem and is admitted only on the readback route.\n\n2026-10-09 done. `flex-auth serve-readback` is a separate subcommand that mounts\nno `/v1/check` or `/v1/batch_check` (404 there). `--readback-caller` is bound\nunder the non-system key `application-readback`. `CheckRequest.purpose` is\nhashed into `request_digest`, `submitted_request_digest` and\n`approval_binding_digest`, but only when set, so enforcement digests are\nunchanged. `/v1/check` refuses a request that carries it. Tests:\n`cmd/flex-auth/readback_test.go`\n(`TestReadbackPrincipalCannotCheckOnEnforcementPin`,\n`TestReadbackHTTPCallerAndRequestShape`, `TestReadbackWithholdsUncommittedAllow`)\nand `pkg/api/purpose_test.go`.\n\n## Readable protected-system registry"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0035-T03",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"FLEX-WP-0035-T01"
|
|
],
|
|
"state_hub_task_id": "5dbb3280-8490-58a5-a0bb-f3883e568f58",
|
|
"body": "Serve a read-only projection: system id, display name, key-cape client binding.\nInclude the registry-snapshot digest so the catalogue is tied to the same\nsnapshot that decisions record (G1, `FLEX-WP-0019`). Grants and revocations stay\ninside access-engine; user-domain admins get no grant surface from this work.\n\nGate: endpoint plus schema, admitted only for the readback caller, tests.\n\n2026-10-09 done. `GET /v1/readback/systems`; optional `client_binding` on\n`protected_system_manifest`. Schemas `readback_request`, `readback_response`\nand `readback_systems` are checked against live service output\n(`TestReadbackShapesMatchSchemas`). schemaguard gained `maxItems` for this.\n\n## informed-decision declares `application.access`"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0035-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "701cbd99-1a84-5290-8f66-15fa7f407d3b",
|
|
"body": "informed-decision is the first participant. Its `informed-decision.lifecycle`\npackage reads `authentication_audience`, which the readback must not use\n(contract \u00a73). Add an `application.access` rule over realm-level claims only,\nas a new package version with fixtures. Coordinate the version bump with\ninformed-decision, because its own pin must run the same digest. Add\n`client_binding` to its registry entry.\n\nGate: package valid with allow/deny fixtures, informed-decision agrees, and\nthe rule reads no audience, authorized-party or client-scoped claim.\n\n2026-10-09 source done. `informed-decision.lifecycle` is now v2\n(`sha256:da01e045\u2026`, `pin.json` updated). It adds `application.access`, which\nrequires `purpose == \"readback\"` and the existing `human` bar: net-kingdom-admins,\nKeyCape AAL2 `pwd`+`otp` within 12h, platform tenant. It has no workload path\nand reads no audience or client-scoped claim. v1's twelve operations are\nunchanged. Eight Go cases cover it, plus a fixture showing that it denies\nwithout the readback purpose. The catalogue `examples/application-readback/`\nbinds informed-decision to `https://kc.coulomb.social` /\n`informed-decision-approver`. `TestReadbackInformedDecisionCatalogue` proves the\nreadback over the shipped files. The live lifecycle pin still runs v1 (image\n`bdac62bc`) until the T04 rollout.\n\n2026-10-10 done. Founder agreed to lifecycle v2 for informed-decision\n(informed-decision itself had not replied to `7fcb1eb7`).\n\n## Deploy the readback pin"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0035-T04",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"FLEX-WP-0035-T05"
|
|
],
|
|
"priority": "medium",
|
|
"state_hub_task_id": "82a8a7e6-54e9-5262-a271-24ce2f161362",
|
|
"body": "Add `values/flex-auth-application-readback.yaml` (or a deploy manifest) for a\ndedicated `flex-auth-application-readback` pin, plus a test asserting that its\npackage paths match each participant's own pin values (digest-equality, \u00a74).\nAdd the user-engine ingress rule, then get the founder's go for the rollout.\n\nPromised to user-engine (reply to `d7e02758`, 2026-10-10), so the values file\nmust match: URL\n`http://flex-auth-application-readback.flex-auth.svc.cluster.local.:8080`\n(trailing dot, in-cluster only), caller token audience `flex-auth`\n(`serve-readback --caller-audience` default), readback caller\n`system:serviceaccount:user-engine:user-engine`.\n\n2026-10-10 repo side done (`bb14ec6`). `values/application-readback.yaml` and the\nchart's `readback.enabled` mode, which renders `--readback-caller`. The lifecycle\npin moves to `e8c57c18` (`main-b5da745`, v2). Rollback target is `bdac62bc`.\n`TestReadbackPinMatchesParticipantPins` checks that the readback pin uses the same\nimage and package path as each participant's own pin. Rollout order: the lifecycle\npin, then the readback pin.\n\n2026-10-10 done. The founder ran both helm upgrades: the lifecycle pin is at\nrevision 2 and `flex-auth-application-readback` at revision 1, both on `e8c57c18`.\nVerified: both Ready, `/healthz` 200 on both, the readback routes return 401\nwithout a token, `/v1/check` returns 404 on the readback pin, anonymous lifecycle\n`/v1/check` returns 401, and ingress admits only `user-engine/user-engine`.\nuser-engine's live check with its own token is still to come.\nThe pin ships with the image that contains `serve-readback`. Hand user-engine\nthe evidence that unblocks `USER-WP-0026-T03`."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/access-engine/workplans/FLEX-WP-0036-runtime-rename-access-engine.md",
|
|
"meta": {
|
|
"id": "FLEX-WP-0036",
|
|
"type": "workplan",
|
|
"title": "Runtime rename: flex-auth to access-engine, run side by side, consumers switch one at a time",
|
|
"domain": "infotech",
|
|
"repo": "access-engine",
|
|
"status": "active",
|
|
"owner": "claude",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-10",
|
|
"updated": "2026-10-10",
|
|
"origin": "demand",
|
|
"origin_ref": "founder 2026-10-10 (\"the relicts are too disorienting\")",
|
|
"related": [
|
|
"FLEX-WP-0020"
|
|
],
|
|
"state_hub_workstream_id": "af0f8d77-af04-569b-8e79-6c47eb8f1087"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "FLEX-WP-0036-T01",
|
|
"status": "progress",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4f9a796d-832f-5936-8a34-eb980f6e1b57",
|
|
"body": "Record `FLEX-DEC-2026-021`: runtime names move to `access-engine`, following\nthe table above. It supersedes the runtime rows of `FLEX-DEC-2026-013`. Fix\nthe namespace, release and DNS pattern, the audience value, and the\n`resource.system` value. Settle the binary question: rename it outright, or\nship `access-engine` with a `flex-auth` alias for one release.\n\nGate: decision accepted by the founder.\n\n2026-10-10: binary settled by `FLEX-DEC-2026-020` (founder): renamed outright,\n`flex-auth` is a stub that prints the rename and exits 2. The other target\nnames in the table still need the founder's acceptance.\n\n## Inventory every consumer reference and open handoffs"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T02",
|
|
"status": "progress",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T01"
|
|
],
|
|
"state_hub_task_id": "8f597899-677e-544b-ad58-26aab2614312",
|
|
"body": "For each consumer, list every place that names the runtime: URL, audience,\negress policy, routing catalog entries, scripts, tests, stance maps, and the\n`resource.system` value. Known consumers: `ops-warden` (two pins, plus\n`flex-auth-policy-check`, registry and manifest scripts), `secrets-engine`,\n`user-engine` (two pins: check and readback), `tenant-engine`,\n`informed-decision` (lifecycle, sitting and t03 pins), and `net-kingdom`\n(`sso-mfa/k8s/**`). Also check the State Hub, `state-hub` CLI and\n`railiance-fabric` discovery for runtime names. Request one work-record id\nfrom each owner.\n\nGate: `docs/runtime-rename-inventory.md` with one row per reference and an\nowner handoff id per consumer.\n\n2026-10-10 inventory written. Handoff ids are not yet requested. They wait for\nT01, so each owner gets the exact new URL and audience in one message. Found\nthat informed-decision's component tests and ops-warden's production smoke\nscript run a binary whose path comes from an env var. A binary built from\ncurrent source must now come from `./cmd/access-engine`.\n\n## Make the PDP accept both names"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T03",
|
|
"status": "todo",
|
|
"priority": "high",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T01"
|
|
],
|
|
"state_hub_task_id": "487525e5-c89e-586e-8e9b-54ac6da0804e",
|
|
"body": "Caller auth accepts `access-engine` and `flex-auth` audiences, and packages\nand caller bindings accept both `resource.system` values. Decision records\nmust still state which value the request carried, so nothing is rewritten\nsilently. Add tests for both values on every pin's package.\n\nGate: tests; a new image rolled to the existing `flex-auth-*` pins with the\nfounder's go.\n\n## Rename the source"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T04",
|
|
"status": "progress",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T01"
|
|
],
|
|
"state_hub_task_id": "ff7fd369-326f-5044-aaa4-96c5f45c80e9",
|
|
"body": "Go module, `cmd/access-engine`, binary, `ACCESS_ENGINE_*` env vars (read the\nold names for one release, with a warning), `charts/access-engine`, and CI\npublishing to `coulomb/access-engine`. Publish to `coulomb/flex-auth` too\nuntil T07 is done, so the old pins can still roll back. No runtime change.\n\nGate: build, tests and stage-1 render green; CI publishes both packages, and\nboth resolve to the same digest.\n\n2026-10-10 binary part done ahead of the rest (`FLEX-DEC-2026-020`). The CLI is\nnow `cmd/access-engine` and the image entrypoint is\n`/usr/local/bin/access-engine`. The image also ships the `flex-auth` stub.\nUpdated: Makefile, CI, `tools/verify-posture.sh`, `tenancy.yaml` and the live\ndocs. Workplans, decisions and ADRs are left as written.\n\n2026-10-10 also done: Go module `github.com/netkingdom/access-engine`; no other\nrepo imports it. `ACCESS_ENGINE_RUN_TOPAZ_INTEGRATION` replaces the only\n`FLEX_AUTH_*` variable, and the old name skips the test with a message naming\nthe new one. README identity paragraph and title updated. Still to do, and\ndeliberately left for T05: the chart name, because it changes selector labels,\nwhich are immutable on a `helm upgrade`, so it ships with the new releases.\nAlso the image package and the `/opt/flex-auth` paths, which every live pin's\nargs reference.\n\n## Stand up the access-engine namespace next to flex-auth"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T05",
|
|
"status": "todo",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T03",
|
|
"FLEX-WP-0036-T04"
|
|
],
|
|
"state_hub_task_id": "13b93d7a-8341-5c76-9ae8-0f36b45b10fc",
|
|
"body": "Create the `access-engine` namespace, then one `access-engine-<consumer>` pin\nfor each live `flex-auth-<consumer>` pin. Each new pin runs the same image\ndigest and package as its twin and gets its own TokenReview binding. Ingress\nadmits the same consumer as the twin does. Extend\n`TestReadbackPinMatchesParticipantPins` to cover the new pins, and add a test\nthat each twin pair runs the same digest.\n\nGate: every new pin Ready, `/healthz` 200, anonymous requests 401; founder go.\nBlocked on `FLEX-WP-0020-T11` closing.\n\n## Consumers switch over, one at a time"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T06",
|
|
"status": "todo",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T02",
|
|
"FLEX-WP-0036-T05"
|
|
],
|
|
"state_hub_task_id": "f0470e5c-3ea7-506c-b8bb-3ade0b57ff88",
|
|
"body": "Each consumer changes its URL, its egress policy (add the new namespace before\nremoving the old one), its audience and, for ops-warden, `owner_repo`. One row\nper consumer in the inventory, closed with that owner's evidence: a live\nallow and a live deny against the new pin, and no traffic left on the twin\n(from twin logs).\n\nGate: every inventory row closed with owner evidence.\n\n## Retire the flex-auth runtime"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T07",
|
|
"status": "todo",
|
|
"priority": "medium",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T06"
|
|
],
|
|
"state_hub_task_id": "e46c9c8e-a114-5c49-b035-22fdbd6a435b",
|
|
"body": "After a soak with no traffic on the old pins: uninstall each `flex-auth-*`\nrelease and its TokenReview binding, delete the `flex-auth` namespace, drop\nthe old audience and `resource.system` from acceptance (`FLEX-DEC-2026-015`\norder), and stop publishing `coulomb/flex-auth`. Keep the flattened emergency\nmanifests in `deploy/` only as rewritten for the new names.\n\nGate: founder go; `kubectl get ns flex-auth` NotFound; every consumer's checks\nstill allow and deny as expected.\n\n## Prose, canon and layer declaration"
|
|
},
|
|
{
|
|
"id": "FLEX-WP-0036-T08",
|
|
"status": "todo",
|
|
"priority": "low",
|
|
"depends_on": [
|
|
"FLEX-WP-0036-T06"
|
|
],
|
|
"state_hub_task_id": "be5440aa-4584-5e4f-9459-242ecf5c7199",
|
|
"body": "SCOPE, INTENT and its layer declaration, the conformance doc, the stance\nregister reviews, `.claude/rules`, the `deploy/` and `railiance/` READMEs,\n`railiance/app.toml`, and `ops-warden`'s routing catalog and credential-routing\ncanon. Raise the canon-naming item (`FLEX-WP-0030` B5) as closed. Historical\nrecords stay as written.\n\nGate: `grep -rn flex-auth` over live docs returns only historical records and\ndeliberate notes about the old name."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": " M WORK-RECORDS.md\n"
|
|
},
|
|
"secrets-engine": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/secrets-engine/workplans/SECRETS-WP-0006-catalog-lane-adoption.md",
|
|
"meta": {
|
|
"id": "SECRETS-WP-0006",
|
|
"type": "workplan",
|
|
"title": "Adopt concrete OpenBao credential lanes from ops-warden",
|
|
"domain": "infotech",
|
|
"repo": "secrets-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "custodian",
|
|
"created": "2026-08-21",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "31f7f8ea-7f73-516c-8877-f03a13f1db82"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "SECRETS-WP-0006-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "94d54df8-4088-5475-992b-7fe838c7c7d7",
|
|
"body": "Completed 2026-08-21. Replied in the existing thread with State Hub message\n`7fb0c2ce-be41-4a1d-95b0-e2cdd97d5718`, marked the inbound message read, and\nrecorded decision `ae676382-1826-4e04-aa4e-bb77990c7a0d`. The reply accepted\nthe five concrete KV lanes, declined the generic OpenBao route and key-cape\nlogin route, corrected the six-delivery-mode interpretation, and kept interim\nproxies in place pending per-lane verification.\n\nReply in the existing State Hub thread with the accepted five-lane scope, the\ntwo declined generic/non-owned routes, and the delivery-mode correction. Accept\nops-warden's offer of a PR-shaped non-secret metadata contribution for the five\nconcrete lanes.\n\nDone when the reply is posted, the inbound message is marked read, and this\ndecision is recorded as non-secret State Hub evidence.\n\n## Define admission contract for existing production lanes"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0006-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "1a04ee82-ff61-55bc-bae8-62e1229d9dcc",
|
|
"body": "Completed 2026-08-21. Added explicit `mount_management`, `delivery_auth`, and\n`workload_delivery` semantics, with the operating contract documented in\n`docs/catalog-admission.md`. Existing mounts and externally managed delivery\nauth now render non-mutating checks; apply cannot create or rewrite them.\nExisting workload delivery remains independent metadata, while an optional\nengine-managed AppRole is a separate approval-gated native delivery surface.\n\nDefine how a catalog entry represents a lane whose KV mount already exists and\nwhose workload delivery is ESO/Kubernetes rather than a secrets-engine-created\nAppRole. Separate these concepts where needed:\n\n- existing-mount versus engine-managed mount;\n- workload delivery versus agent/operator exec delivery;\n- catalog/verification metadata versus engine-managed consumer auth;\n- provider-side rotation owner versus OpenBao value update workflow.\n\nAcceptance:\n\n- Dry-run cannot propose creating or broadening the shared `platform` mount.\n- A lane can retain its existing workload auth/delivery while optionally\n exposing an approved exec-time adapter.\n- The production stage role is not broadened by implication.\n\n## Review and import the five catalog entries"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0006-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "b595f38e-bb31-513b-bc73-796cec76a2aa",
|
|
"body": "Completed 2026-08-21. The offered contribution did not arrive, so drafted all\nfive entries from ops-warden playbooks and the authoritative railiance-platform\nCCRs, then requested line-by-line review in message\n`ceace632-2332-46d8-a2b3-1714fbfa7e2c`. Ops-warden confirmed the mounts, paths,\nfield sets, CCR references, consumers, lifecycle owners, existing workload\ndelivery, proposed exact-path AppRole surface, both route rejections, and the\ndelivery-mode correction in messages `26df37c5-2756-49b8-8f9c-c1bb2bab1b4b`\nand `3f875d90-6f88-4f44-961b-6f6fbd15b01d`. The follow-up retracted the only\napparent metadata concern: `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` is explicitly\npresent in CCR-2026-0005, so both reuse-surface and issue-core remain correctly\nclassified `high`. Interim proxy ownership remains unchanged until T05.\n\nReview ops-warden's proposed entries line by line against the schema, canonical\nsecurity boundary, live route metadata, and owning workload documentation.\nCorrect field lists, mount/path, consumers, delivery modes, approval references,\nrotation owners, and negative checks before merging.\n\nAcceptance:\n\n- All five files contain non-secret metadata only.\n- Generic `openbao-api-key` and `key-cape-oidc-login` entries are absent.\n- Each entry names an exact lane rather than a provider-wide wildcard.\n- Each high-risk lane has explicit rotation and deactivation expectations.\n\n## Implement guards and offline verification"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0006-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "b2ca67ec-48e0-5f85-b4d8-94eb601206c5",
|
|
"body": "Completed 2026-08-21: implemented non-mutating existing-mount/auth planning and\napply behavior, workload-delivery validation, exact field guards for exec and\nverification, safe policy/role overrides, route guidance, and focused tests.\nAll five admitted entries load and render `kv-mount-check` plus an exact-path\npolicy and bounded AppRole plan. Generic/wildcard entries and undeclared fields\nare negatively covered. Privileged provision, verify, exec, handoff, and live\nrevoke operations now fail closed without a resolved approval. Full verification\npasses 82 tests.\n\nImplement only the schema/planning/delivery changes required by the admitted\nentries. Add tests for shared existing mounts, auth/delivery separation,\nmulti-field selection, exact exec-env injection, and rejection of wildcard or\ngeneric provider-wide entries.\n\nAcceptance:\n\n- The complete catalog loads and validates.\n- Each admitted lane renders a non-mutating guarded plan.\n- Negative tests prove no wildcard path, broad policy, undeclared field, or\n unsupported delivery mode is accepted.\n- `uv run pytest` and `git diff --check` pass.\n\n## Stage live apply and verification"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0006-T05",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocked_on": "message-from:railiance-platform",
|
|
"blocking_reason": "OpenRouter key-check native acceptance is recorded in SECRETS-WP-0010-T03. Other lanes still need exact approvals, scoped attended apply and per-lane positive/negative/health/revocation evidence.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "fb103f1e-2ff7-5de5-9a2c-191a19c43542",
|
|
"body": "Inbox triage 2026-09-21. railiance-platform `e82bb289` (2026-09-09) answered\nthe openrouter-llm-connect first-lane request with an explicit **wait on T04\nserving**: no approval object path and no scoped attended authority yet, because\nthe canonical `action=apply` ActionAuthorization does not exist and llm-connect\nhas not confirmed ESO health. It accepts the apply shape and rollback\ncontainment in principle, confirms CCR-2026-0003 is provenance and not\nexecutable authorization for a native AppRole, and will name the approval path\nand attended window together once T04 serves and llm-connect confirms. Keep\n`forgejo-admin-api-token` last. Nothing changes here; T05 stays `wait`.\n\nProgress 2026-09-03. Re-rendered guarded plans on the post-hardening engine.\nEvery admitted lane is still `kv-mount-check` + exact-path read policy +\nbounded AppRole. First live candidate is `openrouter-llm-connect` (narrowest\nconsumer/field set). Procedure: `docs/native-lane-cutover.md`. Coordinated:\nrailiance-platform `0190c9b3` (AppRole-only apply, no KV/ESO mutation),\nops-warden `c2c01262` (keep all five proxies), llm-connect `6f9b460a` (ESO\nstays theirs). Live apply still wait on T04 serving plus a canonical\n`action=apply` approval and scoped attended authority. CCR-2026-0003 remains\nprovenance, not that approval. Proxies stay until T06 per lane.\n\nReadiness update 2026-08-21: rendered non-mutating production dry-runs for all\nfive lanes. Every plan checks the externally managed `platform` mount without\nmutation, writes one exact-path read policy, and proposes the reviewed bounded\nAppRole (15-minute token TTL, 30-minute maximum TTL, 15-minute single-use\nSecret ID, and eight token uses). OpenBao is reachable and unsealed, but route\nstatus remains `ready: false`: the original CCR references approve the existing\nworkload lanes and are not resolvable State Hub approvals for the new native\nAppRoles. This session also has no production OpenBao token or bootstrap file.\nRequested per-lane approval references and scoped attended/apply authority from\nrailiance-platform in message `3db3da86-2f3f-4301-8be6-74b507ea66a0`. No value\nwas read and no OpenBao mutation was attempted.\n\nHardening dependency 2026-08-23: `SECRETS-WP-0007` now owns the engine-level\nprovisioning, lifecycle, approval-binding, delivery-session, verification, and\nevidence gaps found during scope assessment. T05 must not provision or revoke\nthe existing shared paths through the current commands. Native live adoption\nresumes through `SECRETS-WP-0007-T07` after its T01-T06 safety gates; this task\ncontinues to own the per-lane production evidence and acceptance outcome.\n\nFor each lane, obtain the required decision/operator approval before any live\nOpenBao policy, auth-role, provisioning, rotation, or delivery change. Start\nwith metadata/capability-safe checks and preserve the current ops-warden proxy\nuntil native positive and negative verification succeeds.\n\nAcceptance per lane:\n\n- Approval is resolved and linked.\n- Existing workload delivery remains healthy.\n- Positive access and unrelated-consumer denial are proven without reading a\n value into evidence.\n- Rollback/revocation steps are recorded.\n\n2026-10-03: human gate routed to hub decision 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1: Attended OpenBao provisioning window: one session clears the pending credential lanes) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Reconcile routing ownership and retire interim proxies"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0006-T06",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"SECRETS-WP-0006-T05"
|
|
],
|
|
"blocked_on": "message-from:ops-warden",
|
|
"blocking_reason": "Needs owner-agreed routing/proxy retirement for each verified lane and custody disposition of the legacy npm pointer; a single approved OpenRouter key-check does not authorize broader routing cutover.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "1431edae-5791-5892-8c4b-829419b537d2",
|
|
"body": "After a lane is natively ready, update the ops-warden delegation register and\nsafe next action for that lane. Retire interim proxy operation lane by lane,\nnot as a seven-lane batch.\n\nAcceptance:\n\n- Native readiness is evidenced before the proxy is retired.\n- ops-warden remains the routing front door and does not vend non-SSH secrets.\n- The generic OpenBao route and key-cape login route retain their correct\n owners.\n\nDiscrepancy report 2026-09-06 (ops-warden `fc898979`, WARDEN-WP-0037-T01).\nops-warden reports the authoritative whynot-design npm concrete pointer as\n`platform/workloads/coulomb/whynot-design/npm-publish`, field `NPM_AUTH_TOKEN`,\nendpoint `https://forgejo.coulomb.social/api/packages/coulomb/npm/`. Reviewed\nhere without any OpenBao read or mutation:\n\n- Endpoint agrees. `catalog/whynot-design-npm-publish.yaml` already carries the\n Forgejo registry in `delivery_config.npm.registry`.\n- The field claim is a category error, not a repo defect. `NPM_AUTH_TOKEN` is\n the resolved *injection env var* from `publication_policy.resolve` (default\n template, repo-clamped while netkingdom is `maturity-build`), not a KV field\n name. The declared KV field is `npm_token`. `docs/whynot-design-real-publish-closeout.md`\n lists both rows separately. Renaming the catalog field to `NPM_AUTH_TOKEN`\n would break the proven pilot lane.\n- The path claim is credible and unresolved here. `docs/hardening-backlog.md`\n already records the value against *both* `whynot-design-npm-publish` and\n `platform/workloads/coulomb/whynot-design/npm-publish`, and every other\n admitted lane uses the `platform/workloads/...` convention. Which location is\n authoritative for reads is custody state owned by railiance-platform; this\n repo cannot confirm it without lane read authority, and production live\n commands remain fail-closed pending `SECRETS-WP-0007-T04`.\n\nThe catalog mount/path is therefore left unchanged pending a custody-side\nconfirmation from railiance-platform. Rewriting a proven production lane pointer\nfrom an inbox claim is exactly the unverified custody mutation this task must\nnot make. `ready: false` observed by ops-warden is the expected fail-closed\nresult and is not evidence of a wrong path.\n\nNext: obtain from railiance-platform a non-secret confirmation of which KV\nlocation backs this lane. If the platform path is authoritative, the catalog\nmount/path move is a reviewed lane change carrying its own approval, and the\ndeclared field stays `npm_token` unless custody says otherwise.\n\nAsked 2026-09-07 (hub message `546403e4` to `railiance-platform`). The question\nis narrowed to the path alone, since the endpoint agrees and the\n`NPM_AUTH_TOKEN` claim was resolved here as a category error rather than a\ndiscrepancy. Also asked whether the current `secret/...` location still exists\nif the platform path is authoritative \u2014 a stale duplicate holding a real token\nis worth knowing about independently of this lane. Flagged to them that\nops-warden's `ready: false` is our expected fail-closed posture and must not be\nread as corroborating the platform path. Awaiting reply; the catalog is\nunchanged.\n\n\n## Exit criteria\n\n- The five concrete OpenBao lanes have reviewed catalog entries and guarded\n offline plans.\n- Live ownership moves only for lanes that pass approved positive/negative\n verification.\n- The two generic/non-owned routes are not mislabeled as secrets-engine lanes.\n- No secret material is recorded in repository or coordination evidence.\n\n\n### Native OpenRouter handoff from SECRETS-WP-0010 \u2014 2026-09-16\n\nSECRETS-WP-0010-T03 completed the exact read-only key-check recipient: native\napply and verify, distinct human-approved CAS consumption for all three actions,\nOpenRouter GET /api/v1/key HTTP 200, unrelated identity/path denials, explicit\nrevoked-token HTTP 403, and unchanged llm-connect/ESO health. Evidence:\n`docs/evidence/2026-09-16-t03-completion.json`. No inference was performed.\nThis supplies one lane's evidence; this workplan retains its existing broader\nlive adoption tasks. SECRETS-WP-0006-T05/T06 own other-lane acceptance and\nrouting/proxy retirement; SECRETS-WP-0007-T04/T07 retain general native readiness.\nDo not reuse the consumed approvals or treat the temporary key-check overlay as\napproval for a radar trial recipient. IR-WP-0005 owns radar delivery acceptance;\nIR-WP-0006 owns the outstanding USD 0.023712 billing reservation.\n\n\n### 2026-09-21 answered: the exec front door reads the ungoverned legacy path\n\nops-warden (`abf27efc`) and railiance-platform (RPF-WP-0035-T07, `09b719fe`)\nasked the same location-only question. Answered from this repository's own code\nand catalog, with no OpenBao read and no value of any kind.\n\n**`secrets-engine exec --catalog whynot-design-npm-publish` reads\n`secret/coulomb/whynot-design/npm/publish`.** That is the legacy, ungoverned\nduplicate, not the governed lane.\n\nDerivation, which is short because there is no indirection to hide in:\n\n- `catalog/whynot-design-npm-publish.yaml` declares `mount: secret` and\n `path: coulomb/whynot-design/npm/publish`.\n- `exec_with_secret` delegates the read to `_fetch_value` in\n `src/secrets_engine/exec_delivery.py`, which issues\n `kv get -format=json {entry.mount}/{entry.path}` inside the lane's AppRole\n session. The path is the catalog pointer, concatenated, with no override,\n fallback, alias, or environment substitution anywhere on the exec path.\n- `publication_policy.resolve` and `delivery_config.npm` decide the injected\n env-var name and the npm registry. Neither touches the KV location. Nothing\n in `routing.py`, `safe_paths.py`, or the policy layer rewrites mount or path.\n\nSo railiance-platform's straightforward reading was the right one. The proven\n2026-07-03 `@whynot/design` pilot published by reading the legacy duplicate, and\nthe lowercase `npm_token` field this repository has consistently reported is the\nfield **there** \u2014 which is why it never appeared at the governed path and why\nnobody's record was wrong. ops-warden's `NPM_AUTH_TOKEN` and this repository's\n`npm_token` were each correct about the location each side was describing.\n\nThe consequence is the one ops-warden named and it should be stated plainly\nrather than softened: ops-warden's routing catalog lists secrets-engine as\n`exec_owner` and routes callers here as the primary front door, so that front\ndoor currently points at a path no CCR covers, and CCR-2026-0001's acceptance\nevidence describes a path its consumer does not use. That is a real governance\ngap, not a bookkeeping mismatch.\n\n**Not answerable here, and not attempted:** whether the two locations hold the\nsame value. That is a value comparison. This repository will not read, fetch,\nfingerprint, or compare either value, and has not. It is custody's question and\nneeds no answer from us to proceed with the path move.\n\n#### What it would take to move to the governed path\n\nThe move is a reviewed production lane change, not an edit. In order:\n\n1. **Custody confirms the governed lane is consumable by this lane's identity.**\n `platform/workloads/coulomb/whynot-design/npm-publish` under CCR-2026-0001\n grants read to the workload policy; the AppRole this engine's delivery\n session assumes must be admitted on `platform/data/...` and\n `platform/metadata/...` of exactly that path. Without that, the edit produces\n a lane that denies on read.\n2. **Reconcile the field name in the same change.** The catalog declares\n `npm_token`; the governed path was enumerated by railiance-platform on\n 2026-09-10 as holding exactly one field, `NPM_AUTH_TOKEN`. Moving the path\n without moving `fields:` produces `field 'npm_token' absent in lane` from\n `_fetch_value`. The injected env var is separately resolved and stays\n `NPM_AUTH_TOKEN` while netkingdom is `maturity-build`; after the move the KV\n field name and the injected env-var name coincide, which is a coincidence and\n must be annotated as one so the category error corrected on 2026-09-09 is not\n reintroduced.\n3. **Carry an approval.** The lane's `approval.model` is `decision`; this is a\n production lane pointer change and takes its own approved decision, not the\n existing `e6381a56` pilot decision.\n4. **Re-verify positive and negative.** The lane's declared expectations \u2014 the\n approved consumer reads the field, an unrelated identity is denied \u2014 must be\n re-run against the governed path before the old pointer is abandoned.\n5. **Update the derived records:** `docs/whynot-design-real-publish-closeout.md`\n pointer table, `docs/hardening-backlog.md` (which already names both\n locations), and `docs/cli.md`.\n6. **Only then is destruction of the duplicate safe.** RPF-WP-0035-T07 holds\n destruction pending this confirmation, correctly. The confirmation it was\n waiting for is now given, and it is the unwelcome one: the duplicate is the\n live consumer path, so it must not be destroyed or wrapped until this lane\n has moved and re-verified. Destroying it today breaks production publish.\n\nNote also `scripts/demo-e2e.sh:66`, which grants a policy on\n`secret/data/prod/coulomb/whynot-design/npm` \u2014 a third, demo-only spelling under\na `prod/` prefix. It is a throwaway demo fixture and not a consumer lane, but it\nshould be renamed away from `prod` when the lane moves so it cannot be mistaken\nfor a fourth location.\n\n`SECRETS-WP-0006-T06` stays `wait`: this answer unblocks the question, not the\nlane change, which needs custody's step 1 and its own approval.\n\n\n### Existing-work review \u2014 2026-09-27\n\nThe September 16 native OpenRouter key-check receipt supersedes the older\nserving/ESO-health wait for that exact recipient. SECRETS-WP-0007-T04 and\nSECRETS-WP-0008-T02 are now closed against that real evidence and current\nregression coverage. T05 remains open for the other lanes; T06 retains\nper-lane routing/proxy retirement and the npm custody discrepancy. No broader\nrecipient, proxy retirement, or production action is inferred from that receipt.\n\n\n## Loose-end review \u2014 2026-09-28\n\nReviewed all remaining tasks against the native OpenRouter acceptance and current\nGlas receipts. T05 still requires acceptance for the other catalog lanes; T06\nstill requires owner-agreed proxy retirement and platform custody disposition\nof the npm pointer. No remaining task is independently completable in this repo.\nBoth tasks remain wait; the workplan is now blocked. Existing accepted actions\nare not authority for other lanes or routing changes."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/secrets-engine/workplans/SECRETS-WP-0007-production-lifecycle-hardening.md",
|
|
"meta": {
|
|
"id": "SECRETS-WP-0007",
|
|
"type": "workplan",
|
|
"title": "Production-safe provisioning, authorization, and lifecycle hardening",
|
|
"domain": "infotech",
|
|
"repo": "secrets-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "custodian",
|
|
"created": "2026-08-23",
|
|
"updated": "2026-09-28",
|
|
"state_hub_workstream_id": "68a39be1-bd9c-5133-ad64-e7bca892aaf3"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "SECRETS-WP-0007-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5ddba36d-bc86-5670-baf1-50c872e6577e",
|
|
"body": "Completed 2026-08-23. During containment, existing multi-field provisioning\nfailed before file read or backend access. Ordinary `revoke` builds one\nlifecycle plan used by both\ndry-run and live execution, deletes only engine-managed native AppRole/policy\nobjects, and explicitly preserves KV custody, external delivery auth, and\nworkload delivery. No destructive KV command remains on the ordinary CLI.\nFocused lifecycle, admission, auth-capability, and throwaway OpenBao integration\ntests pass. The temporary multi-field rejection was then superseded by the\nmerge-safe primitive completed in T02.\n\nAdd immediate fail-closed guards before implementing replacement primitives:\n\n- reject `provision` on an existing multi-field lane;\n- reject or rename the current destructive KV `revoke` path so it cannot be\n mistaken for soft deactivation;\n- make KV revoke dry-run render exactly the operations the live path would run;\n- document that `SECRETS-WP-0006` may apply/verify metadata but must not provision\n or revoke shared values through the current commands.\n\nAcceptance:\n\n- A regression test proves no backend call occurs for multi-field existing-lane\n provisioning.\n- A regression test proves dry-run and live operation plans contain the same KV,\n AppRole, and policy targets.\n- The destructive action requires an explicit name/flag and a separately\n approved action; ordinary revoke cannot destroy KV metadata.\n- CLI/help/runbook language no longer describes metadata deletion as reversible\n deactivation.\n\n## Implement merge-safe, non-argv provisioning"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0007-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "ddf3ed54-9cbc-5e18-b15a-5da14cda5d9b",
|
|
"body": "Completed 2026-08-23. Replaced raw `field=value` argv writes with a CAS-aware\nbackend primitive: new paths use CAS-zero create; existing paths use server-side\nHTTP patch with the observed metadata version. Values travel through a\nmode-0600 temporary JSON reference removed in `finally`, and never appear in\nargv. Unit tests inspect the full request/cleanup; throwaway OpenBao integration\nproves sibling preservation and stale-CAS rejection. Stage policies now include\nthe narrow KV `patch` capability needed by this operation.\n\nReplace the raw `field=value` subprocess call with a backend write primitive\nthat never places the value in argv and safely updates one or more declared\nfields without removing unmentioned siblings. The design may use OpenBao CAS,\na merge/patch operation, an input file reference with strict cleanup, or direct\nrequest input, but it must remain isolated behind `OpenBaoClient` and preserve\nthe catalog field allowlist.\n\nAcceptance:\n\n- Unit tests inspect the complete subprocess request and prove the fake value is\n absent from argv, environment, output, exceptions, and evidence.\n- Throwaway OpenBao integration proves updating one field preserves every\n sibling field and fails closed on a CAS conflict.\n- Multi-field input is atomic from the caller's perspective; a partial failure\n cannot silently leave an unreported mixed version.\n- Source and generated inputs retain mode/path guards and guaranteed temporary\n cleanup.\n- Production generation remains forbidden, and high-risk production\n provisioning is still decision- and dual-control-gated.\n\n## Split suspend, deactivate, and destroy semantics"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0007-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "bb6073e1-c952-5357-b707-5574cef50f2f",
|
|
"body": "Completed 2026-08-29. Suspend, deactivate, and destroy share one plan object\nfor dry-run and live execution. Ordinary `revoke` aliases native deactivation\nand preserves KV custody plus externally managed workload delivery. Live\ndestroy stays fail-closed until T04's exact-action contract; that is the\ndesigned containment, not unfinished T03 work. Issued delivery sessions\nself-revoke in T05.\n\nResidual from this task, now implemented: `secrets-engine session revoke`\n`--accessor-file` or `--lease-id-file` (hardening H4a).\n\nProgress 2026-08-23. Added one lifecycle plan model shared by dry-run and live\nexecution. Ordinary `revoke` safely aliases native deactivation; suspend and\ndeactivate preserve KV custody and externally managed workload delivery.\nDestroy has an unmistakable dry-run plan and exact-id confirmation, but its live\nhandler is deliberately fail-closed before coarse lane approval or backend\naccess until T04 supplies distinct action authorization. Scoped issued-session\nself-revocation is implemented in T05; a general known-accessor operator\ncommand is `session revoke --accessor-file` (H4a).\n\nReplace the overloaded `revoke` behavior with explicit lifecycle operations and\nplans. Define at least:\n\n- **suspend delivery**: stop minting new native delivery sessions while\n preserving custody and a documented rollback;\n- **deactivate native access**: remove/disable the lane AppRole and consumer\n policy without deleting the KV value;\n- **revoke issued sessions**: revoke known tokens/leases by non-secret accessor\n where the backend supports it;\n- **destroy custody metadata**: irreversibly delete KV metadata/versions only\n through an unmistakable, separately approved action.\n\nPreserve compatibility only where it cannot mislead. A legacy `revoke` alias\nmay map to a safe non-destructive action; it must never silently retain the\ncurrent destructive meaning.\n\nAcceptance:\n\n- Each operation has a guarded dry-run plan, exact targets, distinct approval\n action, non-secret evidence, and documented rollback/irreversibility.\n- Dry-run and live use the same plan object rather than separate handwritten\n descriptions.\n- Integration tests prove suspend/deactivate preserve KV data and destroy does\n not run without its explicit approval and confirmation contract.\n- Auth-capability and KV lanes have coherent but kind-appropriate behavior.\n- Existing workload delivery is reported as an external dependency and is not\n deleted by native lifecycle commands.\n\n## Bind approvals to exact production actions"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0007-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4b58edec-c705-55e5-9ece-362e1ff13079",
|
|
"body": "Completed 2026-09-27 by reconciling the implemented shared approval guard with the\n2026-09-16 native receipt. See the closure note below; the serving-path waits\nin the dated history are superseded. Native lane cutover remains T07.\n\nWait 2026-08-29. The consumer validator and production fail-closed gate are\nshipped. What remains is not local engine work: State Hub / `access-engine`\nmust serve the durable ActionAuthorization object. Paired with\n`SECRETS-WP-0008-T02`. Do not reopen live production on hub status or local\nfixtures.\n\nProgress 2026-09-02. `GH-DEC-2026-003` consume-before-OpenBao is now a\nshared production gate: `_require_lane_approval` CAS-consumes through\napproval-engine before any OpenBao client is resolved. Tests prove 409,\nunreachable, and missing-binding paths never call OpenBao. Live production\nstays fail-closed until the durable object is served; this task remains\n`wait`.\n\nProgress 2026-08-23. flex-auth revision `c473f19` now supplies execute-time\nstructured binding and the proposed durable `ActionAuthorization` schema. The\nengine builds and fail-closed validates the exact secrets-engine profile,\nvalidity, State Hub authority, decision digest/binding, accepted policy\nrevision, and a caller-selected minimum distinct-approver threshold. Every live\nproduction handler now carries its action into the shared gate and fails before\nOpenBao while State Hub lacks the durable endpoint. Legacy local decisions are\nreachable for prod-labeled lanes only with an explicit unsafe-demo switch,\ndisabled Hub URL, and loopback OpenBao. The throwaway scripts declare that\nexception. Live destroy remains disabled independently. State Hub endpoint and\nauthenticated approval storage are still outstanding. flex-auth corrected its\nexample digest and added a complete binding regression assertion in `d402408`.\n\nCorrection 2026-09-06. The 2026-08-29 note above (\"What remains is not local\nengine work\") was wrong. `resolve_consume_binding` was a `return None` stub, so\nprotocol step 1 (PIP `GET /v1/approvals/{id}/claim`) and the validation join\nwere never implemented, and `validate_action_authorization` \u2014 the validator this\nplan called \"shipped\" \u2014 had no caller in `src/` at all. Only step 3 (CAS\nconsume) and the OpenBao gate were real. Production fail-closed was therefore\ncorrect but for a second, undocumented reason.\n\nThe join is now implemented. `resolve_consume_binding` reproduces the exact\nCheckRequest via `build_action_request`, fetches the durable\nActionAuthorization, and validates request binding, digest, validity, authority,\npolicy pin, and distinct-approver threshold before returning a binding.\n`_require_lane_approval` threads the exact field set for provision, rotate,\nverify, and exec so the digest covers the real proposed action. Eight tests in\n`tests/test_consume_binding_join.py` cover unconfigured, half-configured, digest\nmismatch, action mismatch, unreachable, and superseded paths.\n\nTwo deliberate choices, both recorded in `docs/approval-consumption.md`:\nthe approval-engine object id is never inferred from a State Hub decision UUID\n(flex-auth: `GET /decisions/{uuid}` is not the durable object); and there is no\ndefault policy pin, because flex-auth stated `secrets-engine.lifecycle`/`v1` is\nexample vocabulary rather than a published package.\n\nBehavior today is bit-for-bit unchanged: every new input is absent by default,\nso an unconfigured engine still fails production closed, and `plan`/`--dry-run`\nstill work. This task stays `wait`, but the remaining constraint is now purely\ndeployment: approval-engine must serve the claim endpoint and access-engine must\nserve Check. Probed 2026-09-06 \u2014 neither is reachable, and State Hub exposes\nonly `/decisions/`.\n\nInbound 2026-09-06 (approval-engine `APPROVAL-IN-0002`, flex-auth\n`FLEX-DEC-2026-005`). The join committed in `627810b` validates the wrong\nartifact and must not be extended until gate-house rules.\n\n- `ActionAuthorization` is a PROPOSED, unratified object from flex-auth's own\n contract. It appears zero times in gate-house and state-hub. `GH-DEC-2026-003`\n already names step 1 as `GET /v1/approvals/{id}/claim -> valid_now`, an\n approval-claim field that `ActionAuthorization` does not carry. The claim body\n is an approval-claim envelope, not an `ActionAuthorization`.\n- Confirmed defect, ours, independent of the ruling: `authorization.py` pins\n `AUTHORITY = \"state-hub\"` and enforces it unconditionally, contradicting\n flex-auth's statement that State Hub decision records are not the runtime\n approval authority and our own read-model doctrine. Not patched yet: under\n option A the authority check belongs on the claim issuer, so it moves with the\n split rather than being guessed twice.\n- If gate-house confirms option A, `validate_action_authorization` splits across\n the two artifacts already fetched: the claim carries approval fact (binding\n digest, validity window, consumption state, freshness, issuer); the step-2\n DecisionEnvelope carries exact CheckRequest match and the package/version pin.\n No check is lost. Do not start until the ruling.\n- Auth gap, tracked separately so it does not ride the envelope decision: we\n send a static mode-0600 token as Bearer. Production verifies a KeyCape RS256\n JWT against JWKS and refuses opaque tokens. Requested registration clientId\n `secrets-engine-approval`, scopes `approval:read` + `approval:consume`,\n client_credentials, confidential. `aud` MUST be the resource server\n `approval-engine`, never the clientId. `service_auth.py` already implements\n this exchange for `secrets-engine-openbao`, so this is a second registration.\n- approval-engine `APPROVAL-WP-0002-T03` will publish the base URL; it is not\n deployed anywhere today and proceeds on its own evidence. The envelope\n question gates our first live consume, not their rollout.\n- flex-auth endorsed the no-default-pin decision explicitly. The reserved\n coordinate `secrets-engine.catalog-lane.lifecycle` / `v1` is a RESERVATION,\n not a publication; our pin stays unset. `docs/gated-actions.md` delivers the\n authoritative twelve-action list `FLEX-WP-0021-T01` was blocked on. No\n estate-wide PDP exists by design: flex-auth runs per-consumer cluster-local\n pins, and `flex-auth-secrets-engine` has not been created yet, so the\n 2026-09-06 probe finding was the design working rather than an outage.\n\nResolved 2026-09-06 by gate-house `GH-DEC-2026-005` (GH-IN-0002), settling\napproval-engine's `APPROVAL-IN-0002`. Both changes it assigned to this repo are\nimplemented.\n\n1. The validator is split by owning layer. `approval_claim.validate_approval_claim`\n consumes approval-engine's approval-claim for the approval fact (issuer,\n `valid_now`, consumption state, binding digest, freshness, `reason_code`).\n `authorization.validate_decision_envelope` consumes the flex-auth\n DecisionEnvelope for the decision (effect, exact CheckRequest binding,\n canonical request digest, lifetime, policy package/version pin). Neither\n republishes the other's data. `ActionAuthorization` is deferred and never\n ratified (`FLEX-DEC-2026-006`); nothing validates it any more.\n2. `AUTHORITY = \"state-hub\"` and the `provenance.authority` requirement are\n gone. flex-auth traced the constant to their own fixture\n (`examples/caring/action_authorization.json`), which contradicted their\n ownership section \u2014 their bug, fixed at source. State Hub is a read model and\n holds no runtime approval authority, so the check failed closed against every\n correctly issued record.\n\nTwo consequences worth stating rather than burying:\n\n- There are now **two different digests** over the same proposed action, by\n contract, never compared to each other: the approval-engine native binding\n digest over `{action, actor, principal, purpose, target}`, and the flex-auth\n canonical CheckRequest digest. `claim.binding.pdp_digest` is preferred when\n the issuer recorded one. The CheckRequest digest itself is unchanged and its\n contract test is preserved verbatim \u2014 flex-auth confirmed only the envelope\n went away, not the digest join.\n- The distinct-approver threshold is **no longer a consumer-side check**. The\n claim does not expose approver entries; approval-engine folds that requirement\n into `valid_now`. We now rely on the issuer for it, which is the correct layer\n but is a real reduction in what this engine verifies independently.\n\nStill outstanding, unchanged by the ruling: step 2 needs the\n`flex-auth-secrets-engine` Service DNS (not created \u2014 per-consumer cluster-local\npins are the design, so the earlier \"no reachable PDP\" probe was not an outage)\nand the published package from `FLEX-WP-0021-T02`. The pin stays unset.\n`docs/gated-actions.md` delivered the twelve-action vocabulary that unblocks\n`FLEX-WP-0021-T01`. Separately tracked: production requires a KeyCape RS256 JWT,\nnot the static Bearer token this engine currently sends.\n\nClosed out 2026-09-06. gate-house amended `GH-DEC-2026-005`; flex-auth published\nthe policy package (`FLEX-WP-0021-T01`/`T02` done, commit `f75db59`).\n\n- `secrets-engine.catalog-lane.lifecycle` v1 exists with both manifests, a\n loadable registry snapshot, 26 fixtures and five standalone check requests;\n `validate -kind policy` reports 22/22 Rego tests and 26/26 fixtures. Our\n vocabulary is recorded in flex-auth `docs/secrets-engine-action-vocabulary.md`.\n All four constraints from `docs/gated-actions.md` are encoded rather than\n assumed: `test_revoke_is_not_an_action` asserts `revoke` denies\n `unknown_action`, `destroy` is fixtured as the dual-control case before\n `T04` opens the path, `compromise`/`reactivate` are annotated overlay-only,\n and the ungated verbs deny `unknown_action`. flex-auth reports four of the\n twelve would have been inferred wrongly, `revoke` most confidently.\n- **A published limit now rests on a property of this repo.** `apply` and\n `apply --dry-run` are indistinguishable to a PDP; both arrive as action\n `apply`. What separates them is that our PEP does not call the gate for a dry\n run. flex-auth recorded that as a limit rather than implying a control they do\n not have, and asked to be told if the assumption stops holding.\n `tests/test_dry_run_never_gates.py` now enforces it across all five dry-run\n handlers, with a paired test proving the hook is load-bearing. Changing a\n dry-run path to gate is now a test failure carrying the instruction to notify\n flex-auth first.\n- Dual control on `destroy` checks what the claim *says* (two distinct approver\n subject ids). flex-auth deliberately does not re-derive temporal validity,\n signature, or supersession \u2014 those are approval-engine's to assert and **ours\n to verify against the live claim**. `validate_approval_claim` is that check.\n- `allow_ttl` is 15m in the package, stated rather than left to an engine\n default. Per `FLEX-DEC-2026-004` that is authority to *issue* the operation,\n not to keep using what it produced; bounding a delivered secret's own lifetime\n is ours. Already satisfied: `normalize_wrap_ttl` caps wrap at 15m and lane\n AppRoles carry 5m/15m token TTLs with a single-use Secret ID.\n- Structural note carried as a revisit trigger, not a defect: because we named\n exactly one calling identity, the denial ladder has no `action_not_granted`\n branch \u2014 with one subject holding all twelve actions it could never fire, and\n a rule that cannot fail reads as per-action control that is not there.\n Registering a second identity, or splitting the CLI identity by lane or stage,\n is the trigger; adding the branch then is additive and needs no request-shape\n change.\n- gate-house struck the G3 revisit trigger for a composed authorization object,\n verified against the DecisionEnvelope schema: `lifetime` is required whenever\n effect is allow, so carrying its own end \u2014 the one structural thing the bundle\n did that the split does not \u2014 is already answered. Three triggers remain: a\n third or fourth PEP-shaped consumer, a single signed forwardable artifact, and\n \u00a717 request-claim assent.\n- On the approver threshold we stopped checking, gate-house recorded both that\n it is correct on layering **and** a genuine reduction in defence in depth,\n noting a decision recording only the first would be self-serving. The\n compensating property is reconstructability at the issuer under \u00a79.6 \u2014\n detection, not prevention \u2014 not a second check here.\n\n**The pin stays unset.** Publishing is not deploying: there is still no\n`flex-auth-secrets-engine` pin and therefore no address to call. `T04` stands it\nup in `callerAuth.mode warn`; `T05` hands over the Service DNS and confirms the\npackage/version to configure. Next inbound is the `T03` replay fixture \u2014 a real\nDecisionEnvelope from this package including `provenance.registry_snapshot_digest`\n\u2014 to verify the digest join unchanged.\n\nVerified 2026-09-06 against flex-auth's `T03` replay fixtures\n(`FLEX-WP-0021-T03`, commit `9e10d1c`), vendored to\n`tests/fixtures/flex-auth-replay/`. Running them found a defect of exactly the\nclass we had just been warning about.\n\n- **`request_digest` was hashing fields the contract excludes.** The material is\n `tenant`, `subject`, `action`, `resource`, `context` only; `id` is correlation,\n `policy_version` lives in provenance, and `caring_context` is hashed\n separately. This engine included all three when present. Because the join\n adopts the served request id, every real production request would have carried\n one, so the computed digest would have matched no issued decision and failed\n closed against every correct allow \u2014 the same unsatisfiable-rule shape as the\n removed `AUTHORITY` constant and as flex-auth's own destroy rule in `68ad039`.\n Fixed by `digest_material`; both fixtures now reproduce their published\n digests exactly.\n- The previously pinned digest constant was computed *with* the id inside the\n material, so it was wrong and its passing was not evidence. It is replaced by\n fixture-driven contract tests over two real envelopes plus a structural test\n that correlation fields do not move the digest. Both fixtures are required:\n `provenance.input_claim_digests.context` appears only with a non-empty context.\n- **The native claim digest is unusable and is no longer computed.** The claim's\n `binding.action`/`binding.target` speak approval-engine's vocabulary while ours\n speaks the catalog's, and no mapping is published; flex-auth makes no\n cross-check and states the correspondence is ours via `pdp_digest`. A claim\n recording no `pdp_digest` now fails closed naming the missing mapping rather\n than comparing two vocabularies. **A published mapping is a prerequisite for\n making `destroy` reachable under this task.** flex-auth offered to co-author it\n with approval-engine.\n- Narrowing accepted from approval-engine: `entries` is UNIQUE on\n `(approval_id, subject_id)`, so approver distinctness is a storage invariant,\n not a count this engine was previously protecting. What we stopped verifying is\n that approval-engine applies its own invariant correctly \u2014 still a real\n reduction in defence in depth, but narrower than \"the threshold is now\n unverified\". They also added `threshold` objects to issuance and use events\n (`87e55e2`) so the evaluation is reconstructable under \u00a79.6.\n- flex-auth corrected the `destroy` dual-control rule (`68ad039`) before\n generating these fixtures: it had required `context.approval.status ==\n 'approved'` and an approver list, neither of which exists in the claim schema.\n Our acknowledgement of the earlier rule crossed that fix. The corrected rule\n requires only kind/issuer/`valid_now`, and our claim validation is unchanged.\n- One global pin confirmed correct: `secrets-engine.catalog-lane.lifecycle` v1 is\n one package covering all twelve actions. Do not build per-action pin\n configuration for a distinction that does not exist.\n\nBrought into practice 2026-09-06. The chain is complete in code and proven end\nto end; what remains is deployment only.\n\n- Step 2 is implemented (`decision_check.check_decision`, POST `/v1/check`) and\n `approval_consume.authorize_action` coordinates steps 1 and 2. Both build the\n same CheckRequest through one `_expected_request`, since two descriptions of\n the proposed action cannot produce corresponding digests.\n- `apply_unreachable_engine_stance` now takes `authorized=`. The published map\n defines `fail_closed` as no protected side effect *without* a durable\n access-engine decision record, so holding a validated one means the engine was\n reachable and the residue does not apply. This is not a stance bypass: both\n steps must have succeeded, CAS consume still precedes OpenBao, and with\n nothing configured `authorize_action` returns `None` and production fails\n closed exactly as before. Verified by CLI, not only by unit test.\n- `tests/test_integration_authorization.py` drives the real gate through\n claim -> check -> consume -> OpenBao against a live throwaway OpenBao, and\n asserts PIP-before-PDP ordering, consume as the last step before the backend,\n and that an unreachable PDP, a denied decision, an invalid claim, a missing\n `pdp_digest`, a consume conflict, and an action mismatch each stop before the\n backend. The stub serves transport and sequencing only; wire contracts stay\n pinned to flex-auth's real fixtures.\n- The end-to-end run found a third instance of the cross-vocabulary defect: a\n leftover comparison of the claim's `binding.action` against ours. Real claims\n say `secrets.kv.destroy` where we say `destroy`, so it would have failed\n against every one of them. Removed; the tie is `pdp_digest`. Worth noting the\n pattern: unit tests with self-consistent fakes hid all three, and each was\n found only by a real artifact or a real chain.\n\nDestroy gate closed 2026-09-06 (inbound `FLEX-DEC-2026-007`, `GH-DEC-2026-008`,\napproval-engine schema v3). The vocabulary mapping this task was waiting on is\nnot coming, and it should not have been waited on: gate-house rejected it\noutright, for the reason flex-auth and approval-engine both gave independently \u2014\na translation can be confidently wrong and fails **open** by accepting a claim\napproved for a different action. The stronger option arrived instead, and both\nhalves of it are now enforced here.\n\n- **The circularity we reported is fixed at source.** A `pdp_digest` recorded at\n approval-issue time can never equal the `request_digest` of a request that\n carries the claim in its hashed context. With `GH-DEC-2026-008` requiring that\n equality on the PDP path, destroy would have been permanently un-allowable,\n failing closed forever on a check no correct record could pass. flex-auth\n published `binding.approval_binding_digest` (commit `dd3ce4c`): the same\n canonical digest with `context.approval` removed, stable across attaching the\n claim. The comparison is against that field, never `request_digest`.\n- **`request_digest` deliberately still covers the claim**, so the two digests\n disagree on a claim-bearing request and that disagreement is load-bearing: two\n requests differing only in which approval was presented must not share a\n replay identity, or an allow obtained with a valid claim could be replayed\n against a request carrying none. `approval_binding_digest` is not a replay\n identity and is not used as one.\n- `authorization.approval_binding_digest` implements the published exclusion\n rule, including flex-auth's `json:\"context,omitempty\"` behaviour of dropping a\n context that strips empty. `digest_material` now drops an empty context for the\n same reason. `validate_decision_envelope` recomputes the field when present\n rather than trusting it, refuses a claim-bearing request whose decision records\n none, and takes the claim's digest from step 1 as `expected_approval_binding_digest`.\n- **`binding.pdp_path` is required true** before `pdp_digest` is used at all.\n It is approval-engine's declaration that the approval was requested against a\n bound CheckRequest; their `create()` refuses `pdp_path` true without a digest,\n so the declaration guarantees the digest. The converse is not inferred: a\n digest present for some other reason is no declaration, and pre-v3 approvals\n carry `pdp_path` false regardless of any digest they hold.\n- The cost is accepted rather than engineered around: an approval requested\n without a bound CheckRequest is not usable on this path and will not become\n usable later. If a real destroy workflow cannot bind at issue, that is the\n falsifier gate-house wrote into the reversal and it gets raised, not\n worked around.\n\nThe replay fixtures are re-vendored from `dd3ce4c`, and the pins moved a second\nand final time (`request_digest` `sha256:c749ee2d\u2026`, context input-claim digest\n`sha256:8b73d29e\u2026`; `approval_binding_digest` `sha256:fa07becf\u2026`, which did\n**not** move \u2014 that is the point). The fixture now demonstrates the property\ninstead of asserting it: `test_pdp_digest_equals_the_published_approval_binding_digest`\nrederives `fa07becf\u2026` from the fixture's own request through our canonical\nimplementation, which is a hermetic proof that this engine hashes the same\nmaterial flex-auth does. A pin alone would only have asserted the constant.\n`decision_rotate.json` is unchanged and carries no `approval_binding_digest`;\na test pins that omission so the field is not silently duplicated onto ordinary\ndecisions.\n\nOur own CheckRequest stays claim-free (`context` is `{\"purpose\": \u2026}`), so the\nidentity holds transitively today; the code is already correct for the day we\ncarry a claim in context.\n\nStill open and still ours: the T04 consumer-shape question flex-auth has asked\ntwice \u2014 operator CLI reaching an in-cluster pin, a workload we do not have yet,\nor no pin at all. It is a deployment-shape answer, not engine work, and it is\nthe reply owed on that thread.\n\nRemaining to go live is configuration and deployment, not engine work:\n`SECRETS_ENGINE_PDP_URL`/`_PDP_TOKEN_FILE` (awaiting the `flex-auth-secrets-engine`\npin, `FLEX-WP-0021-T04`/`T05`), `SECRETS_ENGINE_APPROVAL_URL`/`_TOKEN_FILE`\n(awaiting `APPROVAL-WP-0002-T03`), the policy pin (published but not to be set\nuntil T05), a KeyCape RS256 credential in place of the static Bearer token, and\n`approval.authorization_id` on each lane. Destroy's additional requirement is\nnow met in code: the `pdp_path` + `approval_binding_digest` identity replaced the\nvocabulary mapping that was never going to exist.\n\nDefine and enforce the decision contract needed by production commands. A\nresolved approval must bind at least:\n\n- canonical decision UUID and non-superseded status;\n- catalog id and stage;\n- action (`apply`, `provision`, `verify`, `exec`, `handoff`, `suspend`,\n `deactivate`, `destroy`, or later `rotate`);\n- exact field set or policy/auth targets where applicable;\n- requesting actor/purpose and expiry or bounded execution window;\n- required approval count and distinct approvers for `dual-control`.\n\nCoordinate the external object shape with State Hub/flex-auth rather than\ninventing authorization ownership in this repo. Keep local fixtures for\nthrowaway demos and non-production tests only; require an explicit unsafe-demo\nswitch if they remain reachable at all.\n\nAcceptance:\n\n- Every privileged production handler passes an action-specific request into\n one shared authorization function.\n- Tests reject wrong lane, stage, action, field set, actor/purpose, expiry,\n superseded status, insufficient approvals, duplicate approvers, and local\n production fixtures before any OpenBao call.\n- `approval.model: dual-control` has enforced semantics rather than being a\n label.\n- Catalogs use resolvable canonical decision UUIDs for live actions; legacy CCR\n references remain provenance, not executable authorization.\n- State Hub outage fails production actions closed while dry-run/catalog\n inspection remains usable.\n\n## Make delivery sessions short-lived and explicitly closed"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0007-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "36bcd64d-8b27-542d-b8da-ede1a4d3c22f",
|
|
"body": "Completed 2026-08-29. Delivery AppRole sessions self-revoke in `finally` on\nexec and both verification kinds. Bootstrap is a named provider with no\nimplicit fallback from the KeyCape scaffold. Wiring that scaffold as OpenBao\nJWT login is `SECRETS-WP-0008-T06` / hardening H1, blocked on the\nplatform-owned role \u2014 not remaining T05 engine work.\n\nProgress 2026-08-23. AppRole login material now travels through strict temporary\nJSON input rather than argv. Exec and both verification kinds use a scoped\nsession that self-revokes in `finally`, drops the in-memory token even when\ncleanup fails, and exposes only an accessor fingerprint plus cleanup booleans as\nevidence. Tests cover success and exception cleanup, idempotence, failed revoke\nvisibility, and value/credential exclusion. Provider review requests were sent\nto railiance-platform (`8f910aff-3a94-43c6-8805-eb9276e46fc0`) and key-cape\n(`0627ca55-115e-43dc-b2f6-3195be3bc90d`); steady-state engine authentication\nremains external-contract work.\n\nKeyCape has accepted the `secrets-engine-openbao` service contract. An explicit\nconsumer scaffold now performs HTTPS client-credentials exchange, strict\nout-of-repo client-secret input, exact claim/assurance/lifetime preflight,\nthree-minute renewal classification, and rejection of ID/refresh tokens. It has\nno bootstrap/operator/AppRole fallback and is deliberately not wired into the\nCLI until railiance-platform materializes the exact OpenBao JWT mount and role.\n\nRefactor AppRole login into a scoped session object that retains only the\nminimum non-secret lifecycle handle needed to revoke the issued token in a\n`finally` path. Apply it consistently to exec, KV verification, auth-capability\nverification, and any future file/wrapped delivery.\n\nDefine the steady-state OpenBao authentication interface separately from the\ndelivery AppRole. Bootstrap token files remain an explicit break-glass/setup\nprovider; add a bounded OIDC/service-auth provider only with railiance-platform\nand identity-owner review.\n\nAcceptance:\n\n- Success, child non-zero exit, setup failure, verification failure, SIGINT, and\n SIGTERM tests all attempt token revocation and clean temporary material.\n- Secret IDs remain single-use where configured; tokens retain TTL/use limits\n as backstops rather than their only cleanup.\n- Evidence records session establishment/revocation outcome using non-secret\n handles or request ids only.\n- A failed revocation is visible and actionable without printing token or\n accessor material.\n- Bootstrap-file authentication is clearly separated from the reviewed\n steady-state provider and cannot become an implicit fallback.\n\n## Strengthen verification, readiness, and evidence"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0007-T06",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "431bc91b-439e-595a-8a8a-7d4c82e68322",
|
|
"body": "Completed 2026-08-29. Acceptance is met: multi-field readiness, real unrelated\nidentity for KV denial, privileged attempt/terminal evidence, and `audit`.\nResiduals belong elsewhere: exact-action authorization is T04 /\n`SECRETS-WP-0008-T02`; OpenBao audit request-id correlation is hardening H5;\nunrelated-identity *selection* for production remains an owner/ops concern,\nnot an engine mint.\n\nProgress 2026-08-23. KV verification now checks every declared field by default,\nwith one path-level negative probe, and route readiness reads once and requires\nall declared fields. Missing readiness evidence contains field names only. Tests\nprove a missing sibling makes readiness false. Evidence delivery attempts now\nreceive append-only local success/failure receipts, and `audit` produces an\nallowlisted per-lane summary of actions, results, decisions, session cleanup,\nand delivery outcomes without echoing arbitrary detail. The real\nunrelated-identity input is now enforced as a strict mode-0600 out-of-repo token\nfile; absence fails closed, and throwaway OpenBao integration deliberately adds\nan overlapping unrelated read policy and proves the check fails. Production\nidentity selection/ownership, audit request correlation, queued/replayed State\nHub delivery, and exact-action authorization remain outstanding. All live\nprivileged handlers now share one attempt/terminal evidence guard: approval\nrejection, backend/input exceptions, interruption, verification failure, and\nsuccess are recorded without exception prose. Tests prove decision and backend\nfailures stop before inappropriate backend work and exclude fake secret text.\n\nState Hub evidence posts now carry stable idempotency, source-agent, and repo\nheaders. HTTP 202 edge-relay receipts are classified as `queued` and retain only\ntheir non-secret outbox id in the companion evidence record and lane audit.\nOutbox replay remains owned by State Hub/operator tooling.\n\nThe complete repository suite is re-run at each implementation slice, including\nthrowaway OpenBao integration coverage.\n\nMake verification and routing truthful for multi-field and high-risk lanes:\n\n- verify every declared field unless the exact approved subset is explicit;\n- make route readiness require every required field, not only the first;\n- replace the garbage-token negative check with a reviewed real unrelated\n identity/token or a capabilities-based denial proof that can detect policy\n overlap;\n- record attempt, success/failure, cleanup, and authorization outcome for every\n privileged command;\n- correlate engine evidence with OpenBao audit request ids where available;\n- provide a non-secret lane audit summary over local/State Hub evidence.\n\nAcceptance:\n\n- Removing any required sibling field makes readiness false and identifies only\n the missing field name, never values.\n- Negative verification fails when a deliberately overlapping unrelated policy\n is introduced in throwaway OpenBao.\n- Evidence tests cover backend exceptions, child failures, State Hub delivery\n failures, and cleanup failures without leaking fake secret patterns.\n- An audit/report command summarizes decisions, attempts, outcomes, and cleanup\n for a lane without becoming an authority or replacing OpenBao audit logs.\n- The full test suite and throwaway OpenBao integration suite pass.\n\n## Resume native production lane adoption"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0007-T07",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"SECRETS-WP-0006-T05",
|
|
"SECRETS-WP-0006-T06"
|
|
],
|
|
"blocking_reason": "Engine approval hardening is complete. Remaining per-lane cutover includes native routing/proxy retirement with ops-warden under SECRETS-WP-0006-T05/T06; the exact OpenRouter key-check receipt does not establish broader recipient readiness.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "a0a1dd92-d703-5a95-b488-d895f34d5cf7",
|
|
"body": "Dependency: T01\u2013T03, T05, T06 are done. T04 implements claim/PDP Check/CAS consume;\nActionAuthorization is deferred, not its serving prerequisite. Production still\nwaits on the admitted Approval Engine identity/audit/service and client-reader\npath, explicit per-lane approval and scoped attended platform authority.\n\n2026-09-14: SECRETS-WP-0010-T01/T02 implemented exact catalog-target binding and\nthe proposed value-safe OpenRouter recipient. FLEX-WP-0026 promoted the dedicated\nPDP to revision 4 and verified the live replay join. Native admission/verification\nremains SECRETS-WP-0010-T03; no real key was retrieved and this task remains wait.\n\nResume `SECRETS-WP-0006-T05` lane by lane. Apply only the exact native policy and\nbounded AppRole, verify every field plus unrelated-consumer denial, confirm the\nexisting workload delivery remains healthy, exercise only an approved\nvalue-safe child command, and record rollback/session-cleanup evidence.\n\nAfter a lane passes, complete `SECRETS-WP-0006-T06` with ops-warden. Retire its\ninterim proxy only after both parties agree that native readiness evidence is\ncomplete. Do not batch-retire all five lanes.\n\nAcceptance per lane:\n\n- Canonical action-bound approval is resolved and linked.\n- Policy/AppRole server readback matches the reviewed exact-path plan.\n- All declared fields pass presence/access checks; a real unrelated identity is\n denied; no value enters evidence.\n- Issued delivery sessions are explicitly revoked and cleanup is evidenced.\n- Existing ESO/OIDC delivery and application health remain good according to\n their owners.\n- Rollback is rehearsed or capabilities-safe verified before proxy retirement.\n- ops-warden routing reports native readiness and removes only that lane's\n interim proxy.\n\n## Dependencies and coordination\n\n- `SECRETS-WP-0006` owns the five-lane catalog admission and live cutover.\n- railiance-platform owns production OpenBao authority, custody, and backend\n audit.\n- State Hub/flex-auth own the canonical decision/authorization contract.\n- key-cape/user-engine own human/service identity and claims.\n- Workload owners own ESO/Kubernetes delivery and provider/application health.\n- ops-warden owns credential routing and interim proxy disposition.\n\nAny external contract change must be recorded as non-secret evidence and must\nnot transfer custody or authorization ownership into this repository.\n\n## Exit criteria\n\n- Current unsafe multi-field provisioning and misleading revoke behavior are\n contained and replaced.\n- Raw values cannot enter subprocess argv or evidence through provisioning.\n- Production approvals are canonical, exact-action, expiring, and genuinely\n dual-control-capable.\n- Delivery tokens are explicitly revoked on every exit path.\n- Readiness and verification cover all declared fields and meaningful unrelated\n identities.\n- Lifecycle operations distinguish reversible access suspension from irreversible\n custody destruction.\n- At least one of the five admitted production lanes completes the hardened\n native verification/cutover path; remaining lanes have explicit external\n blockers rather than engine-safety blockers.\n- Service-mode design remains deferred until these guarantees are demonstrated.\n\n\n### Native OpenRouter handoff from SECRETS-WP-0010 \u2014 2026-09-16\n\nSECRETS-WP-0010-T03 completed the exact read-only key-check recipient: native\napply and verify, distinct human-approved CAS consumption for all three actions,\nOpenRouter GET /api/v1/key HTTP 200, unrelated identity/path denials, explicit\nrevoked-token HTTP 403, and unchanged llm-connect/ESO health. Evidence:\n`docs/evidence/2026-09-16-t03-completion.json`. No inference was performed.\nThis supplies one lane's evidence; this workplan retains its existing broader\nlive adoption tasks. SECRETS-WP-0006-T05/T06 own other-lane acceptance and\nrouting/proxy retirement; SECRETS-WP-0007-T04/T07 retain general native readiness.\nDo not reuse the consumed approvals or treat the temporary key-check overlay as\napproval for a radar trial recipient. IR-WP-0005 owns radar delivery acceptance;\nIR-WP-0006 owns the outstanding USD 0.023712 billing reservation.\n\n\n### T04 completed after evidence reconciliation \u2014 2026-09-27\n\nThe original serving-path wait is superseded by the native 2026-09-16 receipt\n`docs/evidence/2026-09-16-t03-completion.json`, not by synthetic tests or Hub\nstatus. It records separate human-controlled apply, verify and exec approvals,\nthree distinct current PDP decisions/request digests, successful CAS consumes,\nand the resulting native OpenBao operations. The claim/PDP/consume join is the\naccepted path; the earlier proposed ActionAuthorization is not a dependency.\n\nCurrent regression coverage exercises wrong fields/actions/tenant/digest,\nsuperseded or expired claims, changed catalog/owner bindings, denied or missing\nPDP responses, consume conflicts/unavailability, declared human control and\nproduction fixture refusal. Every live privileged handler still uses the shared\napproval gate before backend access. The recorded approvals are consumed and\nexpired; they are historical completion evidence, never reusable grants.\n\nT04 is done. T07 stays wait because its per-lane acceptance includes routing and\nproxy retirement, and the receipt covers only the exact OpenRouter key-check\nrecipient. Other lanes and cross-owner cutover remain SECRETS-WP-0006-T05/T06;\nthis workplan is not finished merely because the engine gate is complete.\n\n\n## Loose-end review \u2014 2026-09-28\n\nT01\u2013T06 implementation is complete. T07 retains the per-lane acceptance and\nrouting retirement in SECRETS-WP-0006-T05/T06. The shared approval service and\nrequester chain have already been exercised natively; those historical serving\nprerequisites are resolved. Remaining gates are exact lane authority, attended\nacceptance and owner-agreed cutover. T07 remains wait; workplan now blocked."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/secrets-engine/workplans/SECRETS-WP-0008-layer-model-lifecycle-conformance.md",
|
|
"meta": {
|
|
"id": "SECRETS-WP-0008",
|
|
"type": "workplan",
|
|
"title": "Evolve the Lifecycle engine to the accepted security layer model",
|
|
"domain": "infotech",
|
|
"repo": "secrets-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "grok",
|
|
"topic_slug": "custodian",
|
|
"created": "2026-08-29",
|
|
"updated": "2026-09-28",
|
|
"state_hub_workstream_id": "9c9e5164-b2f5-5ea2-a557-5368d65e9fe0"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "SECRETS-WP-0008-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "945735c6-2d3d-5f72-baf0-692e6b210889",
|
|
"body": "Completed 2026-08-29. `_require_lane_approval` loads `pep-stance.yaml`.\n`SHIPPED_STANCE` is pinned equal to the published map. Fail-closed production\nevidence records `stance_stage`, `stance_failure_mode`, and omits\n`stance_decision_id` unless a decision was rendered.\n\n`pep-stance.yaml` is published and tests pin `prod: fail_closed` to\n`_require_lane_approval`. The gate is still hardcoded, and a refusal is\nrecorded as a `DecisionError` rather than named stance fields.\n\nLoad the published map as the source of shipped defaults. When the\nunreachable-engine residue is applied, record at least stage, failure mode, and\ndecision id present only where a decision was rendered. Keep the three-factor\nunsafe-demo exception out of the stance table. Assert map equality in\n`tests/test_layer_conformance.py` the way ops-warden's stance test does.\n\nAcceptance:\n\n- `_require_lane_approval` (or its successor) reads `pep-stance.yaml`.\n- Changing the YAML without changing the code fails the test, and the reverse.\n- Fail-closed production evidence includes named stance fields, never a secret.\n- Build/test remain fail-open *relative to access-engine* and still require\n the existing lane-approval check; that residue stays documented as a gap\n until T02.\n\n## Consume access-engine decision records"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0008-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "3eb9cff8-1441-5437-9e92-a2b655c82d04",
|
|
"body": "Completed 2026-09-27: the 2026-09-16 native apply/verify/exec receipt supplies\nthe live PDP/claim/consume return awaited below. The dated serving-path waits\nare historical. Service JWT adoption remains T06.\n\nProgress 2026-09-02. Gate House notice `632bdad9` (`GH-DEC-2026-003`): this\nengine is the PEP for FLEX-WP-0017-T05 / OpenBao writes. The shared consume\nfunction now lives in `src/secrets_engine/approval_consume.py` and every live\nprivileged production handler reaches it through `_require_lane_approval`\nbefore `OpenBaoClient.resolve`. Conflict, unavailability, or a missing\nbinding fail closed with no OpenBao call. Production still also fail-closes\non the unpublished durable ActionAuthorization / consume-binding serving\npath, so this task remains `wait`.\n\nCorrection 2026-09-06. See `SECRETS-WP-0007-T04` for the full note. Summary: the\nconsume-before-OpenBao gate was real, but the PIP claim + validate join was a\n`return None` stub and `validate_action_authorization` had no production caller,\nso this task's \"blocked on the durable serving path\" framing hid an unimplemented\nlocal seam. The join is now implemented and tested; the remaining blocker is\ngenuinely external (approval-engine claim endpoint and access-engine Check, both\nunreachable as of 2026-09-06).\n\nProgress 2026-09-07. **Step 2 is no longer blocked and is proved against a real\ndecision.** The 2026-09-06 note above says \"approval-engine claim endpoint and\naccess-engine Check, both unreachable\"; the second half of that is now out of\ndate and is corrected here rather than left to read as current.\n\n`access-engine` Check is reachable through the owner-documented access path\n(loopback `kubectl port-forward` to the named pod plus a bounded `TokenRequest`\ntoken; `docs/pdp-access-path.md`). A real CheckRequest for\n`glas-claude-agent-dev-anthropic` returned `decision:0f9c98f14545c42d`, `allow`,\n`catalog_lane_policy_matched`, under package `secrets-engine.catalog-lane.lifecycle`\nv2 with `binding.tenant: tenant:platform`.\n\nTwo defects surfaced only because the request was real, both now fixed:\n\n- Our CheckRequest carried no `tenant`, which v2 treats as a `wrong_tenant`\n denial rather than an omission (`80eafaf`).\n- `validate_decision_envelope` required byte-equality between the binding and\n our unenriched request, which no real decision can satisfy because the\n evaluator normalizes and enriches from its registry before hashing. Corrected\n to the published consumer rule in `10baad9`.\n\nSo the acceptance line \"wrong digest, expired lifetime, superseded status, or\nmissing record fail closed before OpenBao\" is now exercised against a genuine\nenvelope: the unrefreshed live decision is refused on lifetime, and a restated\n`resource.attributes.stage`, a foreign `subject.tenant`, or an unexpected\nenrichment field are each refused.\n\n**What remains is step 1 only.** approval-engine must serve the claim endpoint;\n`APPROVAL-WP-0002-T03` is still `wait` with no deployed base URL, so\n`resolve_consume_binding` returns `None` and production stays fail-closed. That\nis one external dependency rather than the two this task previously named.\n\nAlso recorded, and not a blocker for this task: flex-auth's response channel is\nunauthenticated (`FLEX-DEC-2026-010`). Fail-closed protects against a PDP that is\nabsent, not one that lies. Until `FLEX-WP-0024` ships detached signatures, the\nenforced loopback address shape is what stands in for responder authenticity.\n\nBlocked on the durable ActionAuthorization serving path owned with\n`SECRETS-WP-0007-T04` / State Hub / `access-engine`.\n\nOnce that object is served, a protected side effect holds a decision record\nidentifying the request it was rendered for. Replay is permitted iff the\ncanonical request digest matches and the lifetime holds. Do not cache the\nverdict. Do not treat State Hub status, a local fixture, or catalog admission\nas the decision.\n\nAcceptance:\n\n- Every live privileged production handler passes one shared consume function.\n- Wrong digest, expired lifetime, superseded status, or missing record fail\n closed before OpenBao.\n- Evidence carries the decision id; a fail-closed residue still records the\n stance instead.\n- Local fixtures cannot authorize steady-state production.\n\n### 2026-09-09 published replay-identity contract received\n\nOwner message `83db7e47-ba93-4d3e-ac15-2bcb2bb16a34` supplies\nFLEX-DEC-2026-012, flex-auth source `0bc624b`, and updated\n`docs/request-enrichment.md`, `docs/canonical-request-digest.md` and replay\nexamples. This supersedes the earlier \"only external dependency\" reading.\nT02 is progress: the next work is an executable local consumer correction,\nwith no new owner interpretation or approval needed.\n\nImplement `binding.submitted_request_digest` comparison against the exact\nsubmitted CheckRequest. Stop treating enriched `request_digest` or the consumer's\nchosen list of benign enrichment fields as the replay identity. Preserve policy\npin, lifetime and deny checks. Refresh the owner's replay fixtures without\nchanging their existing request_digest/approval_binding_digest pins.\n\nFor the approval join, carry the validated approval claim to the PDP and compare\nits recorded pdp_digest to the evaluator's approval_binding_digest. Do not\nrecompute either side from unenriched material. Prove changed request, wrong\nclaim/digest, absent new binding field and registry-overridden caller attributes\nare handled under the published contract before any live native lane activates.\n\nThe separate approval identity exchange is implemented in SECRETS-WP-0009-T03\nand passes 350 tests plus a real KeyCape/Approval Engine component exercise.\nThat exercise uses a PDP double and does not prove this newer replay contract.\nThe current source has not yet implemented the changes in this return; live\nPDP rollout/adoption evidence remains explicit too. No synthetic fixture or Hub\ndecision substitutes for a runtime allow and consume.\n\n### 2026-09-09 replay consumer implementation and real component acceptance\n\nThe returned correction is implemented. The PEP now checks the exact submitted\nrequest digest including the full carried approval, permits registry-owned\nattribute replacement, joins the evaluator-origin approval digests and rechecks\nclaim freshness after Check. The consume CAS uses the validated evaluator's\nrequest_digest and decision id; an observation alone is not a consume binding.\n\n334 regression tests pass. The disposable KeyCape + actual Approval Engine +\ncompiled Flex Auth exercise passes 13 checks, including real dual-control denial\nthen claim/check/consume, registry override, changed submitted request, wrong\naction, consumed claim and same/different CAS digest. Independent producer\ninputs replace response-reconstructed replay fixtures; existing digest pins\nremain unchanged. Receipt: docs/evidence/2026-09-09-replay-contract-exercise.json.\nNo OpenBao side effect, live credential read or model request occurred.\n\nT02 is wait for the live return: deployed PDP contract adoption and the admitted\nApproval Engine claim/consume path (APPROVAL-WP-0002-T03 and RPF-WP-0035-T06 /\nAUDIT-WP-0009-T09). SECRETS-WP-0009-T03 owns native delivery acceptance. The old\nlive decision lacks submitted_request_digest and is explicitly refused; its\nhistorical evidence was not rewritten. Local conformance does not close the\nremaining live task. This supersedes earlier additive-only and claim-free\ntransitive correspondence descriptions above.\n\n## Emit evidence under the \u00a79.6 bound"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0008-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "0b54cedf-9335-5fa0-bdcb-1efa9a9cd98d",
|
|
"body": "Completed 2026-08-29. `evidence-classification.yaml` is the declaration.\nLoad-bearing records are queued in `evidence_dir/outbox/` before JSONL.\n`secrets-engine evidence heartbeat` emits a positive claim. Drain never sits\non a mutation path and an audit-core outage leaves the queue in place.\n\nClassify each privileged action as load-bearing or attributive. Today's trail\nis attributive local JSONL plus best-effort State Hub notes; completeness is\nalready not claimed and must stay that way until the destination is\n`audit-core`.\n\nLoad-bearing classes (at least live destroy, production revoke/suspend of a\ncontrol, and dual-control provision once those are enabled) require atomic\nemission via a **local** outbox and a declared cadence or heartbeat. Do not\nplace a synchronous `audit-core` dependency inside the state-change\ntransaction. Attributive classes may keep the current non-blocking trade if\nthat trade stays declared.\n\nAcceptance:\n\n- A machine-readable classification exists next to the declaration.\n- No control in this repository branches on presence or absence of a local\n evidence record.\n- Load-bearing emission is queued locally; an `audit-core` outage does not\n block a revocation.\n- Documentation uses the sound claim: the archive proves records it holds were\n not altered or truncated after arrival.\n\n## Accept the SSH-CA signing engine surface"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0008-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "581aeee3-3d99-5034-992b-7d42e6542a19",
|
|
"body": "Completed 2026-08-29. Contract published at `docs/ssh-ca-signing-contract.md`.\nNo OpenBao SSH-CA write was added. `layer.yaml` owner_status remains proposed.\n\nops-warden's `ssh-ca-signing-write` gap names this engine as intended owner.\nAccept the **engine API**, decline the Staff lane. Publish a contract\nops-warden can call after an `access-engine` decision: sign a short-lived\ncertificate for an `adm`/`agt`/`atm` actor under the caller's request, present\nno additional authority, reconstruct as the caller's action.\n\nDo not implement a replacement client until ops-warden assents the contract.\nDo not unpark the standalone `warden-sign` AppRole as break-glass.\n\nAcceptance:\n\n- A non-secret contract document in `docs/` states request, decision binding,\n lifetime, evidence, and non-responsibilities.\n- ops-warden has a recorded chance to assent or contest.\n- No OpenBao SSH-CA write is added to this CLI ahead of that assent.\n- `layer.yaml` owner_status remains `proposed` until the surface ships.\n\n## Accept the secret-use evidence surface"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0008-T05",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "3100d28c-9494-5b21-9d5a-af583cd8aa55",
|
|
"body": "Completed 2026-08-29. Contract published at\n`docs/secret-use-evidence-contract.md`. `layer.yaml` owner_status remains\nproposed. `route`/`audit` are still not this surface.\n\n**2026-09-02:** kings-guard assented in its own voice (message\n`75ebd2cc-a166-4676-94aa-deef2791c0c9`). It will not consume the surface as\nan observation input until the surface ships and publishes its cadence\ndeclaration. No Tooling contact will be opened to fill that wait.\n\n**2026-09-02 later:** shipped `secrets-engine secret-use snapshot`. Cadence is\nthe declared 1d heartbeat on the snapshot envelope. `owner_status` stays\n`proposed` until kings-guard admits the snapshot as an observation input.\n`route`/`audit` remain distinct operator summaries.\n\nkings-guard's secret-abuse posture is fixture-driven because no engine exposes\nlease, revocation, mount, rotation, and delivery-session metadata. `route` and\n`audit` are operator summaries over local JSONL and are not that surface.\n\nPublish a read-only engine contract of non-secret metadata, bounded by \u00a79.6:\nit cannot prove omission at source. Coordinate destination with `audit-core`.\nDo not give kings-guard a vault client, and do not return values.\n\nAcceptance:\n\n- Contract lists fields, freshness, and the evidence bound.\n- kings-guard has a recorded chance to assent or contest.\n- No secret material, token, or accessor is in the surface.\n- `layer.yaml` owner_status remains `proposed` until the surface ships.\n\n## No standing engine credential"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0008-T06",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"RPF-WP-0035-T02"
|
|
],
|
|
"blocking_reason": "Positive service-JWT login proof passed 2026-10-10 (SECRETS-WP-0012-T03, docs/evidence/2026-10-10-keycape-openbao-probe.json). Waits on railiance-platform closing RPF-WP-0035-T02 with the CCR-2026-0038 negative checks, then on routing live engine actions through service-jwt instead of bootstrap/env.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d7bc8bdc-a0f8-5058-a640-374ef9859148",
|
|
"body": "Progress 2026-10-10. The CCR-2026-0038 no-fallback check, which is\nsecrets-engine's to prove, passed. Fixing it exposed a gap: the anonymous JWT\nlogin inherited `BAO_TOKEN`/`VAULT_TOKEN` and the CLI token helper, so it sent an\nambient token alongside the JWT. `OpenBaoClient.login_jwt` now runs with no env\ntoken and with a token helper that returns none. This is verified with the real\n`bao` CLI against a header-recording listener. Evidence:\n`docs/evidence/2026-10-10-service-jwt-no-fallback.json`.\n\nProgress 2026-09-02. Named engine auth is shipped: `service-jwt`, `bootstrap`,\nand `env` are exclusive providers. `--auth service-jwt` exchanges the KeyCape\nservice JWT and logs in through `OpenBaoClient.login_jwt` (JSON file, never\nargv), then self-revokes. A JWT selection refuses `--bootstrap-token-file` and\ndoes not read `BAO_TOKEN` on failure. `--bootstrap-token-file` is a named\nbreak-glass provider with `auth_break_glass` evidence.\n\nThe platform-owned OpenBao JWT mount/role is still unpublished, so auto keeps\nbootstrap/env and this task remains `wait`.\n\nInbox triage 2026-09-21. railiance-platform `29cccf8a` (2026-09-09): status,\nnot a contract. Their side is RPF-WP-0035-T02 (design\n`docs/credential-lane-designs/secrets-engine-service-jwt.md`), still `wait`.\nDesigned: role/audience `secrets-engine-openbao`, subject\n`service:secrets-engine`, token policy `secrets-engine-login-self`, five-minute\nbudget, login-only. KeyCape issuer `https://kc.coulomb.social` and its JWKS are\nnow confirmed live, so the remaining blocker is this registration's issued\nclaims, consumer readiness, an approved source and attended apply authority.\n**Resolved by the operator, 2026-09-27:** OpenBao is platform infrastructure,\nbelonging to tenant zero, `tenant:platform`. Coulomb is a workload tenant;\nits DNS domain does not own the platform. The former matching Coulomb claims\nwere incorrect. KeyCape registrations, platform JWT roles and this consumer's\nstrict preflight are corrected together in source. Live registration/custody,\ncoordinated deployment and native refusal/revocation proof remain T06.\nA service login grants no lane mutation authority. Companion \u00a77 / statute \u00a73.4: an\nagent holds no long-lived credential of its own. Authority is per task,\ntime-bounded, and attributable to the principal it acts for.\n\nBootstrap token files remain break-glass, heavily evidenced, never an implicit\nfallback from service identity.\n\nAcceptance:\n\n- Steady-state CLI/API auth is the reviewed service identity, not\n `--bootstrap-token-file`.\n- Bootstrap is a named break-glass provider with distinct evidence.\n- No fallback from JWT/service-auth failure into bootstrap or AppRole.\n- Issued delivery sessions continue to self-revoke as in WP-0007-T05.\n\n### 2026-09-21 GH-DEC-2026-017 \u2014 section 11 layer declaration ruled\n\nRead from `gate-house/decisions/decisions.md`, not from message text.\n`secrets-engine` is a named affected repository and carries both permitted\nforms, so all four parts apply here. State Hub decision id\n`82dd0fea-fabb-4940-92d5-d6e2ea9985f5`.\n\nWhat the ruling settles for this repository:\n\n1. **`INTENT.md` governs.** Our declaration is the `layer: Engine` key in\n `INTENT.md` frontmatter. `layer.yaml` is a **derived artifact**: it must be\n marked as derived, must name `INTENT.md` as what it derives from, and must\n agree with it. Our `layer.yaml` already carries `declared_by: INTENT.md` and\n a `Voice: INTENT.md (this repository's own declaration, \u00a711)` header comment,\n so we are among the repositories already treating the sidecar as derived in\n substance. What is missing is the explicit derived marking the ruling now\n requires as a field rather than a comment.\n2. **The \u00a73 vocabulary is case-insensitive and comparison must ASCII case-fold.**\n Our `INTENT.md` says `Engine` and our `layer.yaml` says `engine`. Under \u00a72 of\n the ruling that is **conforming**, it was never a disagreement about a layer,\n and **nothing here is re-spelled**. flex-auth withdrew the casing finding\n itself (message `962bf395`) and its validator is the thing that changes. We\n do not touch either file's spelling, and we do not \"align\" them.\n3. **The vocabulary is closed with four tokens** \u2014 `Taxonomy`, `Tooling`,\n `Engine`, `Staff`. `Engine` is in it; no action.\n4. **`standard_version` comes out of the declaration.** Our `layer.yaml` carries\n `standard_version: \"0.7\"`. A declaration asserts a standing property and must\n not carry a standard version; version-scoped state belongs in the derived\n conformance record, which must name what it derives from and the version or\n commit it was derived at.\n\n**Deliberately not done in this session.** The ruling states that\n`standard_version` is not one repository's habit but **ops-warden's reference\nform**, which this repository copied along with seven others, and that ops-warden\nis asked to make the change there rather than each adopter deciding independently.\nops-warden is updating that reference form in a parallel session. Inventing our\nown sidecar shape ahead of it would produce exactly the divergence the ruling\nexists to close, so we record the requirement and wait for the reference form.\n\nWhat `secrets-engine` will need, once the reference form lands:\n\n- Adopt the reference form's derived-artifact marking in `layer.yaml`, keeping\n `declared_by: INTENT.md` or whatever field the reference form names for it.\n- Remove `standard_version: \"0.7\"` from `layer.yaml`.\n- Move the version the conformance run was derived at into our derived\n conformance record, per the reference form's field for it. Our conformance\n checker is `scripts/check_layer_conformance.py`; it reads `layer.yaml` today\n and will need to read `INTENT.md` as the governing form, read the sidecar as\n well, and **report a disagreement between them as a finding** rather than\n resolve it by precedence. A casing-only difference is not such a disagreement.\n- Keep `framework:`, `layer:`, `role:` and the substantive \u00a73/\u00a75/\u00a76/\u00a79.6\n content unchanged. `role:` is explicitly not ruled and stays as it is.\n- The `Framework:` header comment in `layer.yaml` cites\n `security-layer-model_v0.7.md` while the ruling is issued against `v0.8`.\n That is a citation in a comment, not a declaration version, so it is out of\n scope for part 4 \u2014 but it should be refreshed in the same commit so the two\n are not confused for each other.\n\nNo task is opened here by hand. This is a note against the workplan that already\nowns `layer.yaml` / `pep-stance.yaml` / INTENT frontmatter staying in one voice;\nthe work lands under that exit criterion when ops-warden's form is published.\n\n### 2026-09-21 GH-DEC-2026-017 applied \u2014 reference form published, note closed\n\nops-warden published the reference form (commit `a70f559`,\n`wiki/playbooks/netkingdom-layer-declaration.md` \"Reference-form change set\").\nRe-read against the ruling in `gate-house/decisions/decisions.md` and\namendments A9\u2013A13 before editing; the ruling and the playbook agree.\n\nApplied in one commit, field and checker together:\n\n- `layer.yaml`: `standard_version: \"0.7\"` removed; `derived: true` and\n `derived_from: INTENT.md` added (`declared_by: INTENT.md` kept, as the note\n above required). Header comment marks the file derived and drops the version\n from the framework citation.\n- `INTENT.md` frontmatter: never carried `standard_version`, but its\n `standard:` value was a version-pinned path (`..._v0.7.md`). De-versioned to\n `net-kingdom/canon/standards/security-layer-model`, as the reference instance\n did, because a pinned path in the governing form is a standard version by\n another name. The field is kept; only the pin is gone.\n- **No layer value re-spelled.** INTENT says `Engine`, layer.yaml says\n `engine`; both unchanged.\n- `scripts/check_layer_conformance.py`: `standard_version` was a required key,\n so removing the field alone would have exited 2 MALFORMED. It now reads\n INTENT.md as the governing form, requires the derived marking, rejects a\n returning `standard_version` in either form, validates both layer values\n against the closed four-token vocabulary (Taxonomy included) after an ASCII\n fold, and reports a post-fold disagreement between the forms as a finding.\n- `tests/test_layer_conformance.py`: per-file equality on the layer spelling\n replaced by fold assertions; new tests for fold agreement, a real\n disagreement (finding, exit 1), the closed vocabulary (`surface` exit 2,\n `Taxonomy` admitted), and a returning `standard_version` (exit 2).\n Full suite: 430 passed.\n\n`role:` untouched (not ruled). `pep-stance.yaml` untouched (a stance map, not\na declaration). `schema_version` left at `0.1` \u2014 ops-warden bumped its own, but\nthe ruling does not call for it.\n\n**Still open, not ours to answer:** where the removed version lives. A12 says\nthe derived conformance record already MUST carry it; our checker, like\nops-warden's, is re-runnable and emits nothing durable. ops-warden asked\ngate-house (message `4220413a`); we follow that answer rather than choose.\n\n## Exit criteria\n\n- The published PEP stance is the shipped default and stance application is\n recorded by name.\n- Production live side effects require an access-engine decision record, or\n remain fail-closed with a recorded stance.\n- Evidence classification and destination match \u00a79.6; completeness is not\n claimed.\n- SSH-CA and secret-use surfaces are either contracted with the declaring\n repositories or explicitly declined in this repository's own voice.\n- Bootstrap is not the steady-state engine credential.\n- `layer.yaml` / `pep-stance.yaml` / INTENT frontmatter stay in one voice.\n- No raw secret values in Git, State Hub, chat, prompts, workplans, evidence,\n or argv.\n\n\n## Decision consumer closure and declaration ruling applied \u2014 2026-09-27\n\nT02 is done. `docs/evidence/2026-09-16-t03-completion.json` provides the native\nreturn awaited in the September 9 note: separately approved apply/verify/exec\nrequests received current PDP allows and successful CAS consumption before real\nOpenBao work. The shared guard records decision IDs and retains refusal before\nbackend access for invalid/missing/replayed decisions. SECRETS-WP-0007-T04 now\nrecords the same completed contract; no native activation grant is inferred.\n\nThe open conformance-record question is also resolved. GH-DEC-2026-020 \u00a74 says\na versioned/scoped re-runnable checker is sufficient; each declaring repository\nneed not emit a durable record. GH-DEC-2026-021 \u00a72/\u00a73 names the accepted v0.7\ntext plus applicable decisions and the ops-warden reference detector. The\nchecker now copies that detector, permits own-document versions/prose citations,\nrefuses nested/identity-bearing version pins and names the accepted text and\nrulings on every run, including PASS. Declaration spellings are unchanged.\n\nT06 remains wait: railiance-platform's RPF-WP-0035-T02 still records an\nunprovisioned, login-only JWT role, pending platform-tenant live registration and\ncustody/attended admission. The existing env-auth native receipt cannot prove\nsteady-state service JWT login. This is the only remaining task in this workplan.\n\n### 2026-09-27 platform essentials follow-up\n\nOperator tenant-zero decision `be5287cb-d458-47bc-9183-2a40dd7ae04b` corrects\nOpenBao infrastructure identities to `tenant:platform`. Source changes are\ncoordinated in KeyCape, railiance-platform and Secrets Engine. The platform\nowner records the bounded essentials review in\n`docs/platform-tenant-essentials-review.md`. T06 remains wait for coordinated\nlive registration/custody, provisioning and native refusal/revocation evidence.\nNo new task or workplan was created. Warden's npm no-rotation hold remains;\nfactory records now consume the completed generic approval and companion returns.\n\n\n## Loose-end review \u2014 2026-09-28\n\nClosed the stale conformance-record question above by reading GH-DEC-2026-020\n\u00a74 and the published ops-warden reference. The existing checker already prints\nVALIDATED_AGAINST and SCOPE before loading declarations and implements the\nGH-DEC-2026-021 version detector. No durable per-repo conformance record is\nrequired. No further implementation is needed for that note.\n\nT06 still depends on RPF-WP-0035-T02, whose current file remains wait for live\nplatform service registration/custody and scoped JWT provisioning plus native\nlogin, denial and revocation evidence. Source tenant corrections are complete.\nThe workplan is now blocked; no new task or workplan was created."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/secrets-engine/workplans/SECRETS-WP-0009-glas-claude-native-delivery.md",
|
|
"meta": {
|
|
"id": "SECRETS-WP-0009",
|
|
"type": "workplan",
|
|
"title": "Activate native Claude credential delivery for Glas",
|
|
"domain": "infotech",
|
|
"repo": "secrets-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"created": "2026-09-05",
|
|
"updated": "2026-10-08",
|
|
"state_hub_workstream_id": "40ccc3b4-d046-5a58-8649-e7935f45c974"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "SECRETS-WP-0009-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4f1cf242-3aec-56a8-b958-5d53823875e0",
|
|
"body": "Added catalog glas-claude-agent-dev-anthropic; plan checks existing platform\nmount and proposes one data-only read policy/AppRole. Token TTL5m/max15m,\nsingle-use SecretID5m, token use budget8. See docs/glas-claude-delivery.md.\nNo metadata, sibling, listing or write capability is proposed.\n\n## Support data-only delivery policies"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0009-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "fa4a3e87-0854-5e2b-af44-facd5b25f443",
|
|
"body": "Added boolean delivery_auth.metadata_read with compatible default true and\nexplicit false for this lane. Validation refuses non-booleans; generated plan\nomits metadata permissions when disabled. Full owner suite passes. Sand-boxer\nsynthetic exec-env transport proof passed; no real secret was read.\n\n## Activate the approved native lane and verify real owner delivery"
|
|
},
|
|
{
|
|
"id": "SECRETS-WP-0009-T03",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:glas-harness",
|
|
"blocking_reason": "Next owner action: reconcile held parent reservation 6efa9436-6a91-47c0-94e5-b31b5a0e7e3a (EUR 10, observed USD still null) from existing provider records. No corrected runtime digest is admitted; do not retry or replay consumed approvals.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "f8069c8a-ad6b-5d0b-9a36-c2326699437d",
|
|
"body": "Inbound 2026-09-06 (glas-harness `GLAS-WP-0015` production dependency handoff).\nOwnership acknowledged. Answering their tenant question rather than assuming the\nvalues lined up found a blocking defect in this repo, so the handoff earned its\nkeep before any activation work started.\n\n- **Our CheckRequest carried no `tenant` at all.** The deployed\n `secrets-engine.catalog-lane.lifecycle` **v2** package reads\n `request_tenant := object.get(input, \"tenant\", \"\")` against\n `known_tenant := \"tenant:platform\"`, so an absent tenant is a `wrong_tenant`\n denial rather than an ignored field. Every gated action this engine sent would\n have been denied, and the omission also produced a `request_digest` matching no\n correctly issued decision, because `tenant` is hashed material. Fixed in\n `80eafaf`; `REQUEST_TENANT` is pinned against the vendored allow envelopes.\n- **The package is v2, not the v1 glas reported.** v1 had no tenant rule and\n failed open \u2014 a `rotate` under `tenant:coulomb` returned allow against the\n deployed package (`decision:066e629bbf0c0924`). flex-auth superseded rather\n than amended it, because a fail-open correction must be visible as a version\n change. Our accepted version moved to v2 and a test refuses a v1 decision.\n- **Wrong-tenant denial evidence delivered**, from flex-auth's real deny envelope\n rather than asserted: `decision:7d56b7fc274ddfd6`, `matched_rule wrong_tenant`,\n `binding.tenant tenant:coulomb`. Vendored with tests that we refuse it on\n `effect` first and that a deny legally carries no `lifetime`.\n- **Tenant mapping NOT resolved, deliberately.** `service_auth.TENANT` is\n `tenant:coulomb`, which is exactly the value the package denies. Either those\n are two layers sharing a namespace format or one constant is wrong. Choosing\n without an owner ruling is the fail-open shape `GH-DEC-2026-008` rejected for\n action vocabularies. Both constants stay as they are, not unified behind one\n symbol. Recorded in `docs/tenant-alignment.md` for `KEY-WP-0013-T02` /\n `APPROVAL-WP-0002-T01`.\n- **Hazard found while probing the caller access path.** Every\n `*.svc.cluster.local` name resolves on this workstation to one unrelated public\n address via the `ad.binect.de` search suffix, including names of services that\n do not exist. Pointing `SECRETS_ENGINE_PDP_URL` at the Service name would ship\n CheckRequest metadata and the Bearer token to that host, and decision\n envelopes are structurally validated but not signed, so a knowing responder\n could return a well-formed allow. Reported to flex-auth for `FLEX-WP-0021-T05`;\n not mitigated here because the transport control is the owners' call. The pin\n stays unset, so the hazard is theoretical today.\n\nCCR-2026-0016 is explicitly treated as custody provenance, not a per-action\nauthorization. No unsafe-demo switch and no human runtime token will be used to\nreach a prod lane. This task stays `wait`: activation is blocked on the owner\naccess path, not on engine work or on approval shape.\n\nDigest join corrected 2026-09-07. The live proof from 2026-09-06 (commit\n`03c0569`) showed `validate_decision_envelope` rejecting every real allow. The\ncause and the fix are both now settled, and the fix follows a published rule\nrather than an inferred one.\n\n- **Cause.** The evaluator normalizes before hashing: the request tenant is\n copied onto `subject` and `resource`, and a registry hit copies `type`,\n `tenant` and selected `attributes` onto the refs. `binding.request_digest` is\n therefore over material we never sent and cannot reproduce, so byte-equality\n against our unenriched request is unsatisfiable, not merely mismatched.\n- **The rule was already published.** flex-auth's `canonical-request-digest.md`\n section \"Normalization\" states it, and instructs consumers to compare\n structured `binding` fields to the proposed action and treat `request_digest`\n as the evaluator's statement of what it hashed, recomputing independently over\n the tuple the binding carries. Correction to the previous note: this repo\n raised it with flex-auth as an unpublished gap and asked them to choose\n between three shapes. It was already in their contract, and the answer was the\n first of the three. Nothing was blocked on them.\n- **Implemented.** `_require_binding_corresponds` enforces that everything we\n proposed survives unchanged \u2014 tenant, action, context, `subject.id`/`type`,\n `resource.id`/`type`/`system`, and every attribute we sent. Enrichment may add\n only `type`, `tenant`, `attributes`; any other added field is refused, and an\n enriched tenant must be the request tenant so a cross-tenant binding cannot\n arrive wearing our request's clothes. `request_digest` is still checked, now\n against `binding_tuple(binding)` for self-consistency.\n- **Proved against the artifact.** `tests/test_live_decision_enrichment.py`\n validates the real `decision:0f9c98f14545c42d` under the corrected rule, and\n separately asserts the unrefreshed envelope is refused on lifetime \u2014 reaching\n the lifetime check at all is the evidence every binding check now passes on a\n real decision. Negative tests cover a restated `resource.attributes.stage`, a\n foreign `subject.tenant`, and an unexpected enrichment field.\n- **Why the fixtures could not catch it.** `_request_from()` rebuilds the\n request out of the binding, i.e. the already-enriched form, so every digest\n assertion hashed the evaluator's output and compared it to the evaluator's\n output. The defect survived the excluded-fields fix, the\n `approval_binding_digest` fix and the tenant fix because all three were tested\n that way. Only a real request through the owner access path exposed it.\n\nRemaining before activation is now one external dependency, not two:\napproval-engine must serve the claim endpoint so protocol step 1 can run and\n`GH-DEC-2026-003` consume-before-OpenBao can be satisfied. The decision path\nitself is proved end to end against the deployed pin.\n\nDepends on SECRETS-WP-0007-T04 and SECRETS-WP-0008-T02/T06: canonical production\nauthorization, successful consume and scoped service authority must exist.\nCurrent production exec refuses before OpenBao because durable access-engine\ndecision records are not served. Do not bypass this with unsafe-demo or a human\noperator runtime token. Then apply the exact read policy/AppRole, prove positive\nand negative access, register delivery-ready evidence, bind owner exec with\nservice authentication, and return verified pins/evidence to SAND-WP-0015 and\nGLAS-WP-0012. Provider scope/budget and expiry remain explicit acceptance inputs.\nKeep the catalog route inactive until real verification passes.\n\n\n### 2026-09-09 consumer identity implementation and component proof\n\nThe \"one external dependency\" statement above concealed another local seam:\nclaim and consume could only read a manually supplied bearer-token file. The\nOpenBao service-JWT provider cannot be reused with approval credentials because\nits audience, tenant and scope are different.\n\nImplemented the separate secrets-engine-approval provider and wired it into\nboth actual claim/consume call sites. It requests only read or consume for the\ncurrent request, keeps the token in memory, rejects mixed providers, and never\nfalls back on exchange failure. The exact service:secrets-engine / approval-engine /\ntenant:platform identity and scope/time bounds are preflighted. Credential-bearing\nredirects and unsupported approval endpoint shapes are refused.\n\nThe pinned real KeyCape image exposed a second defect: the shared consumer\nexpected assurance.aal/method but the issuer emits assurance.level/methods.\nCorrected to the issuer's actual source contract, with regression coverage.\nThe real Approval Engine JWT verifier and SQLite store then accepted the actual\nconsumer's claim/check/consume chain in a disposable component exercise. Wrong\naction/secret, spent claim, different digest and operator consume scope are\nrefused; same-digest consume retries are idempotent. Only the PDP was a test\ndouble. The suite passed 350 tests; no production credential was read.\n\nContract and repeatable exercise: docs/approval-service-auth.md; receipt:\ndocs/evidence/2026-09-09-approval-identity-exercise.json.\n\nT03 remains wait for RPF-WP-0035-T06's separately admitted client-side reader,\nAUDIT-WP-0009-T09 audit custody, APPROVAL-WP-0002 live endpoint/claim/consume,\nand the existing exact native OpenBao authority/delivery returns. The synthetic\nproof does not grant these. KEY-WP-0013-T02 and verifier CCR-2026-0017/0018\nare complete and must not be requested again. No new workplan duplicates T03.\n\nOwner-return clarification: SECRETS-WP-0008-T02 is now progress for the published\nFLEX-DEC-2026-012 submitted-request replay identity and approval-digest join.\nThe real-component identity exercise used a PDP double and does not close that\nlocal implementation. T03 also consumes that correction before live activation.\n\n\n## Replay-contract return \u2014 2026-09-09\n\nSECRETS-WP-0008-T02 supplies the implemented FLEX-DEC-2026-012 consumer join.\n334 tests and 13 real local KeyCape/Approval Engine/Flex Auth checks pass;\nreceipt: docs/evidence/2026-09-09-replay-contract-exercise.json. The former PDP\ndouble limitation is resolved for component conformance. T03 remains wait for\ncurrent deployed PDP adoption, separately admitted client-side/audit custody,\nactual Approval Engine deployment, and the scoped native OpenBao delivery proof.\n\n\n### 2026-09-10 exact recipient enforcement\n\nThe factory runtime is now installed on workstation and Railiance at digest\n`5371156d2027dde6e8f140cc0a1833c4e90b8c75b3bec862e05f06a957f5fd34`;\nconsume project evidence `2026-09-10-runtime-placement.json`. Native delivery\nreview exposed an unclosed local boundary: exec accepted any argv and inherited\nall parent environment after catalog/action approval.\n\nImplemented optional catalog exec_owner with exact command, private cwd, fixed\nnon-secret environment and file pins. The factory catalog is explicitly pending\nand refuses before approval/backend. The complete binding digest travels in the\nexisting CheckRequest context and producer/approval join. Changes before or during\nretrieval refuse launch; the actual child has closed stdin and receives no inherited\nengine auth environment. Existing action/consume/state/backend gates remain.\n\n361 tests passed. The extended disposable actual KeyCape/Approval Engine/Flex Auth\nexercise passed all 18 checks, including changed-recipient replay refusal and\nconsume-before-synthetic-backend followed by actual child execution. Receipt:\n`docs/evidence/2026-09-10-exec-owner-approval-exercise.json`; contract:\n`docs/exec-owner-binding.md`. Synthetic backend/key/recipient and test operator\nidentity only; no native secret read, human approval or paid execution.\n\nT03 remains wait for configured/pinned owner inputs and holder admission, wanted\nCCR-2026-0019 operator-group/file-delivery return, INFD-WP-0001-T07/T08 real human\napproval, audit custody and deployed services/PDP/native delivery. CCR-2026-0020\nwas cancelled on owner withdrawal; do not wait for or recreate its presenter.\nNo runtime artifact rebuild is needed for this credential-engine change.\n\n### 2026-09-10 workstation procedure return\n\n`docs/approval-service-auth.md` now gives the concrete CCR-2026-0019 consumer\nprocedure requested by Platform: an operator-owned 0700 runtime session directory\noutside Git, a new 0600 file, path-only CLI configuration, claim/consume lifetime,\nEXIT/INT/TERM cleanup and explicit residual-file handling after hard interruption.\nThe source review distinguishes implemented permission/location/empty-file checks\nfrom operator-owned creation, parent custody and cleanup. No automatic cleanup\nor live reader proof is claimed. The exact group remains NetKingdom/KeyCape's\nreturn, followed by reviewed attended admission and positive/negative evidence.\nT03 stays wait; no identity, role, secret, runtime or route readiness changed.\n\n### 2026-09-10 declared human-control consumer return\n\nConsumed APPROVAL-WP-0002's GH-DEC-2026-016 implementation and schema-v5 release.\nThe existing human action-review requirement is explicit on the factory catalog:\n`approval.human_control: true`. The CheckRequest carries that intent in its bound\ncontext; the consumer requires exact true in the served claim before PDP and\nagain afterward. The internal consume binding carries the observed declaration.\nMissing service coordinates, ordinary lane approval, stage and unsafe-demo paths\ncannot substitute for the declared control. Undeclared lanes retain their behavior.\nThe catalog's exec owner stays pending; no policy, role or credential was changed.\n\nValidation: 388 tests pass, including 27 new strict-type, missing/false claim,\nrequest binding, post-PDP recheck, fallback and actual exec-handler cases.\nThe real local KeyCape/Approval Engine/Flex Auth exercise passes 22 checks.\nThe request API declares true; KeyCape service binding is refused; an undeclared\nclaim reaches no PDP/consume/backend; declared positive delivery consumes before\nthe synthetic backend/child. Positive human evidence is an explicit store fixture,\nnot a native human JWT or browser login. Evidence and repeatable command:\n`docs/evidence/2026-09-10-human-control-consumer-exercise.json`,\n`tools/exercise_approval_identity.py --exec-owner --human-control`.\n\nThis closes consumer source adoption. T03 still requires the narrow native\nrequester, INFD T07/T08 functional browser and human approval, audit custody,\nCCR-2026-0019 operator binding/attended read, current deployed service/PDP and\nconfigured MessagesOwner/native delivery. HFACT T01/T04/T05 retains factory\nconfig/G0 and natural queue/model proof. No native secret read or paid attempt.\n\n### 2026-09-21 activation preparation\n\nSECRETS-WP-0010-T03 completed native OpenRouter delivery on 2026-09-16 over the\nsame shared chain: Approval Engine deployed, CCR-2026-0019 reader bound to\n`net-kingdom-admins`, `secrets-engine-requester` admitted, Informed Decision\nhuman review live with a real human approval, current PDP. Those items are no\nlonger T03 blockers. The operator offered the attended session.\n\nLane-specific residue, in order:\n\n1. Operator inputs: placement (workstation or Railiance runtime copy from\n `prj-helixforge-factory/evidence/2026-09-10-runtime-placement.json`), spend\n envelope for one bounded run (`rein-aharness/docs/spend-admission.md` fields:\n per-run/daily/total EUR, max budget/liability USD, FX, expiry), MessagesOwner\n model and token bounds, and a real unrelated identity for negative verification.\n2. Private SpendPolicy + ledger `spend init` and mode-0600 owner config\n (`rein-aharness/docs/owner-bootstrap.md`) at the chosen placement\n (HFACT-WP-0001-T01/T04). Their digests become `exec_owner.files` pins.\n3. Configure `exec_owner` (argv `<runtime>/bin/python3 -I -B -m rein_aharness.cli\n metered-once --owner-config <private-owner-config>`), render final\n apply/verify/exec requests with evaluator-origin digests.\n4. Attended: three human approvals, scoped Warden session, claim/Check/consume\n then apply, positive/negative verify, one bounded exec, session revoke,\n evidence returned to GLAS-WP-0012 / SAND-WP-0015.\n\nCircular wait noted: HFACT-WP-0001-T04 waits on this task's admission while this\ntask waits on the owner config; the operator inputs in step 1 break it.\nNo credential read, no approval created, no policy or role changed.\n\n### 2026-09-21 operator inputs\n\nReceived from the operator (Bernd), recorded here as inputs, not authorization:\n\n- Placement: railiance01 runtime copy (`5371156d\u2026`).\n- Spend envelope: per_run_eur 5, daily_eur 20, total_eur 500; per-run\n max_liability_usd 5.75 and max_budget_usd 5.00 (derived from EUR 5 at the stated\n FX); eur_per_usd from 1 EUR = 1.15 USD; expires 2027-01-31. The operator's\n USD 600/800 figures are overall caps and are dominated by total_eur 500 (= USD 575).\n- EUR 100/month: recorded as an operator-reviewed limit, not enforced; SpendPolicy\n has no monthly ceiling. Follow-up for rein-aharness to add `monthly_eur`.\n- authority_ref: no CCR exists; the operator wants a budget decision in the\n Informed Decision framework. That record becomes `authority_ref`.\n- Model: keep this Anthropic lane with a Claude default for MessagesOwner.\n Separately, the llm-connect default moves to DeepSeek V4.1 Flash (llm-connect\n change, not this task).\n- Negative identity: the operator delegated this. Plan: use the existing\n CCR-2026-0019 approval-client reader token from the attended Warden session\n (real, reviewed, scoped only to its own KV path) written to a 0600 tmpfs file.\n No new identity or authority is minted.\n\n### 2026-09-21 spend authority accepted (step A)\n\nThe operator accepted Informed Decision memo `infd-20260921-b01` at 19:51:29 UTC\nunder fresh AAL2 MFA, after acknowledging that the EUR 100 monthly limit is not\nenforced. Approval Engine approval `ba5ce2d8-8b6d-40be-af89-2e8c147029a3`\n(binding `sha256:e9eaf454\u2026`) carries the confirmed human entry. It is the\nSpendPolicy `authority_ref` for envelope `hfact-glas-anthropic-2026-09`.\nEnforced values: per_run_eur 5, daily_eur 20, total_eur 500, eur_per_usd 0.87,\nmax_liability_usd 5.74, max_budget_usd 5.00, expires 2027-01-31T23:59:59+01:00.\n\nPath: flex-auth compact-sitting v2 (`4f66c4d`/`882b381`, image `d77378e1\u2026`,\npackage `sha256:24a52478\u2026`); informed-decision `c8c60eb`..`4065450` (memo,\nparametrized create/attach tools, WSL2 clock-skew fix, review cutover inputs).\nReceipt: informed-decision `docs/evidence/2026-09-21-budget-sitting-accept.json`.\nThis approval authorizes spend only; it is not the apply/verify/exec approval.\nNext: step B, SpendPolicy scope fields from the admitted factory profile.\n\n### 2026-09-22 Glas candidate profile and runtime placed (steps B1-B2)\n\nOperator chose the Glas acceptance run (GLAS-WP-0012-T04, disposable fixture)\nas the first use of the envelope. glas-harness `462436b` adds\n`harness.agent-dev-local@1.1.0` (unverified, bwrap-local, empty egress, no\ncredential routes, 900 s / 60k tokens / 30 turns / USD 5.00). Owner runtime\n`2cfc7b5f5c03\u2026` (rein `a2149bb`, sandboxer `221126c`) is installed on railiance01\nand passes the synthetic metered proof 4/4; `5371156d` stays for rollback.\nIntermediate `95c9edb1` is installed but refused: a sandboxer bwrap info-fd\npartial-read race, fixed in `221126c`. Receipt: prj-helixforge-factory\n`evidence/2026-09-22-runtime-placement.json`. The exec_owner argv will use\n`2cfc7b5f`. Next: B3 fixture repo, repository grant, ActivityDefinition, worker id.\n\n### 2026-09-23 B3 scope correction and model choice\n\nOperator chose `claude-sonnet-5` for MessagesOwner and a throwaway fixture repo\nwith no remote. Reading the owner contracts corrected the B3 framing above:\n\n- The Glas acceptance run (`glas-harness/docs/local-profile-acceptance.md`,\n `scripts/prove-local-profile.py`) creates its own disposable fixture repo\n (one `PROOF.md`, one local commit, no push remote). No repo is pre-created.\n- That path runs with `--no-metrics` and carries no repository grant, so it\n needs no grant, ActivityDefinition or queue worker id. Those belong to the\n Activity Core queue loop (HFACT-WP-0001-T05), not to this first run.\n- The candidate `harness.agent-dev-local@1.1.0` pins `claude-sonnet-4-6`.\n Moving to `claude-sonnet-5` is a glas-harness profile change, reviewed as a\n new compatibility set, and must be checked against the pinned Claude CLI\n 2.1.263 in runtime `2cfc7b5f` before the attended run.\n\nNo repo, grant, definition, credential or approval was created.\n\n### 2026-09-23 Sonnet 5 compatibility check\n\nCorrection: runtime `2cfc7b5f` ships Claude CLI **2.1.266** (binary\n`19842705e989\u2026`, per `prj-helixforge-factory/evidence/2026-09-22-runtime-placement.json`),\nnot 2.1.263 (that was the earlier `5cf9a16c` candidate). The same binary in the\nlocal `5371156d` store matches that digest. Its built-in model registry lists\n`claude-sonnet-5` as a first-class entry (`{\"name\": \"claude-sonnet-5\",\n\"supports1m\": true}`), and it is the CLI's own example model for hooks. No\ndeprecation marker references it. No runtime rebuild is needed. This was a static\ncheck of the binary, not a provider request. The first real call is still\nthe attended exec. Remaining model work: a glas-harness profile change from\n`claude-sonnet-4-6` to `claude-sonnet-5`, reviewed as a new compatibility set.\n\n### 2026-09-23 Sonnet 5 runtime placed\n\nOperator chose a 1.1.1 bump. glas-harness `30be818` adds\n`harness.agent-dev-local@1.1.1` (`claude-sonnet-5`) and blocks 1.1.0. rein-aharness\n`fdc07ee` pins it in the runtime contract lock (llm-connect `37436bb`, workplan-only).\nOwner runtime `b6e4e8a429393d68831c996a65c0489664205df969ac9882e581983ec2da4969`\n(Claude CLI 2.1.266) is installed on railiance01 beside `2cfc7b5f` and `5371156d`\n(rollback). Synthetic metered proof passes locally and on railiance01 (one fake\nprovider request, zero on refusal, artifact unchanged). Receipt:\n`prj-helixforge-factory/evidence/2026-09-23-runtime-placement.json`. The\n`exec_owner` argv and the owner config `runtime` block will use `b6e4e8a4`, and\n`messages_policy.model` will be `claude-sonnet-5`. Next: private SpendPolicy, ledger\n`spend init` and owner config on railiance01 (HFACT-WP-0001-T01/T04).\nNo credential, approval, profile activation or worker change.\n\n### 2026-09-23 correction: the paid run is a queue claim\n\nThe earlier B3 correction was wrong for this task. It read the Glas acceptance\nrunner, which makes its own fixture. The T03 exec path is different:\n`rein-aharness metered-once` runs one Activity Core claim cycle\n(`docs/owner-bootstrap.md`), and the SpendPolicy binds `worker_id`,\n`activity_definition_id`, `target_repo`, `project` and `repository_grant_id`\n(`docs/spend-admission.md`). The policy is immutable once `spend init` runs, so\nall of these must be fixed first:\n\n- target repo: a throwaway git repo on railiance01, no remote (operator-approved);\n- repository grant v1: `PROOF.md` only, exactly one commit, `publish: false`;\n- a production Activity Core definition carrying that grant and\n `harness.agent-dev-local@1.1.1`, left disabled until the attended run;\n- a worker identity and worker token for the metered owner. The existing\n `rein-aharness-claim-loop.service` on railiance01 claims by label, so the run\n needs a label it does not claim, or it could take the paid run.\n\nNo SpendPolicy, ledger, owner config, repo or definition was created.\n\n### 2026-09-23 option 1 preparation (partial)\n\nOperator chose: request multi-worker identities from activity-core (message\n`914853d9`), and run now under `rein-aharness@railiance01` isolated by label.\n\n- activity-core `6002d5c`: disabled definition `hfact-glas-metered-proof`\n (id `5bae5505-77f1-5ba3-8dfa-2e10ed15531e`), label `hfact-metered`, profile\n 1.1.1, grant `PROOF.md` / one commit / no publish. The parser accepts it; the\n live ConfigMap diff is additive only. **Not applied:** the harness classifier\n blocked the ConfigMap apply and sync Job on railiance01.\n- Fixture repo on railiance01: `/home/tegwick/hfact/targets/hfact-glas-proof`\n (mode 0700, no remote, base `679d23e0`).\n- SpendPolicy inputs: profile_sha256 `10e423fe\u202683ca65`, descriptor_sha256\n `4f151744\u20263a9b`, repository_grant_id `656911f7dff83e871434b415f0cee685`,\n max_turns 30. No `project` value is on record yet.\n\nNo SpendPolicy, ledger or owner config was written. No credential was read.\n\n### 2026-09-23 definition live; owner provisioning prepared\n\nThe operator ran the ConfigMap apply and sync Job. The sync log shows\n`hfact-glas-metered-proof` upserted (29 definitions). Operator chose project\n`prj-helixforge-factory` and list-price bounds for `claude-sonnet-5`\n(claude-api reference, cached 2026-06-24: USD 2 / 10 per MTok). The owner\nMessagesPolicy uses an input bound of 4 micro-USD per token (covers the 1h cache\nwrite), output 10, context 200000, output 32000, and the betas the CLI passed in\nthe synthetic proof. The worst-case hold per request is USD 1.12.\n\nA provisioning script (SpendPolicy, `spend init`, request tables, mode-0600\nowner config under `~/hfact/owner`) validates in memory. Staging it on\nrailiance01 was blocked by the harness classifier as a real-world transaction.\nIt has not been run. No policy, ledger or owner config exists yet.\n\n### 2026-09-23 metered identity and host placement\n\nactivity-core accepted a dedicated worker identity (ACTIVITY-WP-0039):\n`rein-aharness-metered@railiance01`. Its token is delivered by the companion\nlane `activity-core-metered-worker-token` (SECRETS-WP-0011). The operator chose\nto re-provision under that identity. The `~/hfact/owner` set (policy\n`f1e06b0b\u2026`, owner config `5fa8ea21\u2026`) is **superseded and unused**. Its ledger\nhas no reservations, and no `exec_owner` pin will name it. The new set goes in\n`~/hfact/owner-metered` (same envelope, runtime, profile, grant, definition and\ntarget), provisioned by the operator. The owner must be launched with\n`AGENT_HARNESS_WORKER_ID=rein-aharness-metered@railiance01`.\n\nPlacement: the operator chose to run `secrets-engine exec` on railiance01, next\nto the pinned owner. The host checkout is at `f7c12be` (origin/forgejo) with a\nPython 3.12 venv. Preflights pass there: both lanes load, and a pending-owner\nexec refuses before approval or backend. From the host, OpenBao-active,\napproval-engine, `flex-auth-secrets-engine` and KeyCape answer. The PDP and\napproval URLs must be literal loopback or HTTPS (`decision_check.py:73`,\n`approval_auth.py:90`), so the attended session needs host-side\n`kubectl port-forward` to 127.0.0.1 for both. That is a session step, not a\nstanding change.\n\n### 2026-09-23 metered owner provisioned; exec_owner drafted\n\nOperator provisioned `~/hfact/owner-metered` on railiance01: spend policy\n`a8ab3729\u2026`, owner config `0e263f82\u2026`, valid from 2026-09-23T16:36:52Z. The\nowner `--check` passes under `rein-aharness-metered@railiance01` with runtime\n`b6e4e8a4`. No key, no claim, dispatch disabled.\n\nThe configured binding is drafted in `docs/drafts/glas-exec-owner-configured.yaml`.\nIt pins the runtime python and the owner config, uses cwd `~/hfact/owner-metered`,\na fixed non-secret environment, and the companion\n`activity-core-metered-worker-token` \u2192 `ACTIVITY_CORE_WORKER_TOKEN`. It validates\nwith the catalog code, and the real pin and path-safety checks pass on\nrailiance01 (owner digest `00b5f076\u2026`). The catalog stays `pending` until\nACTIVITY-WP-0039 seeds the metered token and rolls out. `ACTIVITY_CORE_URL`\nassumes the host `actcore-api-port-forward` service on 127.0.0.1:8010; check\nthat it answers before the attended session.\n\nFounder decision 2026-09-23, relayed to activity-core (thread `a5449d3f`): the claim-loop token is\nminted fresh with a coordinated claim-loop restart, not moved (ACTIVITY-WP-0039-T03).\n\n\n### 2026-09-27 Activity Core dependency resolved\n\nActivity Core's 2026-09-24 handoff (`a2eae5f8`, `bfef619d`; source `54ab1e4`)\nreports the metered identity live, HTTP 200 for its own no-match claim and HTTP\n403 for a claim as the loop identity. SECRETS-WP-0011 records that return and\ncorrects its former wait reason. The drafted worker identity and label match.\n\nThis resolves the seed/rollout prerequisite in the 2026-09-23 note. It does not\nactivate the native lane. T03 still needs current recipient admission and file\npin validation, exact approvals for each protected action/lane, and attended\nnative apply, positive/negative verification, exec and session revocation.\nThe production catalog remains pending. The companion-only delivery guards\nadded under SECRETS-WP-0011-T05 must be included in the host checkout used for\nactivation. No credential read, queue claim or paid run occurred in this review.\n\n\n### 2026-09-27 configured owner and companion landed\n\nSECRETS-WP-0011 is finished at its catalog/implementation boundary. The binding\nformerly held in `docs/drafts/glas-exec-owner-configured.yaml` is now configured\nin the active Glas catalog, with an added exact private spend-policy file pin.\nThe installed owner's backend-free check and engine path/pin validation passed\non railiance01. Receipt: `docs/evidence/2026-09-27-companion-catalog-readiness.json`.\nThe original pending-recipient configuration is superseded; current code still\nrefuses any substituted child and requires fresh approvals and delivery state.\n\nT03 retains all native activation and delivery acceptance. Revalidate the owner\nand spend envelope in the attended execution window, use approvals bound to the\nnew owner digest and each lane, apply/verify both native lanes, and prove actual\nbounded owner delivery and cleanup. Configuration does not authorize those actions.\n\n### 2026-09-27 exact-model admission correction\n\nThe earlier backend-free pin check verified byte identity, not provider liability\nor actual CLI compatibility. Cross-owner follow-up found the installed owner\nreserved only 200k input tokens although Sonnet 5 accepts 1M, capped output at\n32k although the CLI requests 64k, and omitted a primary-request beta. The prior\nruntime proof silently selected profile 1.0.0; rein now requires exact profile\nand expected model and passed the corrected synthetic proof on Railiance.\n\n`tools/prepare_metered_activation.py` now builds the six exact per-lane/action\nCheckRequests through the PEP's own request builder, renders both plans and\nchecks the pinned non-secret config snapshots against reviewed provider facts\nand observed CLI shape. It makes no network or authorization call. The installed\npolicy fails; the corrected candidate passes. Native evaluator digests and\napproval IDs are deliberately absent. See `docs/proposals/glas-metered-20260927/`.\n\nThe source catalog now pins corrected owner SHA-256\n`e0d3fb84649fdca302eccd9415f3cc2beaee84bf07bd83205cdffbe93e5573bc`.\nThe host still has `0e263f82\u2026`, so current source refuses it until reviewed\nreplacement. The unchanged spend-policy pin is `f31c5859\u2026`; read-only host\ninspection found zero rows in parent, request and route tables and a clean target.\nHost Secrets Engine remains f7c12bed and needs current companion guards before\nactivation. The provider/worker custody and standing claim loop are untouched.\n\nThe corrected maximum hold is USD 4.64; only one fits the existing USD 5.74\nallowance. Do not promise tool-loop completion under that cap. T03 retains\nhost installation, scope/budget/FX/tariff acceptance and the existing native\nattended approvals, verification, delivery and revocation. No secret read,\napproval creation/consume, native apply or paid run occurred.\n\nValidation for this correction: 498 tests passed in the full Secrets Engine suite;\nthe finalized exact-profile Railiance proof passed and records its script SHA-256.\n\n### Approved installation and tool-session proposal \u2014 2026-09-27\n\nThe user approved the configuration/code update and separately requested preparation\nof the \u20ac10 tool-session proposal. Installed Secrets Engine `11cc0d5` and corrected\nowner `e0d3fb84` on Railiance; exact path/hash checks, substituted-command refusal,\nstandalone companion refusal and backend-free owner check pass. Standing worker,\nspend limits and existing ledger are unchanged; no credentials read or paid calls.\nDeployment receipt: `docs/evidence/2026-09-27-metered-owner-deployment.json`.\n\nActual pinned CLI/profile 1.1.1/runtime b6e4e8a4 passes a synthetic two-request Bash\ntool/result exchange and zero-forward underfunded refusal, with teardown and\nunchanged artifact. Receipt: `../rein-aharness/docs/evidence/2026-09-27-sonnet5-tool-session-proof.json`.\nThe inactive proposal is `../prj-helixforge-factory/operations/metered-tool-session-proposal.md`:\nEUR 10 run cap, USD 10 liability, EUR/USD 1.00 treatment, existing native USD 5\nthreshold/daily EUR 20/total EUR 500 retained. Two USD 4.64 holds fit. Installed\n0.87 FX is below the latest observed 0.876962 reference; fresh validity/FX acceptance\nis required. No new grant or paid execution is authorized by proposal preparation.\n\nRemaining owner tasks retain their waiting status: fresh spend grant/window,\naccounting continuity and replacement recipient pins; attended native per-lane\napproval/delivery/revocation; then natural queue/model/tool/commit/recovery proof.\nThis return supersedes earlier installation-pending statements, not those gates.\n\n\n## Loose-end review \u2014 2026-09-28\n\nThe final attended outcome in\n[the replacement-window packet](../docs/proposals/glas-metered-tool-renewal-20260927/README.md)\nsupersedes the installation and approval waits above. Reviewed the owner receipts\n`rein-aharness/docs/evidence/2026-09-27-metered-terminal-delivery.json`,\n`2026-09-27-metered-postflight.json` and `2026-09-27-metered-native-resume.json`.\nAll six exact decisions were consumed; both apply/verify lanes passed and both\nexec sessions were established and successfully revoked. The owner claimed the\nsingle queue job and closed failed at attempt 1. The runtime launchers referenced\na deleted build directory. No successful model/tool/commit acceptance is claimed.\n\nT03 remains wait for corrected runtime admission and recipient pins, owner\naccounting reconciliation (EUR 10 parent reservation held; observed billing\nunknown), and separate authority for another attempt. REINAH-WP-0003-T05/T06\nowns the runtime/accounting return. Previously consumed approvals must not be\nreplayed; absence of request rows does not prove no billing occurred. The workplan\nremains blocked. Installation and native credential delivery are completed\nportions of this existing task, not new work items.\n\n### 2026-10-08 record check \u2014 T03 stays wait\n\nChecked, without a provider call, secret read, host mutation, or owner retry:\n\n- `rein-aharness/docs/evidence/2026-09-27-metered-postflight.json` still has\n reservation `6efa9436-6a91-47c0-94e5-b31b5a0e7e3a` state `held`, liability\n `10000000` (EUR 10), `observed_usd` null, and no provider-request rows.\n `2026-09-27-metered-terminal-delivery.json` records the same unknown billing,\n `retry_authorized: false`, and `corrected_artifact_admitted: false`.\n- No later local receipt names a final USD cost for that run. Spend admission\n blocks a new ledger admission until that held reservation is reconciled from\n reviewed accounting (`rein-aharness/docs/spend-admission.md`).\n- Catalog `glas-claude-agent-dev-anthropic` still pins runtime `b6e4e8a4`,\n owner `e0d3fb84`, and spend policy `f31c5859`. The failed attempt's installed\n binding was owner `fed3f80f`, spend policy `69ea0071`, and exec-owner digest\n `310600ea` on the same broken runtime. Sand-boxer `81b5fcf` fixes launchers\n in source only; no replacement runtime digest is admitted. Founder decision\n `e642c8e2` admits the protected claim-loop service and is not this lane's pin.\n- Pins were not rewritten. Either the broken runtime or an unadmitted successor\n would make the next retry inexact.\n\nSingle next owner action: record the final non-secret cost for reservation\n`6efa9436-6a91-47c0-94e5-b31b5a0e7e3a` and reconcile that existing ledger.\nCorrected artifact admission and a separate retry remain later gates under\nREINAH-WP-0003-T05/T06. T03 stays `wait`; this workplan stays `blocked`."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"ops-mason": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/ops-mason/workplans/MASON-WP-0004-credential-inventory-descriptions.md",
|
|
"meta": {
|
|
"id": "MASON-WP-0004",
|
|
"type": "workplan",
|
|
"title": "Describe every stored credential so the store is navigable",
|
|
"domain": "infotech",
|
|
"repo": "ops-mason",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "codex",
|
|
"topic_slug": "custodian",
|
|
"created": "2026-08-28",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"MASON-WP-0003",
|
|
"NK-WP-0033"
|
|
],
|
|
"state_hub_workstream_id": "e5656747-a974-581a-a3d4-4e6bb7262f4c"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "MASON-WP-0004-T01",
|
|
"status": "done",
|
|
"decision_id": "e9f44beb-ad15-4285-8996-1e66d312fe59",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "5bda75f2-f780-579e-9d44-cc4011662b9a",
|
|
"body": "Most of the seventeen predate this repository and ops-mason cannot invent what\nthey are for. Group them by mount prefix, propose an owning repo for each from\nthe ops-warden catalog and the paths themselves, and take the founder's ruling\non the ones that are genuinely unclear.\n\nGuessing is the failure mode to avoid: a confidently wrong `used_by` is worse\nthan an empty one, because a rotation will trust it.\n\nAcceptance: every one of the seventeen has a named owner, or is explicitly\nlisted as unknown with the question that would settle it.\n\n2026-10-03: human gate routed to hub decision e9f44beb-ad15-4285-8996-1e66d312fe59 (D8: ops-mason plan approvals: unclear metadata paths and the live-survey plan) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n2026-10-09: live inventory under grant `claude-MASON-WP-0004-T01` (revoked\nafter): 49 paths, 45 undescribed (was 21/17 on 2026-08-28). Owner proposals in\n`docs/credential-owner-proposals-2026-10-09.md`: 38 documented (owner from\ncatalog or CCR), 3 genuinely unclear (`activity-core/default/llm-connect-provider-secrets`,\n`forgejo/forgejo-mailer`, `target-revenue/runtime-secrets`), and 4 undocumented\nfluid-telegram entries under tenant `infotech` that conflict with the approved\nMASON-WP-0005 plan (`coulomb`). Waiting on the founder's ruling for A and B.\n\n2026-10-09 done: founder ruled. A: `coulomb` as approved, the four values move\nthere (MASON-WP-0005). B1: retire the duplicate `activity-core/default/...`\nentry (founder-run delete via railiance-platform after a live no-grant check).\nB2: `forgejo/forgejo-mailer` belongs to the new `rapp-forgejo` repo. B3:\n`target-revenue/runtime-secrets` deferred as outdated. Every path now has a\nproposed owner or an explicit reason, which is T01's acceptance.\n\n## Describe the paths whose purpose is already documented"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0004-T02",
|
|
"status": "done",
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "a6a944d7-21c5-5043-a78d-b3809de0ee64",
|
|
"body": "Several are covered by an existing ops-warden catalog entry, playbook, or\nconstruction plan in `plans/` \u2014 `railiance/backup/*`, `rapp-qonto/*`,\n`user-engine/runtime`, `reuse-surface/runtime-secrets` among them. For those the\nfive fields can be written from documents that already exist, with `rotation`\npointing at the real procedure rather than paraphrasing it.\n\nAcceptance: `custody-inventory.py` reports these paths without a `!`, and each\n`rotation` field names a document that exists.\n\n2026-10-03: human gate routed to hub decision 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1: Attended OpenBao provisioning window: one session clears the pending credential lanes) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n2026-10-09: drafted. `scripts/custody-describe.py draft` builds\n`manifests/custody-descriptions.yaml` from the railiance-platform CCRs\n(`target.purpose`, `delivery.target`, `lifecycle.rotate`), the ops-warden\ncatalog and the owner proposals, never from OpenBao; four ops-mason-sourced\nentries were filled by hand from `plans/`. 29 of 38 have all five fields; 9\nhave gaps left empty on purpose (nextcloud x2, keycape-factor-issuer,\ngrafana-admin, smtp, and four `used_by`). Every entry is `review: draft`.\n`apply` writes custom_metadata only, for `review: accepted` entries, silently\n(`tests/test_custody_describe.py`, suite 157 passed). Founder run, after\nreview: `warden access openbao-platform-admin-login --exec -- sh -c 'python3\n/home/worsch/ops-mason/scripts/custody-describe.py apply\n/home/worsch/ops-mason/manifests/custody-descriptions.yaml >/dev/null 2>&1'`,\nthen read `~/.local/state/railiance/receipts/custody-describe.json`.\n(First attempt 2026-10-09 refused by the wrapper because apply printed status\nlines; nothing written, all entries were still drafts. apply is now silent.)\n\n2026-10-09 founder runs 3-4: the wrapper has a temporary HOME and the admin\npolicy has no `patch` capability, so apply now writes its receipt under the\nreal home and falls back to metadata get + merged put. Run 4 receipt: 27 of 29\naccepted entries `merged` (existing custom_metadata kept), 2 `failed put\nhttp=400` (`core-hub/forgejo-source-read`, `secrets-engine/approval-client`):\n`used_by` was 514 bytes, clipped by characters. Clipping is now by bytes; those\ntwo need one more run.\n\n2026-10-09 founder run 5: exit 0, receipt 29/29 accepted entries `merged`, 9\ndrafts `skipped`. Remaining for T02 acceptance: re-run custody-inventory under\na survey grant to confirm the 29 report without `!`. The 9 gaps go to owners\nin T03.\n\n2026-10-09 done: custody-inventory under grant `claude-MASON-WP-0004-T02`\n(revoked after): 49 paths, 16 undescribed (from 45); none of the 29 accepted\npaths is flagged, and the keycape entry kept its CCR-2026-0033 keys next to the\nfive new ones. Each `rotation` names an existing CCR file or document. The 16\nleft: the 9 drafts with gaps (T03), the four `infotech` fluid-telegram entries\n(moving, MASON-WP-0005-T04), the retiring `activity-core/default` duplicate,\n`forgejo/forgejo-mailer` (rapp-forgejo) and the deferred\n`target-revenue/runtime-secrets`.\n\n## Resolve the rest with their owners"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0004-T03",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"MASON-WP-0004-T01"
|
|
],
|
|
"blocked_on": "owners",
|
|
"blocking_reason": "Owners fill the gaps in manifests/custody-descriptions.yaml for the 9 draft entries (asked 2026-10-09).",
|
|
"priority": "low",
|
|
"state_hub_task_id": "fff26914-d854-5854-b350-d7241812fb04",
|
|
"body": "Blocked on T01. What remains after T02 are paths whose purpose is not written\ndown anywhere. Each needs its owner to answer three questions: what is this, what\nbreaks when it changes, and what do you do when it is lost.\n\nA path whose owner cannot answer the third question is a finding in its own\nright \u2014 it is a credential with no recovery story, and that is worth knowing\nbefore it is lost rather than after.\n\nAcceptance: `custody-inventory.py` exits 0 across both mounts, or the remainder\nis a short list with a recorded reason each.\n\n2026-10-09: asked railiance-platform (nextcloud x2, telemetry smtp,\ngrafana-admin, agent-harness deploy key, whynot-design npm-publish),\nnet-kingdom (keycape-factor-issuer) and key-cape (rapp-qonto keycape-client).\nuser-engine/runtime's `on_loss` is ops-mason's own to write from the\nuser-engine plan once its ESO rotation rehearsal is recorded.\n\n2026-10-09: net-kingdom answered for `keycape-factor-issuer` (message\n`75b48030`): four fields filled in the manifest; `rotation` stays empty because\nno rotation document exists, a gap attributed to railiance-platform. The entry\nstays a draft until that exists. railiance-platform retired the duplicate\n`activity-core/default/llm-connect-provider-secrets` (message `af873813`), and\nthe four `infotech` fluid-telegram entries were moved to `coulomb`.\n\n2026-10-10: answers filled into the manifest (still `review: draft`, awaiting\nfounder acceptance and an apply run): railiance-platform (message `3e490cd4`)\ncompleted `operators/nextcloud/backup`, `railiance-telemetry/smtp`,\n`telemetry/grafana-admin`, `agent-harness/forgejo-deploy-key` and\n`whynot-design/npm-publish`; key-cape (message `40395cc2`) named the two readers\nof `rapp-qonto/keycape-client` (the rapp-qonto runtime's transport is for\nrailiance-apps to name). Still open: `operators/nextcloud` (railiance-platform\nis asking the founder what it holds), `keycape-factor-issuer` rotation\n(railiance-platform gap) and `user-engine/runtime` on_loss (ops-mason, after\nits rotation rehearsal).\n\n2026-10-10: founder accepted the six and applied: 34 paths `merged`, 3 drafts\nskipped. `operators/nextcloud/backup` failed with HTTP 403, under both the\nadmin wrapper and the founder's own session (`operator-custody`): metadata is\nreadable but neither patch nor put may write it. Asked railiance-platform\nwhether `operators/*` metadata is write-protected by design and who writes\ndescriptions there (message `6b08c40d`).\n\n2026-10-10 inventory (same grant as WP-0009-T05): 49 paths, 11 undescribed.\nNew since the last run: the four fluid-telegram entries at the `coulomb` path\n(moved, never described) and `email-connect/callers/user-engine`. Drafted the\nfluid-telegram four from the approved plan (draft until fluid-telegram confirms,\nmessage `da7e711c`); asked email-connect for its new path (message\n`acb3ff22`).\n\n## Make an undescribed path visible before it accumulates"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0004-T04",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"MASON-WP-0004-T03"
|
|
],
|
|
"blocking_reason": "After T03. A scheduled --undescribed report needs an unattended metadata-read credential and a named reader; survey grants are human-minted and expire within an hour.",
|
|
"priority": "low",
|
|
"state_hub_task_id": "9a0cea06-eb63-54ad-963d-db4ea79c7c66",
|
|
"body": "Blocked on T03. Seventeen accumulated because nothing ever looked. Wire\n`custody-inventory.py --undescribed` into whatever already runs regularly\nagainst this repo, so a new undescribed path is noticed in days rather than\ndiscovered in a year.\n\nThe check must not fail a build for a path someone else owns; it reports, and\nthe report has a reader.\n\nAcceptance: an undescribed path added today surfaces without anyone\nremembering to look.\n\n## Loose-end review \u2014 2026-09-28\n\nT01\u2013T04 remain wait: no valid scoped metadata grant/current inventory or complete owner/recovery confirmations are available. Inventory failure handling and the private-tunnel defaults are fixed and tested; scheduled reporting still needs its reader and credential.\n\nEvidence and precise resumption conditions: [review](../docs/evidence/2026-09-28-loose-end-review.md). Existing tasks retain all remaining obligations; no new task or workplan was opened."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-mason/workplans/MASON-WP-0005-fluid-telegram-operator-credential-lane.md",
|
|
"meta": {
|
|
"id": "MASON-WP-0005",
|
|
"type": "workplan",
|
|
"title": "Construct the fluid-telegram operator credential lane",
|
|
"domain": "infotech",
|
|
"repo": "ops-mason",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "codex",
|
|
"topic_slug": "helix-forge",
|
|
"created": "2026-09-04",
|
|
"updated": "2026-10-05",
|
|
"state_hub_workstream_id": "483e56d6-6601-5377-9066-66225214c046"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "MASON-WP-0005-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "18c9099f-882f-575c-93b9-cc68d7fbc2af",
|
|
"body": "Obtain railiance-platform's explicit confirmation of the tenant/path segment\nand KeyCape group claim. The current recommendation is\n`platform/workloads/coulomb/fluid-telegram/hall-of-helix`; it follows the\nowner's established tenant/org shape and deliberately replaces the consumer's\nunconfirmed `infotech` assumption. The proposed OIDC group is\n`fluid-telegram-operators`, but no role may be built until the actual claim is\nconfirmed.\n\nRe-run the live policy/auth/mount survey with a scoped ops-mason session before\nmoving the construction plan from `draft` to `reviewed`. Do not infer absence\nfrom the current disk-only survey.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): the two unread railiance-platform\nreplies of 2026-10-02 concern MASON-WP-0007 only and say nothing about this\nlane. The applicable answer is railiance-platform's earlier reply of 2026-09-09\n(read, never recorded here): the OIDC group, assurance level and callbacks\nbelong to KeyCape/NetKingdom; the tenant/path and per-entry field/capability\nmatrix are not accepted by a draft and need acceptance (now carried by the T03\nplan approval); the construction contract and writer authority are ops-mason's\nside. Re-qualified from `message-from:railiance-platform` to\n`message-from:key-cape`; asked key-cape for the claim the same day.\n\n2026-10-08: key-cape answered (message `b2ed890f`, source key-cape `e0b5fae`):\n`groups_claim=groups`, bound `groups=[fluid-telegram-operators]`; bound\n`/assurance/level=aal2` with `bound_claims_type=string` (as CCR-2026-0034);\ncallbacks are the two loopback CLI URIs on 8250 plus the operator-tunnel UI\ncallback on 18200. Recorded in the plan's OIDC role shape. The executor now\nalways pins `aal2` and accepts that exact UI callback, refusing the retired\npublic one (`tests/test_oidc_matrix.py`, 153 passed). Two inputs remain, both\nhuman: the founder go for net-kingdom to create the LLDAP group with its\nmembers, and a scoped grant for the live survey (no operator session today).\n\n2026-10-08: founder go given in this session: create LLDAP group\n`fluid-telegram-operators` with the single initial member `tegwick`. Sent to\nnet-kingdom (message `259ec26d`), which owns directory acts; ops-mason does not\nwrite LLDAP. Waiting for net-kingdom's metadata-only evidence.\n\n2026-10-08: live survey run under grant `claude-MASON-WP-0005-T01`\n(`ops-mason-survey`), recorded in the plan's section 2: path unused, proposed\npolicy and OIDC role names free, all 81 policy bodies scanned and only\n`platform-admin` covers the path, no catalog route. The live\n`keycape-secrets-engine-openbao-operator` role confirms the binding shape. Only\nthe group evidence remains for T01; the plan can then move to `reviewed`.\n\n2026-10-09: net-kingdom (reply `a2693a9d`, earlier `62e1b721`): no agent path\ntoday. identity-provisioner `POST /v1/groups/ensure` exists only from\nnet-kingdom `630ebfd`, the live image is the older `main-6c4fcaf`, and the\n`identity-provisioner-groups` lane waits on WARDEN-WP-0044. The founder creates\nthe group in the LLDAP admin UI (Groups, Create group, add `tegwick` only) and\nreports names only; `tegwick` may need to sign in again before the claim shows.\n\n2026-10-09 done: founder reports \"group exists, members [tegwick]\". Every T01\ninput is closed (claims, callbacks, group, live survey); the plan is now\n`reviewed` and its section 5 executive summary is written for T03.\n\n## Extend the construction and credential-change contracts"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0005-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "69c558d9-664f-5ce0-80b2-d2e7544353a3",
|
|
"body": "Add an approved `openbao-oidc-kv-read-write` engine shape to ops-mason rather\nthan forcing this demand through the AppRole/Kubernetes read-lane executor.\nCoordinate the matching railiance-platform CCR schema/validator extension;\nits current `request_type` enum and name checks accept only\n`workload-kv-read`.\n\nThe extension must render four exact KV-v2 data-path stanzas, preserve the\nphase-4 approval gate, refuse wildcard/parent scopes, bind one confirmed OIDC\nclaim, and emit metadata-only audit records. It must never read or write KV\nvalues. Add unit tests for approval refusal, exact capabilities, no sibling or\nparent access, and the create-only salt shape.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): no new railiance-platform reply bears\non this task; its 2026-09-09 reply says the per-path capability schema,\nvalidator and exact policy are already drafted on its side (RPF-WP-0035-T03,\n`docs/credential-lane-designs/fluid-telegram-operator-kv.md`) and it will\nreview the field/capability matrix against the validator whenever ops-mason\nhas one. The platform-side wait is gone, so the task moves from `wait` to\n`todo`: build the engine shape and tests with the OIDC claim as a parameter,\nthen send the matrix to railiance-platform for review. Binding the confirmed\nclaim still needs T01. Not built in this sweep.\n\n2026-10-05 done: source contract checked against this task, not against the\nprior progress note. `python3 -m pytest tests/test_oidc_matrix.py` \u2014 20 passed.\nNamed tests: `test_draft_and_changed_approval_never_execute` (approval\nrefusal, no bao call); `test_matrix_has_exact_data_scope_and_write_once_salt`\n(four exact KV-v2 data-path capabilities, no sibling or parent path,\ncreate-only salt); `test_refuses_unsafe_matrix_before_bao` (wildcard and\nparent scopes refused); `test_exact_role_binding_and_value_free_build` (one\n`groups` claim parameter, policy/auth writes only, metadata-only audit);\n`test_failure_suppresses_output_and_never_claims_success` (no value in the\nfailure). No OpenBao run and no plan approval. The confirmed claim value\nremains T01. Matrix paths sent to railiance-platform for RPF-WP-0035-T03\nreview (message `79570eb8-2107-4f75-b463-a45c2a70b7bf`):\n`src/ops_mason/executor.py` and `tests/test_oidc_matrix.py`.\n\n## Review the plan and obtain the decision"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0005-T03",
|
|
"status": "done",
|
|
"decision_id": "e9f44beb-ad15-4285-8996-1e66d312fe59",
|
|
"priority": "high",
|
|
"state_hub_task_id": "48a2b4ec-8e66-5b98-b039-c17fd8d820ab",
|
|
"body": "Complete the live existing-structure survey and review\n`plans/fluid-telegram-operator-credential-lane.md`. Present the exact path,\npolicy, OIDC role, confirmed claim, callbacks, capability matrix,\nTTL/default-policy posture,\nwrite-once recovery consequence, agent boundary, reversal procedure, and\nadapter separation for explicit human approval. Only the plan's\n`status: approved` plus `approved_by` and `approved_at` authorizes a build.\n\n2026-10-03: human gate routed to hub decision e9f44beb-ad15-4285-8996-1e66d312fe59 (D8: ops-mason plan approvals: unclear metadata paths and the live-survey plan) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n2026-10-09 done: founder approved in this session (\"APPROVE\nfluid-telegram-operator-credential-lane\"). The plan carries `status:\napproved`, `approved_by: \"Bernd Worsch\"`, `approved_at: \"2026-10-09\"`, the full\n`build_spec` and `approved_spec_sha256` `41a0ca27...`; the executor's approval\ngate accepts it (checked by loading the plan, no bao call). Hub decision\n`e9f44beb` also gates WP-0004-T01 and stays open until that half is answered.\n\n## Build the approved operator lane"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0005-T04",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"MASON-WP-0005-T03"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "0e3d1333-ffc3-5f67-8528-50a9551c4949",
|
|
"body": "After T03, create the exact policy and `auth/netkingdom` OIDC role through the\napproved engine surface. Add each high-risk data and metadata path to the\nagent read boundary. Do not create a wildcard campaign prefix and do not enter,\nrequest, fetch, or display any Telegram value.\n\nThe redaction-salt path grants `create,read` only. It does not grant `update`,\n`patch`, `delete`, metadata mutation, destroy, or undelete. Recovery from a bad\nfirst write is therefore an attended, separately approved platform action, not\na provisioner capability.\n\n2026-10-09: four values already sit at\n`platform/workloads/infotech/fluid-telegram/hall-of-helix/` (written\n2026-10-07, operator-session v4). Founder ruling: keep `coulomb` as approved\nand move them. The move is part of this build: one attended, output-free\nplatform-admin step that writes each entry at the `coulomb` path with CAS 0,\nverifies versions, then deletes the `infotech` metadata, so `redaction-salt`\nkeeps its value and stays write-once. fluid-telegram repoints its refs.\n\n2026-10-09 done (railiance-platform `ce1c1a6`, message `af873813`, evidence\n`docs/evidence/2026-10-09-fluid-telegram-t03-founder-session.json`): the\nfounder applied CCR-2026-0039 at 10:30Z (policy, OIDC role, 8 agent denies\nappended to `agent-high-risk-boundary`; readback matched) and ran the custody\nmove: all four entries now at the `coulomb` path, version 1 each, `infotech`\nmetadata deleted. fluid-telegram must set\n`FLUID_BAO_PREFIX=workloads/coulomb/fluid-telegram/hall-of-helix`.\n\n## Verify capabilities and record metadata-only evidence"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0005-T05",
|
|
"status": "progress",
|
|
"depends_on": [
|
|
"MASON-WP-0005-T04"
|
|
],
|
|
"blocked_on": "human",
|
|
"blocking_reason": "ops-mason checks and the non-member refusal pass (2026-10-09). tegwick has no MFA factor: it enrolls through user-engine self-service MFA (message ab89a591, USER-WP-0028-T03), then the founder runs scripts/verify-fluid-telegram-lane.sh member; fluid-telegram runs the salt create-once probe (FT-WP-0002).",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4c205be7-4f1f-5dd1-aafa-fc112fdd640e",
|
|
"body": "Use a short-lived token for the confirmed operator identity to prove:\n\n- reads on all four exact data paths;\n- create/update on `operator-session` and `bot-token`;\n- no provisioner write on `operator-app`;\n- create but no update/patch/delete on `redaction-salt`;\n- deny on the parent, another campaign, a sibling workload, and unrelated\n high-risk paths;\n- deny for a non-member identity; and\n- agent-bound identities remain denied on all four paths.\n\nRevoke the test token immediately. Record only path names, reported\ncapabilities, audit request ids/timestamps, versions/timestamps, and pass/fail.\nAny value-side create/update test must be performed by the sanctioned\noperator/platform flow and return metadata-only evidence to ops-mason.\n\n2026-10-09 (grant `claude-MASON-WP-0005-T05`, revoked after): live policy\n`workload-kv-fluid-telegram-hall-of-helix-operator` equals the approved matrix\nexactly (so parent, sibling campaign and sibling workload are not granted);\nthe OIDC role equals the approved role document (groups + aal2, 15m/30m, no\ndefault policy, three callbacks); `agent-high-risk-boundary` holds the 8\n`deny` stanzas (data + metadata for the four entries); all four entries at the\n`coulomb` path v1, the `infotech` ones gone. Owner-run remainder: a member\nlogin and a non-member login with `scripts/verify-fluid-telegram-lane.sh`\n(capabilities only, receipt under `~/.local/state/railiance/receipts/`), and\nthe salt create-once probe by fluid-telegram (message `f966db1c`).\n\n2026-10-09: non-member check passed. A login on the role as `platform-root`\n(not in `fluid-telegram-operators`) was refused by OpenBao with \"claim groups\ndoes not match any associated bound claim values\" (receipt\n`fluid-telegram-lane-non-member.txt`, 18:11Z). Member run as `tegwick` pending.\n\n2026-10-10: the member run cannot pass yet: `tegwick` has no enrolled factor, so\nKeyCape asks for an OTP it cannot satisfy, and the role requires `aal2` anyway.\n`tegwick` enrolls TOTP through privacyIDEA self-service (net-kingdom\nplatform-root-custody.md steps 6-7, same procedure), then the member run.\n\n2026-10-10: founder direction: MFA setup becomes a convenient self-service\njourney for all users, not a one-off. Asked user-engine (message `ab89a591`) to\ndeliver it (USER-WP-0028-T03 / USER-WP-0027-T04, decision cef97ccd), with\n`tegwick` as the first attended real-user acceptance, and to reply when\n`tegwick` has an active factor.\n\n## Hand off routing and keep the adapter lane separate"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0005-T06",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"MASON-WP-0005-T05"
|
|
],
|
|
"blocking_reason": "After T05 verification; only ops-warden activates the entry.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "09eae088-808d-5342-b100-292e13958ee3",
|
|
"body": "Propose `fluid-telegram-operator` to ops-warden as a pointer-only entry with\n`owner_repo: ops-mason`, `warden_executes: false`, and\n`resolvable: false`. It may move from `draft` to\n`applied-pending-verify` after construction, and only ops-warden may activate\nit after T05.\n\nThe adapter lane is tracked separately as `MASON-IN-0003`, tied to\n`FT-WP-0002-T06`. Its future policy may read only `bot-token` and\n`redaction-salt`; it must be denied `operator-app` and `operator-session` and\nmust use the adapter's own runtime identity rather than this attended OIDC\nrole.\n\n2026-10-09: entry proposed to ops-warden as pointer-only, `resolvable: false`,\n`applied-pending-verify` (message `856bd6ba`); activation stays with\nops-warden after T05.\n\n2026-10-10: ops-warden catalogued it (`23ba584`, message `b73aa5f0`) as\n`fluid-telegram-operator`, pointer-only, status `draft` (its catalog has no\napplied-pending-verify), with playbook `wiki/playbooks/fluid-telegram-operator.md`.\nIt activates on the member receipt and the FT-WP-0002 salt probe.\n\n## Loose-end review \u2014 2026-09-28\n\nT01\u2013T06 remain wait: accepted tenant/matrix, confirmed identity/MFA/callbacks, approved matching writer contracts, live survey, explicit construction approval and verification are outstanding. The platform design remains proposed. No lane was built or activated.\n\nEvidence and precise resumption conditions: [review](../docs/evidence/2026-09-28-loose-end-review.md). Existing tasks retain all remaining obligations; no new task or workplan was opened.\n\n\n## Operator-matrix source delivery \u2014 2026-10-04\n\nT02 advances to progress. The ops-mason engine now renders the exact four-entry\nOIDC matrix, writes only policy/auth structure, checks confirmed identity and\nplatform-review reference parameters, enforces narrow loopback callbacks and\nbounded tokens, and reuses the existing fresh exact-spec construction approval\ncheck before any Bao command. Value output is suppressed; audit records hold\nonly coordinates and approval digest. Actual source tests cover no-approval,\nchanged scope, unsafe paths/claims/callbacks, salt create-only capabilities,\nrole payload, no KV-value calls, and failure redaction.\n\nPlatform's design is still a proposal: no matching operator-matrix request type\nexists in its current CCR schema/validator. The old September note saying the\nschema/validator are already drafted does not establish implementation or\nacceptance. Platform contract support/review remains in T02; confirmed claim,\nissuer/MFA assurance and callbacks remain T01, then live survey and explicit\nexact-plan approval T03. No production role, policy, login or credential was\ncreated. The construction plan stays draft; local synthetic identity references\nin tests do not count as owner returns. This source wave also preserves all\nunrelated dirty owner files and the existing untracked construction plan.\n\n2026-10-04 normal receiving initially refused an identical duplicate T01 fence\nin the closed MASON-0001 bootstrap source. Removed only the repeated identical\nfence, preserving the single logical task, label, existing UUID, title, status\nand every prose section; no record migration or task deletion. Retry normal\nForge receiving after this source-level duplicate repair.\n\n2026-10-05: T02 is done on the source contract and the unit tests named in\nthat task. Platform review of the matrix is the RPF-WP-0035-T03 handoff, not\nan open ops-mason code gap. T01 and T03\u2013T06 stay wait. This workplan stays\nblocked. The construction plan stays draft."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-mason/workplans/MASON-WP-0006-readiness-tier-check.md",
|
|
"meta": {
|
|
"id": "MASON-WP-0006",
|
|
"type": "workplan",
|
|
"title": "Check the target's readiness tier before a direct Kubernetes apply",
|
|
"domain": "infotech",
|
|
"repo": "ops-mason",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "claude",
|
|
"topic_slug": "ops-mason",
|
|
"created": "2026-09-21",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "1b900161-51ff-544f-8412-ba7fcab64bb5"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "MASON-WP-0006-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "7b6fe7b4-08f7-5ad0-899d-a4862b5ddb00",
|
|
"body": "`bundles/whitehat-foundational-plane.yaml` is the only bundle today, and its plan\nis `built`. It targets the `whitehat` namespace, which is not a rApp and carries\nno ADR-0006 `readiness_state`. Under the decision it therefore defaults to the\nproduction tier, and once T03 lands, a further direct apply of it would be\nrefused.\n\nThis workplan was told the check must not change behaviour for today's\nnon-production plans. Whether the whitehat plane is one of them is not a\nquestion ops-mason can answer for itself. The founder chooses one of:\n\n- (a) it is a platform object and production-tier, as the default says; future\n changes to it go through the manifest repository or `BREAK_GLASS`;\n- (b) it gains a readiness state from its owner (whitehat-security), in which\n case `readiness.target` names that record; or\n- (c) an explicit, dated exception.\n\nT03 must not merge before this is answered.\n\n**Resolved 2026-09-21; implemented 2026-09-28.** The founder chose explicit\nnon-production placement for namespace whitehat. Decision and inbox receipt\nare recorded in the September 28 review. This unblocks T03.\n\n## Extend the bundle schema with the readiness block"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0006-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "89d07bd5-5a92-5a06-9ecb-441799c14dd7",
|
|
"body": "Add the optional `readiness` block to `PlaneBundle.load` as described above. It\nis included in the bundle digest, as the bundle file already is. Add a\n`--activation {APPROVED,BREAK_GLASS}` option to `plane apply`, defaulting to\n`APPROVED`, and a `--readiness-repo` option. `BREAK_GLASS` requires a\n`--break-glass-reason` string. No existing refusal is relaxed.\n\n**Done 2026-09-28.** Schema/CLI implemented; the mapping also requires an\nexplicit namespace matching the bundle. Whitehat now pins the source used to\ncheck whether a binding supersedes its explicit placement.\n\n## Enforce the tier in preflight and apply"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0006-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "163a807b-29aa-5eb7-a9a8-ef1ac70c89d3",
|
|
"body": "Add a pure function, `resolve_tier(state, target, activation, today)`, returning\nthe tier and whether a direct apply is allowed, and call it from `apply` after\nthe plan-approval and digest checks and before any `kubectl` write. `preflight`\nreports the resolved tier without refusing, so a production-tier plane can\nstill be validated.\n\nTests, all against the injected runner:\n\n- a `verified` rApp target applies under `APPROVED` (non-production tier);\n- a `production-approved` target is refused under `APPROVED`, with no `kubectl\n apply` call made;\n- the same target is allowed under `BREAK_GLASS`, and the evidence records it;\n- `rapp-policy-nexus` is allowed under `APPROVED` on 2026-12-20, is recorded\n with `transition: true` and tier production, and is refused on 2026-12-22;\n- no `readiness` block, `kind: platform`, an unlisted rApp, a digest mismatch,\n and a file changed since the pin each resolve to production and are refused;\n- the existing forbidden-kind, `data`/`stringData` and namespace tests still pass\n unchanged.\n\n**Done 2026-09-28.** Source digest, ancestry, local freshness and complete\nbinding history are checked. Historical production approval remains production;\ndeprecation retains the last known tier. Unknowns fail closed. The policy-nexus\ntransition stops on December 21 itself. Preflight reports; apply refuses before\nKubernetes commands. Covered by injected-runner regression tests.\n\n## Record BREAK_GLASS and its reconcile-back obligation"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0006-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "66349531-09ee-55b9-be47-537842c80f3b",
|
|
"body": "A `BREAK_GLASS` apply writes its reason, actor and time into the evidence\nrecord and prints the follow-up that is owed: the same change, committed to the\nmanifest repository that ArgoCD reconciles. ops-mason does not open that change\nitself.\n\n**Done 2026-09-28.** Apply evidence and printed JSON include the emergency\nreason, local account, UTC time and GitOps reconciliation obligation. Empty\nreasons are refused without invoking the runner.\n\n## Update the docs and the declaration"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0006-T05",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "6d64e7f5-9cff-5bf9-9851-97d318d1df0a",
|
|
"body": "Update `docs/kubernetes-plane.md` with the tier table and the readiness block,\nand change the `enforcement` line of the `kubernetes-plane-apply` entry in\n`INTENT.md` from \"not yet in code\" to point at the check.\n\n**Done 2026-09-28.** Documented tiers, pins, mapping, history, checkout\nfreshness limits and emergency procedure; removed the withdrawn\nrail-kubernetes ownership/layer assertion from INTENT.md.\n\n## Review on 2026-12-21"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0006-T06",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "89f1058f-33bc-47a8-8a49-0b44d426c67e",
|
|
"blocked_on": "message-from:railiance-platform",
|
|
"blocking_reason": "Dated review 2026-12-21: platform confirms policy-nexus ArgoCD onboarding; founder reviews the plan-approval exception.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "49dd5f9a-307b-5baf-809e-bd3893c73341",
|
|
"body": "On 2026-12-21 the policy-nexus transition ends and the plan-approval exception\ncomes up for review. Confirm with railiance-platform that policy-nexus is\nonboarded to ArgoCD. The date check in T03 ends the transition in code on that\ndate either way.\n\n2026-10-03: human gate routed to hub decision 89f1058f-33bc-47a8-8a49-0b44d426c67e (D2: ArgoCD owns production: go-ahead sequence for railiance-apps-root, issue-core, policy-nexus and activity-core automation) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): the 2026-10-02 railiance-platform\nreplies concern the tenant-engine audit-core sender (MASON-WP-0007) and say\nnothing about policy-nexus ArgoCD onboarding. Gate unchanged: still the dated\n2026-12-21 review, platform confirmation plus founder decision 89f1058f.\n\n## Loose-end review \u2014 2026-09-28\n\nT01\u2013T05 are done: the founder resolved the whitehat placement and the guarded readiness implementation, tests, emergency evidence and docs are complete. T06 remains wait until the 2026-12-21 platform/exception review; this workplan is blocked on that dated review.\n\nEvidence and precise resumption conditions: [review](../docs/evidence/2026-09-28-loose-end-review.md). Existing tasks retain all remaining obligations; no new task or workplan was opened."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-mason/workplans/MASON-WP-0009-keycape-secrets-engine-openbao-client-custody.md",
|
|
"meta": {
|
|
"id": "MASON-WP-0009",
|
|
"type": "workplan",
|
|
"title": "Place the KeyCape secrets-engine-openbao client secret in OpenBao",
|
|
"domain": "infotech",
|
|
"repo": "ops-mason",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "claude",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-06",
|
|
"updated": "2026-10-07",
|
|
"state_hub_workstream_id": "d9be08f5-a0f5-5cd1-8f87-0a6868661d77"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "MASON-WP-0009-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "67e6b80b-3d21-5d19-80e9-23afb2453d0a",
|
|
"body": "Plan written and reviewed from source state. The live `bao` survey is\ndeferred to T04 (no bao access in this task).\n\n## Founder approval"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0009-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4329bcd1-d42f-56a3-92cb-63b36d79549e",
|
|
"body": "2026-10-08 (inbox sweep): given and acted on. key-cape reported 2026-10-07\n(message `dc8b5d3b`) that the founder applied CCR-2026-0033 (amended under\ndecision `1fdd993b` with `token_self_lifecycle`) and CCR-2026-0034; the custody\nlocation decision is `2ab717e1`; the client was registered under live go\n`caafe4be`.\n\n## Owner changes delivered"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0009-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "f59fae58-397a-5bf5-9d1d-a33dc4aaa2ac",
|
|
"body": "2026-10-08 (inbox sweep): all three owners delivered. railiance-platform\nrevised CCR-2026-0033 (`4a284f0`, message `7e96e835`); secrets-engine replaced\nthe consumer file with an in-memory OpenBao read (`b8094f7`, message\n`c84fb5ba`); key-cape confirmed `groups` and the `aal2` assurance binding\n(`7d96ee4`, message `71a31d0d`). Live result (key-cape `e0b5fae`, KEY-WP-0037\nfinished 2026-10-07): ESO `sso/keycape-secrets-engine-openbao-client` synced,\nverify-client 10/10 with excess scope and wrong secret refused, founder\noperator OIDC login (net-kingdom-admins, aal2) and revoke-self worked.\nEvidence: key-cape `docs/evidence/2026-10-07-secrets-engine-openbao-issuance.json`.\nOnly T05 (service-JWT lane proof, RPF-WP-0035-T02) remains.\n\n## Verify and propose the route"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0009-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "01f55a4d-06de-5d48-a3db-a0746dcf9892",
|
|
"body": "After platform applies the objects: a live metadata-only survey and the\nplan's six verification checks (capabilities and metadata only). Then a\npointer-only ops-warden entry for the operator lane (`resolvable: false`\nuntil the checks pass).\n\nNote (2026-10-07, MASON-IN-0004): the capability verification runs under the\nread-only `ops-mason-survey` grant, which replaces `ops-mason-build`. Installing\nthat policy is a founder act (AGENTS.md, \"Installing the survey policy\");\nops-mason cannot install or widen it.\n\nDone 2026-10-07 under grant `claude-MASON-WP-0009-T04` (`ops-mason-survey`,\nrevoked and shredded after use). Evidence, value-free:\n`docs/evidence/2026-10-07-keycape-secrets-engine-openbao-capabilities.json`.\nAll five capability checks pass: both lane policies match the platform repo\nfiles; both roles match CCR-2026-0033/0034 (retired redirect noted); KV metadata\nis v1, `cas_required`, `max_versions=2`, `delete_version_after=0s`, custom\nmetadata as in plan 3.1; only the two lane policies plus `platform-admin`/root\nreach the data path, no `auth/jwt` (or `keycape-services`) mount exists, the\nESO reader is on Kubernetes auth; the grant itself is `deny` on the data path\nand read-only on `sys/policies/acl/*`. Not permitted by the survey grant:\n`auth/keycape/role`. Owner observations (retired `ops-mason-build` still\ninstalled; `secrets-engine-prod` can author `se-prod-*` policies; this path is\nmissing from `agent-high-risk-boundary`) are in the evidence file. Plan checks\n1-3 and 6 need live lane tokens and the route proposal is still owed: T05.\n\nSide finding, fixed: `scripts/bao-session.sh grant` reported \"policy does not\nexist yet\" whenever `bao policy read` failed, including when the founder's\n`~/.vault-token` session was expired or unauthorised. It now says \"cannot read\n(session expired or not permitted)\" unless bao answers \"No policy named\"\n(`tests/test_bao_session.py`).\n\n## Live lane proof and pointer route"
|
|
},
|
|
{
|
|
"id": "MASON-WP-0009-T05",
|
|
"status": "progress",
|
|
"blocked_on": "human",
|
|
"blocking_reason": "ops-mason checks complete (policies, roles, invariant ii, login proof). Owner-run: live operator/ESO token capability checks and a non-member refusal; ops-warden activates the proposed pointer.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "1b1a0566-add7-59c1-94b0-6bb81d2d1537",
|
|
"body": "Once the service-JWT lane exists: re-run invariant (ii) against its policy,\ncollect owner-run evidence for checks 1-3 and 6 (operator and ESO token\ncapabilities, non-member refusal, a secrets-engine `service-jwt` run), then\npropose the pointer-only ops-warden entry for the operator lane\n(`resolvable: false` until those pass).\n\n2026-10-09: railiance-platform packaged the lane as CCR-2026-0038 (proposed,\n`0b2e7dd`, message `029a6ee2`): isolated JWT mount `auth/keycape-services`,\nrole `secrets-engine-openbao` (KeyCape registration claims, 5m, 8 uses, no\ndefault policy), policy `secrets-engine-login-self` (self endpoints only, with\nexplicit deny on `platform/data/` and `platform/metadata/` for\n`workloads/keycape/secrets-engine-openbao`, so invariant (ii) holds by\nconstruction). New `service-jwt-login` applier with read-back; 8 tests. Waits\non the founder's approve, confirm-binding and delegated apply.\n\n2026-10-09: already applied. railiance-platform `1b36e14` records the founder's\napproval, binding confirmation and delegated apply at 2026-10-08T22:42Z, with a\nmatching value-free readback (evidence in the CCR). RPF-WP-0035-T02 now waits\nonly on the login proof (SECRETS-WP-0012-T03).\n\n2026-10-10: check 6 passed. The founder ran `secrets-engine service-auth\nprobe-openbao`: ok, auth provider service-jwt, secret source\nopenbao-oidc-in-memory, both revoke-self true (secrets-engine evidence\n`docs/evidence/2026-10-10-keycape-openbao-probe.json`, `a963a77`; message\n`6ed92390`). SECRETS-WP-0012 is finished.\n\n2026-10-10 (grant `claude-MASON-WP-0009-T05`, revoked): invariant (ii) holds:\nlive `secrets-engine-login-self` equals the railiance-platform file and carries\n`deny` on both `platform/data/` and `platform/metadata/` for\n`workloads/keycape/secrets-engine-openbao`; the ESO and operator reader\npolicies equal their files; mount `keycape-services/` is type jwt. Reading the\nrole was refused: `ops-mason-survey` did not cover `auth/keycape-services/role/*`.\nAdded to `policies/ops-mason-survey.hcl`; the founder reinstalls it (AGENTS.md\ncommand), then the role check runs.\n\n2026-10-10 15:45Z: founder reinstalled `ops-mason-survey`; the installed policy's\nsha256 equals the repo file's (`c845bc79\u2026`, receipt\n`~/.local/state/railiance/receipts/ops-mason-survey.sha256`). Role check runs\nunder the next grant.\n\n2026-10-10 (grant `claude-MASON-WP-0009-T05`, revoked): role\n`auth/keycape-services/role/secrets-engine-openbao` equals railiance-platform\n`openbao/auth/secrets-engine-jwt-role.json` on every field compared (jwt,\n`sub`, audience `secrets-engine-openbao`, subject `service:secrets-engine`,\nclaims principal_type/roles/scope/tenant, policy `secrets-engine-login-self`\nonly, 5m, 8 uses, no default policy). ops-mason's checks are complete. Pointer\nentry proposed to ops-warden as draft, non-resolvable (message `8ad8ed4e`).\nLeft owner-run: capability checks with live operator and ESO tokens and a\nnon-member refusal."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-mason/workplans/MASON-WP-0010-security-case-materialization.md",
|
|
"meta": {
|
|
"id": "MASON-WP-0010",
|
|
"type": "workplan",
|
|
"title": "Materialize SecurityCases from their type, with acceptance as the only gate",
|
|
"domain": "infotech",
|
|
"repo": "ops-mason",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "claude-code",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-08",
|
|
"updated": "2026-10-09",
|
|
"depends_on": [],
|
|
"related_repos": [
|
|
"net-kingdom",
|
|
"ops-warden",
|
|
"railiance-platform"
|
|
],
|
|
"state_hub_workstream_id": "eabf2c39-94bd-5a11-8f2e-76d7a95d1583"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "MASON-WP-0010-T01",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"NK-WP-0048-T03"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "3382ea7b-65ca-59a9-97ae-273455af44c2",
|
|
"body": "### T01 \u2014 Define the type's materialization section\n\nPropose the `materialization` part of the SecurityCaseType schema together with\nnet-kingdom: policy, role, KV path structure and catalog-entry templates over\ncase parameters, with naming rules. These must respect ops-mason's existing\n\"respect, extend or compact before adding\" review, so that a type cannot\ntemplate sprawl. Write it for the first type, `oidc-browser-relying-party`, from\nMASON-WP-0009 and the existing key-cape client custody paths.\n\n**Review (2026-10-08) of net-kingdom `security-case-types/oidc-browser-relying-party/type.yaml` 1.0.**\nThe structure (four items, all but the catalog entry conditional on\n`confidential`) is right. The names add three new families where existing ones\ncover the need, so they fail \"respect, extend or compact before adding\".\nRequested refinements, each from the live CCR-2026-0033 placement\n(`plans/keycape-secrets-engine-openbao-client-custody.md`):\n\n1. **Fix the path in the type.** `secret_ref` should not be case-settable; a\n free pattern under `platform/workloads/` lets every case pick its own layout.\n Derive it: `platform/workloads/keycape/{client_id}` (field `CLIENT_SECRET`),\n as for `secrets-engine-openbao`.\n2. **Reuse the policy family.** Existing readers are\n `workload-kv-read-keycape-<client>-<reader>`. Rename\n `keycape-client-{client_id}-read` to `workload-kv-read-keycape-{client_id}-eso`\n (KeyCape reads its client secret only through ESO), and\n `{consuming_service}-oidc-client-{client_id}-read` to\n `workload-kv-read-keycape-{client_id}-{consuming_service}`. Update\n verification `custody-allowed-to-consumer` and rollback to match.\n3. **Template the policy body, not just its name.** An `openbao_policy` item\n needs its rules (`read` on `platform/data/workloads/keycape/{client_id}`,\n nothing else: no metadata, list, parent or sibling), or the review cannot\n check invariant (ii) and a rendered plan is not buildable.\n4. **Add the missing ESO role.** `deliver-secret` needs a Kubernetes-auth role\n `external-secrets-keycape-{client_id}` (kind `openbao_role`, bound to the\n ESO service account, policy from item 2, 15m TTL, no default policy), as\n the reference placement has.\n5. **Catalog naming.** The one existing entry is `rapp-qonto-keycape-client`;\n prefer `{consuming_service}-keycape-client` over `oidc-client-{client_id}`.\n6. **Rollback order.** `mint-secret` \"destroy\" and `client-secret-path`\n \"remove\" act on the same KV path; collapse to one step (metadata delete\n after the ExternalSecret is gone) so rollback cannot fail on a missing path.\n\nWith 1-4 applied, the section is acceptable to ops-mason for NK-WP-0048-T05.\n\n2026-10-08: net-kingdom folded in all six (net-kingdom `074b3a0`, message\n`508e2a12`); its schema/validator now require a body on policy and role items.\nNK-WP-0048-T05 still waits on WARDEN-WP-0044-T01 and a founder answer.\n\n2026-10-09: the founder accepted memo r4; hub decision `e418263e` resolved and\nthe type is `acknowledged` (net-kingdom `0e86f95`). T02 is unblocked."
|
|
},
|
|
{
|
|
"id": "MASON-WP-0010-T02",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"MASON-WP-0010-T01",
|
|
"NK-WP-0048-T05"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "fd385537-7378-5539-8a6e-f45851296f42",
|
|
"body": "### T02 \u2014 Render a construction plan from a case\n\n`mason plan --case <case.yaml>` validates the case against its `implemented`\ntype, renders the construction plan from the type's templates, and runs the\nexisting consistency review against current OpenBao structure (read-only, no\nvalues). The output is the usual plan, marked `derived-from-type`, plus the\ncase-acceptance reference in place of a fresh executive summary.\n\nTests: render the reference case; refuse a case whose type is not\n`implemented`; refuse parameter values outside the type's validation; flag a\ncollision with existing structure.\n\n2026-10-09 done: `ops-mason plan --case <case.yaml> [--out F] [--no-live]`\n(`src/ops_mason/case_plan.py`). Validation and rendering are net-kingdom's own\n`security_case_validator.py` (imported, not copied), with provider declarations\nloaded through its composer. ops-mason adds the review against existing\nstructure: a read-only live survey (policy list, role lists, KV metadata,\nops-warden catalog ids) that fails loudly instead of returning an empty\nstructure, and flags each collision as a finding. Output is a construction\nplan with `derived_from_type` and `render_digest`, and section 5 is the case\nacceptance; status `reviewed` only when accepted and collision-free. Exit 0\nclean, 1 collisions, 2 refused. `tests/test_case_plan.py` (8, on a copy of the\ntype marked `implemented`); suite 167 passed. The live Forgejo case is refused\ntoday, correctly: the type is `acknowledged`, not yet `implemented`.\n\n2026-10-09: net-kingdom accepted the Forgejo case\n(`net-kingdom/security-cases/forgejo-netkingdom-oidc.yaml`, message `d1bbcb44`).\nAs the reference case it renders with `--allow-unimplemented`, mirroring the\nvalidator's flag: allowed only for an `acknowledged` type, marked\n`reference_case: true`; and `reviewed` now requires a live survey. Rendered\nlive into `plans/case-forgejo-netkingdom-oidc.md`: status `reviewed`, no\ncollision, digest `sha256:fb8b114d\u2026`."
|
|
},
|
|
{
|
|
"id": "MASON-WP-0010-T03",
|
|
"status": "progress",
|
|
"depends_on": [
|
|
"MASON-WP-0010-T02"
|
|
],
|
|
"blocked_on": "message-from:railiance-platform",
|
|
"blocking_reason": "Built 2026-10-09 (builds/case-forgejo-netkingdom-oidc). Acceptance waits on railiance-platform filing the CCR drafts and the founder applying them, plus mint-secret; then the Forgejo case is live.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "56cea6be-c613-586c-80cd-125340b374da",
|
|
"body": "### T03 \u2014 Build from an accepted case\n\n`mason build --case <case.yaml>` builds a rendered plan when the case's\nacceptance record is present, with no separate executive-summary approval. Its\naudit trail names the case, the type version and the acceptance. It proposes the\npointer-only ops-warden catalog entries the type defines, as today. Rollback\nremoves exactly what this case created.\n\nAcceptance: the Forgejo reference case (NK-WP-0048-T06) materializes through this\npath.\n\n2026-10-09: implemented. `ops-mason build --case <case> --plan <plan> [--out]\n[--allow-unimplemented]` (`src/ops_mason/case_build.py`) refuses unless the\ncase is accepted, the plan is `reviewed` and its render digest equals a fresh\nrender. It writes a bundle and never touches OpenBao: one workload-kv-read CCR\ndraft per policy (ESO policy + Kubernetes role, mirroring CCR-2026-0033; the\nconsumer policy `in_flight` with `openbao.auth` missing until the consumer owner\nbinds it), the policy HCL, an ops-warden catalog proposal, `rollback.yaml`\n(exactly what the case creates, reverse order) and a manifest with file hashes.\nEvery file names the case, type version, render digest and acceptance record;\nthe audit log gets a `case-build-prepared` record with the case acceptance as\napprover. The drafts are checked with railiance-platform's own\n`credential-change.py validate`. `tests/test_case_build.py` (6); suite 175\npassed. Forgejo bundle built into `builds/case-forgejo-netkingdom-oidc/`,\nplatform validation pass; handed to railiance-platform (message `2c409503`)."
|
|
},
|
|
{
|
|
"id": "MASON-WP-0010-T04",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"MASON-WP-0010-T03"
|
|
],
|
|
"blocking_reason": "After T03, and only once a type fits: secrets-engine-openbao is a service (JWT) client, which oidc-browser-relying-party does not cover.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "f6ad0d3c-8f47-5fdf-8115-6ca9d8a1fead",
|
|
"body": "### T04 \u2014 Adopt MASON-WP-0009 as a case\n\nOnce `oidc-browser-relying-party` (or the confidential service client type) is\nimplemented, express MASON-WP-0009's placement as a case of that type without\nchanging the live structure, and close the hand-built path.\n\n2026-10-10 (T03): railiance-platform filed the drafts as CCR-2026-0041 (ESO\nreader) and CCR-2026-0042 (consumer reader, in_flight until railiance-apps binds\nit), messages `83465dcd`/`be3a762d`; the founder applied CCR-2026-0041 at\n2026-10-09T18:09Z. Its review found a render defect: the CCRs declare\n`token_self_lifecycle: true` but the policies lacked the lookup-self/revoke-self\nstanzas, so the applier refused them. Fixed in `case_build.py` (test asserts\nthe three stanzas; output now equals the platform-generated policy apart from\ncomments) and in the committed bundle. Two follow-ups for the next render:\nnet-kingdom changed the type to `KEYCAPE_{client_id:env}_CLIENT_SECRET`\n(ops-warden `23ba584`), so the render digest will change; and a live re-render\nof a partly applied case will report its own objects as collisions. The KV\nvalue waits on mint-secret (RPF-WP-0054).\n\n2026-10-10 (T03 follow-up): `plan --case` now recognises objects listed in the\ncase's own committed bundle (`builds/case-<id>/rollback.yaml`, same case id) as\n\"already present from this case's own build\", not collisions; anything else\nexisting still collides (2 tests, suite 177 passed). The committed Forgejo plan\nis stale: net-kingdom's `{client_id:env}` change moves the render digest from\n`fb8b114d\u2026` to `5e97931e\u2026`. Re-render it live under the next survey grant.\n\n2026-10-10: Forgejo plan re-rendered live: `reviewed`, no collision, digest\n`af1f4f81\u2026`; policy `workload-kv-read-keycape-forgejo-eso` shown as already\npresent from this case's own bundle. The ESO role did not appear as present;\ncheck on the next grant.\n\n2026-10-10: checked. `auth/kubernetes/role/external-secrets-keycape-forgejo`\nexists as applied (external-secrets/external-secrets, audience openbao, 15m,\npolicy `workload-kv-read-keycape-forgejo-eso`, no default policy). Why the plan's\n\"already present\" list omitted it is not yet confirmed (the survey should list\n`auth/kubernetes/role`); reproduce under the next grant. The collision review\nis unaffected: it never flagged the role.\n\n2026-10-10: type 1.1 (net-kingdom `e2174ce`, message `af66538c`) adds the\nconsumer-enforces-groups verification and tightens redirect URIs; the case is\nre-pinned to @1.1. The live re-render above was already 1.1. Bundle rebuilt\nfrom it (`builds/case-forgejo-netkingdom-oidc/`, platform validation pass);\nthe ESO policy is unchanged against the applied CCR-2026-0041, so 1.1 changes\nno OpenBao object."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": "?? uv.lock\n"
|
|
},
|
|
"ops-warden": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/ops-warden/workplans/WARDEN-WP-0027-credential-governance-lockdown.md",
|
|
"meta": {
|
|
"id": "WARDEN-WP-0027",
|
|
"type": "workplan",
|
|
"title": "Tamper-resistant credential governance + mass rotation/lockdown (Strand B)",
|
|
"domain": "infotech",
|
|
"repo": "ops-warden",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "custodian",
|
|
"planning_priority": "medium",
|
|
"planning_order": 27,
|
|
"created": "2026-07-16",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "21528e8d-a049-523d-9ae1-da7a27cb8bbf"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "WARDEN-WP-0027-T01",
|
|
"status": "cancel",
|
|
"priority": "high",
|
|
"state_hub_task_id": "b5691939-9d84-5115-9618-0f8839010d14",
|
|
"body": "Turn Strand A's per-lane `rotation:` guidance (WP-0026 T06) into an executable\ndriver: `warden rotate <id>` (single lane) and `warden rotate --tainted` (all lanes\nmarked EXPOSED per WP-0026 T05). Each step runs the owner-native command\n(provider re-mint, `bao kv put`, re-encrypt+reupload for re-establish lanes) as the\ncaller, verifies via capabilities (never reads the value), and clears the\n`exposed_at` taint on success. Dry-run first; idempotent; per-lane failure isolates.\n\n**Done when:** a tainted set of lanes can be rotated/re-established with one command,\neach verified capabilities-safe, taint cleared only on success.\n\n**Depends on:** WP-0026 T05 (taint convention), T06 (rotation registry).\n\n## Task: Graded lockdown / break-glass with explicit trust-root"
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0027-T02",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa",
|
|
"blocking_reason": "Trust-root design is a founder decision: who holds unseal shares and recovery keys, quorum, break-glass invocation; executable seal steps are attended.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "cae498ee-6307-5d32-9f1b-a471cfcc2536",
|
|
"body": "Design and document a graded lockdown: (a) soft \u2014 deny agent roles read on all\nhigh-risk lanes; (b) hard \u2014 seal + re-key with a pre-designed trust-root and quorum.\nDefine the trust-root (who holds unseal shares, recovery keys), the break-glass\ninvocation, and the re-entry path. **Design + runbook first**; any executable seal\nstep is opt-in and attended.\n\n**Done when:** a documented, rehearsed break-glass path exists with a named\ntrust-root and quorum, and soft-lockdown is executable via capabilities-based\npolicy toggles.\n\n**Parked input \u2014 the warden-sign AppRole (2026-08-11).** secrets-engine holds a\nvalidated dry-run for a `warden-sign` AppRole (policy + role, `update` on\n`ssh/sign/{agt,adm,atm}-role` only). It was **parked** rather than withdrawn\nspecifically because it is an input to this task: today the credential broker is the\nonly *autonomous* path to a signing token, so if its issuer lapses, recovery is a\nfounder OIDC act. Whether a second autonomous path should exist \u2014 and whether it is\nthe AppRole or something this trust-root design supersedes \u2014 is a break-glass\nquestion, not a routing one. Resolve it here. Context and the counter-argument\n(AppRole is narrower in capability than placing the broker's issuer token on a remote\nhost) are in `workplans/ADHOC-2026-08-11.md` T03 (ad-hoc **finished** 2026-08-15;\nquestion lives here now); secrets-engine was told to stop holding apply\nreadiness until this task or the ops-bridge cutover fires (msg `863c7b57`).\n\n**Rebaselined 2026-08-22.** The July description predates the authoritative\nOpenBao migration. The current barrier is a rotated **2-of-3**, not the\naspirational 3-of-5 value still present in ops-warden's legacy posture\ndescriptor. `RMASTER-WP-0020` records two attended restart/unseal cycles on\n2026-08-03 with shares supplied through hidden prompts, matching inventory,\naudit continuity, exact-path read, and sibling denial. That is valid rehearsal\nevidence for re-entry, but it is not misreported as a current production\nemergency-seal drill.\n\nThe soft half is also already live: `RAILIANCE-WP-0022` reports total concrete\nhigh-risk path coverage and a dedicated coding-agent AppRole proving deny-wins\nwithout reading a secret value. ops-warden consumes that owner control through\n`scripts/check_agent_read_boundary.py`; it does not take ownership of the live\nOpenBao policy.\n\nThe consumer contract and remaining acceptance gate are now documented in\n`docs/credential-governance-break-glass.md`. One attended production emergency\nseal/unseal drill remains. It must use railiance-platform's evidence template\nand validator, have snapshot/quorum/console/driver/abort receipts before the\nseal hold point, and be executed by the platform owner\u2014not by a coding agent.\n\n**Parked AppRole disposition:** do not unpark the standalone `warden-sign`\nAppRole for T02 break-glass. The normal broker remains autonomous; an issuer\nfailure deliberately crosses into attended OIDC and, below that, the 2-of-3\nplatform trust-root. A standing AppRole placed outside the broker would weaken\nthat boundary and still would not recover a sealed OpenBao. A separately\napproved ops-bridge unattended-signing design may re-evaluate the narrow\nAppRole under its own workplan; that is service access, not recovery authority.\n\n**Read-only readiness 2026-08-22.** The owner `node-reboot` preflight passed\nevery automated check without observing a secret value: node/k3s, platform-pg\nand continuous archiving, a 16.37-hour successful backup, initialized/unsealed\nOpenBao with `shares=3` and `threshold=2`, ESO stores/projections, and the\nreviewed audit-core digest were healthy. `ready_for_live_execution` correctly\nremained false because no approved window, current encrypted off-host snapshot\nreceipt, provider-console attestation, quorum attestation, owner-ack flag, or\nnamed abort operator was supplied.\n\nThat preflight also exposed a Warden safety defect: the ceremony request matched\nthe generic `openbao-api-key` template and proposed paste-once provisioning.\n`openbao-shamir-recovery-ceremony` now distinguishes the owner-operated approval\nceremony from secret retrieval. It is a non-value-bearing pointer and can never\noffer `--fetch`, `--exec`, `--out`, `--wrap`, or paste-once share transport.\n\n**Scenario established 2026-08-22.** The operator delegated preparation to the\nagent and reserved their involvement for the final GO/NO-GO. The bounded,\nnon-secret scenario is\n`docs/evidence/WARDEN-WP-0027-T02-drill-scenario-2026-08-22.md`: ops-warden\ncoordinates and enforces the hold point; railiance-platform is the proposed\nOpenBao driver; railiance-infra is the proposed independent console/abort owner;\nand railiance-master is asked only for a metadata-only 2-of-3 availability\nattestation. All three owner receipts and a green fully parameterized preflight\nare required before the final operator question.\n\nThe railiance-infra role is scoped by the authoritative review contract\n`WARDEN-WP-0027-T02-DRILL-20260822-01-INFRA` in\n`interfaces/reviews/WARDEN-WP-0027-T02-DRILL-20260822-01-railiance-infra.json`.\nIt binds the exact scenario artifact and expiry, requires explicit independent\nprovider-console and distinct-abort attestations, permits metadata-only evidence,\nand states `authorizes_execution: false`.\n\n**Preparation approved 2026-08-22.** Decision\n`9da57559-712a-4521-b46e-a4c69729f9d2` authorizes preparation only and narrows\nthe possible live scope to one intentional OpenBao seal followed by the existing\n2-of-3 unseal ceremony. It excludes a host reboot, re-key, restore, policy\nchange, PVC mutation, credential disclosure, and general workload restart.\nRailiance-infra satisfied its direct contract with receipt\n`01a02b4b-7295-7836-b288-f29407008524`. The revisioned, non-authorizing gate\nmatrix is in\n`docs/evidence/WARDEN-WP-0027-T02-drill-preparation-checklist-2026-08-22.md`;\nplatform snapshot/driver and master quorum contracts remain required before the\nfully parameterized read-only preflight.\n\n**Live attempt terminal NO-GO 2026-08-23.** All owner receipts and the final\nread-only preflight became green, and the operator opened the exact bounded\nwindow with decision `449a697a-5303-4582-aa9e-b0bc8b35ab2d`. The platform\ndriver stopped before seal when attended OIDC succeeded but the read-only agent\nhome prevented token-helper persistence and the underlying client emitted the\nshort-lived credential into captured output despite `-no-print`. The credential\nwas immediately self-revoked. Independent metadata confirmed OpenBao remained\ninitialized and unsealed with zero unseal progress; no seal, unseal, reboot,\nrestore, policy, PVC, or workload mutation occurred. NO-GO decision\n`85724c0c-e70f-4e2f-a8c6-a9cb1ea6331b` supersedes and consumes the GO; the\nscenario and its receipts cannot be reused.\n\nThe direct remediation interface is `RAILIANCE-WP-0026-T01`. Ops-warden commit\n`0fae0904ce8d8694338dd53a8a79abec5fec788d` replaces the persistent login-only\nhandoff with a contained login-plus-reviewed-command envelope. It proves a\nprivate writable helper before OIDC, captures login/child/revocation stdout and\nstderr, fails closed on any output or persistence defect, self-revokes, and\nremoves the helper. No live OIDC was used for verification. The value-safe\nowner receipt is\n`docs/evidence/RAILIANCE-WP-0026-T01-ops-warden-receipt.json`; a future drill\nrequires owner acceptance, fresh receipts, a new scenario id, and a new human\ndecision.\n\n**Containment review status 2026-08-23.** `railiance-infra` independently\naccepted the exact implementation revision at its commit `186b030` and State\nHub message `7b2846dd-4b7c-4933-b61f-921e8ccf9ff2`, after rerunning the 42\nfocused tests and lint. Direct platform review request\n`9a5f8973-0e74-4df2-8089-5a5bdc42295b` now carries the exact revision, receipt,\ntest results, and infra acceptance. T02 remains `progress` until\n`railiance-platform` accepts or requests changes. No human GO is relevant while\nthat owner gate is open; acceptance will permit preparation of a new scenario,\nnot execution or reuse of the terminal one.\n\n**Owner gate CLOSED \u2014 accepted 2026-08-23, found 2026-08-28.**\n`railiance-platform` accepted the exact revision `0fae0904`. Recorded in their\n`RPF-WP-0017-attended-login-output-containment.md` (`status: finished`), which\nalso records railiance-infra's independent approval at `186b030` and marks all\nfive acceptance criteria met. The receipt digest was verified here rather than\ntaken on trust: `docs/evidence/RAILIANCE-WP-0026-T01-ops-warden-receipt.json` at\nops-warden `bc1966da` hashes to\n`d2ba444ed16989590325697e69d25283dc75a9432c29a72e627e80bf9fd987e4`, matching\ntheir record exactly.\n\nNote the identifier: the remediation interface recorded above as\n`RAILIANCE-WP-0026-T01` is `RPF-WP-0017-T01` in the owner's repo. Searching for\nthe cited id finds an unrelated workplan, which is part of why this sat unnoticed.\n\n**Their acceptance is source acceptance only and authorizes no live OIDC or\ndrill** \u2014 their words, and the boundary holds. So T02's state changes but its\n`Done when` does not: what was blocked was *preparing a new scenario*, and that\nis now permitted. The terminal NO-GO scenario and its receipts remain unusable.\n\n**Third instance of the same failure this session.** The acceptance existed for\nfive days; no message reached ops-warden. Identically, `key-cape` accepted the\nWP-0033-T04 question on 2026-08-23 with no message, and nine unread messages\nwere sitting on already-superseded threads. The `verified:` field added by\nWP-0033-T05 was built for exactly this and it works \u2014 what does not work is\nwaiting for a counterparty to tell you. Re-checking a blocker means reading the\nowner's repository.\n\n**Remaining to close T02:** one attended production emergency seal/unseal drill,\nrequiring a new scenario id, fresh owner receipts from platform/infra/master, a\nfully parameterized green preflight, and a new human GO. It is executed by the\nplatform owner, never by a coding agent. That is an operator decision, not an\nagent one, so T02 stays `progress` and the decision is surfaced rather than taken.\n\n2026-10-03: human gate routed to hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: Trust root and secret custody: unseal/recovery holders, break-glass, and the deferred rotation of exposed material) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Task: Tamper-evident policy governance + reconcile"
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0027-T03",
|
|
"status": "cancel",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "7dbedcdc-dd5a-551c-bff1-0702fea0a9cf",
|
|
"body": "Policy-as-code for OpenBao policies/roles with tamper-evidence: a signed/hashed\nmanifest of the intended policy set, drift **detection** against live OpenBao, and a\nreconcile-to-known-good-commit path. (Drift detection may land independently even if\nfull reconcile stays gated.) Coordinate ownership with railiance-platform (OpenBao\ndeployment) \u2014 ops-warden contributes the ops-access policy surface, not the cluster.\n\n**Done when:** live OpenBao policy state is diffable against a signed known-good\nmanifest, and an attended reconcile can restore it.\n\n**Cross-repo:** railiance-platform (OpenBao cluster + policy custody).\n\n## References\n\n- `WARDEN-WP-0026` \u2014 Strand A (disclosure hygiene, advisory rotation) \u2014 prerequisite\n- `.claude/rules/credential-routing.md` \u2014 ops-warden custodies no secret values\n- `railiance-platform` \u2014 OpenBao cluster, policy custody, credential broker\n- `wiki/AccessRouting.md` \u2014 issue vs route vs assist boundary\n- `workplans/ADHOC-2026-08-11.md` T03 \u2014 parked warden-sign AppRole (ad-hoc finished\n 2026-08-15); T02 resolves it as unsuitable for break-glass, while a separately\n approved ops-bridge unattended-signing design may still re-evaluate it\n cert_command cutover\n- `secrets-engine` `SECRETS-WP-0004` \u2014 the parked AppRole apply/handoff\n\n### 2026-09-28 loose-end review\n\nT02 now waits and the workplan is blocked. Source containment acceptance is\nalready complete in railiance-platform's archived RPF-WP-0017; it is not a live\ndrill receipt. The terminal August scenario remains consumed. Completion still\nrequires a fresh platform-driven attended emergency seal/unseal scenario, fresh\nplatform/infra/master receipts and a new founder GO. The cancelled T01/T03 stay\ncancelled. No ceremony, rotation or production mutation was performed."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-warden/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md",
|
|
"meta": {
|
|
"id": "WARDEN-WP-0034",
|
|
"type": "workplan",
|
|
"title": "Layer model v0.7 conformance \u2014 state the deadline, bind the agent boundary, steward the estate's newest rule",
|
|
"domain": "infotech",
|
|
"repo": "ops-warden",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"depends_on": [
|
|
"WARDEN-WP-0030"
|
|
],
|
|
"owner": "ops-warden",
|
|
"topic_slug": "netkingdom",
|
|
"planning_priority": "P1",
|
|
"depends_on_workplans": [
|
|
"WARDEN-WP-0030"
|
|
],
|
|
"created": "2026-08-29",
|
|
"updated": "2026-09-28",
|
|
"state_hub_workstream_id": "ae3ff76f-883d-5e2f-b6aa-144d61e8fdef"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "WARDEN-WP-0034-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8b3bdb9f-d2c2-5b3e-89e2-417bf3e37484",
|
|
"body": "**State the revocation visibility deadline (\u00a79.7.2, a MUST).**\n\nops-warden states none, and the honest value is the certificate TTL: **up to 48 hours**.\nA cert issued under an allow remains valid for its full TTL even if the authorizing\ndecision is revoked the next minute. There is no CRL, no KRL distribution, and host-side\n`auth_principals` belongs to `railiance-infra`.\n\nAdd the deadline to `pep-stance.yaml` as what it is \u2014 `adm` 48h / `agt` 24h / `atm` 8h \u2014\nwith the mechanism named (TTL expiry, no revocation channel) rather than implied. Assert\nit against the shipped `ActorType` TTL policy by test, the same way the stance map is\nasserted equal to shipped behaviour: a stated deadline free to drift from the code has\nthe same defect as a stated stance free to drift.\n\n**Done when:** the deadline is published, test-bound to the TTL policy, and the absence\nof a revocation channel is stated rather than left to inference.\n\n**Not in scope:** shortening it. Whether 48h is acceptable is a joint question with\n`railiance-infra` (KRL distribution) and is T05's to raise, not this task's to decide.\n\nCompleted 2026-09-04. `pep-stance.yaml` now publishes TTL expiry as the only\nrevocation mechanism, explicitly records that no CRL/KRL channel exists, and\nstates `adm=48h`, `agt=24h`, and `atm=8h`. The conformance test derives the\nexpected map from `ActorType`/`MAX_TTL_HOURS`, so declaration and issuance\npolicy cannot drift independently. The layer and stance declarations now name\nthe accepted v0.7 standard."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0034-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "3318ee1a-b5d9-5d39-baf7-9c42a8bc7b55",
|
|
"body": "**Bind the agent read-boundary to an issued identity (\u00a73.4 rule 1).**\n\n`ADR-0004`'s boundary triggers on `WARDEN_AGENT_ID` \u2014 a variable the agent sets about\nitself. An agent that omits it is not recognised as one. \u00a73.4 rule 1 now requires\nauthority to be *issued* per task and attributable to the principal acted for.\n\nThe identity exists as of `KEY-WP-0009-T03`: `codex-railiance-platform`, subject\n`service:codex:railiance-platform`, role `coding-agent`, 15-minute lifetime, with\n`railiance-platform` enforcing the OpenBao-side policy.\n\nKey the boundary on the issued identity where one is present; keep `WARDEN_AGENT_ID` as\na fallback that fails **toward** the boundary, never away from it. State plainly in the\nADR trail which half is enforced and which is advisory: the OpenBao-side deny is real,\nthe ops-warden-side refusal is a courtesy that a determined caller can decline.\n\n**Done when:** an agent presenting the issued identity is recognised without setting\n`WARDEN_AGENT_ID`, the fallback still refuses on `risk: high` lanes, and the\nenforced/advisory split is written down.\n\n**Watch:** do not turn this into ops-warden validating a token \u2014 that is verifying an\nidentity claim, adjacent to deciding, and `ADR-0002`/\u00a76 both point away from it. Read\nthe identity; do not adjudicate it.\n\nCompleted 2026-09-04. The advisory CLI guard now prefers the exact issued\nKeyCape subject `service:codex:railiance-platform` from\n`WARDEN_POLICY_SUBJECT`, then falls back to `WARDEN_AGENT_ID`. Tests prove the\nissued subject triggers exit 7 without the legacy marker, the fallback remains,\nand an operator subject does not manufacture an agent identity. ADR-0004\nrevision 2 records the enforced/advisory split: Warden reads the marker and\ndoes not validate a token; OpenBao's `agent-high-risk-boundary` is the real\nenforcement."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0034-T03",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "a891b32c-b0a7-59f6-a5cd-977be65c09ca",
|
|
"body": "**Derive an emission cadence, or defer it with a reason (\u00a79.6).**\n\nops-warden's trail is attributive, so cadence is a SHOULD rather than v0.7's MUST for\nload-bearing sources. It has been silent through two reviews, which is the one outcome\nthat is not defensible.\n\nDerive a baseline from the existing `audit.jsonl` and signatures log. If the signal is\ntoo bursty to support a threshold \u2014 plausible, since volume is operator-driven \u2014 record\nthat as the finding with the distribution that shows it, and declare the deferral in\n`pep-stance.yaml`. A measured \"no useful baseline\" is a result; silence is not.\n\n**Done when:** either a declared cadence with its derivation, or a declared deferral\ncarrying the data that justifies it.\n\nCompleted 2026-09-04 with an explicit measured deferral. The signatures log\ncontains three issuances across the 79-day observation window, on only two\nactive days: one on 2026-06-17 and two within 40 minutes on 2026-08-22. The\nunified audit carries the latter two events. `pep-stance.yaml` records the\ncounts, dates, attributive classification, and reason that this sparse,\noperator-driven burst cannot support a meaningful rate threshold."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0034-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "94e73daa-f74d-51fd-8639-68896a4066ee",
|
|
"body": "**Answer the question the companion sends the estate here to ask.**\n\n> *\"For how to get something done \u2014 which lane, which credential, which route \u2014 ask\n> `ops-warden`.\"*\n\nToday the repo answers credential questions and no others. `warden route` and\n`warden plan` cover lanes, owners and acts. Nothing answers *\"which layer am I\"*, *\"how\ndo I declare\"*, *\"I am PEP-shaped, what do I owe\"* \u2014 and eight of fifteen catalogued\nrepositories have yet to declare.\n\nProvide the path, not the doctrine (that boundary is `ADR-0010`'s and does not move):\na routing entry and a short playbook that carry a reader from the companion to the files\nto copy \u2014 `layer.yaml`, `pep-stance.yaml`, `check_layer_conformance.py`,\n`test_layer_conformance.py` \u2014 and the check to run. The standard already names these in\n\u00a711 and \u00a76.4; what is missing is the route to them.\n\n**Done when:** `warden route find \"how do I declare my layer\"` resolves, and the\nplaybook is reachable from the catalog. **Not** a restatement of the companion \u2014 a\npointer layer, per `ADR-0001`.\n\nCompleted 2026-09-04. Catalog entry `netkingdom-layer-declaration` resolves the\nexact query to `wiki/playbooks/netkingdom-layer-declaration.md`. The short\nplaybook points at the accepted companion/statute, the four reference artifacts\nand checks, and the gate-house review path while explicitly leaving doctrine\nwith gate-house and declaration truth with each repository."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0034-T05",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:ops-mason",
|
|
"blocking_reason": "Two items to route, not absorb: ops-mason has published no stance map; the second is another repository's to own.",
|
|
"priority": "low",
|
|
"state_hub_task_id": "7d1b3c82-9b96-5087-a53a-496212909029",
|
|
"body": "**Two things to raise rather than absorb.**\n\nBoth are other repositories' to own; ops-warden's obligation is to route them, not to\nfix them (`ADR-0003`, `ADR-0005`).\n\n1. **`ops-mason` has published no stance map.** \u00a713.1's register has one row and the\n standard says that is itself the finding. `ops-mason` is catalogued PEP-shaped in\n the same paragraph and is ops-warden's peer lane owner. Offer the reference form;\n do not write their map.\n2. **The 48-hour replay window from T01.** Once stated, raise with `railiance-infra`\n whether KRL distribution is worth building, and with `access-engine` whether a\n decision lifetime shorter than the cert TTL is meaningful when nothing can recall\n the cert. State the question; let the owners answer.\n\n**Done when:** both are routed with reasoning, and the answers recorded either way \u2014\nincluding a refusal, which is an equally good answer.\n\nRaised 2026-09-04 and waiting for answers. Ops-mason received the stance-map\nreference and classification question (message `6ddd6cc7`). Railiance-infra\nreceived the KRL-versus-TTL question (message `3bfa306e`). Flex-auth, as the\ncurrent access-engine implementation, received the decision-lifetime semantics\nquestion (message `02c99a74`). No implementation or policy decision was assigned\nto another owner by these messages.\n\n**One of three answered, 2026-09-09.** `flex-auth` answered the decision-lifetime\nquestion as `FLEX-DEC-2026-004` (flex-auth commit `6a6464f`), and answered it\nrather than declining it: a decision lifetime shorter than the certificate TTL is\nmeaningful, but only as authority to **issue**, never as authority to **use** an\nalready-issued certificate. The action is `sign` and it completes at issuance, so\nthe decision is consumed once the certificate exists and no field in the decision\nrecord reaches the artifact. 15m against a 48h `adm` certificate was never an\ninconsistency to reconcile \u2014 the question mistook a decision lifetime for a\ncredential lifetime.\n\nTwo obligations land on this side and are accepted: no replay of an allow past\n`expires_at`, and a fresh Check per sign. The second is where the value is, and it\nis real rather than nominal because claims are not cached PDP-side (deadline 0 for\nthe claim class), so a revoked principal stops obtaining *new* certificates\nimmediately.\n\n`pep-stance.yaml` \u00a79.7.2 is unchanged and stays here: flex-auth explicitly declined\nto move the residue to their side, on the ground that a PDP recalling an issued\ncredential would be \"the same shape of lie as fail-open\". Declining it was the\nright call even though absorbing it would have made their record look tidier.\n\nThe TTL lever they named \u2014 capping requested TTL per actor class or zone, already a\npolicy input since `ttl_out_of_bounds` is denied before OpenBao is reached \u2014 is\nnoted and deliberately not requested. Shortening `adm` from 48h has an operator\ncost, and issuance on this lane is too sparse (3 signature records across 79 days,\n`pep-stance.yaml` `emission_cadence`) to price it from intuition.\n\nT05 stays `wait` on the remaining two: `ops-mason` (no stance map published) and\n`railiance-infra` (KRL distribution versus TTL expiry). Neither has replied.\n\n## Await gate-house's \u00a711 precedence and case-sensitivity ruling"
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0034-T06",
|
|
"status": "done",
|
|
"priority": "low",
|
|
"state_hub_task_id": "b3b573df-2d2d-5a2c-9662-a13e435be57b",
|
|
"body": "ops-warden declares `layer: Staff` in `INTENT.md` frontmatter and `layer: staff`\nin `layer.yaml`. \u00a711 permits both forms and is silent on which governs when both\nexist and disagree, so two conformance runs over this repository can disagree\nwhile both follow the standard. Nine of nine repositories carrying both forms do\nthe same thing (flex-auth `tools/survey_layer_declarations.go`, receipt\n`docs/evidence/2026-09-21-layer-declaration-survey.json`).\n\n**RULED 2026-09-21, APPLIED 2026-09-21.** `GH-DEC-2026-017`\n(`gate-house@def0af2`, amendments A9-A13) answers both questions, and the answer\nto the second dissolves the first's consequence:\n\n- **`INTENT.md` governs**; `layer.yaml` is a derived artifact that must be marked\n derived, must name `INTENT.md` as its source, and must agree with it.\n- **The \u00a73 vocabulary is case-insensitive**, closed, and has four tokens\n (`Taxonomy`, `Tooling`, `Engine`, `Staff`). A conformance run MUST ASCII-fold\n case before comparing, and **no repository was asked to re-spell anything**.\n `Staff` and `staff` are one value.\n- **A declaration MUST NOT carry a standard version** \u2014 and that field is the\n *reference form's*, not this repository's habit, so ops-warden was asked to\n remove it here rather than each of seven adopters deciding.\n\nVerified before editing against gate-house's own committed files rather than the\ninbox message: the decision at `gate-house@def0af2`, amendments A9-A13 in\n`docs/amendments/v0.8-section-11-declaration-amendments.md`, and \u00a73/\u00a74/\u00a711 of\n`net-kingdom/canon/standards/security-layer-model_v0.8.md`.\n\n**What was applied.** `standard_version` removed from `layer.yaml` **and** from\n`INTENT.md` frontmatter (the ruling's subject is the declaration, and `INTENT.md`\nis the declaration), with the version-pinned `standard:` path de-versioned for the\nsame reason; `derived: true` / `derived_from: INTENT.md` added; **no layer value\nchanged**; `scripts/check_layer_conformance.py` rewritten to read `INTENT.md` as\ngoverning, fold case, validate the closed four-token vocabulary, require the\nderived marking, and reject a returning `standard_version` \u2014 it previously\n*required* that field and so would have rejected the conforming declaration this\nruling produces; `tests/test_layer_conformance.py` asserts the **fold** rather\nthan equality, because an equality assertion would perform the re-spelling the\nruling declined to order. `pep-stance.yaml` untouched: a stance map is not a layer\ndeclaration, and the schema beyond the derived marking and the version is\nexplicitly not ruled.\n\n**Evidence.** `python3 scripts/check_layer_conformance.py --report` exits 0 and\nprints the governing form and the derived one separately; `pytest\ntests/test_layer_conformance.py` green; full suite and `ruff` green. Reasoning\nand the adopter change set: `docs/layer-declaration-precedence.md` and\n`wiki/playbooks/netkingdom-layer-declaration.md`.\n\n**Left open, and not decided here.** Where the removed version now lives. A12\nsays version-scoped state belongs in the derived conformance record, which\n\"already MUST\" carry the version it was derived at; ops-warden has a re-runnable\nchecker that emits nothing durable, not an emitted record. Whether \u00a711 expects an\nemitted artifact or a re-runnable check discharges it is asked of gate-house in\nmessage `4220413a` and unanswered. Nothing applied above depends on the answer.\n**Closed 2026-09-21 by `GH-DEC-2026-020` \u00a74 (gate-house@104f3fc):** \u00a75 was wrong\nthat the record exists; a re-runnable checker is sufficient if every run prints\nthe version it checks against and its scope. Applied: the checker now prints\n`VALIDATED_AGAINST` and `SCOPE` on every run and enforces A12 r2 by content, not\nkey name (versioned `standard:` path, `companion_version`); `pep-stance.yaml`\nuntouched per \u00a73; the playbook carries the adopter change set.\n\n**Ruled the same day, and still `wait` \u2014 deliberately.** `GH-DEC-2026-017`\n(message `3715e247`) landed hours later: `INTENT.md` governs, the sidecar is a\nderived artifact that must be marked as such, \u00a73's vocabulary is case-insensitive\nso **nobody re-spells anything**, and `standard_version` must come out of the\ndeclaration. Two asks land on ops-warden specifically because `layer.yaml` is the\nform seven repositories copied.\n\nThis task stays `wait` rather than flipping to `progress`, because applying it\nedits this repository's security-layer declaration \u2014 and the estate's reference\nshape \u2014 on the strength of an instruction delivered in an inbox message. The\nsession that applies it should be mandated to, and should verify the decision at\n`gate-house@def0af2` and amendments A9\u2013A13 in the repository rather than from the\nmessage text. The exact change set and its four conditions are written down in\n`docs/layer-declaration-precedence.md`; the casing half of the original \"done\nwhen\" above is moot rather than outstanding, since the ruling folds case.\n\nRaised by flex-auth's corrected B1 (message `719b3e9e`, 2026-09-21), which\nwithdrew an earlier claim that the estate disagreed *across* repositories. The\nwithdrawal matters to this task: the original finding would have had ops-warden\nchanging a file to match an estate consensus that did not exist.\n\n## Related\n\nReview 2026-09-05: reviewed the pending implementation and fixed the identity\nhelper so an explicitly empty environment does not inherit the process identity.\nRegression coverage also proves an operator subject cannot override the legacy\nagent marker. Refreshed the generated high-risk path artifact after the catalog\nchanges. T05 remains waiting: no corresponding reply was present in the inbox,\nand the checked owner workplans contained no resolution of these questions.\nValidation: 415 unit tests and four SSH integration tests pass; Ruff, the\nlayer-conformance script, and the declaration-route CLI smoke check pass.\n\n- `history/2026-08-29-v07-scope-intent-assessment.md` \u2014 the gap analysis behind this plan\n- `history/2026-08-29-layer-model-v04-review.md`, `-v06-review.md` \u2014 the two prior reviews\n- `security-layer-model_v0.7.md` \u00a73.4, \u00a76.4, \u00a79.6, \u00a79.7, \u00a711, \u00a713.1\n- `net-kingdom/SECURITY-COMPANION.md` v0.2\n- `ADR-0002`, `ADR-0003`, `ADR-0004`, `ADR-0005`, `ADR-0009`, `ADR-0010`\n\n### 2026-09-28 loose-end review\n\nT05 remains wait; the workplan is blocked on the two outstanding owner answers.\nThe local ops-mason checkout still has no published stance map, and the available\nrailiance-infra workplans/docs contain no KRL-versus-TTL acceptance or refusal.\nThe flex-auth decision-lifetime answer remains accepted. Warden's declaration,\nTTL-bound tests and fresh-check behavior are complete; inventing an owner answer\nwould not satisfy T05. No certificate lifetime or revocation policy was changed."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-warden/workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md",
|
|
"meta": {
|
|
"id": "WARDEN-WP-0037",
|
|
"type": "workplan",
|
|
"title": "Repoint the whynot-design npm lane to Forgejo",
|
|
"domain": "infotech",
|
|
"repo": "ops-warden",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"owner": "codex",
|
|
"topic_slug": "whynot-design-forgejo-npm-lane",
|
|
"created": "2026-09-04",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "42a097db-1c24-558e-a724-030bb2b4443e"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "WARDEN-WP-0037-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "afc4d325-1c6d-5c25-aaf7-2118aa8f86c6",
|
|
"body": "Use only the governed execution transport to test the existing publish identity\nagainst the canonical Forgejo npm endpoint. Do not print or persist the token.\n\n2026-09-04: `warden plan` classified the exact verification as autonomous and\nselected this lane. A contained login using the documented\n`whynot-design-workload-kv-read` role proved `read` on the exact OpenBao data\npath, and the governed child proved the secret is present. A real 0.4.2 publish\nthrough that credential then failed. No value was printed or persisted and each\ncontained session self-revoked. The lane therefore needs token rotation, not an\nOpenBao policy repair.\n\n## Repoint the catalog and playbook"
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0037-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "7ceb2f74-496c-54e8-bf5a-3c49f994ff23",
|
|
"body": "Replace the retired Gitea endpoint and discovery language with Forgejo while\npreserving the established OpenBao path, field, and least-privilege boundary.\nThis delivers the npm facet of routed intake\n`01a06e07-f2f9-7586-9745-b359eb0025b6`; its inter-hub SSH facet remains separate.\n\nCompleted 2026-09-04. The catalog title, discovery keywords, rotation guidance,\nand worker playbook now name the canonical Forgejo registry at\n`https://forgejo.coulomb.social/api/packages/coulomb/npm/`. The OpenBao path,\nfield, owner, native-exec pointer, and high-risk boundary are unchanged. A\nregression assertion prevents the retired Gitea discovery term and guidance\nfrom returning.\n\n## Prove routing and publication"
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0037-T03",
|
|
"status": "wait",
|
|
"priority": "high",
|
|
"needs_human": true,
|
|
"decision_id": "1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa",
|
|
"depends_on": [
|
|
"SECRETS-WP-0006-T06"
|
|
],
|
|
"blocking_reason": "Founder HOLD 2026-09-21: no rotation until SECRETS-WP-0006-T06 moves the publish lane off the legacy whynot-design npm path; then rotate and prove a fresh publish.",
|
|
"intervention_note": "HOLD (founder, 2026-09-21): do not rotate yet. secrets-engine exec reads the ungoverned legacy path secret/coulomb/whynot-design/npm/publish (field npm_token); this runbook writes the governed path platform/workloads/coulomb/whynot-design/npm-publish (NPM_AUTH_TOKEN). A rotation now would not reach the live publish path. Resume after SECRETS-WP-0006-T06 moves the lane. Then: rotate the dedicated Forgejo package token, and prove a fresh publish and exact npm view through this lane.",
|
|
"state_hub_task_id": "a8b1b855-ab34-5835-b9fd-5f48bc0b6817",
|
|
"body": "Pass catalog and routing tests, verify the checkout route, and record the exact\nForgejo package release proven through the lane.\n\n2026-09-04: repo-local verification is complete: the checkout route ranks\n`whynot-design-npm-publish` first for a Forgejo npm publish need, reports the\ncanonical Forgejo title and verification command, all focused\nrouting/access/proxy tests pass (`145 passed`).\n\nThe sibling repo's `@whynot/design@0.4.2` release (105 files; IR\n`designVersion` 0.4.2; five visual tests pass) was published through the\nplan-authorized `forgejo-admin-api-token` one-time recovery lane. An\nauthenticated exact-version lookup proved that Forgejo's remote integrity\nmatches the local dry-run. T03 waits only on rotating the dedicated package\ntoken and proving the next fresh version through `whynot-design-npm-publish`;\nthe package migration itself is complete.\n\n**2026-09-09 \u2014 field claim corrected, path routed.** `secrets-engine` (msg\n`15f0c0ca`) corrected two things and declined a third, all correctly.\n\nThe KV field is `npm_token`. `NPM_AUTH_TOKEN` is the environment variable their\npublication-scope policy injects, and ops-warden had copied the env var in as the\nfield name \u2014 so the catalog's `fetch_command` named a field that does not exist\nand could only ever have failed. Corrected in `registry/routing/catalog.yaml` and\n`wiki/playbooks/whynot-design-npm-publish.md` from the owner's statement rather\nthan re-derived here. This was `ADR-0001`'s failure mode rather than a typo: a\npointer layer restating an owner's procedure and getting a detail wrong.\n\nThe endpoint claim already agreed; `delivery_config.npm.registry` has been the\nForgejo URL throughout.\n\nThe **path** is routed to `railiance-platform` and the catalog is unchanged pending\ntheir answer. Which location backs the lane for reads is custody state they own;\n`secrets-engine` has no lane read authority to confirm it and refused to rewrite a\nproduction lane pointer from a coordination message (`SECRETS-WP-0006-T06`). Their\nreasoning is right, and asserting our own pointer is authoritative because it is\nours would route around it. The ask names a location only and flags that a\n`bao kv get` answer would be the 2026-07-16 disclosure vector on a `risk: high`\nlane.\n\n`ready: false` is not being read as path evidence: a source checkout with no\nproduction authority reports not-ready regardless of which path the catalog names.\n\nT03 still waits on the human rotation of the dedicated Forgejo package token; the\npath question does not block that, it determines whether the pointer is correct\nonce it rotates.\n\n**2026-09-21 \u2014 field reverted to `NPM_AUTH_TOKEN`; path confirmed; a second\nlocation found.** `railiance-platform`, who holds custody of the path, answered\nboth halves (msgs `c6841bdb`, `79f3e047`) and the answer reverses the 2026-09-09\nchange above.\n\nAn attended founder session enumerated the field names present at\n`platform/workloads/coulomb/whynot-design/npm-publish`: read-only, no mutation,\nno value emitted, `attended_identity` true. **Exactly one field is present, and\nit is `NPM_AUTH_TOKEN`.** Receipt: `railiance-platform\ndocs/evidence/2026-09-10-npm-lane-field-resolution.json`, commit `9d24086`. The\nboth-fields reconciliation offered the day before is ruled out by the same\nenumeration. `CCR-2026-0001` has carried two dated receipts naming that field\nsince 2026-06-28, one of them an attended founder fetch that exited zero \u2014 which\nis itself proof the field exists.\n\nSo `npm_token` is wrong *for this path*, and the catalog and playbook are\nreverted to `NPM_AUTH_TOKEN`. Reverting is a correction back to the evidenced\nvalue, not a new lane change.\n\nThe lesson is the one this plan already recorded, one level in. On 2026-09-09\nthis file wrote that adopting a correction from `secrets-engine` rather than\nre-deriving it was the right shape. It was the right *source* and the wrong\n*standard of evidence*: a correction adopted from a coordination message is\nstill an unverified mutation, even when it is only a field name in a catalog,\nand this one would have failed at the rotation T03 is waiting for \u2014 the moment\nit is most expensive to discover. railiance-platform's phrasing, kept because it\nis better than ours: it will break \"at the moment you least want it to\".\n\n**The second location, which is not ours to dispose of.**\n`secret/coulomb/whynot-design/npm/publish` exists \u2014 version 1, created\n2026-07-03T15:00:44Z, never updated, five days *after* the governed lane was\nverified. It sits outside this lane's exact-path policy and outside any CCR.\nrailiance-platform read metadata only: field names were not enumerated, the\nvalue was not read, nothing was deleted, because a location holding real\ncredential material is disposed of deliberately by its owner rather than tidied\naway by whoever finds it.\n\nTheir unconfirmed hypothesis, recorded because it changes what this lane's\nacceptance evidence means if true: `secrets-engine`'s lowercase field may belong\nto *that* path, their catalog may declare that location, and the proven pilot\npublish may have been reading the duplicate all along. If so, a working\nproduction lane has been running ungoverned and this lane's acceptance evidence\ndescribes a path its consumer does not use. Tracked as `RPF-WP-0035-T07`;\nrailiance-platform has asked `secrets-engine` which location their publish\nreads, and ops-warden has asked the same about the native\n`secrets-engine exec` front door this catalog points at (`exec_owner`).\n\nRecorded in the catalog and in `wiki/playbooks/whynot-design-npm-publish.md` as\nan explicit non-lane rather than deleted from the record. Not routed around: the\ngoverned path stays the pointer.\n\n### 2026-09-27 owner follow-up\n\nConsumed the September 21 secrets-engine source return: the active catalog\nstill names `secret/coulomb/whynot-design/npm/publish`, field `npm_token`.\nThe governed field remains `NPM_AUTH_TOKEN`; no pointer correction is needed\nin Warden. RPF-WP-0035-T07 now requires native governed-consumer proof before\nlegacy destruction and no longer asks for comparison of secret values.\n\nT03 remains wait and the founder's no-rotation hold remains effective.\nResume only on the SECRETS-WP-0006-T06 migration receipt, then rotate through\nthe dedicated package lane and prove a fresh publish plus exact npm view.\nDo not treat the September 16 OpenRouter key-check receipt as npm acceptance.\n\n### 2026-09-28 loose-end review\n\nWorkplan state corrected to blocked to match T03's wait and the September 27\nowner return. The governed catalog field and path are already correct. The\nfounder's no-rotation hold remains binding until SECRETS-WP-0006-T06 supplies\nnative governed-consumer migration evidence; a dedicated token rotation and a\nfresh package publish/exact-version lookup then remain. No credential fetch,\nrotation or publication was attempted.\n\n2026-10-03 (CUST-WP-0075): the gate was only in intervention_note. Encoded as blocking_reason, depends_on SECRETS-WP-0006-T06, and hub decision 1591daa1-6e85-4dfd-aadd-5a9fe1ef47fa (D3: trust root and secret custody), which also carries the matching RPF-WP-0035-T07 hold."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-warden/workplans/WARDEN-WP-0040-unknown-zone-fail-closed-adoption.md",
|
|
"meta": {
|
|
"id": "WARDEN-WP-0040",
|
|
"type": "workplan",
|
|
"title": "Adopt unknown -> fail_closed behind signing-target classification coverage",
|
|
"domain": "infotech",
|
|
"repo": "ops-warden",
|
|
"status": "blocked",
|
|
"flavor": "planning",
|
|
"depends_on": [
|
|
"WARDEN-WP-0032",
|
|
"WARDEN-WP-0034"
|
|
],
|
|
"owner": "ops-warden",
|
|
"topic_slug": "netkingdom",
|
|
"planning_priority": "P1",
|
|
"depends_on_workplans": [
|
|
"WARDEN-WP-0032",
|
|
"WARDEN-WP-0034"
|
|
],
|
|
"created": "2026-09-09",
|
|
"updated": "2026-09-28",
|
|
"state_hub_workstream_id": "c8ee441e-1be1-5219-910c-e79ff23cc9ec"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "WARDEN-WP-0040-T01",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:ops-bridge",
|
|
"blocking_reason": "Warden's own declaration cannot classify the repair-path target workloads; the owner must declare the continuity actor/target and its z2-continuity resolution (see 2026-09-28 review).",
|
|
"priority": "high",
|
|
"state_hub_task_id": "611f0901-9fb5-5954-8dd0-a860c5f0cbec",
|
|
"body": "2026-09-30: gate stated. The 2026-09-28 review found the classification is not ours to make (target workloads belong to ops-bridge, the Inter-Hub execution owner and the backup owner), so T01 waits on the owner declaration, same as T02. Qualified per Task Wait Qualifiers v0.1.\n\n\n**Classify the continuity path before anything else changes.**\n\nThe deadlock is specific and worth naming before it is designed around: flex-auth\nunreachable \u2192 operator needs an SSH certificate to reach the host \u2192 target is\n`unknown` because nobody classified the repair path \u2192 `fail_closed` denies it.\n\n`z2-continuity` exists for this and its stance is `fail_open`, so the fix is\nclassification, not an exception. Determine which actor(s) constitute the\nrepair path, establish whether the declaration is ops-warden's to make (our own\n`tenancy.yaml` covers ops-warden as a workload; the actors' target workloads may\nnot be ours), and route what is not.\n\nBlocks T03. Converting the cell with the repair path unclassified is the one\noutcome this workplan exists to prevent."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0040-T02",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:ops-bridge",
|
|
"blocking_reason": "Owners of agt-codex-interhub-bootstrap (ops-hub) and agt-state-hub-bridge (ops-bridge) must publish authoritative workload identity declarations; atm-backup-daily declared by activity-core and compiled 2026-10-09 (z2-protected, admission unsatisfied: M1 below M2 floor).",
|
|
"priority": "high",
|
|
"state_hub_task_id": "54ad4864-7bcf-592e-a187-9239a81a0b11",
|
|
"body": "**Raise signing-target coverage, by asking owners \u2014 never by inferring.**\n\nThree actor resources report `workload_resolution_absent`:\n`agt-codex-interhub-bootstrap`, `agt-state-hub-bridge`, `atm-backup-daily`.\nTheir owners (ops-bridge and the backup execution unit among them) have not\npublished an authoritative workload identity declaration.\n\n`ADR-0009` rule 3 forbids closing this with path or repository-name inference,\nand that prohibition holds under pressure from this workplan specifically \u2014\nadopting a stricter stance is not a licence to manufacture the membership that\nmakes it survivable.\n\nRoute to each owner with the concrete consequence: while the declaration is\nabsent their actor cannot be issued a certificate during a flex-auth outage once\nthe cell converts. That is a better ask than a generic request to publish a\ndeclaration, and it is true.\n\nReport coverage with `scripts/report_workload_join.py`; this task is done when\ncoverage is stated, not when it reaches a threshold \u2014 the threshold is T03's\ngate, and owners may legitimately decline."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0040-T03",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"WARDEN-WP-0040-T01"
|
|
],
|
|
"blocking_reason": "Gated on T01 and on layer model v0.8 (or successor) reaching accepted; never convert against a proposed standard.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "93eaf1f2-daaa-5e22-8804-85ca9433571c",
|
|
"body": "**Convert the cell and supersede `ADR-0009`'s unknown row.**\n\nGated on T01, and on v0.8 (or its successor) reaching `accepted`. Do not convert\nagainst a `proposed` standard.\n\n`ADR-0009` is `owner: ops-warden`, so changing it means a superseding ADR, never\nan in-place edit (`.claude/rules/architecture.md`). The superseding record should\ncarry the v0.8 argument rather than restate it: unknown is not a zone, so a \u00a79.3\nper-zone trade was never made for that request.\n\n`pep-stance.yaml` is asserted equal to `PolicyConfig.failure_modes` by\n`tests/test_layer_conformance.py`, so the map and the code convert in one commit\nor the test fails \u2014 which is the property that makes the map worth publishing."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0040-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "222a8c5d-0c0f-5a1d-98d8-02be7dca3358",
|
|
"body": "**Return findings to gate-house and track the transition ask.**\n\nSent 2026-09-09 with the review. Two asks, in preference order: obligation 3\nnames a dated transitional state gated on coverage; or failing that, \u00a713.1\nrecords classification coverage alongside stance, so a register row cannot read\n`unknown: fail_closed` while every target is unknown.\n\nIf both are declined, that is an answer and this workplan proceeds unchanged \u2014\nthe cell stays a **declared gap** under \u00a711 with this workplan as its route,\nwhich is what the `declared-gap` mark (our own v0.6 finding) exists to express.\n\n**Answered 2026-09-09 \u2014 GH-DEC-2026-011.** Ask 1 declined, ask 2 adopted;\nstandard amended at `net-kingdom@64394e9`.\n\nAsk 1's refusal is correct and we are not appealing it: a sanctioned transitional\n`fail_open` is indistinguishable at runtime from the stance the rule forbids, and\nwould make the rule optional at the only moment it costs anything. Ask 2 gave us\nwhat we actually needed \u2014 \u00a713.1 carries a Coverage column with this repo's\nfigures as its first entries, guarded so that coverage never softens a stance,\nnever gates one, and never makes a non-conformant cell conformant.\n\nThe reversal condition on that column binds ops-warden first, since the column\nexists because we asked: if a row is ever argued conformant *because* its coverage\nis low, the column comes out. Our row reads non-conformant and low-coverage, and\nthe second is not a defence of the first.\n\ngate-house confirmed explicitly that they are **not** asking for the cell to be\nflipped before coverage exists, and that this workplan's order is right. The cell\nstays a declared gap under \u00a711 with WP-0040 recorded as its route \u2014 the outcome\nthis task named as acceptable if both asks were declined, reached with one of them\nadopted.\n\nT01\u2013T03 are unchanged and still gate the conversion. Coverage is now measured\nrather than asserted (`scripts/report_coverage.py`), so T02's reporting obligation\nhas a tool behind it and the published figure cannot drift from the register's.\n\n### 2026-09-28 loose-end review\n\nT04 is done: GH-DEC-2026-011 already answered both transition asks on September 9;\nthe accepted coverage column and declared-gap disposition are recorded above.\nNo additional response is required to meet that task's acceptance criterion.\n\nT01/T02 now wait; the workplan is blocked. Re-ran both coverage reports:\nsigning targets = 0 resolved / 3 unknown / 1 not-applicable; routing lanes =\n3 resolved / 20 unknown / 15 not-applicable. Refreshed pep-stance.yaml's measured\ndate. These figures describe the checked-in registry and local owner declarations,\nnot a live PDP query. No zone membership was inferred or changed.\n\nThe exact missing workload resolutions are `ops-bridge-tunnel` for\n`agt-state-hub-bridge`, `codex-interhub-bootstrap` for\n`agt-codex-interhub-bootstrap`, and `backup-daily` for `atm-backup-daily`.\nThe seed inventory's `adm-example` is not an admitted repair actor.\nWarden's own workload declaration cannot classify those target workloads.\nT01 needs an owner-declared continuity actor/target and its authoritative\nz2-continuity resolution; T02 retains the owner-routing/declaration follow-up\n(ops-bridge, the Inter-Hub execution owner and the backup execution owner).\nWithout it, changing unknown to fail_closed would deny their issuance during a\nPDP outage. Coverage reporting is complete, but owner coordination is not.\n\nT03 also remains gated on standard acceptance: the local authoritative\nnet-kingdom/canon/standards/security-layer-model_v0.8.md still says proposed.\nNo superseding ADR or runtime stance change is warranted before these gates.\n\n### 2026-09-30 owner asks sent\n\nRouted the concrete-consequence ask (T01 classification + T02 declaration) to `ops-bridge` (agt-state-hub-bridge), `ops-hub` (agt-codex-interhub-bootstrap; owner unconfirmed, asked to name the owner if not theirs) and `railiance-platform` (atm-backup-daily; same caveat). Declining is an accepted answer. No membership inferred. T01/T02 stay `wait` on these replies.\n\n### 2026-10-08 owner replies recorded\n\n`atm-backup-daily`: railiance-platform declined in its replies of 2026-10-02\n(msgs 53234ede, a3691df9). It declares only the credential lane\n`railiance-backup-offsite-lane`, and no workload in railiance-platform has that\nname. It names activity-core as the declaring owner, because activity-core is\nthe source repo of `daily-cnpg-option-a-backup`. It classifies the actor as\n**ordinary**, not z2-continuity repair-path. activity-core will not declare\nwithout founder confirmation (ACTIVITY-WP-0042-T03, decision 89f1058f). So this\nactor now waits on that founder decision, not on railiance-platform. No\nmembership is inferred. `agt-state-hub-bridge` (ops-bridge) and\n`agt-codex-interhub-bootstrap` (ops-hub) are still unanswered.\n\n2026-10-08 (later): the founder confirmed in session that activity-core's\n`daily-cnpg-option-a-backup` worker is the `atm-backup-daily` unit, and that it\nis classed as ordinary. The confirmation was relayed to activity-core for\nACTIVITY-WP-0042-T03. Decision 89f1058f (D2) was deliberately left open,\nbecause it also gates production ArgoCD go-aheads. `atm-backup-daily` now waits\nonly on activity-core publishing its declaration.\n\n### 2026-10-09 atm-backup-daily compiled\n\nactivity-core published `declarations/backup-daily/tenancy.yaml` (c1533fe).\nzone-engine's `resolve_zones.py` resolves it with the\n`netkingdom-build-v0.1` profile:\n\n- declared zone: `z2-protected` (ordinary, not z2-continuity)\n- admission: `unsatisfied`, reason `M1_below_M2_zone_floor`\n- effective zone: `unknown`\n\nThe resolved view is committed as `registry/flex-auth/zone-resolutions.json`,\nand the snapshot was rebuilt from it. Resolution is no longer absent. The actor\nstays `unknown` because the owner declared M1, below the M2 floor, which is\naccurate rather than a gap ops-warden may close. Coverage, stated as T02\nrequires: signing targets 0/3 resolved, 3 unknown, 1 not-applicable. The\nfigure is unchanged because `report_coverage.py` counts effective zones.\n`atm-backup-daily` now waits on owner M2 evidence. It does not wait on a\ndeclaration. Still unanswered: `agt-state-hub-bridge` (ops-bridge) and\n`agt-codex-interhub-bootstrap` (ops-hub)."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/ops-warden/workplans/WARDEN-WP-0044-security-case-follow-through.md",
|
|
"meta": {
|
|
"id": "WARDEN-WP-0044",
|
|
"type": "workplan",
|
|
"title": "Follow through on KnownSecurityCases along their type's route",
|
|
"domain": "infotech",
|
|
"repo": "ops-warden",
|
|
"status": "active",
|
|
"flavor": "implementation",
|
|
"owner": "claude-code",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-08",
|
|
"updated": "2026-10-09",
|
|
"depends_on": [],
|
|
"related_repos": [
|
|
"net-kingdom",
|
|
"ops-mason",
|
|
"key-cape",
|
|
"railiance-platform"
|
|
],
|
|
"state_hub_workstream_id": "f7e81013-6868-5d99-8528-ba75a442eca9"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "WARDEN-WP-0044-T01",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"NK-WP-0048-T03"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "ef0920fc-418e-52cb-acff-9a5c0c728bf5",
|
|
"body": "### T01 \u2014 Define the type's follow-through section\n\nPropose the `follow_through` part of the SecurityCaseType schema together with\nnet-kingdom. For each step it names the owner entry point, `warden_executes`,\nthe auth method and lane, whether an attended human login is unavoidable (with\nthe type's justification), and the verification command. Write it for the first\ntype, `oidc-browser-relying-party`, covering key-cape client registration,\ncustody minting and LLDAP group membership.\n\n2026-10-08: NK-WP-0048-T03/T04 landed with a drafted section. Review is in\n`history/2026-10-08-oidc-rp-follow-through-review.md`. It requires three\nchanges before T02: a per-step `lane`, a narrow `warden_executes`, and\n`value_handling`. It also lists four refinements. This task is done when\nnet-kingdom acknowledges the review (NK-WP-0048-T05).\n\n2026-10-09: R4 was withdrawn in favour of ops-mason's per-case\n`{consuming_service}-keycape-client`, with the entry body templated in the type\n(R4\u2032, see the addendum in the review).\n\n2026-10-09: the revised 1.0 type and canon now carry R1\u2013R3, R4\u2032, R5\u2013R7.\n`warden case check-type <type.yaml>` (`src/warden/case_type.py`, tests in\n`tests/test_case_type.py`) checks a type's follow-through mechanically: the\nlive type is schema-conformant, with one attended session\n(`key-cape-oidc-login`). It is not yet plannable, because two lanes are not\nin the catalog: `identity-provisioner-groups` (net-kingdom) and\n`keycape-client-secret-generate` (railiance-platform). These gate T02, not\nT01. T01 still closes on net-kingdom's acknowledgement (NK-WP-0048-T05).\n\n2026-10-09: ops-warden cannot add `identity-provisioner-groups` as the type\ndeclares it. The provisioner accepts only user-engine's runtime token and\nadmits only user-engine pods, so no caller-identity path exists. R8 (review\naddendum) asks net-kingdom either to move `ensure-groups` into the existing\nattended session (recommended) or to give the provisioner an operator\ncredential. `keycape-client-secret-generate` needs a generate-in-custody entry\npoint from railiance-platform, and the broker does not have one yet. Both were\nsent to their owners.\n\n2026-10-09: done. net-kingdom took R8 option 1, so `ensure-groups` runs attended\nin the `register-client` session and `identity-provisioner-groups` is dropped\n(net-kingdom `0e86f95`). The founder acknowledged the type with memo r4 (hub\ndecision `e418263e`, NK-WP-0048-T05 done)."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0044-T02",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"WARDEN-WP-0044-T01"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "5f68c991-f490-58f8-a121-92f74073d272",
|
|
"body": "### T02 \u2014 Plan a case run\n\n`warden case plan <case.yaml>` checks that the case is accepted and materialized,\nresolves each step to its catalog entry and entry point, and prints the run:\nwhich steps warden executes, which run as the attended caller, what the\nverification is. No secret values; no execution.\n\nTests: refuse an unaccepted or unmaterialized case; refuse a step whose catalog\nentry is missing or not reviewed; show attended steps explicitly.\n\n2026-10-09: done. `warden case plan <case.yaml> [--type] [--json]`\n(`src/warden/case_plan.py`, 14 tests in `tests/test_case_plan.py`). It refuses:\n- a case that is not `materialized`, or has no acceptance record\n- a type that is mismatched or not acknowledged\n- any `case check-type` finding, including a missing or unreviewed lane\n- undeclared, type-fixed or secret-sensitivity parameters\n- a placeholder the case does not set, or an unsupported `when`\n\nIt fills type defaults (`issuer`), evaluates `<param> == <value>` conditions,\nrenders owner, entry point, auth and ready_check, groups attended steps per\nlane, and lists the applicable verification.\n\nThe live Forgejo case is correctly refused: it is `accepted`, not\nmaterialized. A materialized copy, with a stand-in lane for\n`keycape-client-secret-generate`, renders six steps: two attended steps plus\n`register-client` in one `key-cape-oidc-login` session, one warden step\n(`mint-secret`), and two owner steps. Seven checks follow.\n\nObservation for net-kingdom (not blocking): `bind-env` runs before\n`register-client`, in type order. Its entry carries a literal\n`KEYCAPE_<CLIENT_ID>_CLIENT_SECRET`, which is not a `{param}` placeholder, so it\nreaches the plan unrendered.\n\n2026-10-09 follow-up:\n- **Format specs.** `_render` supports net-kingdom's `{param:env}` spec (upper\n case, `-` as `_`, the same as `keycape-client.py env_name`) and refuses any\n other spec or `!conversion`.\n- **Case reference.** The plan prints `case-ref: <case_id>@sha256:<hex>` over the\n case file's exact bytes. This is the reference proposed to railiance-platform\n for `credential.py generate --case-ref` (RPF-WP-0054-T01); the broker\n re-derives it from the file.\n- 18 tests now."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0044-T03",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"WARDEN-WP-0044-T02",
|
|
"MASON-WP-0010-T03"
|
|
],
|
|
"blocking_reason": "The Forgejo case must be materialized (MASON-WP-0010-T03) before a run can be built and proven against it.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "bcbf6c91-2c04-5c16-ae8c-5d6c06fd6b89",
|
|
"body": "### T03 \u2014 Run and verify a case\n\n`warden case run <case.yaml>` executes the plan. Owner entry points run through\nthe existing proxy as the caller; steps that need an attended login use the\nexisting contained login envelope (silent command, session revoked afterwards),\ngrouped into as few attended sessions as possible. Then it runs the type's\nverification and writes a receipt without values. `warden case rollback`\nreverses exactly this case's steps.\n\nAcceptance: the Forgejo reference case (NK-WP-0048-T06) reaches `live` through\nthis path, with no case-specific script.\n\nAgreed with railiance-platform (RPF-WP-0054-T01, 2026-10-09):\n- `mint-secret` runs `credential.py generate --grant keycape/client-secret-generate\n --client-id <id> --case-ref <case-ref> --case-file <case.yaml>` as the caller's\n child process. The broker re-derives the case-ref and checks status and\n client_id.\n- warden refuses that step when `WARDEN_AGENT_ID` is set.\n\n2026-10-10: railiance-platform implemented the command (RPF-WP-0054-T03). It is\ncatalogued as draft `keycape-client-secret-generate`, with `exec_owner`\nrailiance-platform and `exec_capable: false`. `warden case check-type` now\nreports the lane as LANE-UNREVIEWED rather than LANE-MISSING. Before it can be\nactivated:\n- the founder binds the issuer policy to the operator OIDC role\n- key-cape confirms the secret format\n- the RPF-WP-0054-T05 probe passes\n\n2026-10-10 (later):\n- **Broker lane.** The issuer role is bound (CCR-2026-0043) and the T05 probe\n passed (railiance-platform `21b8af3`). Only key-cape's format confirmation is\n left. The playbook now includes the issuer-role login, a 15m token with\n unlimited uses that `warden case run` must group with the attended session.\n- **Env spec.** net-kingdom adopted `{client_id:env}` as a 1.0 patch\n (`9a9b8e3`). The plan renders `KEYCAPE_FORGEJO_CLIENT_SECRET`.\n- **Forgejo case.** Rendered and built by ops-mason. It is not yet\n `materialized`: MASON-WP-0010-T03 waits on the railiance-platform CCRs and\n their founder apply.\n\n2026-10-10: `keycape-client-secret-generate` activated on railiance-platform's\ngo-ahead (message 20973a9c) after key-cape confirmed the format (4e0213b3).\n`warden case check-type` on the live type now reports `plannable=True`. The\nonly thing T03 still waits on is the Forgejo case reaching `materialized`\n(MASON-WP-0010-T03).\n\n2026-10-10: net-kingdom moved the type to 1.1 (`e2174ce`) and re-pinned the\nForgejo case. 1.1 adds the verification `consumer-enforces-groups` and requires\nthe hand-over to enforce `access_groups`. `check-type` on 1.1 reports\n`plannable=True`, and a materialized copy renders six steps and the new check.\nThe case-ref digest covers the whole case file, including `status`, so it\nchanges when the case becomes `materialized`. `warden case run` therefore takes\nit from the file at run time, and the broker re-derives it from the same file."
|
|
},
|
|
{
|
|
"id": "WARDEN-WP-0044-T04",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"WARDEN-WP-0044-T03"
|
|
],
|
|
"blocking_reason": "Catalog integration follows a proven run.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "4a0fa4a7-5ca9-518a-ab92-a79a5e2cf93e",
|
|
"body": "### T04 \u2014 Catalog entries from types\n\nLet a type contribute reviewed catalog entries once, so that every case of that\ntype routes without a new catalog edit. Cases add parameter values, not routes.\n`warden route find` should be able to answer \"which SecurityCaseType covers this\nneed?\" before anyone builds by hand."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"key-cape": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/key-cape/workplans/KEY-WP-0038-forgejo-oidc-client.md",
|
|
"meta": {
|
|
"id": "KEY-WP-0038",
|
|
"type": "workplan",
|
|
"title": "Forgejo as a NetKingdom OIDC client, so the forge can close",
|
|
"domain": "infotech",
|
|
"repo": "key-cape",
|
|
"status": "active",
|
|
"flavor": "implementation",
|
|
"owner": "claude-code",
|
|
"topic_slug": "railiance",
|
|
"created": "2026-10-08",
|
|
"updated": "2026-10-10",
|
|
"depends_on": [],
|
|
"related_repos": [
|
|
"prj-forgejo-org-refactor",
|
|
"railiance-apps",
|
|
"railiance-platform"
|
|
],
|
|
"state_hub_workstream_id": "098e3e2c-a138-560e-b2d3-3a15eb49d8a9"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "KEY-WP-0038-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5f019d13-1fa3-5b88-a27a-75a3339ca96e",
|
|
"body": "### T01 \u2014 Define what Forgejo receives\n\nWrite the claim contract Forgejo consumes, as a non-secret request packet under\n`docs/`:\n\n- issuer `https://kc.coulomb.social`; confidential client `forgejo`; authorization\n code with PKCE; scopes `openid profile email groups`\n- redirect URI\n `https://forgejo.coulomb.social/user/oauth2/netkingdom/callback`. The\n authentication-source name `netkingdom` must match railiance-apps'\n configuration exactly.\n- subject and username: canonical directory subject, plus a stable\n `preferred_username` that Forgejo can match to the existing local accounts\n (founder and agent accounts) for linking\n- `groups` naming the Forgejo organisations and teams to map to (for example\n `forge:coulomb:owners`, `forge:coulomb:readers`), and `principal_type` so that\n human and service principals stay distinguishable\n- MFA: forge administrators and owners require assurance with a fresh second\n factor; plain readers follow the client-aware MFA policy (KEY-WP-0008)\n\nAcceptance: the founder accepts the packet. The group names are agreed with\nrailiance-apps.\n\n2026-10-08: packet drafted at `docs/forgejo-oidc-client-request.yaml`. It covers a\nconfidential client `forgejo` with PKCE and `mfaRequired: true`, the exact\ncallback, scopes, a custody path, the claims as emitted at this revision, new\nLLDAP groups `forge-admins`, `forge-coulomb-owners` and `forge-coulomb-readers`\nwith a required-claim gate, no automatic account creation, and linking of local\naccounts. It also proposes that agents and services use scoped tokens bound to\nservice identities, not browser sign-in.\n\n2026-10-08: accepted by the founder (in session). railiance-apps' RAPPS-WP-0016\nuses the same authentication-source name `netkingdom` and the same group names,\nso the agreement condition holds. Before T02, the LLDAP groups `forge-admins`,\n`forge-coulomb-owners` and `forge-coulomb-readers` must exist, with the founder\nin the first two."
|
|
},
|
|
{
|
|
"id": "KEY-WP-0038-T02",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"KEY-WP-0038-T01",
|
|
"NK-WP-0048-T06"
|
|
],
|
|
"blocking_reason": "Registration runs as the first KnownSecurityCase of type oidc-browser-relying-party (NK-WP-0048-T06), not as a hand-built rollout.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "ddcfb482-8f33-5c81-9ce8-84be8fa5dc30",
|
|
"body": "### T02 \u2014 Register the client and hand over its secret\n\n**Changed 2026-10-08 (founder direction):** no case-specific helper script.\nRegistration is the first case of the SecurityCaseType `oidc-browser-relying-party`\n(net-kingdom NK-WP-0048, canon `security-case-types_v0.1`). The parameters\naccepted in T01 become the case; ops-mason materializes it (MASON-WP-0010) and\nops-warden follows through (WARDEN-WP-0044). The registration capability is\nnet-kingdom's (`net-kingdom.keycape-client-registration`); key-cape's part is its\nfield rules and reviewing the type's composition.\n\nThe original intent below still describes what must result.\n\nRegister `forgejo` from the packet. Mint the client secret straight into custody\n(OpenBao path `platform/workloads/keycape/forgejo`, field `CLIENT_SECRET`, derived\nby the case type since net-kingdom 074b3a0; custody owner railiance-platform,\nconsumers KeyCape via ESO and Forgejo). Record a receipt with no\nsecret value.\n\nAcceptance: discovery metadata lists the client's redirect URI. The secret is\nreadable by Forgejo's custody path only.\n\n2026-10-10: key-cape reviewed the type's composition\n(`docs/oidc-browser-relying-party-type-review.md`). net-kingdom fixed the findings\nin `61ab6bc`, a 1.0 patch: redirects with `?` or `#` refused, the groups scope\nrequired, and descriptions corrected. A new 1.1 (`e2174ce`, founder go) adds the\n`consumer-enforces-groups` verification. For Forgejo, that is the required-claim\nsetting railiance-apps configures. `security-cases/forgejo-netkingdom-oidc.yaml`\nis re-pinned to @1.1, with parameters unchanged. KeyCape added `keycape\ncheck-config` (`c528daa`), which register-client runs before the restart. T02 still\nwaits on NK-WP-0048-T06, which needs both executors' light paths (MASON-WP-0010-T03,\nWARDEN-WP-0044-T03)."
|
|
},
|
|
{
|
|
"id": "KEY-WP-0038-T03",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"KEY-WP-0038-T02"
|
|
],
|
|
"blocking_reason": "Claims are verified against the registered client.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "40ddaa29-7245-508c-ad48-ddc063e25115",
|
|
"body": "### T03 \u2014 Prove the claims for each kind of identity\n\nBefore Forgejo uses the client, verify the issued ID token and UserInfo for one\nhuman (the founder, with MFA), one agent identity and one service identity:\nsubject, `preferred_username`, `groups`, `principal_type`, assurance. Record the\nclaims, minus tokens, as evidence.\n\nDecide with railiance-apps whether agents and services sign in to Forgejo at\nall, or receive scoped Forgejo tokens bound to a NetKingdom service identity\n(ORGREF-WP-0002-T06). Record the decision.\n\nAcceptance: evidence for all three principals; the agent and service decision is\nrecorded. Then hand over to RAPPS-WP-0016."
|
|
},
|
|
{
|
|
"id": "KEY-WP-0038-T04",
|
|
"status": "cancel",
|
|
"priority": "high",
|
|
"state_hub_task_id": "583cf1f1-16dc-515f-83bc-1efc45024a89",
|
|
"body": "### T04 \u2014 Implement the `keycape-client` entry point\n\n**Cancelled 2026-10-08: moved to net-kingdom NK-WP-0048-T09 (done).** The live\nregistration machinery (contained kubectl, cluster and issuer pins) already lives\nin net-kingdom `sso-mfa/k8s/keycape/`, where KeyCape is deployed; a copy here\nwould drift. The entry point is `net-kingdom/sso-mfa/k8s/keycape/keycape-client.py`\nand the declaration is `net-kingdom.keycape-client-registration`; key-cape's draft\ndeclaration is removed. key-cape still owns the client field rules (canonical\nmodel) and their enforcement at authorization time.\n\n`capabilities/playbooks/key-cape.oidc-client-registration.yaml` (contract PASS,\n`maturity: planned`) declares client registration as a playbook capability, so\nthat the SecurityCaseType `oidc-browser-relying-party` (net-kingdom NK-WP-0048)\ncan compose it. Implement the entry point it names, `tools/keycape-client/`:\n\n- `keycape-client register --client-file <rendered-client.yaml>` with modes\n `inspect`, `dry-run`, `apply` and `remove`; adds, updates or removes exactly one\n client in the live registry; idempotent; never prints or writes secret values;\n a confidential client's secret is read from its custody reference\n- one implementation replacing the per-client helpers in net-kingdom\n `sso-mfa/k8s/keycape/` (register-coulomb-social, portal-client-rollout,\n vergabe-client-rollout, secrets-engine-openbao-client-rollout), keeping their\n safeguards (byte-preserving merge, compare-and-swap, cluster pin, safe receipts)\n and their tests as regression cases\n- client field validation by the KEY-WP-0028 rules\n- then set the declaration's `maturity` to `implemented`\n\nLonger term, loading clients from a non-secret registry with secrets referenced\nfrom custody would remove the type's only attended step (see the type README,\n\"Attended steps\")."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/key-cape/workplans/KEY-WP-0039-openbao-negative-probe-tokens.md",
|
|
"meta": {
|
|
"id": "KEY-WP-0039",
|
|
"type": "workplan",
|
|
"title": "Negative-check tokens for the secrets-engine OpenBao JWT role",
|
|
"domain": "infotech",
|
|
"repo": "key-cape",
|
|
"status": "active",
|
|
"flavor": "implementation",
|
|
"owner": "claude-code",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-10",
|
|
"updated": "2026-10-10",
|
|
"depends_on": [],
|
|
"related_repos": [
|
|
"railiance-platform",
|
|
"secrets-engine"
|
|
],
|
|
"state_hub_workstream_id": "09c3bddf-6058-5603-8488-cccdb7be4f86"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "KEY-WP-0039-T01",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "4d06b059-3768-53bb-83a4-a9a71c0850b8",
|
|
"body": "### T01 \u2014 Define the probe registrations\n\nWrite a non-secret request packet under `docs/` with one probe client per claim\nmismatch, each identical to `secrets-engine` except for:\n\n- `aud`: a different access-token resource audience\n- `sub`: a different service subject\n- `tenant`: a tenant other than `platform`\n- `roles`: a role other than `secrets-engine`\n- `scope`: a scope outside the role's bound scope\n\nTwo cases need no probe client. A service token always carries\n`principal_type: service` (`src/internal/server/oidc/token.go`), so the wrong\n`principal_type` case uses a human access token from an attended login. The\ncoding-agent case uses the existing `codex-railiance-platform` registration (role\n`coding-agent`, `docs/openbao-service-auth-contract.md`) if it is registered live;\nT01 confirms that.\n\nThe expired-JWT case reuses any probe client: request a token, wait past its\n60-second lifetime, then present it.\n\nAcceptance: railiance-platform agrees the packet covers every refusal that\nCCR-2026-0038 names.\n\n2026-10-10: railiance-platform agreed that the case list covers every\nCCR-2026-0038 claim negative. The remaining CCR checks (capabilities-self deny, no\nprovider fallback) are theirs and secrets-engine's. Packet written at\n`docs/openbao-negative-probe-clients.yaml`. It departs from the agreed list in two\nways, both sent back for re-agreement:\n\n- **Expired case.** A token from another probe already fails a claim, so its\n refusal does not show that expiry was checked. It needs a sixth client,\n `openbao-probe-expiry`, identical to `secrets-engine-openbao` in every claim. That\n makes it a second credential able to log in as secrets-engine for the session.\n OpenBao's `expiration_leeway` (150s by default) also extends the wait.\n- **Audience pin.** A service token's `aud` is its `clientId` unless `audience` is\n set. Every probe except the aud probe therefore pins\n `audience: secrets-engine-openbao`, so it fails only on its own claim.\n\nCondition (a), no OpenBao custody, holds. The values still have to reach KeyCape's\nenvironment, because KeyCape resolves `secretRef` at startup. The packet uses a\ntransient Kubernetes Secret that is deleted in the same session."
|
|
},
|
|
{
|
|
"id": "KEY-WP-0039-T02",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"KEY-WP-0039-T01"
|
|
],
|
|
"blocking_reason": "Live registration and custody need owner authorization.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "03da4c38-1dac-53b1-8b0b-e697df48e9d3",
|
|
"body": "### T02 \u2014 Register the probe clients, run the attended probe, then remove them\n\nWrite the attended script, which prints booleans only.\n\n2026-10-10: script written at `scripts/openbao_negative_probe.py`, with tests in\n`scripts/test_openbao_negative_probe.py`. It meets condition (b): one refused\nboolean per case plus the refusal class (`claim_mismatch`, `expired`,\n`not_service_principal`), and no token, secret, claim value or OpenBao error text.\nA transport failure or an unexpected response is reported as `inconclusive`, never\nas a refusal. A token that OpenBao accepts is revoked at once and fails the run.\nStill waiting: railiance-platform's re-agreement on the two departures above, and\nan attended registry session with net-kingdom. Register the clients\nthrough the normal registration path, hand the run to railiance-platform, record\na value-free receipt in `docs/evidence/`, and deregister the clients afterwards.\n\nAcceptance: every case is refused, the receipt is committed, and the probe clients\nare gone."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"user-engine": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/user-engine/workplans/USER-WP-0026-account-recovery.md",
|
|
"meta": {
|
|
"id": "USER-WP-0026",
|
|
"type": "workplan",
|
|
"title": "Account recovery and visible identity and access",
|
|
"domain": "communication",
|
|
"repo": "user-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "user-engine",
|
|
"created": "2026-09-12",
|
|
"updated": "2026-10-09",
|
|
"state_hub_workstream_id": "0aea0a52-13f9-515b-bda8-665f8a4f2d5e"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "USER-WP-0026-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "86324ec8-cf2f-5e9e-bb60-670c4d792828",
|
|
"body": "Route failed browser login to the public account recovery surface without codes,\nstate or unverified identity. Show verified portal identity, tenant memberships,\nand recorded workload memberships; preserve operator/customer separation.\nProvide CSRF-protected portal logout and confirmed shared provider sign-out with\nfixed owner-configured return locations. No automatic reauthentication loops,\nMFA downgrade, global JWT revocation claim or inferred workload entitlements.\n\n## Publish and verify the recovery flow"
|
|
},
|
|
{
|
|
"id": "USER-WP-0026-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "ad5b0a77-d8ec-5e07-9a9e-2fa231a6f792",
|
|
"body": "Publish immutable images, update canonical runtime pins, verify anonymous\nrecovery and sign-out confirmation live, and record actual account switching\nonly after browser evidence. Existing application sessions may outlive provider\nlogout. Related: USER-WP-0025-T03 and VERGABE-WP-0019-T06.\n\nSource verification: 182 tests passed with three optional integration skips; layer conformance passed. Immutable publication and live checks are in progress.\n\n2026-09-27: closed against the completed release and attended owner evidence.\nThe 2026-09-12 release receipt is supplemented by\n`key-cape/docs/evidence/2026-09-24-fresh-login-and-account-switch.md`:\nthe founder confirmed fresh login and account switching, and the issuer recorded\nthree fresh portal authentication/token-issuance sequences after an MFA failure.\nKEY-WP-0034-T02 is done. Existing application JWTs may still outlive provider\nlogout. This does not accept the remaining multi-user Vergabe pilot.\n\n## Discover workload access from authoritative application records"
|
|
},
|
|
{
|
|
"id": "USER-WP-0026-T03",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:access-engine",
|
|
"blocking_reason": "Needs access-engine's per-identity decision/grant/revocation/readback contract and a readable protected-system registry (with key-cape client binding) as the workload catalogue; the membership store cannot represent the allow list.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "95e9a6d4-7e57-5483-97c5-3f4a45bb6767",
|
|
"body": "The requested cross-application allow list is not represented by the current\nUser Engine membership store. Establish a provider-owned workload catalogue and\nread current application access decisions for the signed-in identity. Link only\nregistered HTTPS workload entry points. Distinguish allow, deny and unavailable;\nnever turn a tenant membership, platform role, application registration or a\nmissing access record into an inferred grant. Current UI displays recorded\nworkload memberships only; no complete fleet entitlement inventory is claimed.\n\n2026-10-09: net-kingdom answered (hub message 19a0cbcd, 2026-10-03) that it\nowns neither record. Decisions, scoped grants, revocation and readback belong to\naccess-engine, the only PDP. The workload catalogue is the binding of three\nrecords: access-engine protected-system registration, key-cape OIDC client\n(entry points) and the user-engine application record. A workload is listed\nonly when all three exist and are bound. \"Unavailable\" is the PEP outcome when\nno decision is returned, never an inferred allow. Wait retargeted to\naccess-engine. Ask filed for the decision/readback contract and a readable\nprotected-system registry. If access-engine declines, return to net-kingdom\nfor an orchestration workplan.\n\n2026-10-09 (later): access-engine accepted the ask as FLEX-WP-0035 and sent\nthe draft contract `docs/application-access-readback.md` (9d9ca69,\nFLEX-DEC-2026-019) for review. user-engine reviewed it and replied (hub message\nf54df082). Shape accepted: dedicated readback pin, `purpose=readback` in the\nhashed request, per-package `application.access`, no grant surface. Answers:\nforward verified claims, in the same subject shape as `/v1/check`, plus\n`subject.tenant`; informed-decision first; 64 per request is enough; reuse\neach row until `expires_at`, per session and only on account-page views.\nRequested: application.access rules may use only realm-level IAM Profile\nclaims, because the session claims carry user-engine's audience. Render\ndeny, not_applicable, failure and expired as not available, never as allow.\nUse a separate `USER_ENGINE_READBACK_TOKEN_FILE`. Wait stays on access-engine\nT02/T03 code and its T04 founder go.\n\n2026-10-10: access-engine folded amendments (a)-(c) into the contract,\naccepted FLEX-DEC-2026-019 and shipped T02/T03 (8f2ba75). T05 (b5da745) gives\ninformed-decision a separate `application.access` rule. user-engine's client is\nnow in the repo, off by default: `application_access.py`,\n`adapters/application_access.py`, the account-page section, and\n`USER_ENGINE_READBACK_URL` / `USER_ENGINE_READBACK_TOKEN_FILE` (see\ndocs/configuration.md). A workload is listed only when all three records are\nbound. Rows follow the agreed rendering table, and none is inferred as allow.\nRemaining before this task is done: access-engine T04 (readback pin values,\ndigest-equality test, founder go), operator-installed readback URL and token\nfile, and a live check against the pin.\n\n2026-10-10: access-engine gave the T04 values (hub 12cefad4), not live yet.\nURL `http://flex-auth-application-readback.flex-auth.svc.cluster.local.:8080`\n(the trailing dot is required). Projected service-account token audience\n`flex-auth`, the same as the /v1/check pin. The admitted caller is\nsystem:serviceaccount:user-engine:user-engine, for readback routes only. The\noperator change goes into the apply home, rapp-user-engine\nmanifests/runtime.yaml: set `USER_ENGINE_READBACK_URL`, mount a second\nprojected token, and set `USER_ENGINE_READBACK_TOKEN_FILE`. T04 itself waits on\ninformed-decision accepting lifecycle v2, then the founder go.\n\n### Live recovery rollout \u2014 2026-09-12\n\nRecovery is deployed in KeyCape 4d8b8fe, User Engine e54b6ee and Vergabe c067993\n(Helm revision 3). All three are Ready. Six provider checks, eleven product\nchecks and six fresh anonymous Chromium checks pass, including actual provider\nlogout POST and return to the portal without test overrides. Real-user identity\nswitching is still awaiting operator evidence; no authenticated/MFA acceptance\nis inferred. Detailed receipt: railiance-apps/docs/evidence/2026-09-12-account-recovery-live.md.\n\n2026-09-27: blocked on an owner-supported workload catalogue/admission and\nscoped grant/revocation contract. The access-engine policy evaluator and local\nuser-engine application/membership records do not establish that contract.\nNeed registered HTTPS entry points, exact identity/tenant/action mapping,\nauthoritative allow/deny/unavailable results, and scoped mutation/readback\nsemantics from the application and authorization owners. Continues jointly with\nUSER-WP-0028-T02; no local grant inference or substitute catalogue was added.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): the net-kingdom reply of 2026-09-29\n(`f1b61ee9`) concerns root-grant custody for USER-WP-0037-T02 and does not\naddress the workload catalogue. No request had ever been sent for this task\ndespite its `message-from:net-kingdom` qualifier (added 2026-09-28). Sent one\nnow (message `db1b7d6e`): does NetKingdom own the workload catalogue/admission\nrecord and the scoped access-decision contract, and if not, who does. The\nqualifier stays on net-kingdom until it answers or names another owner."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/user-engine/workplans/USER-WP-0027-account-journey-clarity.md",
|
|
"meta": {
|
|
"id": "USER-WP-0027",
|
|
"type": "workplan",
|
|
"title": "Clear account state and complete user, tenant-admin and platform-admin journeys",
|
|
"domain": "communication",
|
|
"repo": "user-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "communication",
|
|
"created": "2026-09-13",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "455300ca-ec1e-569e-a584-a8dcda2595cf"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "USER-WP-0027-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "7f184a7c-2b93-5e6a-a15c-6fd8f3e9ff33",
|
|
"body": "Defined 29 journeys in docs/account-journeys.md: 13 user, 8 tenant administrator,\n8 platform administrator. Each has success, failure/recovery and current support\nstatus. The document is the browser acceptance contract, not proof all journeys\nare implemented. Includes OTP state contract and cross-role/isolation checks.\n\n## Make account controls and browser recovery reflect verified state"
|
|
},
|
|
{
|
|
"id": "USER-WP-0027-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "897988e5-32a5-55e0-a49f-92d0e39971b6",
|
|
"body": "Signed-out/expired sessions show Sign in; verified sessions show identity and\nLog out. Logout uses existing scope confirmation; wrong shared-identity recovery\nstays accessible without implying a portal session. Signed-in registration routes\nto account. Browser errors retain status and gain safe recovery navigation; APIs\nremain JSON. Public /security explains OTP setup/recovery without claiming factor\nstate or activation. Fixed HTTPS provider handoff is configurable but disabled by\ndefault pending provider verification. `make test`: 188 tests, 3 optional skips;\nlayer conformance passed. `git diff --check` passed.\n\n## Publish and verify the portal UI cleanup"
|
|
},
|
|
{
|
|
"id": "USER-WP-0027-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "90284878-ace3-5b90-96ed-845bc69f6e61",
|
|
"body": "Publish reviewed source, pin the CI image in rapp-user-engine, deploy with CAS,\nverify readiness, signed-out browser controls, and recovery/security navigation.\nKeep live OTP handoff disabled until T04 dependencies are met.\n\nDeployed source a9ff77d, image sha256:558e489f0b6e0b7160ab0d370560a66497e12488b95531bbccca122b46331a6f, runtime pin commit 367bb1b. Deployment Ready 1/1. Eight live HTTP checks and twelve isolated Chromium checks passed; see docs/evidence/2026-09-13-account-clarity.md. No authenticated OTP acceptance is inferred.\n\n## Complete provider OTP activation and recovery path"
|
|
},
|
|
{
|
|
"id": "USER-WP-0027-T04",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "cef97ccd-4ee7-40fe-859e-1df9c9360ecb",
|
|
"blocking_reason": "Attended live acceptance of U05-U08/P04-P06 against the real provider factor (enrollment, cancellation, replacement, recovery, fresh login, privileged portal policy); the net-kingdom-privacyidea-admin-token route is still resolvable:false because railiance-platform has not published its OpenBao path/field/expiry contract.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "9657abcb-690e-5323-8ff3-58253298ce7b",
|
|
"body": "2026-10-03: depends_on targets terminal (C-40); re-qualified by CUST-WP-0075: KEY-WP-0035-T02/T03 are done (2026-09-13 custody activation superseded the owner-handoff gate) and NK-WP-0033 finished 2026-09-23 with the custody gap closed, so no owner return is outstanding from key-cape or net-kingdom. What remains is attended: live U05-U08/P04-P06 acceptance with a real OTP factor, and the net-kingdom-privacyidea-admin-token route still reports resolvable:false (owner railiance-platform, custody contract unpublished).\n\nDepends on KEY-WP-0035-T02/T03 and NK-WP-0033 custody handoff. Current owner route\nnet-kingdom-privacyidea-admin-token remains non-resolvable. Restore scoped factor\nlookup and verify possession-confirmed enrollment, cancellation, replacement,\nrecovery and fresh login; resolve privileged portal policy. Only then configure\nUSER_ENGINE_MFA_MANAGEMENT_URL and accept U05\u2013U08/P04\u2013P06. Do not fake a status from\nassurance claims, redirect return parameters or manual step completion.\n\n2026-09-27: the missing credential/policy blocker above is superseded.\nKEY-WP-0035 finished on September 14; RPF-WP-0040 delivered the renewable\nfactor-reader lane. NK-WP-0033 closed its separate historical incident on\nSeptember 23. P04 recovery and P06 optional policy are implemented and deployed;\nsee `docs/evidence/2026-09-13-p04-recovery.md` and\n`docs/evidence/2026-09-13-p06-authentication-policy.md`.\nInstalled-provider fixtures prove activation, cancellation, old-session MFA and\nrecovery/replacement; they do not prove a real invited person's full OTP journey.\nRemaining gate: attended U05\u2013U08 enrollment/cancel/replacement/lost-factor and\nfresh-login acceptance, plus verified portal setup handoff configuration. No new\ncredential request is required to resolve the historical blocker.\n\n2026-10-03: human gate routed to hub decision cef97ccd-4ee7-40fe-859e-1df9c9360ecb (D10: Identity record and MFA: accept NK-ADR-0017, choose the record read surface, agree the MFA user experience) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n## Close tenant and platform administrator usability gaps"
|
|
},
|
|
{
|
|
"id": "USER-WP-0027-T05",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "92906113-e28b-58d3-95a7-779e815d1ced",
|
|
"body": "Implement remaining T02\u2013T08/P02/P04/P07/P08 browser gaps from docs/account-journeys.md:\nclear login-name versus display-name and lifecycle states, delivery confirmation,\nconsolidated onboarding diagnosis, scoped lifecycle confirmation/readback, admin\nsuccession guard review and safe audit/support recovery. Existing headless routes\nare starting points, not browser acceptance. Split into owner workplans as needed.\n\n2026-09-22: closed. Split into USER-WP-0029 and USER-WP-0030 (both finished);\n`tests/journey-coverage.json` marks T03, T06\u2013T08, P02, P04, P07 and P08\nimplemented, and `make test-journeys` passes 61 tests. The remaining gaps in scope\nlie outside the admin browser layer and each already has an owner: T02 invited-person\nmail receipt (T06 here), T04 provider lost-factor recovery (T04 here), and T05\napplication grant/revoke (USER-WP-0028-T02). This closes the implementation only.\nIt does not accept those journeys.\n\n## Validate all journeys across roles and applications"
|
|
},
|
|
{
|
|
"id": "USER-WP-0027-T06",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"USER-WP-0026-T03",
|
|
"USER-WP-0027-T04",
|
|
"VERGABE-WP-0019"
|
|
],
|
|
"blocking_reason": "Full journey matrix needs authoritative application access (USER-WP-0026-T03), factor recovery (T04) and preserves VERGABE-WP-0019 real-user acceptance.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "550886ca-f916-5637-9639-b4134b0da939",
|
|
"body": "Execute success/failure/recovery matrix with synthetic user, tenant admin,\nplatform operator, expired and wrong-tenant identities. Include invitation/mail,\nactual OTP, shared sign-out, keyboard/mobile, form preservation, and authoritative\napplication access (USER-WP-0026-T03). Preserve VERGABE-WP-0019 real-user acceptance.\nRecord live evidence and hand off any residuals as live work before closing.\n\n\nImplementation is split into USER-WP-0028 (user), USER-WP-0029 (tenant admin),\nUSER-WP-0030 (platform admin), and USER-WP-0031 (automated acceptance). These\nare live workplans, not residuals parked only in the journey document.\n\nImplemented admin journeys and automated suites are deployed; see docs/evidence/2026-09-13-journey-release.md and its machine-readable report. Full acceptance remains incomplete for the named integration/provider gaps.\n\n2026-09-27: blocked on the remaining acceptance dependencies, not ongoing\nlocal implementation. USER-WP-0026-T02 now closes account-switch verification.\nUSER-WP-0035-T02 retains setup-link delivery; USER-WP-0028-T03 retains actual\nOTP journeys; USER-WP-0026-T03/USER-WP-0028-T02 retain authoritative workload\naccess. VERGABE-WP-0019-T06 still needs the second user and setup-to-workflow\nacceptance. Automated coverage remains an implementation check, not full live\nacceptance. See `docs/evidence/2026-09-27-loose-ends-review.md`."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/user-engine/workplans/USER-WP-0028-user-journey-acceptance.md",
|
|
"meta": {
|
|
"id": "USER-WP-0028",
|
|
"type": "workplan",
|
|
"title": "User account journeys and recovery",
|
|
"domain": "communication",
|
|
"repo": "user-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "codex",
|
|
"topic_slug": "communication",
|
|
"created": "2026-09-13",
|
|
"updated": "2026-10-03",
|
|
"state_hub_workstream_id": "145df9d5-a7e9-5d20-8280-9d3ea069838b"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "USER-WP-0028-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "baa9938e-271b-5590-bdc0-5c844070144c",
|
|
"body": "U01\u2013U04/U10\u2013U13: preserve safe profile input on validation failure; confirm saves, expose actual login name at password handoff, keep invitation/expired/session recovery reachable. Cover success, denial, provider interruption and retry.\n\n## Connect authoritative application access"
|
|
},
|
|
{
|
|
"id": "USER-WP-0028-T02",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"USER-WP-0026-T03"
|
|
],
|
|
"blocking_reason": "Blocked on the provider-owned catalogue/admission and scoped grant/revocation contract from USER-WP-0026-T03.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "5d1bf977-034d-5448-b4fb-5a8b630af6ba",
|
|
"body": "U09 and T05: integrate a supported catalogue/admission source and scoped grants/revocation. Do not present static links or membership as effective authorization. Continues USER-WP-0026-T03; establish provider contract before deployment.\n\n2026-09-27: blocked on the provider-owned catalogue/admission and scoped\napplication grant/revocation contract described in USER-WP-0026-T03. Current\nmembership CRUD and PDP evaluation cannot supply fleet-wide admission or mutate\napplication-owned grants. Resume integration after owners identify the supported\nsource, entry-point registry, identity/action mapping and mutation contract.\n\n## Complete optional OTP onboarding with provider evidence"
|
|
},
|
|
{
|
|
"id": "USER-WP-0028-T03",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "cef97ccd-4ee7-40fe-859e-1df9c9360ecb",
|
|
"blocking_reason": "Attended live acceptance of U05-U08 (enrollment, cancel, replace, lost-factor recovery, old-AAL1-session behavior) against the real provider factor before enabling live handoff; no stub acceptance.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "40e46e52-31ac-5abd-8793-04c1b7b82df3",
|
|
"body": "2026-10-03: depends_on targets terminal (C-40); re-qualified by CUST-WP-0075: KEY-WP-0035 and NK-WP-0033 are both finished (custody gap closed 2026-09-23), so credential custody is no longer the gate. What remains is attended live acceptance of U05-U08 with a real OTP factor; see USER-WP-0027-T04 for the still-unresolvable net-kingdom-privacyidea-admin-token route (owner railiance-platform).\n\nU05\u2013U08: depends on KEY-WP-0035 and NK-WP-0033 credential custody. Verify enrollment/cancel/replace/lost-factor recovery and old-AAL1-session behavior before enabling live handoff. No stub acceptance.\n\n\nValidation: 210 database-enabled regression tests passed with no skips,\nincluding independent-connection last-admin protection and nested bootstrap\nrollback. Thirteen isolated Chromium checks passed. Provider OTP and application\naccess integration remain explicitly open; no complete-journey claim is inferred.\n\n2026-09-27: credential custody and optional-policy rollout are complete\n(KEY-WP-0035, RPF-WP-0040); NK-WP-0033 is also finished. The earlier missing-\ncredential dependency is superseded. P04/P06 installed-provider evidence covers\nenrollment/cancellation, recovery/replacement and old-session enforcement.\nThe remaining blocker is attended real-user U05\u2013U08 acceptance and verified\nportal setup handoff, not another service token. See USER-WP-0027-T04 and\n`docs/evidence/2026-09-13-p06-authentication-policy.md`.\n\n2026-10-03: human gate routed to hub decision cef97ccd-4ee7-40fe-859e-1df9c9360ecb (D10: Identity record and MFA: accept NK-ADR-0017, choose the record read surface, agree the MFA user experience) by CUST-WP-0075; resolving that decision raises C-40 here.\n\n2026-10-09: founder chose coulomb-social as the MFA pilot (docs/mfa-pilot-decision.md).\nMFA stays optional there, and all MFA code stays in NetKingdom infrastructure:\nthe issuer plus user-engine. Admin-required MFA is deferred and would be an\nissuer-side client policy. The attended run accepts U05-U08 for a coulomb-social user:\noptional enrollment, then return, then lost-factor recovery. cef97ccd stays open for\nthat acceptance.\n\n2026-10-10: founder asked (via ops-mason, hub ab89a591) for self-service MFA\nsetup for all users, with tegwick as the first attended run. The run is\nprepared in docs/mfa-attended-run.md. It covers the start point, the attended\nsteps, evidence rules (no seeds, codes or QR), the handoff URL and what stays\ndeferred. It needs the founder's go to set USER_ENGINE_MFA_MANAGEMENT_URL, and\na decision on whether tegwick joins the coulomb-social pilot.\n\n2026-10-10 (later): the founder approved both points. tegwick runs U05-U08 on\ncoulomb-social; there is no pilot member list, a first sign-in is enough. The\nhandoff URL change was sent to net-kingdom (hub 58e999b3), env only. Next:\nnet-kingdom's rollout reply, then the attended run with tegwick.\n\n2026-10-10: net-kingdom replied (7ee2459e) that the handoff URL was already\nlive from rapp-user-engine manifests/runtime.yaml, the apply home. The net-kingdom\nfile is migration input only. Public /security verified showing the\npink-account link. Next: the attended run with tegwick."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/user-engine/workplans/USER-WP-0035-onboarding-handoff-findings.md",
|
|
"meta": {
|
|
"id": "USER-WP-0035",
|
|
"type": "workplan",
|
|
"title": "Onboarding handoff findings from the 2026-09-23 operator run",
|
|
"domain": "communication",
|
|
"repo": "user-engine",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"owner": "claude-code",
|
|
"topic_slug": "user-engine",
|
|
"created": "2026-09-23",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"USER-WP-0027",
|
|
"USER-WP-0028",
|
|
"NK-WP-0036",
|
|
"NK-WP-0041"
|
|
],
|
|
"state_hub_workstream_id": "35aa6adf-255a-5705-9294-a50d98e45f00"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "USER-WP-0035-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "a26b22ae-05fd-52f4-accc-068ccba7bbda",
|
|
"body": "Findings 2 and 3. The derived login name (`bernd.worsch-99` from a\nplus-addressed mail) is not obvious to the recipient, users try the email\naddress first, and the tenant-admin user entry offered no sign-in address to\npass on. Plus-addressed email sign-in additionally fails at Authelia, which\nnet-kingdom tracks as NK-WP-0041-T02; user-engine must therefore not imply\nthat the email address works.\n\n2026-09-23: the tenant-admin user entry now shows the sign-in address next to\nthe login name and states that the email address is not the login name. The\npassword-setup handoff page repeats the sign-in address for after the\npassword is set and says plainly that this portal does not deliver the link.\nRegression coverage is in\n`test_journey_roles.UserJourneys.test_password_handoff_names_actual_login_and_failure_can_retry`.\nNo claim about password or factor state is added, and no delivery is claimed.\n\n## Deliver the setup link to the recipient"
|
|
},
|
|
{
|
|
"id": "USER-WP-0035-T02",
|
|
"status": "wait",
|
|
"needs_human": true,
|
|
"decision_id": "62aa95e4-3ccc-4867-8806-5e3db005b483",
|
|
"blocking_reason": "Needs the operator-owned governed transactional mail lane (email-connect plus the OpenBao delivery token).",
|
|
"priority": "high",
|
|
"state_hub_task_id": "fae614ba-ffc0-511d-9d22-2d91fbab057f",
|
|
"body": "Finding 1: the setup link reaches the provider's screen only. A real handoff\ndepends on the operator passing it on out of band. Closing this needs the\ngoverned transactional mail lane (`email-connect` plus the OpenBao delivery\ntoken) that SCOPE records as operator-owned; U04 and T02 in\n`tests/journey-coverage.json` stay `external-blocked` until then. Do not\nsubstitute a portal-rendered link for delivery evidence.\n\n2026-09-27: the generic missing-mail-lane description above is superseded\nby EMAIL-WP-0004 and USER-WP-0032/P05: the authenticated mail lane exists and\nlive non-sending SMTP/store checks passed. That adapter handles invitation\noutbox events, not the provider's single-use password-setup link. Closing this\ntask still needs an owner-supported setup-link delivery handoff and evidence of\nreceipt by the intended person; a generic SMTP success is insufficient.\nThe latest attended onboarding record still uses out-of-band handoff. No message\nwas sent and no setup-link secret was copied into an event or work record.\n\n2026-10-03: human gate routed to hub decision 62aa95e4-3ccc-4867-8806-5e3db005b483 (D1: Attended OpenBao provisioning window: one session clears the pending credential lanes) by CUST-WP-0075; resolving that decision raises C-40 here."
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"file": "/home/worsch/user-engine/workplans/USER-WP-0037-hub-authority-lookup.md",
|
|
"meta": {
|
|
"id": "USER-WP-0037",
|
|
"type": "workplan",
|
|
"title": "Read-only account authority for Hub integration",
|
|
"domain": "communication",
|
|
"repo": "user-engine",
|
|
"status": "blocked",
|
|
"owner": "codex",
|
|
"topic_slug": "communication",
|
|
"created": "2026-09-28",
|
|
"updated": "2026-10-03",
|
|
"related": [
|
|
"HUB-WP-0012"
|
|
],
|
|
"state_hub_workstream_id": "54d99faf-4c53-5927-a82c-feca41de2cf3"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "USER-WP-0037-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "eb4c1a6c-3cf2-5195-9388-cb9db3190197",
|
|
"body": "Add an authorized service lookup for exact issuer/subject and scoped tenant.\nAuthorize the caller separately before target lookup. Unknown identities never\nprovision; return current global/scoped account state without roles or profile\nPII. Preserve source observation time and identity/account references.\n\nImplemented `UserEngineService.lookup_account_authority` with the separate\n`account.authority.read` action and a digest-bound issuer/subject/tenant resource.\nCaller identity is distinct from the target. Missing tenant-account state is\nexplicit `None`, not active. AccountAuthority contains no root grant, token roles\nor profile/email data. Authorization denial may emit the existing audit record;\nthis operation does not provision or mutate domain records.\n\nValidation: `make test` ran 270 tests successfully (eight optional skips), including\nsix new lookup checks; layer conformance passed. No HTTP endpoint, live grant or\nproduction deployment was added. T02/T03 retain those outstanding owner gates.\n\n## Root entitlement and mapping disposition"
|
|
},
|
|
{
|
|
"id": "USER-WP-0037-T02",
|
|
"status": "done",
|
|
"depends_on": [
|
|
"NK-WP-0045-T05"
|
|
],
|
|
"priority": "high",
|
|
"state_hub_task_id": "23a5c211-277b-561e-a4b3-0f8e99537cac",
|
|
"body": "With NetKingdom, specify explicit current root-grant custody/revocation and\nplatform:root to tenant:platform mapping. Do not derive a grant from JWT roles,\na username, or Hub's configured root subject. Define retainable evidence for\naccount and entitlement observations.\n\nBlocked 2026-09-28: this is a NetKingdom canon decision, not a user-engine\nimplementation choice. `net-kingdom/docs/platform-root-custody.md` covers\nOpenBao/king-credential bootstrap custody but does not yet define how a\nworkload-facing root-grant fact is derived, represented, or revoked for a\nconsumer like the Hub. Requested via State Hub message\n`379d266b-b738-4772-82c0-318e67a50bc8` to `net-kingdom`. `AccountAuthority`\ndeliberately still carries no root-grant field pending that decision.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): net-kingdom replied (message\n`f1b61ee9`) with proposed NK-ADR-0017: the custody record is the sole root-grant\nauthority (LLDAP/JWT are projections, revocation is a recorded custody action);\nthe grant is relation `platform-root-custodian` in `tenant:platform` only,\n`owner_system: net-kingdom-custody`; retainable evidence is subject, grant,\nsource record id+revision, observed_at, revoked_at/expires_at, cached at most\n15 minutes, fail closed. No machine-readable read surface exists yet. user-engine\nconfirmed the mapping is sufficient (reply `60acf176`), stated the intended\noptional `root_grant` observation shape and fail-closed behaviour, and asked\nfor exact (issuer, subject) keys and a monotonic revision. The wait moved from\n`blocked_on: message-from:net-kingdom` to `depends_on` NK-WP-0045-T01 (founder\naccepts or amends NK-ADR-0017) and NK-WP-0045-T04 (read-surface decision), both\nrouted to hub decision cef97ccd (packet D10). No code changed: the field is\nadded once the read surface exists; until then no root grant is returned.\n\n2026-10-03 source-side progress (handoff `d6efcf93`): added transport-neutral\n`src/user_engine/custody.py`. Injected source binding, owner read timestamp,\nNetKingdom validation/transition/observation policy and atomic persistent baseline\ninterfaces; every observation performs a fresh owner read, including writes.\nRead failures, stale/future data, rollback, same-revision mutations and persistence\nconflicts yield no grant. Empty/revoked revisions retain the monotonic baseline.\nInitial baseline establishment defaults denied and needs an approved bootstrap\nprocedure. No runtime binding or AccountAuthority root field is activated.\n\nApproved OpenBao design envelope supplied by railiance-platform is\n`data.data.document` containing the complete canon document. This is compatible\nwith the reader seam; the design approval does not establish an authenticated live source. This\nrepo contains no Kubernetes deployment/SA identity to use as an admission receipt.\n\nRemaining owner requirements: version-pinned canon policy packaging, bounded\nauthenticated reader, atomic durable baseline store with controlled rebootstrap,\nreal read identity/provenance and denial/outage/recovery acceptance; then add the\noptional AccountAuthority mapping and downstream integration receipts. T02 remains\n`wait`, workplan remains `blocked`; local fixtures do not establish live delivery.\n\nFounder approval received during this session: ADR-0017 and the proposed\nOpenBao delivery design are approved; NK-WP-0045-T01/T04 no longer block T02.\nThis does not authorize live provisioning/deployment or create a custody entry.\nThe remaining dependency is NK-WP-0045-T05 owner delivery plus user-engine's\nruntime admission, durable baseline, policy packaging and integration receipts.\n\nValidation: `PYTHONDONTWRITEBYTECODE=1 make test` passed all 284 tests\n(eight optional skips), including seven new cross-repo canon fixture checks;\nlayer conformance and `git diff --check` passed. The fixture tests optionally\nload the sibling validator and skip if it or jsonschema is absent; production\nhas no dependency on a sibling checkout and no policy loader is configured.\n\nSecurity orientation: emergent knowledge 0.2.3/start digest\n`60f8811c6b94b30d357a0d9e5022f2a8ea52e69b47138d3a536755f3295310b5`,\nwithheld due to changed informed-decision source. Reviewed current local source\nREADME plus current NetKingdom companion and custodian build guidance; restricted\nwork to offline source/tests, with no authority or live-readiness inference.\n\n2026-10-03 continued go-forward implementation: the source is now complete for\nthe confirmed OpenBao/Kubernetes interface. Added dedicated projected-JWT login,\nexact-path fresh KV reader (256 KiB; bounded timeout; denied redirects/cache hits;\nsafe errors), persistent PostgreSQL baseline compare-and-swap in the existing\ndatabase, optional AccountAuthority.root_grant and disabled-by-default runtime\nconfiguration. Owner check time is sampled after I/O; returned observation retains\nthe canon-derived expires_at. Embedded validator/schema/provenance are pinned to\nNetKingdom `db319335b27b61b855382ee5af5d690f06eeb010`, with schema lookup only\nrelocated. No sibling checkout dependency in the runtime.\n\nConfirmed deployment source in `rapp-user-engine/manifests/runtime.yaml`: namespace\nand ServiceAccount user-engine; existing flex-auth audience is not reused. Platform\nagreed dedicated auth/kubernetes role user-engine-root-custody-reader, audience\nopenbao, no default policy and 60-second maximum token lifetime. The packaging\nowner prepares the separate projected token and disabled overlay. No live grant,\ncredential provisioning or deployment acceptance is inferred from source changes.\n\n`python -m user_engine.custody_bootstrap --expected-sha256 <publisher-digest>` is\nthe concrete controlled initialization tool: fresh authenticated read, exact\nsource/record binding and validated canonical JSON digest from a reviewed owner\nreceipt; initialize absent baseline once, never reset. Restore/source changes\nrequire external producer audit/high-water reconciliation before reactivation.\nComplete procedures and configuration: `docs/root-custody-runtime.md`.\n\nValidation: full make test passed 296 tests (eight optional skips), with layer\nconformance and diff checks passing; isolated disposable\nPostgreSQL16 verified bootstrap CAS, competing-writer conflict and reconnect\npersistence. Wheel build succeeded with embedded policy/schema/provenance. Offline\nintegration covers nested data.data.document to serialized AccountAuthority,\nexact source/path/role mapping, post-read timing and emitted expires_at. No live\nOpenBao or production database was accessed by these checks.\n\nFounder reports no existing ceremony record; the approved initial document may\ncontain entries[] and therefore no grant. T02 remains wait for authenticated\npublisher receipt (empty no-grant initialization is acceptable), platform reader admission,\nowner image promotion, reviewed baseline initialization and live acceptance.\nUSER-WP-0037 stays blocked; T03 retains its independent Hub admission dependency.\n\n2026-10-03 LIVE acceptance complete: producer admission/publication returned\nok=true for the approved empty revision1/KV1 document; controlled authenticated\nreceipt-bound baseline initialization succeeded. Actual consumer pod restart kept\nthe existing baseline with no reset/reinitialization. Fresh owner read matched;\nwrong-audience login and real reader metadata LIST/sibling GET/custody POST were\ndenied. The internal fixture service harness against the actual live empty source\nserialized root_grant:null; this is not a real admitted Hub caller acceptance.\nConsumer-injected read failure/same-revision mutation retained the baseline.\nEvidence: `docs/evidence/2026-10-03-root-custody-consumer-live.{md,json}`.\n\nT02 is now done for delivered no-grant integration. No certified custodian or\nactual grant was invented. Producer recovery/read-audit acceptance remains the\nseparate RPF-WP-0049/NK-WP-0045-T05 gate; T03 remains wait for real Hub credentials\nand private integration. Workplan remains blocked solely on T03.\n\n## Authenticated workload transport and private acceptance"
|
|
},
|
|
{
|
|
"id": "USER-WP-0037-T03",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:state-hub",
|
|
"blocking_reason": "T02 delivered empty no-grant custody integration; real independently authenticated Hub caller credential admission and withdrawal/outage/private integration acceptance remain with state-hub (original f3bcc516; renewed request 350c3e12-284c-43a7-9ab1-116df8bcc007). Hub repository registration is not caller admission.",
|
|
"priority": "high",
|
|
"state_hub_task_id": "c5d67725-c685-50f6-9db8-28114a34014b",
|
|
"body": "Expose a narrowly scoped read API with an independently authenticated Hub\nworkload, policy action account.authority.read, exact target binding and no\nend-user bearer forwarding. Add HTTP schema and denial/no-provisioning tests,\nthen admit real caller credentials through their owner and verify withdrawal,\noutages and private Hub integration. A service method alone is not this gate.\n\nImplemented 2026-09-28: `POST /api/v1/platform/account-authority/lookup`\n(`src/user_engine/web.py`), gated by a dedicated `hub_authority_caller` /\n`hub_authority_token` pair distinct from `trusted_proxy_secret` and end-user\nOIDC claims \u2014 a bearer mismatch or unconfigured route denies/404s before any\ndomain lookup runs. Wired in `runtime.py` behind\n`USER_ENGINE_HUB_AUTHORITY_TOKEN` (+ `_ISSUER`/`_SUBJECT`/`_TENANT`), unset by\ndefault so the route stays absent until provisioned. Schema, denial, and\nno-provisioning tests: `tests/test_web_account_authority.py` (7 tests, all\ngreen against `make test`, 277 tests total).\n\nBlocked 2026-09-28 on the remaining half of this gate: admitting a *real*\nHub workload credential is a credential-routing matter\n(`.claude/rules/credential-routing.md`) \u2014 OpenBao/ops-warden issue it, this\nrepo only consumes it. Requested via State Hub message\n`f3bcc516-7241-4050-ba52-5723bb174936` to `state-hub`. Withdrawal, outage,\nand private-integration verification with the real credential are still\nowed once it exists.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): the net-kingdom reply (`f1b61ee9`)\ndoes not bear on this task's own gate; the `message-from:net-kingdom`\nqualifier was stale. The NetKingdom dependency is carried through\n`depends_on: [USER-WP-0037-T02]`; the outstanding owner request is the\ncredential admission message `f3bcc516` to `state-hub`, still unanswered, so\nthe qualifier now names `state-hub`.\n\nSource delivery receipt: implementation commit `0d0751d` pushed to main; image\nCI is triggered by source changes, expected tag `main-0d0751d`; immutable digest030fe90232e20bb02b372e3d16b8ff659a5407d54f6405eb85754262b9ad7dc6\nand owner rollout/restart receipts are now verified (see live consumer evidence). Empty owner candidate digest\n`33a2ae086385028db1b654aa5646b7a98bcde1c5878c804e19315dadc3f87248`\nis approved no-grant initialization input, not notice of live publication.\n\n\n2026-10-04 CUST-WP-0075 reconciliation: `USER-WP-0037-T03`: Completed T02 no-grant integration edge removed. The live consumer receipt explicitly excludes actual admitted Hub principal acceptance; full filtered state-hub replies supply no T03 acceptance. Preserve message-from:state-hub pending exact admission/withdrawal/outage/private-integration evidence, renewed on original request thread as 350c3e12-284c-43a7-9ab1-116df8bcc007. No root grant, credential or private acceptance inferred from Hub record registration."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": "?? .claude/settings.local.json.\n"
|
|
},
|
|
"tenant-engine": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/tenant-engine/workplans/TEN-WP-0012-external-conformance-waits.md",
|
|
"meta": {
|
|
"id": "TEN-WP-0012",
|
|
"type": "workplan",
|
|
"title": "Track the two external dispositions tenant-engine is waiting on",
|
|
"domain": "infotech",
|
|
"repo": "tenant-engine",
|
|
"status": "blocked",
|
|
"flavor": "residual",
|
|
"owner": "claude",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-09-07",
|
|
"updated": "2026-09-10",
|
|
"depends_on": [
|
|
"TEN-WP-0011"
|
|
],
|
|
"unblocks": [],
|
|
"origin": "residual",
|
|
"origin_ref": "TEN-WP-0011",
|
|
"state_hub_workstream_id": "cb7387d0-431d-56a2-bb7b-86a024aeeefb"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "TEN-WP-0012-T01",
|
|
"status": "wait",
|
|
"flavor": "residual",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "7898c1aa-b5de-54cf-87b7-67b727b5d0b2",
|
|
"body": "The emission path shipped in `TEN-WP-0011-T04`: the local outbox is inside\nthe mutation transaction, the drain POSTs `/v1/events` and never fails a\nmutation, and the trade is declared in `docs/evidence-emission.md`. What is\nmissing is sender registration \u2014 a credential audit-core issues and holds\ncustody of. `src/tenant_engine/audit_core.py` documents that this module\nholds no audit-core credential beyond that sender token.\n\nWaiting on: `AUDIT-IN-0002`, filed on audit-core.\n\n**2026-09-10 \u2014 registered, and a blocking defect found on our side.**\naudit-core registered the sender (attributive, `source` pinned to\n`tenant-engine`, `may_write`, `secret_policy: redact`, `tenants: [\"*\"]`\njustified per sender) and recorded our declared completeness trade on the\nsender identity itself. The token and the operator apply are still theirs\nto issue, so this task stays `wait`.\n\nTheir review then found that **no event we emitted could ever have been\naccepted**. `envelope_for` sent five of the eight required fields under\nits own names (`event_id`, `action`, `resource`, `observed_at`,\n`details`) and omitted `correlation_id` entirely; `normalize()` rejects\nthat whole, `400`. Our drain treated `400` as terminal, so every event\nwould have been marked handled here while audit-core held only an\nunchained dead letter \u2014 lost on both sides, silently, with the\nintegration looking healthy. The root cause was on their side: the wire\ncontract was published nowhere we could read, and\n`docs/audit-backend-contract.md` describes the *stored* record, from\nwhich the names we chose were a reasonable inference. It is now published\nas audit-core `docs/event-envelope.md`.\n\nFixed here the same day, ahead of any token:\n\n- `envelope_for` emits exactly the eight required fields and sends none\n of the six audit-core derives.\n- `correlation_id` is threaded through create / revoke / plan, which had\n no such field. It is optional on those three request bodies for\n compatibility; when a caller supplies none this engine mints\n `req-<uuid>` for the operation it actually performed and returns it.\n Never synthesized at the archive, which is what audit-core refuses and\n is right to refuse.\n- `Idempotency-Key` is sent and equals the body `id`.\n- `400` no longer dead-letters. The row stays pending with the rejection\n reason recorded on it, per their guidance that a 400 is an integration\n defect to fix, not a delivery outcome to record.\n- `wire_envelope` upgrades outbox rows written in the old shape at send\n time, and refuses to send one whose correlation cannot be recovered\n from its payload.\n\nVerified by running all nine event types, through the API, through\naudit-core's actual `normalize()` with a matching `SenderIdentity` \u2014 all\naccepted. That is the check their message asked for, short of a live\nnon-production `202`, which still needs the token.\n\nDone when: audit-core registers the sender and production mutations land\nexternally, **or** audit-core declines and `SCOPE.md` row\n\"Independent audit-core emission\" is restated to say so.\n\nDo not: request the token by message, or synthesize a local stand-in that\nwould make the outbox look drained when it is not.\n\n**2026-10-01 \u2014 token minted; manifest side done here; projection pending.**\naudit-core minted the sender token on 2026-09-15 (`AUDIT-WP-0010-T02`) and\nproved a 202/200 pair (`T05`). `deploy/base/tenant-engine.yaml` now carries the\negress rule, the two `TENANT_ENGINE_AUDIT_CORE_*` variables and an optional\nmount for Secret `tenant-engine-audit-core-sender` (`TEN-IN-0005`, `9fabfd7`).\nWhat remains is outside this repo: `ops-mason` `MASON-WP-0007` (draft plan,\nblocked) for a dedicated OpenBao path with Kubernetes-auth ESO, railiance-platform\ndeclaring the policy and role, our ServiceAccount/store/ExternalSecret, and an\nattended founder step that copies the token. The drain re-reads the token file\non every delivery, so no rollout is needed after the first sync. Stays `wait`.\n\n## T02 \u2014 boundary-contract amendment (NET-IN-0002)"
|
|
},
|
|
{
|
|
"id": "TEN-WP-0012-T02",
|
|
"status": "wait",
|
|
"flavor": "residual",
|
|
"priority": "low",
|
|
"state_hub_task_id": "f7d27d7c-f599-5d0e-b60b-9c3ad2b27b87",
|
|
"body": "`net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md` still\ncalls guardrail/quota policy \"reserved, not implemented\" and this repository\n\"not a policy enforcement point\". Guardrails shipped in `TEN-WP-0006`/`0007`,\nand the write path is PEP-shaped without this repository being a PDP, so\nboth sentences now mislead a reader who trusts the contract over the code.\n\nWaiting on: `NET-IN-0002`, filed on `net-kingdom` by `TEN-WP-0011-T06`.\n\nDone when: the contract is amended at its next cut, **or** `net-kingdom`\ndeclines and the standing divergence is recorded here rather than left as\na live contradiction between contract and code.\n\n## Closing this workplan\n\nClose when both tasks reach a disposition, whichever way each falls. If\neither stays open long enough to stop being worth re-reading, `cancel` the\ntask and say in `SCOPE.md` that the gap is permanent \u2014 an accepted,\ndocumented divergence beats an indefinite `wait`."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"gate-house": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/gate-house/workplans/GH-WP-0004-section-11-layer-declarations.md",
|
|
"meta": {
|
|
"id": "GH-WP-0004",
|
|
"type": "workplan",
|
|
"title": "\u00a711 layer declarations \u2014 amendment set and estate closure",
|
|
"domain": "infotech",
|
|
"repo": "gate-house",
|
|
"status": "blocked",
|
|
"flavor": "implementation",
|
|
"origin": "GH-IN-0003",
|
|
"owner": "codex",
|
|
"topic_slug": "infotech",
|
|
"created": "2026-09-21",
|
|
"updated": "2026-10-05",
|
|
"state_hub_workstream_id": "59481e51-2792-5f2c-99c8-2732a0561939"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "GH-WP-0004-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8b4042db-d827-5788-9a08-71e351375f05",
|
|
"body": "### T02 \u2014 A10: \u00a74 gains an evidence-source marking; \u00a711's check reads the marking\n\nIncludes the per-event-class clause and the count repair. Then assess the remaining \u00a74\nrows repository by repository \u2014 `access-engine` is marked by `GH-DEC-2026-018` \u00a72; the\nothers are asked, not assigned."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "813b00f4-1d72-5530-8777-c7983a2559ad",
|
|
"body": "### T03 \u2014 A11: `INTENT.md` governs, the sidecar is derived, a run states its scope"
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T03",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "7735233f-864f-5a73-9b60-7399995b5b97",
|
|
"body": "### T04 \u2014 A12: a declaration carries no standard version\n\nIncludes asking `ops-warden` to drop `standard_version` from the reference form rather\nthan each of the seven adopters deciding separately.\n\n**Revised as A12 r2 (2026-09-21, `GH-DEC-2026-020`).** Applying A12 split thirteen\nrepositories on its reach. r2 states that it reaches every key and value of the declaration\n(a version-bearing `standard:` path and `companion_version` included), does not reach stance,\nclaims or classification maps, and puts the version in the run's output rather than in a\nrecord every repository must emit. Required per-repository changes are listed in\n`GH-DEC-2026-020` \u00a71, \u00a72 and \u00a74. r2 is re-circulated under T09; assent to A12 as first\ncirculated does not carry over."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T04",
|
|
"status": "done",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d40253b6-cdee-5ec3-960a-81a24cdd1947",
|
|
"body": "### T05 \u2014 A13: the `access-engine` coordinate is pending, not broken\n\nOne line in \u00a74. No gate-house ruling required; substance already ruled in the owning\nrepository under `FLEX-WP-0020`."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T05",
|
|
"status": "done",
|
|
"priority": "low",
|
|
"state_hub_task_id": "8dd32a14-35d9-55c3-adfa-d9c728b550b1",
|
|
"body": "### T06 \u2014 Ask `informed-decision` whether it should become a \u00a74 catalog row\n\nAsked, not enrolled. Its correction from `surface` to `Staff`/`pep-shaped` is its own and\nis not a condition of this task.\n\nAnswered **yes** by `informed-decision` (`docs/section-4-catalog-row.md`). The row is not\ndrafted yet: it is coupled to `INFD-IN-0007` (how \u00a73.4's Staff definition fits a\ndeterministic repository that holds evidence), which is left open by `GH-DEC-2026-021`.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): `informed-decision`'s 2026-09-27 reply approves A11 r2\nand A12 r3 (operator-authorized; recorded under T09), changes no files, and confirms\n`INFD-IN-0007` and the \u00a74 row coupling stay open with no deadline. Nothing the task waits\nfor was delivered; the wait stays on `informed-decision` resolving `INFD-IN-0007`.\n\n2026-10-03 (CUST-WP-0075, second check): `informed-decision`'s 2026-10-03 message (`6ab42744`,\nINFD-WP-0005 doctrine check on frictionless decision intake) is about memo admission, not\n`INFD-IN-0007` or the \u00a74 row. It was answered separately (reply `4a290496`; draft\n`decisions/drafts/GH-DEC-2026-023-frictionless-decision-intake.md`). No other\n`informed-decision` message delivers the gate. The wait stands."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T06",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:informed-decision",
|
|
"blocking_reason": "informed-decision answered yes; its section-4 row is coupled to INFD-IN-0007, still open with no deadline (reply 2026-09-27; rechecked 2026-10-03).",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "62ac1f55-d3fc-59bd-84a5-8baec5de6bac",
|
|
"body": "### T07 \u2014 Closing condition 2: `audit-core` returns its \u00a711 review or declines in writing\n\nA written decline closes it. \u00a714 records *not claimed* rather than counting silence as\nassent, and the point is that the record says which.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): `audit-core` **returned** its \u00a711 review on 2026-09-23\n(\"returned, not declined\"; `audit-core` history/2026-09-23-v0.8-section-11-review.md), which\ncloses closing condition 2. It carries two findings against the cut \u2014 the explicit\ncompleteness non-claim should bind load-bearing as well as attributive emission guarantees,\nand A10's evidence-source column needs three values (`yes` / `no` / `unassessed`) with\n`audit-core` marked `no`. Their disposition is tracked in T12, not here."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T07",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "eb459f71-a163-5920-b2fb-63d97d225952",
|
|
"body": "### T08 \u2014 Closing condition 3: `key-cape`, `ops-mason`, `net-kingdom` declare or record a dated gap\n\n`gate-house`'s own is discharged (`GH-DEC-2026-017` \u00a76, this commit). A declaration or a\ndated gap satisfies this equally; conformance is not the condition.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): all three have declared, none needed a gap.\n`key-cape` declared `layer: Tooling`, `role: \u2014` in INTENT.md frontmatter (key-cape 9cb9507,\nreply 2026-09-21); `ops-mason` declared `layer: Staff`, `role: pep-shaped` (ops-mason 0ff263a,\nnow on origin/main, reply 2026-09-21; it records its \u00a75.3 tooling contacts as dated gaps);\n`net-kingdom`'s 2026-09-23 reply confirms its bare `layer: Taxonomy` declaration satisfies\nA12 r2/r3. All three verified in the local checkouts. Closing condition 3 is met."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T08",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "b512f842-f061-53b3-b6f4-a1618db3ff37",
|
|
"body": "### T09 \u2014 Circulate A9\u2013A13 for assent and disposition the returns\n\nRound list: `net-kingdom` (publisher), `access-engine`, `audit-core`, `approval-engine`,\n`ops-warden`, `kings-guard`, plus `informed-decision` and `railiance-master` as the two\nrepositories the vocabulary ruling touches from outside \u00a74.\n\nReturns so far: `approval-engine` assents to A9\u2013A13 as first circulated (98d337c4). A12 r2\nre-circulated 2026-09-21 to the round list with `GH-DEC-2026-020`; assent to r2 is asked\nafresh from every round member, including `approval-engine`.\n\nA12 r2 returns: `approval-engine` approved; `kings-guard` revised (KG-DEC-2026-005, prose\ncitations; A11 single-repository scope); `audit-core`, `access-engine` (`flex-auth`) and\n`ops-warden` deferred assent to the operator, which is pending and not refused.\n`GH-DEC-2026-021` rules both findings. The set is now v0.3, with **A11 r2 and A12 r3**\nre-circulated 2026-09-21. Assent to the earlier texts does not carry over.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): A11 r2 / A12 r3 returns now in \u2014 `audit-core`\napproved (2026-09-23, founder's disposition in its voice), `net-kingdom` approved (A11 r2\nfresh; A12 r3 by operator decision, net-kingdom@a7a4db5), `informed-decision` approved\n(2026-09-27, operator-authorized), and the operator's 2026-09-21 disposition stands as the\nreturn for `access-engine` and `ops-warden`. Still outstanding and theirs to give:\n`approval-engine`, `kings-guard`, `railiance-master` (no r2/r3 return in the inbox). Wait\nre-qualified from `audit-core` to the outstanding members."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T09",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:kings-guard",
|
|
"priority": "high",
|
|
"blocking_reason": "A11 r2 / A12 r3 returns outstanding from kings-guard, approval-engine and railiance-master; all others returned approved.",
|
|
"state_hub_task_id": "ea3e5868-74c8-5893-b514-f60abdaaf42f",
|
|
"body": "### T10 \u2014 `net-kingdom` assembles the amendments into the v0.8 cut and flips acceptance\n\nPublication and the flip are `net-kingdom`'s and were handed over at v0.8 round close.\nThis task tracks the handoff, not the execution.\n\n2026-10-03 (CUST-WP-0075 inbox sweep): `net-kingdom` (2026-09-23) recorded A11 r2 and A12 r3\nin the v0.8 \u00a711 set and confirmed the flip notice will name the eight T11 checkers; the hold\nunder `GH-DEC-2026-019` stands and v0.8 is not flipped. The flip now waits on T09's remaining\nreturns and on T12 (audit-core's findings are against the cut), then on `net-kingdom`.\n\n2026-10-05: T12's disposition is recorded (`GH-DEC-2026-024`). T09's remaining returns and\nthe net-kingdom flip remain. v0.8 is not flipped; the hold under `GH-DEC-2026-019` stands."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T10",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"GH-WP-0004-T09",
|
|
"GH-WP-0004-T12"
|
|
],
|
|
"blocked_on": "message-from:net-kingdom",
|
|
"blocking_reason": "T12 disposition is recorded (GH-DEC-2026-024). net-kingdom flips v0.8 once T09 returns; the hold under GH-DEC-2026-019 stands. v0.8 is not flipped.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "34d0582b-9b7e-5dcf-ac1e-0257312b8b7b",
|
|
"body": "### T11 \u2014 Post-flip: all eight checkers name v0.8 and run the reference detector\n\nA post-flip closing condition, not a condition on the flip (`GH-DEC-2026-021` \u00a74). The\nfollowing re-point `VALIDATED_AGAINST` to the accepted v0.8 and converge their copies on the\nreference detector in `ops-warden`'s playbook (`GH-DEC-2026-021` \u00a73), or record a dated\nreason in writing: `kings-guard`, `user-engine`, `zone-engine`, `secrets-engine`,\n`maturity-engine`, `ops-warden`, `tenant-engine` and `flex-auth`. The T10 flip notice names\nall eight. `whitehat-security`'s move of `conformance_state` out of its declaration is\ntracked here with the same deadline."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T11",
|
|
"status": "wait",
|
|
"depends_on": [
|
|
"GH-WP-0004-T10"
|
|
],
|
|
"blocking_reason": "Post-flip condition: the eight checkers re-point to accepted v0.8.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "1643517b-96e5-5cad-bbe0-0207189e352c",
|
|
"body": "### T12 \u2014 Disposition `audit-core`'s \u00a711 review findings and its \u00a79.6 exception question\n\nAdded 2026-10-03 (CUST-WP-0075 inbox sweep). `audit-core`'s returned review (T07) carries two\nfindings against the cut: (1) the completeness non-claim should be required for load-bearing\nas well as attributive emission guarantees in \u00a711; (2) A10's evidence-source marking needs\n`yes` / `no` / `unassessed`, with `audit-core` marked `no` (`GH-DEC-2026-018`, `AUDIT-IN-0005`).\nSeparately, `audit-core` asked on 2026-09-24 (`AUDIT-IN-0006`, from `FLEX-DEC-2026-018`) whether\n\u00a79.6 admits a declared, detectable, direction-limited failure-path release exception for a\nload-bearing source, and whether \u00a711 should read it. gate-house replied 2026-10-03 with the\nreading of the current text (no exception admitted; \u00a711 reads no such declaration; the\nconflict with fail-closed is gate-house's to resolve) and deferred the ruling to a decision\nrecord. Rule all three via `rmgr decision create`, amend the set, and re-circulate as needed.\n\n2026-10-05: ruled as `GH-DEC-2026-024`. (1) The completeness non-claim binds load-bearing\nsources as well as attributive ones, where the declared guarantee is not itself completeness;\nA2 is amended. (2) A10's evidence-source column is `yes` / `no` / `unassessed`, and\n`audit-core` is `no`. (3) A \u00a79.6 exception for a declared, detectable, direction-limited\nfailure-path release is refused; \u00a711 gains no declaration for it. v0.8 is not flipped.\nPublication remains net-kingdom's under T10. T09 stays wait."
|
|
},
|
|
{
|
|
"id": "GH-WP-0004-T12",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "8585b3e2-f858-5e10-8f42-abfd2a36d428",
|
|
"body": "## Done when\n\nAll five amendments are in the v0.8 cut, the three `GH-DEC-2026-019` closing conditions\nare met, `net-kingdom` has flipped v0.8 to `accepted`, and T11's post-flip re-point is\ndone."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"kings-guard": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/kings-guard/workplans/KG-WP-0005-qonto-source-cadence-admission.md",
|
|
"meta": {
|
|
"id": "KG-WP-0005",
|
|
"type": "workplan",
|
|
"title": "Admit and validate qonto-assistant source completeness evidence",
|
|
"domain": "infotech",
|
|
"repo": "kings-guard",
|
|
"status": "blocked",
|
|
"owner": "codex",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-09-04",
|
|
"updated": "2026-10-03",
|
|
"origin": "cross-repo",
|
|
"origin_ref": "QONTO-WP-0005",
|
|
"state_hub_workstream_id": "db9c1dfb-cab3-5887-963a-bfcdf01cff69"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "KG-WP-0005-T01",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "f65d9f88-2ce3-5b32-b3a0-2395d79c5923",
|
|
"body": "Prefer source-emitted `identity_binding` and `egress_destination` over legacy\nnormalization hints, retain the hints for old records, and prove the live\nmapping does not drift.\n\n## Validate cadence, heartbeat, sequence, and reconciliation locally"
|
|
},
|
|
{
|
|
"id": "KG-WP-0005-T02",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "4978e781-ad4a-5601-ac18-d67dbab61885",
|
|
"body": "Consume the source-owned cadence separately from kings-guard's Taxonomy draft.\nDrive qonto-assistant's real AuditLogger emit path, require one stream instance\nwith contiguous sequence numbers, translate heartbeat claims, compare source\ntransition counts with captured request evidence, and prove the resulting deny\nstream evaluates complete without findings.\n\n## Validate the deployed stream"
|
|
},
|
|
{
|
|
"id": "KG-WP-0005-T03",
|
|
"status": "wait",
|
|
"blocked_on": "message-from:qonto-assistant",
|
|
"blocking_reason": "Operational evidence from an authorized deployed qonto-assistant process; local source-path proof does not substitute.",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "d2f59a1b-ee01-51b5-b9b6-6e7875d6c988",
|
|
"body": "Observe an authorized deployed qonto-assistant process from startup through at\nleast one allow/deny transition and reconciliation read. Confirm the deployed\nconfiguration emits periodic heartbeats at the declared interval, preserves\nsequence/instance semantics, and produces no unexplained divergence. This is\noperational evidence; the local source-path proof does not substitute for it.\n\n**Review 2026-09-05:** Local source-path tests pass with source context,\nheartbeat counters, sequence and reconciliation checks. The canonical cadence\nfixture migration and rejection-path hardening are tracked in KG-WP-0006.\nT03 remains waiting: the source workplan explicitly leaves deployment with the\nruntime owner; this repository supplies no authorized deployed stream endpoint\nor process-lifecycle observation route. Required input is a runtime-owner\ncapture from startup, a request transition, periodic heartbeat timing, and a\nsame-instance reconciliation snapshot. No cluster or Tooling client was used.\n\n**Blocked 2026-09-27:** T01 and T02 remain the only work completable inside\nthis repo; both are done. T03 needs a runtime-owner capture of an authorized\ndeployed process (startup, an allow/deny transition, periodic heartbeat\ntiming, and a same-instance reconciliation read) that this Staff-layer repo\nhas no route to produce itself \u2014 AGENTS.md forbids opening a direct client to\na Tooling-layer system or deployment to obtain it. Workplan moved from\n`active` to `blocked` pending that external input; no further action is\npossible here until it arrives.\n\n\n## Align the observer with the NetKingdom profile namespace"
|
|
},
|
|
{
|
|
"id": "KG-WP-0005-T04",
|
|
"status": "done",
|
|
"priority": "high",
|
|
"state_hub_task_id": "461c62b1-147b-5465-9f3f-38cad0ed753e",
|
|
"body": "2026-10-03: migrated the parser and both copied cadence fixtures to source-owned\nextensions.netkingdom. Legacy extensions.net-kingdom, conflicting dual namespace,\nmissing/malformed profile or invalid classification receive explicit rejection\ndiagnostics; classifications are never inferred. Tests retain generic owner-schema\nchecks and source fixture-only evidence. See docs/CadenceObserverAdmission.md.\n\nT03 remains the owned operational wait: require runtime-owner deployed startup,\nallow/deny, periodic heartbeat and same-instance snapshot plus actual receiver\nread/mapping receipts. Reuse AUDIT-WP-0009's delivered reconciliation, cadence\nregistration and findings interfaces. No source sender, protected registry,\ncredential, live deployment, containment or profile acceptance was changed."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
},
|
|
"policy-nexus": {
|
|
"plans": [],
|
|
"git_status": ""
|
|
},
|
|
"informed-decision": {
|
|
"plans": [
|
|
{
|
|
"file": "/home/worsch/informed-decision/workplans/INFD-WP-0008-lifecycle-expansion-contracts.md",
|
|
"meta": {
|
|
"id": "INFD-WP-0008",
|
|
"type": "workplan",
|
|
"title": "Lifecycle expansion beyond the initial production audience",
|
|
"domain": "infotech",
|
|
"repo": "informed-decision",
|
|
"status": "backlog",
|
|
"owner": "codex",
|
|
"topic_slug": "netkingdom",
|
|
"created": "2026-10-05",
|
|
"updated": "2026-10-05",
|
|
"origin": "residual",
|
|
"origin_ref": "INFD-WP-0007",
|
|
"state_hub_workstream_id": "c7752c09-2b18-55be-85e2-cec44836cfa5"
|
|
},
|
|
"tasks": [
|
|
{
|
|
"id": "INFD-WP-0008-T01",
|
|
"status": "todo",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "17787557-b5f8-5161-b449-8ef050e9fd5b",
|
|
"body": "Contract with KeyCape and Access Engine for agents outside cluster TokenReview,\nadditional tenants/audiences and any anonymous publication. Retain per-record\npolicy and authentication-derived attribution; do not treat arbitrary JWT claims\nas admission. Initial authenticated publication remains the supported path.\n\n## Source connector and retention controls"
|
|
},
|
|
{
|
|
"id": "INFD-WP-0008-T02",
|
|
"status": "todo",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "34c5dbaa-49ac-5294-a576-ab1833c3415e",
|
|
"body": "Select actual source connectors and define their retrieval/credential boundaries,\nnetwork restrictions, content limits and provenance. Define retention/export/\nerasure requirements and owner review before introducing deletion. Existing\ncaller-supplied evidence and append-only custody remain the default.\n\n## Non-approval binding profiles"
|
|
},
|
|
{
|
|
"id": "INFD-WP-0008-T03",
|
|
"status": "todo",
|
|
"priority": "medium",
|
|
"state_hub_task_id": "9c7b6e1d-dcb6-5f96-b623-01b3b4a50f54",
|
|
"body": "Define and implement non-approval L0/L2 presentation/disposition workflows against\nthe shared schema with the identity, authorization and audit owners. Do not create\nan Approval Engine object solely to simulate an unrelated binding act. Preserve\nschema compatibility, human-only binding and revision-specific evidence.\n\n## Optional State Hub outcome write-back"
|
|
},
|
|
{
|
|
"id": "INFD-WP-0008-T04",
|
|
"status": "todo",
|
|
"priority": "low",
|
|
"state_hub_task_id": "91d23710-8d7d-508f-98fd-9d778dcc6acd",
|
|
"body": "Independently admit and verify optional resolution write-back with State Hub.\nKeep explicit correlation, replay, and uncertain-outcome recovery; a human answer\nmust never become an execution authorization. Current notification delivery and\nagent outcome retrieval remain available without automatic write-back."
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"git_status": ""
|
|
}
|
|
} |