{"slug":"operations/DEPLOYMENT_RUNBOOK","title":"Deployment Runbook — Cloudflare (P1 unblock)","section":"operations","sectionLabel":"Operations","status":"unclassified","type":"document","path":"operations/DEPLOYMENT_RUNBOOK.mdx","bytes":5328,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n> **Tier:** B (Operations). Canon: `AGENTS.md` (HARD RULE 3 — deploy), `docs/operations/CF_WIRE_STATUS.md`.\n> **Date:** June 12, 2026 | **Purpose:** Make the blocked frontend deploy + Live Verification a true\n> release gate. The code/workflows are ready; the only blockers are **credentials/secrets** (your\n> dashboard action). No token or account-ID values appear in this file (HARD RULE 2).\n\n---\n\n## TL;DR — what's blocked and why\n\n```text\nCode ✓   Workflows ✓   Tests ✓   Live Verify (wired, non-blocking)   Pages Deploy ✗ (token scopes)\n```\n\nThe Pages deploy fails with `Authentication error [code: 10000]` / missing `User → Memberships → Read`.\nThat's a **token-scope** problem, not a code problem. Fix the token + a few secrets and the whole\ndeploy + verification chain turns green.\n\n---\n\n## Fix 1 — Cloudflare API token (the actual blocker)\n\n`wrangler pages deploy` needs a token that can edit Pages **and** read the user/membership it runs as.\nCreate/edit the token in the Cloudflare dashboard (My Profile → API Tokens) with these permissions:\n\n| Scope                                               | Permission |\n| --------------------------------------------------- | ---------- |\n| Account → **Cloudflare Pages**                      | **Edit**   |\n| User → **Memberships**                              | **Read**   |\n| User → **User Details**                             | **Read**   |\n| (workers deploy only) Account → **Workers Scripts** | **Edit**   |\n\nAccount resource: the IntegrateWise account (id is in `AGENTS.md` / dashboard — do not paste it into code).\n\nThen set it as the GitHub repo secret **`CLOUDFLARE_API_TOKEN`** (Settings → Secrets and variables →\nActions). Also confirm **`CLOUDFLARE_ACCOUNT_ID`** secret is set to the IntegrateWise account id.\n\n> The classic \"Edit Cloudflare Workers\" template often omits **User → Memberships → Read**, which is\n> exactly the `code 10000` failure. Add it explicitly.\n\n## Fix 2 — VITE\\_\\* build secrets (so the deployed app actually boots)\n\nThe build embeds runtime config. Without these the deployed SPA boots blank/stuck (the same reason\nthe Live Verification e2e can't reach the workspace on a bare runner). Set as GitHub secrets:\n\n| Secret                                                      | Used for                                              |\n| ----------------------------------------------------------- | ----------------------------------------------------- |\n| `VITE_API_BASE_URL`                                         | gateway base (e.g. the auth/gateway URL)              |\n| `VITE_SUPABASE_URL` / `VITE_SUPABASE_ANON_KEY`              | legacy client bootstrap (until de-Supabase completes) |\n| `VITE_STREAM_URL`                                           | stream gateway (optional)                             |\n| `VITE_POSTHOG_KEY` · `VITE_SENTRY_DSN` · `VITE_LANDING_URL` | optional analytics/links                              |\n\n(Names only — values live in Cloudflare/GitHub secrets, never in the repo.)\n\n## Fix 3 — confirm the Pages project exists\n\nWorkflows deploy to `--project-name=integratewise`. Confirm a Pages project named **`integratewise`**\nexists in the account (Cloudflare → Workers & Pages). Landing uses `integratewise-landing`.\n\n---\n\n## Verify (after the fixes)\n\n1. **Frontend preview deploy** — push to a `feat/**` or `staging` branch, or run _Deploy Frontend_\n   manually. Expect a `*.integratewise.pages.dev` preview URL in the run summary. Pushes to `main`\n   deploy straight to `app.integratewise.ai` instead (see below).\n2. **Live Verification becomes real** — set the GitHub secret **`PLAYWRIGHT_BASE_URL`** to the preview\n   (or `app.integratewise.ai`) and run _Live Verification → e2e_. The CS-persona projection guard then\n   runs against a real deployed app instead of a bare dev server.\n3. **Health check** — after an approved release, verify the deployed Pages URL and the Gateway health endpoint for that environment.\n\n---\n\n## Production deploys\n\n- Frontend source changes on `main` continue through `deploy-frontend.yml`. Lockfile-only and workflow-only\n  changes do not publish Pages. `deploy-cloudflare.yml` is the deliberate manual frontend path; select a\n  dry run first, then an approved environment.\n- Core Workers never deploy from a push. Use **Release Core Workers** (`deploy-workers.yml`) for a test\n  preflight/release first. The `production` environment is restricted to `main`; a production release also\n  requires explicit confirmation and a reference to successful test-release evidence. The canonical script\n  deploys Gateway last.\n- **Local wrangler:** `unset CLOUDFLARE_API_TOKEN` before any local `wrangler` command so the\n  OAuth session (connect@integratewise.ai) is used (AGENTS.md). CI uses the token instead.\n\n---\n\n## The cascade (why this is P1)\n\n```text\nFix token + VITE_* secrets\n   ├─▶ Frontend preview deploys (green)\n   │      └─▶ PLAYWRIGHT_BASE_URL set → Live Verification runs against real app\n   │             └─▶ CS-persona projection guard becomes a true release gate\n   └─▶ Deployed SPA boots with real config (no blank/stuck workspace)\n```\n\nOne credential fix unblocks deploy, live verification, and the regression gate together.\n"}