Skip to main content

Deployment

Vercel, one project per app, deployed from main.

Environment

Secrets live in Vercel environment variables and in /opt/ai4boards/.sanctum-ops.env on the ops host. Never in the repository, never in chat.

The ops file is read as data by run-with-ops-env.mjs, never sourced — a connection string contains & and ?, and sourcing one lets the shell split the line and echo the password. That has happened once.

VariableUsed by
DATABASE_URLapp — must point at a role without BYPASSRLS
ADMIN_DATABASE_URLadmin console only
BEDROCK_MODEL_IDan au. inference profile
CRON_SECRETuser-gui, and the ops host scheduler
STRIPE_SECRET_KEYbilling

Scheduled work

Vercel Hobby allows two daily crons, which is not enough — the cycle tick needs to run every five minutes. scripts/scheduler.sh runs from the ops host instead, with TZ=Australia/Sydney set in the script: CRON_TZ in a crontab changes when the entry fires, not the timezone the job reads.

Before believing a pricing change worked

node scripts/stripe-verify.mjs

Confirms every plan and pack points at a live Price, in AUD, GST-exclusive, at the catalogue amount, with the right interval — and that the ladder still gives better value at higher tiers. Non-zero exit, so it can gate a deploy.