Skip to content

fix(api): auth-gate /api/setup and /api/seed operator endpoints - #174

Open
dirtybits wants to merge 1 commit into
mainfrom
fix/auth-gate-setup-seed
Open

fix(api): auth-gate /api/setup and /api/seed operator endpoints#174
dirtybits wants to merge 1 commit into
mainfrom
fix/auth-gate-setup-seed

Conversation

@dirtybits

Copy link
Copy Markdown
Owner

Summary

POST /api/setup and POST /api/seed were the only operator state-mutating
API endpoints with no authentication at all — no middleware.ts exists and
no route-level auth check, so they were internet-reachable in production.

Concrete risk on a fresh production deploy (empty Postgres):

  • POST /api/seed (no auth, 200 on success): an anonymous caller could
    inject the demo seed skill + version rows into the live skills /
    skill_versions tables (the route only skips when SELECT COUNT(*) FROM skills is non-zero).
  • POST /api/setup: re-runs bootstrapDatabase() DDL against the live DB.

Both are also redundant for schema work: ensureUsdcPurchaseSchema() and
ensureAgentIdentitySchema() already run on the request path, and Vercel
Postgres persists between deployments.

Fix: gate both routes with the exact auth pattern already used by the
equally-operator-facing POST /api/github/skills/discover (and the cron
routes): Bearer CRON_SECRET, constant-time compare, and — matching the
stronger discover variant — fail closed in both production and preview
(preview deployments are internet-reachable). No secret + local development =
open, so the local dev flow is unchanged.

Test Plan

  • npm run format:check — clean (prettier).
  • npm run lint:web — clean (eslint).
  • npm run typecheck — clean (next typegen && tsc --noEmit).
  • npm run test:web — 130 files / 965 tests pass, including:
    • updated web/__tests__/api/setup.test.ts (7 tests): local-open, 500
      passthrough, and 401 fail-closed in production/preview with secret unset,
      missing token, wrong token; 200 with valid token.
    • new web/__tests__/api/seed-route.test.ts (7 tests): same auth matrix +
      seed-into-empty-DB and skip-when-populated behavior.
  • npm exec --workspace @agentvouch/web -- next build --webpack — builds
    successfully (explicit webpack per AGENTS.md bundler-parity gate).

Operational note (deploy)

If anything in the deploy/provisioning flow calls these endpoints in
production or preview (no in-repo callers found — CI, vercel.json, scripts,
and docs were all checked), set CRON_SECRET on the Vercel project; the same
env var is already used by the cron + discover endpoints, so no new secret is
introduced. Until it is set, these two endpoints return 401 in deployed
environments while remaining open locally.

Signing caveat

Committed unsigned: this headless runner has no GPG secret key for the
repo's signing identity (gpg: skipped "andy <dirtybitsofficial@gmail.com>": No secret key) and no 1Password agent. To re-sign before merging:

git fetch origin && git checkout fix/auth-gate-setup-seed
git commit --amend -S --no-edit
git push --force-with-lease

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant