docs: align scope with implemented capabilities
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0217e-8c4c-7383-be6b-f50a6e485306
This commit is contained in:
tegwick 2026-08-23 10:48:16 +02:00
parent 3ca0e63bed
commit 7799716c73
4 changed files with 454 additions and 159 deletions

355
SCOPE.md
View file

@ -1,207 +1,244 @@
# SCOPE
> Lightweight boundary for agents and contributors.
> Implemented capability boundary for agents and contributors. Aspirational
> direction belongs in `INTENT.md`; current work and operational gates belong in
> `workplans/`.
## One-liner
secrets-engine is the workflow and automation interface for approved secret
custody, auth-capability handoff, delivery, and lifecycle work across build,
test, and production, with OpenBao as the enforcement backend.
secrets-engine is a decision-gated Python CLI that validates non-secret secret
lane metadata and orchestrates narrowly scoped OpenBao policy, AppRole,
provisioning, verification, delivery, routing, handoff, and revocation actions.
## Core Idea
It is an OpenBao workflow client, not a vault, authorization service, identity
provider, credential broker, or general secrets API.
OpenBao is the vault. secrets-engine is the day-to-day interaction layer that
connects cataloged secret lanes, scoped auth-capability lanes, approval
decisions, stage-specific OpenBao roles, safe delivery modes, and non-secret
evidence.
## Implemented Capabilities
## In Scope
### Catalog and validation
- Non-secret catalog of secret lanes, grants, consumers, stages, and delivery
modes.
- Non-secret catalog of scoped OpenBao auth capabilities where the protected
material is a narrow policy/AppRole grant rather than a KV value.
- Decision-aware planning and apply flows for OpenBao policies, auth roles, and
metadata.
- Build, test, and production privilege separation.
- Safe provisioning, verification, rotation, revocation, and deactivation
workflows.
- Exec-time delivery to operators, agents, CI jobs, workloads, and ops-bridge
tasks without printing raw values.
- Future service/API mode that exposes the same approved planning, delivery,
handoff, lifecycle, and evidence semantics to ops-warden, agents, CI,
workloads, and UI surfaces without exposing OpenBao internals.
- ops-warden routing contract for non-SSH credentials and scoped OpenBao
capabilities.
- State Hub non-secret evidence and progress integration.
- Canonicalization of terms with info-tech-canon.
- Loads YAML catalog entries for `kv` and `auth-capability` lanes.
- Models `build`, `test`, and `prod` stages, exact mounts/paths/fields,
consumers, approvals, delivery modes, verification, lifecycle ownership,
workload-delivery metadata, and `standard`/`high` risk.
- Distinguishes engine-managed and existing KV mounts, and engine-managed,
existing, or absent native delivery auth.
- Rejects malformed entries, inline secret-looking values, wildcard paths,
unsupported modes, bootstrap-only approval for high-risk lanes, and high-risk
entries without rotation/deactivation owners.
- Records existing ESO/Kubernetes/OIDC workload delivery as metadata only; it
does not operate those delivery systems.
## Out of Scope
### Decision-gated planning and OpenBao metadata apply
- Replacing OpenBao as custody, policy, lease, or audit backend.
- Replacing flex-auth authorization decisions.
- Replacing user-engine/key-cape identity and claim lifecycle.
- Issuing SSH certificates, which remains ops-warden responsibility.
- Owning tunnels or remote transport, which remains ops-bridge responsibility.
- Storing raw secret values in this repo, State Hub, chat, prompts, or logs.
- Broad platform-root or platform-admin automation as a steady-state model.
- Handing broad OpenBao tokens to another subsystem when a narrower
cataloged capability can satisfy the request.
- Resolves a catalog lane by catalog id or `approval.decision_ref`.
- Resolves an approval from State Hub by id, with tracked local YAML mirrors as
a pilot/offline fallback.
- Fails privileged live commands closed when a required decision is missing,
unapproved, or superseded. Plans and `apply --dry-run` remain non-mutating.
- Renders guarded OpenBao plans for exact consumer ACL policies and AppRoles.
- Applies policy and AppRole metadata idempotently. Existing mounts render a
non-mutating check and are never created by apply.
- Rejects stage mismatches, wildcard paths, broad-admin names, forbidden
`sys/`, token, identity, root, or sudo semantics, and auth-capability paths
outside an exact allowlist.
## Relevant When
### KV provisioning
- An approved decision needs to become a narrow OpenBao policy/auth-role apply
without platform-root hand-typing.
- A workload or operator command needs a secret delivered **into the command**
without printing or exporting it (e.g. `npm publish`).
- A non-SSH credential need (API key, provider token, npm token, DB password,
scoped OpenBao token) is routed here by ops-warden.
- ops-warden needs an approved, narrow OpenBao capability such as
`ssh/sign/<role>` access for its own SSH certificate flow, without receiving a
broad platform-root token.
- Build/test/production need different privilege, ceremony, and delivery rules
for the same kind of secret.
- A reviewer needs non-secret evidence of who applied/provisioned/verified what.
- Imports one declared field from a mode-0600 file outside Git worktrees.
- Generates random values only for non-production lanes.
- Keeps values out of CLI output and evidence records.
## Not Relevant When
This is a bootstrap/pilot primitive, not a safe general updater for existing
multi-field production paths. The current adapter invokes `bao kv put` with one
field and can replace sibling fields at that KV path; it also places the value
in the local `bao` subprocess argument vector. Do not use it for the admitted
shared multi-field lanes until merge-safe, non-argv provisioning is implemented.
- You need an **SSH certificate** (→ ops-warden `warden sign`).
- You need an **authorization decision** (→ flex-auth).
- You need **identity / OIDC / MFA / claim lifecycle** (→ user-engine / key-cape).
- You need a **tunnel** or remote transport (→ ops-bridge).
- You want OpenBao itself replaced as the custody/lease/audit backend (it is not).
- You want a raw secret value moved through Git, State Hub, chat, prompts, or logs
(never — delivery is exec-time or out-of-band only).
### Verification
## Current State
- KV positive verification logs in through the lane AppRole and reports whether
one declared field is present, without printing the field value.
- KV negative verification checks that a fixed invalid token cannot read the
path.
- Auth-capability verification checks the AppRole token's capabilities on exact
allowlisted and denial-probe paths.
MVP delivered. The Python CLI (`src/secrets_engine/`) supports the core lane
flow: catalog → decision check → guarded OpenBao policy/AppRole apply →
provision or handoff → positive/negative verification → safe delivery →
non-secret route pointers → revoke.
These are bounded policy/presence probes. They do not yet prove denial for a
real unrelated workload identity, validate every field by default, exercise a
provider operation, or produce OpenBao audit-request correlation.
The repo supports both stored-value KV lanes and non-KV auth-capability lanes.
KV lanes cover secrets such as npm publish tokens; auth-capability lanes cover
narrow OpenBao policy/AppRole grants such as `ssh/sign/<role>` access for
ops-warden. The maturity-gated publication-scope policy is in place and
fail-safe: until the broader domain reaches the required maturity, publish lanes
clamp to the safest repo-scoped token shape.
### Exec-time delivery
Current operational status lives in workplans, `.custodian-brief.md`, and
`history/`; this file should stay stable enough for agents and contributors to
use as the boundary reference.
- `exec-env` fetches one declared field through the lane AppRole and injects it
into a child process environment.
- `npm-config` creates a temporary mode-0600 npm config containing an environment
reference rather than the token, injects the value only into the child, and
deletes the config afterward.
- Child stdout and stderr are combined and streamed through token-pattern and
exact-value redaction.
- Undeclared fields and undeclared/unsupported exec modes are rejected before
value fetch.
## Hardening Trajectory
The OpenBao KV response is parsed in the parent process, so every field stored
at the path crosses that process boundary even though only the selected field is
injected. Scoped AppRole tokens rely on configured TTL/use limits; exec and
verification do not explicitly revoke them after use.
The steady-state target is to keep routine secure work low-friction while
removing bootstrap shortcuts. The hardening path is tracked in
`docs/hardening-backlog.md` and includes:
### Auth-capability handoff
- replacing bootstrap token files with OIDC, service auth, or another scoped
OpenBao auth path for steady-state stage roles;
- using response wrapping, short leases, and single-use handoff paths when
exec-time delivery does not fit;
- requiring dual control for production value provisioning beyond approved
pilots;
- making rotation, revocation, and deactivation routine evidenced operations;
- exposing stabilized CLI semantics through service/API mode only after the
underlying decision, delivery, lifecycle, and evidence contracts are proven.
- Models narrow non-KV AppRole grants such as exact `ssh/sign/<role>` update
capability.
- Mints `role_id`/`secret_id` material only after approval and writes it to
distinct mode-0600 files outside Git worktrees without printing the
`secret_id`.
## How It Fits
The cataloged standalone `warden-sign` AppRole is currently parked by governance
and must not be applied as a break-glass or recovery path. OpenBao being sealed
cannot be recovered through that AppRole.
secrets-engine is the **interaction layer** in the NetKingdom security stack. It
sits between approval/identity systems and the OpenBao backend:
### Routing and evidence
- **OpenBao / railiance-platform** — enforces custody, policy, lease, audit.
secrets-engine drives it through least-privilege stage roles and validated
paths, never as root.
- **flex-auth / State Hub decisions** — authorize. secrets-engine requires and
verifies a decision before privileged action and writes non-secret evidence
back.
- **user-engine / key-cape** — own identity and claims that bind consumers.
- **ops-warden** — routes non-SSH credential needs here (conduit-not-broker) and
issues SSH certs itself; secrets-engine orchestrates OpenBao-backed issuance,
delivery, handoff, verification, and revocation while OpenBao remains the
custody backend.
- **ops-bridge** — may consume scoped delivery for remote execution but stores no
secret material.
- **info-tech-canon** — source of canonical terminology and stage/policy concepts.
- `route` returns a non-secret pointer containing lane ownership, decision
status, metadata/value-presence booleans, readiness, and a safe next command.
- Records scrubbed local JSONL evidence and posts a minimal State Hub progress
event on a best-effort basis.
- Keeps OpenBao audit logs as the backend source of truth.
Canonical cross-system boundary: `net-kingdom/docs/secrets-engine-security-infrastructure-boundary.md`.
Route readiness checks only the first declared KV field, and State Hub evidence
delivery is not durable or transactional. Treat route output as operational
guidance, not complete attestation for multi-field or high-risk lanes.
## Terminology
### Revocation currently available
| Term | Meaning |
| --- | --- |
| **lane / catalog id** | a non-secret entry describing a KV secret or auth capability, its OpenBao location, consumers, delivery, and approval |
| **auth-capability lane** | a catalog lane whose protected material is a narrow OpenBao policy/AppRole capability, not a stored KV value |
| **stage** | `build` / `test` / `prod` — separate OpenBao privilege contexts |
| **stage role** | `secrets-engine-{build,test,prod}` OpenBao role, confined to its prefix |
| **delivery mode** | how material leaves OpenBao: `exec-env`, `npm-config`, `read-check`, `wrapped`, `approle-login` |
| **org / repo** | Gitea organisation (`coulomb`) / repository (`whynot-design`) — explicit, not the overloaded "project" |
| **npm scope** | the `@`-prefixed npm name (`@whynot`) — distinct from org and repo |
| **maturity** | `maturity-build/test/prod` package tag; feeds the publication-scope policy |
| **bootstrap token** | temporary mode-0600 OpenBao token used during setup, revocable, outside repos |
| **service/API mode** | future stable API surface over proven CLI semantics for approved plans, deliveries, handoffs, lifecycle actions, and evidence |
- For `auth-capability` lanes, live `revoke` deletes the AppRole and policy.
- For KV lanes, live `revoke` deletes all KV metadata/versions at the path.
## Related / Overlapping
KV revoke is destructive decommissioning, not soft deactivation: it currently
leaves the KV lane's consumer AppRole and policy in place. There is no general
lease/accessor revoke, rotation command, compromised state, or reversible lane
state machine.
- **ops-warden** — front door / SSH cert issuer; routes non-SSH needs here.
- **OpenBao (railiance-platform)** — the custody/policy/lease/audit backend.
- **flex-auth** — authorization decisions secrets-engine depends on.
- **user-engine / key-cape** — identity and claim lifecycle for consumers.
- **ops-bridge** — remote transport; may consume scoped delivery.
- **net-kingdom** — owns the cross-system security-infrastructure boundary doc.
- **info-tech-canon** — canonical terminology source.
## CLI Surface
```text
secrets-engine catalog list|show
secrets-engine decision inspect
secrets-engine plan
secrets-engine apply [--dry-run]
secrets-engine provision
secrets-engine verify
secrets-engine handoff
secrets-engine exec
secrets-engine policy publication
secrets-engine route
secrets-engine revoke [--dry-run]
```
The implemented exec adapters are `exec-env` and `npm-config`. `read-check` is
verification, `approle-login` is auth-capability handoff metadata, and
`exec-file`/`wrapped` are reserved schema names without executable adapters.
## Proven Operationally
- The whynot-design npm pilot completed a real publish through native
`secrets-engine exec` without placing the token in the parent shell.
- Throwaway OpenBao integration tests exercise plan, apply, provisioning,
positive/negative verification, exec delivery, routing, revocation, and
idempotent metadata apply.
- Five existing high-risk `platform` mount lanes have reviewed catalog metadata
and guarded dry-run plans. Their native AppRoles are not live: workplan
`SECRETS-WP-0006` waits on per-lane approval, production authority, live
positive/negative verification, and routing cutover.
## Not Implemented
- A service API, daemon, UI, queue, scheduler, or remote multi-user service.
- OpenBao OIDC/service-auth login for steady-state secrets-engine operation.
- Native `exec-file` or response-wrapped delivery.
- Merge-safe multi-field KV updates or provider-side rotation.
- First-class rotate, compromise, suspend, reactivate, lease-status, or audit
report commands.
- Dual-control enforcement beyond accepting the catalog label.
- Direct flex-auth evaluation, claim validation, or identity authentication.
- Runtime tenancy isolation; `org`, `repo`, consumers, and stages are catalog
metadata plus local path/policy guards, not a tenant control plane.
- Management or health verification of ESO, Kubernetes Secrets, deployments,
provider accounts, SSH issuance, tunnels, or remote transport.
- Any backend other than the local `bao`/`vault` CLI speaking to OpenBao.
## System Boundary
- **OpenBao / railiance-platform** owns custody, policy enforcement, leases, and
audit. secrets-engine invokes it through supplied credentials.
- **flex-auth / State Hub decisions** own authorization. secrets-engine only
resolves and enforces recorded decision status.
- **user-engine / key-cape** own identity, OIDC, MFA, and claims.
- **ops-warden** issues SSH certificates and routes non-SSH credential needs; it
does not vend their values.
- **ops-bridge** owns tunnels and remote execution transport and may consume a
scoped delivery path.
- **workload/platform repositories** own ESO/Kubernetes delivery, provider
rotation, and application health.
- **info-tech-canon / net-kingdom** own canonical terminology and the
cross-system security boundary.
Canonical boundary:
`net-kingdom/docs/secrets-engine-security-infrastructure-boundary.md`.
## Security Rules
- Never place raw secret values in Git, State Hub, chat, prompts, workplans,
normal logs, or evidence.
- Never treat catalog admission, a dry-run, or an old workload CCR as approval
for a new production auth surface.
- Never mutate an existing shared mount or replace workload delivery by
implication.
- Never use current single-field provisioning on a shared multi-field path.
- Never call KV `revoke` unless destructive deletion of all path versions is the
explicitly approved intent.
- Keep bootstrap and handoff material outside repositories with mode 0600 and
explicit expiry/revocation handling.
## Where Current Work Lives
- `workplans/` is the source of truth for open work and operational gates.
- `docs/hardening-backlog.md` tracks exit from bootstrap mode.
- `history/` contains dated capability and intent assessments.
- `INTENT.md` remains the stable aspirational direction.
## Provided Capabilities
```capability
type: security
title: Decision-aware OpenBao policy/role apply
description: Turns an approved State Hub decision into a narrow, guarded OpenBao apply —
catalog lane to dry-run plan to idempotent ACL policy + AppRole write — through
least-privilege build/test/prod stage roles. Refuses unapproved, superseded, wildcard,
out-of-stage, or broad-admin plans before any backend call. Writes non-secret evidence.
keywords: [secrets, openbao, vault, policy, approle, catalog, decision, stage, least-privilege, netkingdom]
title: Guarded OpenBao lane planning and metadata apply
description: Validates cataloged KV and auth-capability lanes, renders exact policy/AppRole plans,
and applies approved metadata while rejecting missing decisions, stage mismatches, wildcards,
broad-admin names, and forbidden capability paths. Existing mounts are check-only.
keywords: [secrets, openbao, policy, approle, catalog, decision, stage, least-privilege]
```
```capability
type: security
title: Exec-time secret delivery
description: Delivers a secret into a child process only — never printing, exporting, or
persisting the value. npm-config injects a temporary mode-0600 .npmrc pointing at the
configured registry; exec-env injects a scoped env var. Temp config is cleaned up on
success, failure, and interruption; child output is redacted as a backstop.
keywords: [secrets, delivery, exec, npm, publish, token, injection, redaction, npmrc, openbao]
```
```capability
type: governance
title: Maturity-gated publication-scope policy
description: Binds npm publication scope to package maturity (build to gitea-wide, test to
org-wide, prod to repo-scoped) and gates the graduated table behind the netkingdom domain
reaching production grade. While dormant, every lane clamps to the safest repo-scope —
fail-safe, never fail-open. The injected token env-var name signals the effective blast radius.
keywords: [policy, maturity, publication-scope, governance, least-privilege, npm, gitea, netkingdom]
title: AppRole-scoped exec delivery
description: Fetches one declared KV field through a lane AppRole and injects it into a child
process using exec-env or a temporary npm config, with output redaction and cleanup. This is
CLI-local delivery; exec-file, wrapping, service delivery, and explicit token revocation are absent.
keywords: [secrets, delivery, exec, npm, injection, redaction, openbao]
```
```capability
type: security
title: Scoped OpenBao auth-capability handoff
description: Models non-KV grants such as warden-sign as guarded policy/AppRole lanes.
Plans refuse wildcards, sys/auth/token/identity paths, root-like capabilities, and
non-update SSH signing paths; handoff emits only file paths and non-secret metadata
while keeping role-id and secret-id material outside Git and normal logs.
keywords: [secrets, openbao, approle, auth-capability, warden-sign, ssh-signing, handoff, least-privilege]
description: Generates an exact-path policy/AppRole plan and writes role-id/secret-id material to
strict out-of-repo files after approval. Operational use remains subject to lane-specific governance.
keywords: [openbao, approle, auth-capability, handoff, least-privilege]
```
```capability
type: security
title: Lifecycle and non-secret evidence
description: Tracks secret and capability lifecycle actions as explicit, reversible
workflow steps: provision, verify, deliver, rotate, revoke, deactivate, and audit.
OpenBao keeps custody and audit; secrets-engine records only non-secret decisions,
paths, policy names, actors, timestamps, and verification outcomes.
keywords: [secrets, lifecycle, rotation, revocation, deactivation, audit, evidence, openbao, state-hub]
type: governance
title: Non-secret routing and evidence pointers
description: Reports decision/readiness metadata and records scrubbed local and best-effort State Hub
evidence without returning secret values. It is not a durable audit store or complete multi-field attestation.
keywords: [routing, evidence, state-hub, audit, secrets]
```

