From 28152aa14f26a3814e84aaf49983142da0fc062a Mon Sep 17 00:00:00 2001 From: uncle6me-web Date: Mon, 13 Jul 2026 22:09:11 +0800 Subject: [PATCH] =?UTF-8?q?sdd(portal-auth):=20tasks=20=E2=80=94=20P1-P4?= =?UTF-8?q?=20=E5=8F=AF=E7=8D=A8=E7=AB=8B=20PR=20=E5=88=87=E5=88=86?= =?UTF-8?q?=EF=BC=8B=E5=90=84=E9=9A=8E=E6=AE=B5=E9=A9=97=E6=94=B6=EF=BC=88?= =?UTF-8?q?=E5=85=A8=E6=9C=AA=E5=8B=95=E5=B7=A5=EF=BC=8C=E5=BE=85=E5=AF=A9?= =?UTF-8?q?=E5=BE=8C=E9=96=8B=E5=B7=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- system-dev/docs/3-specs/portal-auth/tasks.md | 59 ++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 system-dev/docs/3-specs/portal-auth/tasks.md diff --git a/system-dev/docs/3-specs/portal-auth/tasks.md b/system-dev/docs/3-specs/portal-auth/tasks.md new file mode 100644 index 0000000..d784413 --- /dev/null +++ b/system-dev/docs/3-specs/portal-auth/tasks.md @@ -0,0 +1,59 @@ +# portal-auth — Tasks(實作切分,每階段可獨立 PR) + +> 狀態:**全部未動工——本 SDD 待總管/leo 審後才開工**(B 類流程:SDD 審 → 實作 PR → component-pr-review-standard → 總管 review → gated 部署 leo21c) +> 對應:Gitea #24/#25;design.md 各 § + +依賴鏈:P1 → P2 → P3 → P4(P2 不依賴 P1 可並行起,但 P3 要兩者都齊)。 + +--- + +## P1 — KBDB「庫」filter 地基(design §3.2/§3.3)|觸碰:`kbdb/` + +- [ ] 開工第一件事:實測 Vectorize metadata filter `$in` 支援與否(決定主路徑 vs fan-out fallback) +- [ ] `/entries/search`+`/entries` 加 `library` 多值參數(D1 json_extract IN+NULL→general fallback) +- [ ] embed upsert metadata 加 `library` 欄;semanticSearch filter 支援 library($in 或 fan-out) +- [ ] Vectorize `library` metadata index 建立步驟+reindex backfill 寫進部署清單 +- [ ] cypher `kbdb-proxy` 透傳 `library` 參數(供 owner/admin 面用;portal 面走 P3 的注入,不經這) +- [ ] 測試:D1 filter 單元測、NULL fallback、多值、semantic filter(mock VECTORIZE) +- **驗收**:curl `/entries/search?q=&library=finance` 只回 finance+未標記條目歸 general 可驗;semantic 同 +- **工程量**:小-中(0.5–1 個 CC 工作天) + +## P2 — portal_user 模型+認證 API(design §2/§4)|觸碰:`cypher-executor/`(新 route 檔) + +- [ ] seed template `portal_user`+`portal_library`(init-seed 慣例) +- [ ] PBKDF2-SHA256 雜湊模組(600k iters、常數時間比對、`pbkdf2-sha256$…` 格式) +- [ ] `POST /portal/admin/bootstrap`(console owner session 閘) +- [ ] login/logout/session/改密碼(KV `portal_sess:`、TTL var、每請求回讀 record 驗 status) +- [ ] admin 用戶 CRUD+libraries 授權+庫目錄 CRUD(role=admin 閘) +- [ ] 登入失敗節流(5 次/15 分鐘,KV TTL) +- [ ] 順手修 `record-crud.ts` updateRecord grow 路徑漏 owner_id(design §2.2 附帶) +- [ ] 測試:bootstrap 閘、登入對錯、停用即拒(session 立即失效)、role 閘、雜湊格式、`{tenant}::portal` 子 namespace 隔離(**搜 email 搜不到**) +- **驗收**(=#25 驗收):新增用戶能登入;停用登入被拒+既有 session 失效;KBDB 無新表;密碼抽查非明碼 +- **工程量**:中(約 1 個 CC 工作天) + +## P3 — `/portal` UI:登入殼+搜尋頁+設定頁+scope enforce(design §1/§3.3/§5/§6)|觸碰:`cypher-executor/` + +- [ ] `/portal` HTML 殼(重用 console 樣式/搜尋 view 抽共用 helper;`CONSOLE_BRAND` 品牌;零 Mira 字樣) +- [ ] 未登入只見登入殼;登入後兩頁:搜尋(keyword/semantic/graph 三模式+source 溯源+卡片詳頁)+設定(改密碼/看自己權限/主題) +- [ ] `/portal/data/*` server-side enforce:session→record→注入 `owner_id`+`library`;**前端絕不下發租戶字串** +- [ ] 卡片詳頁逐筆驗 library(越庫 id 直讀 → 404) +- [ ] graph 粗閘(D-4:無 graph 來源庫權限 → 模式不顯示+API 403) +- [ ] 測試:curl 帶 user session 直打 data API 驗 filter 繞不過(=#24 驗收 3 的 server-side 證明) +- **驗收**(=#24 驗收):leo21c `/portal` 可開;未登入只見登入殼;三模式+溯源可用;A 用戶(僅 general)搜不到 finance 內容——UI 與 curl 雙驗 +- **工程量**:大(1–1.5 個 CC 工作天,UI 是最大件) + +## P4 — admin 頁+工作流顯示(design §6)|觸碰:`cypher-executor/` + +- [ ] 帳號管理頁(admin-only nav):列表/新增/停用/重設密碼+每帳號庫權限勾選 +- [ ] 庫目錄管理(登記/停用庫) +- [ ] 工作流頁(唯讀 list+最近執行;`PORTAL_SHOW_WORKFLOWS` 預設 admin;不開 trigger) +- **驗收**:admin 全流程「發帳號→授庫→同仁登入查詢→停用」在 UI 走通;一般用戶看不到 admin 頁與(預設下)工作流頁 +- **工程量**:中(約 1 個 CC 工作天) + +--- + +## 第二波(不在本 SDD 動工範圍,掛號) + +- MCP token 綁庫集合(design §9;PR#15 擴充,只動 `mcp/`) +- graph 逐節點/逐邊細粒度過濾 +- Google OAuth2 fast-follow、審計 log、忘記密碼 email 自助、舊資料 library 回填清潔工