Local checks
Requirements: Node.js 20 or newer.
npm ci
npm test
npm run buildnpm run dev serves the Eleventy frontend on port 8080. To exercise Pages Functions, build first and run:
npx wrangler pages dev distWorking subscription, admin, cron, and feed paths also need suitable local D1/R2 bindings and non-production test credentials.
Deployment order
- Run
npm testandnpm run build. - Review new D1 migrations. Migration
0008requires the token-hash-only code first. Migrations0009and0010are safe after the compatible email-template code is live. - Apply remote migrations with
npm run migrate. - Deploy
dist/and the Pages Functions through the configured Pages project. - Smoke-test the resident form, one tokenized feed request, the admin authorization boundary, and one rendered email preview.
Configuration map
| Area | Names |
|---|---|
| Storage | SUBS_DB, CAL_BUCKET, PROGRAMS_ICS_KEY |
RESEND_API_KEY, RESEND_FROM, RESEND_WEBHOOK_SECRET | |
| Bot check | TURNSTILE_SITE_KEY, TURNSTILE_SECRET |
| Tokens and renewal | TOKEN_TTL_DAYS, TOKEN_PEPPER, BASE_PUBLIC |
| Feed generation | NOTION_EVENTS_DB_ID, NOTION_TOKEN, CRON_BEARER_TOKEN |
| Admin identity | ACCESS_TEAM_DOMAIN, ACCESS_AUD |
| Admin authorization | PANEL_URL, AUTHZ_SERVICE_TOKEN |
| Legacy Internal feed | N8N_BASE |
Secrets belong in Cloudflare Pages secrets or the local secret environment, never in source or documentation.
Common failure checks
Resident did not receive a magic link
- Check
RESEND_API_KEYandRESEND_FROM. - Inspect the request event and
email_events/Resend outcome. - Confirm the one-minute per-email cooldown is not active.
- Confirm Turnstile verification succeeds when enabled.
Feed returns not found
- Confirm the token is current, not revoked, and not expired.
- Confirm the subscriber and Programs calendar are enabled.
- Confirm
programs.icsexists inCAL_BUCKET. - Inspect
calendar_access_logwithout copying private token values into tickets or chat.
Programs feed is stale
- Check the last
regenerate-programs-icscron result. - Confirm
NOTION_TOKENcan read the configured Events database. - Confirm the intended rows have Include in External Feed enabled.
- A successful unchanged run will not write R2; that is expected.
Admin API returns 401, 403, or 503
401: verify the Access application, JWT issuer, and audience.403: confirm the route has an action mapping and the person’s Calendar role includes it.- Policy service unavailable or missing
AUTHZ_SERVICE_TOKEN: the request fails closed. Check RC Console health rather than adding a bypass.
Email preview is blank or stale
- Confirm
POST /api/admin/templates/previewreaches thetemplate.readaction. - Confirm migrations
0009and0010are applied. - Compare the preview with a test email; both should use the same renderer.
- Use version history to restore a bad template or shared-footer edit.
Observability
calendar_access_logexplains feed delivery status and latency.event_logpowers product/security timelines, funnel, cohort, and replay views.email_eventsrecords signed provider delivery outcomes.system_staterecords cron summaries.
Mixpanel checks and environment variables are obsolete and should not be restored.