# 2026-05-13 cypher-executor outbound fetch 全失效（CF 同 zone 自循環死鎖）

> **總耗時**：約一整天 debug
> **根因**：Cloudflare Workers 對「綁 custom domain 的 Worker fetch 同 zone 另一個 custom domain Worker」會撞 zone routing 死鎖 → 回 522
> **修法**：cypher-executor fetch component worker 改走 `*.workers.dev` 子域（不同路由系統，繞過 zone proxy）
> **影響**：mira 7B.3c 阻擋一整天；封測 P0 從「全綠」revert 成 #9 阻擋

---

## 症狀

mira 跑 `acr run wiki_synthesis`（5 節點 workflow，含 kbdb_get / claude_api）回：

```
n1 → {"success": false, "status": 522, "error": "error code: 522"}
```

每節點精準 ~1000ms timeout 後 522。

進一步測試發現**所有 outbound HTTP fetch from cypher-executor 都 522**，無論目標是：

- 同 zone：`kbdb-get.arcrun.dev`、`claude-api.arcrun.dev`、`cypher.arcrun.dev/health`（self）
- 外部：`httpbin.org`、`github.com`、`google.com`

但 **service binding 路徑（SVC_STRING_OPS 等 15 個邏輯零件）完全正常**。

## 觀察矩陣

| 路徑 | 結果 |
|---|---|
| 本機 curl → kbdb-get.arcrun.dev | 200 ✓ |
| cypher-executor → kbdb-get.arcrun.dev (HTTP fetch) | **522** |
| cypher-executor → claude-api.arcrun.dev (HTTP fetch) | **522** |
| cypher-executor → httpbin.org (HTTP fetch) | **522** |
| cypher-executor → string_ops (Service Binding) | 200 ✓ |
| `acr run hello`（純 SB 1 節點）| 200 ✓ |
| `acr run`（5 節點純 SB chain，wallTime 2.2s）| 200 ✓ |
| **wrangler dev（本機跑 cypher-executor）→ httpbin / kbdb-get** | **200 ✓** |
| 同 src 部署成 `arcrun-cypher-executor-probe`（純 workers.dev，無 routes 綁定）→ httpbin / kbdb-get / claude-api | **200 ✓** |

最關鍵兩條：

1. **本機 wrangler dev 跑同 src，fetch 全通** → 不是 code bug，是 prod 環境問題
2. **probe worker（同 src、不同 name、走 workers.dev、無 cypher.arcrun.dev route）→ 全通** → 是 `cypher.arcrun.dev/*` route 觸發的環境問題

## 誤判路徑（重要 — 避免重犯）

| 假設 | 為什麼錯 |
|---|---|
| **A. CF Free Tier 10ms CPU cap**（首先猜的）| 5 節點 SB chain 跑 2.2 秒卻通過，CPU cap 假設立刻被推翻。但前期 debug 走了不少彎路 |
| **B. 用戶從 Paid 掉到 Free** | 用戶確實掉到 Free，當下繳費恢復 Paid，**重測仍全 522**，徹底排除付費假設 |
| **C. compatibility_date 太舊（2025-02-19）**| 沒嘗試 bump，但本機 dev 跟 prod 同個 compatibility_date 一通一不通，**不是這個** |
| **D. 5/8-5/9 manual deploy 推了壞掉的 unpushed commits** | git diff 本機 vs origin/main 確實有 3 個 unpushed commits，但檢查 prod bundle 內 `makeHttpRunner` 跟本機 src 一字不差。**code 沒問題** |
| **E. Bot Fight Mode / WAF 攔截 outbound fetch** | 用戶截圖 zone Security 設定，Bot Fight Mode 未開。**不是這個** |
| **F. 帳號層 outbound network policy 限制** | dashboard worker bindings 完全乾淨（無 outbound worker / tail consumer / Hyperdrive 等），**不是這個** |
| **G. CF Worker subrequest quota** | wrangler tail 顯示 `wallTime: 497ms, cpuTime: 2ms, outcome: ok` —— cypher-executor 自己沒撞任何 quota，是 fetch 出去就被攔 |
| **H. u6u-mcp service trigger 攔截** | 那是 reverse direction（u6u-mcp 把 cypher-executor 當 service binding 呼叫），跟 outbound fetch 無關 |

**共通教訓**：522 來自「fetch 出去就被攔截，cypher-executor 不知情把 522 包成 component output 回 client」。wrangler tail 看 cypher-executor outcome 是 `ok` —— **不要被 worker 自己的 `ok` 騙了**，要看 trace 內 component output 才是真相。

## 真相

CF Workers 對「綁 custom domain Worker A 用 `fetch()` 打同 zone 另一個 custom domain Worker B」會撞 **zone reverse proxy 路由死鎖**。具體機制（推測）：

