secrets-engine/docs/whynot-design-real-publish-closeout.md
tegwick 550ba95a67 Answer the exec-path question: the front door reads the ungoverned duplicate.
ops-warden and railiance-platform asked, independently, which OpenBao location
`secrets-engine exec --catalog whynot-design-npm-publish` reads. Answered from
this repository's own code and catalog with no OpenBao read and no value.

It reads `secret/coulomb/whynot-design/npm/publish` — the legacy, ungoverned
duplicate. `_fetch_value` concatenates the catalog's `mount` and `path` with no
override or fallback, so the proven pilot published from the duplicate and the
lowercase `npm_token` field is the field there. ops-warden's front door names
this repository as exec_owner, so it currently routes callers at a path no CCR
covers.

Recorded in SECRETS-WP-0006 with what a move to the governed lane requires, and
flagged that the duplicate must not be destroyed until the lane moves. Whether
the two locations hold the same value is a value comparison and is not answered
here.

Also records GH-DEC-2026-017 against SECRETS-WP-0008: INTENT.md governs, the
sidecar is derived, the vocabulary is case-insensitive so nothing is re-spelled,
and standard_version comes out of layer.yaml once ops-warden updates the
reference form this repository copied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 02:36:31 +02:00

5.2 KiB

whynot-design real publish closeout

This runbook is the SECRETS-WP-0003 closeout path for turning the whynot-design-npm-publish pilot from a dry-run/demo lane into a real production @whynot/design publish through secrets-engine exec.

No raw npm token, OpenBao token, token accessor, NPM_AUTH_TOKEN, package-token value, or private credential material may be written to Git, State Hub, chat, prompts, workplans, or normal logs.

Current non-secret pointers

Pointer Value
Catalog id whynot-design-npm-publish
Canonical decision e6381a56-6b04-4fd5-b2de-f3ef59cde888
Org/repo coulomb/whynot-design
npm package @whynot/design
npm registry https://forgejo.coulomb.social/api/packages/coulomb/npm/
Catalog mount/path secret/coulomb/whynot-design/npm/publish (ungoverned legacy — see below)
Catalog field npm_token
Injected env var NPM_AUTH_TOKEN

Governance status, 2026-09-21. The catalog mount/path above is the location secrets-engine exec actually reads — confirmed from exec_delivery._fetch_value, which concatenates entry.mount and entry.path with no override — and it is the ungoverned duplicate. The governed lane is platform/workloads/coulomb/whynot-design/npm-publish under CCR-2026-0001, field NPM_AUTH_TOKEN. The lowercase npm_token in the table above is the field at the legacy path, which is why the two records disagreed without either being wrong. Moving to the governed path is a reviewed lane change with its own approval; the steps are recorded in workplans/SECRETS-WP-0006-catalog-lane-adoption.md (2026-09-21). Until that move completes and re-verifies, the legacy path must not be destroyed or wrapped — it is the live publish path.

The decision UUID above is resolved from State Hub in normal operation. A UUID-named local fixture exists only as an offline fallback for throwaway demos.

Source-side preflight

From this repo, with State Hub reachable:

scripts/whynot-real-publish-preflight.sh

Expected source-side result:

  • decision inspect e6381a56-6b04-4fd5-b2de-f3ef59cde888 shows source: hub and APPROVED;
  • policy publication whynot-design-npm-publish resolves to the repo-clamped NPM_AUTH_TOKEN path while netkingdom remains maturity-build;
  • route whynot-design-npm-publish --json returns a pointer only. If OpenBao is not reachable or the value is not provisioned, ready=false is acceptable and must be handled by the operator steps below.

Operator live gates

  1. Create or confirm a dedicated Gitea bot account such as se-whynot-design. Record only non-secret evidence: username, owning org/repo, package scope, creation timestamp, and who confirmed it.
  2. Confirm the bot can publish @whynot/design to the coulomb registry and cannot publish outside the intended org/scope. Record only pass/fail and package names.
  3. Mint the Gitea npm/package token for that bot and place it in a mode-0600 file outside any Git worktree. Do not print the value.
  4. Apply/provision through secrets-engine using approved OpenBao authority:
BAO_ADDR=https://bao.coulomb.social \
  secrets-engine apply whynot-design-npm-publish --stage prod \
  --bootstrap-token-file ~/.secrets-engine/bootstrap/prod-whynot-design.token

BAO_ADDR=https://bao.coulomb.social \
  secrets-engine provision whynot-design-npm-publish --stage prod \
  --field npm_token \
  --from-file ~/.secrets-engine/handoff/whynot-design-npm.token \
  --bootstrap-token-file ~/.secrets-engine/bootstrap/prod-whynot-design.token
  1. Verify without disclosing the value:
BAO_ADDR=https://bao.coulomb.social \
  secrets-engine verify whynot-design-npm-publish \
  --field npm_token --positive --negative \
  --negative-token-file /secure/path/reviewed-unrelated.token \
  --bootstrap-token-file ~/.secrets-engine/bootstrap/prod-whynot-design.token

The unrelated token must represent a reviewed identity outside the lane policy; it is not the bootstrap token and must be held in a separate mode-0600 file outside Git.

  1. In the whynot-design repo, coordinate a real version bump. Run the publish through child-only injection:
BAO_ADDR=https://bao.coulomb.social \
  secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
  1. Confirm the published version appears in the coulomb Gitea npm registry. Record package name, version, registry URL, timestamp, and result only.

ops-warden handoff

ops-warden should route npm publish credential requests here and return a pointer, not a value:

secrets-engine route whynot-design-npm-publish --json

Safe pointer payload:

{
  "catalog_id": "whynot-design-npm-publish",
  "kind": "kv",
  "decision_ref": "e6381a56-6b04-4fd5-b2de-f3ef59cde888",
  "owner": "coulomb/whynot-design",
  "stage": "prod",
  "next_command": "secrets-engine exec --catalog whynot-design-npm-publish -- npm publish"
}

Revocation and cleanup

Track the OpenBao bootstrap token and the Gitea bot package token in hardening-backlog.md. After publish verification, remove any handoff/source token files with shred -u and revoke or rotate the Gitea bot token according to the recorded lifecycle task.