Operate
Deployment
Deploy the web and API services with separate trust boundaries.
Required topology
- Deploy the API service behind TLS with database and shared rate-limit access.
- Set NODE_ENV=production and an explicit public listener such as HOST=0.0.0.0.
- Configure server-only provider, Stripe, hashing, session, and observability secrets.
- Set ERROR_MONITOR_WEBHOOK_URL to a plain HTTPS endpoint that accepts SkillRouter JSON error events, and set a separate ERROR_MONITOR_WEBHOOK_TOKEN of at least 32 characters; it is not a Sentry DSN.
- Set DASHBOARD_ORIGINS to the exact deployed web origin and verify credentialed CORS.
- Set TRUST_PROXY_CIDRS to the exact reverse-proxy ranges allowed to supply forwarding headers.
- Run database migrations and curated seed data before serving traffic.
- Build the web app with explicit bare HTTPS API and site origins plus NEXT_PUBLIC_SKILLROUTER_DEMO_MODE=false. Do not add paths, credentials, queries, or fragments.
- Verify session-cookie origin, CORS, Stripe webhook signatures, health checks, and kill switches.
Production gates
- Keep OPENROUTER_PRODUCTION_RESALE_ENABLED=false until commercial authorization is recorded.
- Treat environment flags as hard upper bounds and enable the matching audited database flags separately.
- Keep AUTO_SETUP_DATABASE=false and run compiled db:migrate and db:seed as separate deployment jobs.
- Set per-request output limits and account, key, token, concurrency, and spend controls.
- Use a shared production rate-limit store; do not depend on process memory.
- Alert on daily upstream spend, provider failure rate, margin anomalies, and stream disconnects.
- Alert on error_monitor_delivery_failure; network errors and non-2xx webhook responses increment it.
- Test backup restoration and payment-ledger reconciliation before launch.
Stripe webhook
Register https://api.useskillrouter.com/webhooks/stripe with its own signing secret. A checkout redirect does not credit the ledger.
checkout.session.completed
checkout.session.async_payment_succeeded
refund.created
refund.failed
charge.dispute.created
charge.dispute.funds_withdrawn
charge.dispute.funds_reinstatedstripe listen \
--events checkout.session.completed,checkout.session.async_payment_succeeded,refund.created,refund.failed,charge.dispute.created,charge.dispute.funds_withdrawn,charge.dispute.funds_reinstated \
--forward-to localhost:3001/webhooks/stripeWhen a created refund fails, refund.failed restores the related credits or account deficit idempotently. Test both successful and failed refund paths.