1. cypher.arcrun.dev/* route 觸發 → cypher-executor 收到請求
2. cypher-executor 內部 `fetch("https://kbdb-get.arcrun.dev/")` 出去
3. CF edge 看「目標 hostname 是同 zone (`arcrun.dev`)，有 worker route」 → 走 zone reverse proxy
4. 同 zone re-entry 觸發 CF 自循環防護 → fetch 不能完成
5. 對 cypher-executor 表現為「fetch 等到 timeout，得到一個假 522 response」
6. cypher-executor 不知情，把 522 當作 component 真實回應傳回 client

httpbin.org 也 522 不是 same-zone 問題，可能是「進入 outbound fetch code path 就被同樣機制 abort」的副作用（這部分仍不完全清楚，但實證 workers.dev 路徑無此問題）。

**`*.workers.dev` 不走 zone reverse proxy**，是 CF 內部的另一條路由（worker-to-worker internal routing），不撞死鎖。**Service Binding 同理**（不走網路，process 內呼叫）。

## 為什麼以前能跑

4/18 arcrun.md 記錄「httpbin_post 端對端驗證通過」，當時 cypher-executor 也是綁 cypher.arcrun.dev/*，也是 fetch *.arcrun.dev，**卻能通**。推測 CF 之後某次平台更新收緊了 same-zone fetch 防護，但確切時間不可考。

→ **教訓**：CF 平台行為會悄悄變，依賴 `fetch(*.same-zone.dev)` 是脆弱設計，從此架構上不該再依賴。

## 修法

**改 4 個檔案**（commit see git log around 2026-05-13）：

1. `cypher-executor/src/lib/component-loader.ts`：
   - `wasmWorkerUrl(canonicalId, subdomain)` 簽名加 `subdomain` 參數
   - URL pattern 從 `https://${kebab}.arcrun.dev` 改為 `https://arcrun-${kebab}.${subdomain}.workers.dev`
   - 兩個 caller（line 128 / line 192 fallback）同步改

2. `cypher-executor/src/actions/auth-dispatcher.ts`：
   - `wasmWorkerUrl(...)` 呼叫同步加 `subdomain` 參數，從 `env.WORKER_SUBDOMAIN` 取

3. `cypher-executor/src/types.ts`：
   - `Bindings` 加 `WORKER_SUBDOMAIN: string`

4. `cypher-executor/wrangler.toml`：
   - `[vars]` 加 `WORKER_SUBDOMAIN = "uncle6-me"`

**Dashboard 一次性手動操作**：5 個 P0 component worker（kbdb-get / kbdb-ingest / kbdb-create-block / kbdb-patch-block / claude-api）→ Settings → Domains & Routes → workers.dev → **Enable**

**未來新增 component worker 時必須**：dashboard 啟用 workers.dev URL（rule 03 已加入步驟 5）

## 驗證

修復後重測同樣 3 個 trigger：

| Trigger | 修復前 | 修復後 |
|---|---|---|
| cypher → kbdb-get | 522 (1064ms) | **200 (2027ms)** 拿回真實 block 內容 |
| cypher → claude-api | 522 (1014ms) | **200 (6226ms)** Claude 真實回應 |
| cypher → httpbin | 522 (1023ms) | 404 error 1042（不是 522 死鎖了；外部 fetch 限制是另一個問題，不影響 mira）|

mira `acr run wiki_synthesis` 5 節點 workflow 跑通前 3 節點（load_schema / load_skill / load_entities），後續節點失敗是 mira 業務邏輯問題（Unauthorized 在某個 block id），不是 cypher-executor 平台問題。

## 影響範圍與善後

**影響**：

- 任何用 cypher-executor 跑外部 fetch 的 workflow 都壞（封測 Step 2/5/6 / mira / 自架用戶）
- arcrun 「每個零件 = 公開 URL」承諾在純 `*.arcrun.dev` 體系下無法跟「cypher-executor HTTP fetch」並存

**善後（已做）**：

- ✅ rule 01-tech-stack.md：URL 慣例改為「對內 workers.dev / 對外 arcrun.dev」二元
- ✅ rule 03-component-architecture.md：第一核心概念改為「每個零件 = 兩個 URL」，部署步驟加 dashboard workers.dev enable
- ✅ arcrun.md P0 #9 標 resolved 並 reference 本 incident
- ✅ probe worker 已刪
- ⏳ mira tasks.md 7B.3c 解除阻擋（即將）

## 未來怎麼避免

1. **新 component worker 部署 checklist 強制包含 dashboard workers.dev enable**（rule 03 已加，但實務上靠 dashboard 容易忘，未來可考慮寫 deploy 後驗證 script）
2. **不要再加 outbound HTTP fetch 對同 zone hostname** —— cypher-executor 對任何 `*.arcrun.dev` 的 fetch 都該走 workers.dev URL
3. **wrangler dev 是診斷神器** —— 本機跑 prod 同份 src 是區分「環境問題 vs code 問題」最快方法，未來 prod 出怪異行為先跑這個
4. **wrangler tail outcome:ok 不代表沒問題** —— 要看 component trace output 才是真相
5. **Self-hosted fork 文件要明寫**：必須改 `WORKER_SUBDOMAIN` + 所有 component worker dashboard 啟用 workers.dev（rule 03 已加，BETA_TEST.md 待 onboarding 章節加）

## Reference

- 對應 SDD：`matrix/arcrun/.agents/specs/arcrun/arcrun.md` P0 #9
- 規範更新：`matrix/arcrun/.claude/rules/01-tech-stack.md`、`rules/03-component-architecture.md`
- 受影響 SDD：`polaris/mira/.agents/specs/mira-app/tasks.md` 7B.3c（阻擋一整天）
