Cloudflare Access is the first identity boundary for admin routes. Application code then verifies the identity and applies the service’s own permissions. Private calendar feeds and voting use scoped tokens; sensitive public flows add magic links, rate limits, or bot checks.
Access boundaries by service
Landing
- Analytics and dataset APIs under
/api/statsand/api/csv-* - Protection typically handled at the edge (Cloudflare Access)
Sources: ihnyc-rc-landing/functions/api/stats.ts, ihnyc-rc-landing/functions/api/csv-upload.ts, ihnyc-rc-landing/README.md
RC Console
- RC Console verifies the Access JWT in application code.
- The front door has a static steward rule and a managed current-roster group.
- D1 people, assignments, and access maps drive current council access.
- Integrated services use a service token for action-level policy checks.
- Casework keeps a separate, stricter Access application.
Sources: ihnyc-rc-landing/rc-admin/src/middleware/auth.ts, ihnyc-rc-landing/rc-admin/src/roster.ts, ihnyc-rc-landing/rc-admin/src/authz.ts
Calendar
- Programs flow uses magic-link verification and token-gated ICS
- Only SHA-256 token hashes are retained; renewal links use a separate signed credential
- Internal feed proxies to n8n
- Admin endpoints verify the Access JWT and then require an action-level allow from RC Console
Sources: ihnyc-rc-cal-landing/functions/api/subs/new.ts, ihnyc-rc-cal-landing/functions/api/subs/verify.ts, ihnyc-rc-cal-landing/functions/cal/programs.ics.ts, ihnyc-rc-cal-landing/functions/cal/internal.ics.ts, ihnyc-rc-cal-landing/functions/api/admin/stats.ts
Gallery (decommissioned)
The retired implementation protected /admin and /api/admin at the edge with Cloudflare Access.
Sources: ihnyc-rc-gallery/src/index.ts, ihnyc-rc-gallery/README.md
Vote
- Admin routes require Cloudflare Access headers or
ADMIN_API_KEY - Local dev bypass available
Sources: ihnyc-rc-vote/src/middleware/auth.ts
I-House Pub
- Pub verifies the Cloudflare Access JWT and reads the operator’s permissions from
pub_admin_roles. - Permission scopes cover scheduler, TV, content, DJ, and tutorial work.
- A full administrator token remains a root path for automation and recovery.
- Pub manages its delegated operator Access policy independently from RC Console.
Sources: ihnyc-avi-pub-landing/worker/lib/admin-auth.js, ihnyc-avi-pub-landing/worker/lib/admin-permissions.js, ihnyc-avi-pub-landing/worker/lib/admin-access-policy.js
Tokens and magic links
Programs calendar flow
- User submits a verification request; only the one-time code hash is stored.
- A successful magic link mints a random feed token and stores only its SHA-256 hash.
/cal/programs.icshashes the presented token and compares it with D1.- Renewal email uses a separate HMAC-signed, expiring row credential that cannot fetch the feed.
Sources: ihnyc-rc-cal-landing/functions/api/subs/verify.ts, ihnyc-rc-cal-landing/functions/cal/programs.ics.ts, ihnyc-rc-cal-landing/functions/_lib/renew-link.ts, ihnyc-rc-cal-landing/migrations/0008_drop_token_plain.sql
Admin identity and authorization
Calendar separates the two decisions explicitly:
flowchart LR ACCESS["Cloudflare Access<br/>Who is this?"] --> APP["Calendar middleware<br/>What action is requested?"] APP --> POLICY["RC Console policy service<br/>Does this role include it?"] POLICY -- Allow --> RUN["Run handler"] POLICY -- Deny or error --> STOP["403"]
Every Calendar admin endpoint is covered by directory middleware. Unknown route-to-action mappings, invalid JWTs, missing grants, and policy-service failures deny access. Pub uses its own role table and permission registry rather than RC Console.
Sources: ihnyc-rc-cal-landing/functions/api/admin/_middleware.ts, ihnyc-rc-cal-landing/functions/_lib/route-actions.ts, ihnyc-rc-landing/rc-admin/src/authz.ts
Vote Flow
- Vote submissions validate tokens via TokenManager Durable Object
- Ballots stored after validation
Sources: ihnyc-rc-vote/src/routes/vote.ts, ihnyc-rc-vote/wrangler.jsonc
Rate limiting and bot protection
| Service | Protection | Implementation |
|---|---|---|
| Calendar | Turnstile verification | Used in programs subscription flow when TURNSTILE_SECRET is set |
| Vote | IP-based rate limiting | Applied to vote submissions |
Sources: ihnyc-rc-cal-landing/functions/api/subs/new.ts, ihnyc-rc-cal-landing/functions/api/turnstile-site-key.ts, ihnyc-rc-vote/src/middleware/rate-limit.ts, ihnyc-rc-vote/src/routes/vote.ts
Secret handling
| Service | Storage Method | Notes |
|---|---|---|
| Vote | .dev.vars (local), Wrangler secrets (production) | See .dev.vars.example |
| Calendar | Public identifiers in wrangler.toml; Pages Secrets for provider, token, cron, and policy-service credentials | Never commit secrets |
| Gallery (decommissioned) | PUBLIC_MEDIA_BASE_URL, RC_LOGO_URL via wrangler.toml | Historical public variables |
| Landing | Env vars for GitHub and analytics-store | Read in functions |
| RC Console | Wrangler secrets for Access management, alerts, health, and service authorization | Broad Access token requires a narrow service boundary |
| Pub | Wrangler secrets for root administration, providers, and in-venue relays | Delegated browser users rely on verified Access identity and scoped roles |
Sources: ihnyc-rc-vote/.dev.vars.example, ihnyc-rc-vote/README.md, ihnyc-rc-cal-landing/wrangler.toml, ihnyc-rc-cal-landing/README.md, ihnyc-rc-gallery/wrangler.toml, ihnyc-rc-landing/functions/api/changelog.ts, ihnyc-rc-landing/functions/api/publish.ts
Programs calendar access flow
Complete calendar subscription flow with magic-link verification
sequenceDiagram participant U as Resident participant S as Programs calendar participant EXT_T as Cloudflare Turnstile participant EXT_R as Resend participant STORE_D1 as D1 participant STORE_R2 as R2 participant C as Calendar client U->>S: submit form + Turnstile S->>EXT_T: verify bot check S->>STORE_D1: write request S->>EXT_R: send magic link U->>S: click link S->>STORE_D1: mint token C->>S: fetch ICS + token S->>STORE_R2: read ICS S-->>C: return ICS
Sources: ihnyc-rc-cal-landing/functions/api/subs/new.ts, ihnyc-rc-cal-landing/functions/api/subs/verify.ts, ihnyc-rc-cal-landing/functions/cal/programs.ics.ts, ihnyc-rc-cal-landing/functions/_lib/renew-link.ts
Open questions
Production configuration
- Which Resident Council website routes are protected by Cloudflare Access in production?
- Are
/subscribe-internal*and its n8n origin protected consistently in production?
Sources: ihnyc-rc-landing/README.md, ihnyc-rc-gallery/README.md, ihnyc-rc-cal-landing/README.md