diff --git a/cypher-executor/src/actions/auth-dispatcher.ts b/cypher-executor/src/actions/auth-dispatcher.ts index f9b1e69..e1de675 100644 --- a/cypher-executor/src/actions/auth-dispatcher.ts +++ b/cypher-executor/src/actions/auth-dispatcher.ts @@ -20,10 +20,23 @@ 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', @@ -62,18 +75,27 @@ export async function tryAuthDispatch( if (!recipe) return null; if (!SUPPORTED_PRIMITIVES.has(recipe.primitive)) return null; - // 走新路徑:HTTP POST 到對應 auth primitive Worker - // 走 workers.dev 避開同 zone 死鎖(P0 #9) - const primitiveUrl = wasmWorkerUrl(`auth_${recipe.primitive}`, env.WORKER_SUBDOMAIN); - const res = await fetch(primitiveUrl, { + // 呼叫對應 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 = { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - action: 'authenticate', - api_key: apiKey, - service, - }), - }); + 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); + } if (!res.ok) { const text = await res.text().catch(() => ''); diff --git a/cypher-executor/src/types.ts b/cypher-executor/src/types.ts index 698c309..ea4e5c9 100644 --- a/cypher-executor/src/types.ts +++ b/cypher-executor/src/types.ts @@ -21,6 +21,12 @@ 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 b1ad7eb..b294da7 100644 --- a/cypher-executor/wrangler.toml +++ b/cypher-executor/wrangler.toml @@ -91,6 +91,24 @@ 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)。