2026-06-29 16:58:16 +02:00
|
|
|
# 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` |
|
2026-07-09 11:38:15 +02:00
|
|
|
| npm registry | `https://forgejo.coulomb.social/api/packages/coulomb/npm/` |
|
2026-06-29 16:58:16 +02:00
|
|
|
| Catalog mount/path | `secret/coulomb/whynot-design/npm/publish` |
|
|
|
|
|
| Catalog field | `npm_token` |
|
|
|
|
|
| Injected env var | `NPM_AUTH_TOKEN` |
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
5. Verify without disclosing the value:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
BAO_ADDR=https://bao.coulomb.social \
|
|
|
|
|
secrets-engine verify whynot-design-npm-publish \
|
|
|
|
|
--field npm_token --positive --negative \
|
2026-08-23 12:33:38 +02:00
|
|
|
--negative-token-file /secure/path/reviewed-unrelated.token \
|
2026-06-29 16:58:16 +02:00
|
|
|
--bootstrap-token-file ~/.secrets-engine/bootstrap/prod-whynot-design.token
|
|
|
|
|
```
|
|
|
|
|
|
2026-08-23 12:33:38 +02:00
|
|
|
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.
|
|
|
|
|
|
2026-06-29 16:58:16 +02:00
|
|
|
6. In the `whynot-design` repo, coordinate a real version bump. Run the publish
|
|
|
|
|
through child-only injection:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
BAO_ADDR=https://bao.coulomb.social \
|
|
|
|
|
secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
7. 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:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
secrets-engine route whynot-design-npm-publish --json
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Safe pointer payload:
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"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](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.
|