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
43
catalog/example-build-test-token.yaml
Normal file
43
catalog/example-build-test-token.yaml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Example BUILD-stage lane. Demonstrates that build entries can be looser:
|
||||
# generated test values are allowed and no production decision is required.
|
||||
id: example-build-test-token
|
||||
owner: platform-ci
|
||||
stage: build
|
||||
description: >-
|
||||
Throwaway generated credential for build-stage integration tests. May be
|
||||
generated locally; must never be reused in test or prod.
|
||||
|
||||
mount: secret
|
||||
path: build/example/test-token
|
||||
|
||||
fields:
|
||||
- api_token
|
||||
|
||||
consumers:
|
||||
- name: build-runner
|
||||
auth: approle
|
||||
claim: "role:build-runner"
|
||||
purpose: "exercise build-stage integration tests"
|
||||
|
||||
delivery_modes:
|
||||
- exec-env
|
||||
- read-check
|
||||
|
||||
# Build stage permits bootstrap-only / generated values without a prod decision.
|
||||
approval:
|
||||
model: bootstrap-only
|
||||
notes: "Build stage: generated test secret, no production decision required."
|
||||
|
||||
verification:
|
||||
positive: "build-runner token can read the generated value"
|
||||
negative: "prod consumers cannot read build paths"
|
||||
|
||||
rotation:
|
||||
expectation: "regenerate per run"
|
||||
ttl: "1h"
|
||||
|
||||
deactivation:
|
||||
expectation: "delete on build teardown"
|
||||
|
||||
audit:
|
||||
evidence: "actor, path, timestamp, result — no secret value"
|
||||
51
catalog/whynot-design-npm-publish.yaml
Normal file
51
catalog/whynot-design-npm-publish.yaml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# whynot-design npm publish token — the MVP pilot lane.
|
||||
# This file is NON-SECRET. It describes where the token lives in OpenBao and how
|
||||
# it may be consumed. The token VALUE never appears here.
|
||||
id: whynot-design-npm-publish
|
||||
owner: whynot-design
|
||||
stage: prod
|
||||
description: >-
|
||||
npm automation token used to publish the whynot-design package. Delivered to
|
||||
`npm publish` via an exec-time temporary npm config; never printed or exported
|
||||
into the parent shell.
|
||||
|
||||
# OpenBao KV v2 location of the secret material.
|
||||
mount: secret
|
||||
path: whynot-design/npm/publish
|
||||
|
||||
# Field(s) inside the KV entry. The publish token is stored under this key.
|
||||
fields:
|
||||
- npm_token
|
||||
|
||||
# Who may consume this lane and the identity claim that binds them.
|
||||
consumers:
|
||||
- name: whynot-design-ci
|
||||
auth: approle # bound OpenBao auth method
|
||||
claim: "role:whynot-design-publish"
|
||||
purpose: "publish whynot-design npm package from CI"
|
||||
|
||||
# How the value may leave OpenBao. npm-config = temp .npmrc for the child only.
|
||||
delivery_modes:
|
||||
- npm-config
|
||||
- read-check
|
||||
|
||||
# Privileged actions on this lane require an approved decision/CCR.
|
||||
approval:
|
||||
model: decision
|
||||
decision_ref: "whynot-design-npm-publish" # State Hub decision/CCR id or slug
|
||||
notes: "Production lane: apply requires an approved decision."
|
||||
|
||||
# Verification expectations (no value is ever printed).
|
||||
verification:
|
||||
positive: "approved consumer token can read the lane field"
|
||||
negative: "an unrelated token is denied read on the lane path"
|
||||
|
||||
rotation:
|
||||
expectation: "rotate on compromise or every 90 days"
|
||||
ttl: "90d"
|
||||
|
||||
deactivation:
|
||||
expectation: "revoke approle + delete KV metadata; record evidence"
|
||||
|
||||
audit:
|
||||
evidence: "decision id, actor, path, timestamp, result — no secret value"
|
||||
Loading…
Add table
Add a link
Reference in a new issue