Verified the digest join against flex-auth's T03 replay fixtures and found request_digest was hashing fields docs/canonical-request-digest.md excludes. The material is tenant, subject, action, resource, context only: id is correlation, policy_version lives in provenance, caring_context is hashed separately. This engine included all three when present. Because the join adopts the served request id, every real production request would have carried one, so the computed digest would have matched no issued decision and failed closed against every correct allow. Same unsatisfiable shape as the removed AUTHORITY constant. The old pinned constant was computed with the id inside the material, so it was wrong and its passing proved nothing. Replaced with fixture-driven tests over two real envelopes (vendored with provenance) plus a structural test that correlation fields do not move the digest. Both fixtures are needed: input_claim_digests.context appears only with a non-empty context. Also stops computing the native claim digest. The claim's binding.action and binding.target speak approval-engine's vocabulary while ours speaks the catalog's, and no mapping is published; flex-auth makes no cross-check and states the correspondence is ours via pdp_digest. A claim recording no pdp_digest now fails closed naming the missing mapping rather than comparing two different languages. That mapping is a prerequisite for destroy. 274 tests pass. Production still fails closed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M65ovP3eiiPHubibvWs9mD Assistant: claude-code Assistant-Model: opus Assistant-Process: 393550@bnt-lap001 Assistant-Session: 4bb359f9-1f12-4410-9e76-079cf23c82e4 |
||
|---|---|---|
| .claude/rules | ||
| .decisions | ||
| .forgejo/workflows | ||
| catalog | ||
| docs | ||
| history | ||
| intakes | ||
| policies | ||
| registry | ||
| scripts | ||
| src/secrets_engine | ||
| tests | ||
| workplans | ||
| .custodian-brief.md | ||
| .gitignore | ||
| .repo-classification.yaml | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| evidence-classification.yaml | ||
| INTENT.md | ||
| layer.yaml | ||
| LICENSE | ||
| pep-stance.yaml | ||
| ProductRequirementsDocument.md | ||
| pyproject.toml | ||
| README.md | ||
| SCOPE.md | ||
| uv.lock | ||
| WORK-RECORDS.md | ||
secrets-engine
Headless, multi-application, multi-tenant secrets workflow and automation layer for approved secret custody, delivery, and lifecycle work across build, test, and production stages.
Layer: Engine / Lifecycle under the accepted NetKingdom Security Layer
Model (layer.yaml). OpenBao remains the custody and enforcement backend.
secrets-engine is the deterministic API over it: catalog, decision
consumption, plan/apply, guarded provisioning, verification, delivery,
evidence, lifecycle metadata, and native-access deactivation. It does not
render authorization decisions. Local evidence can be inspected through an
allowlisted per-lane audit summary without exposing record detail.
Start Here
- INTENT.md - why this repository exists, including the Engine / Lifecycle declaration.
- layer.yaml - machine-readable layer declaration and proposed surfaces.
- ProductRequirementsDocument.md - product requirements and MVP scope.
- NetKingdom security infrastructure boundary pointer
- points to the canonical document in
net-kingdom/docs/, covering responsibilities and interactions with OpenBao, flex-auth, user-engine, ops-warden, ops-bridge, info-tech-canon, State Hub, and agents.
- points to the canonical document in
- Bootstrap MVP workplan - first implementation plan after State Hub bootstrap.
Core Direction
The MVP proves the whynot-design-npm-publish lane end to end:
- describe the lane in a non-secret catalog (
catalog/); - verify an approved decision (State Hub or local fixture);
- apply OpenBao policy/auth metadata through a stage-aware role;
- provision and verify the value without printing it;
- run a workload command through safe exec-time delivery.
Target command shape:
secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
Quickstart
uv venv && uv pip install -e ".[dev]"
source .venv/bin/activate
secrets-engine catalog list
# Run the whole pilot chain live against a throwaway OpenBao dev server:
SECRETS_ENGINE_HUB_URL="" bash scripts/demo-e2e.sh
- CLI reference: docs/cli.md
- Publication-scope policy (maturity → token scope): docs/publication-scope-policy.md
- Stage roles & bootstrap tokens: docs/openbao-stage-roles.md
- warden-sign auth-capability lane: docs/warden-sign-auth-capability.md
- whynot-design real publish closeout: docs/whynot-design-real-publish-closeout.md
- ops-warden routing contract: docs/ops-warden-routing-contract.md
- Hardening backlog (exit bootstrap mode): docs/hardening-backlog.md
- Existing-lane catalog admission: docs/catalog-admission.md
- Native lane cutover (WP-0006 T05/T06): docs/native-lane-cutover.md
- KeyCape service-auth consumer boundary: docs/service-auth.md
- Approval consume-before-OpenBao (GH-DEC-2026-003): docs/approval-consumption.md
- OpenBao JWT login contract (engine consumer): docs/openbao-jwt-login.md
- Secret-use evidence surface: docs/secret-use-evidence-contract.md
The implementation is a Python package (src/secrets_engine/). OpenBao is
reached only through the bao CLI adapter (openbao.py); the rest of the code
speaks in lanes and guarded plans.
Security Rules
- Do not put raw secret values in Git, State Hub, chat, prompts, issue comments, workplans, or normal logs.
- OpenBao is the backend custody and audit authority.
- Build, test, and production have separate policy boundaries.
- Production live actions fail closed until the durable State Hub action-authorization endpoint is available; local approval mirrors are throwaway-demo material only.
- A privileged production OpenBao call also requires a successful approval-engine CAS consume first. Conflict or unavailability means do not write.
- Temporary bootstrap OpenBao credentials must live outside repos, use mode 0600, be revocable, and be removed after narrower auth is working.