Companion ops guide for [[services/ihnyc-rc-vote]]. This file captures runbooks and operational notes.
Purpose
Single place for how the app runs, how to develop safely, and how to recover.
Stack at a Glance
- Cloudflare Worker (entry:
src/index.ts) with Hono routes undersrc/routes. - Assets:
public/served via Worker assets binding. - Data: Cloudflare D1 (
DBbinding). Durable ObjectTokenManagerhandles token coordination. - Scheduler: Cron every minute (
wrangler.jsonc). - Email: outbound templated emails in
src/utils/email.ts(configure keys via secrets).
Local Development
- Requirements: Node 22+, npm 10+,
wranglerinstalled. - Env/config:
- Copy
.dev.vars.exampleto.dev.varsand fillRESEND_API_KEY,FROM_EMAIL,BASE_URL,ADMIN_API_KEY. - D1: use the dev DB automatically bound by Wrangler; see
wrangler.jsonc.
- Copy
- Run dev server:
npm installthennpm run dev. - Type generation:
npm run cf-typegen.
Testing
- All tests:
npm test - Unit:
npm run test:unit - Integration (D1/Workers pool):
npm run test:integration - Config:
vitest.config.ts, uses@cloudflare/vitest-pool-workers.
Database & Migrations
- Migrations live in
migrations/and are applied with Wrangler:- Remote:
wrangler d1 migrations apply ihnyc-rc-vote --remote - Local dev:
wrangler d1 migrations apply ihnyc-rc-vote
- Remote:
- When altering tables with FKs, avoid data loss:
- Preserve dependent tables (tokens, ballots, invites, candidates) before recreating
elections. - Follow the pattern in
migrations/011_batch_invites.sql(backup → recreate → restore).
- Preserve dependent tables (tokens, ballots, invites, candidates) before recreating
- Inspect schema:
wrangler d1 execute ihnyc-rc-vote --remote --command="SELECT name, sql FROM sqlite_master WHERE type='table';" - See migrations for detailed migration documentation.
Backups & Recovery (D1 Time Travel)
- D1 Time Travel is always on (no setup). You can restore to any minute in the last 30 days (paid) or 7 days (free).
- Check current bookmark:
wrangler d1 time-travel info ihnyc-rc-vote
- Get bookmark for a past timestamp (UTC or RFC3339):
wrangler d1 time-travel info ihnyc-rc-vote --timestamp="2026-01-03T20:20:00+00:00"
- Restore to a bookmark (destructive, overwrites DB):
wrangler d1 time-travel restore ihnyc-rc-vote --bookmark=...
- Keep the “undo” bookmark the CLI prints after a restore; you can restore back if needed.
- Reference: Cloudflare docs on Time Travel https://developers.cloudflare.com/d1/reference/time-travel/
Deployment
- Production deploy:
npm run deploy(alias forwrangler deploy --minify). - Secrets (prod):
wrangler secret put RESEND_API_KEY,FROM_EMAIL,BASE_URL,ADMIN_API_KEY. - Observability:
wrangler.jsonchasobservability.enabled: true.
Key Application Notes
- Invite modes:
invite_modeonelectionssupportsindividualandbatch. Batch sends a single email listing all active elections for an email.- See magic-link-invites for comprehensive documentation on magic link invite mode.
- Bulk invite management: Use
/admin/bulk-invitesto send invites for multiple elections to multiple recipients in one operation. Accessible from Admin Dashboard → ”📧 Bulk Invites”. - Rate limits & auth: see
src/middleware/(auth and rate-limit). - Notion integration: configure in
settings_json; code insrc/utils/notion.tsand related routes.- See notion-setup for Notion database allowlist configuration.
- Templates: server-rendered HTML in
src/templates/.
Operational Runbook (quick)
- Migration safety: run on staging first; for prod have a Time Travel bookmark before apply.
- Recovery from bad migration:
wrangler d1 time-travel info ... --timestamp="<pre-migration UTC>"wrangler d1 time-travel restore ... --bookmark=<bookmark>- Re-run fixed migration.
- Validate data after migrations:
SELECT COUNT(*) FROM elections;and dependent tables: tokens, ballots, invites, candidates.
Documentation
Additional documentation in IHNYC-Remote:
Core Features
- magic-link-invites: Comprehensive guide to magic link invite mode (batch invites)
- voting-system: Ballot types and voting flow
- results-calculation: How election results are computed
Infrastructure
- authentication: Authentication and authorization system
- token-management: Token validation and Durable Objects
- rate-limiting: Rate limit configurations and management
- migrations: Database migration documentation
Integrations
- notion-setup: Notion integration setup and configuration
- notion-integration: How Notion synchronization works
- distribution-lists: Bulk email management
- email-system: Email templates and sending
Operations
- audit-logging: Security and compliance logging
- testing: Testing strategy and test execution
- api-reference: Complete API endpoint documentation
Where to Add More
- Infra changes: update this file.
- New services or env vars: add a short “How to configure & test” subsection here.
- Detailed feature documentation: add a new IHNYC-Remote doc and link from here.