View file

@ -9,12 +9,14 @@
| Kind | ID | Status | Lane | Source |
| --- | --- | --- | --- | --- |
| workplan | ADHOC-2026-08-21 | finished | — | workplans/ADHOC-2026-08-21.md |
| workplan | ADHOC-2026-08-23 | finished | — | workplans/ADHOC-2026-08-23.md |
| workplan | SECRETS-WP-0001 | finished | — | workplans/SECRETS-WP-0001-statehub-bootstrap.md |
| workplan | SECRETS-WP-0002 | finished | — | workplans/SECRETS-WP-0002-bootstrap.md |
| workplan | SECRETS-WP-0004 | finished | — | workplans/SECRETS-WP-0004-warden-sign-token-lane.md |
| workplan | SECRETS-WP-0005 | finished | — | workplans/SECRETS-WP-0005-scope-intent-value-gaps.md |
| workplan | SECRETS-WP-0006 | active | — | workplans/SECRETS-WP-0006-catalog-lane-adoption.md |
| task | ADHOC-2026-08-21-T01 | done | — | workplans/ADHOC-2026-08-21.md |
| task | ADHOC-2026-08-23-T01 | done | — | workplans/ADHOC-2026-08-23.md |
| task | SECRETS-WP-0001-T01 | done | — | workplans/SECRETS-WP-0001-statehub-bootstrap.md |
| task | SECRETS-WP-0001-T02 | done | — | workplans/SECRETS-WP-0001-statehub-bootstrap.md |
| task | SECRETS-WP-0001-T03 | done | — | workplans/SECRETS-WP-0001-statehub-bootstrap.md |

