---
name: Cloudflare Platform Expert
description: Cloudflare Workers, Pages, D1, R2, KV, Access, Tunnels, DNS, wrangler, deploy, custom domain, security hardening, cron trigger, queue, durable object, vectorize, Zero Trust, WAF, cache rules.
---

# Cloudflare Platform Expert

This skill provides deep reference knowledge for all Cloudflare developer platform services used by Sunrise Communities. It covers Workers, Pages, D1, R2, KV, Queues, Durable Objects, Vectorize, Access/Zero Trust, DNS, Tunnels, and Wrangler configuration. All limits and pricing data were researched from official Cloudflare documentation as of March 2026 and should be re-verified for critical cost decisions since Cloudflare updates pricing periodically.

---

## Table of Contents

**Always loaded (this file):**
1. [Sunrise-Specific Configuration](#sunrise-specific-configuration)
2. [Decision Trees](#decision-trees)
3. [Common Gotchas](#common-gotchas)
4. [Progressive Reference Loading](#progressive-reference-loading)

**Load on demand (Read tool → `references/*.md`):**
- `references/workers.md` — Workers Runtime, Static Assets, Durable Objects, Vectorize, Workers AI
- `references/storage.md` — D1, KV, R2, Queues
- `references/pages.md` — Cloudflare Pages
- `references/access-security.md` — CF Access, JWT, Service Tokens, DNS, Tunnels
- `references/wrangler-reference.md` — wrangler.toml, deployment procedures, error codes

---

## Sunrise-Specific Configuration

### Account Details

| Setting | Value |
|---------|-------|
| CF Account ID | `047e4a494864e6404c12ef36eeca1607` |
| CF Zone ID (suncom.work) | `7500114736042bd4c7d36761ea60bc3d` |
| CF Access Org/Team | `suncom` (NOT `sunrise`) |
| CF Access Issuer | `https://suncom.cloudflareaccess.com` |
| CF Access Certs Endpoint | `https://suncom.cloudflareaccess.com/cdn-cgi/access/certs` |
| CF Access Logout URL | `https://suncom.cloudflareaccess.com/cdn-cgi/access/logout` |
| Carlos CF Access Email | `carlos.terrazas@mysunrisecommunity.com` (singular community) |
| Wrangler Version | 4.53.0 (upgraded from 3.x; 4.65.0 available) |
| OAuth Token Location | `~/Library/Preferences/.wrangler/config/default.toml` (zone:read only, NOT zone:write) |

### Deployed Infrastructure

**Workers (all hardened with JWT validation + workers_dev=false):**

| Worker | Domain | Notes |
|--------|--------|-------|
| Sage Brand API | `sage-api.suncom.work` | Reference impl for JWT auth, D1, R2, Queues, AI |
| Tickets | `tickets.suncom.work` | Had JWT auth, added workers_dev=false |
| Sunny AI API | `sunny.suncom.work/api/*` | zone_name path routing, Vectorize + R2 + KV |
| Sunny CM API | `sunny-cm.suncom.work/api/*` | Added JWT auth + CORS lockdown |
| Acquisitions API | `acquisitionsic.suncom.work/api/*` | Replaced fake JWT with crypto verification |
| IR Intelligence | Worker in `/Investor Relations/IR_Intelligence_Layer/` | |
| AP Automation | Worker in `/Finance/AP Process/ap-automation/` | |

**Pages (all with hostname guards):**

| Page | Domain | Guard |
|------|--------|-------|
| KPI Dashboard | `kpi.suncom.work` | Hostname guard |
| Occupancy Dashboard | `occupancy.suncom.work` | Hostname guard |
| Sunny AI | `sunny.suncom.work` | Hostname guard |
| Sunny CM | `sunny-cm.suncom.work` | Hostname guard |
| Resource Hub | `hub.suncom.work` | Hostname guard |
| Resource Hub CM | `hub-cm.suncom.work` | Hostname guard |
| Acquisitions IC | `acquisitionsic.suncom.work` | Hostname guard |

**Key Domains:** `kpi-dashboard-d9y.pages.dev`, `acquisitionsic.suncom.work`, `sunny-cm.suncom.work`

### Established Patterns

**DNS pattern:** All suncom.work subdomains use CNAME records auto-created by CF Custom Domains. Never manually create AAAA `100::` records.

**Pages+Worker same-domain pattern:** Use `zone_name` path routing (`domain.suncom.work/api/*`) so the API shares the domain with Pages. This eliminates CORS issues and requires only a single CF Access app.

**JWT validation pattern:** Reference implementation at `/Investor Relations/Sage_Brand/src/utils/cf-access.ts`. Always validate `Cf-Access-Jwt-Assertion` header with cryptographic signature verification. Never trust raw `Cf-Access-Authenticated-User-Email` header.

**Standard env vars for CF Access:**
```toml
[vars]
CF_ACCESS_TEAM = "suncom"
CF_ACCESS_AUD = "<from CF Access dashboard: Applications > App > Overview > AUD Tag>"
```

### Pending Manual Tasks (as of 2026-02-16)

- Disable `.pages.dev` access for each Pages project in CF dashboard
- Set `CF_ACCESS_AUD` secret for Acquisitions API and Sunny CM Workers
- Create CF Access applications for any unprotected projects

---


---

## Progressive Reference Loading

**This skill uses progressive disclosure to keep context lean.** The sections above (Sunrise-Specific Configuration) always load. For deep technical reference, load only the file you need:

| Topic | Load |
|-------|------|
| Workers runtime, Static Assets, Durable Objects, Vectorize, Workers AI | `references/workers.md` |
| D1, KV, R2, Queues | `references/storage.md` |
| CF Pages (deploy, limits, Functions, custom domains) | `references/pages.md` |
| CF Access, JWT, Service Tokens, DNS, Tunnels | `references/access-security.md` |
| wrangler.toml, deployment procedures, error codes | `references/wrangler-reference.md` |

**Read the reference file with the Read tool only when the task requires that specific area.** Do not preload.

---

## Decision Trees

### New Project: Pages or Workers?

```
Is this a brand new project?
  YES → Use Workers with [assets] for static files
        (Cloudflare is investing only in Workers going forward)

Is this an existing Pages project?
  YES → Is it working well with no issues?
    YES → Keep as Pages; migrate when convenient
    NO → Migrate to Workers

Do you need server-side logic (API, auth, data processing)?
  YES → Workers
  NO → Pages is still simpler for pure static sites

Do you need bindings (D1, R2, KV, etc.)?
  YES → Workers preferred (easier binding management)
```

### Data Storage: D1 vs KV vs R2?

```
What type of data?

Relational (users, records, transactions):
  → D1 (SQLite with SQL queries, joins, indexes)

Simple key-value (config, flags, sessions):
  → KV (edge-cached, eventually consistent)

Large files (images, PDFs, media, backups):
  → R2 (S3-compatible, zero egress)

Need strong consistency + coordination:
  → Durable Objects (single-threaded, transactional)

Existing Postgres/MySQL:
  → Hyperdrive (connection pooling, no migration)

AI embeddings for search:
  → Vectorize (vector database, works with Workers AI)

Real-time metrics/analytics:
  → Analytics Engine (time-series, no storage management)
```

### Domain Setup Sequence (ORDER MATTERS)

```
1. Create Worker/Pages project
2. Configure custom domain in wrangler.toml or dashboard
   - Workers: routes = [{ pattern = "x.suncom.work", custom_domain = true }]
   - Pages: Dashboard → Custom domains → Add
3. Deploy to verify custom domain works
4. THEN disable workers.dev (workers_dev = false)
5. THEN set up CF Access application for the domain
6. THEN add JWT validation to Worker code
7. THEN lock down .pages.dev if using Pages (hostname guard or dashboard)
8. THEN tighten CORS to only allow custom domains
9. Deploy final hardened version
```

### Security Hardening Checklist (Step by Step)

```
For every new project:

[ ] 1. Custom domain configured and working
[ ] 2. workers_dev = false in wrangler.toml
[ ] 3. CF Access application created for domain
[ ] 4. JWT validation added to Worker (copy cf-access.ts)
[ ] 5. CF_ACCESS_TEAM = "suncom" in [vars]
[ ] 6. CF_ACCESS_AUD set via wrangler secret put
[ ] 7. CORS locked down to custom domains only
[ ] 8. .pages.dev access disabled (if Pages project)
[ ] 9. Hostname guard in HTML (if Pages project)
[ ] 10. Test: verify workers.dev/pages.dev URLs return errors
[ ] 11. Test: verify custom domain with CF Access works
[ ] 12. Test: verify JWT validation rejects spoofed headers
```

---

## Common Gotchas

### DNS and Routing

**Problem:** Worker returns 404 or "No route" after deploying with custom domain.
**Cause:** `routes` block placed inside `[vars]` section in wrangler.toml. TOML parser treats it as an env var.
**Fix:** Place `routes` at top level, BEFORE any `[section]` header.

**Problem:** API goes dark after adding `workers_dev = false`.
**Cause:** Custom domain was not set up before disabling workers.dev.
**Fix:** Always set up and verify custom domain FIRST, then disable workers.dev.

**Problem:** Cannot reuse a hostname after deleting a Pages project.
**Cause:** Deleting a Pages project does NOT auto-delete its DNS CNAME record.
**Fix:** Manually delete the stale CNAME record in DNS dashboard before reusing the hostname.

**Problem:** AAAA `100::` DNS record conflicts with Worker Custom Domain.
**Cause:** Legacy pattern of manual DNS + routes conflicts with new Custom Domain feature.
**Fix:** Use Custom Domains (`custom_domain = true`) which auto-manage DNS. Remove manual AAAA records.

**Problem:** `*example.com/*` route matches `myexample.com` (unwanted).
**Cause:** Wildcard `*` matches zero or more characters, including the dot separator.
**Fix:** Use separate routes for exact subdomains or prefix with the dot: `*.example.com/*`.

### CF Access and Authentication

**Problem:** CF Access authentication works on custom domain but not on workers.dev.
**Cause:** CF Access is configured per-domain. The workers.dev URL bypasses it entirely.
**Fix:** This is expected behavior. Always disable workers.dev route for security.

**Problem:** User can spoof `Cf-Access-Authenticated-User-Email` header.
**Cause:** Raw headers are not cryptographically verified and can be set by anyone.
**Fix:** Always validate `Cf-Access-Jwt-Assertion` header with JWKS signature verification.

**Problem:** CF Access login works for one app but not another on same domain.
**Cause:** CF Access cookies are per-domain, not per-path.
**Fix:** Use single CF Access application per domain. Route multiple services via path-based routing on one domain.

**Problem:** Frontend and API on different subdomains cause double login or cookie issues.
**Cause:** CF Access cookies are scoped to the specific domain/subdomain.
**Fix:** Serve both from one domain using Worker `[assets]` or `zone_name` path routing.

### D1 Database

**Problem:** `PRAGMA foreign_keys = OFF` has no effect in batch migration.
**Cause:** D1 executes each statement in a batch independently; PRAGMAs don't persist across statements.
**Fix:** Recreate dependent table without FK first, then target table, then dependent table with FK.

**Problem:** `CREATE TABLE IF NOT EXISTS` does not update an existing table schema.
**Cause:** SQLite behavior: the statement succeeds silently if table exists, regardless of schema differences.
**Fix:** Use `ALTER TABLE` for column additions, or drop-and-recreate for full schema changes.

**Problem:** Large UPDATE or DELETE query exceeds execution limits.
**Cause:** Single query modifying hundreds of thousands of rows exceeds D1's 30-second query timeout.
**Fix:** Batch operations, processing 1,000 rows at a time with LIMIT and WHERE clauses.

**Problem:** Migration succeeds locally but fails on remote.
**Cause:** Local DB state differs from remote due to previous migrations or manual changes.
**Fix:** Always test migrations locally with a baseline file matching remote state.

### Workers Runtime

**Problem:** Error 1102 - Worker exceeded resource limits.
**Cause:** Worker exceeded either 128 MB memory limit or CPU time limit (10ms free, 30s paid default).
**Fix (CPU):** Use CPU profiling with DevTools. Break work into smaller chunks. Stream data. Offload to Durable Objects. On paid plan, raise CPU limit up to 5 min in wrangler.toml: `[limits] cpu_ms = 300000`.
**Fix (Memory):** Avoid buffering large objects. Use streaming APIs (TransformStream). Don't store large objects in global scope.

**Problem:** Cron trigger keeps firing after commenting out `[triggers]` in wrangler.toml.
**Cause:** Commenting out the triggers section does not disable crons.
**Fix:** Explicitly set `crons = []` under `[triggers]`.

**Problem:** Environment variables from wrangler.toml disappear after dashboard edit.
**Cause:** `wrangler deploy` treats wrangler.toml as source of truth and overwrites dashboard changes.
**Fix:** Set `keep_vars = true` in wrangler.toml, or manage all vars exclusively in wrangler.toml.

**Problem:** Bindings (KV, D1, R2) not available in staging environment.
**Cause:** Bindings are non-inheritable and must be explicitly defined in each `[env.X]` block.
**Fix:** Redeclare all bindings in every environment section.

### Pages

**Problem:** No way to fully disable `.pages.dev` URL via API.
**Cause:** Cloudflare does not expose a toggle for this in the API.
**Fix:** Use dashboard (Settings > General > Access Policy > Enable > Block) or add hostname guards in HTML.

**Problem:** Pages Functions changes not taking effect.
**Cause:** Pages Functions are file-based; file must be in correct `functions/` directory structure.
**Fix:** Verify file location matches expected route. Check build logs for errors.

### TOML Configuration

**Problem:** Wrangler says "routes is not a valid configuration key."
**Cause:** `routes` is placed after a `[vars]` or other section header, getting parsed as part of that section.
**Fix:** Move `routes` above ALL `[section]` headers. Top-level keys must come before any bracketed sections.

**Problem:** D1/KV/R2 resources auto-created on every deploy.
**Cause:** Missing `id`, `database_id`, or similar field in binding configuration.
**Fix:** Always specify the resource ID in wrangler.toml after initial creation.

---


---

## References

### Official Documentation

| Topic | URL |
|-------|-----|
| Workers Docs Home | https://developers.cloudflare.com/workers/ |
| Workers Limits | https://developers.cloudflare.com/workers/platform/limits/ |
| Workers Pricing | https://developers.cloudflare.com/workers/platform/pricing/ |
| Wrangler Configuration | https://developers.cloudflare.com/workers/wrangler/configuration/ |
| Wrangler Commands | https://developers.cloudflare.com/workers/wrangler/commands/ |
| Wrangler Environments | https://developers.cloudflare.com/workers/wrangler/environments/ |
| Workers Bindings | https://developers.cloudflare.com/workers/runtime-apis/bindings/ |
| Workers Routing | https://developers.cloudflare.com/workers/configuration/routing/ |
| Custom Domains | https://developers.cloudflare.com/workers/configuration/routing/custom-domains/ |
| Routes | https://developers.cloudflare.com/workers/configuration/routing/routes/ |
| Cron Triggers | https://developers.cloudflare.com/workers/configuration/cron-triggers/ |
| Workers Secrets | https://developers.cloudflare.com/workers/configuration/secrets/ |
| Workers Static Assets | https://developers.cloudflare.com/workers/static-assets/ |
| Workers Errors | https://developers.cloudflare.com/workers/observability/errors/ |
| Storage Options Guide | https://developers.cloudflare.com/workers/platform/storage-options/ |
| Pages Docs Home | https://developers.cloudflare.com/pages/ |
| Pages Limits | https://developers.cloudflare.com/pages/platform/limits/ |
| Pages Functions | https://developers.cloudflare.com/pages/functions/ |
| Pages Bindings | https://developers.cloudflare.com/pages/functions/bindings/ |
| Migrate Pages to Workers | https://developers.cloudflare.com/workers/static-assets/migration-guides/migrate-from-pages/ |
| D1 Docs Home | https://developers.cloudflare.com/d1/ |
| D1 Limits | https://developers.cloudflare.com/d1/platform/limits/ |
| D1 Pricing | https://developers.cloudflare.com/d1/platform/pricing/ |
| D1 SQL Statements | https://developers.cloudflare.com/d1/sql-api/sql-statements/ |
| D1 Migrations | https://developers.cloudflare.com/d1/reference/migrations/ |
| KV Docs Home | https://developers.cloudflare.com/kv/ |
| KV Limits | https://developers.cloudflare.com/kv/platform/limits/ |
| KV Pricing | https://developers.cloudflare.com/kv/platform/pricing/ |
| KV How It Works | https://developers.cloudflare.com/kv/concepts/how-kv-works/ |
| R2 Docs Home | https://developers.cloudflare.com/r2/ |
| R2 Pricing | https://developers.cloudflare.com/r2/pricing/ |
| R2 Presigned URLs | https://developers.cloudflare.com/r2/api/s3/presigned-urls/ |
| R2 CORS | https://developers.cloudflare.com/r2/buckets/cors/ |
| Queues Docs Home | https://developers.cloudflare.com/queues/ |
| Queues Limits | https://developers.cloudflare.com/queues/platform/limits/ |
| Queues Pricing | https://developers.cloudflare.com/queues/platform/pricing/ |
| Queues DLQ | https://developers.cloudflare.com/queues/configuration/dead-letter-queues/ |
| Durable Objects Docs | https://developers.cloudflare.com/durable-objects/ |
| Durable Objects Pricing | https://developers.cloudflare.com/durable-objects/platform/pricing/ |
| Durable Objects Limits | https://developers.cloudflare.com/durable-objects/platform/limits/ |
| Vectorize Docs | https://developers.cloudflare.com/vectorize/ |
| Vectorize Pricing | https://developers.cloudflare.com/vectorize/platform/pricing/ |
| Workers AI Docs | https://developers.cloudflare.com/workers-ai/ |
| Workers AI Pricing | https://developers.cloudflare.com/workers-ai/platform/pricing/ |
| CF Access JWT Validation | https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/ |
| CF Access Service Tokens | https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/service-tokens/ |
| CF Tunnel Docs | https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/ |
| Workers VPC + Tunnel | https://developers.cloudflare.com/workers-vpc/configuration/tunnel/ |
| SSL/TLS Modes | https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/ |
| Origin CA | https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/ |
| Error 1102 | https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1102/ |
| CF Developer Platform Pricing | https://www.cloudflare.com/plans/developer-platform/ |
| Changelog | https://developers.cloudflare.com/changelog/ |

### Sunrise-Specific Files

| File | Purpose |
|------|---------|
| `/Investor Relations/Sage_Brand/src/utils/cf-access.ts` | JWT validation reference implementation |
| `/Investor Relations/Sage_Brand/wrangler.toml` | Complete wrangler.toml reference (D1, R2, Queues, AI, crons) |
| `/sunny-cloudflare/worker/wrangler.toml` | Workers AI + Vectorize + R2 + KV + path routing example |
| `~/.claude/projects/-Users-sunrise-Documents-IA-Projects/memory/cf-pages-security-playbook.md` | Full security hardening playbook |
| `~/.claude/projects/-Users-sunrise-Documents-IA-Projects/memory/MEMORY.md` | Running notes on CF gotchas |

---

*Last updated: 2026-03-02. Pricing and limits sourced from official Cloudflare documentation. Verify critical cost decisions against current docs as Cloudflare updates pricing periodically.*
