From 6365428291d51cb77db993dd5b7197fc936229a0 Mon Sep 17 00:00:00 2001 From: agentnightshift Date: Mon, 22 Jun 2026 15:40:39 -0500 Subject: [PATCH] fix(deploy): catch missing prod alias before functions deploy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firebase CLI v14+ shows the resolved project ID in `firebase use` output whether the project was set via alias (prod) or raw project ID (my-brain-88870), making them indistinguishable. Deploying with the raw project ID silently skips functions/.env.prod, leaving MCP_CLIENT_PROFILES_JSON out of the bundle and causing all /clients/:id/mcp endpoints to 404. - preflight: read the Firebase CLI configstore directly to verify the stored value is the 'prod' alias, not the raw project ID; fail with a clear error and fix command if wrong - DEPLOYMENT.md step 5: warn that --project my-brain-88870 silently skips .env.prod; use --project prod if an explicit flag is needed - DEPLOYMENT.md post-deploy: add step 3 — quick CORS preflight against both client endpoints immediately after deploy to catch missing client profiles before the full smoke test Co-Authored-By: Claude Sonnet 4.6 --- docs/DEPLOYMENT.md | 47 +++++++++++++++++++++++++---- scripts/deploy-session-preflight.sh | 31 ++++++++++++++++++- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index f4a9390..bd44afe 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -298,6 +298,12 @@ cd /Users/nick/git/metacortex firebase deploy --only firestore:indexes,functions ``` +> **Important:** always use `firebase deploy` with the `prod` alias active (confirmed in step 1), +> not `firebase deploy --project my-brain-88870`. Firebase loads `functions/.env.prod` based on +> the **alias** name, not the project ID. Passing the raw project ID silently skips `functions/.env.prod` +> and omits `MCP_CLIENT_PROFILES_JSON` from the deployment, causing all client endpoints to 404. +> Use `firebase deploy --project prod` if you need to pass the project explicitly. + Capture the deployed base URL for `metaCortexMcp`. The useful production routes are: @@ -347,7 +353,36 @@ Expected: - HTTP `401` -### 3. Browser CORS preflight +### 3. Client profile deployment check + +Verify that `MCP_CLIENT_PROFILES_JSON` was bundled into the deployed function by checking +that client endpoints resolve (not 404). A `404` here means the env file was not picked up — +the most common cause is deploying with the raw project ID instead of the `prod` alias. + +```bash +curl -s -o /dev/null -w "%{http_code}\n" \ + -X OPTIONS "/clients/chatgpt-web/mcp" \ + -H "Origin: https://chatgpt.com" +# Expected: 204 +``` + +```bash +curl -s -o /dev/null -w "%{http_code}\n" \ + -X OPTIONS "/clients/claude-web/mcp" \ + -H "Origin: https://claude.ai" +# Expected: 204 +``` + +If either returns `404`, the client profiles were not deployed. Fix: + +```bash +firebase use prod +firebase deploy --only functions +``` + +### 4. Browser CORS preflight details + +Confirm the correct origin headers are returned: ```bash curl -i \ @@ -368,7 +403,7 @@ curl -i \ -H "Origin: https://claude.ai" ``` -### 4. Authenticated admin MCP smoke test +### 5. Authenticated admin MCP smoke test ```bash cd /Users/nick/git/metacortex/functions @@ -391,7 +426,7 @@ This is the first proof that: - Firestore writes work - Firestore vector search works -### 5. Authenticated browser MCP smoke test +### 6. Authenticated browser MCP smoke test ```bash cd /Users/nick/git/metacortex/functions @@ -411,7 +446,7 @@ Repeat the same smoke test against `/clients/claude-web/mcp` with `/dev/null 2>&1; then - firebase use || true + ACTIVE_PROJECT="$(firebase use 2>/dev/null)" + echo "Active project: ${ACTIVE_PROJECT}" + + # Firebase CLI v14+ displays the resolved project ID even when an alias is active, so + # "firebase use" output is ambiguous — it looks identical whether you set the project via + # "firebase use prod" (alias, picks up functions/.env.prod) or "firebase use my-brain-88870" + # (raw project ID, skips functions/.env.prod). Read the configstore directly to check which + # value is actually stored for this directory. + EXPECTED_ALIAS="prod" + STORED_ALIAS="$(node -e " +try { + const os = require('os'); + const path = require('path'); + const configPath = path.join(os.homedir(), '.config', 'configstore', 'firebase-tools.json'); + const data = JSON.parse(require('fs').readFileSync(configPath, 'utf8')); + process.stdout.write(data.activeProjects?.[process.cwd()] ?? ''); +} catch { process.stdout.write(''); } +" 2>/dev/null)" + + if [[ -z "$STORED_ALIAS" ]]; then + echo "warning: could not read active project alias from Firebase configstore — skipping alias check" + elif [[ "$STORED_ALIAS" != "$EXPECTED_ALIAS" ]]; then + echo "ERROR: active project is set to '${STORED_ALIAS}', not the '${EXPECTED_ALIAS}' alias." >&2 + echo " Deploying with the raw project ID skips functions/.env.prod and omits MCP_CLIENT_PROFILES_JSON," >&2 + echo " causing all client endpoints to return 404." >&2 + echo " Fix: firebase use ${EXPECTED_ALIAS}" >&2 + exit 1 + else + echo "Alias '${EXPECTED_ALIAS}' confirmed (stored: '${STORED_ALIAS}' → ${ACTIVE_PROJECT})" + fi else echo "warning: firebase CLI not installed" fi