fix(cypher): 改用 global_fetch_strictly_public flag 解 same-zone 1042(revert service binding)

richblack 拍板:service binding(前一 commit)靜態、加/改要重 deploy cypher,廢。
改用 global_fetch_strictly_public compatibility flag——cypher wrangler.toml 加一行,
讓 fetch() 走公網前門,self-hosted 的 same-zone fetch(cypher 與 auth 同在
{sub}.workers.dev zone)也能通。

- wrangler.toml:compatibility_flags 加 global_fetch_strictly_public(移除 SVC_AUTH_*)
- auth-dispatcher.ts / types.ts:還原到 service binding 之前(單純 fetch workers.dev)
- 安全(官方 docs):唯一副作用 self-loop 僅在 fetch 自己 hostname;cypher 不 self-loop
- 官方/self-host 共用同一份 toml:官方本就跨 zone 行為不變,self-host 被修好
- 規範還原:rule 02/03/CLAUDE.md/pre-bash-guard 的 service binding 禁令維持原狀

SDD: credential-primitives-wasm Phase 7(A→廢→B)。tsc exit 0。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-06-06 21:44:13 +08:00
parent 62f1d1d390
commit 95a1462b65
3 changed files with 18 additions and 57 deletions
+10 -32
View File
@@ -20,23 +20,10 @@
import type { Bindings } from '../types'; import type { Bindings } from '../types';
import { resolveAuthRecipe, resolveRecipe } from '../routes/recipes'; import { resolveAuthRecipe, resolveRecipe } from '../routes/recipes';
import { wasmWorkerUrl } from '../lib/component-loader'; import { wasmWorkerUrl } from '../lib/component-loader';
import type { ServiceBinding } from '../types';
/** 對應 Phase 1-4 會部署的 auth primitive Worker */ /** 對應 Phase 1-4 會部署的 auth primitive Worker */
const SUPPORTED_PRIMITIVES = new Set(['static_key', 'service_account', 'oauth2']); const SUPPORTED_PRIMITIVES = new Set(['static_key', 'service_account', 'oauth2']);
/**
* primitive 名 → service binding keyPhase 72026-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<string, keyof import('../types').Bindings> = {
static_key: 'SVC_AUTH_STATIC_KEY',
service_account: 'SVC_AUTH_SERVICE_ACCOUNT',
oauth2: 'SVC_AUTH_OAUTH2',
mtls: 'SVC_AUTH_MTLS',
};
/** auth primitive 本身的 componentId(避免自引用) */ /** auth primitive 本身的 componentId(避免自引用) */
const AUTH_PRIMITIVE_IDS = new Set([ const AUTH_PRIMITIVE_IDS = new Set([
'auth_static_key', 'auth_static_key',
@@ -75,27 +62,18 @@ export async function tryAuthDispatch(
if (!recipe) return null; if (!recipe) return null;
if (!SUPPORTED_PRIMITIVES.has(recipe.primitive)) return null; if (!SUPPORTED_PRIMITIVES.has(recipe.primitive)) return null;
// 呼叫對應 auth primitive WorkerPhase 72026-06-06): // 走新路徑:HTTP POST 到對應 auth primitive Worker
// binding 優先(CF 內部 RPC,繞開同 zone 522 + 同帳號 workers.dev 子請求 1042,壓測階段 11), // 走 workers.dev 避開同 zone 死鎖(P0 #9
// 無 bindingself-hosted 未綁 / mtls 未部署)fallback 到 fetch(workers.dev)。比照 component-loader makeLogicRunner。 const primitiveUrl = wasmWorkerUrl(`auth_${recipe.primitive}`, env.WORKER_SUBDOMAIN);
const reqInit = { const res = await fetch(primitiveUrl, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'authenticate', api_key: apiKey, service }), body: JSON.stringify({
}; action: 'authenticate',
api_key: apiKey,
const bindingKey = AUTH_BINDING_MAP[recipe.primitive]; service,
const svc = bindingKey ? (env[bindingKey] as ServiceBinding | undefined) : undefined; }),
});
let res: Response;
if (svc) {
// service binding:用任意 URLCF 內部 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) { if (!res.ok) {
const text = await res.text().catch(() => ''); const text = await res.text().catch(() => '');
-6
View File
@@ -21,12 +21,6 @@ export type Bindings = {
SVC_DATE_OPS: ServiceBinding; SVC_DATE_OPS: ServiceBinding;
SVC_VALIDATE_JSON: ServiceBinding; SVC_VALIDATE_JSON: ServiceBinding;
// SVC_AI_TRANSFORM_* 已移除(Phase 2 刪 ai_transform 零件 + wrangler.toml service binding // SVC_AI_TRANSFORM_* 已移除(Phase 2 刪 ai_transform 零件 + wrangler.toml service binding
// Auth primitive Service BindingsPhase 72026-06-06):繞開 self-hosted 同帳號 workers.dev 子請求 1042。
// optionalauth_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 傳遞,解決同名欄位衝突 // KV Context Store:節點 output 透過 KV 傳遞,解決同名欄位衝突
EXEC_CONTEXT: KVNamespace; EXEC_CONTEXT: KVNamespace;
// Recipe StoreAPI recipe 定義(key: recipe:{canonical_id} 或 idx:{hash_id} // Recipe StoreAPI recipe 定義(key: recipe:{canonical_id} 或 idx:{hash_id}
+8 -19
View File
@@ -2,7 +2,14 @@ name = "arcrun-cypher-executor"
main = "src/index.ts" main = "src/index.ts"
compatibility_date = "2025-02-19" compatibility_date = "2025-02-19"
workers_dev = true workers_dev = true
compatibility_flags = ["nodejs_compat"] # global_fetch_strictly_public:讓 fetch() 走公網「前門」,解 self-hosted 的 same-zone 1042
# credential-primitives-wasm Phase 72026-06-06)。
# 病因(官方 docs):self-hosted 的 cypher 與 auth worker 同在 {sub}.workers.dev zone
# cypher fetch auth 屬 same-zone fetchCF 預設擋(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]] [[kv_namespaces]]
binding = "EXEC_CONTEXT" binding = "EXEC_CONTEXT"
@@ -91,24 +98,6 @@ service = "arcrun-date-ops"
binding = "SVC_VALIDATE_JSON" binding = "SVC_VALIDATE_JSON"
service = "arcrun-validate-json" service = "arcrun-validate-json"
# Auth primitive service bindingscredential-primitives-wasm Phase 72026-06-06
# 為何:auth-dispatcher 原用 fetch(workers.dev) 打同帳號 auth workerself-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 22026-05-29)刪除 # ai_transform_compile / ai_transform_run 已於 Phase 22026-05-29)刪除
# (Arcrun 是 AI 呼叫的工具,工作流不該內嵌 AI 節點)。對應 worker 已 wrangler delete # (Arcrun 是 AI 呼叫的工具,工作流不該內嵌 AI 節點)。對應 worker 已 wrangler delete
# service binding 一併移除(否則 deploy 報 referenced Worker not found)。 # service binding 一併移除(否則 deploy 報 referenced Worker not found)。