# FR-132 STATE（living，就地改，只寫此刻）

> 最後更新 2026-10-09 10:50（第 8 棒收尾：**FR-132 arc 結案**——1.26.0 三環境升級完成、收尾文件齊；剩決策者打 tag 與收 Done）。母卡 CM-2510。歷史脈絡看同資料夾 `FR-132-LOG.md`（第 8 棒 block 在最後）。
> **接手側紀律：讀完、盤完即停，回報後等決策者下令才動手**——本檔「下一步」是建議清單，不是執行授權。

## 下一棒的角色（若有）

**本 arc 已結案，正常情況不需要下一棒。** 會再開棒只有三種情況：① 客戶／POC 回報權限相關 bug → 走 `docs/issues/` 或 Notion bug 卡，不回這個 arc；② 決策者要做 follow-up 清單裡的某一項（見「備忘」）→ 另開 FR 或子卡；③ site-regression 重建 → 另開 FR。接手時讀本檔「原始需求」「已定裁示」「環境事實」與 LOG 最後兩個 block 即可。

## 現況一句話

**2026-10-09 10:50（第 8 棒收尾）**：FR-132 存取管理全部完成並上版——**v1.26.0 在 190 e2e／STG 188／POC 189 三環境皆 1.26.0＋commit `01dca31a4`**，208 顆能力點全部真擋，出貨五角色、角色樹、指派起訖日、角色匯出匯入、檢查存取四頁上線；錯誤追蹤（Sentry）本版起隨包內建，190 已接落地版並核過事件。三 repo 皆在 **main**。76 張子卡（69 實作＋收口 5＋排練／真擋 2）首腦逐張驗過，等決策者收 Done；tag `v1.26.0` 待決策者打。

## 上版紀錄（第 8 棒，2026-10-08～09）

- **進版**：BE `73d5bc375`（RN／stamp／spec 快照 `docs/spec-site/v1.26.0/`）、FE `0e2b1799`；三 repo feature/azure-iam fast-forward 併回 main（決策者）。
- **出包**：GitLab pipeline 四次——2925839814 紅 classifier（jedi main 未含 1.6.3）；2925933217 綠但缺 sentry-sdk；2926571216 綠但缺 `sentry_sdk/integrations/`；**2926721749 最終**（main `01dca31a4`）。壞包改名 `.BAD-no-sentry-sdk`／`.BAD-sentry-integrations-missing` 留 188 `.build/bundle/`。根因與補強見 `docs/analysis/2026-10-09-fr132-v1260-three-bundles-sentry-nuitka.md`。
- **部署**：190（deploy 自動；第一次容器起不來是主機 seccomp errno 524、決策者重開後 `sudo guidantai start`）；STG 2928782083／POC 2928798069（deploy_only，決策者放行，首腦按 POC manual play）。三台皆八容器 healthy、schema_migrations 311（FR-132 26 支）、capabilities 208 全 enforce、每租戶一個系統管理員。升級前備份各在主機 `~/backup/`（188 基線庫另有 `guidant_ai_baseline_20261008_1536_before_FR-132.dump`）。
- **Sentry**：190 `guidant.env` 已放落地版 DSN，api log「錯誤追蹤已啟用（environment=PRD, release=guidant-ai@1.26.0+01dca31a47…）」，決策者核過事件。STG／POC 未放 DSN（log「未啟用：未設定連線位址」，預期），要收事件各自放進 `guidant.env` 後 `sudo guidantai start`，不用重發包。
- **Release note**：`docs/release_notes/v1.26.0.md`（SBOM 已填：四顆 image Critical／High 全 0、Trivy 合計 63；§2b 錯誤追蹤；部署段寫三次出包）。

## 原始需求（WHY）

公司層權限是 RBAC，骨架在但四處沒接上：部門範圍只存不判（指到某部門的角色在整個租戶有效）、起訖日判了但畫面設不了、33 支 API 只驗登入、角色只能逐筆勾 123 個能力點且三套命名寫法。另有兩個資安漏洞：選單明細與 JWT `is_admin` claim 不過濾到期／停用的指派。目標照 Azure「誰 × 角色 × 範圍 × 時效」補完：三段式能力點名（`grc.project.read`）、萬用字元角色（`grc.*.*`、`*.*.read`）、部門範圍與起訖日真的進判定、33 支補守門、存取管理前端四頁、角色 JSON 匯出匯入、預設關閉的部門資料隔離開關。專案層成員角色合併是 FR-B，另開。詳見 `design.md` 第 2 節。

