fix(agent): give the Workers deploy path its registry credential #516

Merged
gmackie merged 1 commit from feat/deploy-registry-auth into main 2026-08-28 11:07:48 +00:00
Owner

Completes the registry-auth story. The gap had three homes and this is the last one:

  1. CI workflows — token written to "$HOME/.npmrc" on HOME-less runners, landing in /.npmrc while pnpm read /root/.npmrc (#505).
  2. nix build path — credential now carried in the deploy payload and exported as FG_NPM_TOKEN (#514, agent 0.1.63).
  3. cloudflare-workers path — this PR. It runs pnpm install in a temp checkout and never looked at dep.Registry at all.

ensureForgegraphRegistry writes the @forgegraph scope mapping into that checkout's .npmrc, but nothing wrote an auth line — so pnpm resolved the scope to npm.forgegraf.com and then fetched anonymously, and the registry answered 401.

The error is genuinely misleading: pnpm says "No authorization header was set" and then lists the scope mappings it found, which reads like a missing secret rather than a missing file. And because the nix path had the credential all along, the same deployment could succeed on one platform and 401 on the other. forgegraph → beta (target beta-cf on hetzner-bob) failed this way repeatedly on 2026-08-27.

Appends, never truncates. App repos ship their own .npmrc — ForgeGraph's own carries @preflight:registry and node-linker=hoisted. registry.WriteNpmrc truncates, which suits a CI sandbox but would swap a 401 for an unresolvable scope in a real checkout. Written 0600 since it holds a token; no-op without a credential or when auth for the host is already present; best-effort like its neighbour, so it never fails a deploy.

5 tests: append-preserves-content, create-when-absent, 0600 perms, no-duplicate, no-op-without-credential. go vet clean, agent + registry suites green.

Until this ships I have hand-written /root/.npmrc on hetzner-bob and hetzner-worker to unblock beta deploys — the same invisible node-local config #514 is removing. This lets those be deleted.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CMpzX1b6swjezEptw3T71f

Completes the registry-auth story. The gap had **three** homes and this is the last one: 1. **CI workflows** — token written to `"$HOME/.npmrc"` on HOME-less runners, landing in `/.npmrc` while pnpm read `/root/.npmrc` (#505). 2. **nix build path** — credential now carried in the deploy payload and exported as `FG_NPM_TOKEN` (#514, agent 0.1.63). 3. **cloudflare-workers path — this PR.** It runs `pnpm install` in a temp checkout and never looked at `dep.Registry` at all. `ensureForgegraphRegistry` writes the `@forgegraph` **scope mapping** into that checkout's `.npmrc`, but nothing wrote an **auth line** — so pnpm resolved the scope to npm.forgegraf.com and then fetched anonymously, and the registry answered 401. The error is genuinely misleading: pnpm says *"No authorization header was set"* and then lists the scope mappings it found, which reads like a missing secret rather than a missing file. And because the nix path had the credential all along, **the same deployment could succeed on one platform and 401 on the other**. `forgegraph → beta` (target `beta-cf` on hetzner-bob) failed this way repeatedly on 2026-08-27. **Appends, never truncates.** App repos ship their own `.npmrc` — ForgeGraph's own carries `@preflight:registry` and `node-linker=hoisted`. `registry.WriteNpmrc` truncates, which suits a CI sandbox but would swap a 401 for an unresolvable scope in a real checkout. Written `0600` since it holds a token; no-op without a credential or when auth for the host is already present; best-effort like its neighbour, so it never fails a deploy. 5 tests: append-preserves-content, create-when-absent, 0600 perms, no-duplicate, no-op-without-credential. `go vet` clean, agent + registry suites green. Until this ships I have hand-written `/root/.npmrc` on hetzner-bob and hetzner-worker to unblock beta deploys — the same invisible node-local config #514 is removing. This lets those be deleted. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01CMpzX1b6swjezEptw3T71f
fix(agent): give the Workers deploy path its registry credential
All checks were successful
CI / gitleaks (pull_request) Successful in 6s
CI / storybook (pull_request) Successful in 1m40s
forgegraph/ci CI passed
CI / ci (pull_request) Successful in 10m27s
f01c03b029
The cloudflare-workers deploy runs pnpm install in a temp checkout and
never looked at dep.Registry. ensureForgegraphRegistry writes the
@forgegraph SCOPE mapping into that checkout's .npmrc, so pnpm resolved
the scope to npm.forgegraf.com and then fetched anonymously — 401.

pnpm reports 'No authorization header was set' and then lists the scope
mappings it found, which reads like a missing secret rather than a
missing auth line. The nix build path had the credential all along
(NpmToken -> NixBuild), so the same deployment could succeed on one
platform and 401 on the other. forgegraph -> beta (target beta-cf) failed
this way repeatedly on 2026-08-27.

ensureRegistryAuth APPENDS the auth line rather than writing the file:
app repos ship their own .npmrc with scope mappings and settings that
must survive — registry.WriteNpmrc truncates, which suits a CI sandbox
but would break a real checkout. Written 0600 since it holds a token,
no-op without a credential or when auth for the host is already present,
and best-effort like its neighbour: never fail a deploy over it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMpzX1b6swjezEptw3T71f
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
gmackie/ForgeGraph!516
No description provided.