ops-mason/INTENT.md
tegwick 718df758dc 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 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 2564823@bnt-lap001
Assistant-Session: 2a7ed827-4928-4b9f-8613-9135c9cadfe9
2026-08-28 21:21:08 +02:00

254 lines
14 KiB
Markdown

# 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.
>
> 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; builds and tears down.** Add the layer label and the Staff invariant: ops-mason acts through engine APIs, never against tooling directly. Record the demarcation this repository is half of: **ops-mason and ops-warden own access routes and lanes — how a worker reaches a host; access-engine owns access rules — whether they may.** The perimeter doctrine ops-mason builds to is gate-house's; the building is ops-mason's.
>
> *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 current
> implementation.
---
## One-liner
**The builder of NetKingdom security infrastructure — creates, changes,
maintains, and tears down access routes, credentials, tokens, and policies
so that ops-warden always has something real to route to.**
---
## Why this exists
ops-warden is deliberately narrow: it issues short-lived SSH certificates and
**routes** every other credential need to the subsystem that owns it — it
"owns no secret store and vends nothing" (`ops-warden/wiki/AccessRouting.md`).
That's the right shape for a front door, but it leaves a real gap: **something
has to actually build the AppRole, the policy, the KV secret path, the
catalog entry** that ops-warden then points workers at. Today that gap is
filled ad hoc — a founder spends "~10 minutes" hand-running `bao write`
commands per new lane (see `binky-control/integrations/executor-worker-secrets.md`
for a representative example: a new AppRole, a new policy, delivered
role_id/secret_id files, a catalog entry, repeated by hand every time a new
consumer needs a credential).
ops-mason exists to turn that ad hoc founder mechanic into a **reviewed,
repeatable construction process** — so new security infrastructure gets
built consistently, against what already exists, with a human decision point
before anything is actually applied, instead of bespoke one-off provisioning
every time.
---
## The Mission
ops-mason **builds** NetKingdom security infrastructure — OpenBao AppRoles,
policies, KV secret paths, and their ops-warden catalog entries — as defined
by architecture documents (`net-kingdom`) and by real consumer demand (a
repo/workload that needs a credential lane). It does not decide *whether*
access should exist — that's an architecture or founder decision — it
figures out *how* to build what's already been decided on, and does the
build once approved.
### The four-phase process
1. **Construction plan.** Given an access demand (a consumer, a credential
type, a scope) and the concept behind it, draft what needs to be created,
changed, or torn down to satisfy it — respecting, extending, or compacting
existing structure rather than defaulting to "create something new" every
time. Check first: does an existing policy/path/lane already cover this
(the way `rein-aharness`'s mail-triage reuses the existing
`llm-connect-provider-secrets` lane instead of getting its own)? Does
satisfying this demand let two existing near-duplicate lanes be merged
instead of adding a third?
2. **Review and optimize.** Check the draft plan against what's already
provisioned (no redundant policies, no orphaned roles), consistency with
existing naming/TTL/scoping conventions, and ease of use for the
consumer. This is a self-review pass before a human ever sees the plan —
the plan that reaches phase 3 should already be the best version of
itself, not a first draft.
3. **Executive summary — the decision gate.** Render what the plan actually
grants: which roles get which access, to what, for how long, blast radius
if the credential leaks, and what it costs to reverse. This is the one
mandatory human checkpoint, and it exists for exactly the reason
ops-warden's own design principle names: *"the founder is escalated to,
never tasked with mechanics"* — ops-mason does the mechanical work in
phases 1, 2, and 4; phase 3 is the founder's one decision, made in policy
terms (approve, reject, or send back to phase 1 with feedback), not asked
to review raw `bao` commands.
4. **Build.** Once approved, execute the plan — create/modify/tear down the
AppRole, policy, and secret path *structure*, then propose the matching
ops-warden catalog entry. Not before phase 3 approval, ever, for anything
that grants or widens access. (Tear-down of something already flagged for
removal, or a dry-run/plan-only mode, does not require the same gate —
see Design Principles.)
**ops-mason never touches secret values, including its own builds.** It
creates the empty KV path, the policy, and the AppRole — structure only.
The actual secret value (an API key, a password) goes in through
ops-warden's existing **paste-once provision** desk
(`ops-warden/src/warden/desk.py`'s `paste_once_provision` act): a
localhost-only web form where the founder pastes the value once, written
directly via `bao kv put` and never shown in a terminal, chat, or audit
log. Phase 4 ends with "structure built, ready for paste-once
provisioning" — it does not end with a live credential.
---
## Responsibility boundary
### ops-mason owns
- Drafting and executing construction plans for new/changed/retired OpenBao
AppRoles, policies, and KV secret paths (structure — never secret values,
see phase 4 above)
- Consistency review against existing NetKingdom credential structure —
reuse over duplication, compaction over sprawl
- The executive-summary format that makes a plan decidable at a glance
- Proposing the matching entry in ops-warden's routing catalog
(`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-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/<id>.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
its own CI (`tests/test_routing.py` — anchor resolution) and its stale-review
cadence (new entries typically start `status: draft` until the built lane
is verified end-to-end, then promoted to `active` — same as any other
owner-ship promotion in that catalog). ops-mason does not have, and does
not need, some separate live registration API into ops-warden.
### ops-mason does not own
| Need | Owner | ops-mason's relationship |
|---|---|---|
| Whether access *should* exist at all | Architecture docs / founder | ops-mason builds what's decided, does not decide policy from nothing |
| Runtime authorization ("may actor X do Y") | flex-auth | ops-mason provisions the policy; flex-auth evaluates it at runtime |
| Identity, MFA, human auth | key-cape / Keycloak | Out of scope entirely |
| Routing consumers to the right lane | ops-warden | ops-mason feeds ops-warden's catalog; does not replace `warden access`/`warden route` |
| SSH certificate issuance | ops-warden | Untouched — ops-mason works in OpenBao AppRole/policy/KV space, not the SSH CA lane |
| OpenBao cluster init/unseal, platform deploy | railiance-platform | Out of scope — ops-mason operates within an already-running OpenBao |
| Holding or logging secret values | Nobody, ever | Same invariant as ops-warden: values live in OpenBao and process env only |
| Delivering the actual secret value into a path ops-mason built | ops-warden (`paste_once_provision` desk) | ops-mason builds the empty structure; the founder pastes the value once through ops-warden's existing local web form, never through ops-mason |
**ops-mason is not a second secrets manager and not a policy-decision engine.**
It is the construction crew for a foundation ops-warden and every credential
consumer stands on.
---
## Design principles
1. **Reuse before creation.** Every construction plan's first move is
checking whether existing structure already covers the demand. New
infrastructure is the fallback, not the default.
2. **Compaction is in scope, not just addition.** ops-mason may propose
merging or retiring redundant lanes as part of a construction plan, not
only adding new ones.
3. **One mandatory human gate, not a gate on everything.** Anything that
grants or widens access stops at the phase-3 executive summary. Read-only
plan drafts, dry runs, and tear-down of something already approved for
removal do not need to re-litigate the same decision.
4. **Mechanics stay with the agent; decisions stay with the founder.**
Directly extends ops-warden's own principle 7. The executive summary is
written so the founder never has to read a `bao` command to make the
call.
5. **Nothing built stays invisible.** Every successful build is followed by
a proposed catalog entry to `ops-warden` in the same phase-4 action
(pointer-only, `status: draft` until verified end-to-end) — there should
be no infrastructure ops-mason built that isn't at least a draft entry
away from `warden route find` surfacing it.
6. **Posture-aware, like ops-warden.** The organization is in build phase
(one founder-operator, pre-revenue) — construction plans should reflect
current posture (see `ops-warden/wiki/WorkloadSecurityPosture.md`) and
tighten as posture graduates, not assume production-tier rigor on day one
or dev-tier looseness forever.
---
## Relationship to the rest of NetKingdom
```text
net-kingdom — owns the canonical security architecture
|
v
ops-mason — builds the infrastructure that architecture calls for
| (AppRoles, policies, KV paths, catalog entries)
v
ops-warden — routes consumers to what ops-mason built
|
v
OpenBao / flex-auth / key-cape — hold custody, evaluate policy, verify identity
```
NetKingdom defines what the security model should look like. ops-mason
builds the concrete lanes that satisfy it. ops-warden is the front door that
points consumers at those lanes once built. Confusing ops-mason's builder
role with ops-warden's router role — or with OpenBao's custody role —
recreates exactly the "wrong subsystem for the credential need" confusion
ops-warden itself exists to prevent.
---
## Non-goals
- Being a second OpenBao, a second ops-warden, or a policy-decision engine
- Deciding, unprompted, that new access should exist — that's an
architecture/founder call, ops-mason builds what's already decided
- Applying anything that grants or widens access without a phase-3 approved
plan
- Touching secret values at all, even transiently — structure only; values
go in via ops-warden's `paste_once_provision` desk, not through ops-mason
- Owning OpenBao cluster lifecycle, flex-auth runtime, or key-cape identity
---
## Success criteria
ops-mason is succeeding when:
1. A new credential lane can go from "a consumer needs this" to "built,
catalogued, and routable via ops-warden" without a founder hand-running
`bao` commands.
2. Every construction plan is checked against existing structure before it's
proposed — duplicate/near-duplicate lanes are the exception, not routine.
3. The founder's only touchpoints are the phase-3 decision (plain terms:
who gets what, for how long, what it costs to undo) and, if the lane
needs a live value, one paste through ops-warden's existing desk —
never asked to review or run raw provisioning mechanics.
4. Every ops-mason build ships with a proposed ops-warden catalog entry —
no undocumented lanes, even in `draft` status.
5. Tearing down access is as routine and reviewed a process as creating it —
sprawl doesn't accumulate because removal is just as supported as
construction.