fix(auth): 全新安裝補上 CF_SECRETS_API_TOKEN 的缺口——第一個帳號建得起來了(arcrun-rag#99)
根因:D61(認證與資料分離,c4cee35)把 /console/setup、/portal/admin/bootstrap 的寫入全部改走 CF Workers Secrets(env.CF_SECRETS_API_TOKEN),但這把 token 從安裝那天起就沒被種過——07-29 已知缺口(pending-changes.md「credential 走 n8n 模式」),當時只降級某個功能;D61 之後升級成「連第一個帳號都建不起來」 的硬斷點,每台全新安裝必中(leo 本人+封測者實撞:裝得起來但卡在註冊)。 修法:putWorkerSecret/deleteWorkerSecret/authStoreWritable/writeAuthStore/ mutateAuthStore 新增可選的 tokenOverride 參數(呼叫端提供 > worker 自身 env)。 /console/setup、/portal/admin/bootstrap 讀取 x-arcrun-install-token 表頭, 只有安裝精靈(裝機當下手上有一把自己還有效的 OAuth token,workers-scripts.write scope,同一把已用於 putWorkerSecretDirect/seedCredential)會帶這個表頭; 一般使用者自己在瀏覽器操作不受影響。沿用既有「D36 安裝器代寫」precedent, 不是新開一條路;bootstrap 本身已被「已有 admin → 409」擋成只能成功一次, 不會被拿來反覆濫用。 測試:cypher-executor vitest 443/457(14 個既存失敗與本改動無關,已用 git stash 對照確認);新增 2 則直接證明「缺 token→502 auth_store_not_writable/ 帶 token→200」。tsc --noEmit 無新增錯誤。已跑 build-worker-artifacts.mjs 重打 tier2 bundle 供驗證(工作區未 commit 前提下的本地驗證版)。 未完成:安裝器(products/arcrun-rag/installer/oauth-prototype/worker.js) 端的 x-arcrun-install-token 表頭傳遞已另外修好,但兩邊都還沒部署——需要 ①重打正式 worker artifact ②install.arcrun.dev 的安裝器 wrangler deploy ③已卡住的封測者要再走一次安裝精靈讓他的 cypher worker 拿到新 bundle。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -127,11 +127,17 @@ async function loadCredentials(env: Bindings): Promise<{ creds: StoredCredential
|
||||
return { creds: legacy, source: 'legacy-kv' };
|
||||
}
|
||||
|
||||
/** 寫入 console 管理員帳密——**只寫新家**,不再寫 KV(寫回去等於把病種回土裡)。 */
|
||||
async function saveCredentials(env: Bindings, record: StoredCredentials): Promise<void> {
|
||||
/**
|
||||
* 寫入 console 管理員帳密——**只寫新家**,不再寫 KV(寫回去等於把病種回土裡)。
|
||||
*
|
||||
* `installToken`(2026-08-14,arcrun-rag#99):見 `lib/portal-auth-store.ts authStoreWritable`
|
||||
* 的完整說明——這是安裝精靈裝機當下遞來、cypher 自己不落地的臨時 CF token,補的是
|
||||
* 「這台 worker 從沒被種過 CF_SECRETS_API_TOKEN」這個結構性缺口。
|
||||
*/
|
||||
async function saveCredentials(env: Bindings, record: StoredCredentials, installToken?: string): Promise<void> {
|
||||
await mutateAuthStore(env, (data) => {
|
||||
data.console = record;
|
||||
});
|
||||
}, installToken);
|
||||
}
|
||||
|
||||
// GET /console/auth-status — 前端用來決定顯示「首次設定」還是「登入」表單。不洩漏 email。
|
||||
@@ -171,7 +177,10 @@ consoleAuthRouter.post('/console/setup', async (c) => {
|
||||
const hash = await hashPassword(password, salt);
|
||||
const record: StoredCredentials = { email: email.toLowerCase(), salt, hash, created_at: new Date().toISOString() };
|
||||
try {
|
||||
await saveCredentials(c.env, record);
|
||||
// arcrun-rag#99:安裝精靈裝機當下把自己還有效的 OAuth token 隨這個表頭遞來
|
||||
// (見 lib/portal-auth-store.ts authStoreWritable 的完整說明)。一般用戶自己在瀏覽器
|
||||
// 敲 /console/setup 不會帶這個表頭,行為與今天完全一樣(沒有 token 就是沒有 override)。
|
||||
await saveCredentials(c.env, record, c.req.header('x-arcrun-install-token'));
|
||||
} catch (e) {
|
||||
// 寫不進去就誠實回報(不假綠:舊版寫 KV 幾乎不會失敗,於是沒人處理過這條路)
|
||||
const msg = e instanceof AuthStoreWriteError ? e.message : String(e);
|
||||
|
||||
Reference in New Issue
Block a user