diff --git a/cypher-executor/src/actions/auth-dispatcher.ts b/cypher-executor/src/actions/auth-dispatcher.ts index e1de675..f9b1e69 100644 --- a/cypher-executor/src/actions/auth-dispatcher.ts +++ b/cypher-executor/src/actions/auth-dispatcher.ts @@ -20,23 +20,10 @@ import type { Bindings } from '../types'; import { resolveAuthRecipe, resolveRecipe } from '../routes/recipes'; import { wasmWorkerUrl } from '../lib/component-loader'; -import type { ServiceBinding } from '../types'; /** 對應 Phase 1-4 會部署的 auth primitive Worker */ const SUPPORTED_PRIMITIVES = new Set(['static_key', 'service_account', 'oauth2']); -/** - * primitive 名 → service binding key(Phase 7,2026-06-06)。 - * 比照 component-loader 的邏輯零件:有 binding 走 CF 內部 RPC(繞開同 zone 522 + 同帳號 workers.dev 1042), - * 無 binding(如 self-hosted 未綁、或 mtls 未部署)fallback 到 fetch(workers.dev)。 - */ -const AUTH_BINDING_MAP: Record = { - static_key: 'SVC_AUTH_STATIC_KEY', - service_account: 'SVC_AUTH_SERVICE_ACCOUNT', - oauth2: 'SVC_AUTH_OAUTH2', - mtls: 'SVC_AUTH_MTLS', -}; - /** auth primitive 本身的 componentId(避免自引用) */ const AUTH_PRIMITIVE_IDS = new Set([ 'auth_static_key', @@ -75,27 +62,18 @@ export async function tryAuthDispatch( if (!recipe) return null; if (!SUPPORTED_PRIMITIVES.has(recipe.primitive)) return null; - // 呼叫對應 auth primitive Worker(Phase 7,2026-06-06): - // binding 優先(CF 內部 RPC,繞開同 zone 522 + 同帳號 workers.dev 子請求 1042,壓測階段 11), - // 無 binding(self-hosted 未綁 / mtls 未部署)fallback 到 fetch(workers.dev)。比照 component-loader makeLogicRunner。 - const reqInit = { + // 走新路徑:HTTP POST 到對應 auth primitive Worker + // 走 workers.dev 避開同 zone 死鎖(P0 #9) + const primitiveUrl = wasmWorkerUrl(`auth_${recipe.primitive}`, env.WORKER_SUBDOMAIN); + const res = await fetch(primitiveUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ action: 'authenticate', api_key: apiKey, service }), - }; - - const bindingKey = AUTH_BINDING_MAP[recipe.primitive]; - const svc = bindingKey ? (env[bindingKey] as ServiceBinding | undefined) : undefined; - - let res: Response; - if (svc) { - // service binding:用任意 URL,CF 內部 RPC 直送目標 Worker(不經公網) - res = await svc.fetch(new Request('https://auth-primitive/', reqInit)); - } else { - // fallback:公網 workers.dev(自架未綁 binding / 開發環境 / mtls) - const primitiveUrl = wasmWorkerUrl(`auth_${recipe.primitive}`, env.WORKER_SUBDOMAIN); - res = await fetch(primitiveUrl, reqInit); - } + body: JSON.stringify({ + action: 'authenticate', + api_key: apiKey, + service, + }), + }); if (!res.ok) { const text = await res.text().catch(() => ''); diff --git a/cypher-executor/src/types.ts b/cypher-executor/src/types.ts index ea4e5c9..698c309 100644 --- a/cypher-executor/src/types.ts +++ b/cypher-executor/src/types.ts @@ -21,12 +21,6 @@ export type Bindings = { SVC_DATE_OPS: ServiceBinding; SVC_VALIDATE_JSON: ServiceBinding; // SVC_AI_TRANSFORM_* 已移除(Phase 2 刪 ai_transform 零件 + wrangler.toml service binding) - // Auth primitive Service Bindings(Phase 7,2026-06-06):繞開 self-hosted 同帳號 workers.dev 子請求 1042。 - // optional:auth_mtls 尚未部署(無 binding);無 binding 時 auth-dispatcher fallback 到 fetch(workers.dev)。 - SVC_AUTH_STATIC_KEY?: ServiceBinding; - SVC_AUTH_SERVICE_ACCOUNT?: ServiceBinding; - SVC_AUTH_OAUTH2?: ServiceBinding; - SVC_AUTH_MTLS?: ServiceBinding; // KV Context Store:節點 output 透過 KV 傳遞,解決同名欄位衝突 EXEC_CONTEXT: KVNamespace; // Recipe Store:API recipe 定義(key: recipe:{canonical_id} 或 idx:{hash_id}) diff --git a/cypher-executor/wrangler.toml b/cypher-executor/wrangler.toml index b294da7..3465895 100644 --- a/cypher-executor/wrangler.toml +++ b/cypher-executor/wrangler.toml @@ -2,7 +2,14 @@ name = "arcrun-cypher-executor" main = "src/index.ts" compatibility_date = "2025-02-19" workers_dev = true -compatibility_flags = ["nodejs_compat"] +# global_fetch_strictly_public:讓 fetch() 走公網「前門」,解 self-hosted 的 same-zone 1042 +# (credential-primitives-wasm Phase 7,2026-06-06)。 +# 病因(官方 docs):self-hosted 的 cypher 與 auth worker 同在 {sub}.workers.dev zone, +# cypher fetch auth 屬 same-zone fetch,CF 預設擋(1042)。官方 cypher 在 cypher.arcrun.dev、 +# 打 auth 的 *.workers.dev 屬跨 zone 故不踩。此 flag 讓 same-zone fetch 改走公網前門 → 同 zone 也通。 +# 安全(已查證官方 docs):唯一副作用是「Worker fetch 自己 hostname 會 self-loop」, +# 但 cypher 只打外部 API + sibling auth worker(皆非自己 hostname)→ 不 self-loop。 +compatibility_flags = ["nodejs_compat", "global_fetch_strictly_public"] [[kv_namespaces]] binding = "EXEC_CONTEXT" @@ -91,24 +98,6 @@ service = "arcrun-date-ops" binding = "SVC_VALIDATE_JSON" service = "arcrun-validate-json" -# Auth primitive service bindings(credential-primitives-wasm Phase 7,2026-06-06) -# 為何:auth-dispatcher 原用 fetch(workers.dev) 打同帳號 auth worker,self-hosted 帳號踩 CF 1042 -# (壓測階段 11)。service binding 是 CF 內部 RPC,繞開同 zone 522 + 同帳號 1042。 -# 範圍:只綁「已部署」的 auth worker。auth_mtls 尚未部署(.component-builds 無、官方 404), -# 綁不存在的 worker 會讓 deploy 報 "referenced Worker not found"(見上 ai_transform 教訓), -# 故 mtls 待它部署後再加。auth-dispatcher 對無 binding 的 primitive 自動 fallback fetch。 -[[services]] -binding = "SVC_AUTH_STATIC_KEY" -service = "arcrun-auth-static-key" - -[[services]] -binding = "SVC_AUTH_SERVICE_ACCOUNT" -service = "arcrun-auth-service-account" - -[[services]] -binding = "SVC_AUTH_OAUTH2" -service = "arcrun-auth-oauth2" - # ai_transform_compile / ai_transform_run 已於 Phase 2(2026-05-29)刪除 # (Arcrun 是 AI 呼叫的工具,工作流不該內嵌 AI 節點)。對應 worker 已 wrangler delete, # service binding 一併移除(否則 deploy 報 referenced Worker not found)。