跳至主要内容

ADR-031: 風險導向的 API Capability、資料範圍與稽核

ADR 編號: 031 狀態: 已接受,分階段實作中 (Accepted) 決策日期: 2026-08-14 決策者: Development Team 取代: Authority Model 中「每個 Entity 預設展開 R/W/X/D」的設計慣例 被取代: 無


摘要

API Authority 改以業務 capability 與風險為設計單位,不再依 Entity × CRUD 機械展開。每個 endpoint 在實作前先完成 consumer/lifecycle、security classification、risk、capability、data scope、public predicate 與 audit 的設計矩陣。非敏感端點以 Authenticated + Audit 提供可追溯性,敏感端點才增加 Authority;data scope 依資料邊界獨立適用。Authority 收斂或改名時,Role seed 以顯式撤權遷移既有部署。

背景 (Context)

CRUD-first 讓 Authority 數量隨 Entity 成長,使 Role seed 難以理解,也把公開讀取、管理讀取與 ownership 混在一起。另一方面,缺少消費者的 reference/obsolete API 常因「既然存在就補權限」而永久保留; 過度複雜的 Authority catalog 也容易讓應用層錯配、漏配或以錯誤 capability 保護端點。Audit 因此必須 被用來承擔非敏感端點的事後稽核,但不能放寬敏感端點真正需要的 Authority 與 data scope。

現行框架已具備 resource:actionAuthorityContributorSecurityContributor、持久 Audit sink 與 tenant/ownership primitive,但尚未提供跨這些能力的設計閘門,Role reconcile 也只有 additive 行為。

考量的方案 (Options Considered)

方案 A:維持 Entity × R/W/X/D

優點是規則機械、容易產生;缺點是無法表達風險、職責與資料範圍,Authority 與 Role seed 持續膨脹。

方案 B:每個 endpoint 一個 Authority

能精確控制,但數量更多,且把 URL/HTTP method 當成業務能力,重構 API 就會改變授權詞彙。

方案 C:風險導向 Authenticated/Audit + capability + object scope(採用)

非敏感資訊與低風險操作採明確 Authenticated + Audit,不建立 Authority;只有敏感資訊或敏感/高影響 操作才建立最小 capability。Method security、object policy 與 Audit 依風險組合。

決策 (Decision)

1. 先盤點生命週期,再設計權限

每個 Controller/domain 先盤點 UI、外部 client、背景流程、workflow、framework feature 與 reference/obsolete 來源,結果只能是保留、由框架取代或退役。無消費者且已有替代方案時不得新增 Authority。

2. Authority 表達 capability

Authority 不是 authenticated endpoint 的預設配備。只有敏感資訊或敏感/高影響操作跨過授權門檻時 才建立 capability,命名維持 {domain}:{capability}managedeleteread_allexport 是候選詞彙, 不是固定套餐;領域狀態轉換可用明確動詞。HTTP method 或 CRUD 名稱本身不構成拆分理由。

3. 每個 endpoint 必須有明確分類

分類為 Public、Authenticated、Capability protected、Object scoped 或 System/operation only。 Method annotation 與 SecurityContributor matcher 都是合法宣告面;anyRequest().authenticated() 只是 防漏底線,不算完成分類。框架測試工具應驗證每個 endpoint 都能追溯到唯一 policy owner。

4. 資料範圍獨立於 Authority

非敏感端點可使用 authenticated policy;敏感端點再加 method capability。service/policy 層獨立回答 「能操作哪筆資料」。ownership、 organization、assignee、creator 與 tenant 範圍集中在 service/policy,不散落 Controller。存在枚舉或 IDOR 風險時使用 scoped lookup,以 404 遮蔽未授權資源。

此處的 404 遮蔽只適用於 object/resource authorization decision:service/policy 已判定呼叫者 不在該筆資料的可見範圍時,可把「存在但不可見」與「不存在」映成相同的 404。它不適用於帳號、 credential、challenge 等 authentication 失敗,也不規範既定錯誤的 response 欄位揭露。 ErrorDisclosurePolicy 只投影已完成的 status/type/detail 決策,不得把 404 改成 403、反推或揭露 資源存在性;相反地,最大揭露也不得被用來繞過本段的 object-scope 決策。

5. Public 必須明示並限制狀態

公開 API 必須由明確 permitAll policy 擁有,且查詢只回傳已發布、未過期、未撤銷、可對外顯示的資料。 漏寫 method security 不代表公開。

6. Audit 是低風險端點的正式保護機制

非敏感資訊與低風險操作以明確 authenticated policy 加 Audit 提供事後可偵測、追責與修復能力,藉此 避免為低風險端點建立 Authority。敏感讀取、export、權限變更、不可逆刪除、跨組織操作與法遵狀態 變更仍必須先有 Authority 與適用 data scope,再記 Audit。事件只保存 actor、action、resource locator、result、changed field names、timestamp 與 acting context;不複製 secret、token、附件、個資全文或正文。

7. Role seed 支援顯式撤權

Role seed 可宣告 revokedAuthorities。Reference reconcile 只對 seed 擁有的 SYSTEM role 撤回明列 關聯,CUSTOM role 不受影響;重跑必須冪等。孤兒 Authority 預設保留並告警,刪除須另立資料遷移決策。

權衡分析 (Trade-offs)

  • Authority 與 Role seed 更接近業務責任,數量不再與 Entity × CRUD 成正比。
  • 非敏感端點以 Authenticated + Audit 管理,進一步降低 Role seed 與 Authority catalog 複雜度。
  • 設計階段需要額外產出授權矩陣,且不能只從 Controller 自動反推完整 policy。
  • manage 的範圍必須在各 domain 明文定義;過度收斂仍可能造成權限過大。
  • 既有 CRUD Authority 不立即批次改名;先盤點消費者,再以 revoke/rename migration 漸進收斂。

實作指南 (Implementation Guidelines)

API Spec 必須產出:

EndpointConsumer/lifecycleClassificationRiskCapabilityData scopePublic predicate/maskingAudit

最低測試矩陣涵蓋 Authenticated 的 401/成功/Audit、敏感 capability 的 403/成功、跨 scope 的 403/404、公開狀態 404 masking,以及適用操作的 Audit 持久化與敏感 payload 排除。完整方法見 Authority 權限模型

相關文檔 (References)

變更歷史 (Change Log)

日期變更內容變更者
2026-08-14接受風險導向 capability、object scope、Audit 與 seed revoke 決策Development Team + AI Assistant
2026-08-14明定非敏感端點以 Authenticated + Audit 保護,Authority 只用於敏感資訊與操作Development Team + AI Assistant
2026-08-21明定 404 masking 僅屬 object/resource authorization;authentication 與錯誤欄位揭露由不同政策處理Development Team + AI Assistant

文檔維護者: Development Team + AI Assistant 最後審閱: 2026-08-21