# secrets-engine CLI ## Install ```bash uv venv && uv pip install -e ".[dev]" source .venv/bin/activate secrets-engine --version ``` ## Environment | Var | Default | Purpose | | --- | --- | --- | | `BAO_ADDR` | `http://127.0.0.1:8200` | OpenBao address | | `BAO_TOKEN` | _(unset)_ | OpenBao token (or use `--bootstrap-token-file`) | | `SECRETS_ENGINE_HUB_URL` | `http://127.0.0.1:8000` | State Hub for decisions + evidence (empty to disable) | | `SECRETS_ENGINE_CATALOG` | `./catalog` | catalog directory | | `SECRETS_ENGINE_EVIDENCE` | `./.evidence` | local non-secret evidence log | ## Commands ```text secrets-engine catalog list secrets-engine catalog show secrets-engine decision inspect secrets-engine plan --stage secrets-engine apply --stage [--dry-run] [--bootstrap-token-file F] secrets-engine provision --stage --field NAME (--from-file F | --generate) secrets-engine verify --field NAME [--positive] [--negative] secrets-engine exec --catalog [--field NAME] [--mode auto|npm-config|exec-env] -- CMD... secrets-engine route [--json] secrets-engine revoke [--dry-run] ``` `` is a catalog id or a decision/CCR ref (matched against `approval.decision_ref`). `plan` and `apply --dry-run` never mutate OpenBao. ## Exit codes | Code | Meaning | | --- | --- | | 0 | success | | 2 | catalog error (missing/invalid lane) | | 3 | decision error (unapproved / superseded / missing) | | 4 | policy guard error (out-of-stage / wildcard / broad admin) | | 5 | backend error (OpenBao unreachable / failed) | | 6 | provisioning error (bad file mode / inside repo / missing field) | | 7 | verification failed | | 8 | delivery error | ## End-to-end demo ```bash SECRETS_ENGINE_HUB_URL="" bash scripts/demo-e2e.sh ``` Boots a throwaway in-memory OpenBao dev server and runs the whole pilot chain: plan → apply → provision → verify(+/-) → exec (npm-config injection) → route → revoke. Nothing is persisted; the token is a throwaway local string. ## Pilot: whynot-design npm publish ```bash # 1. inspect the approved decision secrets-engine decision inspect whynot-design-npm-publish # 2. preview the OpenBao changes (no mutation) secrets-engine plan whynot-design-npm-publish --stage prod # 3. apply policy + approle secrets-engine apply whynot-design-npm-publish --stage prod # 4. provision the token from a mode-0600 file OUTSIDE the repo secrets-engine provision whynot-design-npm-publish --stage prod \ --field npm_token --from-file ~/.secrets-engine/whynot.token # 5. prove access without printing the value secrets-engine verify whynot-design-npm-publish --field npm_token --positive --negative # 6. publish with the token injected into the child only secrets-engine exec --catalog whynot-design-npm-publish -- npm publish ```