View file

@ -0,0 +1,217 @@
# Scope and Intent Capability Gap Assessment
Date: 2026-08-23
Author: codex
Compared: `SCOPE.md` against `INTENT.md` and the current implementation
## Executive assessment
The repository has a credible, tested CLI MVP, but it is not yet the complete
secure interaction and automation layer described by `INTENT.md`.
The strongest implemented slice is:
```text
catalog -> approval-status check -> guarded plan -> policy/AppRole apply
-> bounded presence/capability verification -> CLI-local exec/handoff
-> non-secret route/evidence pointer
```
The weakest slice is lifecycle safety beyond that pilot chain. Rotation is
metadata only, KV provisioning is not merge-safe for multi-field paths, KV
revoke is destructive and incomplete, approval integration is still a pilot
resolver rather than a production authorization contract, and service mode does
not exist.
The intent remains directionally sound. The gap is maturity, not a need to move
the system boundary: OpenBao should remain the backend; flex-auth/State Hub
should authorize; key-cape/user-engine should own identity; ops-warden should
route; and secrets-engine should remain the guarded workflow layer.
## Open-work assessment
The only active repository workplan is `SECRETS-WP-0006`:
- T05 waits on explicit per-lane approval and scoped production OpenBao apply
authority for five reviewed existing production lanes.
- T06 waits on successful native verification before ops-warden proxy retirement.
No approval or production authority was available during this assessment. The
latest ops-warden message also parks the standalone `warden-sign` AppRole for
break-glass use and explicitly requests no credential action. There was no safe,
actionable live task, so documentation reconciliation was the appropriate work.
## Intent scorecard
| Intent area | Assessment | Current evidence | Material gap |
| --- | --- | --- | --- |
| Decision first | Partial | Privileged CLI handlers require a resolved status and reject missing, unapproved, or superseded decisions. | Resolution accepts tracked local fixtures, checks only coarse status, has no freshness/purpose/actor semantics, and does not enforce actual dual control. The five new CCR strings do not resolve through the State Hub UUID endpoint. |
| OpenBao enforces; engine orchestrates | Substantially aligned | Backend operations are isolated in `openbao.py`; catalog, plan, guards, delivery, routing, and evidence are separate modules. | Only the local `bao`/`vault` subprocess adapter exists. Some safety depends on local validation rather than backend-bound per-request authorization. |
| Stage-aware privilege | Partial | Stage names, stage mismatch rejection, build/test prefixes, static stage policies, and consumer policy/AppRole naming exist. | Production has no local owner-prefix invariant (`STAGE_PREFIX["prod"]` is empty). Static bootstrap stage policies and supplied credentials remain wider and longer-lived than per-action identity. |
| No values in coordination surfaces | Partial, with a concrete implementation risk | Catalog validation rejects secret-looking inline values; evidence is scrubbed; CLI output avoids values; exec output is redacted. | `kv_put` passes the raw value in the local `bao` subprocess argument vector. Exec/verification parse the complete KV path response in process memory. These do not put values in Git/State Hub, but they fall short of the strongest custody boundary in the intent. |
| Least friction without broad power | Partial | Human-readable dry-runs, one-command exec, route pointers, and exact consumer policies reduce hand-written OpenBao work. | Routine production still needs manual decision and credential bridging. There is no OIDC/service login, service API, or durable request orchestration. |
| Bootstrap honestly, then harden | Partial | Bootstrap files are mode checked, rejected inside Git worktrees, documented, and tracked in the hardening backlog. | Bootstrap mode is still part of the live CLI; one historical cleanup/revocation record remains incomplete; tracked local approval mirrors remain usable for production commands. |
| Prefer exec-time delivery | Partial | `exec-env` and `npm-config` are implemented, including temporary npm config cleanup and child-output redaction. | `exec-file` and `wrapped` are schema-only. Scoped login tokens are not explicitly revoked after exec/verify, and child delivery is local CLI execution only. |
| Auditable and reversible | Weak/partial | Scrubbed JSONL evidence and best-effort State Hub progress events exist; OpenBao remains the audit source. | Many failure paths produce no evidence, State Hub posting silently drops failures, actors are not cryptographically bound, no audit-report command exists, and KV revoke is destructive rather than reversible. |
| Typed multi-application catalog | Substantially aligned as metadata | Multiple KV lanes, an auth-capability lane, explicit org/repo/stage/consumer/field data, existing-mount semantics, and high-risk ownership checks are implemented. | This is not runtime multi-tenancy. Consumer claims are descriptive and are not authenticated or authorized by this process. |
| CLI and service API | CLI achieved; API absent | The documented CLI surface exists and the pilot flow has integration coverage. | No daemon, API, queue, scheduler, UI, remote protocol, or concurrency model exists. |
| Lifecycle: establish/access/rotate/deactivate | Establish/access partial; lifecycle incomplete | Apply, provision, verify, exec, handoff, and two forms of revoke exist. | No rotate command, compromise/suspend state, provider rotation, lease/accessor lifecycle, rollback orchestration, or safe soft deactivation exists. |
## Highest-priority gaps
### P0 — Provisioning is unsafe for shared multi-field paths
`provision_from_file` reads one declared field and calls `OpenBaoClient.kv_put`.
That adapter invokes:
```text
bao kv put <mount>/<path> <field>=<value>
```
Two consequences matter:
1. `kv put` replaces the data at a KV v2 path rather than merging sibling
fields. Updating one field can remove the others.
2. The raw value is present in the local subprocess argument vector while the
command runs.
This is acceptable only as a constrained pilot/bootstrap primitive on a
single-field or disposable path. It must not be used on the newly admitted
issue-core, reuse-surface, Forgejo, or email paths. A production design needs a
merge-safe update mechanism that does not expose values through argv, plus
tests proving sibling preservation and failure cleanup.
### P0 — KV revoke is destructive, incomplete, and inconsistent with dry-run
For a KV lane, live `revoke` deletes all KV metadata/versions but leaves the
consumer AppRole and ACL policy. The dry-run text says it would delete both KV
metadata and the AppRole, which the live path does not do.
This does not meet the intent's reversible lifecycle principle. The command
needs explicit operations with different approvals, for example:
- suspend delivery by deleting/disabling AppRole credentials;
- deactivate consumer policy/auth;
- revoke leases/tokens by accessor;
- delete current value versions;
- irreversibly destroy KV metadata only under an explicit destruction action.
Until then, KV revoke should be treated as destructive path deletion, not a
general revocation or deactivation workflow.
### P0 — Production approval is not yet a complete authorization contract
The resolver accepts `resolved`, `approved`, or `accepted` status and absence of
`superseded_by`. It does not validate action type, lane/stage binding, actor,
expiry, allowed fields, operation, approval count, or flex-auth result.
`dual-control` is a catalog label but is not enforced as two approvals.
Tracked local decision mirrors are useful for demos and historical pilots but
are too permissive as a steady-state production authority source. Production
should require a canonical decision object bound to the exact action and should
fail closed when State Hub/flex-auth cannot prove that binding.
## Important hardening gaps
### P1 — Steady-state authentication is absent
The CLI accepts a token from an environment variable or a mode-0600 bootstrap
file. It does not perform OpenBao OIDC, workload/service auth, short-lived
issuer exchange, or per-action identity binding. This keeps routine production
work dependent on attended external credential bridging.
### P1 — Verification is narrower than the intent
KV positive verification checks one field, defaulting to the first. Route
readiness also checks only the first field, so a multi-field lane can appear
ready while sibling fields are missing. KV negative verification uses a fixed
garbage token, not a real unrelated workload identity. Provider behavior and
application health are outside the check.
High-risk lane acceptance should verify every declared field, use a real
unrelated identity or capabilities proof, capture OpenBao audit request ids,
and, where appropriate, call a value-safe provider/application smoke.
### P1 — Delivery token lifecycle is implicit
Exec and verification create AppRole Secret IDs and login tokens. Secret ID
use counts and token TTL/use bounds limit them, but the code does not revoke the
issued token explicitly on success, child failure, interruption, or verification
failure. Evidence does not include a safe lease/accessor lifecycle.
### P1 — Evidence is informative, not a durable audit workflow
Local JSONL is append-only by convention, not tamper-evident. State Hub posting
is best-effort and silently ignored on error. Apply/provision/handoff failures
are generally recorded only if a caller adds separate evidence; there is no
transaction id joining State Hub evidence to OpenBao audit entries, and no
`audit` command summarizes a lane.
### P1 — Lifecycle metadata is not lifecycle automation
Catalog entries require rotation/deactivation descriptions and owners, which is
valuable governance metadata. The engine does not execute those plans, manage
provider credential overlap, coordinate consumers, maintain compromised or
deactivated state, or verify rollback.
## Longer-term product gaps
### P2 — Service mode
The intent describes a CLI and service API. Only the CLI exists. A service
should wait until approval binding, auth, delivery token lifecycle, evidence,
and destructive-operation semantics are hardened; exposing today's CLI directly
would amplify its pilot shortcuts.
### P2 — Runtime tenancy and consumer identity
The catalog can describe many applications and logical owners, but the engine
does not authenticate a tenant, resolve claims, isolate concurrent callers, or
enforce per-tenant quotas/policies. The current product is multi-application
metadata and path orchestration, not a multi-tenant service.
### P2 — Backend abstraction
OpenBao-specific behavior is isolated reasonably well, but there is only one
subprocess backend. “OpenBao as the initial enforcement backend” remains an
architectural option, not a demonstrated portable backend contract.
## Current evolution phase
Against the phases in `INTENT.md`:
1. **Bootstrap:** implemented and still active.
2. **MVP:** achieved for the whynot-design npm pilot.
3. **Stage separation:** implemented in catalog/plan/static policy form, but
steady-state stage authentication and stronger production owner binding are
incomplete.
4. **Hardening:** started; existing-mount admission, risk classification,
exact-field guards, bounded AppRoles, and fail-closed decisions exist. The P0
and P1 gaps above remain.
5. **Service mode:** not started.
## Recommended next sequence
1. Keep `SECRETS-WP-0006-T05` limited to approved metadata apply and explicit
per-field, positive/negative verification. Do not provision or revoke the
existing shared paths through the current KV lifecycle commands.
2. Fix provisioning transport and merge semantics, with sibling-preservation
and process-argument tests.
3. Split KV suspend/deactivate/destroy semantics and make dry-run match live
behavior.
4. Replace coarse/local production decision resolution with an action-bound,
expiring, dual-control-capable authorization contract.
5. Add steady-state OIDC/service auth and explicit child-token revocation.
6. Strengthen multi-field/readiness and unrelated-identity verification, then
correlate evidence with OpenBao audit request ids.
7. Implement rotation state and wrapped/file delivery before designing service
mode.
## Conclusion
`INTENT.md` still describes the right destination, but the accurate present
tense is a guarded OpenBao CLI MVP with one proven native workload pilot and
several reviewed-but-not-live production lane plans. The repository should not
yet advertise itself as a service API, complete lifecycle engine, runtime
multi-tenant system, wrapped-delivery broker, or production-safe general KV
updater.