## 文件座標

| 檔 | 用途 |
|---|---|
| `design.md`（447 行） | 決策、拆分表（每張卡的驗收與建議 model）；§6.1「情境判準」（153-163 行）與「模組定稿」（165-182 行） |
| `discussion.md`（722 行） | 討論稿（已定案），流程圖與現況細節 |
| `inventory/01～03` | 探脈證據三份（BE＋jedi-iam、專案角色與流程、前端），不再更新 |
| `inventory/a1-grc.md`、`a1-oscal-flow.md`、`a1-detection-evidence-survey.md`、`a1-system-iam.md`、`a1-platform.md` | A.1 五份盤點，各有「定案結論」節（T-1.6 的輸入，定案與樹不一致時以樹為準） |
| **`inventory/a1-capability-tree.md`**（1,456 行） | **A.2 起的唯一來源**：第一部分照選單逐頁（決策者核對用）、第二部分 12 模組資源×動詞樹、附錄 A route→能力點 557 支、附錄 B 123 舊名→新名、附錄 C 豁免、附錄 D 裁示 |
| `inventory/a1-shipped-roles.json` | 出貨五角色 pattern 定稿（A.2 產 seed 用；建表後 expands_to 重算） |
| `inventory/a1-d12-tables.md` | D12 挑選表與 23 條 policy 清單——**本版不用**，留下一版 |
| `notion-cards-spec.json`／`notion-cards.json` | 開卡規格與實際卡號／URL 對照 |
| `README.md` | 站首頁、總進度 |

## 已定裁示（不要重新討論）

