Skip to content

Agent credential bootstrap โ€‹

What is this? โ€‹

Two more per-machine credential files come from Secret Manager instead of staying manually assembled, and gcloud stops being a PATH gamble. โ€‹

  • The operator put 24 new secrets into GCP Secret Manager on 2026-08-24 so agent sessions could stop being blocked on missing local credential files. npm run env:bootstrap (tooling/scripts/bootstrap-env.mjs) already pulled .env.local from Secret Manager; this extends it to two more targets that e2e/browser-test tooling reads directly instead of through process.env: ~/.lantern-agent-probe.env (Agent Probe admin creds) and ~/.lantern-test-accounts.env (app + merchant test accounts). Which keys go where lives in one shared list, tooling/shared/credential-files.cjs, so the bootstrap script and lantern doctor can never drift apart on it.
  • Alongside it, gcloud is now resolved to an absolute path (tooling/shared/gcloud.mjs) instead of trusted on PATH. A non-interactive agent shell never sources the Cloud SDK's PATH line in ~/.bashrc (it lives after the interactive-shell guard's early return, confirmed by reading the file: a bare shell hits that return on line 9 and never reaches the SDK source line near line 125). A session hit exactly this today and came within one step of telling the operator she needed to re-authenticate when she already was.
  • ./lantern doctor now reports on both new files: missing, wrong permissions (want 0600), present but missing specific keys, or present and complete, each with the exact fix command. Stays severity warning, never a gate, so a fresh clone with neither file still exits 0 (the onboarding-routing rule: a newcomer is never told they are blocked on credentials).

What is the current state? โ€‹

All three pieces are built, live-verified, and pushed; nothing is deferred. โ€‹

  • npm run env:bootstrap created both files for real on this machine: ls -l confirmed mode 0600 for both (.lantern-agent-probe.env at 190 bytes, .lantern-test-accounts.env at 624 bytes), all 24 secrets fetched with zero failures.
  • The e2e script that actually needs these files was checked against the real one: tooling/e2e/admin-signin-tier.e2e.mjs's own parseEnv correctly reads AGENT_PROBE_EMAIL as a non-empty string out of the probe file (value never printed; only presence and length checked).
  • ./lantern doctor reports both files, and all four report states (missing / wrong mode / missing keys / complete) were exercised against synthetic scratch files, not just reasoned about, per the safe-automation skill's checklist.
  • The concurrency question the safe-automation skill requires asking ("what happens when three of these run at once?") was answered and then tested for real: six concurrent Node processes racing on one synthetic target file, using the exact pid-suffixed-tmp-plus-atomic-rename mechanism the real writer uses, produced one clean uncorrupted result with zero leftover tmp files.
  • Full scenario list, real commands, and real captured output: docs/engineering/testing/runs/agent-credential-bootstrap/README.md.
  • Both files are gitignored (defensively; they live at $HOME, outside the repo tree entirely, so git never saw them regardless) and confirmed invisible to git status.
  • Secret names were confirmed against gcloud secrets list --project lantern-app-dev rather than trusted from the brief. All 24 requested names matched exactly; zero renames were needed.
  • 2026-06-12-onboarding-bootstrap-cli-design.md: the original design spec behind lantern doctor / lantern setup / bootstrap-env.mjs. This project extends that design with two more bootstrap targets; it does not replace any of it.
  • #858: feat(onboarding): finish-line hook, doctor-green prints the day-one path: a different, unbuilt concern (a hook that fires once doctor goes fully green), not overlapping with this project's scope.
  • The browser-test skill names exactly which keys each file needs and which scripts read them; the safe-automation skill's concurrency question shaped the pid-suffixed tmp-file write. Both were read before building, per this project's own instructions.

Found but deliberately not fixed. โ€‹

  • mergeIntoEnvFile (the pre-existing .env.local writer in bootstrap-env.mjs) uses a non-pid-suffixed tmp path (${filePath}.tmp), so two concurrent env:bootstrap runs could in principle interleave on that one write: the same class of race this project's own new writer (writeSecretFile) was built to avoid. Not touched here: it is pre-existing, untouched-by-incident behavior outside the three pieces asked for, and the fix is a two-line change if picked up later.
  • Several other scripts shell out to bare gcloud: tooling/scripts/onboard-grant.mjs, tooling/scripts/set-admin-role.mjs, services/jobs/ingest-invoices/src/authSetup.js, assorted deploy:dev package.json scripts, and a handful of .sh setup scripts. Only bootstrap-env.mjs and lantern.mjs's doctor were switched to the resolver, because those are the two an agent session runs non-interactively today; the others are human-run, interactive-shell tools (deploys, onboarding grants) where PATH already resolves correctly. Widening the fix to them was judged out of scope for this side quest rather than silently left for someone to rediscover.
  • An ad hoc gcloud ... command typed directly into a shell (not through either fixed script) still needs its full path or PATH support in a non-interactive agent shell. The operator's own preference was to resolve this in the tooling rather than edit her shell profile, which is what this project did; extending ~/.bashrc to export the Cloud SDK's PATH unconditionally (outside the interactive-shell guard) would additionally cover that ad hoc case, but editing her shell profile was explicitly out of scope without her word, so it is named here as a recommendation, not done.

Built with VitePress