page:docs-specs-platform-gaps-phase0-g3-npm-token-restriction
G3 record: restricting the organization secret `NPM_TOKEN` (spec 15 §4.3 G3) reference
The WP-RN-04 secret audit (publish-guards.md, "Secret audit") found NPMTOKEN at organization level with visibility all, which makes a working npmjs token readable by every repository in the organization, including a5c-ai/fabric. Spec 15 G3 ("fabric's repo secrets contain no npmjs token") therefore does not hold at organization level until the secret is restricted to the repositories that legitimately publish to npmjs.
G3 record: restricting the organization secret `NPM_TOKEN` (spec 15 §4.3 G3)
**Status: PENDING OWNER UI ACTION — not changed.** Decided by the owner at breakpoint phase0.npmjs-org on 2026-09-28 ("Restrict now (Recommended)"); the change itself requires the GitHub organization UI, so nothing was modified. This file reproduces the orchestrator's record of the attempt (g3-npm-token-restriction.json) so the procedure, verification and rollback live next to the other phase-0 records.
| Field | Value |
|---|---|
| Secret | NPM_TOKEN |
| Organization | a5c-ai |
| Owner decision | Restrict now (Recommended) — breakpoint phase0.npmjs-org, 2026-09-28 |
| Status | PENDING OWNER UI ACTION — not changed |
| Observed (read-only) | visibility all; updated_at 2026-05-20T09:36:12Z; organization repositories 133; a5c-ai/fabric repository id 1360374425 |
Why
The WP-RN-04 secret audit (publish-guards.md, "Secret audit") found NPM_TOKEN at organization level with visibility all, which makes a working npmjs token readable by every repository in the organization, including a5c-ai/fabric. Spec 15 G3 ("fabric's repo secrets contain no npmjs token") therefore does not hold at organization level until the secret is restricted to the repositories that legitimately publish to npmjs.
Attempt (API, failed by design of the endpoint)
gh api -X PUT orgs/a5c-ai/actions/secrets/NPM_TOKEN with {visibility: 'selected', selected_repository_ids: [132 ids = every org repo except a5c-ai/fabric]} → **HTTP 422** encrypted_value, key_id weren't supplied. The REST endpoint requires re-supplying the secret value to change visibility; the orchestrator does not hold the token and must not handle it. No change was made.
Owner procedure (GitHub UI; the value is not re-entered)
GitHub → Organization a5c-ai → Settings → Secrets and variables → Actions → NPM_TOKEN → Repository access → **Selected repositories** → select every repository that publishes to npmjs (at minimum a5c-ai/babysitter and the babysitter-* plugin repositories) and leave a5c-ai/fabric **unselected** → Save.
Verification (read-only)
gh api orgs/a5c-ai/actions/secrets/NPM_TOKEN --jq .visibility
# => selected
gh api orgs/a5c-ai/actions/secrets/NPM_TOKEN/repositories --paginate --jq '.repositories[].full_name' | grep -c fabric
# => 0Rollback
Repository access → **All repositories** (value unchanged).
Interaction with the fabric guards
Until the restriction is applied, the inherited public-train workflows .github/workflows/publish-packages-from-tag.yml and .github/workflows/fix-npm-tags.yml still reference secrets.NPM_TOKEN; the CI guard (scripts/ci/publish-isolation-guard.cjs) reports them as legacy-train notices, and FABRIC_PRIVATE_TRAIN=1 turns them into hard findings. WP-RN-07 retargets those workflows at Artifact Registry; the restriction here is the belt to that suspenders.