You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 74d11eb
Browse filesBrowse the repository at this point in the historyBrowse files
test(e2e): live provider journeys, production canary, and required checks (#68)
* test(e2e): add live provider journeys and a production canary
Live mode for the locked gate turns the fake provider into a recording proxy
that pins every chat call to one cheap model (Muse Spark 1.3 Contributor by
default) and caps provider calls, while Jev, Exa research, and URL import run
for real. The specs assert response shape, rendered sources, database rows,
and provider health rather than model wording. The production canary checks
the live site, every deployed function's CORS, the ai auth guard, and one
streamed answer as a dedicated capped account.
Database and live jobs now pull Supabase images from ECR, because ghcr.io
rate-limits shared runners.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* ci(db-gate): show why supabase start failed before retrying
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(e2e): require complete live streams and live Jev signals
A 200 Ask stream can still end without its final event, and the Crossfire
test passed even when no Jev signal decision ran. Assert both, and record
the accepted risk that pull-request runs can read the live provider keys.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(canary): check the method and headers a browser preflight needs
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* docs(agents): scope the production canary credential exception
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(crossfire): stop sending client-only turn signals to the server
Once a Jev signal attached to an answer, every later Crossfire request
resent the turn with a `signal` key, and the ai function rejected it as
"transcript[1] is invalid". The live suite caught it. The fake provider
now answers Jev so the credential-free gate exercises the same path.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(full-stack): cover billing, promo codes, data erasure, and exports
- A promo code redeemed in Settings restores AI access for an expired account.
- Signed Stripe webhooks grant and revoke Pro; forged and replayed ones change nothing.
- Delete All My Data erases the account's rows and leaves another account's intact.
- A generated case downloads as a real PDF and DOCX file.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(live): generate a case with every catalog model
The pinned live suite cannot see a production model that times out or
returns invalid JSON. LIVE_MODEL=as-requested makes the proxy forward the
model the Edge Function chose and runs e2e/model-matrix, which picks each
catalog model in the Generate page and prints its provider latency. The
workflow runs daily and on pull requests that touch AI code.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(canary): generate a production case and keep AI checks within the account cap
Main can deploy more than the canary account's 10 AI requests a day, so
deployment runs skip the AI checks; daily and manual runs make them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* ci(model-matrix): run weekly; one run costs about $1
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(canary): check the signed-in app on every production deployment
Deployment runs skip the AI requests to stay under the canary account's
cap, so they now sign in, open Generate, and require Settings to show the
account's Pro plan. That read goes through row-level security, so it
fails on a broken session, and it spends no AI request.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(ai): give provider calls the time research leaves, not a fixed 60 s
Claude Opus 5 needs about 68 s to write a case, so every Opus case
generation hit the 60 s provider timeout and returned 500. Each call now
shares one 140 s request budget, which stays under Supabase's 150 s
response limit. Research, the main call, and its JSON repair retry all use
what is left. The model matrix reproduces the failure and proves the fix.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(ai): keep a finished case when the source-usage check runs late
The post-generation Jev source-usage check shared the request budget, so a
model that finished near the deadline could lose its completed case to a
500. The check now follows only the client's signal and its own 8 s Jev
timeout, and the provider budget drops to 130 s to leave room for it
under Supabase's 150 s limit.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(ai): cover request budget and balanced routing
* test(canary): require complete streamed answers
* docs(testing): keep canary identity private
* docs(testing): describe the shared AI request budget
* test(live): use balanced multi-provider routing
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: AGENTS.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,7 +71,11 @@ CI=1 PORT=18080 PLAYWRIGHT_BASE_URL=http://127.0.0.1:18080 npm run test:e2e:webk
71
71
72
72
- Start bug fixes with a failing test or repeatable browser reproduction when a suitable test layer exists.
73
73
- Stub sessions prove rendering only. Do not call them authenticated backend proof.
74
-
- Never put staging or production credentials in jobs, logs, traces, screenshots, commits, comments, or docs.
74
+
- Never put staging or production credentials in jobs, logs, traces, screenshots, commits, comments, or docs. Two scoped exceptions reach jobs only through GitHub Actions secrets:
75
+
- the protected staging values;
76
+
- the dedicated production canary account (`PROD_CANARY_EMAIL` and `PROD_CANARY_PASSWORD`, a regular user capped at 10 AI requests a day), which Adam approved on 2026-09-24.
77
+
78
+
Neither exception may appear in logs, traces, or screenshots. No other production credential may enter a job.
75
79
- Never substitute the production project when local or staging access is unavailable.
76
80
- Production deployments, data changes, migrations, Edge Function deployments, and secret changes require explicit authorization.
77
81
- A local pass proves only the local commit. Check the current-head GitHub run before calling CI green.
Copy file name to clipboardExpand all lines: docs/operations.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,6 +25,8 @@ Pull requests also start isolated local Supabase for pgTAP and run desktop plus
25
25
26
26
Non-PR runs upload `dist/` briefly and may build a `linux/amd64` and `linux/arm64` Docker image when registry credentials are present. A successful quality run does not by itself prove that an image was pushed.
27
27
28
+
[`.github/workflows/live-e2e.yml`](../.github/workflows/live-e2e.yml) runs the local stack against real providers on pull requests and nightly. [`.github/workflows/model-matrix.yml`](../.github/workflows/model-matrix.yml) generates a case with every catalog model weekly and when AI code changes. [`.github/workflows/prod-canary.yml`](../.github/workflows/prod-canary.yml) checks production after each Vercel production deployment and daily. See [testing.md](testing.md) for all three. Both Supabase-starting jobs pull images from `public.ecr.aws`, because ghcr.io rate-limits shared runners.
29
+
28
30
[`.github/workflows/staging-e2e.yml`](../.github/workflows/staging-e2e.yml) owns protected staging. It accepts eligible successful main-branch quality runs or a manual dispatch from `main`. It runs only when `STAGING_E2E_ENABLED=true` and all protected values exist.
29
31
30
32
## Production image
@@ -111,6 +113,8 @@ Secret names may be documented; values may not. Server-side categories include:
111
113
112
114
Never place server secrets in `VITE_*`, screenshots, traces, logs, comments, commits, or documentation.
113
115
116
+
GitHub Actions secrets: `LIVE_OPENROUTER_API_KEY` and `LIVE_EXA_API_KEY` for live provider tests, and `PROD_CANARY_EMAIL` and `PROD_CANARY_PASSWORD` for the production canary account. The public anon key is the `PROD_SUPABASE_ANON_KEY` repository variable. To rotate the canary password, set it with the Supabase Auth admin API and pipe it into `gh secret set` over stdin.
0 commit comments