# FR-048 全站統一授權守門 — 完工 SUMMARY（2026-07-07 收尾）

> user 已手測通過全部 phase（含 4b 五件與 4a 語意變化確認）。branch `fix/v1.8.0-bugs`，未 push。
> 起源：FR-047 spec 手冊已知坑盤點 §SEC 桶（75 條）→ 實查升級為全站系統性缺口 → 一天內設計拍板 + 六波落地。

## 1. 一句話

把「寫入端點只有 JWT、無角色守門」的全站缺口，收斂成 `common/authz/` 單一守門機制（五軸），
全站 373 支寫入端點逐支判軸掛守，RBAC capability 從「只藏 FE 按鈕」變成 BE 真 enforce。

## 2. 最終形態（開發者視角）

- **canonical 只有一個**：`common/authz/`（決策表在其 `__init__.py`），禁止另立 helper。
- **兩層半模型**：主體層 RBAC（capability／platform-admin／super-admin=break-glass）＋
  資源層成員資格（project/SSP/workflow 單軸三解析器）＋ signed-token（免 bearer 投遞）。
- **雙軌放置**：主體域守門＝route decorator（`@require_capability` / `@require_platform_admin_route`）；
  資源域守門＝app service 層（`assert_project_manager` / `assert_project_role` /
  `assert_project_participant` / `SspPermissionChecker` / workflow guard）。
- **能力點單一真相**：BE 守門讀的＝FE 角色矩陣勾的（121 顆既有 granular cap，動詞精準對 HTTP verb）；
  super_admin 為 break-glass 旁路。

## 3. 六波落地（BE 48 commits ＋ FE 1 commit）

| Phase | 內容 | 關鍵 commits |
|-------|------|-------------|
| 設計 | 五軸模型／兩層半／全站盤點定 scope／P1–P4＋D1–D15＋Q1/Q2 拍板 | `4aa8edce` `b2270dab` `f97e8fd5` |
| 1 | 建 `common/authz/`（4 套搬家 shim＋`require_super_admin` 正名）＋CLAUDE.md 回寫 | `69e043c4` `ee21764a` |
| 2a | 全站 373 支端點授權矩陣（8 subagent 盤點＋交叉驗證 75 pit） | `f0c8d304` |
| 3 | 主體域 decorator＋116 支掛點＋插隊件（schedule-report 任意檔讀取、debug mail route 移除）＋C 類 22 處 inline is_admin 收編 | `f462c2a8`〜`249d293a` |
| 2b/2b-2/2b-3 | 資源域補守（grc D6/D7/D8、SSP export、PSR、留言、batch-complete）＋**flow_engine 守門復活**（v2 鏈）＋evidence_classification 統一 manager＋MF 敏感 GET＋D14 補 JWT | `80514dff` `0f50bbd0` `a83a8619` 等 |
| 2c | 7 份私有 `_check_*` 收編 `assert_project_role` 委派（行為保真）＋AR manager 代行對齊（user 定調） | `616d84dc` `9bb154b4` |
| 4a | capability guard（memoize＋break-glass）＋seed migration（3 組缺口，DEV 已套）＋35 檔換裝、`@require_super_admin_route` 歸零 | `eb590ae4` `7828653e` `e8b28a4a` |
| 4b | signed-token 機制＋五件免 bearer 端點（otp-qrcode 自我限定／框架下載／file 雙軌／survey／task-survey 判 dead）；FE `79c0133`（17 檔） | `40a7d9c5` |

## 4. 行為差異（user 已逐項手測）

1. **系統管理頁寫入**（user/role/org/設定/選單/設備/公告/問卷/範本…）：無對應能力點的帳號 → 403
   `GRC_CAPABILITY_REQUIRED`；**持 Administrator 角色的一般帳號可過**（放寬到 RBAC 正軌）；super_admin 恆過。
2. **GRC 專案寫入**：非該專案 manager（或規定角色）→ 403；AR 寫入 manager 可代行 auditor（對齊全站 override）。
3. **flow_engine 任務/證據**：非該專案參與者 → 403（守門自 FR-038 停用以來首次恢復）。
4. **免 bearer 端點**：QR/下載改走 120 秒簽章 token；otp-qrcode 只能拿自己的（原「知 uid 拿他人 TOTP」洞關閉）；
   file download 雙軌、既有 axios 呼叫方零影響。
5. **未認證洞全關**：log export（SEC-001）、schedule-report 任意檔讀取、debug 寄信 route、issue/get_members、MF 靜態範本。

## 5. 規範文件

- 設計：`docs/analysis/2026-07-07-unified-auth-guard-design.md`（拍板紀錄 P1–P4＋兩層半模型＋反悔條件）
- 台帳：`endpoint-authz-matrix.md`（373 支逐支狀態，§6–§9 各 phase 落地紀錄）— **living tracker，後續改權限先看這份**
- 追蹤：`docs/analysis/2026-07-07-known-pits-remediation-tracker.md` §SEC（75 條銷帳）
- 手冊：Notion「Guidant AI 權限控管使用手冊」（本次收尾新建，見 Notion）
- CLAUDE.md 權限段＋`docs/claude/domain-capabilities.md` 已於 Phase 1 回寫

## 6. Follow-ups（未完事項）

| 項 | 說明 |
|----|------|
| **e2e 兩條** | 4b 前科件（QR 顯示／框架下載）在 test repo 補；含負向案（登出直打→401）＋token 過期實測 |
| **STG/POC migration** | `2026-07-07-fr048-phase4a-capability-seed.sql` 只套了 DEV，部署前要套 |
| **push** | BE 48＋FE 1 commits 全未 push，等 user 指示 |
| 頁面 spec §權限矩陣批次更新 | 67 頁 spec 的權限段與新守門對齊（FR-047 手冊模式，量大另排） |
| api-spec 新端點補登 | 4b 新增 token 發放端點（otp-qrcode-token / oscal token / file access-token / survey token） |
| Phase 5（另案） | 守門下沉 jedi-auth service、platform-admin→capability 併軸、context enrich 評估、process/comments PUT |
| 零星 | subtask_status_history 隨 v1 退役；D 族資訊洩漏（issue token 明文等）在其他桶 |

## 7. 部署 handover

1. 套 STG/POC migration（cmmgr、`--single-transaction`）
2. 部署 BE＋FE **必須同版**（4b 的 token 流程 BE/FE 成對，只上一邊會壞 QR/下載）
3. 部署後煙測：登入→個資頁 QR、框架 OSCAL 下載、任一檔案下載、一般帳號打系統設定寫入 403