- **D1–D12 全照 design.md 建議定案**（2026-10-06）。重點：D4 上層部門指派涵蓋子部門；D6 系統管理員 `*.*.*` 內建不可改不可刪、三個範例角色（稽核主管／稽核員／唯讀）可改可刪；D12 做機制＋租戶開關，預設關。
- **部門範圍採方式乙**：範圍套在資料列的 `org_unit_id` 上——掛在部門 X 的指派，只在被碰的資料落在 X 子樹內時啟用；使用者本人所屬部門（`user_org_units`）不參與判定。隔離開關關著時，部門指派等同整租戶有效（升級不改任何人權限）。
- **`require_capability_on(cap, org_unit_id)`** 單筆寫入守門要做，且直接擋（不走只記錄）。
- **只記錄模式是每個能力點一個旗標**，不是全域開關。
- **T-2.1 改名連程式內宣告一起改。**
- **`is_admin` 角色轉換**：租戶內能力點等於全集者轉 `*.*.*`（同租戶多個取最早建的那個當系統管理員），其餘保留 `is_admin` 旗標、能力點原樣轉、不升級。
- **首腦不切 branch**：A.2 起的實作由決策者另開 branch 後通知；A.1 唯讀，可在任一 branch 跑。
- **FR-B（專案層成員角色合併）另開 FR**，時間等決策者與 PM 討論。
- **模組 12 個**：grc、oscal、flow、detection、evidence、survey、system、iam、platform、asset、ai、workspace（表在 design §6.1）。
- **三條情境通則 A／B／C**：A 任務情境看任務權限；B 挑選名單看呼叫頁權限；C 多資源 API 先解析再判單一權限，不開擇一放行。原廠層兩道都過。
- information-system → asset；storage-config → system 且五門拆開（AI 服務設定→ai.ai-provider-config、Drive 憑證→platform、支援頁→platform.support）；ai-quota 拆 ai.quota／platform.ai-quota-ceiling；ai 獨立模組；公告與回饋→workspace，回饋分 feedback／feedback-review 不合併；license 原廠端→platform.license。
- 填答、檢測執行、任務問卷設定、專案雲端資料夾全歸 grc.job／grc.project；不開 survey.response。
- flow 維持獨立模組（防 `grc.*.*` 順帶拿到範本設計權）；開 flow.template.publish。
- 部門資源名 `iam.org-unit`（決策者：跟程式統一）。
- workflow.* 刪除；grc.audit 不拆；project.approve 名字移給 grc.audit.approve。
- jedi-* 套件該動就動、不逐條問（決策者 2026-10-06）；拆 jedi-remote-agent 守門插槽為讀寫兩個。
- **D12 部門資料隔離不做，記錄為設計決定**（決策者 2026-10-07 拍板，analysis `docs/analysis/2026-10-07-fr132-d12-org-unit-isolation-not-doing.md`）：部門只當屬性；T-3.6／T-5.6 結案 Done；`tenants` 不加開關欄；T-3.5 的 `require_capability_on` 留著當日後「只擋寫」的開關。
- **出貨五角色**：系統管理員 `*.*.*`、稽核主管、稽核員、一般成員（決策者裁補）、唯讀（列舉 read 不用 `*.*.read`）。**稽核員 job 只給 read／update**（2026-10-08 決策者裁拿掉 assign／import／export：稽核員不碰規劃與派工，但要能完成自己的任務；後端寫入另有「指派人或 manager」守門）、audit 加 create 不給 delete；可改角色都不給 `workspace.feedback.export`。
- **角色樹擁有者規則（決策者 2026-10-08 裁甲，CM-2594 補正）**：同一顆權限多頁時，直綁優先 → `home_route_name` 指到的候選頁 → 同資源數 → 先出現者。任務執行面 10 顆（檢視／修改任務、留言 ×4、證據 ×4）宣告歸專案總覽；建立／刪除／指派／匯入任務歸專案規劃；修改稽核歸稽核計畫。
- **角色樹內頁上樹例外（決策者 2026-10-08 點頭，CM-2594）**：第 6 棒「內頁一律不上樹」改為「內頁預設不上樹；`ui_routes.tree_page=true` 的內頁上樹成第三層子頁，收自己與底下內頁的權限」。首批三支：專案規劃、專案總覽、稽核計畫。名稱直接用側欄既有頁名，不另造階段名。
- **稽核七顆寫入權限歸「稽核計畫」頁、我的稽核只留檢視稽核**（同上卡）：我的稽核是個人視角清單、無寫入按鈕，2026-10-07 綁上去是權宜。
- **問卷本體端點依情境守門（決策者 2026-10-08 裁甲，CM-2595）**：`GET /survey/<uid>` 帶 `task_survey_uid`＝任務情境，看任務權限（依狀態兩顆＋專案參與者）；不帶＝管理情境，看 `survey.survey.read`。情境由前端明示，不反查。乙案（補授設計器權限）排除：會讓稽核員側欄冒出問卷管理、看到全租戶範本，且客戶自建角色不知要補。
- **任務產出物結案後視為證據（決策者 2026-10-08 裁甲案，CM-2593）**：問卷 status=9 後的內容／答案／歷史／討論，以及任務的檢測工具執行紀錄，持 `grc.job-evidence.read` 亦可讀；未結案問卷維持只看 `grc.job.read`；寫入端點不變。這是通則 A 的明文例外。
- T-1.6 首腦統一：survey.survey 不改名；platform.license 補 create／delete 空殼；`platform.drive-app-credential`；「範圍型讀取只開 read」唯一破例；license_module 存舊值；`evidence-classification`／`ai-assistant` 進 `INFRASTRUCTURE_MODULES`；taxonomy 寫入守 `detection.profile.update`；三支挑選下拉走通則 B。

## 卡片狀態（2026-10-07 下午）

