kickoff-intake
kickoff-intake is deliberately unusual among SABLE's Edge Functions: it is the only public,
unauthenticated surface in the entire system. A stakeholder opens an invite link
(interview.html#t=<token>) with no SABLE login at all, and works through a short, adaptive AI
interview (or fills a form instead).
Auth model: a token, not a JWT
Because there is no logged-in user, config.toml sets verify_jwt = false for this function —
authentication is a high-entropy invite token, checked by hash lookup, not a Supabase session.
This is a deliberate, narrow exception to the JWT-everywhere pattern the rest of the app follows,
scoped as tightly as the function's own write/read boundaries below make it.
What it can read and write — and nothing more
- Write-only to its own interview's rows. The function cannot touch any other interview, project, or spine data.
- Returns no spine data beyond the project's display name and the stakeholder's own name — nothing about the account, other stakeholders, or SABLE's broader state leaks through this surface.
- On completion, it writes one
sourcesrow (type = 'manual',external_id = 'kickoff:<id>') — the provenance rootinterview-synthesizelater reads.
Hardening, because this is the one function anyone on the internet can reach
- Token hash lookup (never a plaintext token comparison).
- Expiry and revoke checks on every request.
- A per-interview rate limit (20 turns/minute).
- Body-size caps: 6,000 characters for a single answer, 60,000 for the full rendered transcript stored as the source.
- An audit trail on every event.
The interview itself
The canonical themes an interview must cover — success criteria, pain points, risks/concerns,
data/access, and scope/priorities — are built in, so the conversational interviewer works with
zero seeding even for a brand-new project. A project or org can override/extend these via
interview_questions, but nothing has to be configured for a first interview to run.
Where the code lives
sable-agents-demo/supabase/functions/kickoff-intake/index.tssable-agents-demo/supabase/functions/config.toml— theverify_jwt = falseexception for this functionsable-agents-demo/web/interview.htmlsable-agents-demo/web/api/kickoff.js,_kickoff.js— the invite-link creation side