View file

@ -0,0 +1,39 @@
---
id: ADHOC-2026-08-23
type: workplan
title: "Implemented scope and intent-gap reconciliation"
domain: infotech
repo: secrets-engine
status: finished
owner: codex
topic_slug: custodian
created: "2026-08-23"
updated: "2026-08-23"
---
# ADHOC-2026-08-23 - Implemented scope and intent-gap reconciliation
## Reconcile implemented capability scope
```task
id: ADHOC-2026-08-23-T01
status: done
priority: medium
```
Checked the repository workplans and coordination inbox. The only active work,
`SECRETS-WP-0006-T05/T06`, remains waiting on external production approval and
authority; the current ops-warden message requested no credential action.
Rewrote `SCOPE.md` as an implemented capability boundary rather than an
aspirational/current-work ledger, and recorded a dated assessment against
`INTENT.md` in
`history/2026-08-23-scope-intent-capability-gap-assessment.md`. The assessment
documents the achieved CLI MVP and the concrete approval, provisioning,
revocation, verification, auth, evidence, lifecycle, tenancy, and service-mode
gaps without exposing secret material.
`statehub fix-consistency` was attempted twice and interrupted after repeated
60-second stalls in State Hub HTTP calls (`GET /topics/<id>` and
`PATCH /repos/secrets-engine`). The progress event was recorded successfully,
but registrar/index consistency remains pending on State Hub availability.