| 子需求 | 卡號 | 狀態 |
|---|---|---|
| 母卡 | CM-2510 | Not started（標題仍寫 31 子卡，實為 32） |
| A.1 盤點與規則 | CM-2511～2516 | CM-2511～2515 Done；CM-2516 修正待驗證（三檔已驗收，等決策者看功能表後收 Done） |
| A.2 資料地基 | CM-2517～2522 | CM-2517／2518／2519／2520／2521 修正待驗證（首腦驗過）；CM-2522（T-2.6）修正待驗證（首腦驗過，190 排練零遺失） |
| A.3 判定層 | CM-2523～2530、CM-2546 | CM-2523／2524／2525／2526／2527／2529 修正待驗證（首腦驗過）；CM-2528 Done（D12 不做結案）；CM-2530（T-3.8）修正待驗證（首腦驗過，含補件：退回項＋`iam.user.assign`／`evidence.classification.execute` 兩顆新權限）；CM-2553（T-3.10）修正待驗證（首腦驗過；存帳號改差異更新保留起訖）；CM-2546（T-3.9）修正待驗證（首腦驗過；UI 建／改角色現已同時寫 pattern 表） |
| A.4 守門補齊 | CM-2531～2535、CM-2542～2545 | CM-2531／2532／2533 修正待驗證（首腦驗過）；CM-2534（T-4.4）修正待驗證（首腦驗過）；CM-2542（T-4.6）修正待驗證（首腦驗過；退回的 MOUNTS 一行由首腦派 sonnet 補 `0a02c575a`）；CM-2543／2544／2545（T-4.7a/b/c 套件 route 107 支）修正待驗證（首腦驗過）；CM-2535（T-4.5）修正待驗證（首腦驗過，真擋生效） |
| A.5 存取管理前端 | CM-2548～2552（舊 CM-2536～2540 作廢 Done） | CM-2548（T-5.1 元件＋可見頁面端點）修正待驗證（首腦驗過）；CM-2549（T-5.2 角色頁）／2550（T-5.3 指派頁）修正待驗證（首腦驗過）；CM-2551（T-5.4 檢查存取）／2552（T-5.5 收口）修正待驗證（首腦驗過）；**A.5 五張全收**；mockup v3 定稿在 `mockup/role-detail-v3.html`、`roles-and-assignments-v3.html`；CM-2541 Done（D12 不做）；**CM-2555（T-5.6）修正待驗證（首腦 headless 驗過 17:55）**：原四件（數字欄標題、租戶欄與篩選、列表匯出、指派對話框限同租戶）＋第 5 棒補件六件（操作欄改 icon 鈕、使用者欄可排序、權限與可見頁面欄本頁排序、樹不印網址、勾選框顏色、「佐證」統一為「證據」並拆開動詞說明、新增角色標頭改一般表單、範本改用對話框挑、指派對話框捲軸、指派表分組列底色與空欄、已刪除帳號的指派不顯示且使用者數兩條算法統一） |
| 手測回饋裁定 | CM-2556、CM-2557、CM-2558 | 決策者 2026-10-07 傍晚裁：CM-2556 補權限 migration（甲：新拆出的 90 項依附錄 A 分三類補給角色）、CM-2557 權限加歸屬頁（乙）**修正待驗證（首腦驗過，17:10；待裁 system.system-config 四顆暫放全站功能）**；CM-2556 補授 **修正待驗證（首腦驗過 17:25；舊客戶庫排練待 T-2.6，不算完整通過）**。**CM-2562 已修（`21b90c2c8`，第 5 棒 10/7 驗收通過，改寫 role_capability_patterns＋守衛測試）**——第 8 棒前 STATE 一直寫「新開未派」是漏更新，CM-2522／2535 兩棒卡上因此寫「缺口驗不到」，實際缺口已不存在；它們驗不到的只是「非全集 is_admin 角色」這個資料形狀。兩張已開未派；CM-2558 新增帳號直接指派多角色與起訖＋匯入**維持單角色**（決策者 17:35 裁回，多角色是首腦自加）並修「匯入產生部門範圍指派」bug（DEV 16 筆中 12 筆 org 由此來），已開。**2026-10-07 傍晚決策者令四張（2555～2558）平行派出，17:00 前後四棒皆已開跑，等修正待驗證**；卡上各有「平行派工說明」：2555 先做 AssignmentDialog 三件並先 commit，2558 先做匯入、FE 等 2555 的 commit；2556／2557 補權限都用 ON CONFLICT DO NOTHING；同一工作目錄無 worktree，只 add 自己的 hunk |
| **A.6 頁內按鈕照權限隱藏（2026-10-07 傍晚新增子需求）** | CM-2559（子母）、CM-2560（T-6.1）、CM-2561（T-6.2） | 決策者點名「只有後端守門、前端沒動」：117 支有按鈕的頁只有 17 支判權限、51 支寫入鈕無判斷。裁示：隱藏不停用、專案內頁一起收（雙層：公司層權限＋成員角色）、這版做。T-6.1／T-6.2 **修正待驗證（首腦驗過 18:20）**；盤點：428 顆／145 檔，要改 342 顆（222 顆帶專案層條件），附錄 A 查不到 0 筆；四題首腦已裁（寫在 CM-2561 驗收段）；**T-6.3～T-6.10 共 8 棒待開**，另一張死碼清理卡；**缺口（決策者 18:40 問出）：導覽類（router.push／link 約 190 處）沒盤**，FE 141 條路由只有 42 條被側欄門檻擋、路由守衛只擋 admin 旗標，內頁直入不擋——盤點二已併入 CM-2564（登記本身就是盤點）；路由層不用前端 meta 寫死，改後端登記（analysis 丙案排除理由）；實作棒依賴 CM-2556 先補權限 |
| 手測回饋第三批（第 7 棒） | CM-2592～2595 | **四張皆修正待驗證（首腦皆驗過）**；首腦直做無卡：FE `a9c15c1d`＋BE `d519efe7c` 擁有者歸專案總覽（2594 補正）、FE `3b1ff397` 指派頁分組列照 mockup、FE `4b838449` 抽屜 hasCap→v-can 守衛修回、FE `b0ff4b3d` 藏「依資源」：2594 專案管理拆三工作面子頁＋稽核七顆歸稽核計畫（opus，含 jedi-iam 模型加欄＋一支 migration）；2592 任務卡片照「檢視任務」擋點開（輪次總覽 AoJobSection＋待辦任務頁 row-click，sonnet）；2593 結案問卷與掃描紀錄以「檢視任務證據」可讀（決策者裁甲，跨 BE／jedi-survey／jedi-detection／FE，opus，含一支 migration→基線累計 23 支）；首腦直做未開卡：FE `cb3308e0`（問卷非指派人員判定＋抽屜三區塊照權限隱藏）、FE `1005d2e6`（角色樹找回檢視任務＋審閱任務文案） |
| 手測回饋第二批（第 6 棒） | CM-2586、CM-2587、CM-2588 | 皆修正待驗證（首腦驗過）：2586 帳號編輯頁角色改指派表（runner 82368c97 → 首腦重做 09d54f1b）；2587 Drive folders 改守 `grc.project.read`（BE f3f906a3b）；2588 補 `grc.audit.read` migration（BE 1b0c0c1d0，DEV 已套）。另 FE 988d0f3f 勾選框修正無卡（決策者令首腦直做） |
| 收口 | CM-2554 | T-6.1 手測清單卡：已開未派，決策者裁先不需要 |

