Services

2026 06 16 Deployment Docs Review


Cloudflare deployment docs/task surface review — 2026-06-16

Scope: repo-level Cloudflare deployment, task, and documentation surfaces: .mise.toml, root package.json, .docs/cloudflare-deployment.md, docs/cloudflare-*.md, docs/hosting-inventory-2026-06-16.md, and docs/performance-smoke-checks.md. App Wrangler/OpenNext files were inspected only where needed to verify drift claimed by repo-level docs or tasks.

No Cloudflare APIs were called, no deployments were run, and no secrets were printed.

Guidance baseline used#

  • Cloudflare skills index prefers CF_API_TOKEN, optionally mirrored to CLOUDFLARE_API_TOKEN, plus CF_ACCOUNT_ID for account-level Workers/Storage/Pages operations; it also documents least-privilege scopes for Workers, KV/D1/R2, Pages, and DNS.
  • Cloudflare Pages guidance prefers Wrangler for uploads/deploys, REST only where Wrangler lacks coverage, and says to coordinate DNS through the Service Registry when the registry owns the zone.
  • Cloudflare Workers guidance prefers route declarations in wrangler.toml/wrangler.jsonc and notes that svc.assistance.bg/internal routing is typically Service Registry-owned.
  • Cloudflare Storage guidance requires explicit KV/D1/R2 bindings and careful token/scopes for storage operations.
  • Service Registry guidance says https://registry.svc.assistance.bg is the default routed endpoint, svc.assistance.bg hosts are registry/Caddy/split-horizon managed, and new internal hosts should use delegated subzones rather than flat public-domain/internal-zone names.

Positive findings#

  • The repo has a centralized mise Cloudflare surface for build, deploy, release, D1 indexing, and health checks (.mise.toml:1396-1656).
  • Root package.json pins Wrangler as a managed dev dependency and exposes Cloudflare performance-budget scripts (package.json:30-32, package.json:96, package.json:125-134).
  • The hosting inventory captures the current high-level topology: Pages for www/manager, Workers+OpenNext for docs/blog/academy/design-system/ui-library, and self-hosted Go backends (docs/hosting-inventory-2026-06-16.md:17-36).
  • Aggregate deploys include a preflight that prevents the most common OpenNext/KV auth failure by requiring CLOUDFLARE_API_TOKEN before parallel deploys (.mise.toml:1477-1513).

Findings#

1. Health/smoke targets do not match repo-declared Cloudflare routes#

  • Severity: High
  • Evidence:
    • cf:health checks flat hostnames for all frontend apps: docs.assistance.bg, ds.assistance.bg, ui.assistance.bg, academy.assistance.bg, manager.assistance.bg, and blog.assistance.bg (.mise.toml:1643-1656).
    • prod:smoke checks only www.assistance.bg, manager.assistance.bg, and docs.assistance.bg for frontends (.mise.toml:959-967).
    • The only inspected Worker config with explicit routes is apps/docs/wrangler.jsonc, and those routes are path-based: www.assistance.bg/docs* and assistance.bg/docs* (apps/docs/wrangler.jsonc:7-14).
    • docs, blog, design-system, and ui-library set workers_dev=false, but only docs has repo-declared routes; blog, design-system, and ui-library have no routes in their checked Wrangler configs (apps/blog/wrangler.jsonc:5, apps/design-system/wrangler.jsonc:5, apps/ui-library/wrangler.jsonc:5).
  • Why this matters: a deployment can pass wrangler deploy while the repo health task probes hostnames that are not declared in repo-managed routing. Conversely, a correct path-based deployment (www.assistance.bg/docs*) may be reported unhealthy by checks against docs.assistance.bg.
  • Recommended fix:
    1. Decide the canonical public URL per app.
    2. If flat hostnames are canonical, declare the corresponding Workers routes/custom domains in the relevant Wrangler configs or document the external dashboard-managed source of truth.
    3. If path-based composition is canonical, change cf:health and prod:smoke to probe the actual routes, e.g. https://www.assistance.bg/docs/ for docs and the Pages Function paths for blog/docs where applicable.

2. Academy enables OpenNext KV incremental cache without a Wrangler KV binding#

  • Severity: High
  • Evidence:
    • apps/academy/open-next.config.ts imports and enables kvIncrementalCache (apps/academy/open-next.config.ts:3-7).
    • apps/academy/wrangler.jsonc declares the Worker entry, nodejs_compat, and Workers Assets, but has no kv_namespaces binding (apps/academy/wrangler.jsonc:1-10).
    • The hosting inventory already flags that no KV namespace was present for academy (docs/hosting-inventory-2026-06-16.md:33).
    • Other OpenNext apps using KV expose a NEXT_INC_CACHE_KV binding in Wrangler config (apps/blog/wrangler.jsonc:12-16, apps/design-system/wrangler.jsonc:12-16, apps/ui-library/wrangler.jsonc:12-16, apps/docs/wrangler.jsonc:19-23).
  • Why this matters: this is a repo-local OpenNext/storage binding drift. Depending on adapter behavior, academy can fail during deploy/runtime cache operations or silently lose intended incremental-cache behavior.
  • Recommended fix: choose one desired state and make config/docs agree:
    • If academy needs KV incremental cache, provision a namespace and add NEXT_INC_CACHE_KV to apps/academy/wrangler.jsonc with the same binding convention as other OpenNext apps.
    • If academy should not use KV, remove the kvIncrementalCache override from apps/academy/open-next.config.ts and update docs that currently imply academy is a normal KV-backed Worker.

