Secrets
Auth isolation
Separate viewer vs operator Supabase cookie jars (lib/supabase/auth-scope.ts). Theme preview requires operator session.
Database
Enable and keep RLS migrations applied (006+). Service role only on the server.
Cron / jobs
POST /api/internal/jobs/run requires header X-Streamly-Cron-Secret: <STREAMLY_CRON_SECRET>.
Operator login
- First install requires
STREAMLY_INITIAL_ADMIN_EMAILandSTREAMLY_INITIAL_ADMIN_PASSWORD(server-only, neverNEXT_PUBLIC_, password ≥ 16 characters). Only that pair creates and promotes the first operator. - Passwords are hashed by Supabase Auth. Streamly never stores plaintext passwords in application tables.
- After the first operator exists,
/api/admin/loginusessignInWithPasswordand allows access only whenprofiles.is_operator=true. Unknown users are never promoted. In production, the bootstrap password cannot reset an existing operator. - You may remove
STREAMLY_INITIAL_ADMIN_PASSWORDfrom the host after bootstrap. - Configured bootstrap secrets are never returned to the browser.
/api/admin/loginis rate-limited per application instance. Also configure your host firewall/WAF for distributed rate limiting in production.- Public viewer signup does not create operators. The shared operator demo is available only when the public preview explicitly sets
ENABLE_DEMO=true; customer deployments must leave it disabled. There is no Envato verification.