feat(routing): repoint whynot npm lane to Forgejo
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a06d83-1cbc-71f2-b0dc-e0f48cedae43
This commit is contained in:
parent
efabe526d8
commit
81f28ff814
4 changed files with 128 additions and 16 deletions
|
|
@ -196,19 +196,19 @@ entries:
|
||||||
lane: ceremony
|
lane: ceremony
|
||||||
|
|
||||||
- id: whynot-design-npm-publish
|
- id: whynot-design-npm-publish
|
||||||
title: whynot-design npm publish token (@whynot/design → coulomb Gitea registry)
|
title: whynot-design npm publish token (@whynot/design → coulomb Forgejo registry)
|
||||||
# Publish rights to the package registry — a leaked token is a supply-chain write, not a read (WARDEN-WP-0032-T05).
|
# Publish rights to the package registry — a leaked token is a supply-chain write, not a read (WARDEN-WP-0032-T05).
|
||||||
risk: high
|
risk: high
|
||||||
workload_ref:
|
workload_ref:
|
||||||
applicability: applicable
|
applicability: applicable
|
||||||
unknown_reason: "whynot-design has not published an authoritative workload identity declaration."
|
unknown_reason: "whynot-design has not published an authoritative workload identity declaration."
|
||||||
need_keywords: [whynot-design, whynot, npm, publish, npm_auth_token, gitea, registry, coulomb, package]
|
need_keywords: [whynot-design, whynot, npm, publish, npm_auth_token, forgejo, registry, coulomb, package]
|
||||||
owner_repo: railiance-platform
|
owner_repo: railiance-platform
|
||||||
subsystem: OpenBao
|
subsystem: OpenBao
|
||||||
warden_executes: false
|
warden_executes: false
|
||||||
wiki_ref: wiki/playbooks/whynot-design-npm-publish.md#worker-checklist
|
wiki_ref: wiki/playbooks/whynot-design-npm-publish.md#worker-checklist
|
||||||
canon_ref: net-kingdom/docs/platform-identity-security-architecture.md
|
canon_ref: net-kingdom/docs/platform-identity-security-architecture.md
|
||||||
reviewed: "2026-06-29"
|
reviewed: "2026-09-04"
|
||||||
status: active
|
status: active
|
||||||
delegation:
|
delegation:
|
||||||
mode: native
|
mode: native
|
||||||
|
|
@ -238,9 +238,9 @@ entries:
|
||||||
owner: railiance-platform
|
owner: railiance-platform
|
||||||
automatable: false
|
automatable: false
|
||||||
steps:
|
steps:
|
||||||
- "In the coulomb Gitea/Forgejo registry, revoke the current @whynot/design publish token and generate a new one (scope: package read/write) for the whynot-design publish identity."
|
- "In the coulomb Forgejo registry, revoke the current @whynot/design publish token and generate a new one (scope: package read/write) for the whynot-design publish identity."
|
||||||
- "Write it back: `bao kv put platform/workloads/coulomb/whynot-design/npm-publish NPM_AUTH_TOKEN=@file` (value from a mode-0600 file)."
|
- "Write it back: `bao kv put platform/workloads/coulomb/whynot-design/npm-publish NPM_AUTH_TOKEN=@file` (value from a mode-0600 file)."
|
||||||
- "Verify capabilities-safe, then confirm publish works via `secrets-engine exec --catalog whynot-design-npm-publish -- npm whoami` (value used, not printed)."
|
- "Verify capabilities-safe, then publish a fresh version and confirm it with Forgejo-supported `npm view <package>@<version>` through the governed execution lane (value used, not printed)."
|
||||||
|
|
||||||
- id: policy-nexus-forgejo-source-read
|
- id: policy-nexus-forgejo-source-read
|
||||||
title: Policy Nexus Forgejo private-source repository read token
|
title: Policy Nexus Forgejo private-source repository read token
|
||||||
|
|
@ -325,8 +325,8 @@ entries:
|
||||||
# point is to obtain one). warden runs it interactively as the caller and never
|
# point is to obtain one). warden runs it interactively as the caller and never
|
||||||
# captures the resulting token — the owner tool writes it to the caller's store.
|
# captures the resulting token — the owner tool writes it to the caller's store.
|
||||||
lane: login
|
lane: login
|
||||||
auth_method: "browser OIDC via key-cape / Keycloak"
|
auth_method: "browser OIDC via key-cape / Keycloak at auth/netkingdom"
|
||||||
fetch_command: "bao login -method=oidc role=<domain>"
|
fetch_command: "bao login -no-print -method=oidc -path=netkingdom role=<domain>"
|
||||||
exec_capable: true
|
exec_capable: true
|
||||||
|
|
||||||
- id: ops-bridge-tunnel
|
- id: ops-bridge-tunnel
|
||||||
|
|
|
||||||
|
|
@ -144,13 +144,19 @@ def test_route_find_vault_token_ops_warden_prefers_broker_lane():
|
||||||
|
|
||||||
|
|
||||||
def test_whynot_design_npm_lane_is_concrete_and_resolvable():
|
def test_whynot_design_npm_lane_is_concrete_and_resolvable():
|
||||||
"""The provisioned npm publish lane has no placeholders and reports resolvable."""
|
"""The provisioned Forgejo npm lane is exact, concrete, and resolvable."""
|
||||||
catalog = load_catalog(_repo_catalog())
|
catalog = load_catalog(_repo_catalog())
|
||||||
e = catalog.get("whynot-design-npm-publish")
|
e = catalog.get("whynot-design-npm-publish")
|
||||||
assert e is not None and e.is_active and e.exec_capable
|
assert e is not None and e.is_active and e.exec_capable
|
||||||
assert e.resolvable is True
|
assert e.resolvable is True
|
||||||
|
assert "Forgejo registry" in e.title
|
||||||
|
assert "forgejo" in e.need_keywords
|
||||||
|
assert "gitea" not in e.need_keywords
|
||||||
assert "<" not in e.fetch_command and ">" not in e.fetch_command
|
assert "<" not in e.fetch_command and ">" not in e.fetch_command
|
||||||
assert "platform/workloads/coulomb/whynot-design/npm-publish" in e.fetch_command
|
assert "platform/workloads/coulomb/whynot-design/npm-publish" in e.fetch_command
|
||||||
|
rotation = " ".join(e.rotation.steps)
|
||||||
|
assert "Forgejo-supported `npm view <package>@<version>`" in rotation
|
||||||
|
assert "Gitea" not in rotation
|
||||||
|
|
||||||
|
|
||||||
def test_policy_nexus_source_read_lane_is_exact_high_risk_and_resolvable():
|
def test_policy_nexus_source_read_lane_is_exact_high_risk_and_resolvable():
|
||||||
|
|
@ -183,7 +189,11 @@ def test_generic_and_template_lanes_not_resolvable():
|
||||||
catalog = load_catalog(_repo_catalog())
|
catalog = load_catalog(_repo_catalog())
|
||||||
# generic openbao lane has <FIELD>/<path_template>; login lane has <domain>.
|
# generic openbao lane has <FIELD>/<path_template>; login lane has <domain>.
|
||||||
assert catalog.get("openbao-api-key").resolvable is False
|
assert catalog.get("openbao-api-key").resolvable is False
|
||||||
assert catalog.get("key-cape-oidc-login").resolvable is False
|
login = catalog.get("key-cape-oidc-login")
|
||||||
|
assert login.resolvable is False
|
||||||
|
assert login.fetch_command == (
|
||||||
|
"bao login -no-print -method=oidc -path=netkingdom role=<domain>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_platform_admin_login_lane_is_exact_and_non_value_bearing():
|
def test_platform_admin_login_lane_is_exact_and_non_value_bearing():
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
# whynot-design npm publish token
|
# whynot-design npm publish token
|
||||||
|
|
||||||
Date: 2026-06-29
|
Date: 2026-09-04
|
||||||
Catalog: `whynot-design-npm-publish` (status `active`, `resolvable: true`)
|
Catalog: `whynot-design-npm-publish` (status `active`, `resolvable: true`)
|
||||||
Owner: `railiance-platform` (OpenBao) · provisioning CCR-2026-0001 (commit 8f617fc)
|
Owner: `railiance-platform` (OpenBao) · provisioning CCR-2026-0001 (commit 8f617fc)
|
||||||
|
|
||||||
The `NPM_AUTH_TOKEN` that publishes `@whynot/design` to the coulomb Gitea npm registry
|
> **Rotation required (2026-09-04).** The OIDC role and OpenBao read path are
|
||||||
(`https://gitea.coulomb.social/api/packages/coulomb/npm/`). ops-warden **does not hold
|
> healthy, but the stored credential failed a real Forgejo publish. Version
|
||||||
|
> `@whynot/design@0.4.2` was published and integrity-verified through the
|
||||||
|
> plan-authorized Forgejo admin recovery lane. Treat this dedicated lane as
|
||||||
|
> unverified for writes until its package token is rotated and re-proven.
|
||||||
|
|
||||||
|
The `NPM_AUTH_TOKEN` that publishes `@whynot/design` to the coulomb Forgejo npm registry
|
||||||
|
(`https://forgejo.coulomb.social/api/packages/coulomb/npm/`). ops-warden **does not hold
|
||||||
this token** — it is the access front door: `warden access` proxies the read from OpenBao
|
this token** — it is the access front door: `warden access` proxies the read from OpenBao
|
||||||
**as the caller** and never persists, caches, or logs the value.
|
**as the caller** and never persists, caches, or logs the value.
|
||||||
|
|
||||||
|
|
@ -42,13 +48,20 @@ this token** — it is the access front door: `warden access` proxies the read f
|
||||||
for this lane (SECRETS-WP-0003, decision e6381a56); ops-warden routes to it:
|
for this lane (SECRETS-WP-0003, decision e6381a56); ops-warden routes to it:
|
||||||
```bash
|
```bash
|
||||||
secrets-engine route whynot-design-npm-publish --json # pointer / readiness
|
secrets-engine route whynot-design-npm-publish --json # pointer / readiness
|
||||||
|
secrets-engine exec --catalog whynot-design-npm-publish -- \
|
||||||
|
npm view @whynot/design@<version> version \
|
||||||
|
--registry=https://forgejo.coulomb.social/api/packages/coulomb/npm/
|
||||||
secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
|
secrets-engine exec --catalog whynot-design-npm-publish -- npm publish
|
||||||
```
|
```
|
||||||
|
|
||||||
**ops-warden transparent fallback** — same lane via the `warden access` proxy (fetches as
|
**ops-warden transparent fallback** — same lane via the `warden access` proxy (fetches as
|
||||||
you, holds nothing). Field-verified flags (whynot-design, @whynot/design@0.4.0):
|
you, holds nothing). The project `.npmrc` must point both the `@whynot` scope and
|
||||||
|
token fragment at `forgejo.coulomb.social`:
|
||||||
```bash
|
```bash
|
||||||
# --exec needs the env-var name. The zone-aware policy gate always runs first.
|
# --exec needs the env-var name. The zone-aware policy gate always runs first.
|
||||||
|
warden access whynot-design-npm-publish --field NPM_AUTH_TOKEN \
|
||||||
|
--exec -- npm view @whynot/design@<version> version \
|
||||||
|
--registry=https://forgejo.coulomb.social/api/packages/coulomb/npm/
|
||||||
warden access whynot-design-npm-publish --field NPM_AUTH_TOKEN \
|
warden access whynot-design-npm-publish --field NPM_AUTH_TOKEN \
|
||||||
--exec -- npm publish
|
--exec -- npm publish
|
||||||
warden access whynot-design-npm-publish --field NPM_AUTH_TOKEN --fetch
|
warden access whynot-design-npm-publish --field NPM_AUTH_TOKEN --fetch
|
||||||
|
|
@ -63,9 +76,19 @@ this token** — it is the access front door: `warden access` proxies the read f
|
||||||
`resolvable: true` means the lane is concrete and `--fetch` will run; a template lane
|
`resolvable: true` means the lane is concrete and `--fetch` will run; a template lane
|
||||||
reports `false`.
|
reports `false`.
|
||||||
|
|
||||||
4. **Publish is outward-facing and immutable.** `npm publish` is irreversible and public.
|
4. **Publish is outward-facing and immutable.** Before publishing, confirm that
|
||||||
Even once the token resolves, hold for an explicit operator "yes, publish" — do not
|
`package.json#publishConfig.registry` is exactly the Forgejo URL above, verify the
|
||||||
auto-run it from an agent.
|
intended version and `npm pack --dry-run` contents, and obtain explicit operator
|
||||||
|
approval. `npm publish` is irreversible; do not auto-run it from an agent.
|
||||||
|
|
||||||
|
5. **Record non-secret release evidence.** After the owner publishes, record only the
|
||||||
|
package coordinate (for example `@whynot/design@0.4.2`), registry URL, authenticated
|
||||||
|
install result, and release-content verification. Never record the token or npm
|
||||||
|
configuration generated for its delivery.
|
||||||
|
|
||||||
|
Forgejo advertises `npm view`, search, install, publish, unpublish, and dist-tag
|
||||||
|
support; it does not advertise `npm whoami`. Use the exact-version lookup above
|
||||||
|
rather than treating `npm whoami` failure as a credential failure.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
79
workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md
Normal file
79
workplans/WARDEN-WP-0037-whynot-design-forgejo-npm-lane.md
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
---
|
||||||
|
id: WARDEN-WP-0037
|
||||||
|
type: workplan
|
||||||
|
title: "Repoint the whynot-design npm lane to Forgejo"
|
||||||
|
domain: infotech
|
||||||
|
repo: ops-warden
|
||||||
|
status: active
|
||||||
|
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
|
||||||
|
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.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue