uncle6me-web
|
4b6cc159b8
|
feat(auth): 認證儲存搬回 D1/KV——落實方案C(leo confirm「走C」,arcrun-rag#99)
實作 pending-changes.md「認證儲存要不要搬回 D1/KV」提案(commit 8286c8a):
D61 的病根「重裝時 binding 被安裝器照名字重新指到新建空資源」已被更通用的
shared/resource-rule(Arcrun#97,2026-08-13)解掉,故不再需要繞開 binding
去躲這個病——而繞開的代價正是這次要收的債:Workers Secrets 寫入需要外部
CF_SECRETS_API_TOKEN,這把 token 從安裝那天起就沒被種過,止血版只解掉
「建第一個帳號」這一格,之後的每一次寫入(換密碼/加帳號/改權限)仍卡死。
改動:
- console 管理員帳密:家改回 SESSIONS_KV(binding,console-auth.ts)
- portal 多人帳號:家改回 KBDB(binding,走 base HTTP API,D38 零 SQL,portal.ts)
- D61 認證儲存(CF Workers Secrets)留為舊實例的唯讀回退路徑:讀取零成本、
零外部憑證需求(只有寫入才要 token);登入成功即 best-effort 自動搬進新家,
且**這次登入發出的 session 就直接指向新 record_id**(不必等下一次登入)
- D61 的三項「明顯失敗」語意全部保留:auth_store_empty(讀不到不算密碼錯、
不計入鎖定)、/console/setup 遇既有帳號說清楚密碼沒被採用、/health 與
/console/auth-status 吐儲存狀態
- 移除止血版的 x-arcrun-install-token 表頭傳遞機制(installToken 參數)——
帳號寫入從此不需要任何外部 CF token,這個結構性缺口已從根拔除
測試:cypher-executor 全套 vitest 439/453(14 個既存失敗與本改動無關,已用
git stash 對照 clean checkout 逐一比對檔名確認完全相同);tsc --noEmit
無新增錯誤(3 個既存錯誤同上核實無關)。已跑 build-worker-artifacts.mjs
重打 tier2 bundle,grep 複驗 createKbdbUserRecord/promoteToKbdb 進了成品、
promoteLegacyUser/x-arcrun-install-token 完全從成品消失。
未覆蓋:POST /credentials(一般 workflow API 金鑰儲存)仍依賴
CF_SECRETS_API_TOKEN——這是 01-tech-stack.md 既有的、獨立於 D61 之外的
credential 儲存架構(D19「擁有目錄不擁有內容物」),本提案範圍只涵蓋「認證」
(登入帳密),不涵蓋一般 credential 儲存;07-29 已知缺口仍待另案處理。
不准 merge 進 main(SDD 鐵律③,等總管審過再併);不准部署(D20 出貨閘)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-08-14 12:52:07 +08:00 |
|
uncle6me-web
|
88f308642e
|
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>
|
2026-08-14 11:46:56 +08:00 |
|
uncle6me-web
|
b223a69884
|
fix(portal): 藏書地圖看得到自己的知識——租戶字串改從「寫入端」來,不再拿環境變數預設值(Arcrun#108)
leo 2026-08-12 實撞:藏書地圖回 0 個庫,同一分鐘 KBDB 裡有 1854 條三元組,
`arcrun_whoami` 顯示 admin/全部知識庫、`kbdb_search` 也查得到——只有地圖那格是空的。
病根(不是資料掉了,是讀寫兩端各拿一個來源):
寫入端 owner_id = `~/.arcrun/config.yaml` 的 `api_key`(CLI push/小幫手上傳/MCP,
leo = `bfezv28v`)
讀取端過濾 = `portalTenant(env) = env.CONSOLE_TENANT || "leo"`
——repo toml 帶的**官方 prod 值**,而 `acr` 從來不注入 CONSOLE_TENANT
⇒ 那個 `"leo"` 不是理論邊角,是每台 self-hosted 實例的實際行為,1854 條全被濾掉。
與 #105(`env.MCP_OWNER_NAMESPACE || "leo"`)同一句話,換一個檔案。
租戶字串該從哪裡來(本票的核心判斷):
**從「寫入這批知識的那一方」來,不是從一份手抄的環境變數預設值來。**
不是「掛到每個帳號上」——portal 帳號共用同一台實例的知識庫(design D-2),
帳號之間的差別是 libraries 權限不是 owner_id;複製一份到帳號上只是多一個會過期的副本。
#105 真正的教訓是:過濾用的租戶字串要有單一權威來源、解析不到要誠實失敗、且要能機械驗證。
修法:
1. 唯一產地 `cypher-executor/src/lib/tenant.ts`
- `knowledgeOwner(env)` → branded `TenantId`:`ARCRUN_NAMESPACE` → `CONSOLE_TENANT` →
丟 `TenantUnresolvedError`。**沒有字面預設值**——`|| 'leo'` 正是把「這台機器沒設定」
偽裝成「你沒有資料」的元凶。
- `accountTenant(env)` → 普通 `string`(帳號子 namespace `{tenant}::portal` 與 cypher
自己寫的設定用它)。**回 string 是刻意的**:型別上就不可能流進知識資料面。
- 資料面過濾一律經 `ownerQuery()` / `ownerField()`,只吃 `TenantId`。
2. 值的正解由 CLI 從真相源導出:`acr update` 把 config 的 `api_key` 注入成 `ARCRUN_NAMESPACE`,
但**先驗再寫**(`GET /kbdb/map?owner_id=<api_key>` 查得到庫才寫;查不到/問不到就一個字
都不動)。無條件覆蓋會把「知識本來就在 CONSOLE_TENANT 底下」的一鍵安裝實例指向空的那一格
——那是 #97/#106 那類「更新一次把人家的東西弄不見」,比原本的 bug 更糟。
未注入時回退 CONSOLE_TENANT ⇒ 對官方 prod 與未更新的實例,這次改動是惰性的。
3. 空地圖分四態(沿 #100「讀不到就說讀不到」):no_library_grant/filtered_out/
scope_mismatch/confirmed_empty。scope_mismatch 以前不存在,所以設定錯誤被畫成
「你沒有資料」。回應仍不含租戶字串(design §3.3 紅線)。
4. 同族一起修(同一道閘一次抓到):console-dashboard 4 處、console-auth 1 處
——console 首頁的規模數字與藏書地圖對 leo 也一直是空的。
留下的閘(規則存在但沒機制驗證=會再犯第三次):
· 型別閘:TenantId 只能由 tenant.ts 產出 → 拿隨手一個 string 去過濾,tsc 當場不給過。
· 出貨閘:scripts/build-worker-artifacts.mjs 編 tier2 成品前先掃,違規 → 編不出成品。
· 閘自己可測:規則是純函式(tenant-source-rules.mjs),tests/tenant-gate.test.ts
逐條驗「5 種壞例子會擋」+「11 種合法寫法零誤攔」;掃描範圍只有 src/,擋不到自己。
規範寫入 .claude/rules/02-forbidden.md 第六類、system-dev/wiki/mistakes.md #26。
沒動:庫權限過濾(一字未改,回歸測試釘住)、帳號資料落點、任何金鑰、租戶字串仍不下發前端。
驗證:
cypher vitest 441 綠 / 14 紅,14 紅與 base commit e05518a 逐字相同(既有)
tsc 5 個既有錯誤,零新增
cli node:test 60/60 綠(含本次新增 12 條);tsc 零錯誤
閘 壞例子實跑 exit 1;build 實跑「建置中止」;乾淨時實跑通過
端到端 ◐ 未驗:需部署到 leo21c,那道閘要 leo 親手解(見 PR ③)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-13 00:15:58 +08:00 |
|
uncle6me-web
|
c4cee35adb
|
feat(auth): 認證與資料分離——搬動知識資料時登入不再跟著壞掉(D61 / arcrun-rag#55)
leo 2026-08-10 下令:「登入認證資料要分離⋯⋯就算只有我一個人存在單獨的 json 檔也好,
它不能被改資料庫的連結導致無法登入。」「昨天不能登入 portal,今天不能登入 mcp,
這根本就是一個問題。」
病:portal 帳號住 KBDB(owner_id = {CONSOLE_TENANT}::portal),console 管理員帳密住
SESSIONS_KV。兩者都靠 binding 指過去,重裝/遷移一定會被重新指一次 ⇒ 保險箱的鑰匙
放在保險箱裡。2026-08-09 leo 資料一個位元組都沒動,卻被鎖在門外。
修:認證搬到 CF Workers per-script Secrets(掛在 script 上,與 bindings 兩套資源,
重部不會洗掉;journeys/gemini-key-lost-on-reinstall.md 與 installer worker.js:1148 皆有實證)。
- 新增 lib/portal-auth-store.ts:自足的 JSON,讀取零網路呼叫,>4.6KB 自動溢位分片
- portal.ts 的帳號讀寫全部改走它;KBDB 只留為舊實例的回退讀路徑,登入成功順手搬過去
- console-auth.ts 的第二份認證資料同樣搬離 KV
- 不牴觸 D38:KBDB 三張核心表不增不減,本案是把東西搬出去
- 沿用 credentials.ts 既有的 putWorkerSecret/deleteWorkerSecret,不另造第二套寫入路徑(D36)
明顯失敗(把 #10「寧可明顯失敗,不要靜默錯置」套到門鎖上):
- 「這台實例讀不到任何登入資料」回 503 + code=auth_store_empty,且**不計入 5 次鎖定**
(08-09 leo 就是被系統自己的誤判鎖了 15 分鐘)
- /console/setup 遇既有帳號改說「你剛才輸入的密碼沒有被採用」,不再只說「已設定過」
- /health 與 /console/auth-status 吐 auth_store 狀態(住哪、寫不寫得進去)
stage 實測撞到並修掉的坑:改 secret 會產生 worker 新版本,既有 isolate 讀到的還是舊 env
⇒ 「建好帳號立刻登入」有 15 秒以上 401,還被算進鎖定。加一層短 TTL 的 KV 加速器
(非真相源,只在 secret 查不到/密碼對不上時問一次),換 KV 不影響不變量。
驗收:stage(youlin)把知識資料庫換成另一顆空的 + 換租戶代號 + SESSIONS_KV 換成空的,
三樣一起換之後 portal / MCP /authorize / console 三條登入路徑仍全綠(複跑 3 次)。
對照組(舊版程式碼同樣換庫):登入回「email 或密碼錯誤」,5 次後鎖 15 分鐘。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-08-10 14:13:37 +08:00 |
|
Leo
|
5cd790c94a
|
feat(console): 收件夾改裝=全部待辦分流台(Arcrun#9,kb-ingest SDD R7 消費端)
console 頁 7 從 Telegram 訊息清單改裝成三欄分流台:
- 資料源二合一:entry_type=todo(Logseq 萃取,Arcrun#8 ingest 線)+ entry_type=inbox
(Telegram),/console/inbox-data → /console/triage-data(唯一消費者是本頁,一起改
裝不留死端點;仍鎖 console session——待辦原文屬機敏)
- 三欄 80/15/5:ai=AI 會幫我搞定/collab=協作/leo=非我不可;owner_tier 缺席或看
不懂(triage engine 還沒判)→ 歸 collab 欄+「未分流」徽章,不冒領 ai、不誤判 leo
- 各項顯示 text/project 徽章/source/marker;status:done 預設隱藏可切換
- per-project chips 過濾(全部/各 project/未分項),前端同包資料過濾零額外請求
- 手機直排沿 console 單檔薄殼;讀 KBDB 走既有 kbdbBase HTTP 慣例,不新增 binding
契約解析/分欄/計數=純函式 lib/console-triage-model.ts(比照 console-dashboard-model
模式,route 只做 IO),tests/console-triage-model.test.ts 11 測全綠(紅→綠驗證:抽掉
實作模組同測試即紅)。全套 vitest 98 passed,唯一失敗為 pre-existing executor
「不存在的零件」訊息斷言(main 同紅,與本 PR 無關)。
[總管-subagent]
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-08 22:44:54 +08:00 |
|
uncle6me-web
|
f9e44abc59
|
feat(console): Mira Console 完整版——8 頁紙感定稿視覺 SPA (Arcrun#3 console 系)
依 claude design 定稿(紙感暖黑 2a)+ brief 8 頁資訊架構重寫 /console:
- 單檔 HTML+原生 JS hash routing,零外部資源;紙紋底/明體標題/琥珀強調/
呼吸球嵌「安/趕/滯」;手機優先 390px + ≥1024px 側欄 + 底部五 tab
- 頁1 登入/首次設定(沿 console-auth v1)|頁2 駕駛艙(dashboard-data,60s 刷新;
/console/dashboard 免登入獨立頁同步換視覺)|頁3 總庫搜尋(entry_type chips=
KBDB 真能篩的欄位、共 N 筆中命中 M(誠實 total)、語意未啟用誠實降級 banner)|
頁4 卡片詳頁+關聯(Markdown 渲染 + kbdb-graph-plugin 鄰居放射圖,經新 proxy
/kbdb/graph/neighbors/:name;無 triplet →「尚無關聯資料」)|頁5 工作流
(/webhooks/named list+手動觸發+最近執行;釘選 localStorage;v0 零件/recipes
查詢收進本頁折疊區不砍功能)|頁6 憑證(新 GET /credentials/catalog D1 目錄
唯讀,絕不回密文;新增/替換走既有端點;刪除未接 D1(T9)標「即將開通」)|
頁7 收件匣(新 GET /console/inbox-data,session 鎖——訊息原文屬機敏)|
頁8 設定(vectorize 狀態探測讀 search 降級訊號、開關標「即將開通」、
/console/setup/reset 換帳密、系統資訊)
驗證:tsc exit 0;vitest 26/27(1 失敗 stash 複驗 pre-existing);wrangler
deploy --dry-run 打包過;inline JS 求值後 node --check + esc/mdRender/parseAtMs
純函式行為測試全過(含 XSS escape)。未部署,留總管接手。
|
2026-07-04 17:49:49 +08:00 |
|
Leo
|
abf232327c
|
feat(console): API Key 介面錯位收斂為簡單 email+password 登入 (Arcrun#3 發現②)
背景:self-hosted 單租戶下 console 原本那格「API Key」其實只是 namespace
明碼字串,不是註冊制 key(leo 原話:理論上根本沒有 API Key 這件事)。leo 拍板:
換成簡單 email+password 登入頁(自己設一組帳密,不用 OAuth),登入成功後端發
session token 存 localStorage;後端 API 呼叫仍用固定租戶字串打 KBDB(登入系統
只擋外人看頁面,不做多租戶)。
租戶字串收斂:發現①已核實 owner_id='leo' 是 D1 中 458,357 筆資料實際使用的
租戶字串(ak_... 只有 2 筆孤兒資料)。CONSOLE_TENANT 預設 "leo",不製造第三個租戶。
新增:
- cypher-executor/src/routes/console-auth.ts:/console/auth-status、
/console/setup(首次自助設定帳密,寫入 SESSIONS_KV console:credentials)、
/console/setup/reset(換帳密,需舊密碼)、/console/login、/console/session
(驗 session + 回傳固定租戶字串)、/console/logout。密碼用 salt + 3 輪
SHA-256 雜湊,不存明碼。
- cypher-executor/src/types.ts:Bindings 加 CONSOLE_TENANT。
- cypher-executor/wrangler.toml:[vars] 加 CONSOLE_TENANT = "leo"。
- cypher-executor/src/routes/console.ts:① 卡片從「貼 API Key」改成登入/首次
設定表單;查詢函式改用登入後端回的固定租戶字串,使用者不再需要知道任何
namespace 字串。
驗證見 issue #3 留言。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
2026-07-03 09:01:04 +00:00 |
|