## 待裁

無。本 arc 所有裁示已落地（見「已定裁示」與 LOG）。

## 決策者驗證路徑（2026-10-07 首腦給的 15 步）

帳號：blsadmin（系統管理員）、blsit（IT Manager）、blspan（稽核人員）。

**一、擋人**
1. blspan 登入，側欄沒有存取管理入口。
2. blsit 登入，指派頁沒有新增指派鈕。
3. blsadmin 登入，全部都有。

**二、角色改了，判定跟著變**
4. 以「稽核人員」為範本建一個「驗收用」角色，拿掉「檢視總結報告」。
5. 把它指派給 blspan。
6. blspan 重登，側欄少一頁。
7. 回角色頁把權限勾回來，blspan 重登，那頁回來。

**三、到期**
8. 用 SQL 把該指派的 `ends_at` 改成昨天。
9. blspan 重登，功能消失；指派頁顯示「已到期」且看得到。

**四、存帳號不弄壞指派**
10. 帳號頁改一個人的電話存檔，回指派頁到期日仍在。
11. 帳號表單的角色區塊是唯讀，旁邊有「管理指派」鈕。

**五、檢查存取**
12. 搜 blsit：列出來源角色與到期日；右欄可見選單要等於他實際看到的側欄。搜 blsadmin：出現豁免說明。

**六、只記錄沒擋人**
13. blsit 把全站頁面點一遍，畫面不變；`grep -c '\[authz.log_only\]' log/app.log` 的數字在增加。

**七、匯出匯入**
14. 角色匯出，改個名字再匯入，成功。
15. 匯入含 `foo.bar.*` 的角色，回 400 並列出不認得的項目。

驗完清理：