3. .docs/cloudflare-deployment.md DNS guidance is stale and boundary-blurring#

  • Severity: Medium
  • Evidence:
    • The doc says www.assistance.bg is “managed in Cloudflare DNS (proxied, orange cloud)” (.docs/cloudflare-deployment.md:109-112).
    • It also says internal dev/prod subzones are NS-delegated to Linode and then recommends mcp__registry__dns_cloudflare/mcp__registry__dns_linode generically (.docs/cloudflare-deployment.md:113-128).
    • Current repo tasks and inventory focus on public assistance.bg app hostnames and Pages/Workers deployments, not the nested assistance.prod.assistance.bg / assistance.dev.assistance.bg tree shown in that doc (.mise.toml:1528-1554, docs/hosting-inventory-2026-06-16.md:79-105).
    • Service Registry guidance draws a stricter boundary: svc.assistance.bg internal hosts are registry/Caddy/split-horizon managed, while Cloudflare Pages/Workers custom-domain bindings and public-zone DNS need explicit coordination.
  • Why this matters: an operator following the stale DNS section could mutate the wrong DNS plane, assume flat public hostnames are registry-owned, or miss that Worker routes/custom domains must align with the actual Cloudflare zone.
  • Recommended fix: rewrite the DNS section around ownership boundaries:
    • Public assistance.bg Cloudflare zone: use Cloudflare DNS/Workers routes/custom-domain guidance and avoid hardcoded zone IDs.
    • Registry/Linode/split-horizon zones: use Service Registry MCP/API, especially for svc.assistance.bg, delegated service subzones, and Caddy exposure.
    • Document the current canonical app URL map and where each URL is configured (wrangler route, Pages custom domain, registry record, or external dashboard state).

4. Token and secret handling is partially documented but inconsistent across surfaces#

  • Severity: Medium
  • Evidence:
    • cf:deploy:preflight requires only CLOUDFLARE_API_TOKEN and prints minimum scopes for Workers Scripts, Workers KV Storage, and Pages (.mise.toml:1477-1492).
    • The Cloudflare skills baseline prefers CF_API_TOKEN, with CLOUDFLARE_API_TOKEN as a compatibility alias, and also calls out CF_ACCOUNT_ID for account-level operations.
    • .docs/cloudflare-deployment.md lists deploy and D1 index commands but does not document required env vars/scopes for deploys, Pages secrets, D1 indexing, or Worker routes (.docs/cloudflare-deployment.md:62-79, .docs/cloudflare-deployment.md:147-157).
    • apps/www/wrangler.toml correctly keeps form secrets as comments/instructions rather than values (apps/www/wrangler.toml:5-9).
  • Why this matters: missing/ambiguous env guidance causes late failures in parallel deploys or D1 indexing, and inconsistent token naming increases the chance operators set one variable while a task expects another.
  • Recommended fix:
    • Add a single “Cloudflare auth and secrets” section to .docs/cloudflare-deployment.md covering CF_API_TOKEN, CLOUDFLARE_API_TOKEN=$CF_API_TOKEN, CF_ACCOUNT_ID, Pages secrets via wrangler pages secret put, and least-privilege scopes.
    • Either teach cf:deploy:preflight to accept CF_API_TOKEN by exporting CLOUDFLARE_API_TOKEN when absent, or document that this repo’s deploy tasks require the CLOUDFLARE_API_TOKEN alias specifically.
    • Add D1-specific scope/account guidance near mise run cf:index:search.

5. Verification coverage is not explicit enough for the full Cloudflare surface#

  • Severity: Low
  • Evidence:
    • cf:build runs all app builds and then check:links:prod, but that link task covers only www, docs, and academy (.mise.toml:1396-1402, .mise.toml:1344-1361).
    • Per-app release tasks for blog, manager, design-system, and ui-library build and deploy without link checks (.mise.toml:1581-1641).
    • docs/performance-smoke-checks.md documents local performance smoke checks for www, docs, and blog only, plus root pnpm perf:* scripts (docs/performance-smoke-checks.md:10-38, package.json:30-32).
    • Recent Cloudflare performance docs recommend per-app build evidence, route/cache smoke checks, and artifact budgets, but the deployment doc does not provide a current verification matrix.
  • Why this matters: operators can overstate “Cloudflare is green” from checks that do not cover every deployed app or from local smoke checks that do not prove deployed routes.
  • Recommended fix: add a verification matrix to .docs/cloudflare-deployment.md that separates:
    • build proof (mise run cf:build:*),
    • deploy proof (mise run cf:deploy:*),
    • post-deploy HTTP route proof (mise run cf:health, after fixing canonical URLs),
    • link checks for apps with specs,
    • artifact budgets (pnpm perf:cf-budgets / pnpm perf:check), and
    • local-only performance smoke checks.

Changes applied in this review#

No existing deployment tasks or docs were edited. The findings above require operator decisions about canonical hostnames, DNS ownership, and academy cache behavior, so this review records recommended fixes rather than guessing.