fix(cypher): credential 全部從新家取到時不再打 auth_static_key worker(Arcrun#124)
病:cypher 看到 {{credential.X}} 就無條件 fetch
arcrun-auth-static-key.{WORKER_SUBDOMAIN}.workers.dev。那顆 worker
**不在網頁安裝器的首裝清單裡**(只裝 cypher-executor / kbdb / http_request / code
四顆),也沒有「用到才長」的機制 ⇒ fetch 撞 CF 邊緣 404 `error code: 1042`
⇒ 凡是用到 {{credential.X}} 的節點全部 500。
實測兩台都一字不差地同死(唯讀證據):
leo21c GET /q/bfezv28v/rag_chat → 500 Node kw_search failed: ... 1042
youlin GET /q/yuga3bse/rag_chat → 500 Node kw_search failed: ... 1042
geek6688(手工維護、那顆在) → 過得了這關
leo 的 8 支 RAG 工作流每一支都用 {{credential.}}(rag_chat 6 處、
rag_ingest_card 7 處)⇒ 問答與寫入同時死,不只 ingest。
修法:resolveCredentialRefs 在 resolveSecretsFromNewHome 之後,若 nameList
每一個都已取到明文,就直接 replaceCredentialRefs 回傳,不打那顆 worker。
為什麼是零行為變化:回填本來就在本檔做(replaceCredentialRefs);那顆 worker
在這條路徑上唯一多做的事是幫「沒取到」的 name fallback 舊 KV(T7 雙讀)。
全取到時它收到 resolved_secrets 就是原樣回傳。只要有任一 name 沒取到,
仍照舊全量交給 WASM 走 T7——不縮減既有能力,只在等價時省掉那一跳。
證據那把金鑰早就在手上:leo21c 的 credential 目錄 last_used_at=1786715805,
與最後一次失敗執行的時間戳同一秒(touchLastUsed 只在真的從新家取到值時才寫)。
🔴 這個 1042 與 d2048e2/95a1462 那兩輪不是同一個病:那兩輪是 same-zone fetch
被擋(解=global_fetch_strictly_public flag,service binding 的解法已被 revert
不要拿回來);本案是目標 worker 根本不存在。同一個錯誤碼、兩種原因。
邊界:rule 02 §2.2 不變(不解密/不展開模板/不組 JWT);rule 3.1 不變(不加
service binding)。明文來源仍是 secret_get host function,與改動前同一條路。
驗證:tsc 對本檔零錯誤;auth-dispatcher+credentials 測試 5 紅 8 綠,
與改動前基準線逐項相同(零回歸;那 5 紅是 7ba7855 註明的「刻意留紅燈」)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -245,6 +245,35 @@ export async function resolveCredentialRefs(
|
||||
// 沒取到的 name 缺席 → WASM 的 resolve_credentials 分支 fallback 舊 KV(T7)。
|
||||
const resolvedSecrets = await resolveSecretsFromNewHome(env, apiKey, nameList);
|
||||
|
||||
// ── 全部取到 → 不必打 auth_static_key worker(Arcrun#124,2026-08-14)────────────
|
||||
//
|
||||
// 這條路徑上,那顆 worker 唯一比這裡多做的事,是「幫**沒取到**的 name 回頭翻舊 KV」
|
||||
// (T7 雙讀 fallback)。當 nameList 每一個都已經從新家取到明文時,它收到
|
||||
// `resolved_secrets` 後就是原樣回傳——回填本來就由下面的 `replaceCredentialRefs`
|
||||
// 在本檔做。**所以那趟往返在「全取到」時不產生任何結果差異。**
|
||||
//
|
||||
// 為什麼這不是效能微調,是修 bug:`wasmWorkerUrl` 推導出的
|
||||
// `arcrun-auth-static-key.{WORKER_SUBDOMAIN}.workers.dev` **在網頁安裝器裝出來的實例上不存在**
|
||||
// (首裝只裝 cypher-executor / kbdb / http_request / code 四顆,auth primitive 不在其中,
|
||||
// 也沒有「用到才長」的機制)。於是 fetch 撞 CF 邊緣的 404 `error code: 1042`
|
||||
// ⇒ 下面的 `!res.ok` throw ⇒ **凡是工作流用到 {{credential.X}} 的節點全部 500**。
|
||||
// 實測:leo21c 與全新安裝的 youlin 兩台,問答與寫入路徑一字不差地同死。
|
||||
//
|
||||
// 🔴 給下一個人:**這個 1042 跟 d2048e2/95a1462 那兩輪的 1042 不是同一個病。**
|
||||
// 那兩輪是「same-zone fetch 被 CF 擋」(解法=`global_fetch_strictly_public` flag,
|
||||
// 且 service binding 的解法**已被 revert、不要再拿回來**)。本案是「**目標 worker 根本不存在**」
|
||||
// ——同一個錯誤碼、兩種原因。照舊帳去動 flag 或 binding 對本案完全無效(flag 早就在了)。
|
||||
//
|
||||
// 邊界(rule 02 §2.2)不變:本檔仍然不解密、不展開模板、不組 JWT。
|
||||
// 明文的來源是 `secret_get`(host function,實作 = env[ref]),與改動前完全同一條路;
|
||||
// 這裡只是不再為了「拿一份自己已經拿到的東西」去 fetch 一顆可能不存在的 worker。
|
||||
//
|
||||
// 刻意保留 WASM 路徑:只要有任何一個 name 沒從新家取到(舊租戶、遷移過渡期的 KV 存量),
|
||||
// 就照舊全量交給 WASM 走 T7 雙讀——**不縮減既有能力,只在等價時省掉那一跳**。
|
||||
if (nameList.every((n) => Object.prototype.hasOwnProperty.call(resolvedSecrets, n))) {
|
||||
return replaceCredentialRefs(data, resolvedSecrets) as Record<string, unknown>;
|
||||
}
|
||||
|
||||
const url = wasmWorkerUrl('auth_static_key', env.WORKER_SUBDOMAIN);
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user