apps/chat has native TanStack Start + Vite+ + Void source beside its Next build,
generated by the start-bridge codemod. The Next
build and vercel.json are untouched, so the current deployment keeps serving until
the route is flipped. vercel-production-chat.yaml still deploys the Next app.
Worker
- Staging candidate: the staging Worker name (
workers_devandpreview_urlsoff,TUTURUUU_NOINDEX=1). Production profileVITE_CHAT_NATIVE_PROFILE=productionemitstuturuuu-chatwith the same flags,TUTURUUU_NOINDEX=0, and no routes. The operator attacheschat.tuturuuu.comat cutover; config never declares a route. - Entry:
apps/chat/cloudflare/worker.ts; Wrangler config is emitted byvoidintodist. The cutover job seals that emitted config, includingconfigPath,userConfigPath,topLevelName, anddefinedEnvironments. - Host:
chat.tuturuuu.com. Root-only:mountHostsis empty andunknownHostisreject, sotuturuuu.com/chatand any other host answer 404 before app code runs. - Binding:
ASSETSonly (static output,run_worker_first). No Durable Object binding and no realtime service binding. - Variables (names):
TUTURUUU_NOINDEX(0on the production profile), optionalINTERNAL_WEB_API_ORIGIN(defaulthttps://tuturuuu.com). - Secrets (names, set on the Worker before the flip, never in the repo):
NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY,SUPABASE_SECRET_KEY,TUTURUUU_APP_COORDINATION_SECRET.TUTURUUU_APP_COORDINATION_SECRETmust be exactly Web’s signer value (theSUPABASE_SECRET_KEYvalue).apps/chat/vite.config.mtsdoes not inject a startup secret check, and the Worker entry has norequired-secretsassertion, so a missing name is not a startup 500 from those gates. Auth and the Supabase server client read the four names above. Compare with the Vercel project environment list before the flip. - Not Worker requirements:
UPSTASH_REDIS_REST_URL,UPSTASH_REDIS_REST_TOKEN, andABUSE_GUARD_BACKEND. The API proxy guard fails open when Upstash is absent.CHAT_REALTIME_TOKEN_SECRETandCHAT_REALTIME_INTERNAL_URLbelong toapps/webandapps/chat-realtime, not this Worker. See the Chat realtime runbook. - Optional variables read by the source:
CHAT_APP_URL,NEXT_PUBLIC_CHAT_APP_URL,NEXT_PUBLIC_APP_URL,WEB_APP_URL,NEXT_PUBLIC_WEB_APP_URL. Production falls back tohttps://chat.tuturuuu.comandhttps://tuturuuu.comwhen they are unset.
Build and qualification
chat-cloudflare.yaml job chat-cutover-artifact runs the same production-profile build and seals the output with scripts/ci/chat-native-artifact.py (CHAT_SOURCE_SHA mapped onto APPS_SOURCE_SHA). The sealed Worker name is tuturuuu-chat, workers_dev is false, and the config has no routes. Run the build on a CI or remote runner, not a developer machine.
The native job builds with the profile unset (the staging Worker name). test:runtime starts the emitted Worker in workerd
with synthetic secrets and no network egress: build identity, root host, apex rejection,
unknown paths, and the signed-out redirect through the app-owned
cloudflare/auth-redirect.runtime.mjs fixture (8 checks).
The app proxy admits anonymous GET/HEAD /api/build-info without an app-session
refresh, so deployment verification gets 200 instead of 401.
Smoke checks after the route is attached
5xx.
Rollback
- Before the flip, record the current production Vercel deployment id for the app (the repo
does not store it) and the DNS records and TTLs for
chat.tuturuuu.comin the release record. - Roll back by detaching the Worker route or restoring the captured DNS records to the
recorded deployment.
vercel-production-chat.yamlstill deploys the Next app. - Rerun the smoke checks against the previous origin.