From 3a4333d850295d2bed39136bfe53f786564eec03 Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 26 Aug 2026 21:56:44 +0200 Subject: [PATCH 01/32] feat(routing): propose state-hub-forge-derivation-read lane (draft) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warden route find "state hub read private repository" returned nothing, which is why the need had to be reasoned out from first principles instead of looked up. Pointer-only (warden_executes: false): ops-mason builds the AppRole, policy, and KV path under MASON-WP-0003; the forge owner mints the value; paste_once_provision delivers it. ops-warden routes and executes nothing. Graded high on breadth, not on write authority — the token is read-only but organisation-wide, so a leak reads every private repository. Approved at that breadth 2026-08-26 (ops-mason plan §6). status: draft until MASON-WP-0003-T02 has created the structure and the negative capability check passes. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 3377672@bnt-lap001 Assistant-Session: 15463ccf-238f-4e13-b163-93aa25c6d166 --- registry/routing/catalog.yaml | 38 +++++++ .../state-hub-forge-derivation-read.md | 107 ++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 wiki/playbooks/state-hub-forge-derivation-read.md diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 0ab246b..0e2cec8 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -574,6 +574,44 @@ entries: - "Verify capabilities-safe on the data path (`bao token capabilities`); run a restore drill against a re-encrypted artifact." - "After rotation, clear EXPOSED taint: remove custom_metadata exposed_at/exposed_version (see `warden taint railiance-backup-offsite-lane`)." + - id: state-hub-forge-derivation-read + title: Forgejo read-only token for State Hub projection derivation + # Organisation-wide repository read: if the value leaks, every private + # repository is readable. Read-only, no write, no admin, no persistence — + # but the breadth is the grade (approved knowingly 2026-08-26). + risk: high + workload_ref: + applicability: applicable + unknown_reason: "The state-hub deployment has no authoritative workload identity declaration yet; the AppRole is the identity until it does." + need_keywords: [state-hub, statehub, forge, forgejo, derivation, derive, projection, private, repository, clone, FORGE_READ_TOKEN, ADR-012, work-records, unreadable] + owner_repo: ops-mason + subsystem: OpenBao + Forgejo + warden_executes: false + wiki_ref: wiki/playbooks/state-hub-forge-derivation-read.md#worker-checklist + canon_ref: ops-mason/plans/state-hub-forge-derivation-read.md + reviewed: "2026-08-26" + status: draft + delegation: + mode: native + intended_owner: ops-mason + blocked_on: "Entry proposed ahead of the build (MASON-WP-0003-T03). Promote to active once MASON-WP-0003-T02 has created the policy, AppRole, and KV path and the negative capability check passes." + reviewed: "2026-08-26" + verified: unverified + # ops-warden routes this and executes nothing: it issues SSH certificates + # only and owns no secret store. ops-mason builds the structure; the forge + # owner mints the value; paste_once_provision delivers it. + auth_method: "AppRole login (state-hub-forge-derivation) from the in-cluster state-hub workload" + path_template: "platform/workloads/state-hub/forge-derivation (field FORGE_READ_TOKEN)" + rotation: + method: rotate + owner: ops-mason + automatable: false + steps: + - "Mint a replacement read-only token in Forgejo — repository read, organisation-wide, no other scope." + - "Deliver it to platform/workloads/state-hub/forge-derivation, field FORGE_READ_TOKEN, via paste_once_provision. ops-mason does not handle the value." + - "Revoke the previous token in Forgejo." + - "Confirm a derivation pass still reads a known private repository; rotation must not require a chart change or a redeploy." + - id: forgejo-admin-api-token title: Forgejo operator/admin API token (PAT) need_keywords: [forgejo, admin, pat, package, prune, FORGEJO_ADMIN_TOKEN, forgejo-package-prune, forgejo-tegwick, webhook, forgejo-npm] diff --git a/wiki/playbooks/state-hub-forge-derivation-read.md b/wiki/playbooks/state-hub-forge-derivation-read.md new file mode 100644 index 0000000..0c316d3 --- /dev/null +++ b/wiki/playbooks/state-hub-forge-derivation-read.md @@ -0,0 +1,107 @@ +# State Hub Forge Derivation Read Token + +Date: 2026-08-26 (proposed) +Catalog: `state-hub-forge-derivation-read` (status `draft` until built) +Owner: `ops-mason` (built under `ops-mason/plans/state-hub-forge-derivation-read.md`, approved 2026-08-26) + +Read-only Forgejo token so the State Hub can clone **private** repositories and +derive their work records. `CUST-ADR-012` makes the forge the projection source; +that premise held only for repositories central could read, and nine private +repositories were invisible to derivation entirely (`STATE-WP-0083-T04`, +2026-08-26). + +**This lane is a pointer.** ops-warden routes it and executes nothing: it issues +SSH certificates only and owns no secret store. The AppRole, policy, and KV path +are ops-mason's build; the token value is minted by the forge owner and +delivered through `paste_once_provision`. + +**Ask first:** `warden plan "state hub read private repository" --json`. + +--- + +## OpenBao pointers + +| Field | Value | +| --- | --- | +| Mount | `platform` | +| Path | `platform/workloads/state-hub/forge-derivation` | +| Secret field | `FORGE_READ_TOKEN` | +| Policy | `workload-kv-read-state-hub-forge-derivation` (read on that path alone) | +| AppRole | `state-hub-forge-derivation` (`token_ttl=15m`, `token_max_ttl=30m`) | + +**Forgejo token scope:** repository **read**, organisation-wide. No push, no +administration, no other Forgejo resource. Approved at that breadth on +2026-08-26 — the maintenance cost of per-repository grants lands on whoever adds +a private repository later, and the leak radius (every private repository, +read-only) was accepted knowingly. Reasoning in the construction plan §6. + +**Not the admin PAT.** `forgejo-admin-api-token` is a site-admin credential +owned by `railiance-platform`. Reusing it here was considered and rejected: a +projection that only reads must not hold an identity that can write. + +--- + +## Worker checklist + +1. **Plan** (agents — always): + + ```bash + warden plan "state hub read private repository" --json + # expect lane=state-hub-forge-derivation-read + ``` + +2. **In-cluster consumers do nothing here.** The `state-hub` deployment receives + the credential as a Kubernetes Secret; `derive_from_forge()` picks it up on + its own. If derivation reports a repository as unreadable, the lane is the + thing to check — not the repository. + +3. **Never put the token in a clone URL.** Embedded userinfo lands in logs and + process listings. Use a credential helper or an HTTP header. + +4. **Reading the value directly** (operators, rare — verification only): + + ```bash + bao kv get -field=FORGE_READ_TOKEN platform/workloads/state-hub/forge-derivation + ``` + +--- + +## Verify the lane (capabilities-safe — never read the value) + +```bash +# Positive: the AppRole identity can read the data path +bao token capabilities platform/data/workloads/state-hub/forge-derivation +# → expect: read + +# Negative: it can read nothing else, including the admin lane +bao token capabilities platform/data/workloads/forgejo/forgejo-admin +# → expect: deny +``` + +The negative check is the one that matters. The whole argument for building this +lane instead of reusing `forgejo-admin-api-token` is that it cannot do what that +one can. + +--- + +## Rotation + +Re-mint in Forgejo, then overwrite the KV field. Rotation must not require a +chart change or a redeploy — if it does, the delivery in +`STATE-WP-0084-T02` is wrong and should be fixed rather than worked around. + +1. Mint a replacement read-only token in Forgejo (same scope: repository read, + organisation-wide). +2. Deliver it to `platform/workloads/state-hub/forge-derivation`, field + `FORGE_READ_TOKEN`, via `paste_once_provision`. +3. Revoke the previous token in Forgejo. +4. Confirm a derivation pass still reads a known private repository. + +--- + +## See also + +- `ops-mason/plans/state-hub-forge-derivation-read.md` — the construction plan +- `ops-mason/workplans/MASON-WP-0003-state-hub-forge-read-lane.md` — the build +- `state-hub/workplans/STATE-WP-0084-forge-read-for-private-repositories.md` — the consumer +- `wiki/playbooks/forgejo-admin-api-token.md` — the lane this one is deliberately not From 6294e4b52156dbfb30caabb4582bae7c964f56ce Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 26 Aug 2026 21:56:55 +0200 Subject: [PATCH 02/32] chore(registry): regenerate high-risk data paths Picks up state-hub-forge-derivation-read, and two lanes added on 2026-08-23 that were never regenerated after (net-kingdom-lldap-bind-credential, net-kingdom-privacyidea-admin-token). 21 -> 24. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 3377672@bnt-lap001 Assistant-Session: 15463ccf-238f-4e13-b163-93aa25c6d166 --- registry/generated/high-risk-data-paths.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index 6c2c341..c77940d 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,12 +10,12 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-22T23:31:10Z" +generated_at: "2026-08-26T19:56:48Z" source: ops-warden/registry/routing/catalog.yaml -catalog_revision: "0fae0904ce8d8694338dd53a8a79abec5fec788d" -catalog_revision_date: "2026-08-23T01:31:05+02:00" +catalog_revision: "3a4333d850295d2bed39136bfe53f786564eec03" +catalog_revision_date: "2026-08-26T21:56:44+02:00" catalog_dirty: false -high_risk_lane_count: 21 +high_risk_lane_count: 24 concrete_path_count: 14 # Graded high but not a single KV address -- a routing pattern, a broker @@ -23,11 +23,14 @@ concrete_path_count: 14 no_concrete_path: - database-dynamic-credentials - inter-hub-bootstrap-ssh + - net-kingdom-lldap-bind-credential + - net-kingdom-privacyidea-admin-token - object-storage-sts - openbao-api-key - openbao-platform-admin-login - openbao-shamir-recovery-ceremony - ops-warden-warden-sign-token + - state-hub-forge-derivation-read paths: - id: agent-harness-binky-mail-approle From 6e66a5665320c569c7888cccec653d7d5703bfd6 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 27 Aug 2026 22:49:03 +0200 Subject: [PATCH 03/32] fix(routing): state-hub lane uses Kubernetes auth, not an AppRole The construction plan proposed an AppRole from a survey written with no OpenBao session. The phase-4 live survey found kubernetes/ auth already enabled on this cluster with four external-secrets-* roles using it, and the founder ruled for it on 2026-08-27. The pod authenticates with its own projected ServiceAccount token, so the lane has no role_id/secret_id to deliver, store, or rotate. Bound to state-hub/state-hub and deliberately not to default, which would grant the lane to every pod in the namespace. Policy and role are built and capability-verified. Entry stays draft: the KV path holds no token until paste_once_provision delivers one, and the ServiceAccount does not exist yet (STATE-WP-0084-T02). Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 3377672@bnt-lap001 Assistant-Session: 15463ccf-238f-4e13-b163-93aa25c6d166 --- registry/routing/catalog.yaml | 6 ++--- .../state-hub-forge-derivation-read.md | 24 ++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 0e2cec8..d3ca951 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -583,7 +583,7 @@ entries: workload_ref: applicability: applicable unknown_reason: "The state-hub deployment has no authoritative workload identity declaration yet; the AppRole is the identity until it does." - need_keywords: [state-hub, statehub, forge, forgejo, derivation, derive, projection, private, repository, clone, FORGE_READ_TOKEN, ADR-012, work-records, unreadable] + need_keywords: [state-hub, statehub, forge, forgejo, derivation, derive, projection, private, repository, clone, FORGE_READ_TOKEN, ADR-012, work-records, unreadable, kubernetes-auth] owner_repo: ops-mason subsystem: OpenBao + Forgejo warden_executes: false @@ -594,13 +594,13 @@ entries: delegation: mode: native intended_owner: ops-mason - blocked_on: "Entry proposed ahead of the build (MASON-WP-0003-T03). Promote to active once MASON-WP-0003-T02 has created the policy, AppRole, and KV path and the negative capability check passes." + blocked_on: "Policy and Kubernetes auth role built and capability-verified 2026-08-27 (MASON-WP-0003-T02). Still draft: the KV path holds no token until paste_once_provision delivers one, and ServiceAccount state-hub/state-hub does not exist yet (STATE-WP-0084-T02). Promote to active once both land." reviewed: "2026-08-26" verified: unverified # ops-warden routes this and executes nothing: it issues SSH certificates # only and owns no secret store. ops-mason builds the structure; the forge # owner mints the value; paste_once_provision delivers it. - auth_method: "AppRole login (state-hub-forge-derivation) from the in-cluster state-hub workload" + auth_method: "Kubernetes auth (role state-hub-forge-derivation, ServiceAccount state-hub/state-hub) from the in-cluster state-hub workload" path_template: "platform/workloads/state-hub/forge-derivation (field FORGE_READ_TOKEN)" rotation: method: rotate diff --git a/wiki/playbooks/state-hub-forge-derivation-read.md b/wiki/playbooks/state-hub-forge-derivation-read.md index 0c316d3..3969485 100644 --- a/wiki/playbooks/state-hub-forge-derivation-read.md +++ b/wiki/playbooks/state-hub-forge-derivation-read.md @@ -1,7 +1,7 @@ # State Hub Forge Derivation Read Token -Date: 2026-08-26 (proposed) -Catalog: `state-hub-forge-derivation-read` (status `draft` until built) +Date: 2026-08-26 (policy and auth role built and verified 2026-08-27) +Catalog: `state-hub-forge-derivation-read` (status `draft` until the token and ServiceAccount land) Owner: `ops-mason` (built under `ops-mason/plans/state-hub-forge-derivation-read.md`, approved 2026-08-26) Read-only Forgejo token so the State Hub can clone **private** repositories and @@ -27,7 +27,7 @@ delivered through `paste_once_provision`. | Path | `platform/workloads/state-hub/forge-derivation` | | Secret field | `FORGE_READ_TOKEN` | | Policy | `workload-kv-read-state-hub-forge-derivation` (read on that path alone) | -| AppRole | `state-hub-forge-derivation` (`token_ttl=15m`, `token_max_ttl=30m`) | +| Auth | Kubernetes auth role `state-hub-forge-derivation`, bound to ServiceAccount `state-hub/state-hub` (`token_ttl=15m`, `token_max_ttl=30m`) | **Forgejo token scope:** repository **read**, organisation-wide. No push, no administration, no other Forgejo resource. Approved at that breadth on @@ -69,15 +69,27 @@ projection that only reads must not hold an identity that can write. ## Verify the lane (capabilities-safe — never read the value) ```bash -# Positive: the AppRole identity can read the data path -bao token capabilities platform/data/workloads/state-hub/forge-derivation +# Positive: the lane identity can read the data path +bao token capabilities platform/data/workloads/state-hub/forge-derivation # → expect: read # Negative: it can read nothing else, including the admin lane -bao token capabilities platform/data/workloads/forgejo/forgejo-admin +bao token capabilities platform/data/workloads/forgejo/forgejo-admin # → expect: deny ``` +Verified 2026-08-27 through a 2-minute test token, revoked after use: `read` on +its own path; `deny` on `forgejo-admin`, on the shared `llm-connect` provider +secrets, and on the parent metadata path (no listing). + +**Why Kubernetes auth and not an AppRole.** The construction plan proposed an +AppRole; the phase-4 live survey found `kubernetes/` auth already enabled on +this cluster, and the founder ruled for it on 2026-08-27. The pod authenticates +with its own projected ServiceAccount token, so this lane has no `role_id` +/`secret_id` pair to deliver, store, or rotate. The role binds to +`state-hub/state-hub` and deliberately **not** to `default`, which would grant +the lane to every pod in the namespace. + The negative check is the one that matters. The whole argument for building this lane instead of reusing `forgejo-admin-api-token` is that it cannot do what that one can. From 030362085a8efb834708344b57d4943627d0d5b7 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 00:28:23 +0200 Subject: [PATCH 04/32] fix(workplans): qualify ad-hoc identifiers with the repository prefix `ADHOC-YYYY-MM-DD` is unique per date but not per repository, so any two repos opening an ad-hoc on the same day collide. The 2026-08-26 fleet projection reset refused 9 records for exactly this reason. Canon (work-record-types_v0.1, CUST-WP-0066) settled the form as `{PREFIX}-WP-ADHOC-YYYY-MM-DD`, filename unchanged, and grandfathered existing ids on the condition they are never *silently* re-derived. This is the explicit migration that clause allows for. The hub id is derived from the record id, so a changed id is a different record: stale state_hub_*_id fields are dropped and fix-consistency re-derives. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006 --- workplans/ADHOC-2026-06-27.md | 6 ++---- workplans/ADHOC-2026-06-29.md | 6 ++---- workplans/ADHOC-2026-08-11.md | 12 ++++-------- workplans/ADHOC-2026-08-17.md | 15 +++++---------- 4 files changed, 13 insertions(+), 26 deletions(-) diff --git a/workplans/ADHOC-2026-06-27.md b/workplans/ADHOC-2026-06-27.md index cda844a..dfbe370 100644 --- a/workplans/ADHOC-2026-06-27.md +++ b/workplans/ADHOC-2026-06-27.md @@ -1,5 +1,5 @@ --- -id: ADHOC-2026-06-27 +id: WARDEN-WP-ADHOC-2026-06-27 type: workplan title: "Ad Hoc Tasks — 2026-06-27" domain: infotech @@ -9,7 +9,6 @@ owner: claude topic_slug: custodian created: "2026-06-27" updated: "2026-06-27" -state_hub_workstream_id: "142b171b-c34b-4a45-91a5-c77e6d07ec6f" --- # Ad Hoc Tasks — 2026-06-27 @@ -19,10 +18,9 @@ Low-risk opportunistic fixes completed directly during the consolidation session ### T01 — Fix stale `warden` CLI install + make it usable outside the repo ```task -id: ADHOC-2026-06-27-T01 +id: WARDEN-WP-ADHOC-2026-06-27-T01 status: done priority: medium -state_hub_task_id: "867c72c9-9904-400f-8542-04264e5856c2" ``` issue-core reported (msg `70bcf238`) that the `warden` CLI on `~/.local/bin` lacked diff --git a/workplans/ADHOC-2026-06-29.md b/workplans/ADHOC-2026-06-29.md index 34aac41..7346a3d 100644 --- a/workplans/ADHOC-2026-06-29.md +++ b/workplans/ADHOC-2026-06-29.md @@ -1,5 +1,5 @@ --- -id: ADHOC-2026-06-29 +id: WARDEN-WP-ADHOC-2026-06-29 type: workplan title: "Ad Hoc Tasks — 2026-06-29" domain: infotech @@ -9,7 +9,6 @@ owner: claude topic_slug: custodian created: "2026-06-29" updated: "2026-06-29" -state_hub_workstream_id: "1c0460b7-bc8a-48db-96d4-681bce18ac91" --- # Ad Hoc Tasks — 2026-06-29 @@ -17,10 +16,9 @@ state_hub_workstream_id: "1c0460b7-bc8a-48db-96d4-681bce18ac91" ### T01 — Joint-smoke mode for the deployed flex-auth (assist FLEX-WP-0007 T4) ```task -id: ADHOC-2026-06-29-T01 +id: WARDEN-WP-ADHOC-2026-06-29-T01 status: done priority: medium -state_hub_task_id: "371235cc-b9d3-4103-b09f-e4e01cc83c5b" ``` flex-auth (msg `ea00620b`) asked ops-warden to help close FLEX-WP-0007 T4 (joint OpenBao diff --git a/workplans/ADHOC-2026-08-11.md b/workplans/ADHOC-2026-08-11.md index 4f234fb..a8734b0 100644 --- a/workplans/ADHOC-2026-08-11.md +++ b/workplans/ADHOC-2026-08-11.md @@ -1,5 +1,5 @@ --- -id: ADHOC-2026-08-11 +id: WARDEN-WP-ADHOC-2026-08-11 type: workplan title: "Ad Hoc Tasks — 2026-08-11" domain: infotech @@ -9,7 +9,6 @@ owner: claude topic_slug: custodian created: "2026-08-11" updated: "2026-08-15" -state_hub_workstream_id: "bc6dd3e3-ab2b-567a-9574-30d2650f20a2" --- # Ad Hoc Tasks — 2026-08-11 @@ -17,10 +16,9 @@ state_hub_workstream_id: "bc6dd3e3-ab2b-567a-9574-30d2650f20a2" ### T01 — Repair stale `rapp-qonto-keycape-client` wiki anchor (restore green routing suite) ```task -id: ADHOC-2026-08-11-T01 +id: WARDEN-WP-ADHOC-2026-08-11-T01 status: done priority: medium -state_hub_task_id: "ddd0c95c-1196-5251-a4ca-6ef441c2f377" ``` rapp-postgres (msg `96907986`, residual from RAPP-POSTGRES-WP-0002-T04) reported the @@ -39,10 +37,9 @@ an anchor that does not exist. The intended heading is `## Routing catalog index ### T02 — Triage the stale ops-warden inbox (11 unread, C-28/C-29) ```task -id: ADHOC-2026-08-11-T02 +id: WARDEN-WP-ADHOC-2026-08-11-T02 status: done priority: medium -state_hub_task_id: "fda35ad4-f526-5012-a2be-ef6b5dcbc8af" ``` `fix-consistency` flagged 11 unread messages older than 3 days, two of them as possible @@ -73,10 +70,9 @@ read. Inbox is now empty. ### T03 — warden-sign AppRole: PARKED pending WP-0027 break-glass + ops-bridge cutover ```task -id: ADHOC-2026-08-11-T03 +id: WARDEN-WP-ADHOC-2026-08-11-T03 status: done priority: medium -state_hub_task_id: "7ef4b6b0-26bf-5456-8429-8cf8458c2ddc" ``` secrets-engine (msg `80456912`, 2026-06-29) is holding a validated non-mutating dry-run diff --git a/workplans/ADHOC-2026-08-17.md b/workplans/ADHOC-2026-08-17.md index 15f35e5..431ecd6 100644 --- a/workplans/ADHOC-2026-08-17.md +++ b/workplans/ADHOC-2026-08-17.md @@ -1,5 +1,5 @@ --- -id: ADHOC-2026-08-17 +id: WARDEN-WP-ADHOC-2026-08-17 type: workplan title: "Ad Hoc Tasks — 2026-08-17" domain: infotech @@ -9,7 +9,6 @@ owner: claude topic_slug: custodian created: "2026-08-17" updated: "2026-08-17" -state_hub_workstream_id: "8376eb89-36f2-52b0-a59a-2954b2e49349" --- # Ad Hoc Tasks — 2026-08-17 @@ -21,10 +20,9 @@ workload-identity owner. ### T01 — Answer flex-auth: how should `/v1/check` authenticate its callers? ```task -id: ADHOC-2026-08-17-T01 +id: WARDEN-WP-ADHOC-2026-08-17-T01 status: done priority: high -state_hub_task_id: "b980d1f7-2fcc-58dd-97d8-6e9b9ba57bc9" ``` flex-auth (msg `130a148c`, FLEX-WP-0015 T02) reported that `POST /v1/check` and @@ -69,10 +67,9 @@ Their four questions answered in `wiki/NetKingdomSecurityMap.md` ### T02 — user-engine: USER_ENGINE_PROXY_SECRET stays railiance-apps; record consumer-only ```task -id: ADHOC-2026-08-17-T02 +id: WARDEN-WP-ADHOC-2026-08-17-T02 status: done priority: medium -state_hub_task_id: "e76b9b3e-189b-5a4f-8815-4ccf2057507c" ``` user-engine (msg `2af4a124`) answered the open confirm question on @@ -95,10 +92,9 @@ consumes it and has no authority over custody, rotation, or issuance. ### T03 — key-cape: `rapp-qonto-keycape-client` interim accepted; refresh the blocker ```task -id: ADHOC-2026-08-17-T03 +id: WARDEN-WP-ADHOC-2026-08-17-T03 status: done priority: medium -state_hub_task_id: "edfb0626-5022-5f49-aaf9-08e0d1002b90" ``` key-cape (msg `099b7cba`) acknowledged the lane staying interim on ops-warden. @@ -118,10 +114,9 @@ workplan. ### T04 — Session hygiene ```task -id: ADHOC-2026-08-17-T04 +id: WARDEN-WP-ADHOC-2026-08-17-T04 status: done priority: low -state_hub_task_id: "62109af6-f095-5e7b-9258-0fcec29d30e8" ``` - [x] `uv run pytest -q` → 338 passed, 4 deselected (routing anchor + no-double-source From 37c387bd34b361539c5eef61a4bdada3537dd41f Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 00:34:02 +0200 Subject: [PATCH 05/32] fix(workplans): qualify archived ad-hoc identifiers The live-file pass missed these: archived ad-hocs carry a YYMMDD- filename prefix, so the ADHOC-* glob did not match them. They still derive from the forge, so they are live records rather than dead files. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006 --- workplans/archived/260707-ADHOC-2026-07-07.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/workplans/archived/260707-ADHOC-2026-07-07.md b/workplans/archived/260707-ADHOC-2026-07-07.md index d2929fb..aadfbbd 100644 --- a/workplans/archived/260707-ADHOC-2026-07-07.md +++ b/workplans/archived/260707-ADHOC-2026-07-07.md @@ -1,5 +1,5 @@ --- -id: ADHOC-2026-07-07 +id: WARDEN-WP-ADHOC-2026-07-07 type: workplan title: "Ad Hoc Tasks — 2026-07-07" domain: infotech @@ -9,7 +9,6 @@ owner: grok topic_slug: custodian created: "2026-07-07" updated: "2026-07-07" -state_hub_workstream_id: "2e8bc783-2e37-4b86-a691-177b18329783" --- > **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`). @@ -19,10 +18,9 @@ state_hub_workstream_id: "2e8bc783-2e37-4b86-a691-177b18329783" ### T01 — Roll out proxy pipe fix (be3b4a2) ```task -id: ADHOC-2026-07-07-T01 +id: WARDEN-WP-ADHOC-2026-07-07-T01 status: done priority: high -state_hub_task_id: "55b6de52-b958-4b72-94eb-4ba1b8da2629" ``` `warden access` failed on `reuse-surface-hub-write-token` because `shlex.split` From 347e47ce8e11d33c3840fd1ca2248c63c036956d Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 20:33:43 +0200 Subject: [PATCH 06/32] Note NetKingdom layering review in INTENT Records this repository's layer in the NetKingdom IT-security layer model (Taxonomy / Tooling / Engines / Staff) and what should change in this INTENT as a result. Links to the review that established the model: gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md The note flags pending adaptation only; the body is unchanged. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9 --- INTENT.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/INTENT.md b/INTENT.md index 0f0919e..adb4c81 100644 --- a/INTENT.md +++ b/INTENT.md @@ -1,5 +1,20 @@ # INTENT +> **NetKingdom layering review — 2026-08-28.** This repository's role was reviewed +> against the NetKingdom IT-security layer model: **Taxonomy → Tooling → Engines → +> Staff**, layered by determinism and by the kind of artifact each layer produces. +> Findings and the argument behind them: +> `gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md`. +> The model as currently stated is `gate-house/INTENT.md` § "Where Gate House Sits"; +> it is ruled to become a `net-kingdom/canon/standards/` standard, not yet written. +> +> The layer rule that binds every repository: **Staff never touches tooling +> directly. It acts only through engine APIs.** +> +> **This repository is Staff — interactive, non-deterministic; operational stewardship.** Add the layer label and the Staff invariant. Two substantive changes. (1) The **"NetKingdom Security Literacy"** section is evidence that the security curriculum had no owner; it now has one. Doctrine and curriculum move to gate-house, and this section becomes lane-specific runbooks that reference gate-house doctrine rather than restating it. The boundary is **doctrine versus runbook**. (2) The literacy and routing tables should add gate-house — currently every plane is listed and gate-house appears nowhere — routing doctrine and authority-model questions there, while continuing to route policy decisions to access-engine. Record the lane/rule demarcation as in ops-mason. +> +> *This note records what should change. The body below is not yet adapted.* + > This file captures **why this repository exists**, the **direction it is > moving toward**, and the **kind of system it is meant to become**. > It is intentionally **aspirational and stable**, not a description of From 15730bb65004554f8ae889d7f46fe1124235914a Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 21:21:08 +0200 Subject: [PATCH 07/32] Point layering note at the published standard The layer model is now published as net-kingdom/canon/standards/security-layer-model_v0.1.md (proposed) and ratified by gate-house GH-DEC-2026-001. The note previously said the standard was not yet written. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9 --- INTENT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/INTENT.md b/INTENT.md index adb4c81..caa3c68 100644 --- a/INTENT.md +++ b/INTENT.md @@ -5,8 +5,8 @@ > Staff**, layered by determinism and by the kind of artifact each layer produces. > Findings and the argument behind them: > `gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md`. -> The model as currently stated is `gate-house/INTENT.md` § "Where Gate House Sits"; -> it is ruled to become a `net-kingdom/canon/standards/` standard, not yet written. +> The model is `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed), +> ratified by `gate-house/decisions/decisions.md` GH-DEC-2026-001. > > The layer rule that binds every repository: **Staff never touches tooling > directly. It acts only through engine APIs.** From 467635e84b99757336ee49d7f0dbf107607d0560 Mon Sep 17 00:00:00 2001 From: repo-manager Date: Fri, 28 Aug 2026 21:30:28 +0200 Subject: [PATCH 08/32] repo.work.create_intake WARDEN-IN-0001 correlation_id: 65d40cdd-5894-440e-9c95-c6bcfe259b66 reason: Request assent for GH-DEC-2026-001 boundaries source: repo-manager Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9 --- intakes/intakes.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 intakes/intakes.md diff --git a/intakes/intakes.md b/intakes/intakes.md new file mode 100644 index 0000000..a7f4472 --- /dev/null +++ b/intakes/intakes.md @@ -0,0 +1,35 @@ +# Intake records + +## WARDEN-IN-0001 — Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule demarcation + +```yaml +id: WARDEN-IN-0001 +kind: intake +title: 'Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule + demarcation' +status: open +origin: cross-repo +origin_ref: gate-house GH-DEC-2026-001 +priority: medium +owner: ops-warden +requested_by: gate-house +standard: net-kingdom/canon/standards/security-layer-model_v0.1.md +description: 'gate-house asks ops-warden to assent to three boundary items. (1) ops-warden + is Staff, bound by the rule that Staff acts only through Engine APIs and never touches + Tooling directly (standard section 5). (2) Doctrine versus runbook: the NetKingdom + Security Literacy section in ops-warden INTENT is evidence the security curriculum + had no owner; it now has one in gate-house. Proposal is that doctrine and curriculum + move to gate-house and that section becomes lane-specific runbooks referencing gate-house + doctrine rather than restating it. ops-warden keeps the lanes it stewards and everything + operational about them. (3) The access lane/rule demarcation, normative in standard + section 8: ops-warden and ops-mason own access lanes — how a worker reaches a host; + access-engine owns access rules — whether they may. This demarcation is the condition + attached to renaming flex-auth to access-engine, so ops-warden effectively holds + a veto on that name. Also requested: add gate-house to the Security Literacy and + routing tables — currently every plane is listed and gate-house appears nowhere + — routing doctrine and authority-model questions there while continuing to route + policy decisions to access-engine. If moving the curriculum out leaves ops-warden + unable to instruct its own workers, say so; the boundary is wrong if it does.' +created: '2026-08-28T19:30:28.087109Z' +updated: '2026-08-28T19:30:28.087109Z' +``` From 85d3078bae0b624b364a819d6903ab6307fbff49 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 21:35:57 +0200 Subject: [PATCH 09/32] Refresh work-record index Regenerated by fix-consistency; adds the inbound assent intake. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9 --- WORK-RECORDS.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 0bc6497..9b8146f 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -8,10 +8,10 @@ | Kind | ID | Status | Lane | Source | | --- | --- | --- | --- | --- | -| workplan | ADHOC-2026-06-27 | finished | — | workplans/ADHOC-2026-06-27.md | -| workplan | ADHOC-2026-06-29 | finished | — | workplans/ADHOC-2026-06-29.md | -| workplan | ADHOC-2026-08-11 | finished | — | workplans/ADHOC-2026-08-11.md | -| workplan | ADHOC-2026-08-17 | finished | — | workplans/ADHOC-2026-08-17.md | +| workplan | WARDEN-WP-ADHOC-2026-06-27 | finished | — | workplans/ADHOC-2026-06-27.md | +| workplan | WARDEN-WP-ADHOC-2026-06-29 | finished | — | workplans/ADHOC-2026-06-29.md | +| workplan | WARDEN-WP-ADHOC-2026-08-11 | finished | — | workplans/ADHOC-2026-08-11.md | +| workplan | WARDEN-WP-ADHOC-2026-08-17 | finished | — | workplans/ADHOC-2026-08-17.md | | workplan | WARDEN-WP-0016 | finished | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md | | workplan | WARDEN-WP-0017 | finished | — | workplans/WARDEN-WP-0017-access-front-door-discoverability.md | | workplan | WARDEN-WP-0018 | finished | — | workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md | @@ -30,15 +30,15 @@ | workplan | WARDEN-WP-0031 | finished | — | workplans/WARDEN-WP-0031-policy-caller-identity.md | | workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md | | workplan | WARDEN-WP-0033 | active | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | -| task | ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md | -| task | ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md | -| task | ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md | -| task | ADHOC-2026-08-11-T02 | done | — | workplans/ADHOC-2026-08-11.md | -| task | ADHOC-2026-08-11-T03 | done | — | workplans/ADHOC-2026-08-11.md | -| task | ADHOC-2026-08-17-T01 | done | — | workplans/ADHOC-2026-08-17.md | -| task | ADHOC-2026-08-17-T02 | done | — | workplans/ADHOC-2026-08-17.md | -| task | ADHOC-2026-08-17-T03 | done | — | workplans/ADHOC-2026-08-17.md | -| task | ADHOC-2026-08-17-T04 | done | — | workplans/ADHOC-2026-08-17.md | +| task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md | +| task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md | +| task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md | +| task | WARDEN-WP-ADHOC-2026-08-11-T02 | done | — | workplans/ADHOC-2026-08-11.md | +| task | WARDEN-WP-ADHOC-2026-08-11-T03 | done | — | workplans/ADHOC-2026-08-11.md | +| task | WARDEN-WP-ADHOC-2026-08-17-T01 | done | — | workplans/ADHOC-2026-08-17.md | +| task | WARDEN-WP-ADHOC-2026-08-17-T02 | done | — | workplans/ADHOC-2026-08-17.md | +| task | WARDEN-WP-ADHOC-2026-08-17-T03 | done | — | workplans/ADHOC-2026-08-17.md | +| task | WARDEN-WP-ADHOC-2026-08-17-T04 | done | — | workplans/ADHOC-2026-08-17.md | | task | WARDEN-WP-0016-T01 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md | | task | WARDEN-WP-0016-T02 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md | | task | WARDEN-WP-0016-T03 | done | — | workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md | @@ -129,3 +129,4 @@ | task | WARDEN-WP-0033-T04 | wait | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | +| intake | WARDEN-IN-0001 | open | — | intakes/intakes.md | From 70d8b503f04dd0366ea2193d6efaf262ad129de7 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 21:47:44 +0200 Subject: [PATCH 10/32] Assent to the NetKingdom security layer model (WARDEN-IN-0001) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gate-house asked ops-warden to assent to three boundary items ratified in GH-DEC-2026-001. All three are assented in ADR-0010. Staff: accepted. Grepping section 5 as it invites turned up a real non-conformance — src/warden/vault.py is a direct OpenBao client performing a write, and so is `warden desk`'s `bao kv put`. Section 5's only escape hatch is read-only diagnostics, which does not cover a signing write, so both are declared in INTENT.md as an engine gap with intended owner secrets-engine and the blocker "no engine exposes an SSH-CA surface" — ADR-0003 turned inward rather than an exemption argued for. taint.py is metadata-only and declared under the read-only allowance; `warden access` proxies run under the caller's identity and supply no authority of their own. Doctrine versus runbook: accepted. NetKingdom Security Literacy becomes a lane routing runbook that references gate-house doctrine instead of restating it. It had also become a prose second source for registry/routing/catalog.yaml, which ADR-0001 already rules against. Lane versus rule: assented unconditionally, and the access-engine veto is not exercised. One request on sequencing only — a window where both names resolve. gate-house added to the routing tables in INTENT.md and SCOPE.md. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- .claude/rules/architecture.md | 2 + .repo-manager/index.json | 2215 +++++++++++++++++ INTENT.md | 85 +- SCOPE.md | 4 +- docs/adr/ADR-0010-ops-warden-is-staff.md | 109 + docs/adr/README.md | 1 + .../2026-08-28-security-layer-model-assent.md | 171 ++ intakes/intakes.md | 23 +- 8 files changed, 2579 insertions(+), 31 deletions(-) create mode 100644 .repo-manager/index.json create mode 100644 docs/adr/ADR-0010-ops-warden-is-staff.md create mode 100644 history/2026-08-28-security-layer-model-assent.md diff --git a/.claude/rules/architecture.md b/.claude/rules/architecture.md index 6f6cde3..ee357fb 100644 --- a/.claude/rules/architecture.md +++ b/.claude/rules/architecture.md @@ -16,6 +16,8 @@ distinction that matters here. | `ADR-0006` | Enforcement is zone-scoped, never a global flag | | `ADR-0007` | Build-stage permissiveness stops at credential disclosure; every lane carries an explicit `risk` grade | | `ADR-0008` | A lane's risk grade covers every field its path discloses, not just the field it is named after | +| `ADR-0009` | Adopt security-zones v0.1 as a consumer; membership is compiled, never inferred | +| `ADR-0010` | ops-warden is Staff: it owns access lanes, never access rules; doctrine belongs to gate-house | ### Owned versus inherited — check `owner:` before changing anything diff --git a/.repo-manager/index.json b/.repo-manager/index.json new file mode 100644 index 0000000..a0e6bd2 --- /dev/null +++ b/.repo-manager/index.json @@ -0,0 +1,2215 @@ +{ + "schema": "repo_manager.index.v1", + "slug": "layer-model-assent", + "repo_root": "/home/worsch/ops-warden", + "head_sha": "467635e84b99757336ee49d7f0dbf107607d0560", + "observed_at": "2026-08-28T19:30:29.828983Z", + "source_fingerprint": "7dfae4f3d33f6a9503a2c7326b925efb378613e772b39c4dd9b0640a35b85654", + "source_files": [ + ".repo-classification.yaml", + "INTENT.md", + "intakes/intakes.md", + "workplans/ADHOC-2026-06-27.md", + "workplans/ADHOC-2026-06-29.md", + "workplans/ADHOC-2026-08-11.md", + "workplans/ADHOC-2026-08-17.md", + "workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md", + "workplans/WARDEN-WP-0017-access-front-door-discoverability.md", + "workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md", + "workplans/WARDEN-WP-0019-route-to-secrets-engine.md", + "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "workplans/WARDEN-WP-0022-audit-trail-and-activity.md", + "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "workplans/WARDEN-WP-0027-credential-governance-lockdown.md", + "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "workplans/WARDEN-WP-0030-delegation-register.md", + "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "workplans/WARDEN-WP-0032-security-zones.md", + "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "workplans/archived/260515-WARDEN-WP-0002-correctness-and-completeness.md", + "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "workplans/archived/260617-WARDEN-WP-0004-repo-hygiene-and-hub-sync.md", + "workplans/archived/260617-WARDEN-WP-0005-openbao-doc-alignment.md", + "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "workplans/archived/260617-WARDEN-WP-0007-policy-gate-and-production-verify.md", + "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "workplans/archived/260623-WARDEN-WP-0009-flex-auth-policy-gate-production.md", + "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "workplans/archived/260707-ADHOC-2026-07-07.md" + ], + "work_records": [ + { + "kind": "workplan", + "id": "WARDEN-WP-ADHOC-2026-06-27", + "status": "finished", + "title": "Ad Hoc Tasks \u2014 2026-06-27", + "source_path": "workplans/ADHOC-2026-06-27.md", + "uuid": null, + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-06-27-T01", + "status": "done", + "title": "T01 \u2014 Fix stale `warden` CLI install + make it usable outside the repo", + "source_path": "workplans/ADHOC-2026-06-27.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-06-27", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-ADHOC-2026-06-29", + "status": "finished", + "title": "Ad Hoc Tasks \u2014 2026-06-29", + "source_path": "workplans/ADHOC-2026-06-29.md", + "uuid": null, + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-06-29-T01", + "status": "done", + "title": "T01 \u2014 Joint-smoke mode for the deployed flex-auth (assist FLEX-WP-0007 T4)", + "source_path": "workplans/ADHOC-2026-06-29.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-06-29", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-ADHOC-2026-08-11", + "status": "finished", + "title": "Ad Hoc Tasks \u2014 2026-08-11", + "source_path": "workplans/ADHOC-2026-08-11.md", + "uuid": null, + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-11-T01", + "status": "done", + "title": "T01 \u2014 Repair stale `rapp-qonto-keycape-client` wiki anchor (restore green routing suite)", + "source_path": "workplans/ADHOC-2026-08-11.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-11", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-11-T02", + "status": "done", + "title": "T02 \u2014 Triage the stale ops-warden inbox (11 unread, C-28/C-29)", + "source_path": "workplans/ADHOC-2026-08-11.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-11", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-11-T03", + "status": "done", + "title": "T03 \u2014 warden-sign AppRole: PARKED pending WP-0027 break-glass + ops-bridge cutover", + "source_path": "workplans/ADHOC-2026-08-11.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-11", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-ADHOC-2026-08-17", + "status": "finished", + "title": "Ad Hoc Tasks \u2014 2026-08-17", + "source_path": "workplans/ADHOC-2026-08-17.md", + "uuid": null, + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-17-T01", + "status": "done", + "title": "T01 \u2014 Answer flex-auth: how should `/v1/check` authenticate its callers?", + "source_path": "workplans/ADHOC-2026-08-17.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-17", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-17-T02", + "status": "done", + "title": "T02 \u2014 user-engine: USER_ENGINE_PROXY_SECRET stays railiance-apps; record consumer-only", + "source_path": "workplans/ADHOC-2026-08-17.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-17", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-17-T03", + "status": "done", + "title": "T03 \u2014 key-cape: `rapp-qonto-keycape-client` interim accepted; refresh the blocker", + "source_path": "workplans/ADHOC-2026-08-17.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-17", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-08-17-T04", + "status": "done", + "title": "T04 \u2014 Session hygiene", + "source_path": "workplans/ADHOC-2026-08-17.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-08-17", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0016", + "status": "finished", + "title": "ops-bridge cert_command pilot \u2014 readiness gate + handoff", + "source_path": "workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md", + "uuid": "a56da8db-38bc-4bbe-8671-823360ec9245", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0016-T01", + "status": "done", + "title": "T1 \u2014 Read-only `cert_command` readiness preflight", + "source_path": "workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md", + "uuid": "fea84495-dbec-480a-b42b-90e39f414b78", + "parent_id": "WARDEN-WP-0016", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0016-T02", + "status": "done", + "title": "T2 \u2014 Offline cert_command contract smoke", + "source_path": "workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md", + "uuid": "e34ae1a8-2ba9-4324-8d1a-005d61dae478", + "parent_id": "WARDEN-WP-0016", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0016-T03", + "status": "done", + "title": "T3 \u2014 Playbook gate + ops-bridge handoff", + "source_path": "workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md", + "uuid": "330e01f4-4927-4280-b0e0-49d35b4416d6", + "parent_id": "WARDEN-WP-0016", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0016-T04", + "status": "done", + "title": "T4 \u2014 INTENT/SCOPE alignment", + "source_path": "workplans/WARDEN-WP-0016-ops-bridge-tunnel-cert-pilot.md", + "uuid": "4726f5bb-4ffd-484f-8674-91ee5658434f", + "parent_id": "WARDEN-WP-0016", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0017", + "status": "finished", + "title": "Access front-door discoverability \u2014 stop reading as SSH-only", + "source_path": "workplans/WARDEN-WP-0017-access-front-door-discoverability.md", + "uuid": "cf8b392e-7624-4585-8935-a85e29202935", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0017-T01", + "status": "done", + "title": "T1 \u2014 CLI discoverability: route role + access framing", + "source_path": "workplans/WARDEN-WP-0017-access-front-door-discoverability.md", + "uuid": "6e98df42-b5b4-49f8-a444-3c6346c8abd7", + "parent_id": "WARDEN-WP-0017", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0017-T02", + "status": "done", + "title": "T2 \u2014 Agent rule + SCOPE reframe", + "source_path": "workplans/WARDEN-WP-0017-access-front-door-discoverability.md", + "uuid": "6e2a7067-1afc-4f38-8d99-4d5c36a4661c", + "parent_id": "WARDEN-WP-0017", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0017-T03", + "status": "done", + "title": "T3 \u2014 Federated capability registration", + "source_path": "workplans/WARDEN-WP-0017-access-front-door-discoverability.md", + "uuid": "7199625b-e78e-4495-8ca0-076100ae9f08", + "parent_id": "WARDEN-WP-0017", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0018", + "status": "finished", + "title": "Activate whynot-design npm publish lane + resolvable readiness flag", + "source_path": "workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md", + "uuid": "1256aca2-5979-4d21-818e-0de42c5d811b", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0018-T01", + "status": "done", + "title": "T1 \u2014 Concrete catalog entry + playbook", + "source_path": "workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md", + "uuid": "189d0883-22b9-42dc-bda0-89460509a87d", + "parent_id": "WARDEN-WP-0018", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0018-T02", + "status": "done", + "title": "T2 \u2014 `resolvable` readiness flag + stable-id resolution", + "source_path": "workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md", + "uuid": "b5dc1013-5334-43ff-afd6-1f99d521358f", + "parent_id": "WARDEN-WP-0018", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0018-T03", + "status": "done", + "title": "T3 \u2014 Close the loop", + "source_path": "workplans/WARDEN-WP-0018-whynot-design-npm-lane-activation.md", + "uuid": "95b00ef8-477a-4f0d-bd71-6154fba401f5", + "parent_id": "WARDEN-WP-0018", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0019", + "status": "finished", + "title": "Route secret-exec lanes to secrets-engine (route-primary, proxy fallback)", + "source_path": "workplans/WARDEN-WP-0019-route-to-secrets-engine.md", + "uuid": "5e49abb6-497f-4640-a484-2da5f39a7c4e", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0019-T01", + "status": "done", + "title": "T1 \u2014 Catalog + CLI: surface the owner-native exec front door", + "source_path": "workplans/WARDEN-WP-0019-route-to-secrets-engine.md", + "uuid": "ea153605-7a14-4db7-8bce-d780ea143f8a", + "parent_id": "WARDEN-WP-0019", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0019-T02", + "status": "done", + "title": "T2 \u2014 Agent rule, SCOPE, playbook", + "source_path": "workplans/WARDEN-WP-0019-route-to-secrets-engine.md", + "uuid": "96059b8a-8938-4763-b3d0-cc5a0eb2465c", + "parent_id": "WARDEN-WP-0019", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0020", + "status": "finished", + "title": "ops-warden worker \u2014 autonomous coordination via llm-connect", + "source_path": "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "uuid": "c906ba1d-f991-4fb0-b113-59432ddf87c0", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0020-T01", + "status": "done", + "title": "T1 \u2014 Worker scaffold (llm-connect-independent, safe)", + "source_path": "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "uuid": "979c2d9b-0803-442f-aa2e-acb02bac07e9", + "parent_id": "WARDEN-WP-0020", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0020-T02", + "status": "done", + "title": "T2 \u2014 llm-connect brain", + "source_path": "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "uuid": "52d281b2-7d48-44f5-b77e-80e3ed500b5f", + "parent_id": "WARDEN-WP-0020", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0020-T03", + "status": "done", + "title": "T3 \u2014 Action dispatch + guardrails (full-auto in-scope)", + "source_path": "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "uuid": "3a71965e-42d5-4258-9761-aced804c88e7", + "parent_id": "WARDEN-WP-0020", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0020-T04", + "status": "done", + "title": "T4 \u2014 Scheduled trigger", + "source_path": "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "uuid": "7f77ea6d-c281-42c5-ad25-2a0bb9fd68de", + "parent_id": "WARDEN-WP-0020", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0020-T05", + "status": "done", + "title": "T5 \u2014 Docs / SCOPE / INTENT", + "source_path": "workplans/WARDEN-WP-0020-ops-warden-worker.md", + "uuid": "6e7ae317-7f8b-468a-bb5c-b08093ed43a0", + "parent_id": "WARDEN-WP-0020", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0021", + "status": "finished", + "title": "Enable the scheduled worker tick \u2014 conservative inbox triage, unattended", + "source_path": "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "uuid": "8c487014-b630-4016-a4f0-31b971a473d2", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0021-T01", + "status": "done", + "title": "T1 \u2014 Scheduler install + enablement + kill switch", + "source_path": "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "uuid": "10451fe6-7fab-4ae0-8494-e6cfdfbcf8cf", + "parent_id": "WARDEN-WP-0021", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0021-T02", + "status": "done", + "title": "T2 \u2014 Scheduled-run robustness (graceful degradation)", + "source_path": "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "uuid": "1f35f816-1af5-46ff-b48c-1715f3ae5784", + "parent_id": "WARDEN-WP-0021", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0021-T03", + "status": "done", + "title": "T3 \u2014 Operator visibility (see new drafts)", + "source_path": "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "uuid": "3c7f6423-8db0-4bc6-b67d-078d9d929c6d", + "parent_id": "WARDEN-WP-0021", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0021-T04", + "status": "done", + "title": "T4 \u2014 Review\u2192send loop (`warden worker approve`)", + "source_path": "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "uuid": "dabc9fc0-abb1-4e9d-b87e-5f0c5950693c", + "parent_id": "WARDEN-WP-0021", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0021-T05", + "status": "done", + "title": "T5 \u2014 Runbook + SCOPE", + "source_path": "workplans/WARDEN-WP-0021-enable-scheduled-worker-tick.md", + "uuid": "9915da96-1b33-4d0f-b752-408ea8d43333", + "parent_id": "WARDEN-WP-0021", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0022", + "status": "finished", + "title": "Audit trail + `warden activity` \u2014 one place to see what ops-warden did", + "source_path": "workplans/WARDEN-WP-0022-audit-trail-and-activity.md", + "uuid": "fc8afa28-68a7-4250-a19e-9754829f0cd5", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0022-T01", + "status": "done", + "title": "T1 \u2014 Unified audit event log", + "source_path": "workplans/WARDEN-WP-0022-audit-trail-and-activity.md", + "uuid": "7f8f768a-4c62-4096-bad8-912cea0f35a7", + "parent_id": "WARDEN-WP-0022", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0022-T02", + "status": "done", + "title": "T2 \u2014 Instrument the actions", + "source_path": "workplans/WARDEN-WP-0022-audit-trail-and-activity.md", + "uuid": "e7ae4037-ca79-4557-81f0-bfb8478ff647", + "parent_id": "WARDEN-WP-0022", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0022-T03", + "status": "done", + "title": "T3 \u2014 `warden activity` command", + "source_path": "workplans/WARDEN-WP-0022-audit-trail-and-activity.md", + "uuid": "4439bdd8-1461-47df-8b0b-048df7384a68", + "parent_id": "WARDEN-WP-0022", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0022-T04", + "status": "done", + "title": "T4 \u2014 Tests, runbook, SCOPE", + "source_path": "workplans/WARDEN-WP-0022-audit-trail-and-activity.md", + "uuid": "bdfb8703-7a79-43e7-913b-19d61722f164", + "parent_id": "WARDEN-WP-0022", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0023", + "status": "finished", + "title": "INTENT\u2013SCOPE Alignment Closeout", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "7bad1ec4-a7c2-4980-b8f9-49a7f5408574", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T01", + "status": "done", + "title": "T01 \u2014 Persist gap analysis", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "52485c90-87fe-40b1-9db5-a51ebb957dd5", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T02", + "status": "done", + "title": "T02 \u2014 Refresh INTENT.md", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "9a9b3631-8948-45af-ace1-c19ee74ace4d", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T03", + "status": "done", + "title": "T03 \u2014 Production integration coordination pack", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "26f23798-494b-45fc-baa8-af27bdffa038", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T04", + "status": "done", + "title": "T04 \u2014 `warden sign` broker hint when `VAULT_TOKEN` unset", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "85e324f9-273d-4740-a202-9c4e8fb122ae", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T05", + "status": "done", + "title": "T05 \u2014 Catalog draft-lane promotion checklist", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "82608692-2845-41e1-a498-90ed53780748", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T06", + "status": "done", + "title": "T06 \u2014 SCOPE and workplan consistency", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "79ca7b9a-554e-4952-9393-a29b100f6190", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0023-T07", + "status": "done", + "title": "T07 \u2014 Sequence WP-0022 audit implementation", + "source_path": "workplans/WARDEN-WP-0023-intent-scope-alignment-closeout.md", + "uuid": "1f3b3b33-974e-49bf-be4a-9d50b702c2a4", + "parent_id": "WARDEN-WP-0023", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0024", + "status": "finished", + "title": "Experiential Memory Across Worker, Agent Sessions, And OpenRouter", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "5d9fafb3-f9b6-43bf-b259-5f5301daa2e9", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T01", + "status": "done", + "title": "T01 - Canonical memory store and discovery", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "6305f1bc-c016-4298-adc2-a07d52b6aca5", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T02", + "status": "done", + "title": "T02 - Session recording hooks in CLI commands", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "242a4d9a-5375-4df8-8d43-063b0491d202", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T03", + "status": "done", + "title": "T03 - Memory-aware worker tick", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "176fcae1-e4e5-481f-9a83-e9a7000fac1a", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T04", + "status": "done", + "title": "T04 - Agent session activation helper", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "16501557-6cde-44ea-bc6f-1726cb7ec070", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T05", + "status": "done", + "title": "T05 - Cross-runtime continuity", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "55ae679c-c08f-4afd-8646-9f5f3019f86e", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T06", + "status": "done", + "title": "T06 - OpenRouter efficiency layer", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "fc2dffcf-7184-4f3d-8653-d26dc18a9afc", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0024-T07", + "status": "done", + "title": "T07 - Operator and agent documentation", + "source_path": "workplans/WARDEN-WP-0024-experiential-memory-and-agent-sessions.md", + "uuid": "ca2aaf23-833f-49a6-a49b-a0b659208f5f", + "parent_id": "WARDEN-WP-0024", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0025", + "status": "finished", + "title": "Forgejo admin PAT OpenBao lane (CCR-2026-0006)", + "source_path": "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "uuid": "70c11222-d8e7-5936-99f7-7d626a4a5deb", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0025-T01", + "status": "done", + "title": "T1 \u2014 Draft CCR + policy metadata", + "source_path": "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "uuid": "2c288bf0-b39c-5f5b-ad25-eed3da826dc3", + "parent_id": "WARDEN-WP-0025", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0025-T02", + "status": "done", + "title": "T2 \u2014 ops-warden catalog + playbook", + "source_path": "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "uuid": "01b81595-f9e5-5746-b0dd-2075189cb00e", + "parent_id": "WARDEN-WP-0025", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0025-T03", + "status": "done", + "title": "T3 \u2014 Platform-operator approval + metadata apply", + "source_path": "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "uuid": "279b74d7-3240-5ca0-897d-b1ddffd23c4e", + "parent_id": "WARDEN-WP-0025", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0025-T04", + "status": "done", + "title": "T4 \u2014 Attended PAT provision + verification", + "source_path": "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "uuid": "4e21232c-62a1-5115-acce-edfbcfa84e48", + "parent_id": "WARDEN-WP-0025", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0025-T05", + "status": "done", + "title": "T5 \u2014 Notify downstream consumers", + "source_path": "workplans/WARDEN-WP-0025-forgejo-admin-api-token-lane.md", + "uuid": "f8c7c70b-b9b6-5980-a25b-7f11033b81a2", + "parent_id": "WARDEN-WP-0025", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0026", + "status": "finished", + "title": "Credential disclosure hygiene + rotation guidance (Strand A)", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "331c7620-bd34-5acd-9135-591985b568e5", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T01", + "status": "done", + "title": "Task: Capabilities-based lane verification", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "1cb22a40-b7c6-560a-a805-7766a5786dcc", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T02", + "status": "done", + "title": "Task: Safe access transport (no stdout values)", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "bcb7da96-0a28-5484-bf3e-06e97acf5873", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T03", + "status": "done", + "title": "Task: Masking display filter (defense-in-depth)", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "d90b0628-fa1d-527d-99c3-28a7ed933e52", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T04", + "status": "done", + "title": "Task: Agent read-boundary on high-risk lanes", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "827fa67d-5f69-5fac-bdce-9903b1b909fb", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T05", + "status": "done", + "title": "Task: EXPOSED taint convention", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "09ef8727-31da-59ac-aac7-2d47924569fe", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T06", + "status": "done", + "title": "Task: Rotation / re-establishment guidance registry", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "a2e1544e-e501-57eb-a40e-9a2147cef12a", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0026-T07", + "status": "done", + "title": "Task: Incident lessons + first worked lane (CCR-2026-0004)", + "source_path": "workplans/WARDEN-WP-0026-credential-disclosure-hygiene.md", + "uuid": "62d8286f-7954-52a8-bce6-6a16072e5246", + "parent_id": "WARDEN-WP-0026", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0027", + "status": "active", + "title": "Tamper-resistant credential governance + mass rotation/lockdown (Strand B)", + "source_path": "workplans/WARDEN-WP-0027-credential-governance-lockdown.md", + "uuid": "21528e8d-a049-523d-9ae1-da7a27cb8bbf", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0027-T01", + "status": "cancel", + "title": "Task: Executable mass rotation driver", + "source_path": "workplans/WARDEN-WP-0027-credential-governance-lockdown.md", + "uuid": "b5691939-9d84-5115-9618-0f8839010d14", + "parent_id": "WARDEN-WP-0027", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0027-T02", + "status": "progress", + "title": "Task: Graded lockdown / break-glass with explicit trust-root", + "source_path": "workplans/WARDEN-WP-0027-credential-governance-lockdown.md", + "uuid": "cae498ee-6307-5d32-9f1b-a471cfcc2536", + "parent_id": "WARDEN-WP-0027", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0027-T03", + "status": "cancel", + "title": "Task: Tamper-evident policy governance + reconcile", + "source_path": "workplans/WARDEN-WP-0027-credential-governance-lockdown.md", + "uuid": "7dbedcdc-dd5a-551c-bff1-0702fea0a9cf", + "parent_id": "WARDEN-WP-0027", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0028", + "status": "finished", + "title": "Tenant secret custody \u2014 NetKingdom pattern for client/tenant secrets", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "6b66228a-199a-5b85-b5e2-a7afeaab903b", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T01", + "status": "done", + "title": "T01 \u2014 Canon note: tenant secret path + ownership", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "9982a884-7a50-593e-861e-cc8d2343a0ba", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T02", + "status": "done", + "title": "T02 \u2014 Align binky-control integration plan to production path", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "d7d7ee9d-2ecf-5492-8a13-0b747d899456", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T03", + "status": "done", + "title": "T03 \u2014 Enable `tenants` mount + extend CCR tooling + policy/role", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "e0b675ef-9c08-5f89-8f13-ef4249ca2364", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T04", + "status": "done", + "title": "T04 \u2014 ops-warden catalog + playbook + rotation", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "9405b13d-4045-519b-8e3f-79a891323397", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T05", + "status": "done", + "title": "T05 \u2014 Founder provision (Red) + first scan evidence", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "f17bba95-bc53-5c2a-8b44-7df9e42b2341", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T06", + "status": "done", + "title": "T06 \u2014 Generalize \"tenant secret onboarding\" playbook", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "76bd01a0-1d03-5ff9-8f59-a1b44763979d", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0028-T07", + "status": "done", + "title": "T07 \u2014 secrets-engine alignment decision (record only)", + "source_path": "workplans/WARDEN-WP-0028-tenant-secret-custody.md", + "uuid": "46c8f8a9-3bbe-568f-8a45-07b690874273", + "parent_id": "WARDEN-WP-0028", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0029", + "status": "finished", + "title": "Policy front door: posture-aware access planning + founder interaction surface", + "source_path": "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "uuid": "bbb3d9ec-d88d-5088-b4c0-55bfba0a10cf", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0029-T02", + "status": "done", + "title": "T02 \u2014 Declared organization posture (build phase)", + "source_path": "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "uuid": "6c213024-6601-5116-b52f-d6711dc0587d", + "parent_id": "WARDEN-WP-0029", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0029-T05", + "status": "done", + "title": "T05 \u2014 Catalog freshness + agent guidance", + "source_path": "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "uuid": "c82d8745-4af4-5b89-ab49-06d8a902e592", + "parent_id": "WARDEN-WP-0029", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0029-T01", + "status": "done", + "title": "T01 \u2014 `warden plan` decision front door", + "source_path": "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "uuid": "34db38fa-cb99-5ced-9a12-85176a7f2b44", + "parent_id": "WARDEN-WP-0029", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0029-T04", + "status": "done", + "title": "T04 \u2014 Retire file-drop patterns from playbooks", + "source_path": "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "uuid": "717f57da-fbc4-5a4d-9f8c-c1c3fa75e0ee", + "parent_id": "WARDEN-WP-0029", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0029-T03", + "status": "done", + "title": "T03 \u2014 Founder interaction surface (local web approval page)", + "source_path": "workplans/WARDEN-WP-0029-policy-front-door-and-founder-surface.md", + "uuid": "47c781d2-768b-5777-b971-b5227fe41f5c", + "parent_id": "WARDEN-WP-0029", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0030", + "status": "finished", + "title": "Delegation register \u2014 make gap-covering interim, visible, and retirable", + "source_path": "workplans/WARDEN-WP-0030-delegation-register.md", + "uuid": "da3367d5-890c-52c6-aa54-1bdd0f277342", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0030-T01", + "status": "done", + "title": "T01 \u2014 Interim custodianship doctrine", + "source_path": "workplans/WARDEN-WP-0030-delegation-register.md", + "uuid": "6f88876e-434c-5718-9c8d-ec6bf64ae4aa", + "parent_id": "WARDEN-WP-0030", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0030-T02", + "status": "done", + "title": "T02 \u2014 `delegation:` metadata + backfill", + "source_path": "workplans/WARDEN-WP-0030-delegation-register.md", + "uuid": "b02e8da6-57ca-5f9f-9405-9b0624498e3a", + "parent_id": "WARDEN-WP-0030", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0030-T03", + "status": "done", + "title": "T03 \u2014 `warden route gaps` + conformance test", + "source_path": "workplans/WARDEN-WP-0030-delegation-register.md", + "uuid": "f5e0f5af-45d8-5c82-9de2-d640d7d0a1f7", + "parent_id": "WARDEN-WP-0030", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0030-T04", + "status": "done", + "title": "T04 \u2014 Promotion gate", + "source_path": "workplans/WARDEN-WP-0030-delegation-register.md", + "uuid": "b808a749-e1d7-5708-aabf-91732dd76abd", + "parent_id": "WARDEN-WP-0030", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0030-T05", + "status": "done", + "title": "T05 \u2014 Publish the register to the owners", + "source_path": "workplans/WARDEN-WP-0030-delegation-register.md", + "uuid": "b0188ec4-4860-57c8-8030-45904a132190", + "parent_id": "WARDEN-WP-0030", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0031", + "status": "finished", + "title": "Calling-side identity for flex-auth, so policy.enabled can flip", + "source_path": "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "uuid": "739bad25-2345-5f4f-aaa3-cc4cd8c71f6c", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0031-T01", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "uuid": "d3b7c701-bcdd-53f9-aa72-6f289bf5909b", + "parent_id": "WARDEN-WP-0031", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0031-T02", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "uuid": "b77b3c80-a168-564a-9b7f-3063aefc3c2e", + "parent_id": "WARDEN-WP-0031", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0031-T03", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "uuid": "4245155e-6c71-5425-b574-11f61e1d4461", + "parent_id": "WARDEN-WP-0031", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0031-T04", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "uuid": "f3834af7-2a08-51dd-bf31-8ce8550de699", + "parent_id": "WARDEN-WP-0031", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0031-T05", + "status": "cancel", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0031-policy-caller-identity.md", + "uuid": "3f6dc609-89db-52eb-a6f9-d2fd271be821", + "parent_id": "WARDEN-WP-0031", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0032", + "status": "finished", + "title": "Adopt security zones as a consumer \u2014 retire the global policy.enabled", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "38c6a5f3-fb0d-5230-be85-f9e3ffc850f6", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T01", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "b03a5caa-0bb5-5cdd-bb99-32c694b0da29", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T02", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "b3f41c85-a293-58ad-ac27-9f8110c51266", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T03", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "d04a737b-ecdf-5747-ba25-20dadd99d3bc", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T04", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "c7879127-3dba-55c0-853c-a10775736873", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T05", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "1d968627-83f4-59cd-84ca-0f9f35e435ff", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T06", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "4294084c-bf3f-5aa6-b84d-5173121882ff", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0032-T07", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0032-security-zones.md", + "uuid": "6b4bbbed-2864-5fe9-82be-22ff9543f6f4", + "parent_id": "WARDEN-WP-0032", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0033", + "status": "active", + "title": "Native lane handoff \u2014 review secrets-engine's catalog admission, and fix what it exposed", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "4627d89b-4b00-562a-81e9-76e96f90fa7e", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0033-T01", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "154f2f03-387d-5fe6-a0f5-1929c46a2bd8", + "parent_id": "WARDEN-WP-0033", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0033-T02", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "6996d07f-63bb-5708-a171-68c4b1bbddde", + "parent_id": "WARDEN-WP-0033", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0033-T03", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "a736f983-94da-5a4a-aaf9-5114485518a6", + "parent_id": "WARDEN-WP-0033", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0033-T04", + "status": "wait", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "5acac140-a586-5db3-b231-bbf236710786", + "parent_id": "WARDEN-WP-0033", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0033-T05", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "75051d17-399b-5129-860b-ae00dae91c47", + "parent_id": "WARDEN-WP-0033", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0033-T06", + "status": "done", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "uuid": "94f77f5a-f919-5328-832c-ba1d24c6431b", + "parent_id": "WARDEN-WP-0033", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0001", + "status": "archived", + "title": "OpsWarden Initial Implementation", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "c3118cc6-adfb-428c-a9c6-edd0ee152ae6", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T1", + "status": "done", + "title": "T1 \u2014 Repository bootstrap", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "6d643e9d-5e97-4224-9d82-87267b5ba6bc", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T2", + "status": "done", + "title": "T2 \u2014 Models and config", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "c66fc65a-0b16-4ba2-9e70-a83d875572ec", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T3", + "status": "done", + "title": "T3 \u2014 LocalCA backend", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "a5a41e58-1c6d-42a9-9b11-2088f17c29b5", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T4", + "status": "done", + "title": "T4 \u2014 VaultCA backend", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "b2067ee6-c9ce-423b-9d60-0d28069fb304", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T5", + "status": "done", + "title": "T5 \u2014 Principals inventory", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "6d13f8cd-1850-44c9-b769-b21250348319", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T6", + "status": "done", + "title": "T6 \u2014 CLI commands", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "656a4615-92bb-4b5d-9406-e86d24fa15d0", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T7", + "status": "done", + "title": "T7 \u2014 Scorecard runner", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "7818bcc5-f40e-4793-b117-d36f653ffeed", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T8", + "status": "done", + "title": "T8 \u2014 ops-ssh-wrapper script", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "e9c28152-5785-4995-83a5-439985ed3db9", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T9", + "status": "done", + "title": "T9 \u2014 Tests", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "950139ab-cc17-4f1d-9a17-d5744e402ddf", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0001-T10", + "status": "done", + "title": "T10 \u2014 Documentation", + "source_path": "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", + "uuid": "271d6759-e359-41ce-80e4-76c574634a87", + "parent_id": "WARDEN-WP-0001", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0002", + "status": "archived", + "title": "OpsWarden Correctness and Operational Completeness", + "source_path": "workplans/archived/260515-WARDEN-WP-0002-correctness-and-completeness.md", + "uuid": "5a9fba2c-6161-49a4-a231-e750fa4ab572", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0002-T1", + "status": "done", + "title": "T1 \u2014 TTL max enforcement per ActorType", + "source_path": "workplans/archived/260515-WARDEN-WP-0002-correctness-and-completeness.md", + "uuid": "b0d0b5f7-a181-4590-be26-c48ae28cd964", + "parent_id": "WARDEN-WP-0002", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0002-T2", + "status": "done", + "title": "T2 \u2014 Stale cert cleanup command", + "source_path": "workplans/archived/260515-WARDEN-WP-0002-correctness-and-completeness.md", + "uuid": "aeeefbad-c0bd-4ae8-a3fe-9f72321b4caa", + "parent_id": "WARDEN-WP-0002", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0002-T3", + "status": "done", + "title": "T3 \u2014 Outgoing signatures log", + "source_path": "workplans/archived/260515-WARDEN-WP-0002-correctness-and-completeness.md", + "uuid": "0194d24f-a8fe-4f6d-88e6-addea3542c0e", + "parent_id": "WARDEN-WP-0002", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0003", + "status": "archived", + "title": "OpsWarden Test Coverage and Code Quality", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "cb2bbf3c-848a-4af6-ba64-8361e64cd4d7", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0003-T1", + "status": "done", + "title": "T1 \u2014 VaultCA tests", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "eff074ce-c027-4df5-8006-0990296592ac", + "parent_id": "WARDEN-WP-0003", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0003-T2", + "status": "done", + "title": "T2 \u2014 LocalCA.generate_keypair tests", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "ddfe5331-0a3b-4783-bdf4-f5ebcdf7965c", + "parent_id": "WARDEN-WP-0003", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0003-T3", + "status": "done", + "title": "T3 \u2014 CLI tests", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "040ce3a1-0efb-4816-a2d9-357162dd1612", + "parent_id": "WARDEN-WP-0003", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0003-T4", + "status": "done", + "title": "T4 \u2014 Real ssh-keygen integration test", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "434fb008-103f-410c-85fd-e77b33e61fe4", + "parent_id": "WARDEN-WP-0003", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0003-T5", + "status": "done", + "title": "T5 \u2014 File permissions enforcement (mode 600)", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "ac146fe6-d1fd-4186-91bd-6f098de72449", + "parent_id": "WARDEN-WP-0003", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0003-T6", + "status": "done", + "title": "T6 \u2014 warden status --state-dir override", + "source_path": "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", + "uuid": "1c9f1987-7b11-43c1-a5e3-c2fd8d1c1589", + "parent_id": "WARDEN-WP-0003", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0004", + "status": "archived", + "title": "OpsWarden Repo Hygiene and Hub Sync", + "source_path": "workplans/archived/260617-WARDEN-WP-0004-repo-hygiene-and-hub-sync.md", + "uuid": "3c4b6e68-550a-4fc6-a804-95f1f68936c3", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0004-T01", + "status": "done", + "title": "T1 \u2014 Update orientation docs", + "source_path": "workplans/archived/260617-WARDEN-WP-0004-repo-hygiene-and-hub-sync.md", + "uuid": "f9d3926c-8637-411c-a477-2960b754704c", + "parent_id": "WARDEN-WP-0004", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0004-T02", + "status": "done", + "title": "T2 \u2014 Fill agent rules", + "source_path": "workplans/archived/260617-WARDEN-WP-0004-repo-hygiene-and-hub-sync.md", + "uuid": "86c764a5-62fc-45fe-a8d2-332d6554a976", + "parent_id": "WARDEN-WP-0004", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0004-T03", + "status": "done", + "title": "T3 \u2014 Archive finished workplans", + "source_path": "workplans/archived/260617-WARDEN-WP-0004-repo-hygiene-and-hub-sync.md", + "uuid": "d3e54e63-ce98-4632-bc08-0e2667f19f12", + "parent_id": "WARDEN-WP-0004", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0004-T04", + "status": "done", + "title": "T4 \u2014 Sync State Hub", + "source_path": "workplans/archived/260617-WARDEN-WP-0004-repo-hygiene-and-hub-sync.md", + "uuid": "51729695-262f-4fe4-9c38-f99ee046d32a", + "parent_id": "WARDEN-WP-0004", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0005", + "status": "archived", + "title": "OpsWarden OpenBao-First Documentation Alignment", + "source_path": "workplans/archived/260617-WARDEN-WP-0005-openbao-doc-alignment.md", + "uuid": "57f6ebf8-0ef3-4686-9a73-3f9d38288be9", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0005-T01", + "status": "done", + "title": "T1 \u2014 OpsWardenConfig.md", + "source_path": "workplans/archived/260617-WARDEN-WP-0005-openbao-doc-alignment.md", + "uuid": "bbbc4dda-9634-4c04-86e5-94b96c021b43", + "parent_id": "WARDEN-WP-0005", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0005-T02", + "status": "done", + "title": "T2 \u2014 Cross-reference updates", + "source_path": "workplans/archived/260617-WARDEN-WP-0005-openbao-doc-alignment.md", + "uuid": "6391cb82-896e-405a-a59b-36640e6480ba", + "parent_id": "WARDEN-WP-0005", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0006", + "status": "archived", + "title": "NetKingdom Alignment and Operational Access Stewardship", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "a5c9f24b-1ad4-46da-bc8e-b99897f8e302", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T01", + "status": "done", + "title": "T1 \u2014 Credential routing runbook", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "ffc6a0c2-4312-4584-be7a-c8411cb01899", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T02", + "status": "done", + "title": "T2 \u2014 Actor inventory patterns", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "3816463d-7dfd-469d-9324-fd7880b50608", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T03", + "status": "done", + "title": "T3 \u2014 NetKingdom cross-links (ops-warden side)", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "f158366a-5746-48b8-acce-472dce8f925e", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T04", + "status": "done", + "title": "T4 \u2014 NetKingdom canon patch (coordination)", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "e40e4395-8f01-4f79-a539-d0de8e427321", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T05", + "status": "done", + "title": "T5 \u2014 OpenBao SSH engine operational checklist", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "a94e20a2-970b-4a0c-bd23-8510b841b938", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T06", + "status": "done", + "title": "T6 \u2014 Policy-gated signing design (design only)", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "b10a4b4d-bfa1-4f49-b6a5-f339f1e6a2e1", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0006-T07", + "status": "done", + "title": "T7 \u2014 Re-assess INTENT \u2194 SCOPE", + "source_path": "workplans/archived/260617-WARDEN-WP-0006-netkingdom-alignment-and-access-stewardship.md", + "uuid": "ef8b5c57-2343-4cfc-9fee-48db1e56f69a", + "parent_id": "WARDEN-WP-0006", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0007", + "status": "archived", + "title": "Policy Gate and Production OpenBao Verification", + "source_path": "workplans/archived/260617-WARDEN-WP-0007-policy-gate-and-production-verify.md", + "uuid": "3718ac07-2fa2-47d0-a02a-c9a7b83a5ba9", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0007-T01", + "status": "done", + "title": "T1 \u2014 Production OpenBao verification evidence", + "source_path": "workplans/archived/260617-WARDEN-WP-0007-policy-gate-and-production-verify.md", + "uuid": "344540ad-5912-4118-b406-450b96e13c40", + "parent_id": "WARDEN-WP-0007", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0007-T02", + "status": "done", + "title": "T2 \u2014 Policy config and flex-auth client", + "source_path": "workplans/archived/260617-WARDEN-WP-0007-policy-gate-and-production-verify.md", + "uuid": "05424ddf-5fe9-43a1-a2f8-c47235a012c8", + "parent_id": "WARDEN-WP-0007", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0007-T03", + "status": "done", + "title": "T3 \u2014 Wire policy gate into sign/issue", + "source_path": "workplans/archived/260617-WARDEN-WP-0007-policy-gate-and-production-verify.md", + "uuid": "f5ae8e6e-8cce-4526-b18c-0452a135af49", + "parent_id": "WARDEN-WP-0007", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0007-T04", + "status": "done", + "title": "T4 \u2014 Tests and docs", + "source_path": "workplans/archived/260617-WARDEN-WP-0007-policy-gate-and-production-verify.md", + "uuid": "ea921d56-033b-4619-8032-61af7992e610", + "parent_id": "WARDEN-WP-0007", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0008", + "status": "finished", + "title": "Production SSH Path and Stewardship Closeout", + "source_path": "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "uuid": "a174963a-4ff1-4565-b19f-896cd4ff14a0", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0008-T01", + "status": "done", + "title": "T1 \u2014 Post-WP-0007 INTENT/SCOPE reassessment", + "source_path": "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "uuid": "05379da4-79d0-4742-8638-9e9565cccf72", + "parent_id": "WARDEN-WP-0008", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0008-T02", + "status": "done", + "title": "T2 \u2014 Production OpenBao end-to-end sign verification", + "source_path": "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "uuid": "b1a1831d-b2b3-4204-95f6-04dc7f29f67c", + "parent_id": "WARDEN-WP-0008", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0008-T03", + "status": "done", + "title": "T3 \u2014 State Hub task status canon migration", + "source_path": "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "uuid": "876827c4-4a86-4e58-9a1f-ac87045dc903", + "parent_id": "WARDEN-WP-0008", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0008-T04", + "status": "done", + "title": "T4 \u2014 Production config example and archive hygiene", + "source_path": "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "uuid": "75b9f366-3d7a-419d-98ad-bc10ab90a697", + "parent_id": "WARDEN-WP-0008", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0008-T05", + "status": "cancel", + "title": "T5 \u2014 flex-auth policy gate production readiness (coordination)", + "source_path": "workplans/archived/260618-WARDEN-WP-0008-production-ssh-path-and-stewardship-closeout.md", + "uuid": "03b412a5-5b99-42df-a154-733dd4156000", + "parent_id": "WARDEN-WP-0008", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0009", + "status": "archived", + "title": "flex-auth Policy Gate Production Readiness", + "source_path": "workplans/archived/260623-WARDEN-WP-0009-flex-auth-policy-gate-production.md", + "uuid": "9213b262-e2f5-480e-a5bc-56635d5eb4c9", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0009-T01", + "status": "done", + "title": "T1 \u2014 flex-auth policy package confirmation", + "source_path": "workplans/archived/260623-WARDEN-WP-0009-flex-auth-policy-gate-production.md", + "uuid": "f988ed2e-0f63-4e89-abc4-183a7f23ddc2", + "parent_id": "WARDEN-WP-0009", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0009-T02", + "status": "done", + "title": "T2 \u2014 Production enablement and smoke", + "source_path": "workplans/archived/260623-WARDEN-WP-0009-flex-auth-policy-gate-production.md", + "uuid": "9d0fabc2-10ef-426d-a3d2-d4970d377029", + "parent_id": "WARDEN-WP-0009", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0010", + "status": "archived", + "title": "Access Routing \u2014 Charter and Pointer Catalog", + "source_path": "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "uuid": "e93de9fd-0192-4d02-bb7c-5e859fb76b9b", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0010-T01", + "status": "done", + "title": "T1 \u2014 INTENT wording", + "source_path": "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "uuid": "589081a6-d1f5-47b4-bec0-e82d9c3444f4", + "parent_id": "WARDEN-WP-0010", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0010-T02", + "status": "done", + "title": "T2 \u2014 Routing-role wiki page", + "source_path": "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "uuid": "9ac333f7-5fc4-4fa2-82f3-d5ece8ff0d92", + "parent_id": "WARDEN-WP-0010", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0010-T03", + "status": "done", + "title": "T3 \u2014 Pointer catalog schema + seed", + "source_path": "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "uuid": "59e0f480-694a-482a-b35e-b7bc4930aa41", + "parent_id": "WARDEN-WP-0010", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0010-T04", + "status": "done", + "title": "T4 \u2014 Routing index in CredentialRouting.md", + "source_path": "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "uuid": "aabd28c0-db2d-4267-be98-95be272c687d", + "parent_id": "WARDEN-WP-0010", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0010-T05", + "status": "done", + "title": "T5 \u2014 Registry and repo-boundary alignment", + "source_path": "workplans/archived/260624-WARDEN-WP-0010-access-routing-charter.md", + "uuid": "3335a689-922c-4319-98d0-4263ab13790b", + "parent_id": "WARDEN-WP-0010", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0011", + "status": "archived", + "title": "Routing Lookup CLI", + "source_path": "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "uuid": "0a520f8e-01b4-48f1-9af3-2f3f69fd0672", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0011-T01", + "status": "done", + "title": "T1 \u2014 Catalog loader and models", + "source_path": "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "uuid": "55b8422c-ad3c-4084-9e00-acaa4c360906", + "parent_id": "WARDEN-WP-0011", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0011-T02", + "status": "done", + "title": "T2 \u2014 `warden route list` and `show`", + "source_path": "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "uuid": "60b679c5-79bd-4186-b5a6-ac576931f06c", + "parent_id": "WARDEN-WP-0011", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0011-T03", + "status": "done", + "title": "T3 \u2014 `warden route find`", + "source_path": "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "uuid": "d307701f-0117-44f0-80fd-ca6f7ae06f42", + "parent_id": "WARDEN-WP-0011", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0011-T04", + "status": "done", + "title": "T4 \u2014 Tests", + "source_path": "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "uuid": "00a76e0f-8ab6-4f9a-ac6a-00eae633342c", + "parent_id": "WARDEN-WP-0011", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0011-T05", + "status": "done", + "title": "T5 \u2014 Doc consistency + drift guard", + "source_path": "workplans/archived/260624-WARDEN-WP-0011-routing-guide-cli.md", + "uuid": "bf848375-eca7-4116-bb1d-fb7df6395c70", + "parent_id": "WARDEN-WP-0011", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0013", + "status": "archived", + "title": "Production Integration & Stewardship Closeout", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "4678c41a-c1d0-48cd-9988-4ea0380e8258", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0013-T01", + "status": "done", + "title": "T1 \u2014 Post-gap reassessment and SCOPE refresh", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "de46f9a2-bf11-4651-a23c-430c63f396c8", + "parent_id": "WARDEN-WP-0013", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0013-T02", + "status": "done", + "title": "T2 \u2014 Archive hygiene (WP-0010, WP-0011)", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "1b35321d-63ad-40da-a1aa-0b66190a0733", + "parent_id": "WARDEN-WP-0013", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0013-T03", + "status": "done", + "title": "T3 \u2014 ops-bridge cert_command migration playbook", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "ad8588b2-9ae9-4f94-bd77-8025851a38f5", + "parent_id": "WARDEN-WP-0013", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0013-T04", + "status": "done", + "title": "T4 \u2014 Operator OpenBao token hygiene runbook", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "5cb35829-32eb-4d59-97a1-f4d92ce8e239", + "parent_id": "WARDEN-WP-0013", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0013-T05", + "status": "done", + "title": "T5 \u2014 Principals inventory drift check", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "4025cd32-89f8-42c3-b1e8-eaf78497d91f", + "parent_id": "WARDEN-WP-0013", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0013-T06", + "status": "done", + "title": "T6 \u2014 Policy gate production enablement checklist", + "source_path": "workplans/archived/260624-WARDEN-WP-0013-production-integration-and-stewardship-closeout.md", + "uuid": "51663f65-79cb-4108-87c8-9721f9476259", + "parent_id": "WARDEN-WP-0013", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0012", + "status": "finished", + "title": "Routing Scenario Playbooks", + "source_path": "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "uuid": "a7e712a0-02f8-4f83-944e-6b207e77bc4c", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0012-T01", + "status": "done", + "title": "T1 \u2014 issue-core ingestion key playbook", + "source_path": "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "uuid": "830bb512-0288-4dba-9dd4-ccfd28a4921f", + "parent_id": "WARDEN-WP-0012", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0012-T02", + "status": "done", + "title": "T2 \u2014 Inter-Hub and bootstrap lanes", + "source_path": "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "uuid": "7726a703-6e00-4e49-9380-ed3fb3268827", + "parent_id": "WARDEN-WP-0012", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0012-T03", + "status": "done", + "title": "T3 \u2014 ops-bridge tunnel migration", + "source_path": "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "uuid": "9fb397f0-0abb-48f5-bb62-7e77edae93bb", + "parent_id": "WARDEN-WP-0012", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0012-T04", + "status": "done", + "title": "T4 \u2014 Platform secret scenarios (LLM, STS, DB)", + "source_path": "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "uuid": "edcf4ed7-f18d-4a92-a42d-8cc7ca0ab792", + "parent_id": "WARDEN-WP-0012", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0012-T05", + "status": "done", + "title": "T5 \u2014 Drift review cadence", + "source_path": "workplans/archived/260627-WARDEN-WP-0012-routing-scenario-playbooks.md", + "uuid": "db98d655-8551-487b-9413-41bf97fc06e1", + "parent_id": "WARDEN-WP-0012", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0014", + "status": "finished", + "title": "Operator Access Assist \u2014 warden access front door", + "source_path": "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "uuid": "3c30b2ed-6ede-4b95-a438-fde6da6f6633", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0014-T01", + "status": "done", + "title": "T1 \u2014 Catalog schema: structured handoff fields", + "source_path": "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "uuid": "abb0e722-6524-4224-8638-6ee1573ed3e0", + "parent_id": "WARDEN-WP-0014", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0014-T02", + "status": "done", + "title": "T2 \u2014 `warden access` advisory surface", + "source_path": "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "uuid": "c1497263-7124-459f-b63a-d0c0c7005c86", + "parent_id": "WARDEN-WP-0014", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0014-T03", + "status": "done", + "title": "T3 \u2014 OpenBao proxy lane (`--fetch` / `--exec`)", + "source_path": "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "uuid": "6d3eb0e4-309c-4065-893e-6c4053fb0db2", + "parent_id": "WARDEN-WP-0014", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0014-T04", + "status": "done", + "title": "T4 \u2014 key-cape / login orchestration lane", + "source_path": "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "uuid": "481997e4-193d-4724-84a6-61cbc2940153", + "parent_id": "WARDEN-WP-0014", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0014-T05", + "status": "done", + "title": "T5 \u2014 Docs, security model, and INTENT/SCOPE alignment", + "source_path": "workplans/archived/260627-WARDEN-WP-0014-operator-access-assist.md", + "uuid": "a5eb616e-4edf-42db-a4fb-bf296cdb92bc", + "parent_id": "WARDEN-WP-0014", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0015", + "status": "finished", + "title": "Workload Security Posture \u2014 env posture \u00d7 maturity + conformance", + "source_path": "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "uuid": "99f4a0e1-853c-456f-8aa7-8ff0f318ea65", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0015-T01", + "status": "done", + "title": "T1 \u2014 Author the two-axis Workload Security Posture standard (canon-bound)", + "source_path": "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "uuid": "85aeb676-a593-4056-986a-db14d4c5209f", + "parent_id": "WARDEN-WP-0015", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0015-T02", + "status": "done", + "title": "T2 \u2014 Machine-readable posture descriptors (both axes)", + "source_path": "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "uuid": "011fb0af-154d-40f4-a03e-3172c325321a", + "parent_id": "WARDEN-WP-0015", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0015-T03", + "status": "done", + "title": "T3 \u2014 Conformance checker (incl. secret-flow lattice)", + "source_path": "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "uuid": "c1a0e987-19d0-478e-ac08-2dbe98e64e09", + "parent_id": "WARDEN-WP-0015", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0015-T04", + "status": "done", + "title": "T4 \u2014 Dev-tier contract-double fixture library", + "source_path": "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "uuid": "e556fd2e-4e39-4c7d-bd94-b4330e4bef45", + "parent_id": "WARDEN-WP-0015", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0015-T05", + "status": "done", + "title": "T5 \u2014 INTENT/SCOPE alignment + canon contributions", + "source_path": "workplans/archived/260627-WARDEN-WP-0015-secret-lifecycle-tiering.md", + "uuid": "298c9b09-4a5a-41bf-a3bd-6c572385236b", + "parent_id": "WARDEN-WP-0015", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-ADHOC-2026-07-07", + "status": "finished", + "title": "Ad Hoc Tasks \u2014 2026-07-07", + "source_path": "workplans/archived/260707-ADHOC-2026-07-07.md", + "uuid": null, + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-ADHOC-2026-07-07-T01", + "status": "done", + "title": "T01 \u2014 Roll out proxy pipe fix (be3b4a2)", + "source_path": "workplans/archived/260707-ADHOC-2026-07-07.md", + "uuid": null, + "parent_id": "WARDEN-WP-ADHOC-2026-07-07", + "extra": {} + }, + { + "kind": "intake", + "id": "WARDEN-IN-0001", + "status": "open", + "title": "Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule demarcation", + "source_path": "intakes/intakes.md", + "uuid": null, + "parent_id": null, + "extra": { + "record": { + "id": "WARDEN-IN-0001", + "kind": "intake", + "title": "Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule demarcation", + "status": "open", + "origin": "cross-repo", + "origin_ref": "gate-house GH-DEC-2026-001", + "priority": "medium", + "owner": "ops-warden", + "requested_by": "gate-house", + "standard": "net-kingdom/canon/standards/security-layer-model_v0.1.md", + "description": "gate-house asks ops-warden to assent to three boundary items. (1) ops-warden is Staff, bound by the rule that Staff acts only through Engine APIs and never touches Tooling directly (standard section 5). (2) Doctrine versus runbook: the NetKingdom Security Literacy section in ops-warden INTENT is evidence the security curriculum had no owner; it now has one in gate-house. Proposal is that doctrine and curriculum move to gate-house and that section becomes lane-specific runbooks referencing gate-house doctrine rather than restating it. ops-warden keeps the lanes it stewards and everything operational about them. (3) The access lane/rule demarcation, normative in standard section 8: ops-warden and ops-mason own access lanes \u2014 how a worker reaches a host; access-engine owns access rules \u2014 whether they may. This demarcation is the condition attached to renaming flex-auth to access-engine, so ops-warden effectively holds a veto on that name. Also requested: add gate-house to the Security Literacy and routing tables \u2014 currently every plane is listed and gate-house appears nowhere \u2014 routing doctrine and authority-model questions there while continuing to route policy decisions to access-engine. If moving the curriculum out leaves ops-warden unable to instruct its own workers, say so; the boundary is wrong if it does.", + "created": "2026-08-28T19:30:28.087109Z", + "updated": "2026-08-28T19:30:28.087109Z" + } + } + } + ], + "events": [ + { + "type": "repo.command.applied", + "command": "repo.work.create_intake", + "operation": "create", + "correlation_id": "65d40cdd-5894-440e-9c95-c6bcfe259b66", + "kind": "intake", + "id": "WARDEN-IN-0001", + "git_sha": "467635e84b99757336ee49d7f0dbf107607d0560", + "files_touched": [ + "intakes/intakes.md" + ], + "source": "repo-manager", + "emitted_at": "2026-08-28T19:30:29.829125Z" + } + ] +} diff --git a/INTENT.md b/INTENT.md index caa3c68..d1c0a97 100644 --- a/INTENT.md +++ b/INTENT.md @@ -1,19 +1,26 @@ # INTENT -> **NetKingdom layering review — 2026-08-28.** This repository's role was reviewed -> against the NetKingdom IT-security layer model: **Taxonomy → Tooling → Engines → -> Staff**, layered by determinism and by the kind of artifact each layer produces. -> Findings and the argument behind them: -> `gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md`. -> The model is `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed), -> ratified by `gate-house/decisions/decisions.md` GH-DEC-2026-001. +> **Layer: Staff.** ops-warden is a Staff repository under the NetKingdom +> IT-security layer model (Taxonomy -> Tooling -> Engines -> Staff, layered by +> determinism and by the kind of artifact each layer produces): +> `net-kingdom/canon/standards/security-layer-model_v0.1.md`, owned by gate-house, +> ratified as `gate-house/decisions/decisions.md` GH-DEC-2026-001. > -> The layer rule that binds every repository: **Staff never touches tooling -> directly. It acts only through engine APIs.** +> **The binding rule: Staff never touches Tooling directly. It acts only through +> Engine APIs.** ops-warden holds no state another layer depends on at runtime and +> renders no authorization decision — it consumes them from access-engine. > -> **This repository is Staff — interactive, non-deterministic; operational stewardship.** Add the layer label and the Staff invariant. Two substantive changes. (1) The **"NetKingdom Security Literacy"** section is evidence that the security curriculum had no owner; it now has one. Doctrine and curriculum move to gate-house, and this section becomes lane-specific runbooks that reference gate-house doctrine rather than restating it. The boundary is **doctrine versus runbook**. (2) The literacy and routing tables should add gate-house — currently every plane is listed and gate-house appears nowhere — routing doctrine and authority-model questions there, while continuing to route policy decisions to access-engine. Record the lane/rule demarcation as in ops-mason. +> **Declared exception (standard section 5).** `src/warden/vault.py` (`VaultCA`) is a +> direct OpenBao client that performs a write, and `warden desk` shells `bao kv put` +> for paste-once provisioning. Both are non-conformant. Intended owner: +> **secrets-engine**; blocked on: no engine exposes an SSH certificate signing +> surface; reviewed quarterly. `src/warden/taint.py` reads KV metadata only, declared +> under the read-only observation allowance. `warden access --fetch/--exec/--wrap` +> runs the owner's tool under **the caller's** identity and supplies no authority of +> its own (`ADR-0002`). > -> *This note records what should change. The body below is not yet adapted.* +> Assent, reasoning, and the amendment offered back to gate-house: +> `history/2026-08-28-security-layer-model-assent.md` and `ADR-0010`. > This file captures **why this repository exists**, the **direction it is > moving toward**, and the **kind of system it is meant to become**. @@ -92,30 +99,51 @@ owns one lane and points at the rest: --- -## NetKingdom Security Literacy +## Lane routing — who owns which need -ops-warden should be fluent in the platform architecture documented in -`net-kingdom` — especially: +**This is a runbook, not doctrine.** Security doctrine, the authority model, and the +security curriculum are **gate-house's** (`security-layer-model_v0.1` section 8). +ops-warden references them and does not restate them. What follows is lane +stewardship: which subsystem owns which need, and what ops-warden does about it. -| Plane / component | Role in access | ops-warden relationship | -| --- | --- | --- | -| **key-cape / Keycloak** | Identity — who is the actor, MFA, IAM Profile claims | Instruct identity path; do not re-implement OIDC | -| **flex-auth + Topaz** | Authorization — may this actor perform this action | Caller-side policy gate shipped (opt-in); production flip is flex-auth's | -| **OpenBao** | Runtime secrets — API keys, dynamic creds, leases, audit | Instruct custody paths; SSH engine is signing backend only; proxy reads as caller when `exec_capable` | -| **secrets-engine** | Owner-native secret-exec (`secrets-engine exec`) | Route provisioned exec lanes (e.g. npm publish); ops-warden does not hold tokens | -| **railiance-platform** (credential broker) | Scoped lease grants (`credential exec`) | Route `warden-sign` token needs; ops-warden does not mint OpenBao tokens | -| **tenant-engine** | Tenant/client secret custody and front door | Route tenant lanes once fronted; ops-warden's current tenant proxies are interim (§9) | -| **user-engine** | End-user identity and account lifecycle | No ops-warden lane today; route rather than absorb | -| **ops-warden** | Operational SSH certificates — short-lived host access | **Own and issue** this lane | -| **ops-bridge** | Tunnel transport — consumes certs via `cert_command` | Primary consumer; document integration | -| **railiance-infra** | Host principals, force-command, SSH hardening | Instruct host-side deployment; do not own Ansible | -| **railiance-platform** (deploy) | OpenBao/K8s/platform service deployment | Instruct production endpoints; do not deploy clusters | +The machine-readable form is `registry/routing/catalog.yaml`, and the executable form +is `warden plan ""` / `warden route find`. Prefer either over this table — it is +orientation, and the catalog is the source of truth (`ADR-0001`). + +| Component | Layer | Owns | ops-warden relationship | +| --- | --- | --- | --- | +| **gate-house** | Staff | Security doctrine, invariants, authority ceilings, authority context, conformance review, curriculum | **Route doctrine and authority-model questions here.** Not policy decisions — those go to access-engine | +| **access-engine** (`flex-auth`) | Engine | **The policy decision** — whether an actor may act. The only decision point in NetKingdom | Consume decisions; caller-side pre-sign gate. ops-warden never renders or caches one | +| **key-cape / Keycloak** | Tooling | Identity — who the actor is, MFA, IAM Profile claims | Instruct the identity path; do not re-implement OIDC | +| **OpenBao** | Tooling | Runtime secrets — API keys, dynamic creds, leases, audit | Instruct custody paths; proxy reads as the caller when `exec_capable`. Direct client use is the declared exception above | +| **secrets-engine** | Engine | Credential abstraction, custody, lifecycle; owner-native exec | Route provisioned exec lanes (e.g. npm publish). **Intended owner of the SSH-CA surface** | +| **tenant-engine** | Engine | Tenant/client secret custody and front door | Route tenant lanes once fronted; current tenant proxies are interim (section 9) | +| **user-engine** | Engine | Users, accounts, memberships | No ops-warden lane today; route rather than absorb | +| **zone-engine** | Engine | Zone identity and membership | Consume compiled membership; ops-warden declares `z1-operational` (`ADR-0009`) | +| **railiance-platform** (broker) | — | Scoped lease grants (`credential exec`) | Route `warden-sign` token needs; ops-warden does not mint OpenBao tokens | +| **ops-mason** | Staff | Building and tearing down access routes and perimeters | Peer lane owner; same lane/rule demarcation applies | +| **ops-warden** | Staff | **Operational access lanes** — short-lived SSH certificates, routing, stewardship, runbooks | **Own and issue** the SSH lane | +| **ops-bridge** | Staff | Tunnel transport — consumes certs via `cert_command` | Primary consumer; document integration | +| **railiance-infra** | — | Host principals, force-command, SSH hardening | Instruct host-side deployment; do not own Ansible | +| **kings-guard** | Staff | Adaptive defence, observation, containment; publishes posture | Posture may reduce authority, never manufacture it | + +### Access lane versus access rule + +Normative, per `security-layer-model_v0.1` section 8 and assented to in `ADR-0010`: + +- **access lane** — ops-warden and ops-mason. *How* a worker reaches a host. +- **access rule** — access-engine. *Whether* they may. + +ops-warden owns the route and never the decision. A question about whether an actor +may do something is not an ops-warden question, however it arrives. Canonical references: +- `net-kingdom/canon/standards/security-layer-model_v0.1.md` (layers, section 5, section 8) - `net-kingdom/docs/platform-identity-security-architecture.md` - `net-kingdom/docs/responsibility-map.md` - `wiki/AccessManagementDirective.md` (ops SSH actor model) +- `.claude/rules/credential-routing.md` (agent-facing runbook — stays inline by design) --- @@ -138,7 +166,8 @@ Canonical references: | Need | Route to | | --- | --- | | OIDC login, MFA, human identity claims | key-cape / Keycloak (NetKingdom IAM Profile) | -| Policy decision — may actor X access resource Y | flex-auth | +| Security doctrine, invariants, authority model | gate-house | +| Policy decision — may actor X access resource Y | access-engine (`flex-auth`) | | API keys, provider secrets, DB creds, object-storage STS | OpenBao (+ flex-auth policy where required) | | Inter-Hub operator keys, LLM provider credentials | OpenBao or approved operator secret store | | Tunnel lifecycle, port forwarding | ops-bridge | diff --git a/SCOPE.md b/SCOPE.md index ae19ee4..46c9eec 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -156,6 +156,7 @@ superseding ADR, never an in-place edit. | `ADR-0007` | Build-stage permissiveness stops at credential disclosure; every lane carries an explicit `risk` grade | | `ADR-0008` | A lane's risk grade covers every field its path discloses, not just the field it is named after | | `ADR-0009` | Adopt security-zones v0.1 and compile explicit workload membership; PEP failure mode is per zone | +| `ADR-0010` | ops-warden is Staff — it owns access lanes, never access rules; the direct OpenBao client is a declared engine gap, not an exemption | Rules we follow but do not own — NetKingdom canon, the IAM profile, the credential-management standard, the-custodian's ADR-001 workplan convention — are @@ -433,11 +434,12 @@ Downstream: `ops-bridge` (primary), kaizen agents, CI automations, human operato | Repo | Relationship | | --- | --- | +| `gate-house` | Owns security doctrine, invariants, authority context, and conformance review; ops-warden routes doctrine questions there and references rather than restates them (`ADR-0010`) | | `net-kingdom` | Canonical security architecture; ops-warden aligns to it | | `ops-bridge` | Primary cert_command consumer | | `railiance-infra` | Host-side SSH principals and hardening | | `railiance-platform` | OpenBao deployment and platform secrets | -| `flex-auth` | Authorization; policy package shipped (FLEX-WP-0006); runtime deploy FLEX-WP-0007 | +| `flex-auth` | Authorization — ruled name `access-engine`; the only policy decision point. Policy package shipped (FLEX-WP-0006); runtime deploy FLEX-WP-0007 | | `key-cape` | Identity / IAM Profile lightweight mode | | `secrets-engine` | Owner-native secret-exec front door (`secrets-engine exec/route`); ops-warden routes provisioned secret lanes to it (WP-0019) and holds 6 more as interim proxies pending its front doors | | `tenant-engine` | Intended owner of tenant/client secret front doors; ops-warden holds 3 tenant lanes as interim proxies (WP-0028 pattern, WP-0030 register) | diff --git a/docs/adr/ADR-0010-ops-warden-is-staff.md b/docs/adr/ADR-0010-ops-warden-is-staff.md new file mode 100644 index 0000000..65e4ed2 --- /dev/null +++ b/docs/adr/ADR-0010-ops-warden-is-staff.md @@ -0,0 +1,109 @@ +--- +id: ops-warden-adr-0010 +type: adr +title: "ADR-0010 — ops-warden is Staff: lanes, not rules, and one declared engine gap" +domain: infotech +repo: ops-warden +status: accepted +version: "1.0" +revision: "1" +owner: ops-warden +binds: "ops-warden" +created: "2026-08-28" +updated: "2026-08-28" +last_reviewed: "2026-08-28" +review_interval: 3m +enforced_by: "INTENT.md layer declaration; docs/adr/ADR-0002; docs/adr/ADR-0003; docs/adr/ADR-0005; registry/routing/catalog.yaml delegation fields" +supersedes: "" +successor: "" +--- + +# ADR-0010 — ops-warden is Staff: lanes, not rules, and one declared engine gap + +## Status + +Accepted 2026-08-28, answering intake `WARDEN-IN-0001` from gate-house, which +carries decision `GH-DEC-2026-001`. The standard being adopted — +`net-kingdom/canon/standards/security-layer-model_v0.1.md` — is `proposed`, and was +proposed pending assent from flex-auth, kings-guard, and ops-warden. This ADR is +ops-warden's half of that assent. + +## Context + +The estate acquired overlapping claims to the same responsibility, most visibly two +repositories describing themselves as the authorization control plane. The layer +model resolves the overlap by layering repositories on determinism — Taxonomy, +Tooling, Engines, Staff — and by two rules: Staff never touches Tooling directly +(§5), and `access-engine` is the only policy decision point (§6). + +ops-warden is assigned Staff. Two demarcations follow that touch this repository: +the security curriculum it had been carrying belongs to gate-house, and the words +*access lane* and *access rule* are bound to different owners. + +Full reasoning: `history/2026-08-28-security-layer-model-assent.md`. + +## Decision + +**1. ops-warden is Staff and declares it.** `INTENT.md` carries the layer label and +the §5 invariant. ops-warden holds no state another layer depends on at runtime and +renders no authorization decision — it consumes them. + +**2. Lanes, not rules.** ops-warden owns *how* a worker reaches a host: SSH +certificate issuance, the routing catalog, `warden access`, `warden plan`, +`cert_command`. It never owns *whether* a worker may — that is `access-engine` +(today `flex-auth`), and ops-warden neither renders nor caches that decision. This +restates what `ADR-0002` and `ADR-0005` already bind; it is recorded here because +the demarcation is now normative estate-wide and other repositories rely on +ops-warden holding to it. The ruled rename `flex-auth` → `access-engine` is assented +to; ops-warden asks only for a window in which both names resolve. + +**3. Doctrine goes to gate-house; runbooks stay here.** ops-warden does not restate +security doctrine, the authority model, or the curriculum. It references +gate-house's. It keeps everything operational about the lanes it stewards: which +subsystem owns which need, how to obtain a credential lane by lane, and conformance +evidence for its own lanes. `.claude/rules/credential-routing.md` is runbook, not +curriculum, and stays inlined in this and every other repository. + +**4. One declared engine gap, not an exemption.** `src/warden/vault.py` (`VaultCA`) +is a direct OpenBao client performing a write from a Staff repository. It is a §5 +non-conformance. ops-warden declares it rather than arguing it away: + +- **intended owner:** `secrets-engine` (credential abstraction, custody, lifecycle) +- **blocked on:** no engine exposes an SSH certificate signing surface +- **review:** with this ADR, every 3 months + +Until that surface exists, ops-warden continues to sign — refusing to would remove +production host access to close a documentation gap — and reports the position as +open. `warden desk`'s `bao kv put` is declared on the same terms. `taint.py` is +metadata-only observation, declared under §5's read-only allowance. `proxy.py` +supplies no authority of its own: it runs the owner's tool under the caller's +identity and is governed by `ADR-0002`. + +This is `ADR-0003` turned inward. ops-warden has required an intended owner and a +blocker on 27 catalog lanes it holds for other repositories; it holds itself to the +same record. + +## Consequences + +ops-warden's conformance under §10 is *declared non-conformant with a tracked +closure path*, not clean. That is the accurate state and it is the state that gets +fixed, because it names an owner who can fix it. + +An amendment to §5 has been offered to gate-house — a second sanctioned shape +alongside read-only diagnostics: a declared engine gap carrying intended owner, +blocker, and review date, machine-readable so §10 can tell a tracked gap from an +undeclared violation. It is offered, not assumed; §5 stays gate-house's to write. If +gate-house declines it, ops-warden's position is a plain non-conformance and is +reported as one. + +The `NetKingdom Security Literacy` section stops being a prose second source for +`registry/routing/catalog.yaml`, which `ADR-0001` had already ruled against for +catalog procedure. + +## Related + +- `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed, gate-house) +- `gate-house/decisions/decisions.md` — `GH-DEC-2026-001` +- `history/2026-08-28-security-layer-model-assent.md` +- `ADR-0001`, `ADR-0002`, `ADR-0003`, `ADR-0005`, `ADR-0009` +- `WARDEN-IN-0001` diff --git a/docs/adr/README.md b/docs/adr/README.md index 9de6ae1..8678e25 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -71,3 +71,4 @@ and the publication is a defect. | `ADR-0007` | Build-stage permissiveness stops at credential disclosure | ops-warden | | `ADR-0008` | A lane's risk grade covers every field its path discloses | ops-warden | | `ADR-0009` | Adopt security-zones v0.1; compile explicit membership and select PEP failure mode per zone | ops-warden | +| `ADR-0010` | ops-warden is Staff: it owns access lanes, never access rules; the direct OpenBao client is a declared engine gap | ops-warden, and gate-house as the standard's owner | diff --git a/history/2026-08-28-security-layer-model-assent.md b/history/2026-08-28-security-layer-model-assent.md new file mode 100644 index 0000000..286b855 --- /dev/null +++ b/history/2026-08-28-security-layer-model-assent.md @@ -0,0 +1,171 @@ +# Security layer model — ops-warden's assent (WARDEN-IN-0001) + +**Date:** 2026-08-28 +**Intake:** `WARDEN-IN-0001` +**Requested by:** gate-house, ratified as `GH-DEC-2026-001` +**Standard:** `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed) +**Outcome:** assent to all three items; one declared non-conformance and one +proposed amendment to the standard. + +--- + +## What was asked + +gate-house asked ops-warden to assent to three boundary items: + +1. **ops-warden is Staff**, bound by §5 — Staff acts only through Engine APIs and + never holds a direct Tooling client. +2. **Doctrine versus runbook** — the security curriculum moves to gate-house; the + `NetKingdom Security Literacy` section in `INTENT.md` becomes lane-specific + runbooks that reference gate-house doctrine rather than restating it. +3. **The access lane / access rule demarcation** (§8) — ops-warden and ops-mason own + *lanes* (how a worker reaches a host); access-engine owns *rules* (whether they + may). This is the condition attached to renaming flex-auth to access-engine, so + ops-warden effectively holds a veto on that name. + +Plus: add gate-house to the literacy and routing tables, and say so if moving the +curriculum out leaves ops-warden unable to instruct its own workers. + +--- + +## Item 1 — Staff, and the §5 problem it exposes + +**Assent to the layer.** Staff is the right assignment and not a demotion. +ops-warden's artifacts are exactly what §3.4 describes: routing decisions, +workplans, runbooks, an audit trail. Its one production lane is non-deterministic +in the sense that matters — it is an operator front door, not a contract. + +**But §5 is violated today, and by the one lane ops-warden permanently owns.** +The rule is deliberately greppable, so grepping is the honest response: + +| Path | Tooling contact | Kind | Whose credential | +| --- | --- | --- | --- | +| `src/warden/vault.py` (`VaultCA.sign`) | `POST /v1//sign/` | **write** | broker-issued token held by ops-warden's process | +| `src/warden/desk.py` | `bao kv put` (paste-once provisioning) | **write** | founder's, at the desk | +| `src/warden/taint.py` | `bao kv metadata get` | read (metadata only, never data) | caller's | +| `src/warden/proxy.py` (`warden access --fetch/--exec/--wrap`) | catalog `fetch_command` | read | **the caller's own** | + +Two of these are not really ops-warden's clients. `proxy.py` runs the owner's tool +under the caller's identity and supplies no authority of its own — that is +`ADR-0002`, conduit not broker, and it is arguably outside §5's target. `taint.py` +reads metadata only, and fits §5's read-only-observation allowance once declared. + +**`VaultCA` does not have that defence.** It is a direct OpenBao client, in a Staff +repository, performing a write, presenting a token from its own environment. It is +production-verified and it is the SSH lane — the single thing ops-warden owns +permanently. Under §5 as written, adopting this standard puts ops-warden's core +lane in violation on the day it is adopted. + +The escape hatch §5 offers does not fit: it covers *read-only observation for +diagnostics*, and signing is a write. The route §5 prescribes does fit — + +> *A Staff repository needing a capability no engine exposes MUST raise that as an +> engine gap, not solve it locally.* + +— and no engine exposes SSH certificate signing. `secrets-engine` owns credential +abstraction, custody and lifecycle, which is the layer this belongs in, but it +fronts no SSH-CA API today. + +**So ops-warden assents and declares the non-conformance rather than negotiating an +exemption.** `VaultCA` is recorded in `INTENT.md` as a declared §5 exception with a +named intended owner (`secrets-engine`), a blocker (no SSH-CA engine surface), and a +review date. That is `ADR-0003` — cover gaps, never silently own them — applied to +ops-warden itself instead of to someone else's lane. + +### Proposed amendment to the standard + +§5 has exactly one shape for a Staff repository that legitimately touches Tooling: +read-only diagnostics. That shape is too narrow to describe the estate as it exists, +and a rule with no lane for a real, sanctioned case gets satisfied by relabelling +rather than by closing the gap. + +Recommend §5 gain a second shape: a **declared engine gap** — a Staff repository MAY +hold a Tooling client for a capability no engine exposes, provided it is declared in +`INTENT.md` with an intended owner, the blocker, and a review date, and provided the +declaration is machine-readable so the conformance check in §10 can distinguish a +tracked gap from an undeclared violation. + +ops-warden already runs this machinery for other repositories' lanes: 27 catalog +entries carry `delegation:` with `intended_owner` and `blocked_on`, and +`warden route gaps` lists them (WP-0030). It is offered, not imposed — the standard +is gate-house's. + +--- + +## Item 2 — Doctrine versus runbook + +**Assent.** The `NetKingdom Security Literacy` section is what gate-house says it is: +evidence that the curriculum had no owner, so it accreted in whatever `INTENT.md` +was open. That is the same failure `risk-nexus` names for findings and the same one +`ADR-0001` prevents for catalog procedure. ops-warden has argued this rule twice +against other repositories; it applies here. + +The boundary, drawn precisely: + +| Moves to gate-house | Stays with ops-warden | +| --- | --- | +| Why the planes are separated; the authority model | Which subsystem owns which credential need | +| What "posture", "zone", "authority ceiling" mean | How to obtain a cert, a lease, a login — per lane | +| The security curriculum a worker is taught | The runbook a worker executes | +| Doctrine a lane must conform to | Evidence of conformance for ops-warden's lanes | + +**gate-house's test question, answered: no, it does not leave ops-warden unable to +instruct its workers — and the reason is worth recording.** What actually instructs +an ops-warden worker is not the prose in `INTENT.md`. It is `warden plan ""`, +`warden route find`, and `.claude/rules/credential-routing.md`, which is inlined into +every repository's agent instructions precisely because credential routing is +high-frequency and high-risk. That surface is executable, lane-specific, and +unambiguously runbook. It does not depend on the literacy table, and moving doctrine +out does not weaken it. + +If anything the move improves it: the literacy table has been a second, prose copy of +what `registry/routing/catalog.yaml` states machine-readably, which is the +double-source failure `ADR-0001` exists to stop. + +**One thing must not move with it.** `.claude/rules/credential-routing.md` stays +inline in this repository and in every other. It is not doctrine and not a +curriculum; it is the anti-pattern list an agent needs *before* it acts, and a +reference to a document in another repository would not be read in time. + +--- + +## Item 3 — Access lane versus access rule + +**Assent, unconditionally, and the veto on `access-engine` is not exercised.** + +ops-warden is already built this way. `ADR-0005` implements one lane narrowly and +routes everything else; `ADR-0002` makes it a conduit that never decides; `ADR-0009` +has ops-warden compile membership attributes and apply a zone's failure mode while +flex-auth owns the stance. ops-warden consumes decisions; it has never rendered one. +The demarcation costs nothing because it describes what is already true. + +`access-engine` is also the better name. ops-warden's own routing table has had to +say "authorization" for the decision and "access" for the route for a year, and the +collision is visible in every playbook. + +**One operational condition, on execution rather than on the ruling.** The rename is +598 references across 82 files in this repository alone — catalog `owner:` fields, +`registry/flex-auth/`, `src/warden/policy.py`, the production registry snapshot +builder, playbooks, and the `.claude/rules/` files that other repositories inline. +Ops-warden asks for a deprecation window in which both names resolve, rather than a +flag day; ops-warden will do its own migration inside that window. This is a request +about sequencing, not a reservation about the name. + +--- + +## Item 4 — gate-house is missing from every table + +Correct, and fixed in this pass. gate-house is added to the literacy/routing table +in `INTENT.md` as the owner of doctrine, invariants, authority context, and +conformance review — with the routing rule stated explicitly: **doctrine and +authority-model questions go to gate-house; policy decisions continue to go to +access-engine.** Those are different questions and the distinction is the whole +point of §6. + +--- + +## Recorded as + +- `ADR-0010` — ops-warden is Staff; lanes not rules; the declared §5 exception +- `INTENT.md` — layer declaration, reworked routing table, gate-house row +- `WARDEN-IN-0001` — closed, outcome `assented` diff --git a/intakes/intakes.md b/intakes/intakes.md index a7f4472..2535d91 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -7,7 +7,8 @@ id: WARDEN-IN-0001 kind: intake title: 'Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule demarcation' -status: open +status: closed +outcome: assented origin: cross-repo origin_ref: gate-house GH-DEC-2026-001 priority: medium @@ -30,6 +31,24 @@ description: 'gate-house asks ops-warden to assent to three boundary items. (1) — routing doctrine and authority-model questions there while continuing to route policy decisions to access-engine. If moving the curriculum out leaves ops-warden unable to instruct its own workers, say so; the boundary is wrong if it does.' +notes: 'Assented to all three items in ADR-0010, with reasoning in + history/2026-08-28-security-layer-model-assent.md. (1) Staff accepted; the section 5 + binding rule exposed a real non-conformance — src/warden/vault.py is a direct + OpenBao client performing a write, as is warden desk''s bao kv put. Declared in + INTENT.md as an engine gap with intended owner secrets-engine and blocker "no engine + exposes an SSH-CA surface", not negotiated as an exemption; taint.py declared under + the read-only allowance; warden access proxies run under the caller''s identity. + An amendment is offered back to gate-house: a second sanctioned shape in section 5 for + a declared engine gap carrying intended owner, blocker and review date, machine-readable + so section 10 can tell a tracked gap from an undeclared violation. (2) Doctrine versus + runbook accepted; the literacy section is now a lane routing runbook referencing + gate-house doctrine. Answering gate-house''s test question: it does not leave ops-warden + unable to instruct its workers, because what instructs them is warden plan / warden route + and .claude/rules/credential-routing.md, which stays inline by design. (3) The lane/rule + demarcation assented unconditionally and the access-engine veto not exercised — ops-warden + already consumes decisions and renders none. One request on sequencing only: a deprecation + window in which both names resolve (598 references across 82 files here). gate-house added + to the routing tables in INTENT.md and SCOPE.md.' created: '2026-08-28T19:30:28.087109Z' -updated: '2026-08-28T19:30:28.087109Z' +updated: '2026-08-28T21:05:00Z' ``` From f7664005631cd9efcf36903953b45f910f7d79c2 Mon Sep 17 00:00:00 2001 From: repo-manager Date: Fri, 28 Aug 2026 21:52:03 +0200 Subject: [PATCH 11/32] chore(registrar): assign State Hub identifiers Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- WORK-RECORDS.md | 2 +- intakes/intakes.md | 1 + workplans/ADHOC-2026-06-27.md | 1 + workplans/ADHOC-2026-06-29.md | 1 + workplans/ADHOC-2026-08-11.md | 1 + workplans/ADHOC-2026-08-17.md | 1 + workplans/archived/260707-ADHOC-2026-07-07.md | 1 + 7 files changed, 7 insertions(+), 1 deletion(-) diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 9b8146f..8bbeb08 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -129,4 +129,4 @@ | task | WARDEN-WP-0033-T04 | wait | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | -| intake | WARDEN-IN-0001 | open | — | intakes/intakes.md | +| intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md | diff --git a/intakes/intakes.md b/intakes/intakes.md index 2535d91..4a91201 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -51,4 +51,5 @@ notes: 'Assented to all three items in ADR-0010, with reasoning in to the routing tables in INTENT.md and SCOPE.md.' created: '2026-08-28T19:30:28.087109Z' updated: '2026-08-28T21:05:00Z' +state_hub_intake_id: "01a049ed-bbbc-7520-bc7c-6b0912ca534a" ``` diff --git a/workplans/ADHOC-2026-06-27.md b/workplans/ADHOC-2026-06-27.md index dfbe370..e7e0a23 100644 --- a/workplans/ADHOC-2026-06-27.md +++ b/workplans/ADHOC-2026-06-27.md @@ -9,6 +9,7 @@ owner: claude topic_slug: custodian created: "2026-06-27" updated: "2026-06-27" +state_hub_workstream_id: "a222c91f-3bb5-58a4-b6b2-f0fb18cdd5c3" --- # Ad Hoc Tasks — 2026-06-27 diff --git a/workplans/ADHOC-2026-06-29.md b/workplans/ADHOC-2026-06-29.md index 7346a3d..d078876 100644 --- a/workplans/ADHOC-2026-06-29.md +++ b/workplans/ADHOC-2026-06-29.md @@ -9,6 +9,7 @@ owner: claude topic_slug: custodian created: "2026-06-29" updated: "2026-06-29" +state_hub_workstream_id: "13fa845f-852e-55ec-a2a5-2296996e0216" --- # Ad Hoc Tasks — 2026-06-29 diff --git a/workplans/ADHOC-2026-08-11.md b/workplans/ADHOC-2026-08-11.md index a8734b0..a25c69f 100644 --- a/workplans/ADHOC-2026-08-11.md +++ b/workplans/ADHOC-2026-08-11.md @@ -9,6 +9,7 @@ owner: claude topic_slug: custodian created: "2026-08-11" updated: "2026-08-15" +state_hub_workstream_id: "9f99cc64-4682-5f20-b13e-89af2b6f7c70" --- # Ad Hoc Tasks — 2026-08-11 diff --git a/workplans/ADHOC-2026-08-17.md b/workplans/ADHOC-2026-08-17.md index 431ecd6..1b0b62f 100644 --- a/workplans/ADHOC-2026-08-17.md +++ b/workplans/ADHOC-2026-08-17.md @@ -9,6 +9,7 @@ owner: claude topic_slug: custodian created: "2026-08-17" updated: "2026-08-17" +state_hub_workstream_id: "5c6c2bbb-b944-5afd-b89c-20d865518849" --- # Ad Hoc Tasks — 2026-08-17 diff --git a/workplans/archived/260707-ADHOC-2026-07-07.md b/workplans/archived/260707-ADHOC-2026-07-07.md index aadfbbd..fc02506 100644 --- a/workplans/archived/260707-ADHOC-2026-07-07.md +++ b/workplans/archived/260707-ADHOC-2026-07-07.md @@ -9,6 +9,7 @@ owner: grok topic_slug: custodian created: "2026-07-07" updated: "2026-07-07" +state_hub_workstream_id: "90568b1e-8395-5c67-9c69-851ed08ff3d3" --- > **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`). From d7f4ebcfe0769dc704b37f5dbac14957ec826318 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 21:55:33 +0200 Subject: [PATCH 12/32] Re-emit the high-risk path artifact after the NetKingdom SSO lanes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c374d41 added net-kingdom-lldap-bind-credential and net-kingdom-privacyidea-admin-token as `risk: high` and did not re-run the emitter, so registry/generated/high-risk-data-paths.yaml still described the catalog at 0fae090. railiance-platform consumes that file instead of hand-maintaining its deny list, and it has been reading a census two lanes short since 2026-08-23. This is precisely the drift WARDEN-WP-0033-T03 built the guard for — a lane graded high after the last emit silently failing to reach the consumer. The guard fired; nothing had acted on it. The deny list itself does not move: both lanes are blocked on their OpenBao path being published, so they land in `no_concrete_path` and concrete_path_count stays 14. What changes is the count the consumer sees — 23 high-risk lanes, two of which have no address yet. That is the honest signal and the reason the bucket is listed rather than omitted. check_agent_read_boundary.py still reports 0 uncovered. The workload-join census moves 9 -> 11 not-applicable: both lanes are provider/control-plane credentials rather than workload delivery lanes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- registry/generated/high-risk-data-paths.yaml | 10 ++++++---- tests/test_workload_join.py | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index 6c2c341..a0b7ea0 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,12 +10,12 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-22T23:31:10Z" +generated_at: "2026-08-28T19:54:29Z" source: ops-warden/registry/routing/catalog.yaml -catalog_revision: "0fae0904ce8d8694338dd53a8a79abec5fec788d" -catalog_revision_date: "2026-08-23T01:31:05+02:00" +catalog_revision: "c374d41a4925720ae7706dfda020537b60a07eb9" +catalog_revision_date: "2026-08-23T21:43:12+02:00" catalog_dirty: false -high_risk_lane_count: 21 +high_risk_lane_count: 23 concrete_path_count: 14 # Graded high but not a single KV address -- a routing pattern, a broker @@ -23,6 +23,8 @@ concrete_path_count: 14 no_concrete_path: - database-dynamic-credentials - inter-hub-bootstrap-ssh + - net-kingdom-lldap-bind-credential + - net-kingdom-privacyidea-admin-token - object-storage-sts - openbao-api-key - openbao-platform-admin-login diff --git a/tests/test_workload_join.py b/tests/test_workload_join.py index 559a875..dab4df8 100644 --- a/tests/test_workload_join.py +++ b/tests/test_workload_join.py @@ -14,7 +14,9 @@ def test_repo_catalog_uses_only_explicit_workload_references(): assert report["ok"] is True assert len(report["resolved"]) == 3 assert len(report["unknown"]) == 17 - assert len(report["not_applicable"]) == 9 + # 11 since WARDEN-WP-0033: the two NetKingdom SSO lanes (c374d41) are + # provider/control-plane credentials, not workload delivery lanes. + assert len(report["not_applicable"]) == 11 assert {row["lane"] for row in report["resolved"]} == { "ops-warden-warden-sign-token", "issue-core-ingestion-api-key", From ee94c189385271194f22a53998b2c6e12e961ea9 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 22:00:09 +0200 Subject: [PATCH 13/32] =?UTF-8?q?WARDEN-WP-0033=20finished=20=E2=80=94=20k?= =?UTF-8?q?ey-cape=20accepted=20the=20issuance=20question=20five=20days=20?= =?UTF-8?q?ago?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit T04 was the last open task, waiting on key-cape to accept or refuse ownership of the coding-agent OpenBao issuance identity. They accepted, in KEY-WP-0009-T03, on 2026-08-23: codex-railiance-platform is published in their config/service-clients.example.yaml with subject service:codex:railiance-platform, role coding-agent, scope openbao:login, 15m lifetime, and the service-auth semantics in docs/openbao-service-auth-contract.md. The split is the one we routed for — KeyCape issues, railiance-platform binds the OpenBao role, OpenBao enforces, no secret value in either repo. We found it by reading their repository. KEY-WP-0009-T04 records replying to ops-warden; the inbox has zero messages from key-cape, read or unread. The task sat `wait` on an answer that already existed. That is T05's own lesson arriving on T04: a blocker is a claim about the world at a date. So the same pass re-verified the two lanes pointing at key-cape against their source instead of bumping dates: - rapp-qonto-keycape-client -> verified: source-read. KEY-WP-0009-T02 did add bounded service-auth, but that is client_credentials JWT issuance for OpenBao machine login and does not front this client_secret_basic exchange or its rotation. Blocker stands, now with evidence rather than memory. - key-cape-oidc-login -> asked of key-cape today, which the entry had recorded as still outstanding since 2026-08-21. Also cleared the inbox that hid this: 9 stale unread, all superseded by shipped work, with late closes sent to secrets-engine and llm-connect on the two threads that had asked ops-warden something and never got an answer. 391 tests pass, ruff clean, boundary coverage 0 uncovered. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- registry/generated/high-risk-data-paths.yaml | 4 +-- registry/routing/catalog.yaml | 10 +++--- .../WARDEN-WP-0033-native-lane-handoff.md | 33 +++++++++++++++++-- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index a0b7ea0..35d494b 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,11 +10,11 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-28T19:54:29Z" +generated_at: "2026-08-28T19:58:57Z" source: ops-warden/registry/routing/catalog.yaml catalog_revision: "c374d41a4925720ae7706dfda020537b60a07eb9" catalog_revision_date: "2026-08-23T21:43:12+02:00" -catalog_dirty: false +catalog_dirty: true high_risk_lane_count: 23 concrete_path_count: 14 diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 0ab246b..09f690e 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -281,8 +281,8 @@ entries: delegation: mode: interim intended_owner: key-cape - blocked_on: "REFUSED by secrets-engine 2026-08-21: login, MFA and identity-token issuance are key-cape/Keycloak's; secrets-engine may consume OIDC for OpenBao auth but does not own the login capability. ops-warden agrees — intended_owner corrected from secrets-engine to key-cape. Not yet asked of key-cape." - reviewed: "2026-08-21" + blocked_on: "REFUSED by secrets-engine 2026-08-21: login, MFA and identity-token issuance are key-cape/Keycloak's; secrets-engine may consume OIDC for OpenBao auth but does not own the login capability. ops-warden agrees — intended_owner corrected from secrets-engine to key-cape. Asked of key-cape 2026-08-28; KEY-WP-0009 accepting issuance ownership for machine identities is the precedent that makes it answerable." + reviewed: "2026-08-28" verified: asked-and-waiting # Login lane (WP-0014 T4) — interactive auth bootstrap, not a secret read. No # secret-read gate (you have no identity yet) and no caller-auth precheck (the @@ -710,9 +710,9 @@ entries: delegation: mode: interim intended_owner: key-cape - blocked_on: "client_secret_basic exchange is a key-cape protocol procedure, not a KV read; KEY-WP-0008 finished 2026-08-15 without a key-cape-native exchange/rotation command, and the workplan that would add one is not yet opened (key-cape acked interim 2026-08-15)" - reviewed: "2026-08-17" - verified: unverified + blocked_on: "client_secret_basic exchange is a key-cape protocol procedure, not a KV read; still no key-cape-native exchange/rotation command. Re-checked against key-cape source 2026-08-28: KEY-WP-0009 finished 2026-08-23 and did add bounded service-auth (per-client tokenLifetime, docs/openbao-service-auth-contract.md), but that is client_credentials JWT issuance for OpenBao machine login — it does not front this client_secret_basic exchange or its rotation. The server advertises client_secret_basic (src/internal/server/oidc/discovery.go) without exposing an owner command for it. Blocker stands." + reviewed: "2026-08-28" + verified: source-read risk: high workload_ref: applicability: applicable diff --git a/workplans/WARDEN-WP-0033-native-lane-handoff.md b/workplans/WARDEN-WP-0033-native-lane-handoff.md index 1e20015..55cd015 100644 --- a/workplans/WARDEN-WP-0033-native-lane-handoff.md +++ b/workplans/WARDEN-WP-0033-native-lane-handoff.md @@ -4,14 +4,14 @@ type: workplan title: "Native lane handoff — review secrets-engine's catalog admission, and fix what it exposed" domain: infotech repo: ops-warden -status: active +status: finished owner: ops-warden topic_slug: netkingdom planning_priority: P1 depends_on_workplans: - WARDEN-WP-0030 created: "2026-08-21" -updated: "2026-08-23" +updated: "2026-08-28" state_hub_workstream_id: "4627d89b-4b00-562a-81e9-76e96f90fa7e" --- @@ -160,7 +160,7 @@ railiance-platform may deny more, deny less, or dispute a grade (`ADR-0002`). ```task id: WARDEN-WP-0033-T04 -status: wait +status: done priority: medium state_hub_task_id: "5acac140-a586-5db3-b231-bbf236710786" ``` @@ -212,6 +212,33 @@ accept that target identity with an authoritative workplan/interface, or refuse and name the actual owner. T04 remains `wait` until one of those two answers is recorded; the live AppRole is operational evidence, not an ownership answer. +**Answered — accepted. Closed 2026-08-28.** `key-cape` accepted issuance +ownership in `KEY-WP-0009-T03` (`status: done`, 2026-08-23): the non-secret static +registration `codex-railiance-platform` is published in +`key-cape/config/service-clients.example.yaml` — subject +`service:codex:railiance-platform`, tenant `tenant:coulomb`, role `coding-agent`, +scope `openbao:login`, `client_credentials`, 15-minute lifetime — with the +service-auth claims, renewal, expiry and failure semantics in +`key-cape/docs/openbao-service-auth-contract.md` (`T02`). The split is exactly the +one the routing asked for: KeyCape owns JWT issuance and client disablement, +railiance-platform owns the exact-bound OpenBao role and policy, OpenBao owns +enforcement, and no secret value enters either repository. + +**The answer was found by reading their repo, not by receiving it.** +`KEY-WP-0009-T04` records replying to ops-warden; no such message exists in the +ops-warden inbox — 0 messages from `key-cape`, read or unread. The acceptance had +been sitting done for five days while this task sat `wait` on it. + +That is the T05 lesson landing on T04: a blocker is a claim about the world at a +date, and this one had stopped being true. `verified: source-read` is doing real +work here — it is the difference between "we asked" and "we checked". The +mechanism is right; what it needs is for someone to run it, which is why the +lanes below were re-verified in the same pass rather than date-bumped. + +Consequence for `ADR-0004`: the honour-system `WARDEN_AGENT_ID` marker now has a +real issuance identity behind it on the OpenBao side. ops-warden remains a +consumer of that identity and does not own it. + ```task id: WARDEN-WP-0033-T05 status: done From 61c992923c3c99604eddcbe3653cbe8d92e29e37 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 22:01:47 +0200 Subject: [PATCH 14/32] WARDEN-WP-0027-T02: the owner gate closed five days ago MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit railiance-platform accepted ops-warden revision 0fae0904 on 2026-08-23, in RPF-WP-0017 (status: finished), together with railiance-infra approval at 186b030 and all five acceptance criteria met. T02 has been sitting `progress` on a gate that was already open. Verified rather than trusted: the receipt at bc1966da hashes to d2ba444ed16989590325697e69d25283dc75a9432c29a72e627e80bf9fd987e4, matching their record exactly. One reason it went unnoticed is an identifier mismatch — T02 cites the remediation interface as RAILIANCE-WP-0026-T01, but it is RPF-WP-0017-T01 in the owner repo, and the cited id resolves to an unrelated workplan there. Their acceptance is source acceptance only and authorizes no live drill, so T02 stays progress: what unblocks is preparing a NEW scenario, which needs a fresh human GO and is the platform owner s to execute. Surfaced, not taken. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- ...-WP-0027-credential-governance-lockdown.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/workplans/WARDEN-WP-0027-credential-governance-lockdown.md b/workplans/WARDEN-WP-0027-credential-governance-lockdown.md index 840f291..a111c31 100644 --- a/workplans/WARDEN-WP-0027-credential-governance-lockdown.md +++ b/workplans/WARDEN-WP-0027-credential-governance-lockdown.md @@ -222,6 +222,39 @@ test results, and infra acceptance. T02 remains `progress` until that owner gate is open; acceptance will permit preparation of a new scenario, not execution or reuse of the terminal one. +**Owner gate CLOSED — accepted 2026-08-23, found 2026-08-28.** +`railiance-platform` accepted the exact revision `0fae0904`. Recorded in their +`RPF-WP-0017-attended-login-output-containment.md` (`status: finished`), which +also records railiance-infra's independent approval at `186b030` and marks all +five acceptance criteria met. The receipt digest was verified here rather than +taken on trust: `docs/evidence/RAILIANCE-WP-0026-T01-ops-warden-receipt.json` at +ops-warden `bc1966da` hashes to +`d2ba444ed16989590325697e69d25283dc75a9432c29a72e627e80bf9fd987e4`, matching +their record exactly. + +Note the identifier: the remediation interface recorded above as +`RAILIANCE-WP-0026-T01` is `RPF-WP-0017-T01` in the owner's repo. Searching for +the cited id finds an unrelated workplan, which is part of why this sat unnoticed. + +**Their acceptance is source acceptance only and authorizes no live OIDC or +drill** — their words, and the boundary holds. So T02's state changes but its +`Done when` does not: what was blocked was *preparing a new scenario*, and that +is now permitted. The terminal NO-GO scenario and its receipts remain unusable. + +**Third instance of the same failure this session.** The acceptance existed for +five days; no message reached ops-warden. Identically, `key-cape` accepted the +WP-0033-T04 question on 2026-08-23 with no message, and nine unread messages +were sitting on already-superseded threads. The `verified:` field added by +WP-0033-T05 was built for exactly this and it works — what does not work is +waiting for a counterparty to tell you. Re-checking a blocker means reading the +owner's repository. + +**Remaining to close T02:** one attended production emergency seal/unseal drill, +requiring a new scenario id, fresh owner receipts from platform/infra/master, a +fully parameterized green preflight, and a new human GO. It is executed by the +platform owner, never by a coding agent. That is an operator decision, not an +agent one, so T02 stays `progress` and the decision is surfaced rather than taken. + ## Task: Tamper-evident policy governance + reconcile ```task From a45280f30da866254e3d00661bf875b6456466ea Mon Sep 17 00:00:00 2001 From: custodian-sync Date: Fri, 28 Aug 2026 22:02:58 +0200 Subject: [PATCH 15/32] chore(consistency): sync task status from DB [auto] Updated by fix-consistency on 2026-08-28: - update .custodian-brief.md for ops-warden Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- .custodian-brief.md | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.custodian-brief.md b/.custodian-brief.md index a0eb681..eb06359 100644 --- a/.custodian-brief.md +++ b/.custodian-brief.md @@ -2,29 +2,17 @@ # Custodian Brief — ops-warden **Domain:** infotech -**Last synced:** 2026-08-25 18:17 UTC +**Last synced:** 2026-08-28 20:02 UTC **State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)* ## Active Workstreams -### Native lane handoff — review secrets-engine's catalog admission, and fix what it exposed -Progress: 5/6 done | workplan_id: `4627d89b-4b00-562a-81e9-76e96f90fa7e` - -**Open tasks:** -- ! Tasks `5acac140` - ### Tamper-resistant credential governance + mass rotation/lockdown (Strand B) Progress: 2/3 done | workplan_id: `21528e8d-a049-523d-9ae1-da7a27cb8bbf` **Open tasks:** - ► Task: Graded lockdown / break-glass with explicit trust-root `cae498ee` -## Inbox Hygiene - -**Stale unread:** 9 message(s) older than 3 day(s) — triage at session start. -**Missing thread_id:** 7 unread message(s) lack supersession chains. -- ! secrets-engine: Re: Need the warden-sign live apply/handoff (FLEX-WP-0007 T4) `80456912` - --- ## MCP Orientation (when available) From f289465b90fcdffe2c8bf4a51cc71607747126f9 Mon Sep 17 00:00:00 2001 From: repo-manager Date: Fri, 28 Aug 2026 22:40:24 +0200 Subject: [PATCH 16/32] repo.work.create_intake WARDEN-IN-0002 correlation_id: 676e92a9-dc2e-4101-a31c-a584962c25df reason: Propose layer model v0.3 for review source: repo-manager Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9 --- intakes/intakes.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/intakes/intakes.md b/intakes/intakes.md index 4a91201..192d793 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -53,3 +53,40 @@ created: '2026-08-28T19:30:28.087109Z' updated: '2026-08-28T21:05:00Z' state_hub_intake_id: "01a049ed-bbbc-7520-bc7c-6b0912ca534a" ``` + +## WARDEN-IN-0002 — Review requested: security layer model v0.3 — and does maturity-engine absorb warden route gaps? + +```yaml +id: WARDEN-IN-0002 +kind: intake +title: 'Review requested: security layer model v0.3 — and does maturity-engine absorb + warden route gaps?' +status: open +origin: cross-repo +origin_ref: net-kingdom security-layer-model_v0.3 +priority: medium +owner: ops-warden +requested_by: gate-house +description: 'v0.3 is proposed and changes sections 4, 9 and 13 only; the v0.2 assent + record stands. Two new engines: approval-engine (section 9.4) and maturity-engine + (section 9.5). THE QUESTION FOR YOU concerns section 5.3, which exists because you + offered the amendment. v0.3 gives declared gaps an owner: maturity-engine takes + the gap register with intended_owner, blocked_on and review dates, and section 13 + now says the register in the standard is interim and should not outlive that engine. + You offered warden route gaps and the 27 delegation catalog entries as reusable + prior art. So the question is whether that machinery should MOVE, be MIRRORED, or + STAY. Our tentative reading, which we want tested rather than accepted: routing + is yours and stays yours — warden route find answers where a credential need goes, + and that is lane knowledge, not maturity. What might move is the readiness half: + whether a declared gap is still within its review date, and whether an intended + owner has an engine surface yet. If splitting those creates two sources for one + fact, that is worse than either option and we would rather hear it now. Your SSH-CA + signing write would be tracked in maturity-engine as a declared gap with intended + owner secrets-engine and a review date — that is reporting your own non-conformance + to an engine, so we would rather you assent to it than discover it. Also note approval-engine + (section 9.4): it owns the approval object, not the approval workflow, so ops-warden + lanes needing approval consume a claim rather than implementing one. Assent, revision, + or rejection acceptable.' +created: '2026-08-28T20:40:24.957468Z' +updated: '2026-08-28T20:40:24.957468Z' +``` From 57d39ede0f6c85fde3f2d4f3eb0b08b5f671e385 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 28 Aug 2026 22:43:06 +0200 Subject: [PATCH 17/32] Refresh work-record index Regenerated by fix-consistency; adds the inbound v0.3 review intake. Co-Authored-By: Claude Opus 5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2564823@bnt-lap001 Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9 --- WORK-RECORDS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 8bbeb08..5425d47 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -29,7 +29,7 @@ | workplan | WARDEN-WP-0030 | finished | — | workplans/WARDEN-WP-0030-delegation-register.md | | workplan | WARDEN-WP-0031 | finished | — | workplans/WARDEN-WP-0031-policy-caller-identity.md | | workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md | -| workplan | WARDEN-WP-0033 | active | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | +| workplan | WARDEN-WP-0033 | finished | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md | | task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md | | task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md | @@ -126,7 +126,8 @@ | task | WARDEN-WP-0033-T01 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T02 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T03 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | -| task | WARDEN-WP-0033-T04 | wait | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | +| task | WARDEN-WP-0033-T04 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md | +| intake | WARDEN-IN-0002 | open | — | intakes/intakes.md | From f815bb35caad1d157f5407576abaa02ffec02b2b Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 29 Aug 2026 02:45:29 +0200 Subject: [PATCH 18/32] =?UTF-8?q?Implement=20=C2=A75.3=20machine-readably?= =?UTF-8?q?=20=E2=80=94=20layer.yaml,=20checker,=20conformance=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The security layer model moved v0.1 -> v0.4 (accepted) after ops-warden's assent. Both §5 asks from ADR-0010 were adopted: §5.2 now sanctions the conduit shape on the supplied-authority property, and §5.3 is the declared engine gap amendment, carrying the four fields verbatim and crediting ops-warden's delegation machinery as prior art. Which creates an obligation. §5.3 requires those fields MACHINE-READABLY, and §11 makes "every direct Tooling client maps to a declared §5.1/§5.2/§5.3 entry" a mechanical check. ops-warden's declaration was prose in INTENT.md — the repo that proposed the shape was not implementing it. layer.yaml is the map: 5 contacts (2 declared gaps, 1 read-only observation, 2 conduits) plus the non-Tooling clients recorded explicitly so the check is total rather than silently selective. scripts/check_layer_conformance.py enforces it and found three undeclared modules on its first run — all false positives (help text, a docstring, and the doubles library that SIMULATES bao rather than calling it), which is why the scan now matches invocation shapes instead of the word: an httpx call built against the configured OpenBao address, or an argv whose first element is the bao binary. tests/test_layer_conformance.py adds the §5.2 test the standard says SHOULD exist: _caller_env() returns the caller's environment unchanged, and proxy.py is asserted not to reference X-Vault-Token, approle login, or token create — a conduit that presents its own token is not a conduit. No assertion on review dates, deliberately: a date-triggered failure breaks the build on a calendar day with no code change, the same reasoning WP-0033-T05 recorded for blocker staleness. 398 tests pass, ruff clean. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- .repo-manager/index.json | 66 +++++--- INTENT.md | 16 +- layer.yaml | 123 ++++++++++++++ registry/generated/high-risk-data-paths.yaml | 8 +- scripts/check_layer_conformance.py | 164 +++++++++++++++++++ tests/test_layer_conformance.py | 98 +++++++++++ 6 files changed, 448 insertions(+), 27 deletions(-) create mode 100644 layer.yaml create mode 100644 scripts/check_layer_conformance.py create mode 100644 tests/test_layer_conformance.py diff --git a/.repo-manager/index.json b/.repo-manager/index.json index a0e6bd2..95e4806 100644 --- a/.repo-manager/index.json +++ b/.repo-manager/index.json @@ -1,10 +1,10 @@ { "schema": "repo_manager.index.v1", - "slug": "layer-model-assent", + "slug": "layer-model-v03-review", "repo_root": "/home/worsch/ops-warden", - "head_sha": "467635e84b99757336ee49d7f0dbf107607d0560", - "observed_at": "2026-08-28T19:30:29.828983Z", - "source_fingerprint": "7dfae4f3d33f6a9503a2c7326b925efb378613e772b39c4dd9b0640a35b85654", + "head_sha": "f289465b90fcdffe2c8bf4a51cc71607747126f9", + "observed_at": "2026-08-28T20:40:26.143458Z", + "source_fingerprint": "a9ae0d530804e039aae34b4902d8609723e9bba4385a501b9a4027911c3b6302", "source_files": [ ".repo-classification.yaml", "INTENT.md", @@ -55,7 +55,7 @@ "status": "finished", "title": "Ad Hoc Tasks \u2014 2026-06-27", "source_path": "workplans/ADHOC-2026-06-27.md", - "uuid": null, + "uuid": "a222c91f-3bb5-58a4-b6b2-f0fb18cdd5c3", "parent_id": null, "extra": {} }, @@ -75,7 +75,7 @@ "status": "finished", "title": "Ad Hoc Tasks \u2014 2026-06-29", "source_path": "workplans/ADHOC-2026-06-29.md", - "uuid": null, + "uuid": "13fa845f-852e-55ec-a2a5-2296996e0216", "parent_id": null, "extra": {} }, @@ -95,7 +95,7 @@ "status": "finished", "title": "Ad Hoc Tasks \u2014 2026-08-11", "source_path": "workplans/ADHOC-2026-08-11.md", - "uuid": null, + "uuid": "9f99cc64-4682-5f20-b13e-89af2b6f7c70", "parent_id": null, "extra": {} }, @@ -135,7 +135,7 @@ "status": "finished", "title": "Ad Hoc Tasks \u2014 2026-08-17", "source_path": "workplans/ADHOC-2026-08-17.md", - "uuid": null, + "uuid": "5c6c2bbb-b944-5afd-b89c-20d865518849", "parent_id": null, "extra": {} }, @@ -1192,7 +1192,7 @@ { "kind": "workplan", "id": "WARDEN-WP-0033", - "status": "active", + "status": "finished", "title": "Native lane handoff \u2014 review secrets-engine's catalog admission, and fix what it exposed", "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", "uuid": "4627d89b-4b00-562a-81e9-76e96f90fa7e", @@ -1232,7 +1232,7 @@ { "kind": "task", "id": "WARDEN-WP-0033-T04", - "status": "wait", + "status": "done", "title": "Tasks", "source_path": "workplans/WARDEN-WP-0033-native-lane-handoff.md", "uuid": "5acac140-a586-5db3-b231-bbf236710786", @@ -2155,7 +2155,7 @@ "status": "finished", "title": "Ad Hoc Tasks \u2014 2026-07-07", "source_path": "workplans/archived/260707-ADHOC-2026-07-07.md", - "uuid": null, + "uuid": "90568b1e-8395-5c67-9c69-851ed08ff3d3", "parent_id": null, "extra": {} }, @@ -2172,17 +2172,18 @@ { "kind": "intake", "id": "WARDEN-IN-0001", - "status": "open", + "status": "closed", "title": "Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule demarcation", "source_path": "intakes/intakes.md", - "uuid": null, + "uuid": "01a049ed-bbbc-7520-bc7c-6b0912ca534a", "parent_id": null, "extra": { "record": { "id": "WARDEN-IN-0001", "kind": "intake", "title": "Assent requested: Staff layer, doctrine vs runbook, and the access lane/rule demarcation", - "status": "open", + "status": "closed", + "outcome": "assented", "origin": "cross-repo", "origin_ref": "gate-house GH-DEC-2026-001", "priority": "medium", @@ -2190,8 +2191,35 @@ "requested_by": "gate-house", "standard": "net-kingdom/canon/standards/security-layer-model_v0.1.md", "description": "gate-house asks ops-warden to assent to three boundary items. (1) ops-warden is Staff, bound by the rule that Staff acts only through Engine APIs and never touches Tooling directly (standard section 5). (2) Doctrine versus runbook: the NetKingdom Security Literacy section in ops-warden INTENT is evidence the security curriculum had no owner; it now has one in gate-house. Proposal is that doctrine and curriculum move to gate-house and that section becomes lane-specific runbooks referencing gate-house doctrine rather than restating it. ops-warden keeps the lanes it stewards and everything operational about them. (3) The access lane/rule demarcation, normative in standard section 8: ops-warden and ops-mason own access lanes \u2014 how a worker reaches a host; access-engine owns access rules \u2014 whether they may. This demarcation is the condition attached to renaming flex-auth to access-engine, so ops-warden effectively holds a veto on that name. Also requested: add gate-house to the Security Literacy and routing tables \u2014 currently every plane is listed and gate-house appears nowhere \u2014 routing doctrine and authority-model questions there while continuing to route policy decisions to access-engine. If moving the curriculum out leaves ops-warden unable to instruct its own workers, say so; the boundary is wrong if it does.", + "notes": "Assented to all three items in ADR-0010, with reasoning in history/2026-08-28-security-layer-model-assent.md. (1) Staff accepted; the section 5 binding rule exposed a real non-conformance \u2014 src/warden/vault.py is a direct OpenBao client performing a write, as is warden desk's bao kv put. Declared in INTENT.md as an engine gap with intended owner secrets-engine and blocker \"no engine exposes an SSH-CA surface\", not negotiated as an exemption; taint.py declared under the read-only allowance; warden access proxies run under the caller's identity. An amendment is offered back to gate-house: a second sanctioned shape in section 5 for a declared engine gap carrying intended owner, blocker and review date, machine-readable so section 10 can tell a tracked gap from an undeclared violation. (2) Doctrine versus runbook accepted; the literacy section is now a lane routing runbook referencing gate-house doctrine. Answering gate-house's test question: it does not leave ops-warden unable to instruct its workers, because what instructs them is warden plan / warden route and .claude/rules/credential-routing.md, which stays inline by design. (3) The lane/rule demarcation assented unconditionally and the access-engine veto not exercised \u2014 ops-warden already consumes decisions and renders none. One request on sequencing only: a deprecation window in which both names resolve (598 references across 82 files here). gate-house added to the routing tables in INTENT.md and SCOPE.md.", "created": "2026-08-28T19:30:28.087109Z", - "updated": "2026-08-28T19:30:28.087109Z" + "updated": "2026-08-28T21:05:00Z", + "state_hub_intake_id": "01a049ed-bbbc-7520-bc7c-6b0912ca534a" + } + } + }, + { + "kind": "intake", + "id": "WARDEN-IN-0002", + "status": "open", + "title": "Review requested: security layer model v0.3 \u2014 and does maturity-engine absorb warden route gaps?", + "source_path": "intakes/intakes.md", + "uuid": null, + "parent_id": null, + "extra": { + "record": { + "id": "WARDEN-IN-0002", + "kind": "intake", + "title": "Review requested: security layer model v0.3 \u2014 and does maturity-engine absorb warden route gaps?", + "status": "open", + "origin": "cross-repo", + "origin_ref": "net-kingdom security-layer-model_v0.3", + "priority": "medium", + "owner": "ops-warden", + "requested_by": "gate-house", + "description": "v0.3 is proposed and changes sections 4, 9 and 13 only; the v0.2 assent record stands. Two new engines: approval-engine (section 9.4) and maturity-engine (section 9.5). THE QUESTION FOR YOU concerns section 5.3, which exists because you offered the amendment. v0.3 gives declared gaps an owner: maturity-engine takes the gap register with intended_owner, blocked_on and review dates, and section 13 now says the register in the standard is interim and should not outlive that engine. You offered warden route gaps and the 27 delegation catalog entries as reusable prior art. So the question is whether that machinery should MOVE, be MIRRORED, or STAY. Our tentative reading, which we want tested rather than accepted: routing is yours and stays yours \u2014 warden route find answers where a credential need goes, and that is lane knowledge, not maturity. What might move is the readiness half: whether a declared gap is still within its review date, and whether an intended owner has an engine surface yet. If splitting those creates two sources for one fact, that is worse than either option and we would rather hear it now. Your SSH-CA signing write would be tracked in maturity-engine as a declared gap with intended owner secrets-engine and a review date \u2014 that is reporting your own non-conformance to an engine, so we would rather you assent to it than discover it. Also note approval-engine (section 9.4): it owns the approval object, not the approval workflow, so ops-warden lanes needing approval consume a claim rather than implementing one. Assent, revision, or rejection acceptable.", + "created": "2026-08-28T20:40:24.957468Z", + "updated": "2026-08-28T20:40:24.957468Z" } } } @@ -2201,15 +2229,15 @@ "type": "repo.command.applied", "command": "repo.work.create_intake", "operation": "create", - "correlation_id": "65d40cdd-5894-440e-9c95-c6bcfe259b66", + "correlation_id": "676e92a9-dc2e-4101-a31c-a584962c25df", "kind": "intake", - "id": "WARDEN-IN-0001", - "git_sha": "467635e84b99757336ee49d7f0dbf107607d0560", + "id": "WARDEN-IN-0002", + "git_sha": "f289465b90fcdffe2c8bf4a51cc71607747126f9", "files_touched": [ "intakes/intakes.md" ], "source": "repo-manager", - "emitted_at": "2026-08-28T19:30:29.829125Z" + "emitted_at": "2026-08-28T20:40:26.143617Z" } ] } diff --git a/INTENT.md b/INTENT.md index d1c0a97..86254a7 100644 --- a/INTENT.md +++ b/INTENT.md @@ -3,8 +3,9 @@ > **Layer: Staff.** ops-warden is a Staff repository under the NetKingdom > IT-security layer model (Taxonomy -> Tooling -> Engines -> Staff, layered by > determinism and by the kind of artifact each layer produces): -> `net-kingdom/canon/standards/security-layer-model_v0.1.md`, owned by gate-house, -> ratified as `gate-house/decisions/decisions.md` GH-DEC-2026-001. +> `net-kingdom/canon/standards/security-layer-model_v0.4.md` (**accepted**), owned by +> gate-house, ratified as `gate-house/decisions/decisions.md` GH-DEC-2026-001. +> ops-warden's assent is recorded there as `ADR-0010`. > > **The binding rule: Staff never touches Tooling directly. It acts only through > Engine APIs.** ops-warden holds no state another layer depends on at runtime and @@ -19,8 +20,15 @@ > runs the owner's tool under **the caller's** identity and supplies no authority of > its own (`ADR-0002`). > -> Assent, reasoning, and the amendment offered back to gate-house: -> `history/2026-08-28-security-layer-model-assent.md` and `ADR-0010`. +> **The declaration is `layer.yaml`, not this note.** v0.4 §5.3 requires a gap to +> carry `capability`, `intended_owner`, `blocked_on` and `review` *machine-readably*, +> and §11 makes "every direct Tooling client maps to a declared §5.1/§5.2/§5.3 entry" +> a mechanical check. `layer.yaml` is that map; `scripts/check_layer_conformance.py` +> and `tests/test_layer_conformance.py` enforce it, so a new undeclared OpenBao +> client fails on the commit that introduces it. +> +> Assent, reasoning, and the amendment offered back to gate-house — adopted as +> v0.4 §5.3: `history/2026-08-28-security-layer-model-assent.md` and `ADR-0010`. > This file captures **why this repository exists**, the **direction it is > moving toward**, and the **kind of system it is meant to become**. diff --git a/layer.yaml b/layer.yaml new file mode 100644 index 0000000..23d099a --- /dev/null +++ b/layer.yaml @@ -0,0 +1,123 @@ +# ops-warden — NetKingdom security layer declaration +# +# Framework: net-kingdom/canon/standards/security-layer-model_v0.4.md +# Assent: docs/adr/ADR-0010 (ops-warden's own voice, per §11 "who must declare") +# Validate: python3 scripts/check_layer_conformance.py +# +# §11 makes one check mechanical: "every direct Tooling client in a Staff +# repository maps to a declared §5.1, §5.2, or §5.3 entry". This file is that +# map. It is machine-readable because §5.3 requires it to be — ops-warden +# proposed that shape and is implementing it rather than declaring in prose. +# +# Conformance rule inherited from tenancy.yaml: accuracy, not altitude. A +# declared gap is TRACKED NON-CONFORMANCE (§11), never a claim of conformance. + +schema_version: "0.1" +framework: netkingdom-security-layer-model +standard_version: "0.4" +repository: ops-warden +layer: staff +declared_by: docs/adr/ADR-0010 +declared_at: "2026-08-29" + +# Every direct contact with a Tooling-layer system (§4), one entry each. +tooling_contacts: + + - id: ssh-ca-signing-write + shape: "5.3" # declared engine gap + module: src/warden/vault.py + symbol: VaultCA.sign + tooling: OpenBao + operation: "HTTP POST /v1//sign/ with X-Vault-Token" + write: true + capability: "Sign a short-lived SSH certificate for an adm/agt/atm actor" + intended_owner: secrets-engine + blocked_on: >- + No engine exposes an SSH certificate signing surface. secrets-engine owns + credential abstraction, custody and lifecycle, which is the layer this + belongs in, but fronts no SSH-CA API today. + review: "2026-11-28" + note: >- + Production-verified and in daily use. This is the one lane ops-warden owns + permanently (§4). Signing continues while the gap is open: refusing would + remove production host access to close a documentation gap. + + - id: desk-paste-once-provision + shape: "5.3" + module: src/warden/desk.py + symbol: _provision_to_openbao + tooling: OpenBao + operation: "bao kv put =- (value on stdin, never argv)" + write: true + capability: "Founder paste-once provisioning of a secret straight into OpenBao" + intended_owner: secrets-engine + blocked_on: >- + No engine exposes an attended provisioning surface for a value the founder + holds and no automated path can produce. + review: "2026-11-28" + note: >- + Attended and founder-operated (WP-0029). The value reaches OpenBao without + passing through a terminal, an argv, or the audit log. + + - id: taint-metadata-read + shape: "5.1" # read-only diagnostic observation + module: src/warden/taint.py + symbol: fetch_taint_status + tooling: OpenBao + operation: "bao kv metadata get -format=json " + write: false + capability: "Report EXPOSED taint (custom_metadata) without reading secret data" + intended_owner: secrets-engine + blocked_on: >- + No engine exposes a disclosure-taint query. Metadata-only by construction — + reading the data would be the 2026-07-16 vector this exists to avoid. + review: "2026-11-28" + + - id: access-proxy-conduit + shape: "5.2" # conduit + module: src/warden/proxy.py + symbol: proxy_fetch, proxy_attended_login_exec + tooling: OpenBao, key-cape + operation: "Runs the catalog-declared owner fetch_command as a child process" + write: false + capability: "warden access --fetch/--exec/--out/--wrap for exec_capable lanes" + supplied_authority: none + evidence: + no_own_credential: src/warden/proxy.py::_caller_env + test: tests/test_proxy.py::test_conduit_supplies_no_authority_of_its_own + audit: "audit.jsonl records the caller, the lane, and the outcome; never a value" + note: >- + The §5.2 test is the supplied-authority property: ops-warden presents no + credential of its own, cannot widen what the caller could already do, and + the action reconstructs as the caller's. Governed by ADR-0002. + + - id: caller-identity-token + shape: "5.2" + module: src/warden/caller_identity.py + symbol: resolve_caller_token + tooling: OpenBao + operation: "Runs the operator-configured caller_auth command, or reads token env" + write: false + capability: "Establish the caller's own identity for the pre-sign policy gate" + supplied_authority: none + detection: voluntary # runs an operator-configured command, so no fixed + # argv shape to scan for; declared rather than omitted + note: >- + Obtains the CALLER's credential by the operator's configured means; adds no + authority. Never mints, and never persists what it resolves. + +# Contacts that are deliberately NOT Tooling contacts, recorded so the check is +# total rather than silently selective. +non_tooling_clients: + + - module: src/warden/policy.py + target: access-engine (flex-auth) + rationale: "Engine API — §5 permits it; this is the shape §5 prescribes." + + - module: src/warden/worker.py + target: state-hub, llm-connect + rationale: >- + Not catalogued in §4. The layer catalog scopes the security estate, and + neither the State Hub nor llm-connect appears in it, so no §5 shape applies + on the standard's own terms. Raised with gate-house 2026-08-29 as a scope + question rather than resolved unilaterally — see the assessment note. diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index 35d494b..78d3ce6 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,11 +10,11 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-28T19:58:57Z" +generated_at: "2026-08-29T00:44:23Z" source: ops-warden/registry/routing/catalog.yaml -catalog_revision: "c374d41a4925720ae7706dfda020537b60a07eb9" -catalog_revision_date: "2026-08-23T21:43:12+02:00" -catalog_dirty: true +catalog_revision: "ee94c189385271194f22a53998b2c6e12e961ea9" +catalog_revision_date: "2026-08-28T22:00:09+02:00" +catalog_dirty: false high_risk_lane_count: 23 concrete_path_count: 14 diff --git a/scripts/check_layer_conformance.py b/scripts/check_layer_conformance.py new file mode 100644 index 0000000..5313a34 --- /dev/null +++ b/scripts/check_layer_conformance.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +"""Check ops-warden against the NetKingdom security layer model (§5, §11). + +Read-only. Makes §11's second mechanical check real: + + every direct Tooling client in a Staff repository maps to a declared + §5.1, §5.2, or §5.3 entry + +The failure this catches is a *new* direct OpenBao contact appearing in +src/warden/ without an entry in layer.yaml — an undeclared violation (§11), +which is a finding rather than a tracked gap. It deliberately does NOT check +the review dates: a date-triggered failure breaks the build on a calendar day +with no code change (the reasoning recorded in WARDEN-WP-0033-T05), so +staleness is reported and left to `--report`, never to CI. + +Exit 0 clean, 1 undeclared contact found, 2 declaration malformed. +""" +from __future__ import annotations + +import argparse +import re +import sys +from datetime import date +from pathlib import Path + +import yaml + +ROOT = Path(__file__).resolve().parents[1] +SRC = ROOT / "src" / "warden" +DECL = ROOT / "layer.yaml" + +VALID_SHAPES = {"5.1", "5.2", "5.3"} + +# A direct Tooling contact is an *invocation*, not a mention. Matching the word +# "bao" caught help text, a docstring, and the dev-tier doubles library that +# simulates bao rather than calling it — three false positives on first run. +# So match the two shapes that actually execute: +# 1. an HTTP request built against the OpenBao address +# 2. an argv list whose first element is the bao binary +TOOLING_PATTERNS = ( + # httpx call whose URL is built from the configured OpenBao/Vault address + re.compile(r"""\bhttpx\.\w+\(|url\s*=\s*f?["'].*\{self\._cfg\.addr\}"""), + # argv construction: [bao_bin, ...] / ["bao", ...] / [bao_binary, ...] + re.compile(r"""\[\s*(?:["']bao["']|bao_bin\b|bao_binary\b)\s*,"""), +) + +# httpx alone is not a Tooling contact — policy.py calls an Engine and worker.py +# calls the State Hub. A module matching only the httpx pattern counts as a +# contact only if it also references the OpenBao address configuration. +ADDR_HINT = re.compile(r"""_cfg\.addr|VAULT_ADDR|BAO_ADDR""") + +# Modules that talk to an Engine or to something outside the §4 catalog. Listed +# in layer.yaml under non_tooling_clients and excluded from the scan with it. +def _excluded(decl: dict) -> set[str]: + return {e["module"].split("/")[-1] for e in decl.get("non_tooling_clients", [])} + + +def load_declaration() -> dict: + if not DECL.exists(): + print(f"MISSING: {DECL} — ops-warden must declare in its own voice (§11)") + raise SystemExit(2) + decl = yaml.safe_load(DECL.read_text()) + for key in ("layer", "repository", "standard_version", "tooling_contacts"): + if key not in decl: + print(f"MALFORMED: layer.yaml has no {key!r}") + raise SystemExit(2) + for c in decl["tooling_contacts"]: + if c.get("shape") not in VALID_SHAPES: + print(f"MALFORMED: {c.get('id')} has shape {c.get('shape')!r}, not one of {sorted(VALID_SHAPES)}") + raise SystemExit(2) + # §5.3 carries four fields, machine-readably. That is the whole point of + # the shape; a gap missing them is prose wearing a schema. + if c["shape"] == "5.3": + for field in ("capability", "intended_owner", "blocked_on", "review"): + if not c.get(field): + print(f"MALFORMED: §5.3 entry {c['id']!r} is missing {field!r}") + raise SystemExit(2) + # §5.2's test is the supplied-authority property. + if c["shape"] == "5.2" and c.get("supplied_authority") != "none": + print(f"MALFORMED: §5.2 conduit {c['id']!r} must declare supplied_authority: none") + raise SystemExit(2) + return decl + + +def scan_modules() -> dict[str, list[int]]: + """Return {module_name: [line numbers]} for direct Tooling contacts.""" + found: dict[str, list[int]] = {} + for path in sorted(SRC.rglob("*.py")): + if path.name.startswith("test_"): + continue + text = path.read_text() + hits: list[int] = [] + for n, line in enumerate(text.splitlines(), 1): + stripped = line.strip() + if stripped.startswith("#") or stripped.startswith('"'): + continue + if any(p.search(line) for p in TOOLING_PATTERNS): + hits.append(n) + if hits: + # An httpx-only match needs the OpenBao address to be a Tooling + # contact; otherwise it is an Engine or non-catalogued call. + argv_shape = any(TOOLING_PATTERNS[1].search(ln) for ln in text.splitlines()) + if argv_shape or ADDR_HINT.search(text): + found[path.name] = hits + return found + + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("--report", action="store_true", help="also print the declaration and gap review dates") + args = ap.parse_args() + + decl = load_declaration() + declared = {c["module"].split("/")[-1] for c in decl["tooling_contacts"]} + excluded = _excluded(decl) + found = scan_modules() + + undeclared = {m: lines for m, lines in found.items() if m not in declared and m not in excluded} + # A voluntary declaration has no fixed argv shape to detect (an + # operator-configured command). Over-declaring is safe; not reporting it as + # stale keeps the signal meaningful. + voluntary = { + c["module"].split("/")[-1] + for c in decl["tooling_contacts"] + if c.get("detection") == "voluntary" + } + stale_decls = declared - set(found) - voluntary + + if args.report: + print(f"{decl['repository']} — layer: {decl['layer']} (model v{decl['standard_version']})") + print(f"declared by {decl['declared_by']}\n") + for c in decl["tooling_contacts"]: + line = f" §{c['shape']} {c['id']:<28} {c['module']}" + if c["shape"] == "5.3": + overdue = str(c["review"]) < date.today().isoformat() + line += f" -> {c['intended_owner']} review {c['review']}" + if overdue: + line += " [REVIEW OVERDUE]" + print(line) + gaps = [c for c in decl["tooling_contacts"] if c["shape"] == "5.3"] + print(f"\n{len(gaps)} declared gap(s) — tracked non-conformance, not conformance (§11).") + + ok = True + if undeclared: + ok = False + print("\nUNDECLARED TOOLING CONTACT — a finding under §11, not a tracked gap:") + for m, lines in sorted(undeclared.items()): + print(f" src/warden/{m}: line(s) {', '.join(map(str, lines[:6]))}") + print("\nAdd a §5.1/§5.2/§5.3 entry to layer.yaml, or route it through an engine.") + + if stale_decls: + print("\nNote: declared but no contact found (module removed or refactored?):") + for m in sorted(stale_decls): + print(f" {m}") + + if ok and not args.report: + print(f"PASS — {len(found)} module(s) with Tooling contact, all declared.") + elif ok: + print("\nPASS — every direct Tooling contact maps to a declared shape.") + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/test_layer_conformance.py b/tests/test_layer_conformance.py new file mode 100644 index 0000000..86b39a0 --- /dev/null +++ b/tests/test_layer_conformance.py @@ -0,0 +1,98 @@ +"""Layer-model conformance (security-layer-model_v0.4 §5, §11). + +Two things are checked here. §11 makes one of them mechanical: every direct +Tooling client maps to a declared shape. §5.2 asks for the other: the conduit's +supplied-authority property covered by a test. + +Deliberately absent: any assertion on a §5.3 review date. A date-triggered +failure breaks the build on a calendar day with no code change, punishing +whoever commits next rather than whoever owns the gap — the same reasoning +recorded in WARDEN-WP-0033-T05 for blocker staleness. +""" +from __future__ import annotations + +import os +import subprocess +import sys +from pathlib import Path + +import yaml + +ROOT = Path(__file__).resolve().parents[1] + + +def _decl() -> dict: + return yaml.safe_load((ROOT / "layer.yaml").read_text()) + + +class TestDeclaration: + def test_declares_staff_layer_in_its_own_voice(self): + d = _decl() + assert d["repository"] == "ops-warden" + assert d["layer"] == "staff" + # §11: "only the repository's own file, in its own voice, conforms." + assert d["declared_by"] == "docs/adr/ADR-0010" + + def test_every_tooling_contact_maps_to_a_declared_shape(self): + """§11 mechanical check — the guard against a new undeclared client.""" + result = subprocess.run( + [sys.executable, str(ROOT / "scripts" / "check_layer_conformance.py")], + capture_output=True, + text=True, + ) + assert result.returncode == 0, ( + f"undeclared Tooling contact — a finding under §11, not a tracked gap:\n" + f"{result.stdout}{result.stderr}" + ) + + def test_declared_gaps_carry_all_four_fields(self): + """§5.3 is machine-readable or it is prose wearing a schema.""" + for c in _decl()["tooling_contacts"]: + if c["shape"] == "5.3": + for field in ("capability", "intended_owner", "blocked_on", "review"): + assert c.get(field), f"{c['id']} missing {field}" + + def test_gaps_are_not_counted_as_conformance(self): + """§11: a declared gap is tracked non-conformance. Keep that visible.""" + text = (ROOT / "layer.yaml").read_text() + assert "TRACKED NON-CONFORMANCE" in text.upper() + + +class TestConduitSuppliesNoAuthority: + """§5.2: 'MUST NOT present its own credential, MUST NOT widen what the + caller could already do.' The standard says this SHOULD be covered by a + test; this is that test.""" + + def test_conduit_supplies_no_authority_of_its_own(self, monkeypatch): + from warden import proxy + + monkeypatch.setenv("VAULT_TOKEN", "caller-own-token") + monkeypatch.setenv("HOME", "/home/nobody") + before = dict(os.environ) + + env = proxy._caller_env() + + # The child environment IS the caller's environment — nothing added, + # nothing removed, no ops-warden credential injected. + assert env == before, ( + "conduit altered the caller's environment; §5.2 requires it to " + "supply no authority of its own" + ) + assert env["VAULT_TOKEN"] == "caller-own-token" + + def test_conduit_declares_supplied_authority_none(self): + conduits = [c for c in _decl()["tooling_contacts"] if c["shape"] == "5.2"] + assert conduits, "no §5.2 conduit declared — proxy.py is one" + for c in conduits: + assert c["supplied_authority"] == "none" + + def test_proxy_holds_no_credential_constant(self): + """A conduit that presents its own token is not a conduit (§5.2).""" + src = (ROOT / "src" / "warden" / "proxy.py").read_text() + # It may name token ENV VARS to detect caller auth; it must not carry a + # token value or mint one. + for forbidden in ("X-Vault-Token", "auth/approle/login", "token create"): + assert forbidden not in src, ( + f"proxy.py references {forbidden!r} — that is presenting or " + f"minting authority, not conducting the caller's" + ) From ec625873fbb3dec3969ba6c4a6395eed003a36fb Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 29 Aug 2026 02:46:50 +0200 Subject: [PATCH 19/32] Review layer model v0.4; correct an unsound audit claim it exposes Assessment in history/2026-08-29-layer-model-v04-review.md. No objection to the ruling; both ops-warden amendments were adopted (5.2 conduit, 5.3 declared gap). Three findings, one against us. The one against us is real. 9.6 requires emission atomic with the state change for load-bearing evidence. ops-warden ca.py carries `pass # audit must not block signing` and AuditTrail.md advertises that the trail never blocks the primary action, so a failed append loses the event while the cert still issues -- a suppressed event leaving the chain intact, which is exactly what 9.6 describes. Whether to make it atomic is gate-house doctrine, not ops-wardens call: it would give the estates operational access lane a new dependency on its own evidence store. But one half of the fix is ours regardless -- the trail must not be read as complete. AuditTrail.md now says absence of a record is not evidence of absence, which it did not. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- history/2026-08-29-layer-model-v04-review.md | 136 +++++++++++++++++++ wiki/AuditTrail.md | 9 ++ 2 files changed, 145 insertions(+) create mode 100644 history/2026-08-29-layer-model-v04-review.md diff --git a/history/2026-08-29-layer-model-v04-review.md b/history/2026-08-29-layer-model-v04-review.md new file mode 100644 index 0000000..a548399 --- /dev/null +++ b/history/2026-08-29-layer-model-v04-review.md @@ -0,0 +1,136 @@ +# Security Layer Model v0.4 — ops-warden's review + +**Date:** 2026-08-29 +**Reviewed:** `net-kingdom/canon/standards/security-layer-model_v0.4.md` (accepted) +**Prior position:** `ADR-0010`, assent to v0.1 (`WARDEN-IN-0001`) +**Outcome:** no objection to the ruling; three findings, one of them against ops-warden. + +--- + +## What v0.4 did with ops-warden's amendment + +Both §5 asks from `ADR-0010` were adopted. + +**§5.3 declared engine gap** is the amendment ops-warden offered, adopted with the +four fields intact (`capability`, `intended_owner`, `blocked_on`, `review`), the +rationale preserved — *a rule offering no lane for a real sanctioned case gets +satisfied by relabelling rather than by closing the gap* — and the framing that +matters most kept explicit: **a declared gap is tracked non-conformance, not +conformance**. ops-warden's delegation machinery is cited as prior art. + +**§5.2 conduit** resolves the question ops-warden flagged rather than assumed. The +test is the supplied-authority property, which is the right test: it turns on what +the repository presents, not on what it touches. *"A conduit that presents its own +token is not a conduit"* is a sharper statement of `ADR-0002` than `ADR-0002` makes. + +**This created an obligation ops-warden had not met.** §5.3 requires the fields +*machine-readably* and §11 makes the mapping a mechanical check; ops-warden's +declaration was prose in `INTENT.md`. Fixed in this pass: `layer.yaml`, +`scripts/check_layer_conformance.py`, `tests/test_layer_conformance.py`. The +checker found three undeclared modules on first run, all false positives — help +text, a docstring, and the doubles library that *simulates* `bao` — which is why +it now matches invocation shapes rather than the word. + +--- + +## Finding 1 — §9.1 and §5.3 disagree, and ops-warden's §4 row is the instance + +§9.1: *a Staff repository MUST NOT be catalogued in §4 as owning a capability that +requires a Tooling contact no engine exposes*; where intended but unbuilt, the +entry **MUST be marked pending** and the gap declared under §5.3. + +ops-warden's §4 row reads `operational access lanes, stewardship, runbooks; SSH +certificate issuance` — with no pending mark. And §13 lists *SSH-CA signing write +(`VaultCA`, `bao kv put`) — declared by ops-warden — intended owner secrets-engine*. + +So the catalog asserts ownership of a capability that requires a Tooling contact no +engine exposes, unmarked. By §9.1's own text that is a defect. But the available +fix is worse than the defect: **marking it pending would be false.** SSH issuance is +production-verified and in daily use. `pending` would tell a reader ops-warden does +not yet do the one thing it demonstrably does. + +The root cause is that §9.1 collapses two different states: + +| State | Example | Capability today | +| --- | --- | --- | +| No route exists at all | kings-guard containment (§9.2) | **zero** | +| Route exists via a declared §5.3 gap | ops-warden SSH issuance | **working, tracked** | + +§5.3 exists precisely to sanction the second. §9.1 was written for the first — it +was raised by kings-guard, about containment, and correctly fixed *for that case*. +Applied to the adjacent case it produces a false catalog. + +**Recommendation:** give §9.1 two marks rather than one — `pending` where no route +exists, and `declared-gap` where the capability is discharged under §5.3 and +registered in §13. Both are honest; today's binary forces a choice between a false +label and an unmarked violation. + +This is the §12 loop working as designed, and §12 already says so: a finding that a +rule is unsatisfiable is a success of the loop. + +--- + +## Finding 2 — §5's scope is undefined for infrastructure §4 does not catalogue + +§5 forbids *a direct client for a Tooling-layer system*. §4 catalogues the security +estate, and only `key-cape` and `OpenBao` are Tooling rows. + +ops-warden holds an HTTP client for the **State Hub** and for **llm-connect** +(`src/warden/worker.py`). Neither appears in §4. Both are infrastructure a Staff +repository holds a direct client for. + +The question is not rhetorical, because the answers diverge sharply: + +- **If they are Tooling**, then every Staff repository in the estate is in + undeclared violation on adoption day — they all write progress events — and + §11's second mechanical check fails estate-wide. +- **If they are not**, §5 should say so, because *"a Tooling-layer system"* reads + considerably broader than *"a repository in the §4 Tooling rows"*. + +ops-warden has recorded both under `non_tooling_clients` in `layer.yaml` with the +reasoning stated, rather than resolving it unilaterally. The scope is gate-house's +to set. + +--- + +## Finding 3 — §9.6 lands on ops-warden, and ops-warden does not satisfy it + +This is the one against us, and it is the most consequential item in the review. + +§9.6 consequence 1: *any system whose evidence is load-bearing MUST make emission +atomic with the state change it records. An archive cannot retrofit completeness.* + +**ops-warden's audit emission is deliberately non-atomic.** `src/warden/ca.py:90` +carries `pass # audit must not block signing`, and `wiki/AuditTrail.md` states the +trail *"never blocks the primary action"*. If the audit append fails, the +certificate is still issued and the event is simply lost — a suppressed event that +leaves the chain perfectly intact, which is the exact failure §9.6 describes. + +That was a considered availability choice: an audit-disk problem should not remove +production host access. §9.6 now makes it a conformance question, and the trade is +real in both directions: + +- make emission atomic → an audit write failure fails the sign, and the estate's + operational access lane acquires a new dependency on its own evidence store; +- leave it → signing evidence cannot be treated as complete, and anything reasoning + from *"there is no record of a sign"* is unsound. + +**ops-warden has not changed it, and is not going to decide this alone** — §9.6 is +estate doctrine and the question is whether SSH signing evidence is load-bearing in +gate-house's sense. What ops-warden can say is that the second horn is currently +true and undocumented: `wiki/AuditTrail.md` does not warn that absence of a record +is not evidence of absence. That correction is ops-warden's regardless of the +ruling, and is the smaller half of the fix. + +Note also that §5.2 requires a conduit action to be *"reconstructable as the +caller's action in audit"* — an audit-dependent claim, and therefore bounded by +§9.6. Worth a cross-reference so the two rules do not drift apart. + +--- + +## Offered + +`layer.yaml` + `check_layer_conformance.py` + `test_layer_conformance.py` is a +working reference implementation of §5.3 and of §11's second mechanical check. Eight +of fifteen estate repositories have yet to declare (§14). If it is useful as a +pattern to point them at, it is offered — as the delegation machinery was. diff --git a/wiki/AuditTrail.md b/wiki/AuditTrail.md index 78b34df..7f0b22a 100644 --- a/wiki/AuditTrail.md +++ b/wiki/AuditTrail.md @@ -32,6 +32,15 @@ fresh file starts. high-entropy runs). Signing and proxy paths swallow audit failures so gatekeeping never blocks the primary action — but tests prove values cannot be written. +> **Absence of a record is not evidence of absence.** Because emission never +> blocks the primary action (`src/warden/ca.py`), a failed append loses the event +> while the action still happens. This trail proves that the records it holds were +> not altered or truncated; it does **not** prove that every action produced one. +> Do not reason from a missing entry. This is the estate-wide bound in +> `security-layer-model_v0.4` §9.6 — completeness is the source's obligation, and +> whether ops-warden must make signing emission atomic is an open question with +> gate-house (`history/2026-08-29-layer-model-v04-review.md`, Finding 3). + --- ## Query From 94f32bd160020664c9c8f66dc5ba62421b00f7a6 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 29 Aug 2026 10:20:49 +0200 Subject: [PATCH 20/32] =?UTF-8?q?Review=20layer=20model=20v0.6;=20publish?= =?UTF-8?q?=20the=20PEP=20stance=20map=20=C2=A76.4=20requires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All three v0.4 findings were acted on — §9.1 split into pending/declared-gap and §5's scope rule adopted as recommended and credited, and §9.6 ruled via the load-bearing/attributive distinction with ops-warden's `# audit must not block signing` named as the estate's live example. Checked the favourable ruling rather than accepting it. §9.6's test is "no control branches on its presence": the only consumer of audit.jsonl is `warden activity`, which displays. Nothing gates on a signing record, so the lane is genuinely attributive. AuditTrail.md now records the ruling instead of the open question, and states that the trade must be revisited if a control ever gates on the trail. CONFORMANCE ACTION. §6.4 obligation 3 requires a stance map "published rather than held in code", and requires every PEP-shaped consumer to publish one so the maps can be inventoried — naming ADR-0009 as the reference shape. ops-warden was not doing it: the map lived in PolicyConfig.failure_modes, a dataclass default. Not a code comment, but not published either. pep-stance.yaml publishes it, and the test asserts the published map EQUALS the shipped default. A published map that may drift from the code is worse than no map, because it invites reliance it cannot support. Two findings sent to gate-house, in history/2026-08-29-layer-model-v06-review.md: §6.4 obligation 1 (no side effect without a decision record) contradicts obligation 3 and §9.3, with ops-warden's blessed fail-open stance as the instance; and §6.4 mandates a stance-map inventory in §13 that §13 does not implement — where ops-warden is currently the only PEP to have published one. 402 tests pass, ruff clean. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- history/2026-08-29-layer-model-v06-review.md | 156 +++++++++++++++++++ layer.yaml | 5 + pep-stance.yaml | 69 ++++++++ tests/test_layer_conformance.py | 35 +++++ wiki/AuditTrail.md | 9 +- 5 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 history/2026-08-29-layer-model-v06-review.md create mode 100644 pep-stance.yaml diff --git a/history/2026-08-29-layer-model-v06-review.md b/history/2026-08-29-layer-model-v06-review.md new file mode 100644 index 0000000..857a78a --- /dev/null +++ b/history/2026-08-29-layer-model-v06-review.md @@ -0,0 +1,156 @@ +# Security Layer Model v0.6 — ops-warden's review + +**Date:** 2026-08-29 +**Reviewed:** `security-layer-model_v0.6.md` (proposed), plus v0.5 and the companion +**Prior positions:** `ADR-0010` (v0.1 assent); `history/2026-08-29-layer-model-v04-review.md` +**Outcome:** no objection; one conformance action taken, two findings, one accepted SHOULD. + +--- + +## Disposition of ops-warden's v0.4 findings + +All three were acted on, two of them exactly as recommended. + +| Finding | Outcome | +| --- | --- | +| §9.1 forces a false `pending` onto working capability | **Adopted** — v0.5 split it into `pending` and `declared-gap`, credited to ops-warden | +| §5 scope undefined for uncatalogued infrastructure | **Adopted** — "Tooling-layer system" now means a §4 Tooling row; the State Hub case is recorded, not policed | +| §9.6 atomicity lands on ops-warden's signing lane | **Ruled** — the load-bearing / attributive distinction, with ops-warden's `# audit must not block signing` named as the estate's live example | + +The §9.6 ruling deserves a note, because it went in ops-warden's favour and that is +a reason to check it rather than accept it. The test is *"no control branches on +its presence"*. Verified: the only consumer of `audit.jsonl` is `warden activity` +(`cli.py`), which displays. Nothing gates on a signing record — not the agent +read-boundary, not `warden plan`, not the scorecard. The lane is genuinely +attributive and the trade is legitimate on the standard's own terms. The two +obligations that attach — declare it, never claim completeness — were already met +in `wiki/AuditTrail.md`, now updated to record the ruling rather than the open +question. **If a future ops-warden control ever gates on this trail, the trade has +to be revisited before that ships**, and that is recorded there. + +`layer.yaml` is named in §11 as the estate's reference declaration form, including +the "record non-Tooling clients so the check is total" property. Offered again to +the repositories that have yet to declare. + +--- + +## Conformance action taken — the stance map was not published + +§6.4 obligation 3 requires a declared unreachable-engine stance that is total, per +zone, with no implicit default, *"published rather than held in code comments"* — +and §6.4 requires **every** PEP-shaped consumer to publish its map so the maps can +be inventoried. `ADR-0009` is named as the reference shape. + +ops-warden was not doing this. The map lived in `PolicyConfig.failure_modes`, a +dataclass default in `src/warden/config.py`. That is not a code *comment*, but it +is not published either — it is merely written down, and a consumer of the estate +had no way to read ops-warden's stance without reading ops-warden's source. + +Published as `pep-stance.yaml`, with the property that makes publishing worth +anything: `tests/test_layer_conformance.py` asserts the published map is **equal to +the shipped default**. A published map that may drift from the code is worse than +no map, because it invites reliance it cannot support. The file also records the +obligation-2 position (verdict never cached; input claims cached under their own +freshness rules) and the obligation-4 bound (§9.6 attributive). + +--- + +## Finding 1 — §6.4 obligation 1 contradicts obligation 3, and ops-warden is the instance + +> **1. No side effect without a decision record.** A PEP MUST NOT perform the +> protected action unless it holds a decision from `access-engine` identifying the +> request it was rendered for. + +> **3. A declared unreachable-engine stance (§9.3):** total, per zone... `ops-warden` +> `ADR-0009` is the reference shape. + +These cannot both be absolute. ops-warden's declared stance — blessed by §9.3 as +*"the only thing left"* when there is no engine to ask — is `fail_open` for `z0`–`z2` +and `unknown`. Applying it means issuing a certificate **without holding a +decision**, which obligation 1 forbids without qualification. + +So the same section names ops-warden as the reference shape for obligation 3 while +obligation 1 makes ops-warden's shipped behaviour a violation. §9.3 settled the +substance; §6.4 restates it in a form that takes it back. + +**Recommendation.** Bound obligation 1 by obligation 3: + +> A PEP MUST NOT perform the protected action unless it holds a decision from +> `access-engine` identifying the request it was rendered for, **or its declared +> §9.3 stance for the applicable scope permits proceeding without one and the +> application of that stance is recorded in place of the decision**. + +This is not a weakening. It is stricter than today's text in the case that matters: +it makes the *recorded application of the stance* mandatory, rather than leaving +"no decision record" as a silent state. ops-warden already does this — `ca.py` +writes `policy_zone`, `policy_failure_mode` and `policy_decision_id` (present only +where a decision was rendered) into both the signatures log and `audit.jsonl`, per +`ADR-0009` rule 4: *a fail-open signing result is metadata, not silence*. + +This is the same shape as the v0.4 §9.1 finding: a rule written for the clean case, +correct there, producing a false result on the adjacent case the standard has +already sanctioned elsewhere. + +--- + +## Finding 2 — §6.4 creates a register that §13 does not implement + +§6.4: *"Every PEP-shaped consumer MUST publish its stance map, and those maps MUST +be inventoried — in `maturity-engine` once it exists, **in §13 until then**."* + +§13 contains no stance-map rows. It records declared contacts and unowned +capabilities; there is no column, row, or section for a PEP stance. So the +obligation names a register that does not exist yet, and the failure mode §6.4 +itself warns about — *"`z0`–`z2` and unknown fail open" becoming the estate's real +policy without anyone having compiled it* — is exactly what the missing register +permits. + +**Recommendation.** Either add a stance-map table to §13 with the same +state/owner-status discipline the gap table has, or state that the inventory waits +for `maturity-engine` and mark the obligation pending under §9.1's own logic — a +requirement whose register does not exist is a capability catalogued without a +surface. ops-warden's row is ready to paste: + +| PEP | Protected action | Scope | Stance | Published | +| --- | --- | --- | --- | --- | +| `ops-warden` | SSH certificate issuance | security-zone | open `z0`–`z2`+unknown, closed `z3`/n-a | `ops-warden/pep-stance.yaml` | + +The second half matters more than the first: **ops-warden is currently the only +PEP that has published one**, so an inventory today would contain one row and that +is itself the finding. `ops-mason` is named PEP-shaped in the same paragraph. + +--- + +## Accepted, not yet done — §9.6 emission cadence + +§9.6: *"A source SHOULD declare an expected emission cadence, and a drop below it +SHOULD become a finding in its own right."* + +ops-warden declares none. This is a genuine SHOULD and the reasoning behind it is +sound — it converts the suppression blind spot into something detectable without +any Tooling contact, because the source publishes its own stream. It is not done +here because a cadence asserted without evidence is worse than none: ops-warden's +signing volume is operator-driven and bursty, and a fabricated baseline would +generate findings that mean nothing. Deriving one from the existing trail is +tractable and is recorded as ops-warden's to do, not gate-house's to chase. + +--- + +## On the pace + +Six versions in two days, with four repositories' findings absorbed and credited, +is the §12 loop working at a rate the estate has not seen before. Two cautions, +offered as an interested consumer rather than as objections: + +1. **§13 already says it should not be statute, and it is right.** The register has + grown every version. Moving it to `maturity-engine` is the stated plan; until + that exists, each version of the standard is also a snapshot of a backlog, and + the two have very different review intervals. +2. **The standard is `proposed` again at v0.6**, and the four repositories that + assented did so to v0.1. ops-warden's `ADR-0010` assent covers the three + boundary items, and nothing in v0.2–v0.6 has disturbed them — the layer, the + lane/rule demarcation, and doctrine-versus-runbook all stand. But the + `assented_by` list carries assent forward across five revisions, and a reader + could take it as assent to the current text. Worth distinguishing *assented to + the boundary* from *reviewed the current revision*; ops-warden has now done + both, and this note is the second. diff --git a/layer.yaml b/layer.yaml index 23d099a..be3ec97 100644 --- a/layer.yaml +++ b/layer.yaml @@ -20,6 +20,11 @@ layer: staff declared_by: docs/adr/ADR-0010 declared_at: "2026-08-29" +# §6.4 — ops-warden is PEP-shaped (it causes a protected side effect: issuing a +# certificate). Its unreachable-engine stance map is published separately, and +# asserted equal to shipped behaviour by tests/test_layer_conformance.py. +pep_stance: pep-stance.yaml + # Every direct contact with a Tooling-layer system (§4), one entry each. tooling_contacts: diff --git a/pep-stance.yaml b/pep-stance.yaml new file mode 100644 index 0000000..cf4e83f --- /dev/null +++ b/pep-stance.yaml @@ -0,0 +1,69 @@ +# ops-warden — PEP unreachable-engine stance map +# +# Framework: net-kingdom/canon/standards/security-layer-model_v0.6.md §6.4, §9.3 +# Rule of record: docs/adr/ADR-0009 +# Validate: pytest tests/test_layer_conformance.py -k stance +# +# §6.4 obligation 3 requires a declared unreachable-engine stance that is total, +# scoped per zone, carries no implicit default and no per-call discretion, and is +# "published rather than held in code comments". §6.4 further requires every +# PEP-shaped consumer to PUBLISH its map so the maps can be inventoried. This +# file is ops-warden's, published because a map that lives only in a dataclass +# default is not published — it is merely written down. +# +# The property that makes this worth reading: it is asserted equal to the shipped +# default in src/warden/config.py (PolicyConfig.failure_modes) by +# tests/test_layer_conformance.py. A published map that may drift from the code +# is worse than none, because it invites reliance it cannot support. + +schema_version: "0.1" +framework: netkingdom-security-layer-model +standard_version: "0.6" +repository: ops-warden +pep_shape: true +declared_by: docs/adr/ADR-0009 + +protected_action: "SSH certificate issuance (warden sign / cert_command)" +decision_engine: access-engine # flex-auth until the governed rename +scope: security-zone # security-zones_v0.1 membership of the TARGET workload + +# Total by construction: every zone in security-zones_v0.1, plus the two +# non-zone outcomes. No implicit default — an unlisted value is a config error, +# not a permissive fallback. +stance: + z0-experimental: fail_open + z1-operational: fail_open + z2-protected: fail_open + z2-continuity: fail_open + z3-critical: fail_closed + unknown: fail_open # versioned build profile (ADR-0009); explicit, never inferred + not-applicable: fail_closed + +# What happens when the stance is applied. §6.4 obligation 1 requires a decision +# record for a protected side effect; where the engine is unreachable there is no +# decision to hold, so ops-warden records the APPLICATION OF THE STANCE instead. +# See the assessment note: obligation 1 as written admits no such case. +on_apply: + recorded_fields: + - policy_zone + - policy_failure_mode + - policy_decision_id # present only where a decision was actually rendered + - outcome + written_to: + - "signatures log (src/warden/ca.py)" + - "audit.jsonl (src/warden/audit.py)" + never_recorded: "any secret material, any certificate private key" + +# §6.4 obligation 2 — the verdict is never cached. Input claims (zone membership, +# compiled from the flex-auth registry snapshot) are cached under their own +# freshness rules; the answer is not. +verdict_caching: none +input_claim_caching: "registry/flex-auth/production_registry_snapshot.json, rebuilt by scripts/build_flex_auth_registry.py" + +# §6.4 obligation 4 — reconstructability, bounded by §9.6. ops-warden's audit +# emission on this lane is deliberately non-atomic and therefore ATTRIBUTIVE, not +# load-bearing: no control branches on the presence of a signing record +# (`warden activity` displays it; nothing gates on it). Registered in §13. +reconstructability: + bound: "§9.6 attributive — completeness is not claimed" + declared_at: wiki/AuditTrail.md diff --git a/tests/test_layer_conformance.py b/tests/test_layer_conformance.py index 86b39a0..59284aa 100644 --- a/tests/test_layer_conformance.py +++ b/tests/test_layer_conformance.py @@ -96,3 +96,38 @@ class TestConduitSuppliesNoAuthority: f"proxy.py references {forbidden!r} — that is presenting or " f"minting authority, not conducting the caller's" ) + + +class TestPepStanceMap: + """§6.4: every PEP-shaped consumer MUST publish its unreachable-engine + stance map, total and per zone, 'published rather than held in code'. + ADR-0009 is named as the reference shape, so it should actually hold.""" + + def _stance(self) -> dict: + return yaml.safe_load((ROOT / "pep-stance.yaml").read_text()) + + def test_published_map_equals_shipped_behaviour(self): + """The whole point. A published map that may drift from the code is + worse than none, because it invites reliance it cannot support.""" + from warden.config import PolicyConfig + + assert self._stance()["stance"] == PolicyConfig().failure_modes + + def test_stance_is_total_over_the_zone_model(self): + """§6.4 obligation 3: total, no implicit default.""" + stance = self._stance()["stance"] + required = { + "z0-experimental", "z1-operational", "z2-protected", + "z2-continuity", "z3-critical", "unknown", "not-applicable", + } + assert required <= set(stance), f"stance not total; missing {required - set(stance)}" + assert set(stance.values()) <= {"fail_open", "fail_closed"} + + def test_critical_zone_fails_closed(self): + """ADR-0009's one non-negotiable row.""" + assert self._stance()["stance"]["z3-critical"] == "fail_closed" + + def test_verdict_is_never_cached(self): + """§6.4 obligation 2: caching an input claim is permitted; caching the + answer is a second decision point deciding early (§6.1).""" + assert self._stance()["verdict_caching"] == "none" diff --git a/wiki/AuditTrail.md b/wiki/AuditTrail.md index 7f0b22a..aba9036 100644 --- a/wiki/AuditTrail.md +++ b/wiki/AuditTrail.md @@ -38,8 +38,13 @@ never blocks the primary action — but tests prove values cannot be written. > not altered or truncated; it does **not** prove that every action produced one. > Do not reason from a missing entry. This is the estate-wide bound in > `security-layer-model_v0.4` §9.6 — completeness is the source's obligation, and -> whether ops-warden must make signing emission atomic is an open question with -> gate-house (`history/2026-08-29-layer-model-v04-review.md`, Finding 3). +> **Ruled 2026-08-29** (`security-layer-model_v0.6` §9.6): this trail is +> **attributive**, not load-bearing — no control branches on the presence of a +> signing record — so the non-atomic trade is legitimate, and the obligations are +> to declare it (this note) and never to claim completeness. Atomicity is required +> only where a control's soundness depends on an event being present or absent. +> Registered in the standard's §13 open-gap table as self-declared. If a future +> control ever gates on this trail, the trade must be revisited before it ships. --- From fd08950231aea2f03710775f3c4c114695b40757 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 29 Aug 2026 14:50:55 +0200 Subject: [PATCH 21/32] Align INTENT and SCOPE to layer model v0.7; assess gaps; open WARDEN-WP-0034 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The standard is accepted at v0.7, with SECURITY-COMPANION.md v0.2 as its operative form. Four ops-warden findings were adopted between v0.4 and v0.7 — §9.1's two marks, §5's Tooling scope rule, §6.4 obligation 1's second limb, and §13.1's existence — and both ops-warden declaration artifacts are now cited in the text as the estate's reference forms. INTENT.md gains frontmatter (layer: Staff, pep_shaped: true) because §11 requires a machine-readable declaration and prose cannot distinguish a declaration from a transcribed review. The note now covers the agent principal (§3.4), the PEP shape, the attributive evidence position, and the role the companion assigns: the estate is told to ask ops-warden which lane, which credential, which route. SCOPE.md records what is actually shipped against v0.7 and the honest conformance state — declared gap, which is tracked non-conformance, not conformance. The assessment checked every obligation against shipped code rather than intent. Three gaps survive: - §9.7.2 requires a PEP to state one revocation visibility deadline. Ours is unstated, and the honest value is uncomfortable: the cert TTL, up to 48h. A cert outlives revocation of the decision that authorized it — no CRL, no KRL distribution. That is a design property never written down, which is exactly what §9.7.2 exists to force into the open. - §3.4 rule 1 forbids standing credentials and requires issued, attributable authority. ADR-0004's boundary keys on WARDEN_AGENT_ID, which an agent sets about itself. key-cape now issues a real coding-agent identity, so the ops-warden half can stop being advisory. - §9.6 cadence remains undeclared. Attributive, so SHOULD not MUST, but silence through two reviews is the one outcome that is not defensible. WARDEN-WP-0034 addresses all three, plus the discoverability gap the companion creates and two items to route rather than absorb. 402 tests pass, ruff clean. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- INTENT.md | 90 +++++++--- SCOPE.md | 29 ++- .../2026-08-29-v07-scope-intent-assessment.md | 157 +++++++++++++++++ ...DEN-WP-0034-layer-model-v07-conformance.md | 165 ++++++++++++++++++ 4 files changed, 411 insertions(+), 30 deletions(-) create mode 100644 history/2026-08-29-v07-scope-intent-assessment.md create mode 100644 workplans/WARDEN-WP-0034-layer-model-v07-conformance.md diff --git a/INTENT.md b/INTENT.md index 86254a7..3522a93 100644 --- a/INTENT.md +++ b/INTENT.md @@ -1,34 +1,67 @@ +--- +layer: Staff +role: null # Engines only: PDP | PIP | Evidence | Lifecycle +pep_shaped: true # §6.4 — issuing a certificate is a protected side effect +standard: net-kingdom/canon/standards/security-layer-model_v0.7.md +standard_version: "0.7" +companion: net-kingdom/SECURITY-COMPANION.md +declaration: layer.yaml +pep_stance: pep-stance.yaml +assent: docs/adr/ADR-0010 +--- + # INTENT -> **Layer: Staff.** ops-warden is a Staff repository under the NetKingdom -> IT-security layer model (Taxonomy -> Tooling -> Engines -> Staff, layered by -> determinism and by the kind of artifact each layer produces): -> `net-kingdom/canon/standards/security-layer-model_v0.4.md` (**accepted**), owned by -> gate-house, ratified as `gate-house/decisions/decisions.md` GH-DEC-2026-001. -> ops-warden's assent is recorded there as `ADR-0010`. +> **ops-warden is Staff, and PEP-shaped.** Declared here in its own voice, per +> `security-layer-model_v0.7` §11 — a layer stated *about* a repository by another +> repository is not a declaration. The standard is **accepted**; its operative form +> is `net-kingdom/SECURITY-COMPANION.md`. ops-warden's assent is `ADR-0010`, and its +> reviews of v0.4, v0.6 and v0.7 are in `history/`. > -> **The binding rule: Staff never touches Tooling directly. It acts only through -> Engine APIs.** ops-warden holds no state another layer depends on at runtime and -> renders no authorization decision — it consumes them from access-engine. +> **Staff** because ops-warden's core function is judgement, not computation: it +> decides which lane a need belongs to and stewards the paths through the estate's +> rules. Its artifacts are runbooks, routing decisions, workplans. **PEP-shaped** +> because issuing a certificate is a protected side effect — a shape, not a layer +> (§6.4). ops-warden renders no authorization decision and never will; it consumes +> them from `access-engine`. > -> **Declared exception (standard section 5).** `src/warden/vault.py` (`VaultCA`) is a -> direct OpenBao client that performs a write, and `warden desk` shells `bao kv put` -> for paste-once provisioning. Both are non-conformant. Intended owner: -> **secrets-engine**; blocked on: no engine exposes an SSH certificate signing -> surface; reviewed quarterly. `src/warden/taint.py` reads KV metadata only, declared -> under the read-only observation allowance. `warden access --fetch/--exec/--wrap` -> runs the owner's tool under **the caller's** identity and supplies no authority of -> its own (`ADR-0002`). +> **The estate's front door for paths.** The companion routes the whole estate here: +> *"For how to get something done — which lane, which credential, which route — ask +> `ops-warden`. This document says what the rules are; ops-warden stewards the paths +> through them."* That is a standing obligation, not a compliment: every rule +> gate-house writes needs a path someone can actually walk, and ops-warden owes the +> estate that path. > -> **The declaration is `layer.yaml`, not this note.** v0.4 §5.3 requires a gap to -> carry `capability`, `intended_owner`, `blocked_on` and `review` *machine-readably*, -> and §11 makes "every direct Tooling client maps to a declared §5.1/§5.2/§5.3 entry" -> a mechanical check. `layer.yaml` is that map; `scripts/check_layer_conformance.py` -> and `tests/test_layer_conformance.py` enforce it, so a new undeclared OpenBao -> client fails on the commit that introduces it. +> **The declarations are files, not this note** — prose cannot distinguish a +> declaration from a transcribed review (§11): > -> Assent, reasoning, and the amendment offered back to gate-house — adopted as -> v0.4 §5.3: `history/2026-08-28-security-layer-model-assent.md` and `ADR-0010`. +> | File | Declares | Enforced by | +> | --- | --- | --- | +> | `layer.yaml` | every Tooling contact, mapped to a §5.1/§5.2/§5.3 shape, plus the non-Tooling clients so the check is total | `scripts/check_layer_conformance.py`, `tests/test_layer_conformance.py` | +> | `pep-stance.yaml` | the unreachable-engine stance map (§6.4 obl. 3), total per zone | test asserts the published map **equals** the shipped default | +> | `tenancy.yaml` | tenancy posture, and `z1-operational` zone membership | `ADR-0009` | +> +> Both are cited in the standard as the estate's reference forms (§11, §6.4, §13.1). +> +> **Two declared engine gaps (§5.3), tracked non-conformance and not conformance.** +> `VaultCA` signs over a direct OpenBao client and `warden desk` shells `bao kv put`. +> Intended owner **secrets-engine**; blocked on no engine exposing an SSH-CA or +> attended-provisioning surface; reviewed quarterly; registered in statute §13. +> ops-warden keeps signing while the gap is open — refusing would remove production +> host access to close a documentation gap. +> +> **The agent principal (§3.4).** ops-warden is operated by agents as well as people, +> and they share the layer but not the blast radius. No standing credential; tool use +> is a conduit or an engine API and there is no third route; **tool availability is +> not permission**, which is exactly what `ADR-0004`'s read-boundary enforces; agent +> memory is not a state plane. Session semantics belong to `glas-harness`, not here. +> +> **Evidence (§9.6).** ops-warden's audit trail is **attributive**, not load-bearing: +> no control branches on the presence of a signing record. Emission is deliberately +> non-atomic so an audit-store failure cannot remove production host access — a trade +> the standard sanctions, declared in `wiki/AuditTrail.md`, registered in §13. If any +> future control ever gates on this trail, that trade must be revisited before it +> ships. > This file captures **why this repository exists**, the **direction it is > moving toward**, and the **kind of system it is meant to become**. @@ -110,7 +143,7 @@ owns one lane and points at the rest: ## Lane routing — who owns which need **This is a runbook, not doctrine.** Security doctrine, the authority model, and the -security curriculum are **gate-house's** (`security-layer-model_v0.1` section 8). +security curriculum are **gate-house's** (`security-layer-model_v0.7` §8). ops-warden references them and does not restate them. What follows is lane stewardship: which subsystem owns which need, and what ops-warden does about it. @@ -137,7 +170,7 @@ orientation, and the catalog is the source of truth (`ADR-0001`). ### Access lane versus access rule -Normative, per `security-layer-model_v0.1` section 8 and assented to in `ADR-0010`: +Normative, per `security-layer-model_v0.7` §8 and assented to in `ADR-0010`: - **access lane** — ops-warden and ops-mason. *How* a worker reaches a host. - **access rule** — access-engine. *Whether* they may. @@ -147,7 +180,8 @@ may do something is not an ops-warden question, however it arrives. Canonical references: -- `net-kingdom/canon/standards/security-layer-model_v0.1.md` (layers, section 5, section 8) +- `net-kingdom/SECURITY-COMPANION.md` — the operative form; start here +- `net-kingdom/canon/standards/security-layer-model_v0.7.md` (accepted; §5 shapes, §6.4 PEP, §8 vocabulary) - `net-kingdom/docs/platform-identity-security-architecture.md` - `net-kingdom/docs/responsibility-map.md` - `wiki/AccessManagementDirective.md` (ops SSH actor model) diff --git a/SCOPE.md b/SCOPE.md index 46c9eec..fb9ed06 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -85,6 +85,28 @@ cutover, flex-auth publishing the zone-aware pre-sign stance package, the owner-driven WP-0015 canon landing, and — newly named — the missing owner front doors that keep ops-warden holding interim lanes (secrets-engine, tenant-engine). +### Layer-model conformance (v0.7, accepted) + +ops-warden declares **Staff**, **PEP-shaped**, in `INTENT.md` frontmatter and in its +own voice — `security-layer-model_v0.7` §11. Shipped declaration artifacts, both +cited in the standard as the estate's reference forms: + +| Artifact | Declares | Status | +| --- | --- | --- | +| `layer.yaml` | 5 Tooling contacts mapped to §5.1/§5.2/§5.3 shapes + non-Tooling clients so the check is total | shipped; named reference form (§11) | +| `pep-stance.yaml` | unreachable-engine stance map, total per zone | shipped; registered in statute §13.1 (§6.4 obl. 3) | +| `scripts/check_layer_conformance.py` | every direct Tooling client maps to a declared shape | shipped; CI-enforced | +| `tests/test_layer_conformance.py` | the §5.2 no-authority property, and published stance map **equals** shipped default | shipped, 11 tests | + +Conformance state under §11: **declared gap** — tracked non-conformance, not +conformance. Two §5.3 contacts (`VaultCA` signing write, `warden desk` `bao kv put`), +intended owner `secrets-engine`, registered in statute §13. + +Four ops-warden findings have been adopted into the standard: §9.1's two marks +(`pending` vs `declared-gap`), §5's Tooling scope rule, §6.4 obligation 1's second +limb, and §13.1's existence. Reviews: `history/2026-08-29-layer-model-v04-review.md`, +`-v06-review.md`, `-v07-scope-intent-assessment.md`. + ### Issue vs route ops-warden executes exactly one lane with its own authority and routes/assists the rest. @@ -156,7 +178,7 @@ superseding ADR, never an in-place edit. | `ADR-0007` | Build-stage permissiveness stops at credential disclosure; every lane carries an explicit `risk` grade | | `ADR-0008` | A lane's risk grade covers every field its path discloses, not just the field it is named after | | `ADR-0009` | Adopt security-zones v0.1 and compile explicit workload membership; PEP failure mode is per zone | -| `ADR-0010` | ops-warden is Staff — it owns access lanes, never access rules; the direct OpenBao client is a declared engine gap, not an exemption | +| `ADR-0010` | ops-warden is Staff and PEP-shaped — it owns access lanes, never access rules; the direct OpenBao client is a declared engine gap, not an exemption | Rules we follow but do not own — NetKingdom canon, the IAM profile, the credential-management standard, the-custodian's ADR-001 workplan convention — are @@ -434,7 +456,7 @@ Downstream: `ops-bridge` (primary), kaizen agents, CI automations, human operato | Repo | Relationship | | --- | --- | -| `gate-house` | Owns security doctrine, invariants, authority context, and conformance review; ops-warden routes doctrine questions there and references rather than restates them (`ADR-0010`) | +| `gate-house` | Owns the security layer model, doctrine, invariants, authority context, and conformance review. ops-warden routes doctrine questions there, and the companion routes the estate's *path* questions back to ops-warden (`ADR-0010`) | | `net-kingdom` | Canonical security architecture; ops-warden aligns to it | | `ops-bridge` | Primary cert_command consumer | | `railiance-infra` | Host-side SSH principals and hardening | @@ -488,6 +510,9 @@ keywords: [access, credential, secret, npm, token, api-key, openbao, key-cape, l | `wiki/CredentialRouting.md` | Which subsystem for each credential need | | `wiki/WorkloadSecurityPosture.md` | Secret-store posture, workload maturity, and blocker triage | | `registry/routing/catalog.yaml` | Machine-readable routing pointer catalog | +| `net-kingdom/SECURITY-COMPANION.md` | **The estate's operative security rules — start here** | +| `layer.yaml` | Layer declaration: every Tooling contact and its §5 shape | +| `pep-stance.yaml` | Unreachable-engine stance map (§6.4); equals shipped behaviour by test | | `tenancy.yaml` | Declared tenancy posture (`I1 A1 E0 P n/a R n/a V0`) and why each axis sits where it does | | `wiki/NetKingdomSecurityMap.md` | Platform security component map | | `examples/warden.production.example.yaml` | Production warden.yaml template | diff --git a/history/2026-08-29-v07-scope-intent-assessment.md b/history/2026-08-29-v07-scope-intent-assessment.md new file mode 100644 index 0000000..f8a2196 --- /dev/null +++ b/history/2026-08-29-v07-scope-intent-assessment.md @@ -0,0 +1,157 @@ +# v0.7 conformance — INTENT vs SCOPE gap assessment + +**Date:** 2026-08-29 +**Standard:** `security-layer-model_v0.7.md` (**accepted**) + `SECURITY-COMPANION.md` v0.2 +**Prior:** `ADR-0010`; v0.4 and v0.6 reviews in `history/` +**Method:** each v0.7 obligation checked against shipped code, not against intent. + +--- + +## Summary + +ops-warden is **conformant on every obligation it can discharge alone except three**, +and holds two declared §5.3 gaps that are tracked, registered and owned elsewhere. +The three genuine gaps are §9.7.2 (no stated revocation visibility deadline — a MUST), +§3.4 rule 1 (the agent read-boundary keys on an honour-system marker rather than an +issued identity), and §9.6's cadence, which is a SHOULD for an attributive source and +remains undone for an honest reason. + +One new obligation is not a rule at all but a role: the companion routes the entire +estate to ops-warden for *how to get something done*. Nothing in the repo answers a +layer or declaration question today, and that is now a discoverability gap. + +Four ops-warden findings were adopted into the standard between v0.4 and v0.7 — §9.1's +two marks, §5's Tooling scope rule, §6.4 obligation 1's second limb, and §13.1's +existence. That is the conformance loop working; it is not a reason to assume the next +pass finds nothing. + +--- + +## Obligation-by-obligation + +### Conformant, shipped, evidenced + +| Obligation | Evidence | +| --- | --- | +| §11 declare layer in own voice, machine-readably | `INTENT.md` frontmatter (`layer: Staff`, `pep_shaped: true`) + `layer.yaml` — cited in §11 as the estate's reference form | +| §5 every Tooling contact maps to a shape; non-Tooling recorded so the check is total | `layer.yaml` 5 contacts + 2 exclusions; `scripts/check_layer_conformance.py` | +| §5.2 conduit supplies no authority | `proxy.py::_caller_env`; `tests/test_layer_conformance.py::test_conduit_supplies_no_authority_of_its_own` | +| §6.4 obl. 1 no side effect without a decision **or a recorded stance** | `ca.py` writes `policy_zone`, `policy_failure_mode`, `policy_decision_id` (present only where rendered). ops-warden is the named reference for limb two | +| §6.4 obl. 2 no verdict recaching | `policy.py` caches nothing — verified by inspection, not by claim | +| §6.4 obl. 3 stance map published, at a path named in the declaration, equal to shipped behaviour, asserted by test | `pep-stance.yaml`, named in `layer.yaml`; test asserts equality with `PolicyConfig().failure_modes`; registered in statute §13.1 | +| §9.3 stance total, per zone, no implicit default | 7 rows covering every zone plus `unknown` and `not-applicable` | +| §9.6 evidence claims bounded | `wiki/AuditTrail.md` declares the attributive trade and states absence is not evidence of absence | +| §9.7.1 every allow has an explicit lifetime | TTL enforced per `ActorType` — `adm` 48h, `agt` 24h, `atm` 8h | +| §3.4 rule 2 tool use is a conduit or engine API | `warden access` is the conduit; `ADR-0004` enforces that tool availability is not permission | + +### Declared gaps — tracked non-conformance, owned elsewhere + +Both registered in statute §13, intended owner `secrets-engine`, reviewed quarterly. +Neither is closable by ops-warden: closing them means another repository shipping a +surface. + +- **`VaultCA` signing write** — no engine exposes SSH-CA signing. +- **`warden desk` `bao kv put`** — no engine exposes attended provisioning. + +Nothing in v0.7 changes their status. The right ops-warden behaviour is to keep them +declared, keep the review dates honest, and not quietly grow a third. + +--- + +## The three real gaps + +### G1 — §9.7.2: no stated revocation visibility deadline (MUST) + +> *A **PEP** has one boundary and MUST state one deadline… an unstated deadline is +> an unbounded replay window.* + +ops-warden states none, and the honest answer is uncomfortable: **the effective +window is the certificate TTL — up to 48 hours.** A certificate issued under an allow +stays valid for its full TTL even if the decision that authorized it is revoked or +superseded the next minute. ops-warden has no revocation channel for an issued cert: +there is no CRL, no KRL distribution, and host-side `auth_principals` is +`railiance-infra`'s. + +This is not a documentation gap. It is a design property that has never been written +down, and §9.7.2 exists precisely to force it into the open. Two things follow: + +1. The deadline must be **stated** — `adm` 48h / `agt` 24h / `atm` 8h — in + `pep-stance.yaml`, as what it is rather than as an aspiration. +2. Whether 48h is *acceptable* is a separate question, and it is partly + `railiance-infra`'s (KRL distribution) and partly ours (TTL policy). Stating it is + ours and is cheap; shortening it is a joint change. + +Stating a bad number is better than stating none: an unstated deadline is an +unbounded replay window, and this one is bounded and already implemented. + +### G2 — §3.4 rule 1: the agent boundary rests on an honour-system marker + +> *No standing credential. Authority is issued per task, time-bounded under §9.7, +> and attributable to the principal on whose behalf it acts.* + +`ADR-0004`'s read-boundary triggers when `WARDEN_AGENT_ID` is set — an environment +variable the agent sets **about itself**. An agent that does not set it is not +recognised as an agent. ops-warden has known this (`WARDEN-WP-0033-T04` recorded it +as "an honour-system marker on the ops-warden side"), and it was tolerable while no +issued agent identity existed. + +One now does. `key-cape` accepted issuance ownership in `KEY-WP-0009-T03`: +`codex-railiance-platform`, subject `service:codex:railiance-platform`, role +`coding-agent`, scope `openbao:login`, 15-minute lifetime. The OpenBao side is +enforced by `railiance-platform`'s policy, which is the half that actually holds. + +So the gap is narrower than it looks and worth stating precisely: **the OpenBao-side +boundary is real; the ops-warden-side boundary is advisory.** ops-warden should key +its read-boundary on the issued identity where one is present, and treat +`WARDEN_AGENT_ID` as a fallback that fails *toward* the boundary rather than away +from it. That is a change in this repo and does not need another repo to move. + +### G3 — §9.6 emission cadence (SHOULD, for an attributive source) + +Unchanged from the v0.6 review and still honest: ops-warden declares no expected +cadence because its signing volume is operator-driven and bursty, and a fabricated +baseline generates findings that mean nothing. v0.7 makes cadence a **MUST for +load-bearing sources**; ops-warden's trail is attributive, so it remains a SHOULD. + +Deriving a real baseline from the existing trail is tractable and is ops-warden's to +do. It should be derived and declared, or explicitly deferred with a reason — not +left silent, which is what it is today. + +--- + +## The role the companion assigns, and what it costs + +> *"For how to get something done in NetKingdom — which lane, which credential, which +> route — ask `ops-warden`. This document says what the rules are; ops-warden stewards +> the paths through them."* + +This is the largest change in ops-warden's INTENT surface and it is not a rule, so it +does not appear in any conformance check. The estate has been told to come here. + +**Today the repo answers credential questions and no others.** `warden route` and +`warden plan` cover lanes, owners and acts. Nothing answers *"which layer am I"*, +*"how do I declare"*, *"I am PEP-shaped, what do I owe"* — the questions the companion +and the standard's adoption status (eight of fifteen repositories undeclared) actually +generate. + +ops-warden has already built the reference artifacts those repositories need, and the +standard points at them by name in §11 and §6.4. What is missing is the path: a +discoverable route from *"I read the companion"* to *"here is the file to copy and the +check to run"*. That is exactly the stewardship ops-warden claims, applied to the +estate's newest rule rather than to its credential lanes. + +Also worth noting, and not ops-warden's to fix: §13.1's register has one row, and +`ops-mason` — catalogued PEP-shaped in the same paragraph — has published nothing. +The standard says one row is itself the finding. + +--- + +## What does not need doing + +- **No new ADR.** `ADR-0010` holds: Staff, lanes not rules, declared gaps not + exemptions. v0.2–v0.7 refined the rules around it and disturbed none of its three + positions. The reviews extend it; a superseding record would add ceremony without + changing a decision. +- **No change to the two §5.3 gaps.** They are correctly declared and owned elsewhere. +- **No re-assent.** ops-warden assented to the boundary in `ADR-0010` and has now + reviewed three revisions on their merits, which is the stronger position. diff --git a/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md b/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md new file mode 100644 index 0000000..b233411 --- /dev/null +++ b/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md @@ -0,0 +1,165 @@ +--- +id: WARDEN-WP-0034 +type: workplan +title: "Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule" +domain: infotech +repo: ops-warden +status: ready +owner: ops-warden +topic_slug: netkingdom +planning_priority: P1 +depends_on_workplans: + - WARDEN-WP-0030 +created: "2026-08-29" +updated: "2026-08-29" +--- + +# WARDEN-WP-0034 — Layer model v0.7 conformance + +`security-layer-model_v0.7` is **accepted**. ops-warden declared Staff and PEP-shaped, +shipped the two declaration artifacts the standard now cites as estate reference forms, +and had four findings adopted into the text between v0.4 and v0.7. + +The assessment in `history/2026-08-29-v07-scope-intent-assessment.md` checked every +v0.7 obligation against shipped code rather than intent. Three gaps survive, plus a +role the companion assigns that no conformance check will ever catch. + +## Why a workplan and not an adhoc + +T01 is a `MUST` that is currently unstated. T02 changes an enforcement boundary and +touches `ADR-0004`. T04 is a cross-repo stewardship commitment against a standard eight +repositories have yet to adopt. The convention reserves adhocs for low-risk work +completed directly; none of these qualify. + +## Tasks + +```task +id: WARDEN-WP-0034-T01 +status: todo +priority: high +``` + +**State the revocation visibility deadline (§9.7.2, a MUST).** + +ops-warden states none, and the honest value is the certificate TTL: **up to 48 hours**. +A cert issued under an allow remains valid for its full TTL even if the authorizing +decision is revoked the next minute. There is no CRL, no KRL distribution, and host-side +`auth_principals` belongs to `railiance-infra`. + +Add the deadline to `pep-stance.yaml` as what it is — `adm` 48h / `agt` 24h / `atm` 8h — +with the mechanism named (TTL expiry, no revocation channel) rather than implied. Assert +it against the shipped `ActorType` TTL policy by test, the same way the stance map is +asserted equal to shipped behaviour: a stated deadline free to drift from the code has +the same defect as a stated stance free to drift. + +**Done when:** the deadline is published, test-bound to the TTL policy, and the absence +of a revocation channel is stated rather than left to inference. + +**Not in scope:** shortening it. Whether 48h is acceptable is a joint question with +`railiance-infra` (KRL distribution) and is T05's to raise, not this task's to decide. + +```task +id: WARDEN-WP-0034-T02 +status: todo +priority: high +``` + +**Bind the agent read-boundary to an issued identity (§3.4 rule 1).** + +`ADR-0004`'s boundary triggers on `WARDEN_AGENT_ID` — a variable the agent sets about +itself. An agent that omits it is not recognised as one. §3.4 rule 1 now requires +authority to be *issued* per task and attributable to the principal acted for. + +The identity exists as of `KEY-WP-0009-T03`: `codex-railiance-platform`, subject +`service:codex:railiance-platform`, role `coding-agent`, 15-minute lifetime, with +`railiance-platform` enforcing the OpenBao-side policy. + +Key the boundary on the issued identity where one is present; keep `WARDEN_AGENT_ID` as +a fallback that fails **toward** the boundary, never away from it. State plainly in the +ADR trail which half is enforced and which is advisory: the OpenBao-side deny is real, +the ops-warden-side refusal is a courtesy that a determined caller can decline. + +**Done when:** an agent presenting the issued identity is recognised without setting +`WARDEN_AGENT_ID`, the fallback still refuses on `risk: high` lanes, and the +enforced/advisory split is written down. + +**Watch:** do not turn this into ops-warden validating a token — that is verifying an +identity claim, adjacent to deciding, and `ADR-0002`/§6 both point away from it. Read +the identity; do not adjudicate it. + +```task +id: WARDEN-WP-0034-T03 +status: todo +priority: medium +``` + +**Derive an emission cadence, or defer it with a reason (§9.6).** + +ops-warden's trail is attributive, so cadence is a SHOULD rather than v0.7's MUST for +load-bearing sources. It has been silent through two reviews, which is the one outcome +that is not defensible. + +Derive a baseline from the existing `audit.jsonl` and signatures log. If the signal is +too bursty to support a threshold — plausible, since volume is operator-driven — record +that as the finding with the distribution that shows it, and declare the deferral in +`pep-stance.yaml`. A measured "no useful baseline" is a result; silence is not. + +**Done when:** either a declared cadence with its derivation, or a declared deferral +carrying the data that justifies it. + +```task +id: WARDEN-WP-0034-T04 +status: todo +priority: medium +``` + +**Answer the question the companion sends the estate here to ask.** + +> *"For how to get something done — which lane, which credential, which route — ask +> `ops-warden`."* + +Today the repo answers credential questions and no others. `warden route` and +`warden plan` cover lanes, owners and acts. Nothing answers *"which layer am I"*, *"how +do I declare"*, *"I am PEP-shaped, what do I owe"* — and eight of fifteen catalogued +repositories have yet to declare. + +Provide the path, not the doctrine (that boundary is `ADR-0010`'s and does not move): +a routing entry and a short playbook that carry a reader from the companion to the files +to copy — `layer.yaml`, `pep-stance.yaml`, `check_layer_conformance.py`, +`test_layer_conformance.py` — and the check to run. The standard already names these in +§11 and §6.4; what is missing is the route to them. + +**Done when:** `warden route find "how do I declare my layer"` resolves, and the +playbook is reachable from the catalog. **Not** a restatement of the companion — a +pointer layer, per `ADR-0001`. + +```task +id: WARDEN-WP-0034-T05 +status: todo +priority: low +``` + +**Two things to raise rather than absorb.** + +Both are other repositories' to own; ops-warden's obligation is to route them, not to +fix them (`ADR-0003`, `ADR-0005`). + +1. **`ops-mason` has published no stance map.** §13.1's register has one row and the + standard says that is itself the finding. `ops-mason` is catalogued PEP-shaped in + the same paragraph and is ops-warden's peer lane owner. Offer the reference form; + do not write their map. +2. **The 48-hour replay window from T01.** Once stated, raise with `railiance-infra` + whether KRL distribution is worth building, and with `access-engine` whether a + decision lifetime shorter than the cert TTL is meaningful when nothing can recall + the cert. State the question; let the owners answer. + +**Done when:** both are routed with reasoning, and the answers recorded either way — +including a refusal, which is an equally good answer. + +## Related + +- `history/2026-08-29-v07-scope-intent-assessment.md` — the gap analysis behind this plan +- `history/2026-08-29-layer-model-v04-review.md`, `-v06-review.md` — the two prior reviews +- `security-layer-model_v0.7.md` §3.4, §6.4, §9.6, §9.7, §11, §13.1 +- `net-kingdom/SECURITY-COMPANION.md` v0.2 +- `ADR-0002`, `ADR-0003`, `ADR-0004`, `ADR-0005`, `ADR-0009`, `ADR-0010` From 2e3ff772f485f5ba3e858a3adbf778cebe05d44a Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 29 Aug 2026 14:55:36 +0200 Subject: [PATCH 22/32] Refresh work-record index for WARDEN-WP-0034 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YWBMovyFoy9RRrfL7zKvPJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- WORK-RECORDS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 5425d47..d1e0eb4 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -30,6 +30,7 @@ | workplan | WARDEN-WP-0031 | finished | — | workplans/WARDEN-WP-0031-policy-caller-identity.md | | workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md | | workplan | WARDEN-WP-0033 | finished | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | +| workplan | WARDEN-WP-0034 | ready | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | | task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md | | task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md | | task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md | @@ -129,5 +130,10 @@ | task | WARDEN-WP-0033-T04 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T05 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | task | WARDEN-WP-0033-T06 | done | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | +| task | WARDEN-WP-0034-T01 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | +| task | WARDEN-WP-0034-T02 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | +| task | WARDEN-WP-0034-T03 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | +| task | WARDEN-WP-0034-T04 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | +| task | WARDEN-WP-0034-T05 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | | intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md | | intake | WARDEN-IN-0002 | open | — | intakes/intakes.md | From d18d18e313da6ac0f0e8116cf92b707ffa89daab Mon Sep 17 00:00:00 2001 From: custodian-sync Date: Sat, 29 Aug 2026 14:56:20 +0200 Subject: [PATCH 23/32] chore(consistency): sync task status from DB [auto] Updated by fix-consistency on 2026-08-29: - update .custodian-brief.md for ops-warden Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- .custodian-brief.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.custodian-brief.md b/.custodian-brief.md index eb06359..01b0f6c 100644 --- a/.custodian-brief.md +++ b/.custodian-brief.md @@ -2,11 +2,21 @@ # Custodian Brief — ops-warden **Domain:** infotech -**Last synced:** 2026-08-28 20:02 UTC +**Last synced:** 2026-08-29 12:56 UTC **State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)* ## Active Workstreams +### Layer model v0.7 conformance — state the deadline, bind the agent boundary, steward the estate's newest rule +Progress: 0/5 done | workplan_id: `ae3ff76f-883d-5e2f-b6aa-144d61e8fdef` + +**Open tasks:** +- · Tasks `8b3bdb9f` +- · Tasks `3318ee1a` +- · Tasks `a891b32c` +- · Tasks `94e73daa` +- · Tasks `7d1b3c82` + ### Tamper-resistant credential governance + mass rotation/lockdown (Strand B) Progress: 2/3 done | workplan_id: `21528e8d-a049-523d-9ae1-da7a27cb8bbf` From 4e267179db741b27a3e62f81f753cd9752c97412 Mon Sep 17 00:00:00 2001 From: repo-manager Date: Sat, 29 Aug 2026 14:56:21 +0200 Subject: [PATCH 24/32] chore(registrar): assign State Hub identifiers Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014535@bnt-lap001 Assistant-Session: d0036016-73e8-4da1-8e47-563e3ab39a3c --- intakes/intakes.md | 1 + workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/intakes/intakes.md b/intakes/intakes.md index 192d793..0765cd7 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -89,4 +89,5 @@ description: 'v0.3 is proposed and changes sections 4, 9 and 13 only; the v0.2 a or rejection acceptable.' created: '2026-08-28T20:40:24.957468Z' updated: '2026-08-28T20:40:24.957468Z' +state_hub_intake_id: "01a04d97-94cd-7b49-8019-a91c7fce8adb" ``` diff --git a/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md b/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md index b233411..8e52f00 100644 --- a/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md +++ b/workplans/WARDEN-WP-0034-layer-model-v07-conformance.md @@ -12,6 +12,7 @@ depends_on_workplans: - WARDEN-WP-0030 created: "2026-08-29" updated: "2026-08-29" +state_hub_workstream_id: "ae3ff76f-883d-5e2f-b6aa-144d61e8fdef" --- # WARDEN-WP-0034 — Layer model v0.7 conformance @@ -37,6 +38,7 @@ completed directly; none of these qualify. id: WARDEN-WP-0034-T01 status: todo priority: high +state_hub_task_id: "8b3bdb9f-d2c2-5b3e-89e2-417bf3e37484" ``` **State the revocation visibility deadline (§9.7.2, a MUST).** @@ -62,6 +64,7 @@ of a revocation channel is stated rather than left to inference. id: WARDEN-WP-0034-T02 status: todo priority: high +state_hub_task_id: "3318ee1a-b5d9-5d39-baf7-9c42a8bc7b55" ``` **Bind the agent read-boundary to an issued identity (§3.4 rule 1).** @@ -91,6 +94,7 @@ the identity; do not adjudicate it. id: WARDEN-WP-0034-T03 status: todo priority: medium +state_hub_task_id: "a891b32c-b0a7-59f6-a5cd-977be65c09ca" ``` **Derive an emission cadence, or defer it with a reason (§9.6).** @@ -111,6 +115,7 @@ carrying the data that justifies it. id: WARDEN-WP-0034-T04 status: todo priority: medium +state_hub_task_id: "94e73daa-f74d-51fd-8639-68896a4066ee" ``` **Answer the question the companion sends the estate here to ask.** @@ -137,6 +142,7 @@ pointer layer, per `ADR-0001`. id: WARDEN-WP-0034-T05 status: todo priority: low +state_hub_task_id: "7d1b3c82-9b96-5087-a53a-496212909029" ``` **Two things to raise rather than absorb.** From b4c1d3900a528bbb9f2714d59403757426185d63 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 1 Sep 2026 00:13:26 +0200 Subject: [PATCH 25/32] Fix contained OpenBao login handoff Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- src/warden/proxy.py | 15 ++++---- tests/test_proxy.py | 36 +++++++++++++++++++ ...N-WP-0034-attended-login-openbao-output.md | 36 +++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 workplans/WARDEN-WP-0034-attended-login-openbao-output.md diff --git a/src/warden/proxy.py b/src/warden/proxy.py index 0acd379..1fd3e2a 100644 --- a/src/warden/proxy.py +++ b/src/warden/proxy.py @@ -12,8 +12,9 @@ intact. Three guardrails are enforced here in code: the tool with inherited stdout/stderr so the value never enters warden's memory; sanctioned exec/file transports hold it only for their bounded handoff. The high-risk attended-login lane is stricter: it captures every client byte inside - an isolated helper session, permits no output, self-revokes, and cleans up. Audit - records are metadata only. + an isolated helper session, never returns that output, requires successful + persistence to a private token helper, self-revokes, and cleans up. Audit records + are metadata only. * **G3 — policy gate before fetch.** The CLI runs ``check_fetch_policy`` before calling anything here; this module refuses to run an unresolved command template. @@ -380,9 +381,11 @@ def proxy_attended_login_exec( """Run an attended login and one silent child inside a private helper home. The default home is proven writable before the OIDC client starts. Login, - child, and revocation output are captured and discarded. Any non-empty output, - persistence defect, or non-zero result fails closed; any possibly issued token - is revoked before the isolated helper directory is removed. + child, and revocation output are captured and discarded. A successful login + may return client output only after the private helper has been populated; + persistence defects and non-zero results fail closed. The reviewed child must + remain silent. Any possibly issued token is revoked before the isolated helper + directory is removed. """ if not child_argv: raise ProxyError( @@ -428,7 +431,7 @@ def proxy_attended_login_exec( except (OSError, ProxyError): helper_valid = False - if login.returncode != 0 or login_output.strip() or not helper_valid: + if login.returncode != 0 or not helper_valid: revoked = _revoke_contained( resolved.argv[0], env=env, possible_output=login_output ) diff --git a/tests/test_proxy.py b/tests/test_proxy.py index cac3a97..e049b16 100644 --- a/tests/test_proxy.py +++ b/tests/test_proxy.py @@ -391,6 +391,42 @@ def test_attended_login_unexpected_output_is_contained_revoked_and_cleaned( assert not (tmp_path / ".warden-attended-login").exists() +def test_attended_login_contained_success_output_never_escapes(monkeypatch, tmp_path, capsys): + monkeypatch.setattr(Path, "home", lambda: tmp_path) + sentinel = "hvs.NONPRODUCTION_CONTAINED_LOGIN" + child_ran = False + + def fake_run(argv, **kw): + nonlocal child_ran + helper = Path(kw["env"]["HOME"]) / ".vault-token" + if argv[:2] == ["bao", "login"]: + helper.write_text(sentinel) + helper.chmod(0o600) + return subprocess.CompletedProcess( + argv, + 0, + stdout=json.dumps({"auth": {"client_token": sentinel}}).encode(), + stderr=b"", + ) + if argv == ["reviewed-child"]: + child_ran = True + return subprocess.CompletedProcess(argv, 0, stdout=b"", stderr=b"") + if argv[:3] == ["bao", "token", "revoke"]: + return subprocess.CompletedProcess(argv, 0, stdout=b"", stderr=b"") + raise AssertionError(argv) + + monkeypatch.setattr("warden.proxy.subprocess.run", fake_run) + assert proxy_attended_login_exec( + ResolvedFetch(argv=["bao", "login", "-no-print"]), + child_argv=["reviewed-child"], + ) == 0 + captured = capsys.readouterr() + assert child_ran is True + assert sentinel not in captured.out + assert sentinel not in captured.err + assert not (tmp_path / ".warden-attended-login").exists() + + def test_real_catalog_login_entry_is_login_lane(): from warden.routing import load_catalog e = load_catalog(_repo_catalog()).get("key-cape-oidc-login") diff --git a/workplans/WARDEN-WP-0034-attended-login-openbao-output.md b/workplans/WARDEN-WP-0034-attended-login-openbao-output.md new file mode 100644 index 0000000..0b616b8 --- /dev/null +++ b/workplans/WARDEN-WP-0034-attended-login-openbao-output.md @@ -0,0 +1,36 @@ +--- +id: WARDEN-WP-0034 +type: workplan +title: "Accept contained OpenBao login output only after helper persistence" +domain: infotech +repo: ops-warden +status: active +owner: codex +topic_slug: attended-login-openbao-output +created: "2026-09-01" +updated: "2026-09-01" +--- + +## Repair attended-login handoff + +```task +id: WARDEN-WP-0034-T01 +status: done +priority: high +``` + +Allow a successful OpenBao login to proceed when its output is fully contained +and the private mode-0600 token helper is populated. Continue failing closed on +non-zero login, missing persistence, child output, revocation failure, or cleanup +failure. + +## Verify live contained operation + +```task +id: WARDEN-WP-0034-T02 +status: progress +priority: high +``` + +Run the proxy regression suite, reinstall the CLI, and complete one governed +OpenBao platform-admin operation with deterministic self-revocation. From 8f01eefb1e958d060adfb78ea214464b730edd4d Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 1 Sep 2026 00:24:18 +0200 Subject: [PATCH 26/32] Preserve Warden config in attended child Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- src/warden/proxy.py | 4 ++++ tests/test_proxy.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/warden/proxy.py b/src/warden/proxy.py index 1fd3e2a..65e4455 100644 --- a/src/warden/proxy.py +++ b/src/warden/proxy.py @@ -403,6 +403,10 @@ def proxy_attended_login_exec( root, session, root_created = _prepare_attended_login_home() helper = session / _TOKEN_HELPER_NAME env = _caller_env() + if not env.get("WARDEN_CONFIG"): + caller_config = Path.home() / ".config" / "warden" / "warden.yaml" + if caller_config.is_file(): + env["WARDEN_CONFIG"] = str(caller_config) env["HOME"] = str(session) env.pop("BAO_TOKEN", None) env.pop("VAULT_TOKEN", None) diff --git a/tests/test_proxy.py b/tests/test_proxy.py index e049b16..b67b122 100644 --- a/tests/test_proxy.py +++ b/tests/test_proxy.py @@ -427,6 +427,34 @@ def test_attended_login_contained_success_output_never_escapes(monkeypatch, tmp_ assert not (tmp_path / ".warden-attended-login").exists() +def test_attended_login_preserves_caller_warden_config_for_reviewed_child( + monkeypatch, tmp_path +): + monkeypatch.setattr(Path, "home", lambda: tmp_path) + monkeypatch.delenv("WARDEN_CONFIG", raising=False) + caller_config = tmp_path / ".config" / "warden" / "warden.yaml" + caller_config.parent.mkdir(parents=True) + caller_config.write_text("backend: local\n") + seen_config = None + + def fake_run(argv, **kw): + nonlocal seen_config + helper = Path(kw["env"]["HOME"]) / ".vault-token" + if argv[:2] == ["bao", "login"]: + helper.write_text("non-production-test-double") + helper.chmod(0o600) + if argv == ["reviewed-child"]: + seen_config = kw["env"].get("WARDEN_CONFIG") + return subprocess.CompletedProcess(argv, 0, stdout=b"", stderr=b"") + + monkeypatch.setattr("warden.proxy.subprocess.run", fake_run) + assert proxy_attended_login_exec( + ResolvedFetch(argv=["bao", "login", "-no-print"]), + child_argv=["reviewed-child"], + ) == 0 + assert seen_config == str(caller_config) + + def test_real_catalog_login_entry_is_login_lane(): from warden.routing import load_catalog e = load_catalog(_repo_catalog()).get("key-cape-oidc-login") From 4fee839b1138c60642bd6e0210cf8bf541333747 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 1 Sep 2026 00:46:28 +0200 Subject: [PATCH 27/32] feat: route Policy Nexus source credential Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- registry/routing/catalog.yaml | 36 ++++++++++++ tests/test_routing.py | 26 +++++++++ tests/test_workload_join.py | 2 +- .../policy-nexus-forgejo-source-read.md | 55 +++++++++++++++++++ ...N-WP-0034-attended-login-openbao-output.md | 8 ++- ...-policy-nexus-forgejo-source-read-route.md | 36 ++++++++++++ 6 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 wiki/playbooks/policy-nexus-forgejo-source-read.md create mode 100644 workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md diff --git a/registry/routing/catalog.yaml b/registry/routing/catalog.yaml index 09f690e..7b91b40 100644 --- a/registry/routing/catalog.yaml +++ b/registry/routing/catalog.yaml @@ -242,6 +242,42 @@ entries: - "Write it back: `bao kv put platform/workloads/coulomb/whynot-design/npm-publish NPM_AUTH_TOKEN=@file` (value from a mode-0600 file)." - "Verify capabilities-safe, then confirm publish works via `secrets-engine exec --catalog whynot-design-npm-publish -- npm whoami` (value used, not printed)." + - id: policy-nexus-forgejo-source-read + title: Policy Nexus Forgejo private-source repository read token + # Read-only at Forgejo, but disclosure grants estate-wide private source access. + # Agent callers therefore remain inside Warden's sanctioned transport boundary. + risk: high + workload_ref: + applicability: applicable + unknown_reason: "policy-nexus-actions has not published an authoritative workload identity declaration." + need_keywords: [policy-nexus, policy, nexus, forgejo, private, source, repository, read, token, actions, FORGEJO_SOURCE_TOKEN] + owner_repo: railiance-platform + subsystem: OpenBao + Forgejo Actions + warden_executes: false + wiki_ref: wiki/playbooks/policy-nexus-forgejo-source-read.md#worker-checklist + canon_ref: railiance-platform/credential-change-requests/CCR-2026-0014-policy-nexus-forgejo-source-read.yaml + reviewed: "2026-09-01" + status: active + delegation: + mode: native + intended_owner: railiance-platform + reviewed: "2026-09-01" + verified: source-read + auth_method: "bao login -method=oidc -path=netkingdom role=policy-nexus-forgejo-source-workload-kv-read" + path_template: "platform/workloads/policy-nexus/forgejo-source-read" + fetch_command: "bao kv get -field=FORGEJO_SOURCE_TOKEN platform/workloads/policy-nexus/forgejo-source-read" + policy_ref: "flex-auth check secret.read:policy-nexus" + exec_capable: true + lane: secret + rotation: + method: rotate + owner: railiance-platform + automatable: false + steps: + - "Mint a replacement PAT for the restricted policy-nexus-source identity with scope exactly read:repository; retain the predecessor until verification passes." + - "Use the attended railiance-platform bootstrap to update OpenBao and the coulomb/policy-nexus FORGEJO_SOURCE_TOKEN Actions secret without exposing the value." + - "Pass one exact-commit candidate workflow, then revoke the predecessor PAT and record bounded non-secret evidence in CCR-2026-0014." + - id: flex-auth-policy-check title: Authorization decision — may this actor perform this action # Returns an authorization decision; no credential flows (WARDEN-WP-0032-T05). diff --git a/tests/test_routing.py b/tests/test_routing.py index f280dda..1e5d691 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -153,6 +153,32 @@ def test_whynot_design_npm_lane_is_concrete_and_resolvable(): assert "platform/workloads/coulomb/whynot-design/npm-publish" in e.fetch_command +def test_policy_nexus_source_read_lane_is_exact_high_risk_and_resolvable(): + catalog = load_catalog(_repo_catalog()) + entry = catalog.get("policy-nexus-forgejo-source-read") + assert entry is not None and entry.is_active and entry.exec_capable + assert entry.resolvable is True + assert entry.risk == "high" + assert entry.owner_repo == "railiance-platform" + assert entry.fetch_command == ( + "bao kv get -field=FORGEJO_SOURCE_TOKEN " + "platform/workloads/policy-nexus/forgejo-source-read" + ) + assert entry.path_template == "platform/workloads/policy-nexus/forgejo-source-read" + assert entry.auth_method.endswith( + "role=policy-nexus-forgejo-source-workload-kv-read" + ) + assert entry.delegation is not None and entry.delegation.mode == "native" + + +def test_route_find_policy_nexus_source_read_prefers_concrete_lane(): + catalog = load_catalog(_repo_catalog()) + matches = catalog.find( + "policy nexus Forgejo private source repository read token Actions", limit=1 + ) + assert matches[0].id == "policy-nexus-forgejo-source-read" + + def test_generic_and_template_lanes_not_resolvable(): catalog = load_catalog(_repo_catalog()) # generic openbao lane has /; login lane has . diff --git a/tests/test_workload_join.py b/tests/test_workload_join.py index dab4df8..d87e5dd 100644 --- a/tests/test_workload_join.py +++ b/tests/test_workload_join.py @@ -13,7 +13,7 @@ def test_repo_catalog_uses_only_explicit_workload_references(): report = build(ROOT / "registry/routing/catalog.yaml", Path.home()) assert report["ok"] is True assert len(report["resolved"]) == 3 - assert len(report["unknown"]) == 17 + assert len(report["unknown"]) == 18 # 11 since WARDEN-WP-0033: the two NetKingdom SSO lanes (c374d41) are # provider/control-plane credentials, not workload delivery lanes. assert len(report["not_applicable"]) == 11 diff --git a/wiki/playbooks/policy-nexus-forgejo-source-read.md b/wiki/playbooks/policy-nexus-forgejo-source-read.md new file mode 100644 index 0000000..6e704c7 --- /dev/null +++ b/wiki/playbooks/policy-nexus-forgejo-source-read.md @@ -0,0 +1,55 @@ +# Policy Nexus Forgejo source-read token + +Date: 2026-09-01 +Catalog: `policy-nexus-forgejo-source-read` (status `active`, `resolvable: true`) +Owner: `railiance-platform` (OpenBao and credential lifecycle) + +This lane carries the dedicated Forgejo PAT used by Policy Nexus Actions to +fetch exact archives from private owner repositories. The Forgejo identity is +restricted to organization-wide repository-code read and the PAT scope is +exactly `read:repository`. It has no repository write, package, organization +administration, instance administration, cluster, or deployment authority. + +The authoritative lifecycle and evidence record is +`railiance-platform/credential-change-requests/CCR-2026-0014-policy-nexus-forgejo-source-read.yaml`. +Warden is a governed conduit and never owns, persists, caches, or logs the PAT. + +## Owner-confirmed lane + +| Field | Value | +| --- | --- | +| OpenBao path | `platform/workloads/policy-nexus/forgejo-source-read` | +| Primary field | `FORGEJO_SOURCE_TOKEN` | +| Read policy | `workload-kv-read-policy-nexus-forgejo-source` | +| OIDC role | `policy-nexus-forgejo-source-workload-kv-read` | +| Forgejo identity | `policy-nexus-source` | +| Forgejo team | `policy-nexus-source-readers` | +| Actions consumer | `coulomb/policy-nexus` secret `FORGEJO_SOURCE_TOKEN` | + +## Worker checklist + +1. Authenticate as an approved operator through the exact OIDC role. Do not + substitute the Forgejo admin PAT or a broader OpenBao identity. + +2. Confirm the route before use: + + ```bash + warden route show policy-nexus-forgejo-source-read --json | jq .resolvable + ``` + + The result must be `true`, and the rendered fetch must contain no placeholder. + +3. Agent callers must use a sanctioned high-risk transport. Pass the value only + to the bounded source-consuming child: + + ```bash + warden access policy-nexus-forgejo-source-read \ + --field FORGEJO_SOURCE_TOKEN --exec -- + ``` + + Do not use raw `--fetch`, place the value on argv, or write it to chat, Git, + State Hub, workflow logs, or a persistent temporary file. + +4. For rotation or compromise, follow CCR-2026-0014. A replacement is not active + until its scope and negative permissions are verified and one exact-commit + Policy Nexus candidate workflow succeeds; revoke the predecessor afterward. diff --git a/workplans/WARDEN-WP-0034-attended-login-openbao-output.md b/workplans/WARDEN-WP-0034-attended-login-openbao-output.md index 0b616b8..8dee644 100644 --- a/workplans/WARDEN-WP-0034-attended-login-openbao-output.md +++ b/workplans/WARDEN-WP-0034-attended-login-openbao-output.md @@ -4,7 +4,7 @@ type: workplan title: "Accept contained OpenBao login output only after helper persistence" domain: infotech repo: ops-warden -status: active +status: finished owner: codex topic_slug: attended-login-openbao-output created: "2026-09-01" @@ -28,9 +28,13 @@ failure. ```task id: WARDEN-WP-0034-T02 -status: progress +status: done priority: high ``` Run the proxy regression suite, reinstall the CLI, and complete one governed OpenBao platform-admin operation with deterministic self-revocation. + +Completed 2026-09-01. The installed CLI completed the governed Policy Nexus +Forgejo source bootstrap with all child output contained, then revoked and +removed its isolated helper session. diff --git a/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md b/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md new file mode 100644 index 0000000..79e4e0d --- /dev/null +++ b/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md @@ -0,0 +1,36 @@ +--- +id: WARDEN-WP-0035 +type: workplan +title: "Register the Policy Nexus Forgejo source-read route" +domain: infotech +repo: ops-warden +status: active +owner: codex +topic_slug: policy-nexus-forgejo-source-read +created: "2026-09-01" +updated: "2026-09-01" +--- + +## Register the exact high-risk lane + +```task +id: WARDEN-WP-0035-T01 +status: done +priority: high +``` + +Add the exact OpenBao path, field, OIDC role, owner pointer, and rotation +boundary from railiance-platform CCR-2026-0014. The entry must be concrete and +resolvable while remaining subject to Warden's high-risk agent read boundary. + +## Verify routing and governed use + +```task +id: WARDEN-WP-0035-T02 +status: progress +priority: high +``` + +Pass catalog, route-selection, proxy, and policy tests; reinstall the CLI; prove +the installed route resolves and can hand the value only to a sanctioned child +transport without printing or persisting it. From eddb5d426b20c84777e69e4a822ca1a2397e41f4 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 1 Sep 2026 00:47:25 +0200 Subject: [PATCH 28/32] chore: refresh high-risk credential paths Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- registry/generated/high-risk-data-paths.yaml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/registry/generated/high-risk-data-paths.yaml b/registry/generated/high-risk-data-paths.yaml index 78d3ce6..e7f858e 100644 --- a/registry/generated/high-risk-data-paths.yaml +++ b/registry/generated/high-risk-data-paths.yaml @@ -10,13 +10,13 @@ # declares it, and is null where the field set has not been established -- # null means unknown, never 'one field'. -generated_at: "2026-08-29T00:44:23Z" +generated_at: "2026-08-31T22:46:47Z" source: ops-warden/registry/routing/catalog.yaml -catalog_revision: "ee94c189385271194f22a53998b2c6e12e961ea9" -catalog_revision_date: "2026-08-28T22:00:09+02:00" +catalog_revision: "4fee839b1138c60642bd6e0210cf8bf541333747" +catalog_revision_date: "2026-09-01T00:46:28+02:00" catalog_dirty: false -high_risk_lane_count: 23 -concrete_path_count: 14 +high_risk_lane_count: 24 +concrete_path_count: 15 # Graded high but not a single KV address -- a routing pattern, a broker # grant, or a non-KV lane. Nothing here for a policy to deny. @@ -77,6 +77,11 @@ paths: metadata_path: platform/metadata/workloads/activity-core/llm-connect/llm-connect-provider-secrets owner_repo: railiance-platform fields: null # field set not established -- unknown, not one + - id: policy-nexus-forgejo-source-read + data_path: platform/data/workloads/policy-nexus/forgejo-source-read + metadata_path: platform/metadata/workloads/policy-nexus/forgejo-source-read + owner_repo: railiance-platform + fields: null # field set not established -- unknown, not one - id: railiance-backup-offsite-lane data_path: platform/data/workloads/railiance/backup/offsite-lane metadata_path: platform/metadata/workloads/railiance/backup/offsite-lane From 31694ab64ddc8a855a28cc6b04e6b1de5a86fca8 Mon Sep 17 00:00:00 2001 From: custodian-sync Date: Tue, 1 Sep 2026 00:50:08 +0200 Subject: [PATCH 29/32] chore(consistency): sync task status from DB [auto] Updated by fix-consistency on 2026-09-01: - update .custodian-brief.md for ops-warden Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- .custodian-brief.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.custodian-brief.md b/.custodian-brief.md index 01b0f6c..830ff11 100644 --- a/.custodian-brief.md +++ b/.custodian-brief.md @@ -2,7 +2,7 @@ # Custodian Brief — ops-warden **Domain:** infotech -**Last synced:** 2026-08-29 12:56 UTC +**Last synced:** 2026-08-31 22:49 UTC **State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)* ## Active Workstreams @@ -23,6 +23,11 @@ Progress: 2/3 done | workplan_id: `21528e8d-a049-523d-9ae1-da7a27cb8bbf` **Open tasks:** - ► Task: Graded lockdown / break-glass with explicit trust-root `cae498ee` +## Inbox Hygiene + +**Stale unread:** 1 message(s) older than 3 day(s) — triage at session start. +**Missing thread_id:** 6 unread message(s) lack supersession chains. + --- ## MCP Orientation (when available) From 9770d6ad661fcd2fe8c2982fb4f31e7ee9a2d961 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 1 Sep 2026 00:51:52 +0200 Subject: [PATCH 30/32] docs: close Warden credential workplans Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- ...-WP-0035-policy-nexus-forgejo-source-read-route.md | 11 +++++++++-- ...> WARDEN-WP-0036-attended-login-openbao-output.md} | 6 +++--- 2 files changed, 12 insertions(+), 5 deletions(-) rename workplans/{WARDEN-WP-0034-attended-login-openbao-output.md => WARDEN-WP-0036-attended-login-openbao-output.md} (93%) diff --git a/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md b/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md index 79e4e0d..af56f05 100644 --- a/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md +++ b/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md @@ -4,7 +4,7 @@ type: workplan title: "Register the Policy Nexus Forgejo source-read route" domain: infotech repo: ops-warden -status: active +status: finished owner: codex topic_slug: policy-nexus-forgejo-source-read created: "2026-09-01" @@ -27,10 +27,17 @@ resolvable while remaining subject to Warden's high-risk agent read boundary. ```task id: WARDEN-WP-0035-T02 -status: progress +status: done priority: high ``` Pass catalog, route-selection, proxy, and policy tests; reinstall the CLI; prove the installed route resolves and can hand the value only to a sanctioned child transport without printing or persisting it. + +Completed 2026-09-01. All 406 selected tests passed, including the generated +high-risk data-path boundary. The no-cache installed CLI resolves the exact +lane, and `warden plan` returns only sanctioned `--exec`, `--out`, and `--wrap` +transports for an agent caller. Policy Nexus Actions run 32 separately proved +the installed credential against the complete private-source fetch and release +path without exposing the value. diff --git a/workplans/WARDEN-WP-0034-attended-login-openbao-output.md b/workplans/WARDEN-WP-0036-attended-login-openbao-output.md similarity index 93% rename from workplans/WARDEN-WP-0034-attended-login-openbao-output.md rename to workplans/WARDEN-WP-0036-attended-login-openbao-output.md index 8dee644..8607194 100644 --- a/workplans/WARDEN-WP-0034-attended-login-openbao-output.md +++ b/workplans/WARDEN-WP-0036-attended-login-openbao-output.md @@ -1,5 +1,5 @@ --- -id: WARDEN-WP-0034 +id: WARDEN-WP-0036 type: workplan title: "Accept contained OpenBao login output only after helper persistence" domain: infotech @@ -14,7 +14,7 @@ updated: "2026-09-01" ## Repair attended-login handoff ```task -id: WARDEN-WP-0034-T01 +id: WARDEN-WP-0036-T01 status: done priority: high ``` @@ -27,7 +27,7 @@ failure. ## Verify live contained operation ```task -id: WARDEN-WP-0034-T02 +id: WARDEN-WP-0036-T02 status: done priority: high ``` From 529feeac49a8cde94f68776fc45557c90e2a5a5a Mon Sep 17 00:00:00 2001 From: repo-manager Date: Tue, 1 Sep 2026 00:51:59 +0200 Subject: [PATCH 31/32] repo.work.assign_missing_identifiers source: repo-manager reason: deterministic projection registration Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- workplans/ADHOC-2026-06-27.md | 1 + workplans/ADHOC-2026-06-29.md | 1 + workplans/ADHOC-2026-08-11.md | 3 +++ workplans/ADHOC-2026-08-17.md | 4 ++++ .../WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md | 3 +++ workplans/WARDEN-WP-0036-attended-login-openbao-output.md | 3 +++ workplans/archived/260707-ADHOC-2026-07-07.md | 1 + 7 files changed, 16 insertions(+) diff --git a/workplans/ADHOC-2026-06-27.md b/workplans/ADHOC-2026-06-27.md index e7e0a23..d75908f 100644 --- a/workplans/ADHOC-2026-06-27.md +++ b/workplans/ADHOC-2026-06-27.md @@ -22,6 +22,7 @@ Low-risk opportunistic fixes completed directly during the consolidation session id: WARDEN-WP-ADHOC-2026-06-27-T01 status: done priority: medium +state_hub_task_id: "9176b560-8ca5-5143-888d-479857fe60f0" ``` issue-core reported (msg `70bcf238`) that the `warden` CLI on `~/.local/bin` lacked diff --git a/workplans/ADHOC-2026-06-29.md b/workplans/ADHOC-2026-06-29.md index d078876..b46be0f 100644 --- a/workplans/ADHOC-2026-06-29.md +++ b/workplans/ADHOC-2026-06-29.md @@ -20,6 +20,7 @@ state_hub_workstream_id: "13fa845f-852e-55ec-a2a5-2296996e0216" id: WARDEN-WP-ADHOC-2026-06-29-T01 status: done priority: medium +state_hub_task_id: "62540533-f4ca-5176-9237-32adbeb292ee" ``` flex-auth (msg `ea00620b`) asked ops-warden to help close FLEX-WP-0007 T4 (joint OpenBao diff --git a/workplans/ADHOC-2026-08-11.md b/workplans/ADHOC-2026-08-11.md index a25c69f..3d858fe 100644 --- a/workplans/ADHOC-2026-08-11.md +++ b/workplans/ADHOC-2026-08-11.md @@ -20,6 +20,7 @@ state_hub_workstream_id: "9f99cc64-4682-5f20-b13e-89af2b6f7c70" id: WARDEN-WP-ADHOC-2026-08-11-T01 status: done priority: medium +state_hub_task_id: "0771d121-278c-556e-9509-841cf6e657c3" ``` rapp-postgres (msg `96907986`, residual from RAPP-POSTGRES-WP-0002-T04) reported the @@ -41,6 +42,7 @@ an anchor that does not exist. The intended heading is `## Routing catalog index id: WARDEN-WP-ADHOC-2026-08-11-T02 status: done priority: medium +state_hub_task_id: "0ed58145-732f-5102-b6a8-b931d9b6ba08" ``` `fix-consistency` flagged 11 unread messages older than 3 days, two of them as possible @@ -74,6 +76,7 @@ read. Inbox is now empty. id: WARDEN-WP-ADHOC-2026-08-11-T03 status: done priority: medium +state_hub_task_id: "337ae793-c6b0-59e9-8a07-3a7ccba237aa" ``` secrets-engine (msg `80456912`, 2026-06-29) is holding a validated non-mutating dry-run diff --git a/workplans/ADHOC-2026-08-17.md b/workplans/ADHOC-2026-08-17.md index 1b0b62f..65d7595 100644 --- a/workplans/ADHOC-2026-08-17.md +++ b/workplans/ADHOC-2026-08-17.md @@ -24,6 +24,7 @@ workload-identity owner. id: WARDEN-WP-ADHOC-2026-08-17-T01 status: done priority: high +state_hub_task_id: "04a2f8f9-e70b-5eed-ad87-343c8f9ef501" ``` flex-auth (msg `130a148c`, FLEX-WP-0015 T02) reported that `POST /v1/check` and @@ -71,6 +72,7 @@ Their four questions answered in `wiki/NetKingdomSecurityMap.md` id: WARDEN-WP-ADHOC-2026-08-17-T02 status: done priority: medium +state_hub_task_id: "0e815282-2fad-5c8d-be34-398e492737d0" ``` user-engine (msg `2af4a124`) answered the open confirm question on @@ -96,6 +98,7 @@ consumes it and has no authority over custody, rotation, or issuance. id: WARDEN-WP-ADHOC-2026-08-17-T03 status: done priority: medium +state_hub_task_id: "e21781d9-a35d-5916-b335-d12131f97a22" ``` key-cape (msg `099b7cba`) acknowledged the lane staying interim on ops-warden. @@ -118,6 +121,7 @@ workplan. id: WARDEN-WP-ADHOC-2026-08-17-T04 status: done priority: low +state_hub_task_id: "b15724e0-c27a-5260-a810-4dd25bff2228" ``` - [x] `uv run pytest -q` → 338 passed, 4 deselected (routing anchor + no-double-source diff --git a/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md b/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md index af56f05..1210b15 100644 --- a/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md +++ b/workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md @@ -9,6 +9,7 @@ owner: codex topic_slug: policy-nexus-forgejo-source-read created: "2026-09-01" updated: "2026-09-01" +state_hub_workstream_id: "45aec8d3-94b3-586e-b019-a47e656efafa" --- ## Register the exact high-risk lane @@ -17,6 +18,7 @@ updated: "2026-09-01" id: WARDEN-WP-0035-T01 status: done priority: high +state_hub_task_id: "dd84f2be-0143-540c-9c16-74f0fd129260" ``` Add the exact OpenBao path, field, OIDC role, owner pointer, and rotation @@ -29,6 +31,7 @@ resolvable while remaining subject to Warden's high-risk agent read boundary. id: WARDEN-WP-0035-T02 status: done priority: high +state_hub_task_id: "1fa8f778-3e46-5f44-86c4-cab8628b7e60" ``` Pass catalog, route-selection, proxy, and policy tests; reinstall the CLI; prove diff --git a/workplans/WARDEN-WP-0036-attended-login-openbao-output.md b/workplans/WARDEN-WP-0036-attended-login-openbao-output.md index 8607194..594b5ae 100644 --- a/workplans/WARDEN-WP-0036-attended-login-openbao-output.md +++ b/workplans/WARDEN-WP-0036-attended-login-openbao-output.md @@ -9,6 +9,7 @@ owner: codex topic_slug: attended-login-openbao-output created: "2026-09-01" updated: "2026-09-01" +state_hub_workstream_id: "d844c96e-152d-53fa-bff6-e072125ef66c" --- ## Repair attended-login handoff @@ -17,6 +18,7 @@ updated: "2026-09-01" id: WARDEN-WP-0036-T01 status: done priority: high +state_hub_task_id: "7eb8b9c9-1285-5ada-a17b-1d5bfbb8ba59" ``` Allow a successful OpenBao login to proceed when its output is fully contained @@ -30,6 +32,7 @@ failure. id: WARDEN-WP-0036-T02 status: done priority: high +state_hub_task_id: "d22bab05-c38b-561f-95de-6c146ce7c6cf" ``` Run the proxy regression suite, reinstall the CLI, and complete one governed diff --git a/workplans/archived/260707-ADHOC-2026-07-07.md b/workplans/archived/260707-ADHOC-2026-07-07.md index fc02506..31e9d27 100644 --- a/workplans/archived/260707-ADHOC-2026-07-07.md +++ b/workplans/archived/260707-ADHOC-2026-07-07.md @@ -22,6 +22,7 @@ state_hub_workstream_id: "90568b1e-8395-5c67-9c69-851ed08ff3d3" id: WARDEN-WP-ADHOC-2026-07-07-T01 status: done priority: high +state_hub_task_id: "bf985c95-bea6-5057-94f9-9cfa7e1c9dd8" ``` `warden access` failed on `reuse-surface-hub-write-token` because `shlex.split` From 8afcc9c32170d76f6d5d02ea153967ed5c6fc4d5 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 1 Sep 2026 01:27:55 +0200 Subject: [PATCH 32/32] chore: refresh Warden work-record indexes Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- .repo-manager/index.json | 171 ++++++++++++++++++++++++++++++++------- WORK-RECORDS.md | 6 ++ 2 files changed, 150 insertions(+), 27 deletions(-) diff --git a/.repo-manager/index.json b/.repo-manager/index.json index 95e4806..ae60c11 100644 --- a/.repo-manager/index.json +++ b/.repo-manager/index.json @@ -1,10 +1,10 @@ { "schema": "repo_manager.index.v1", - "slug": "layer-model-v03-review", + "slug": "ops-warden", "repo_root": "/home/worsch/ops-warden", - "head_sha": "f289465b90fcdffe2c8bf4a51cc71607747126f9", - "observed_at": "2026-08-28T20:40:26.143458Z", - "source_fingerprint": "a9ae0d530804e039aae34b4902d8609723e9bba4385a501b9a4027911c3b6302", + "head_sha": "529feeac49a8cde94f68776fc45557c90e2a5a5a", + "observed_at": "2026-08-31T22:59:28.638497Z", + "source_fingerprint": "6f60b2dbcb864a3f8e45a97c247ab142a765487187e67edf52bdb57027087bd4", "source_files": [ ".repo-classification.yaml", "INTENT.md", @@ -31,6 +31,9 @@ "workplans/WARDEN-WP-0031-policy-caller-identity.md", "workplans/WARDEN-WP-0032-security-zones.md", "workplans/WARDEN-WP-0033-native-lane-handoff.md", + "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md", + "workplans/WARDEN-WP-0036-attended-login-openbao-output.md", "workplans/archived/260515-WARDEN-WP-0001-initial-implementation.md", "workplans/archived/260515-WARDEN-WP-0002-correctness-and-completeness.md", "workplans/archived/260515-WARDEN-WP-0003-test-coverage-and-quality.md", @@ -65,7 +68,7 @@ "status": "done", "title": "T01 \u2014 Fix stale `warden` CLI install + make it usable outside the repo", "source_path": "workplans/ADHOC-2026-06-27.md", - "uuid": null, + "uuid": "9176b560-8ca5-5143-888d-479857fe60f0", "parent_id": "WARDEN-WP-ADHOC-2026-06-27", "extra": {} }, @@ -85,7 +88,7 @@ "status": "done", "title": "T01 \u2014 Joint-smoke mode for the deployed flex-auth (assist FLEX-WP-0007 T4)", "source_path": "workplans/ADHOC-2026-06-29.md", - "uuid": null, + "uuid": "62540533-f4ca-5176-9237-32adbeb292ee", "parent_id": "WARDEN-WP-ADHOC-2026-06-29", "extra": {} }, @@ -105,7 +108,7 @@ "status": "done", "title": "T01 \u2014 Repair stale `rapp-qonto-keycape-client` wiki anchor (restore green routing suite)", "source_path": "workplans/ADHOC-2026-08-11.md", - "uuid": null, + "uuid": "0771d121-278c-556e-9509-841cf6e657c3", "parent_id": "WARDEN-WP-ADHOC-2026-08-11", "extra": {} }, @@ -115,7 +118,7 @@ "status": "done", "title": "T02 \u2014 Triage the stale ops-warden inbox (11 unread, C-28/C-29)", "source_path": "workplans/ADHOC-2026-08-11.md", - "uuid": null, + "uuid": "0ed58145-732f-5102-b6a8-b931d9b6ba08", "parent_id": "WARDEN-WP-ADHOC-2026-08-11", "extra": {} }, @@ -125,7 +128,7 @@ "status": "done", "title": "T03 \u2014 warden-sign AppRole: PARKED pending WP-0027 break-glass + ops-bridge cutover", "source_path": "workplans/ADHOC-2026-08-11.md", - "uuid": null, + "uuid": "337ae793-c6b0-59e9-8a07-3a7ccba237aa", "parent_id": "WARDEN-WP-ADHOC-2026-08-11", "extra": {} }, @@ -145,7 +148,7 @@ "status": "done", "title": "T01 \u2014 Answer flex-auth: how should `/v1/check` authenticate its callers?", "source_path": "workplans/ADHOC-2026-08-17.md", - "uuid": null, + "uuid": "04a2f8f9-e70b-5eed-ad87-343c8f9ef501", "parent_id": "WARDEN-WP-ADHOC-2026-08-17", "extra": {} }, @@ -155,7 +158,7 @@ "status": "done", "title": "T02 \u2014 user-engine: USER_ENGINE_PROXY_SECRET stays railiance-apps; record consumer-only", "source_path": "workplans/ADHOC-2026-08-17.md", - "uuid": null, + "uuid": "0e815282-2fad-5c8d-be34-398e492737d0", "parent_id": "WARDEN-WP-ADHOC-2026-08-17", "extra": {} }, @@ -165,7 +168,7 @@ "status": "done", "title": "T03 \u2014 key-cape: `rapp-qonto-keycape-client` interim accepted; refresh the blocker", "source_path": "workplans/ADHOC-2026-08-17.md", - "uuid": null, + "uuid": "e21781d9-a35d-5916-b335-d12131f97a22", "parent_id": "WARDEN-WP-ADHOC-2026-08-17", "extra": {} }, @@ -175,7 +178,7 @@ "status": "done", "title": "T04 \u2014 Session hygiene", "source_path": "workplans/ADHOC-2026-08-17.md", - "uuid": null, + "uuid": "b15724e0-c27a-5260-a810-4dd25bff2228", "parent_id": "WARDEN-WP-ADHOC-2026-08-17", "extra": {} }, @@ -1259,6 +1262,126 @@ "parent_id": "WARDEN-WP-0033", "extra": {} }, + { + "kind": "workplan", + "id": "WARDEN-WP-0034", + "status": "ready", + "title": "Layer model v0.7 conformance \u2014 state the deadline, bind the agent boundary, steward the estate's newest rule", + "source_path": "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "uuid": "ae3ff76f-883d-5e2f-b6aa-144d61e8fdef", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0034-T01", + "status": "todo", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "uuid": "8b3bdb9f-d2c2-5b3e-89e2-417bf3e37484", + "parent_id": "WARDEN-WP-0034", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0034-T02", + "status": "todo", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "uuid": "3318ee1a-b5d9-5d39-baf7-9c42a8bc7b55", + "parent_id": "WARDEN-WP-0034", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0034-T03", + "status": "todo", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "uuid": "a891b32c-b0a7-59f6-a5cd-977be65c09ca", + "parent_id": "WARDEN-WP-0034", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0034-T04", + "status": "todo", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "uuid": "94e73daa-f74d-51fd-8639-68896a4066ee", + "parent_id": "WARDEN-WP-0034", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0034-T05", + "status": "todo", + "title": "Tasks", + "source_path": "workplans/WARDEN-WP-0034-layer-model-v07-conformance.md", + "uuid": "7d1b3c82-9b96-5087-a53a-496212909029", + "parent_id": "WARDEN-WP-0034", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0035", + "status": "finished", + "title": "Register the Policy Nexus Forgejo source-read route", + "source_path": "workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md", + "uuid": "45aec8d3-94b3-586e-b019-a47e656efafa", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0035-T01", + "status": "done", + "title": "Register the exact high-risk lane", + "source_path": "workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md", + "uuid": "dd84f2be-0143-540c-9c16-74f0fd129260", + "parent_id": "WARDEN-WP-0035", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0035-T02", + "status": "done", + "title": "Verify routing and governed use", + "source_path": "workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md", + "uuid": "1fa8f778-3e46-5f44-86c4-cab8628b7e60", + "parent_id": "WARDEN-WP-0035", + "extra": {} + }, + { + "kind": "workplan", + "id": "WARDEN-WP-0036", + "status": "finished", + "title": "Accept contained OpenBao login output only after helper persistence", + "source_path": "workplans/WARDEN-WP-0036-attended-login-openbao-output.md", + "uuid": "d844c96e-152d-53fa-bff6-e072125ef66c", + "parent_id": null, + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0036-T01", + "status": "done", + "title": "Repair attended-login handoff", + "source_path": "workplans/WARDEN-WP-0036-attended-login-openbao-output.md", + "uuid": "7eb8b9c9-1285-5ada-a17b-1d5bfbb8ba59", + "parent_id": "WARDEN-WP-0036", + "extra": {} + }, + { + "kind": "task", + "id": "WARDEN-WP-0036-T02", + "status": "done", + "title": "Verify live contained operation", + "source_path": "workplans/WARDEN-WP-0036-attended-login-openbao-output.md", + "uuid": "d22bab05-c38b-561f-95de-6c146ce7c6cf", + "parent_id": "WARDEN-WP-0036", + "extra": {} + }, { "kind": "workplan", "id": "WARDEN-WP-0001", @@ -2165,7 +2288,7 @@ "status": "done", "title": "T01 \u2014 Roll out proxy pipe fix (be3b4a2)", "source_path": "workplans/archived/260707-ADHOC-2026-07-07.md", - "uuid": null, + "uuid": "bf985c95-bea6-5057-94f9-9cfa7e1c9dd8", "parent_id": "WARDEN-WP-ADHOC-2026-07-07", "extra": {} }, @@ -2204,7 +2327,7 @@ "status": "open", "title": "Review requested: security layer model v0.3 \u2014 and does maturity-engine absorb warden route gaps?", "source_path": "intakes/intakes.md", - "uuid": null, + "uuid": "01a04d97-94cd-7b49-8019-a91c7fce8adb", "parent_id": null, "extra": { "record": { @@ -2219,25 +2342,19 @@ "requested_by": "gate-house", "description": "v0.3 is proposed and changes sections 4, 9 and 13 only; the v0.2 assent record stands. Two new engines: approval-engine (section 9.4) and maturity-engine (section 9.5). THE QUESTION FOR YOU concerns section 5.3, which exists because you offered the amendment. v0.3 gives declared gaps an owner: maturity-engine takes the gap register with intended_owner, blocked_on and review dates, and section 13 now says the register in the standard is interim and should not outlive that engine. You offered warden route gaps and the 27 delegation catalog entries as reusable prior art. So the question is whether that machinery should MOVE, be MIRRORED, or STAY. Our tentative reading, which we want tested rather than accepted: routing is yours and stays yours \u2014 warden route find answers where a credential need goes, and that is lane knowledge, not maturity. What might move is the readiness half: whether a declared gap is still within its review date, and whether an intended owner has an engine surface yet. If splitting those creates two sources for one fact, that is worse than either option and we would rather hear it now. Your SSH-CA signing write would be tracked in maturity-engine as a declared gap with intended owner secrets-engine and a review date \u2014 that is reporting your own non-conformance to an engine, so we would rather you assent to it than discover it. Also note approval-engine (section 9.4): it owns the approval object, not the approval workflow, so ops-warden lanes needing approval consume a claim rather than implementing one. Assent, revision, or rejection acceptable.", "created": "2026-08-28T20:40:24.957468Z", - "updated": "2026-08-28T20:40:24.957468Z" + "updated": "2026-08-28T20:40:24.957468Z", + "state_hub_intake_id": "01a04d97-94cd-7b49-8019-a91c7fce8adb" } } } ], "events": [ { - "type": "repo.command.applied", - "command": "repo.work.create_intake", - "operation": "create", - "correlation_id": "676e92a9-dc2e-4101-a31c-a584962c25df", - "kind": "intake", - "id": "WARDEN-IN-0002", - "git_sha": "f289465b90fcdffe2c8bf4a51cc71607747126f9", - "files_touched": [ - "intakes/intakes.md" - ], + "type": "repo.reconciled", + "workplan_count": 41, + "task_count": 183, "source": "repo-manager", - "emitted_at": "2026-08-28T20:40:26.143617Z" + "emitted_at": "2026-08-31T22:59:28.638627Z" } ] } diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index d1e0eb4..80d81c3 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -31,6 +31,8 @@ | workplan | WARDEN-WP-0032 | finished | — | workplans/WARDEN-WP-0032-security-zones.md | | workplan | WARDEN-WP-0033 | finished | — | workplans/WARDEN-WP-0033-native-lane-handoff.md | | workplan | WARDEN-WP-0034 | ready | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | +| workplan | WARDEN-WP-0035 | finished | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md | +| workplan | WARDEN-WP-0036 | finished | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md | | task | WARDEN-WP-ADHOC-2026-06-27-T01 | done | — | workplans/ADHOC-2026-06-27.md | | task | WARDEN-WP-ADHOC-2026-06-29-T01 | done | — | workplans/ADHOC-2026-06-29.md | | task | WARDEN-WP-ADHOC-2026-08-11-T01 | done | — | workplans/ADHOC-2026-08-11.md | @@ -135,5 +137,9 @@ | task | WARDEN-WP-0034-T03 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | | task | WARDEN-WP-0034-T04 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | | task | WARDEN-WP-0034-T05 | todo | — | workplans/WARDEN-WP-0034-layer-model-v07-conformance.md | +| task | WARDEN-WP-0035-T01 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md | +| task | WARDEN-WP-0035-T02 | done | — | workplans/WARDEN-WP-0035-policy-nexus-forgejo-source-read-route.md | +| task | WARDEN-WP-0036-T01 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md | +| task | WARDEN-WP-0036-T02 | done | — | workplans/WARDEN-WP-0036-attended-login-openbao-output.md | | intake | WARDEN-IN-0001 | closed | — | intakes/intakes.md | | intake | WARDEN-IN-0002 | open | — | intakes/intakes.md |