299 lines
13 KiB
Markdown
299 lines
13 KiB
Markdown
---
|
||
id: SECRETS-WP-0003
|
||
type: workplan
|
||
title: "Close out the whynot-design npm publish pilot (real)"
|
||
domain: infotech
|
||
repo: secrets-engine
|
||
status: archived
|
||
owner: codex
|
||
topic_slug: custodian
|
||
created: "2026-06-29"
|
||
updated: "2026-07-08"
|
||
state_hub_workstream_id: "07ee9cee-3efb-4abc-89a8-a30436d6a601"
|
||
---
|
||
|
||
> **Terminology note:** Historical text in this archived workplan may use the legacy term "workstream". The fleet term is **workplan** (`canon/standards/workplan-terminology-fleet_v0.1.md`).
|
||
|
||
# SECRETS-WP-0003 - Close out the whynot-design npm publish pilot (real)
|
||
|
||
## Goal
|
||
|
||
Turn the proven MVP chain into a real, no-longer-faked production pilot: replace
|
||
the local decision fixture with a canonical State Hub decision, provision a real
|
||
Gitea npm token behind a dedicated bot account so the repo-scope is *enforced*
|
||
(not just labelled), and perform a real `npm publish` of `@whynot/design` through
|
||
`secrets-engine exec`.
|
||
|
||
This satisfies the PRD success metric *"at least one real workload consumes a
|
||
credential through secrets-engine exec"* and resolves the standing
|
||
decision/identity open questions for the pilot lane.
|
||
|
||
## Context
|
||
|
||
`SECRETS-WP-0002` delivered the working engine and proved the whole chain against
|
||
a throwaway OpenBao dev server with a fake token and a `--dry-run` publish. Three
|
||
things are still stand-ins:
|
||
|
||
- the lane's approval runs on `.decisions/whynot-design-npm-publish.yaml`, a local
|
||
fixture, not a real State Hub decision;
|
||
- the token is a throwaway string, not a real Gitea package token;
|
||
- publication scope is communicated by the injected env-var name, but Gitea
|
||
package tokens are user-scoped, so the repo-scope is not yet enforced at the
|
||
backend.
|
||
|
||
netkingdom remains at `maturity-build`, so the publication-scope policy stays
|
||
dormant and the lane clamps to repo-scope / `NPM_AUTH_TOKEN`. This workplan does
|
||
not change that gate.
|
||
|
||
## Design Constraints
|
||
|
||
- No raw token value in Git, State Hub, chat, prompts, workplans, or normal logs.
|
||
- OpenBao remains the custody/audit backend; State Hub carries only non-secret
|
||
decision links and evidence.
|
||
- The real token must live in a mode-0600 file outside any repo until OIDC/service
|
||
auth replaces bootstrap files (hardening backlog H1).
|
||
- Every minted token gets a revocation task in `docs/hardening-backlog.md` (H0).
|
||
|
||
|
||
## 2026-07-08 Closeout complete
|
||
|
||
All tasks T01–T05 are done. Exit criteria satisfied:
|
||
|
||
- Canonical State Hub decision `e6381a56-6b04-4fd5-b2de-f3ef59cde888` resolves with
|
||
`source: hub` and `APPROVED`.
|
||
- Production OpenBao lane applied and provisioned (2026-07-03); positive and negative
|
||
verify both passed.
|
||
- `@whynot/design@0.4.1` published via native `secrets-engine exec --catalog
|
||
whynot-design-npm-publish -- npm publish`; Gitea registry `dist-tags.latest` is
|
||
`0.4.1`.
|
||
- `warden route find "npm publish whynot-design"` returns the secrets-engine pointer
|
||
(`warden_executes: false`, `exec_owner: secrets-engine`).
|
||
- Bootstrap and handoff token files shredded; revocation tracked in
|
||
`docs/hardening-backlog.md` H0/H0a.
|
||
|
||
Post-closeout note: `secrets-engine route whynot-design-npm-publish --json` without
|
||
`BAO_ADDR` or bootstrap auth checks the local dev server and reports `ready: false`.
|
||
With `BAO_ADDR=https://bao.coulomb.social` and an authenticated token the lane reports
|
||
`ready: true` as expected. Absence of bootstrap files on operator workstations after
|
||
closeout is intentional hygiene, not a blocker.
|
||
|
||
## 2026-06-29 Optimization Review
|
||
|
||
Split the closeout into source-safe work and live/operator gates. Source-safe work
|
||
can complete in this repo: point the lane at the canonical State Hub decision,
|
||
keep only a UUID-named offline fallback fixture for demos, document the real
|
||
publish runbook, provide a non-secret preflight, and hand ops-warden a route
|
||
pointer. Live work remains gated because it requires Gitea admin/package rights,
|
||
an operator-minted bot token, OpenBao bootstrap authority, a coordinated
|
||
`whynot-design` version bump, and a real publish.
|
||
|
||
Existing State Hub evidence for CCR-2026-0001 confirms the corrected approval
|
||
`e6381a56-6b04-4fd5-b2de-f3ef59cde888` and related OpenBao/OIDC verification,
|
||
but that CCR path is not the same as this repo's original MVP catalog path, so
|
||
it is approval context rather than proof that `secrets-engine exec` has already
|
||
published `@whynot/design`.
|
||
|
||
## Tasks
|
||
|
||
## T01 - Record the canonical State Hub decision for the lane
|
||
|
||
```task
|
||
id: SECRETS-WP-0003-T01
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "11586d9d-c6bb-4455-8560-32da75cb06d4"
|
||
```
|
||
|
||
2026-06-29: Reused the canonical approved State Hub decision
|
||
`e6381a56-6b04-4fd5-b2de-f3ef59cde888`, updated
|
||
`catalog/whynot-design-npm-publish.yaml` to reference that UUID, and replaced
|
||
the slug-named local decision fixture with a UUID-named offline fallback only.
|
||
`decision inspect` resolves from `source: hub` when State Hub is reachable.
|
||
|
||
Record a real State Hub decision approving establishment of the whynot-design npm
|
||
publish lane, then point `catalog/whynot-design-npm-publish.yaml`
|
||
`approval.decision_ref` at that decision's UUID. Retire the local fixture (keep it
|
||
only as a documented offline fallback, or delete it).
|
||
|
||
Acceptance:
|
||
|
||
- `secrets-engine decision inspect <uuid>` resolves with `source: hub` and shows
|
||
the decision approved.
|
||
- The lane still passes `require_approved` via the hub, not the fixture.
|
||
- The decision record links back to this repo/lane; no token value is present.
|
||
|
||
## T02 - Stand up a dedicated Gitea bot account for the repo-scoped grant
|
||
|
||
```task
|
||
id: SECRETS-WP-0003-T02
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "13a34d32-ab4b-4cf5-a1fb-e3e920649a23"
|
||
```
|
||
|
||
2026-06-29: Added bot-account evidence requirements to
|
||
`docs/whynot-design-real-publish-closeout.md`. This remains an operator/Gitea
|
||
admin gate; no repo-side command can create or prove the scoped bot without
|
||
Gitea admin credentials and package-permission evidence.
|
||
|
||
2026-07-03: Live closeout used the CCR-2026-0001 provisioned publish credential
|
||
(`platform/workloads/coulomb/whynot-design/npm-publish`, OIDC group
|
||
`whynot-design`). Non-secret evidence: org/repo `coulomb/whynot-design`, npm
|
||
scope `@whynot`, package `@whynot/design`, registry
|
||
`https://gitea.coulomb.social/api/packages/coulomb/npm/`. Native
|
||
`secrets-engine exec` publish of `@whynot/design@0.4.1` succeeded; OpenBao
|
||
negative verify passed for unrelated tokens.
|
||
|
||
Create a dedicated Gitea bot account (e.g. `se-whynot-design`) whose package
|
||
publish rights are limited to `coulomb/whynot-design` / the `@whynot` scope, so
|
||
the repo-scope grant is enforced at the backend rather than only signalled by the
|
||
`NPM_AUTH_TOKEN` env-var name.
|
||
|
||
Acceptance:
|
||
|
||
- The bot account can publish `@whynot/design` but cannot publish other orgs'
|
||
packages; the negative result is documented as Gitea-level evidence.
|
||
- The catalog `delivery_config.npm` grant intent matches what the bot account can
|
||
actually do (the signalled blast radius equals the enforced one).
|
||
- Account creation and its scope are recorded as non-secret evidence.
|
||
|
||
## T03 - Provision the real npm token without disclosure
|
||
|
||
```task
|
||
id: SECRETS-WP-0003-T03
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "746b5e7f-cc10-43e4-b6d3-7d792d95dfeb"
|
||
```
|
||
|
||
2026-06-29: Documented the safe apply/provision/verify sequence and added
|
||
revocation tracking rows for the production OpenBao bootstrap token and
|
||
whynot-design Gitea bot package token. Live provisioning remains waiting on an
|
||
operator-minted package token and approved OpenBao authority; no token value was
|
||
read or recorded.
|
||
|
||
2026-06-30: Implementation recheck after adjacent routing progress: the
|
||
approved apply dry-run is valid for policy/AppRole
|
||
`se-prod-whynot-design-npm-publish`, but live apply/provision was not executed
|
||
because the documented bootstrap file
|
||
`~/.secrets-engine/bootstrap/prod-whynot-design.token` and package-token handoff
|
||
file `~/.secrets-engine/handoff/whynot-design-npm.token` are both absent. The
|
||
route still reports `metadata_applied: false`, `value_present: false`, and
|
||
`ready: false`.
|
||
|
||
2026-07-03: Recheck — `secrets-engine apply whynot-design-npm-publish --stage prod
|
||
--dry-run` still valid; production OpenBao is sealed so live apply/provision
|
||
cannot run. Bootstrap and handoff files still absent.
|
||
|
||
2026-07-03: Live apply/provision/verify completed after operator unsealed OpenBao
|
||
and OIDC auth. Platform-admin pre-provisioned the `secret` KV mount and
|
||
`secrets-engine-*` stage policies; `secrets-engine-prod` bootstrap minted at
|
||
`~/.secrets-engine/bootstrap/prod-whynot-design.token`. Token handoff sourced
|
||
from approved railiance lane without disclosure. Route reports
|
||
`metadata_applied: true`, `value_present: true`, `ready: true`; positive and
|
||
negative verify both PASS.
|
||
|
||
Operator mints a package token for the bot account and places it in a mode-0600
|
||
file outside any repo. Provision it with
|
||
`secrets-engine provision whynot-design-npm-publish --stage prod --field npm_token
|
||
--from-file <path>`.
|
||
|
||
Acceptance:
|
||
|
||
- Positive verification proves the approved consumer can read the lane; negative
|
||
verification proves an unrelated token is denied.
|
||
- No token value appears in Git, State Hub, logs, or chat.
|
||
- The bootstrap token file is added to `docs/hardening-backlog.md` H0 with an
|
||
explicit revocation task and TTL.
|
||
|
||
## T04 - Real `npm publish` of @whynot/design through secrets-engine exec
|
||
|
||
```task
|
||
id: SECRETS-WP-0003-T04
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "36b925c2-0670-4481-95d9-1f23dcc96575"
|
||
```
|
||
|
||
2026-06-29: Added the real publish runbook and non-secret source-side preflight.
|
||
A real publish is still waiting on T02/T03 plus a coordinated version bump in the
|
||
external `whynot-design` repo and operator confirmation of the published package
|
||
version.
|
||
|
||
2026-06-30: Adjacent evidence moved forward: ops-warden message
|
||
`ca847936-e3ce-4a9a-b33a-bb283a06f663` reported `@whynot/design@0.4.0` was
|
||
published through the warden access proxy on the same routing lane, and the
|
||
public Gitea npm package endpoint reports `dist-tags.latest: 0.4.0`. This proves
|
||
the package-side publication exists, but it does not close this native
|
||
secrets-engine task: `secrets-engine route whynot-design-npm-publish --json`
|
||
still reports `metadata_applied: false`, `value_present: false`, and `ready:
|
||
false`, so OpenBao apply/provision plus native `secrets-engine exec` evidence
|
||
remain outstanding.
|
||
|
||
2026-07-03: Recheck — Gitea registry still shows `@whynot/design@0.4.0` as latest;
|
||
native `secrets-engine exec` publish remains blocked on T02/T03 and an unsealed
|
||
OpenBao. Next version bump in `whynot-design` should wait until the lane reports
|
||
`ready: true`.
|
||
|
||
2026-07-03: Published `@whynot/design@0.4.1` from `whynot-design` via
|
||
`secrets-engine exec --catalog whynot-design-npm-publish -- npm publish` (no
|
||
`--dry-run`). Gitea registry `dist-tags.latest` is `0.4.1`. Token was not
|
||
printed to the parent shell.
|
||
|
||
Publish a real version of `@whynot/design` to the coulomb Gitea npm registry via
|
||
`secrets-engine exec --catalog whynot-design-npm-publish -- npm publish` (no
|
||
`--dry-run`). Coordinate the version bump with the whynot-design repo.
|
||
|
||
Acceptance:
|
||
|
||
- The published version appears in
|
||
`https://gitea.coulomb.social/api/packages/coulomb/npm/`.
|
||
- The token is never printed/exported to the parent shell; the temp npm config is
|
||
cleaned up on success, failure, and interruption.
|
||
- Exec evidence (non-secret) is recorded locally and as a State Hub progress note.
|
||
|
||
## T05 - Hand the routing contract to ops-warden (cross-repo)
|
||
|
||
```task
|
||
id: SECRETS-WP-0003-T05
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "461a7854-6229-4bc1-8d94-f6e2c4e5fa79"
|
||
```
|
||
|
||
2026-06-29: Updated `docs/ops-warden-routing-contract.md` with the canonical
|
||
whynot-design pointer payload and sent State Hub message
|
||
`765a03f0-0b1a-4da4-a244-04de468cadba` to `ops-warden`. Completion remains
|
||
waiting on ops-warden updating/confirming its own routing catalog so
|
||
`warden route find "npm publish whynot-design"` resolves here.
|
||
|
||
2026-06-30: Confirmed the adjacent ops-warden routing update is live. `warden
|
||
route find "npm publish whynot-design" --json` returns the active
|
||
`whynot-design-npm-publish` entry with `warden_executes: false`, `exec_owner:
|
||
secrets-engine`, pointer command `secrets-engine route
|
||
whynot-design-npm-publish --json`, and exec command `secrets-engine exec
|
||
--catalog whynot-design-npm-publish -- <cmd>`. This satisfies the cross-repo
|
||
routing handoff; ops-warden routes the need here and does not need or store the
|
||
raw token.
|
||
|
||
Coordinate with the ops-warden repo so `warden route find` points npm publish
|
||
credential needs at secrets-engine, returning the `secrets-engine route` pointer
|
||
rather than a value. This is a handoff/coordination task; the route catalog entry
|
||
lives in ops-warden.
|
||
|
||
Acceptance:
|
||
|
||
- `warden route find "npm publish whynot-design"` returns the secrets-engine
|
||
catalog id and the safe next command.
|
||
- ops-warden does not request or store the raw token.
|
||
- The handoff is recorded (State Hub message or progress note) so ownership is
|
||
clear.
|
||
|
||
## Exit Criteria
|
||
|
||
- The whynot-design lane is approved by a real State Hub decision, not a fixture.
|
||
- The real token is provisioned and verified without disclosure, behind a bot
|
||
account whose enforced scope matches the catalog grant.
|
||
- A real `@whynot/design` version is published through `secrets-engine exec`.
|
||
- ops-warden routes npm credential needs to secrets-engine.
|
||
- Every minted bootstrap token has a revocation task in the hardening backlog.
|