Client Instance Readiness
Use isolated client instances by default: one Vercel web app, one Supabase project, connector secrets, auth users, storage bucket, and optional docs URL per client.
Do not import real client transcripts or documents until every item below is complete.
Required Instance Settings
Set these on the client Vercel app before production smoke tests:
| Variable | Required | Purpose |
|---|---|---|
SABLE_MODE=production | yes | Disables bundled JSON, legacy app-token, and CMA demo fallbacks |
PUBLIC_APP_ORIGIN | yes | Canonical app origin for operator docs and smoke tests |
NEXT_PUBLIC_SUPABASE_URL | yes | Public browser Supabase URL returned by /api/config |
NEXT_PUBLIC_SUPABASE_ANON_KEY | yes | Public anon key returned by /api/config |
SUPABASE_URL | yes | Server-side Supabase API access |
SUPABASE_SERVICE_ROLE_KEY | yes | Server-side route access; never exposed to the browser |
Set connector secrets in the matching Supabase project, not in a shared demo project.
Fail-Closed Checks
Run these checks on every preview before real data:
curl -i "$PUBLIC_APP_ORIGIN/api/config"
curl -i "$PUBLIC_APP_ORIGIN/api/whoami"
curl -i "$PUBLIC_APP_ORIGIN/api/spine"
curl -i "$PUBLIC_APP_ORIGIN/api/chat"
curl -i "$PUBLIC_APP_ORIGIN/api/doc?id=smoke"
curl -i "$PUBLIC_APP_ORIGIN/api/inbox"
curl -i "$PUBLIC_APP_ORIGIN/api/approvals"
curl -i "$PUBLIC_APP_ORIGIN/api/board"
Expected unauthenticated behavior:
/api/configreturns only public Supabase config.- Authenticated app APIs reject without a valid Supabase JWT.
/api/board,/api/ingest, and/api/statusdo not serve CMA memory-store data in production.
Data Boundary Checks
Create two orgs, two projects, one lead, and one non-lead in the client Supabase project.
Verify:
- Non-leads only see projects where they are in
project_members. - Leads see all projects in their own
org_id, never another org. - Restricted documents are visible only to admin/lead users.
- Search results come from the verified viewer's org/project scope, not a caller-supplied
as. - Service-role routes filter by
viewer.person.org_idbefore shaping responses.
Release Gate
Before promoting a client instance, run:
node --test sable-agents-demo/supabase/tests/*.test.mjs sable-agents-demo/web/tests/*.test.mjs
cd sable-agents-demo/docs-site && npm run build
Then run the live smoke tests above against the preview URL and promote only after the preview passes.