Skip to content

feat: pluggable CDN deploy provider — Cloudflare R2 via Alchemy (Zephyr fallback) - #58

Open
elliotBraem wants to merge 4 commits into
mainfrom
feature/cloudflare-cdn-alchemy
Open

feat: pluggable CDN deploy provider — Cloudflare R2 via Alchemy (Zephyr fallback)#58
elliotBraem wants to merge 4 commits into
mainfrom
feature/cloudflare-cdn-alchemy

Conversation

@elliotBraem

Copy link
Copy Markdown

Summary

Implements Phases 0–2 of plans/infra/cloudflare-cdn-alchemy.md: a pluggable CDN deploy provider for bos publish --deploy. Railway keeps the whole app (host executes api/ui/plugin MF remotes in-process); Cloudflare R2 (custom domain cdn.citynode.app, managed by Alchemy) replaces Zephyr for MF remote bundles. Zephyr stays the default and remains a selectable fallback.

  • [deploy] config sectiondeploy.cdn: "zephyr" | "cloudflare" + optional deploy.cloudflare (hostname, bucket, zone), ordered between ci and app, merged through extends, staging-aware domain resolution, legacy ci.railway.service mapping (resolveDeployConfig)
  • Provider gateBOS_CDN_PROVIDER env + useZephyr gate in all 8 rspack/rsbuild configs; cloudflare builds skip Zephyr and don't expect deploy URLs
  • Alchemy pipelineeverything-dev/cdn module: pinned sandbox install in .bos/alchemy/ (isolated Effect 4 peer resolution — alchemy 2.x peers on effect ≥4 while this repo pins 3.21), generated alchemy.run.ts (R2 bucket + custom domain + CORS + per-workspace upload Actions), publish orchestration with fail-fast credential checks, local SRI computation, R2 URLs written into bos.config.json before the FastKV publish
  • bos cdn login — first-class command (installs the sandbox, runs the alchemy OAuth flow)
  • Live state committeddeploy.cdn: "cloudflare" + cdn.citynode.app URLs (deployed and published to FastKV)

Usage

bos cdn login            # one-time, installs .bos/alchemy sandbox + OAuth
bos publish --deploy     # builds all workspaces → alchemy deploy → FastKV publish

Rollback: set "cdn": "zephyr" and re-run bos publish --deploy.

Known issues

  • R2 uploads currently store content-type: application/octet-stream and no cache-control — a @distilled.cloud/core bug (protocol-http.ts body attachment unconditionally overwrites the explicit Content-Type header) plus the R2 REST PUT path not persisting Cache-Control. Symptom: the deployed CDN serves stylesheets as octet-stream (browsers refuse them — "no CSS"). Root cause fully diagnosed; fix (S3-compatible uploads via aws4fetch + R2 S3 tokens, or upstream SDK bump) lands as a follow-up on this branch, followed by a cdn.citynode.app edge-cache purge. Until then the deployed UI is unstyled.
  • CI deploy workflow will fail at the credentials fail-fast once this merges (no CLOUDFLARE_* secrets yet) — Phase 3 wiring is a follow-up; local deploys are unaffected.

Follow-ups

  • Fix R2 upload metadata + edge purge (tracked locally in .scratch/cloudflare-cdn/issues/02-r2-upload-metadata.md)
  • Phase 3: CI secrets (CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, CI=true)
  • Effect 4 migration → collapse the alchemy sandbox into a direct dependency (.scratch/cloudflare-cdn/issues/01-effect-4-migration-and-alchemy-desandbox.md)

Verification

  • everything-dev: 410 tests pass (28 new: deploy-config, build-cdn-provider, cdn)
  • api: 87 tests pass · host: 143 tests pass
  • bun typecheck (8 workspaces) and bun lint (605 files) clean
  • Live smoke: sandbox resolves effect@4.0.0-rc.112; generated stack imports cleanly; bos cdn login + full local deploy executed end-to-end

…2 via Alchemy

Add deploy.cdn provider selection (zephyr default, cloudflare opt-in) with a
bos-managed Alchemy sandbox in .bos/alchemy, alchemy.run.ts generation (R2
bucket + custom domain + CORS + per-workspace upload Actions), local SRI
computation, publish orchestration with fail-fast credential checks, and a
first-class bos cdn login command. Gate withZephyr behind BOS_CDN_PROVIDER
in all build configs.
….md provider guide

Add plans/infra/cloudflare-cdn-alchemy.md (phases 0-2 done), correct the stale
toml-infra-alchemy.md phase status, and document the deploy.cdn option and
bos cdn login in AGENTS.md.
Set deploy.cdn to cloudflare and adopt the cdn.citynode.app R2 URLs written
by the deploy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant