feat(mvp): working secrets-engine CLI for the whynot-design npm publish lane
Implements SECRETS-WP-0002 end to end as a uv-managed Python package: - catalog: non-secret lane registry + strict validator (build/test/prod) - stage roles + OpenBao ACL policies; guards refuse wildcards, sys/, identity/, admin names, and cross-stage paths before any backend call - plan/apply: dry-run-first, idempotent policy + approle apply, decision-gated - decisions: State Hub lookup with local-fixture fallback; non-secret evidence to JSONL + hub progress, scrubbed of any value - provision/verify: mode-0600 file import + generated test values; positive/ negative checks that never print the value - exec delivery: `exec --catalog ... -- npm publish` injects the token via a temp .npmrc for the child only, cleaned up on exit/failure/interrupt - ops-warden routing contract + hardening backlog docs - 34 tests incl. live OpenBao integration; scripts/demo-e2e.sh runs the full chain against a throwaway bao dev server Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
58c24cff53
commit
a852d3f1ff
47 changed files with 3743 additions and 122 deletions
301
ProductRequirementsDocument.md
Normal file
301
ProductRequirementsDocument.md
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
# Product Requirements Document: secrets-engine
|
||||
|
||||
## Summary
|
||||
|
||||
secrets-engine provides the operational interface for approved secret lifecycle
|
||||
work across build, test, and production. It wraps OpenBao with a catalog,
|
||||
decision checks, stage-aware privilege boundaries, safe delivery modes, and
|
||||
non-secret audit evidence.
|
||||
|
||||
The first implementation should focus on getting one real pilot lane working end
|
||||
to end: the whynot-design npm publish token. The design must also be general
|
||||
enough to support API keys, provider tokens, database passwords, CI credentials,
|
||||
and other workload secrets later.
|
||||
|
||||
## Related Documents
|
||||
|
||||
- [NetKingdom security infrastructure boundary pointer](docs/netkingdom-security-infrastructure.md)
|
||||
points to the canonical document in `net-kingdom/docs/` and defines the
|
||||
responsibilities and interactions with OpenBao, flex-auth, user-engine,
|
||||
ops-warden, ops-bridge, info-tech-canon, State Hub, and agents.
|
||||
|
||||
## Background
|
||||
|
||||
The current platform can define OpenBao paths, policies, and credential-change
|
||||
requests, but the live path still requires too much manual OpenBao UI/CLI work.
|
||||
This creates a trap: the secure process exists on paper, but daily work still
|
||||
falls back to handovers, broad platform-root access, and interface-specific
|
||||
mistakes.
|
||||
|
||||
secrets-engine is the missing workflow layer. It should let an approved decision
|
||||
become an applied and verified secret lane without asking each operator or agent
|
||||
to understand every OpenBao endpoint, CLI quoting rule, auth role shape, or
|
||||
workload-specific delivery convention.
|
||||
|
||||
## Goals
|
||||
|
||||
- Provide one interaction surface for approved secret establishment, access,
|
||||
rotation, deactivation, and verification.
|
||||
- Separate build, test, and production privileges from the beginning.
|
||||
- Let agents and operators apply approved OpenBao metadata without broad admin
|
||||
access.
|
||||
- Deliver secrets to commands and workloads without printing values.
|
||||
- Produce non-secret evidence suitable for State Hub progress, audits, and
|
||||
troubleshooting.
|
||||
- Give ops-warden a credential routing target that is not responsible for secret
|
||||
custody itself.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Replacing OpenBao as the canonical vault and audit backend.
|
||||
- Replacing key-cape, user-engine, flex-auth, or State Hub.
|
||||
- Building a full UI before the CLI/API model is clear.
|
||||
- Automating high-risk production secret value provisioning before the approval,
|
||||
wrapped-delivery, and verification model is proven.
|
||||
- Storing raw secret values in Git, workplans, State Hub, chat, prompts, normal
|
||||
logs, or long-lived local files.
|
||||
|
||||
## Primary Users
|
||||
|
||||
| User | Need |
|
||||
| --- | --- |
|
||||
| Platform operator | Apply approved secret changes without hand-typing OpenBao internals. |
|
||||
| Agent such as Codex or ops-warden | Request or use approved credentials through a safe front door. |
|
||||
| Workload maintainer | Get a clear request, review, approval, and consumption path. |
|
||||
| Security reviewer | See decisions, policy boundaries, verification evidence, and revocation state. |
|
||||
| Future service maintainer | Add new secret types and delivery modes without weakening production custody. |
|
||||
|
||||
## Operating Model
|
||||
|
||||
### Stage roles
|
||||
|
||||
secrets-engine should bootstrap at least three OpenBao-facing roles:
|
||||
|
||||
| Role | Intended use | Initial privilege shape |
|
||||
| --- | --- | --- |
|
||||
| secrets-engine-build | Build/dev lanes, generated test values, low-risk experimentation | Can manage approved build-stage metadata and values under build prefixes. |
|
||||
| secrets-engine-test | Test/staging lanes and integration verification | Can manage approved test-stage metadata and values; can perform positive/negative checks. |
|
||||
| secrets-engine-prod | Production metadata apply and tightly controlled delivery | Can apply approved prod metadata and auth roles; raw prod value read/provisioning remains gated and logged. |
|
||||
|
||||
The exact OpenBao policy names can change, but the stage distinction is a
|
||||
product requirement, not an implementation detail.
|
||||
|
||||
### Bootstrap credential files
|
||||
|
||||
Until proper OIDC/service authentication exists, a platform-root operator may
|
||||
create temporary OpenBao credentials for the three roles and place them outside
|
||||
repositories, for example under a local mode-0700 directory. The files must be:
|
||||
|
||||
- mode 0600;
|
||||
- outside Git worktrees;
|
||||
- named by role and environment only, never by secret value;
|
||||
- revocable;
|
||||
- recorded in non-secret bootstrap notes by path and accessor only when safe;
|
||||
- treated as temporary infrastructure setup material.
|
||||
|
||||
Agents may be told the file path, not the token value. The engine should read
|
||||
such files only when explicitly invoked in bootstrap mode.
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
### FR1 - Secret catalog
|
||||
|
||||
The engine must maintain a non-secret catalog of secret lanes and grants.
|
||||
|
||||
Each catalog entry should include:
|
||||
|
||||
- catalog id;
|
||||
- owning domain/repo/workload;
|
||||
- stage: build, test, production, or another explicit stage;
|
||||
- OpenBao mount and path;
|
||||
- fields exposed;
|
||||
- allowed consumers and auth claims;
|
||||
- delivery modes;
|
||||
- approval requirement;
|
||||
- TTL and rotation expectations;
|
||||
- verification requirements;
|
||||
- revocation/deactivation behavior;
|
||||
- audit evidence expectations.
|
||||
|
||||
### FR2 - Decision integration
|
||||
|
||||
Privileged actions must require an approved decision or approved credential
|
||||
change request unless explicitly running in a local bootstrap or dry-run mode.
|
||||
|
||||
The engine must be able to:
|
||||
|
||||
- inspect a request;
|
||||
- render a human-reviewable plan;
|
||||
- link to the decision record when available;
|
||||
- refuse denied, superseded, stale, or unapproved requests;
|
||||
- record non-secret apply and verification evidence.
|
||||
|
||||
### FR3 - OpenBao metadata apply
|
||||
|
||||
The engine must generate and apply OpenBao metadata safely:
|
||||
|
||||
- ACL policies;
|
||||
- auth roles;
|
||||
- token roles where needed;
|
||||
- KV metadata where safe;
|
||||
- path and name restrictions based on catalog and stage;
|
||||
- dry-run output before live mutation.
|
||||
|
||||
Production apply must fail closed if the request is not approved or if the plan
|
||||
contains an out-of-bound policy, role, mount, path, wildcard, or broad admin
|
||||
capability.
|
||||
|
||||
### FR4 - Secret provisioning
|
||||
|
||||
The engine must support secret value provisioning without exposing raw values in
|
||||
coordination channels.
|
||||
|
||||
Initial supported modes:
|
||||
|
||||
- operator-attended OpenBao provisioning;
|
||||
- bootstrap local file import with strict permissions;
|
||||
- response-wrapped handoff where OpenBao supports it;
|
||||
- generated test secrets for non-production only.
|
||||
|
||||
Production raw value automation should remain deliberately constrained until the
|
||||
wrapped or dual-control flow is proven.
|
||||
|
||||
### FR5 - Secret delivery
|
||||
|
||||
The engine must provide delivery modes that avoid printing secret values:
|
||||
|
||||
- exec-time environment injection;
|
||||
- exec-time temp file injection with cleanup;
|
||||
- workload-specific config file generation such as temporary npm config;
|
||||
- response wrapping for handoff flows;
|
||||
- read checks that return boolean/evidence, not the value.
|
||||
|
||||
A representative target command shape:
|
||||
|
||||
```bash
|
||||
secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
|
||||
```
|
||||
|
||||
For npm, the engine should prefer creating a temporary npm config and setting the
|
||||
child process environment to use it, then deleting it after the child exits.
|
||||
|
||||
### FR6 - Verification
|
||||
|
||||
The engine must support positive and negative verification without printing
|
||||
secrets.
|
||||
|
||||
Positive checks prove an approved consumer can access or use the secret. Negative
|
||||
checks prove an unrelated consumer cannot. Evidence should include non-secret
|
||||
metadata such as catalog id, actor, decision id, path, timestamp, and result.
|
||||
|
||||
### FR7 - CLI/API interface
|
||||
|
||||
The MVP must provide a CLI. The command names may evolve, but the first surface
|
||||
should cover:
|
||||
|
||||
```text
|
||||
secrets-engine catalog list
|
||||
secrets-engine catalog show <catalog-id>
|
||||
secrets-engine decision inspect <decision-or-ccr-id>
|
||||
secrets-engine plan <decision-or-ccr-id>
|
||||
secrets-engine apply <decision-or-ccr-id> --stage <build|test|prod>
|
||||
secrets-engine provision <catalog-id> --stage <stage> --from-file <path>
|
||||
secrets-engine verify <catalog-id> --positive
|
||||
secrets-engine verify <catalog-id> --negative
|
||||
secrets-engine exec --catalog <catalog-id> -- <command...>
|
||||
secrets-engine revoke <catalog-id-or-lease>
|
||||
```
|
||||
|
||||
The API should be designed after the CLI semantics are clear.
|
||||
|
||||
### FR8 - Audit and evidence
|
||||
|
||||
The engine must never log raw secret values. It must write non-secret evidence
|
||||
for:
|
||||
|
||||
- decision inspected;
|
||||
- plan rendered;
|
||||
- apply attempted/succeeded/failed;
|
||||
- secret provisioned without value disclosure;
|
||||
- exec delivery attempted/succeeded/failed;
|
||||
- verification positive/negative result;
|
||||
- revoke/deactivate/rotate actions.
|
||||
|
||||
State Hub integration should use non-secret progress entries and decision links.
|
||||
OpenBao audit logs remain the backend source of truth for vault operations.
|
||||
|
||||
### FR9 - ops-warden routing
|
||||
|
||||
ops-warden should route non-SSH credential requests to secrets-engine. It should
|
||||
not own or vend provider tokens, API keys, database passwords, or OpenBao values.
|
||||
|
||||
A route result should tell the caller:
|
||||
|
||||
- the catalog id;
|
||||
- the decision/request status;
|
||||
- whether the secret is ready/resolvable;
|
||||
- the safe command to request or execute with the credential;
|
||||
- what human decision or provisioning step is still missing.
|
||||
|
||||
## Security Requirements
|
||||
|
||||
- Raw secret values must never appear in prompts, chat, Git, workplans, State
|
||||
Hub messages, issue comments, or normal logs.
|
||||
- Production operations must require an approved decision except break-glass
|
||||
flows, which must be explicit and heavily audited.
|
||||
- Stage roles must be unable to mutate paths outside their stage and allowed
|
||||
prefixes.
|
||||
- Production metadata appliers must not gain broad sys, auth, identity, root, or
|
||||
platform-admin semantics.
|
||||
- Bootstrap token files must be temporary, revocable, mode 0600, and outside
|
||||
repositories.
|
||||
- The engine must redact token-like values from child process output where it
|
||||
controls the execution path.
|
||||
- Every role and delivery mode must have a documented revocation path.
|
||||
|
||||
## MVP Scope
|
||||
|
||||
The MVP is complete when it can support the whynot-design npm publish token
|
||||
pilot with this chain:
|
||||
|
||||
1. Catalog entry exists for whynot-design npm publish.
|
||||
2. Approved decision/CCR is inspected.
|
||||
3. OpenBao ACL policy and auth role are applied through a stage-appropriate
|
||||
secrets-engine role or bootstrap credential.
|
||||
4. The token value is provisioned without being printed or logged.
|
||||
5. Positive and negative verification pass.
|
||||
6. A safe command can execute npm publish with the token injected only into the
|
||||
child process.
|
||||
7. ops-warden can report the catalog entry as ready/resolvable.
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- Approved secret lanes can be applied without platform-root hand typing.
|
||||
- A typical approved non-production credential can be established in minutes.
|
||||
- Production metadata apply succeeds without granting raw secret read authority.
|
||||
- No secret values are found in repo history, State Hub payloads, logs, or chat.
|
||||
- Operators can understand a generated plan without knowing OpenBao endpoint
|
||||
quirks.
|
||||
- At least one real workload consumes a credential through secrets-engine exec.
|
||||
|
||||
## Risks
|
||||
|
||||
| Risk | Mitigation |
|
||||
| --- | --- |
|
||||
| Wrapper accidentally becomes broad platform-admin by another name | Stage roles, path allowlists, decision checks, negative tests. |
|
||||
| Temporary bootstrap files become permanent | Track bootstrap mode, add revocation tasks, replace with OIDC/service auth. |
|
||||
| Agents exfiltrate secrets through logs or prompts | Prefer exec-time delivery, redaction, no raw read default. |
|
||||
| Product scope grows into identity/authorization | Keep key-cape/user-engine and flex-auth boundaries explicit. |
|
||||
| OpenBao-specific assumptions leak everywhere | Keep a catalog and interface model; isolate backend adapter code. |
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Should the first repo expose only a CLI, or also a tiny local service API?
|
||||
- What is the canonical State Hub decision object for secret establishment,
|
||||
rotation, and deactivation?
|
||||
- Which stage names are final: build, test, prod, or build, staging,
|
||||
production?
|
||||
- Should production value provisioning require two-person review immediately or
|
||||
only after the pilot?
|
||||
- Which identity claim should bind the whynot-design consumer long term: group,
|
||||
workload service account, repository identity, or a combination?
|
||||
Loading…
Add table
Add a link
Reference in a new issue