--- id: WARDEN-WP-0037 type: workplan title: "Repoint the whynot-design npm lane to Forgejo" domain: infotech repo: ops-warden status: active flavor: planning owner: codex topic_slug: whynot-design-forgejo-npm-lane created: "2026-09-04" updated: "2026-09-04" state_hub_workstream_id: "42a097db-1c24-558e-a724-030bb2b4443e" --- ## Verify the existing credential against Forgejo ```task id: WARDEN-WP-0037-T01 status: done priority: high state_hub_task_id: "afc4d325-1c6d-5c25-aaf7-2118aa8f86c6" ``` Use only the governed execution transport to test the existing publish identity against the canonical Forgejo npm endpoint. Do not print or persist the token. 2026-09-04: `warden plan` classified the exact verification as autonomous and selected this lane. A contained login using the documented `whynot-design-workload-kv-read` role proved `read` on the exact OpenBao data path, and the governed child proved the secret is present. A real 0.4.2 publish through that credential then failed. No value was printed or persisted and each contained session self-revoked. The lane therefore needs token rotation, not an OpenBao policy repair. ## Repoint the catalog and playbook ```task id: WARDEN-WP-0037-T02 status: done priority: high state_hub_task_id: "7ceb2f74-496c-54e8-bf5a-3c49f994ff23" ``` Replace the retired Gitea endpoint and discovery language with Forgejo while preserving the established OpenBao path, field, and least-privilege boundary. This delivers the npm facet of routed intake `01a06e07-f2f9-7586-9745-b359eb0025b6`; its inter-hub SSH facet remains separate. Completed 2026-09-04. The catalog title, discovery keywords, rotation guidance, and worker playbook now name the canonical Forgejo registry at `https://forgejo.coulomb.social/api/packages/coulomb/npm/`. The OpenBao path, field, owner, native-exec pointer, and high-risk boundary are unchanged. A regression assertion prevents the retired Gitea discovery term and guidance from returning. ## Prove routing and publication ```task id: WARDEN-WP-0037-T03 status: wait priority: high needs_human: true intervention_note: "Rotate the dedicated Forgejo package token, then prove a fresh publish and exact npm view through this lane." state_hub_task_id: "a8b1b855-ab34-5835-b9fd-5f48bc0b6817" ``` Pass catalog and routing tests, verify the checkout route, and record the exact Forgejo package release proven through the lane. 2026-09-04: repo-local verification is complete: the checkout route ranks `whynot-design-npm-publish` first for a Forgejo npm publish need, reports the canonical Forgejo title and verification command, all focused routing/access/proxy tests pass (`145 passed`). The sibling repo's `@whynot/design@0.4.2` release (105 files; IR `designVersion` 0.4.2; five visual tests pass) was published through the plan-authorized `forgejo-admin-api-token` one-time recovery lane. An authenticated exact-version lookup proved that Forgejo's remote integrity matches the local dry-run. T03 waits only on rotating the dedicated package token and proving the next fresh version through `whynot-design-npm-publish`; the package migration itself is complete. **2026-09-09 — field claim corrected, path routed.** `secrets-engine` (msg `15f0c0ca`) corrected two things and declined a third, all correctly. The KV field is `npm_token`. `NPM_AUTH_TOKEN` is the environment variable their publication-scope policy injects, and ops-warden had copied the env var in as the field name — so the catalog's `fetch_command` named a field that does not exist and could only ever have failed. Corrected in `registry/routing/catalog.yaml` and `wiki/playbooks/whynot-design-npm-publish.md` from the owner's statement rather than re-derived here. This was `ADR-0001`'s failure mode rather than a typo: a pointer layer restating an owner's procedure and getting a detail wrong. The endpoint claim already agreed; `delivery_config.npm.registry` has been the Forgejo URL throughout. The **path** is routed to `railiance-platform` and the catalog is unchanged pending their answer. Which location backs the lane for reads is custody state they own; `secrets-engine` has no lane read authority to confirm it and refused to rewrite a production lane pointer from a coordination message (`SECRETS-WP-0006-T06`). Their reasoning is right, and asserting our own pointer is authoritative because it is ours would route around it. The ask names a location only and flags that a `bao kv get` answer would be the 2026-07-16 disclosure vector on a `risk: high` lane. `ready: false` is not being read as path evidence: a source checkout with no production authority reports not-ready regardless of which path the catalog names. T03 still waits on the human rotation of the dedicated Forgejo package token; the path question does not block that, it determines whether the pointer is correct once it rotates.