Cloudflare
Workers, D1, KV, R2, Pages, DNS, Access — inventory, limits, AI query roadmap
Why this page exists
Cloudflare is the load-bearing layer of the platform — Worker (API), D1 (data), KV (cache), R2 (files), Pages (UI), DNS (routing), and soon Workers AI + Vectorize for the natural-language query layer. This page consolidates every product, its current state, where it's referenced in source, common operations, and what's planned next. Decisions about Cloudflare are tracked in ADRs; live health is on admin-dashboard.
Inventory 11 products
Per-product card with status, instance, binding, source/config, common ops, and limits.
Workers
Activegfs-platform
Single public API for the platform. 20+ GET endpoints over the D1 mirror. CORS allowlist, Bearer auth, security headers.
Detail
Binding: —
Source: src/index.ts
Config: wrangler.jsonc
Limits: 100,000 requests/day on free tier; CPU 50ms/request; sub-requests 50/request (Paid: 1000)
Common ops:
- wrangler deploy
- wrangler tail
- wrangler dev
D1
Active — 185K rowsgfs-netsuite
SQLite read-mirror of NetSuite. 18 tables, 152 GL accounts, 102K transactions across 20 types, full entity backfill.
Detail
Binding: DB
Source: schema.sql, sql/*.sql (45 loaders)
Config: wrangler.jsonc d1_databases
Limits: 10 GB max per DB (currently ~150 MB), 100K reads/day free, point-in-time recovery on Paid
Common ops:
- wrangler d1 execute gfs-netsuite --remote --command "SELECT…"
- wrangler d1 backup create gfs-netsuite
- wrangler d1 export gfs-netsuite
KV
Provisioned, not usedCACHE (e880e40b…)
Short-TTL cache layer. Bound but no endpoints read/write yet. Planned uses: cache /api/ar/aging, /api/kpis responses; rate-limit counters for AI query layer; AI response cache.
Detail
Binding: CACHE
Source: src/index.ts (env.CACHE)
Config: wrangler.jsonc kv_namespaces
Limits: 100K reads/day free, 1K writes/day, 25 MB value max
Common ops:
- wrangler kv:key put --binding=CACHE "k" "v"
- wrangler kv:key list --binding=CACHE
R2
Active (light use)gfs-files
Binary file storage. File Upload RESTlet (NS script 2512) writes here via SuiteAttach. Planned uses: scheduled D1 → SQL export for DR, archived PDF templates, AI audit log cold storage.
Detail
Binding: STORAGE
Source: src/index.ts (env.STORAGE)
Config: wrangler.jsonc r2_buckets
Limits: 10 GB free storage, 1M Class A ops/month, 10M Class B/month (egress is free)
Common ops:
- wrangler r2 object put gfs-files/path file.bin
- wrangler r2 object list gfs-files
Pages
Active — this platformgfs-netsuite.pages.dev
Static hosting for this admin guide. All 10 surfaces + JSON data + reference docs deploy here.
Detail
Binding: —
Source: Whole repo minus src/, sql/, archive/, configs
Config: —
Limits: 500 builds/month free, 100 concurrent builds, unlimited bandwidth
Common ops:
- wrangler pages deploy . --project-name gfs-netsuite
- wrangler pages deployment list --project-name gfs-netsuite
- wrangler pages deployment tail --project-name gfs-netsuite
Pages (legacy)
Deprecated — pre-consolidationgfs-system-guide.pages.dev
Original platform site. Kept available until migration is fully validated. Will be deleted after greenlight.
Detail
Binding: —
Source: Frozen at pre-consolidation state
Config: —
Limits: Same as Pages (above)
Common ops:
- dash.cloudflare.com → Workers & Pages → gfs-system-guide → Delete
DNS / Zone
Activeai-globalfoodsolutions.co
Authoritative DNS for ai-globalfoodsolutions.co (owned). Corporate domain globalfoodsolutions.co also owned. 6 records: CNAME (api, www), MX, TXT (SPF + DMARC), NS.
Detail
Binding: —
Source: wrangler.jsonc routes
Config: dash.cloudflare.com → ai-globalfoodsolutions.co → DNS
Limits: DNS records: 3,500/zone soft limit
Common ops:
- dash.cloudflare.com → DNS → add/edit records
Access (Zero Trust)
Tier 1 GAP — required before sharing URL(not configured)
Auth in front of gfs-netsuite.pages.dev. Currently anyone with the URL can read GAPS, NS reference, runbook. Tier 1 in GAPS_TO_CLOSE.
Detail
Binding: —
Source: —
Config: dash.cloudflare.com → Zero Trust → Access → Applications
Limits: 50 free seats on the Free Zero Trust plan
Common ops:
- Create Application → Self-hosted → gfs-netsuite.pages.dev → Email OTP policy → Save
AI Gateway
Planned — AI query layer(planned)
Proxy + cache + logging layer in front of all LLM calls. Lets us swap models (native Llama ↔ Claude/GPT) without changing app code.
Detail
Binding: —
Source: —
Config: dash.cloudflare.com → AI → AI Gateway → Create
Limits: Free tier covers caching, observability, and most use; per-request pricing for advanced routing
Common ops:
- Create gateway
- Point Worker LLM calls at gateway URL
Vectorize
Planned — AI query layer(planned — gfs-corpus)
Vector store for the embedded corpus (D1 entities + manifest + research docs + SuiteQL library + schema). 768-dim (BGE-base). Source of retrieval for AI query.
Detail
Binding: VECTORIZE (planned)
Source: —
Config: wrangler.jsonc vectorize (planned)
Limits: Free tier: 30M queried dimensions/month, 5M stored vector-dimensions
Common ops:
- wrangler vectorize create gfs-corpus --dimensions=768 --metric=cosine
- wrangler vectorize insert gfs-corpus --file=embeddings.ndjson
Workers AI
Planned — AI query layer(planned)
Native inference at the edge. Embeddings: @cf/baai/bge-base-en-v1.5. LLM: @cf/meta/llama-3.3-70b-instruct (fallback @cf/meta/llama-3.1-8b-instruct).
Detail
Binding: AI (planned)
Source: —
Config: wrangler.jsonc ai (planned)
Limits: Pay-per-neuron; ~$0.59/M in + $0.79/M out for Llama 3.3 70B (verify before launch)
Common ops:
- env.AI.run('@cf/meta/llama-3.3-70b-instruct', {messages})
- env.AI.run('@cf/baai/bge-base-en-v1.5', {text})
AI query layer — phased build
Natural-language query over D1 + the manifest + research docs. Decision recorded in ADR-011 (native Cloudflare stack: Workers AI + Vectorize + AI Gateway). Phased so each step ships independently.
| Phase | Deliverable | Status | Detail |
|---|---|---|---|
| Phase 0 | Cloudflare surface + ADR | Done | This page + ADR-011 in decisions log. |
| Phase 1 | Vectorize index seeded | Planned | Create gfs-corpus, embed manifest (3,486 items) + 8 research docs + 29 SuiteQL queries via Workers AI bge-base. Stored vectors ~10K, well under free tier. |
| Phase 2 | Schema + entity chunks | Planned | Add 18 table descriptions + FK notes + ~2,500 entity rows (customers/vendors/items/employees/gl) as additional chunks. Aggregate-only on transactions (monthly summaries, not row-level). |
| Phase 3 | Query endpoint v1 | Planned | POST /api/ai/query — retrieve+answer mode only (no SQL gen). Cite source row/doc. Bearer auth. Per-token rate limit via KV. |
| Phase 4 | SQL generation mode | Planned | LLM emits parameterized SELECT → validator (allowlist tables, no DDL/DML) → D1 execute → LLM summarizes. Test corpus: 20 known admin questions with expected SQL. |
| Phase 5 | /ai-query.html UI | Planned | Chat surface. Citations as links. 'See generated SQL' expandable. Per-role: admin sees SQL by default, reader sees answer only. |
| Phase 6 | Audit + status endpoints | Planned | /api/ai/audit, /api/ai/status, /api/ai/sources. KV 30d hot, R2 cold. |
| Phase 7 | Reindex automation | Planned | Worker scheduled() cron — incremental reindex of D1 rows modified since last run. |
Default decisions (you can override before any phase starts)
- LLM: Llama 3.3 70B Instruct (native Workers AI) for v1. AI Gateway lets us proxy to Claude/GPT later without app changes.
- Embedding model: BGE-base-en-v1.5 (768d, native). Swap to text-embedding-3-small via AI Gateway if recall is poor.
- Transactions in corpus: aggregate-only (monthly summaries per customer/item/account). Row-level is too big and answers little.
- Show generated SQL: yes for admin role, no for reader. Builds trust without overwhelming non-technical users.
- Reindex cadence: nightly Worker cron for v1. Live updates (on sync) in v2.
- Audit retention: KV 30 days hot, R2 cold indefinitely.
Endpoints (planned)
| Endpoint | Auth | Purpose |
|---|---|---|
| POST /api/ai/query | Bearer | Single-turn natural-language query → answer + citations + optional SQL |
| POST /api/ai/index | Bearer (admin) | Force reindex (one source or all) |
| GET /api/ai/status | Bearer | Last index date, query count 24h, cache hit rate |
| GET /api/ai/sources | Bearer | List indexed sources with chunk counts |
| GET /api/ai/audit | Bearer | Recent queries (last N), redacted |
Customer pricing pipeline — phased build
Derive customer price lists from invoice history → review in platform → push back to NS. Decision recorded in ADR-012. Per-customer lists (no shared Price Levels), NetSuite stays the daily editing surface, platform handles migration + audit + AI review.
| Phase | Deliverable | Status | Detail |
|---|---|---|---|
| Phase 1 | Derive job + diff endpoint | Done | Schema migration applied (customer_pricing_proposed, customer_pricing_history, pricing_anomalies). Derive produced 661 rows across 103 customers / 219 items (445 median_last_3, 216 last_paid). Worker endpoints live: GET /api/pricing/derive, /api/pricing/diff, /api/pricing/customer/:id, /api/pricing/audit/summary. Buckets: 434 listed+recent (drift), 830 listed+stale (deprecate), 227 not-listed+recent (orphans — biggest gap). 90 open SOs across 33 customers flagged for cutover handling. |
| Phase 2 | /pricing.html audit view | Planned | Read-only surface. Per-customer view shows Listed+Recent / Listed+Stale / Not-Listed+Recent buckets. Sortable, searchable, exportable CSV. No write to NS yet. ~1 day. |
| Phase 3 | Approval flow | Planned | Admin marks rows approved / rejected / edited in /pricing.html. Writes to customer_pricing_proposed.status. Still no NS push. ~1 day. |
| Phase 4 | Push to NS via SuiteAPI RESTlet | Planned | Worker bulk-writes approved rows to NS Customer → Item Prices sublist. Per-row success/failure reporting. Pilot on 3 customers, validate next-day SOs, then expand. ~2 days. |
| Phase 5 | Effective-date history | Planned | customer_pricing_history table populated on every push (price, effective_from, effective_to, source, change_reason, changed_by). GET /api/pricing/history/:customer/:item. ~half day. |
| Phase 6 | AI review pass | Planned | Workers AI flags anomalies (drift > threshold, outside-peer-band, suspicious one-offs), suggests smoothing for promo-polluted rows, surfaces stale customers due for review. Renders in /pricing.html. ~1 day. |
| Phase 7 | Quote letter generation | Planned | From approved price list + customer context, AI drafts a PDF/HTML quote letter. Stored in R2 with customer + effective date. Optional email via Email Routing. ~1 day. |
Locked defaults
- Derive rule: median(last 3 invoices) when ≥3 exist in 18-month window, fall back to last_paid otherwise.
- Unsold items: left off the customer's price list; populated at next quote/SO.
- System of record: NetSuite for live orders. D1 holds proposed + history. Platform reviews + pushes.
- Exclusions: credit memos, returns, negative quantities. Bid pricing (custbody1 Bid Reference) tagged separately so AI can distinguish.
New D1 tables
- customer_pricing_proposed — (customer, item, derived_price, source, source_invoice_id, derived_at, status, approved_by, approved_at, notes)
- customer_pricing_history — (customer, item, price, effective_from, effective_to, source, change_reason, changed_by, changed_at) — populated on every push to NS
- pricing_anomalies — (customer, item, anomaly_type, severity, detected_at, resolved) — AI's running output
New endpoints
| Endpoint | Auth | Purpose |
|---|---|---|
| POST /api/pricing/derive | Bearer (admin) | Rebuild customer_pricing_proposed from invoice_lines |
| GET /api/pricing/diff | Bearer | Three-bucket audit across all customers (Listed+Recent, Listed+Stale, Not-Listed+Recent) |
| GET /api/pricing/customer/:id | Bearer | Current + proposed for one customer |
| POST /api/pricing/approve | Bearer (admin) | Mark proposed rows approved / rejected / edited |
| POST /api/pricing/push-to-ns | Bearer (admin) | Worker → SuiteAPI RESTlet bulk write |
| GET /api/pricing/history/:customer/:item | Bearer | Full effective-date history |
Pre-cutover audit (Phase 1 output)
Before any write to NS, the diff endpoint surfaces:
- Listed + Recently paid: stable rows. Drift check (paid price within tolerance of listed price?).
- Listed + Stale: customer hasn't bought this item recently. Candidate to deprecate from list.
- Not-Listed + Recently paid: customer is buying it but it's not on their price list. Negotiated at SO time. Biggest gap to close.
- Open SOs in flight: separate query, surfaces SOs that haven't invoiced yet so cutover doesn't break in-progress orders.
AI's role
- Anomaly detection — "last paid 30% below median, investigate" (Workers AI + customer_pricing_history)
- Smoothing suggestions — propose median over last_paid where the spread is large
- Peer comparison — "12 customers in this program pay $5.45 for item X, customer Y pays $5.20"
- Quote letter generation — draft PDF/HTML quote from approved price list (Phase 7)
- Drift narrative — explain why customer X's price for item Y changed N times this year (reads customer_pricing_history)
- Never auto-approves. Human review is mandatory before any push to NS.
Other Cloudflare roadmap
Non-AI items that depend on Cloudflare products. Sequencing per the GAPS tracker tiers.
| Item | Tier | Detail |
|---|---|---|
| Worker scheduled() handler for sync | Tier 2 GAP | Move sync.sh into the Worker so it calls SuiteAPI directly. Eliminates the single-Mac dependency. ~4 hr. |
| R2 archival of D1 | Tier 2 | Daily Worker cron: wrangler d1 export + put to R2. Rolling retention 30/90/365. ~2 hr. |
| KV caching wrapper | Tier 3 | Wrap /api/kpis, /api/ar/aging, /api/items/performance with KV (TTL 5 min). ~3 hr. |
| Email Routing / Email Workers | Optional | If dunning notices move out of NS or admin alerts (sync failed, gap created) need to go to email. ~2 hr. |
| Browser Rendering API | Optional | If Advanced PDF/HTML limits get hit, render templates via Browser Rendering. ~half a day to wire. |
| Durable Objects | Defer | Only if real-time multi-user state shows up (live dashboard collaboration, in-app chat). Not currently needed. |
Usage & limits
Approximate current usage vs ceiling. Refresh from the Cloudflare dashboard for live values.
| Product | Metric | Current | Ceiling | Headroom |
|---|---|---|---|---|
| Workers | Requests/day | low (manual) | unlimited (Paid) | ∞ |
| D1 | Storage | ~150 MB | 10 GB / DB | 98.5% |
| D1 | Reads/day | low (sync only) | 5M (Paid) | ~100% |
| D1 | Writes/day | low (sync only) | 100K (Paid) | ~100% |
| KV | Reads/day | 0 | 10M (Paid) | 100% |
| R2 | Storage | light | 10 GB free, then $0.015/GB-mo | large |
| Pages | Builds/month | ~5 | 500 free | 99% |
| Pages | Concurrent builds | 1 | 5 free | large |
Cost model
Current monthly burn (Workers Paid plan $5 base). All other usage is within free tiers.
| Line item | Unit cost | Current usage | Monthly $ |
|---|---|---|---|
| Workers Paid plan | $5/mo base | — | $5.00 |
| D1 reads / writes / storage | free up to limits | well under | $0.00 |
| KV ops | free up to limits | 0 | $0.00 |
| R2 storage | $0.015/GB-mo after 10 GB | under 10 GB | $0.00 |
| Pages builds + bandwidth | free | under limits | $0.00 |
| Workers AI (when AI query ships) | per-neuron, ~$0.001–$0.005/query | 0 today | ~$5–30 est at 100 queries/day |
| Vectorize | $0.04/M queried dims; storage tiny | 0 today | ~$1–5 est |
| AI Gateway | free tier covers cache + observability | 0 today | $0.00 |
| Access (Zero Trust) | free up to 50 seats | 0 (not configured) | $0.00 |
Wrangler quick-ref
Cross-links
- Data model — D1 schema, ER diagram, example queries, SuiteQL admin library
- Infrastructure — Worker endpoints (per-endpoint detail), DNS records, bindings, secrets
- Admin dashboard — live health of every Cloudflare service
- ADR-011 — AI stack decision
- GAPS — Tier 1 (Access on Pages), Tier 2 (Worker-side sync, D1 backups)
- Runbook → incident response — sync stopped, D1 quota, Pages down
Related surfaces
Infrastructure
Worker endpoints (per-endpoint detail), cron, bindings, secrets map, DNS records.
Data model
D1 schema, ER diagram, FK relationships, example queries, SuiteQL admin library.
Decision log
11 ADRs covering platform architecture, AI stack, pricing pipeline.
Admin dashboard
Live health, sync status, risk register, known issues, pricing pipeline status.
Runbook
Procedures, checklists, onboarding, secret rotation, incident response, pricing procedures.