From 33573a35a1537316798b1b5d8522e7a1698e3642 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 27 Jul 2026 01:25:14 +0200 Subject: [PATCH] Real build executed for real (MASON-WP-0001-T05, MASON-WP-0001 done 5/5) Ran the whole approved pipeline against real OpenBao: created the reins/ KV v2 mount (after pausing for explicit founder confirmation -- a bigger action than the executive summary's blast-radius framing disclosed), the read-only policy, the AppRole, delivered role_id/secret_id. Caught and fixed a real bug in the same pass: built with token_num_uses=0 (OpenBao's default = unlimited) instead of the plan's own stated 8; fixed live and removed the executor's silently-permissive default so it can't recur. Catalog entry proposed and merged in ops-warden (c0a50bc). Corrected a real misreading in this repo's own INTENT.md along the way: pointer fields (auth_method/fetch_command/rotation.steps) are normal on non-SSH catalog entries; only a bare top-level steps:+cert_command: pair is SSH-only -- verified against ops-warden's real entries and its full test suite (326 tests, green). Plan status: built. Catalog entry status: draft until the founder's paste-once-provision and glas-harness/GLAS-WP-0002-T02's live verification succeed. Co-Authored-By: Claude Sonnet 5 --- INTENT.md | 31 ++++++++------ plans/rein-openweights-openrouter-approle.md | 45 +++++++++++++++++++- src/ops_mason/executor.py | 7 ++- tests/test_executor.py | 8 ++++ workplans/MASON-WP-0001-foundation.md | 45 +++++++++++++++----- 5 files changed, 110 insertions(+), 26 deletions(-) diff --git a/INTENT.md b/INTENT.md index 3e416a2..52ba97c 100644 --- a/INTENT.md +++ b/INTENT.md @@ -106,18 +106,25 @@ build once approved. (`ops-warden/registry/routing/catalog.yaml`) for what it builds - Its own audit trail of what it built, when, and under which approved plan -**Catalog entries are pointer-only, same rule ops-warden enforces on every -non-SSH entry (the catalog's own "no-double-source rule", -`ops-warden/workplans/WARDEN-WP-0010-access-routing-charter.md`):** -`id`/`title`/`need_keywords`/`owner_repo`/`subsystem`/`wiki_ref`/`canon_ref`/ -`reviewed`/`status`, always `warden_executes: false` (ops-mason built the -lane, it does not execute the runtime credential fetch — the consumer's own -code does, the way `rein-openweights/credentials.py` does today). **Never** -an authored `steps`/`cert_command` block — those are reserved for -`warden_executes: true` entries, i.e. ops-warden's own SSH lane. The actual -"how a consumer uses this credential" doc lives with the consumer (e.g. -`rein-openweights/INTENT.md`/`credentials.py`), referenced via `wiki_ref`, -not restated inside the catalog. +**Catalog entries are pointer-shaped, same rule ops-warden enforces on +every non-SSH entry (the catalog's own "no-double-source rule", +`ops-warden/workplans/WARDEN-WP-0010-access-routing-charter.md`) — +corrected here 2026-07-27 after checking real catalog entries, not just +the header comment:** `id`/`title`/`need_keywords`/`owner_repo`/ +`subsystem`/`wiki_ref`/`canon_ref`/`reviewed`/`status`, always +`warden_executes: false` (ops-mason built the lane, it does not execute +the runtime credential fetch — the consumer's own code does, the way +`rein-openweights/credentials.py` does today). Fields like +`auth_method`/`path_template`/`fetch_command`/`rotation.steps` **are** +expected on non-SSH entries — e.g. `agent-harness-binky-mail-approle` +carries all of them despite `warden_executes: false`. What's actually +reserved for `warden_executes: true` (ops-warden's own SSH lane) is a +bare **top-level** `steps:` + `cert_command:` pair — that specific +shape, not procedural detail in general. A companion wiki playbook +(`wiki/playbooks/.md`, `## Worker checklist` section) is the norm, +same as every other lane in the catalog — not a violation of +no-double-source as long as it doesn't restate a *different owner's* +procedure. Landing a catalog entry is a normal git contribution to the `ops-warden` repo (a commit/PR touching `registry/routing/catalog.yaml`), subject to diff --git a/plans/rein-openweights-openrouter-approle.md b/plans/rein-openweights-openrouter-approle.md index 7889c84..56cc442 100644 --- a/plans/rein-openweights-openrouter-approle.md +++ b/plans/rein-openweights-openrouter-approle.md @@ -3,7 +3,7 @@ id: rein-openweights-openrouter-approle demand_source: glas-harness/workplans/GLAS-WP-0002-T02 consumer_repo: rein-openweights credential_type: openbao-approle-kv -status: approved +status: built approved_by: "Bernd Worsch" approved_at: "2026-07-27" created: "2026-07-27" @@ -157,4 +157,45 @@ returns `403`; unchanged since `GLAS-WP-0002-T02` first flagged it). ## 6. Build result (phase 4) - +**Built 2026-07-27**, executed via `ops_mason.executor.build_approle_kv_lane` +against real OpenBao (`bao login -method=oidc -path=netkingdom +role=platform-admin`, `platform-admin` policy, ~1h token). Object names only +below — no secret material. + +- **Mount created:** `reins/` (KV v2) — did not exist; `bao secrets list` + showed only `platform/`, `secret/`, `tenants/` at execution time. Per §2's + own caveat ("survey current as of what's on disk, not live OpenBao + ACL state"), this was a real, live discrepancy from what the approved + plan assumed. **Confirmed with the founder before mounting** (a new + top-level secrets engine is a bigger action than "one KV path" implied + in the executive summary's blast-radius framing) — approved to proceed + exactly as originally planned rather than substitute an existing mount. +- **Policy created:** `workload-kv-read-rein-openweights-openrouter` — + read-only, scoped to exactly `reins/rein-openweights/openrouter`. +- **AppRole created:** `rein-openweights` — `token_ttl=15m`, + `token_max_ttl=30m`, `secret_id_ttl=0`. +- **Correction made post-build:** `token_num_uses` was built as `0` + (OpenBao's own default) instead of the plan's own stated `8` + (mirroring `agent-harness-binky-mail`) — `0` means *unlimited* in + OpenBao, the opposite of "bounded." Caught by checking the live + AppRole config against the reference lane immediately after building, + fixed with `bao write auth/approle/role/rein-openweights + token_num_uses=8` (verified). **Root cause fixed in code, not just + patched live:** `AppRoleKVSpec.token_num_uses` no longer has a default + in `ops_mason/executor.py` — it must be passed explicitly every time, + so this specific mistake can't recur silently on a future plan. +- **role_id/secret_id delivered** to `~/.local/rein-openweights/approle/` + (mode `0600`), matching `credentials.py`'s existing + `REIN_OPENWEIGHTS_APPROLE_DIR` default. +- **Catalog entry proposed and merged:** `ops-warden` commit `c0a50bc`, + `rein-openweights-openrouter-approle`, `status: draft` (promotes to + `active` once the founder completes paste-once-provision and + `GLAS-WP-0002-T02`'s live verification succeeds). Playbook: + `ops-warden/wiki/playbooks/rein-openweights-openrouter-approle.md`. + `ops-warden`'s full test suite (326 tests) verified green after the + addition. + +**Remaining, not part of this build:** the founder still needs to paste +the real OpenRouter API key into `reins/rein-openweights/openrouter` +(field `api_key`) through ops-warden's `paste_once_provision` desk — +ops-mason built structure only, per `INTENT.md`. diff --git a/src/ops_mason/executor.py b/src/ops_mason/executor.py index f1c59be..7ac9da6 100644 --- a/src/ops_mason/executor.py +++ b/src/ops_mason/executor.py @@ -40,10 +40,15 @@ class AppRoleKVSpec: policy_name: str kv_path: str approle_name: str + # token_num_uses has no default on purpose: OpenBao's own default (0) + # means *unlimited* uses, the opposite of "bounded" -- a plan that says + # "bounded token_num_uses" (the agent-harness-binky-mail shape, which + # actually uses 8) must have that number chosen explicitly, not + # inherited silently from whatever OpenBao considers a sane default. + token_num_uses: int kv_capabilities: tuple[str, ...] = ("read",) token_ttl: str = "15m" token_max_ttl: str = "30m" - token_num_uses: int = 0 secret_id_ttl: str = "0" delivery_dir: Path | None = None bao_bin: str = "bao" diff --git a/tests/test_executor.py b/tests/test_executor.py index f2e2d2e..a6fe5d5 100644 --- a/tests/test_executor.py +++ b/tests/test_executor.py @@ -26,11 +26,19 @@ def _spec(tmp_path) -> AppRoleKVSpec: policy_name="workload-kv-read-test-lane", kv_path="reins/test/openrouter", approle_name="test-lane", + token_num_uses=8, delivery_dir=tmp_path / "delivery", audit_log_path=tmp_path / "audit.jsonl", ) +def test_token_num_uses_has_no_silently_unbounded_default() -> None: + import inspect + + sig = inspect.signature(AppRoleKVSpec) + assert sig.parameters["token_num_uses"].default is inspect.Parameter.empty + + def test_refuses_when_not_approved(tmp_path) -> None: plan = _plan(tmp_path, status="draft", approved_by=None, approved_at=None) with pytest.raises(BuildRefused, match="not approved"): diff --git a/workplans/MASON-WP-0001-foundation.md b/workplans/MASON-WP-0001-foundation.md index ff7e202..7f92dac 100644 --- a/workplans/MASON-WP-0001-foundation.md +++ b/workplans/MASON-WP-0001-foundation.md @@ -150,20 +150,43 @@ value exists outside OpenBao. Once done, notify `glas-harness`/ `rein-openweights` so `GLAS-WP-0002-T02`'s live OpenBao verification can proceed. -**Phases 1-3 done, approved (2026-07-27):** -`plans/rein-openweights-openrouter-approle.md` is now `status: approved` -(Bernd Worsch, 2026-07-27) — `ConstructionPlan.load(...).is_approved()` -confirmed `True` against the real file. **Blocked on phase 4 execution -only:** no valid OpenBao session from this workstation (`bao token -lookup` still `403`) to actually run -`build_approle_kv_lane`/`bao policy write`/`bao write auth/approle/...`. -Whoever has (or provisions) real `bao` access can run phase 4 directly -against this approved plan — the gate is cleared, only the environment -is missing. +**Done (2026-07-27), all four phases run for real.** Founder logged in +(`bao login -method=oidc -path=netkingdom role=platform-admin` — the +initial bare `-method=oidc` 403'd against the wrong default mount path; +`netkingdom` + an explicit `role=` was required, found via +`ops-warden`'s own catalog/wiki conventions). Executed +`build_approle_kv_lane` for real: + +- **Live-state discrepancy found and handled correctly, not silently:** + no `reins/` KV mount existed (`bao secrets list` showed only + `platform/`/`secret/`/`tenants/`) — a bigger action (new secrets + engine) than the executive summary's blast-radius framing disclosed. + Paused and got explicit founder confirmation before mounting, rather + than substituting a different path or proceeding unilaterally. +- **Built:** `reins/` KV v2 mount, policy + `workload-kv-read-rein-openweights-openrouter`, AppRole + `rein-openweights`, role_id/secret_id delivered to + `~/.local/rein-openweights/approle/` (`0600`). +- **Real bug caught and fixed, root cause and all:** built with + `token_num_uses=0` (OpenBao's own default = *unlimited*) instead of the + plan's own stated `8` — caught by comparing the live AppRole config + against `agent-harness-binky-mail`'s immediately after building, fixed + live (`bao write ... token_num_uses=8`) and in code + (`AppRoleKVSpec.token_num_uses` now has no default — must be passed + explicitly, so this can't recur silently). +- **Catalog entry landed:** `ops-warden` commit `c0a50bc` — and while + writing it, corrected a real misreading in this repo's own `INTENT.md` + of the no-double-source rule (pointer *fields* like `auth_method`/ + `fetch_command`/`rotation.steps` are normal on non-SSH entries; only a + bare top-level `steps:`+`cert_command:` pair is SSH-only) — verified + against `ops-warden`'s full 326-test suite, green. +- Plan file `status: built`; catalog entry `status: draft` until the + founder's paste-once-provision + `GLAS-WP-0002-T02`'s live + verification succeed. ```task id: MASON-WP-0001-T05 -status: wait +status: done priority: high state_hub_task_id: "01782608-aa5a-4f9b-a1fb-9a64f6d9c299" ```