* local proxy-key testing via x-dev-repo bypass
`pnpm play` previously couldn't exercise the proxy/router/oss code path
— `resolveProxyModel` early-exits without OIDC credentials, and
`mintProxyKey` always sends an OIDC bearer to `/api/proxy-token`. since
GitHub Actions OIDC only exists in real workflow runs, billing flows
(auto-reload, balance gates, key rotation, OSS subsidy) had no local
feedback loop.
a server-side dev bypass already exists at `app/api/proxy-token/route.ts`
that accepts an `x-dev-repo: owner/repo` header instead of an OIDC bearer
when `NODE_ENV === "development"`. wire the action side so it sends that
header when there are no OIDC credentials AND `API_URL` resolves to
localhost (i.e. the developer is talking to their own `pnpm dev`
server). production is unreachable through this path because vercel
never sets `NODE_ENV=development`.
document the affordance in `wiki/action-tests.md` so the next person
doesn't have to re-discover it (the server bypass had been sitting
there undocumented since the WIP billing rewrite).
verified end-to-end: `PLAY_LOCAL=1 GITHUB_REPOSITORY=pullfrog/app
API_URL=http://localhost:3100 pnpm play …` now logs `» proxy: dev
bypass (x-dev-repo) for pullfrog/app` → `» proxy: router → openrouter/
anthropic/claude-opus-4.7` → `» model: …(proxy)`, mints a real
OpenRouter key against the dev DB, and the agent runs through the
proxy.
* wiki: cross-reference dev proxy-key affordance from main/e2e/stripe
action-tests.md already documents the localhost+x-dev-repo path; mention
it from the natural discovery points so the next person finds it without
spelunking through git history again:
- main.md: resolveProxyModel row in the dependencies table notes the
two auth paths (OIDC bearer in prod, x-dev-repo in dev).
- e2e-testing.md: "When to use this" calls out the lighter-weight
alternative for proxy-only changes.
- stripe.md: new "Loop including the action" subsection in the Dev
workflow section, alongside the existing dev-script and cron-endpoint
loops.
* test preview bypass 2
Co-authored-by: Cursor <cursoragent@cursor.com>
* add apiFetch wrapper with Vercel bypass via query param + header
the template workflow was missing VERCEL_AUTOMATION_BYPASS_SECRET,
so all action API calls to preview deployments hit Vercel's
deployment protection without bypass. this also consolidates the
bypass logic into a single fetch wrapper that applies the secret
as both a query parameter (matching server-side forwarding) and
a header for belt-and-suspenders reliability.
Co-authored-by: Cursor <cursoragent@cursor.com>
* security hardening for Vercel bypass
- redact bypass token from webhook forwarder logs and response body
- remove dead x-preview-api-forward header
- refactor getAllSecrets() to use SENSITIVE_PATTERNS instead of hardcoded list
- enforce https:// on API_URL (localhost exempt for local dev)
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
action API calls to preview deployments were getting 401'd by Vercel's
deployment protection. add x-vercel-protection-bypass header to the 3
server-to-server fetch sites when VERCEL_AUTOMATION_BYPASS_SECRET is set.
Co-authored-by: Cursor <cursoragent@cursor.com>