```sql
DELETE FROM user_roles WHERE role_id IN (SELECT id FROM roles WHERE name LIKE '驗收用%');
DELETE FROM role_capability_patterns WHERE role_id IN (SELECT id FROM roles WHERE name LIKE '驗收用%');
DELETE FROM role_capabilities WHERE role_id IN (SELECT id FROM roles WHERE name LIKE '驗收用%');
DELETE FROM roles WHERE name LIKE '驗收用%';
```

## 下一步（決策者本人的動作）

1. **打 tag**：BE 與 FE 兩 repo 在 main `git tag v1.26.0` 後 `git push origin v1.26.0`（push 預設不帶 tag）。jedi monorepo 不打產品 tag（套件各自版號已在 Nexus）。
2. **收 Done**：71 張修正待驗證（含 CM-2522、CM-2535）＋收口 CM-2596／2599（CM-2597／2598 裁不做，可 Done 並註明）＋CM-2600；母卡 CM-2510 最後收。
3. POC 升級後請 PM 開 189 看一眼存取管理四頁。

**備忘（follow-up，不在本 arc）**：site-regression 整套重建（決策者裁範圍：整組重寫 vs 縮 smoke＋主鏈兩層；重建前發版不以 e2e 為 gate）；乾淨安裝無基線庫時能力點如何從套件宣告長出（另開 FR）；提權入口「只能指派不高於自己的角色」（下一版）；FR-B 專案層成員角色合併；D12 部門資料隔離記為不做；舊資料與法規證據保留（另開討論串）；`GET /user/<uid>` 對停用列回 500（jedi-iam `user_route.py:146`，一般操作碰不到，順手收）；DEV `.env` 有 SENTRY_DSN，DEV 的 500 會真的送到那個站台，不想收就註解掉重起；三條既有紅燈（route_guard_inventory survey 兩支未登記、permission_matrix_three_way FE v-can 未重產、drive_sync_admin_service guard_non_manager[None]）。

## 環境事實

- **DEV**：本機 `localhost:5432/guidant_ai_dev`（cmmgr 密碼查 `.env` 的 **`DB_PASSWORD`**，CLAUDE.md 已改）。BE 8000 pid 63862（含 DSN 的 .env 起的）、FE 5180。pyproject 已釘版（19 支新版號），改套件源碼要重新切 path 模式。
- **三環境**：190 e2e／188 STG／189 POC 皆 1.26.0＋`01dca31a4`，stack 在 `/srv/guidant-ai`，DB 走 `docker exec guidant-db`。三台主機都有 `reboot-required` 旗標（unattended-upgrades 裝了新核心未重開），升級後容器起不來（seccomp errno 524）就重開再 `sudo guidantai start`，不重跑 upgrade；190 已重開到 5.15.0-198，188／189 未重開。
- **188 build 機**：`/opt/guidant-ai-be` 在 main `01dca31a4`，磁碟清過（舊包 1.24.x／1.25.0 已刪、1.25.1 留回退）；取消的 pipeline 殘留 Nuitka／scons 子程序要手動 kill 才能重跑。
- **基線庫** 188:25432 `guidant_ai`：245 支 migration、208 顆全 enforce，與 `scripts/init/` 三份產生檔對齊（`a256816da`）。本機直連可用，密碼同 DEV `DB_PASSWORD`。
- **Nexus**：19 支 jedi 新版已發（jedi-iam 1.5.0），jedi repo main `143c309e`。
- **陷阱**：jedi-common `db_mw.py` before_flush 會把呼叫者部門蓋進 `org_unit_id=None` 的新列，`UserRole` 已 opt-out；headless 注入 token 要連 `permissions` 一起塞 `cm_store`；pattern 展開有 Redis 快取，直接 SQL 塞 pattern 不清快取；`test_module_boundaries` 基線重產前三條會紅（已綠）。

## 冷接自檢（答不出來回去讀 design.md 第 2、4、6.1 節與 LOG 最後兩個 block）

1. 決策者拿掉「檢視任務證據」後抽屜還看得到證據，是 bug 嗎？為什麼？
2. 結案問卷誰能讀？未結案呢？規則寫在哪一層（route／service）？
3. 角色樹同一顆權限列在多頁時，誰可勾？三條判準的順序？
4. 出貨「稽核員」的任務組為什麼留 update 不留 assign？
5. 基線重產之前有哪三條測試會紅、為什麼不算誰弄壞的？
