# FR-048 Phase 2a — 授權守門盤點：api/oscal

> FACTUAL inventory only（無軸別判定）。Blueprint url_prefix = `/api/1.0`。
> 追蹤方法：route method 讀 decorator + 呼叫的 app-service method，再 trace 進 service 找授權守門。
> 守門常量：`require_platform_admin()`（root 租戶）/ `SspPermissionChecker.require_manager|require_participant`（專案 manager/participant）/ 手動 `ForbiddenError` role 檢查。

## api/oscal

| Route path | Method | Route file:line | @jwt_required? | 呼叫的 service method | 現況守門 | 備註 |
|---|---|---|---|---|---|---|
| /api/1.0/oscal-frameworks | POST | api/oscal/routes/framework/oscal_framework_route.py:49 | 是 | framework_app_service.get_frameworks_and_pager | 僅 JWT | POST 實為分頁查詢(讀) |
| /api/1.0/oscal-framework | POST | api/oscal/routes/framework/oscal_framework_route.py:78 | 是 | framework_app_service.add_framework | 已有: require_platform_admin() @ app/oscal/service/framework_app_service.py:124 | |
| /api/1.0/oscal-framework/&lt;uid&gt; | PUT | api/oscal/routes/framework/oscal_framework_route.py:92 | 是 | framework_app_service.update_framework | 已有: require_platform_admin() @ app/oscal/service/framework_app_service.py:147 | |
| /api/1.0/oscal-framework/&lt;uid&gt; | DELETE | api/oscal/routes/framework/oscal_framework_route.py:101 | 是 | framework_app_service.delete_framework | 已有: require_platform_admin() @ app/oscal/service/framework_app_service.py:161 | |
| /api/1.0/oscal/framework-versions/import | POST | api/oscal/routes/framework/oscal_import_route.py:28 | 是 | framework_app_service.import_framework_version | 已有: require_platform_admin() @ app/oscal/service/framework_app_service.py:177 | 上傳檔案匯入 |
| /api/1.0/oscal-framework-versions | POST | api/oscal/routes/framework/oscal_framework_version_route.py:47 | 是 | framework_version_app_service.get_versions_and_pager | 僅 JWT | POST 實為分頁查詢(讀) |
| /api/1.0/oscal-framework-version | POST | api/oscal/routes/framework/oscal_framework_version_route.py:77 | 是 | framework_version_app_service.add_version | 已有: require_platform_admin() @ app/oscal/service/framework_version_app_service.py:184 | |
| /api/1.0/oscal-framework-version/&lt;uid&gt; | PUT | api/oscal/routes/framework/oscal_framework_version_route.py:92 | 是 | framework_version_app_service.update_version | 已有: require_platform_admin() @ app/oscal/service/framework_version_app_service.py:207 | |
| /api/1.0/oscal-framework-version/&lt;uid&gt; | DELETE | api/oscal/routes/framework/oscal_framework_version_route.py:103 | 是 | framework_version_app_service.delete_version | 已有: require_platform_admin() @ app/oscal/service/framework_version_app_service.py:223 | |
| /api/1.0/oscal-framework-version/download/oscal/&lt;uid&gt; | GET | api/oscal/routes/framework/oscal_framework_version_route.py:129 | 否 | framework_version_app_service.get_version + oscal_export_app_service.export('catalog',...) | 無 JWT | 敏感 GET(下載 OSCAL JSON)；刻意免授權（FE window.open 無法帶 bearer），註解稱靠 unguessable uuid + 系統層共用資料 |
| /api/1.0/oscal-catalog-group/&lt;uid&gt; | PUT | api/oscal/routes/framework/framework_version_edit_route.py:50 | 是 | framework_version_edit_service.update_group | 已有: require_platform_admin() @ app/oscal/service/framework_version_edit_service.py:132 | |
| /api/1.0/oscal-catalog-group/&lt;uid&gt; | DELETE | api/oscal/routes/framework/framework_version_edit_route.py:64 | 是 | framework_version_edit_service.delete_group | 已有: require_platform_admin() @ app/oscal/service/framework_version_edit_service.py:203 | |
| /api/1.0/oscal-catalog-control/&lt;uid&gt; | PUT | api/oscal/routes/framework/framework_version_edit_route.py:80 | 是 | framework_version_edit_service.update_control | 已有: require_platform_admin() @ app/oscal/service/framework_version_edit_service.py:146 | |
| /api/1.0/oscal-catalog-control/&lt;uid&gt; | DELETE | api/oscal/routes/framework/framework_version_edit_route.py:94 | 是 | framework_version_edit_service.delete_control | 已有: require_platform_admin() @ app/oscal/service/framework_version_edit_service.py:214 | |
| /api/1.0/oscal-catalog-control-assessment/&lt;uid&gt; | PUT | api/oscal/routes/framework/framework_version_edit_route.py:110 | 是 | framework_version_edit_service.update_assessment | 已有: require_platform_admin() @ app/oscal/service/framework_version_edit_service.py:176 | |
| /api/1.0/oscal-catalog-control-assessment/&lt;uid&gt; | DELETE | api/oscal/routes/framework/framework_version_edit_route.py:124 | 是 | framework_version_edit_service.delete_assessment | 已有: require_platform_admin() @ app/oscal/service/framework_version_edit_service.py:225 | |
| /api/1.0/oscal-framework-parse-jobs/parse | POST | api/oscal/routes/framework/framework_parse_job_route.py:58 | 是 | framework_parse_job_service.parse | 已有: require_platform_admin() @ app/oscal/service/framework_parse_job_service.py:143 | 上傳 PDF 匯入 |
| /api/1.0/oscal-framework-parse-jobs/&lt;uid&gt; | DELETE | api/oscal/routes/framework/framework_parse_job_route.py:140 | 是 | framework_parse_job_service.discard | 已有: require_platform_admin() @ app/oscal/service/framework_parse_job_service.py:366 | |
| /api/1.0/oscal-framework-parse-jobs/&lt;uid&gt;/confirm | POST | api/oscal/routes/framework/framework_parse_job_route.py:159 | 是 | framework_parse_job_service.confirm | 已有: require_platform_admin() @ app/oscal/service/framework_parse_job_service.py:259 | 寫 catalog/profile/version |
| /api/1.0/oscal/resource-libraries | POST | api/oscal/routes/resource_library_route.py:43 | 是 | resource_library_app_service.create_resource_library | 僅 JWT | 建立資源庫（clone framework_version 三件組）；service 內無授權守門 |
| /api/1.0/oscal/resource-libraries/list | POST | api/oscal/routes/resource_library_route.py:28 | 是 | resource_library_app_service.get_resource_libraries_and_pager | 僅 JWT | POST 實為分頁查詢(讀) |
| /api/1.0/oscal/resource-library/&lt;uid&gt;/publish | POST | api/oscal/routes/resource_library_route.py:76 | 是 | resource_library_app_service.publish_resource_library | 僅 JWT | 狀態轉換(發佈)；service 內無授權守門 |
| /api/1.0/ssp-excel-imports/parse | POST | api/oscal/routes/ssp/ssp_excel_import_route.py:36 | 是 | ssp_excel_import_app_service.upload_and_parse | 條件式：source_type=='ssp' → _require_project_manager @ app/oscal/service/ssp_excel_import_app_service.py:745(_verify_source_exists→745); framework_version/module_frame source_type 僅 tenant 檢查、無專案級授權 | 通用 import 入口，source_type 由 form 傳入 |
| /api/1.0/ssp-excel-import/&lt;parse_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_excel_import_route.py:85 | 是 | ssp_excel_import_app_service.discard_parse | 條件式：source_type=='ssp' → _require_project_manager @ app/oscal/service/ssp_excel_import_app_service.py:271; 其他 source_type 僅 tenant 檢查 | |
| /api/1.0/ssp-excel-import/&lt;parse_uid&gt;/confirm | POST | api/oscal/routes/ssp/ssp_excel_import_route.py:103 | 是 | ssp_excel_import_app_service.confirm_import | 條件式：source_type=='ssp' → _confirm_update_project_ssp→_require_project_manager @ app/oscal/service/ssp_excel_import_app_service.py:455; framework_version/module_frame(Model A/B) 僅 tenant 檢查、無專案級授權 | 建 MF/Profile/parties 或寫專案 SSP |
| /api/1.0/ssp-docx-imports/parse | POST | api/oscal/routes/ssp/ssp_docx_import_route.py:33 | 是 | ssp_docx_import_app_service.upload_and_parse | 條件式：source_type=='ssp' → _require_project_manager @ app/oscal/service/ssp_docx_import_app_service.py:137; module_frame preselect-new → is_admin 檢查 raise ForbiddenError @ 142-143; 既有資源庫 source 僅存在檢查、無授權 | 通用 import 入口 |
| /api/1.0/ssp-docx-import/&lt;parse_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_docx_import_route.py:77 | 是 | ssp_docx_import_app_service.discard_parse | 條件式：source_type=='ssp' → _require_project_manager @ app/oscal/service/ssp_docx_import_app_service.py:279; 其他 source_type 僅 tenant 檢查 | |
| /api/1.0/ssp-docx-import/&lt;parse_uid&gt;/confirm | POST | api/oscal/routes/ssp/ssp_docx_import_route.py:96 | 是 | ssp_docx_import_app_service.confirm_import | 條件式：source_type=='ssp' → _confirm_update_project_ssp→_require_project_manager @ app/oscal/service/ssp_docx_import_app_service.py:465; 其他 source_type 僅 tenant 檢查 | 寫入 SSP / module_frame |
| /api/1.0/ssp/&lt;ssp_uid&gt;/excel-import/upload | POST | api/oscal/routes/ssp/ssp_scoped_excel_import_route.py:42 | 是 | ssp_excel_import_app_service.upload_and_parse (source_type 強制 'ssp') | 已有: _require_project_manager @ app/oscal/service/ssp_excel_import_app_service.py:745（_verify_source_exists→745，source_type=='ssp' 恆觸發） | scoped route；只註冊 upload（preview/confirm 走非 scoped route，其 class 在 __init__.py 已註解停用） |
| /api/1.0/ssp/&lt;ssp_uid&gt;/system-characteristic | PUT | api/oscal/routes/ssp/ssp_system_characteristic_route.py:41 | 是 | ssp_system_characteristic_app_service.update | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_system_characteristic_app_service.py:54 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/components | POST | api/oscal/routes/ssp/ssp_components_route.py:43 | 是 | ssp_components_app_service.add_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_components_app_service.py:63 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/components/&lt;item_uid&gt; | PUT | api/oscal/routes/ssp/ssp_components_route.py:61 | 是 | ssp_components_app_service.update_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_components_app_service.py:86 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/components/&lt;item_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_components_route.py:76 | 是 | ssp_components_app_service.delete_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_components_app_service.py:105 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/inventory-items | POST | api/oscal/routes/ssp/ssp_inventory_items_route.py:42 | 是 | ssp_inventory_items_app_service.add_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_inventory_items_app_service.py:74 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/inventory-items/&lt;item_uid&gt; | PUT | api/oscal/routes/ssp/ssp_inventory_items_route.py:60 | 是 | ssp_inventory_items_app_service.update_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_inventory_items_app_service.py:95 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/inventory-items/&lt;item_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_inventory_items_route.py:75 | 是 | ssp_inventory_items_app_service.delete_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_inventory_items_app_service.py:114 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/leveraged | POST | api/oscal/routes/ssp/ssp_leveraged_route.py:36 | 是 | ssp_leveraged_app_service.add_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_leveraged_app_service.py:74 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/leveraged/&lt;item_uid&gt; | PUT | api/oscal/routes/ssp/ssp_leveraged_route.py:54 | 是 | ssp_leveraged_app_service.update_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_leveraged_app_service.py:95 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/leveraged/&lt;item_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_leveraged_route.py:69 | 是 | ssp_leveraged_app_service.delete_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_leveraged_app_service.py:118 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/parties | POST | api/oscal/routes/ssp/ssp_party_route.py:39 | 是 | ssp_party_app_service.add_party | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_party_app_service.py:78 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/parties/&lt;party_uid&gt; | PUT | api/oscal/routes/ssp/ssp_party_route.py:59 | 是 | ssp_party_app_service.update_party | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_party_app_service.py:99 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/parties/&lt;party_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_party_route.py:75 | 是 | ssp_party_app_service.remove_party | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_party_app_service.py:115 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/ssp-resources/items | POST | api/oscal/routes/ssp/ssp_resources_route.py:46 | 是 | ssp_resources_app_service.add_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_resources_app_service.py:38 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/ssp-resources/items/&lt;item_uid&gt; | PUT | api/oscal/routes/ssp/ssp_resources_route.py:64 | 是 | ssp_resources_app_service.update_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_resources_app_service.py:45 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/ssp-resources/items/&lt;item_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_resources_route.py:79 | 是 | ssp_resources_app_service.delete_item | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_resources_app_service.py:51 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/document-pool | POST | api/oscal/routes/ssp/ssp_document_pool_route.py:55 | 是 | ssp_document_pool_service.add_to_pool | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_document_pool_service.py:64 | 上傳程序書到池 |
| /api/1.0/ssp/&lt;ssp_uid&gt;/document-pool/&lt;doc_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_document_pool_route.py:73 | 是 | ssp_document_pool_service.delete_from_pool | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_document_pool_service.py:118 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/document-mappings | POST | api/oscal/routes/ssp/ssp_document_pool_route.py:103 | 是 | ssp_document_pool_service.add_control_mappings | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_document_pool_service.py:155 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/document-mapping/&lt;doc_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_document_pool_route.py:122 | 是 | ssp_document_pool_service.remove_control_mapping | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_document_pool_service.py:163 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt;/document-mappings | POST | api/oscal/routes/ssp/ssp_document_pool_route.py:154 | 是 | ssp_document_pool_service.add_ao_mappings | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_document_pool_service.py:184 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt;/document-mapping/&lt;doc_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_document_pool_route.py:174 | 是 | ssp_document_pool_service.remove_ao_mapping | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_document_pool_service.py:192 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt; | POST | api/oscal/routes/ssp/ssp_control_implementation_route.py:66 | 是 | ssp_control_implementation_service.update_control_implementation | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:63 | Upsert |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt; | PUT | api/oscal/routes/ssp/ssp_control_implementation_route.py:86 | 是 | ssp_control_implementation_service.update_control_implementation | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:63 | Upsert |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt; | POST | api/oscal/routes/ssp/ssp_control_implementation_route.py:155 | 是 | ssp_control_implementation_service.update_objective | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:497 | Upsert |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt; | PUT | api/oscal/routes/ssp/ssp_control_implementation_route.py:176 | 是 | ssp_control_implementation_service.update_objective | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:497 | Upsert |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt;/document/&lt;file_id&gt; | DELETE | api/oscal/routes/ssp/ssp_control_implementation_route.py:198 | 是 | ssp_control_implementation_service.remove_objective_document | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:517 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/reference-documents | POST | api/oscal/routes/ssp/ssp_control_implementation_route.py:221 | 是 | ssp_control_implementation_service.add_reference_documents | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:534 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/reference-document/&lt;doc_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_control_implementation_route.py:242 | 是 | ssp_control_implementation_service.delete_reference_document | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:540 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt;/reference-documents | POST | api/oscal/routes/ssp/ssp_control_implementation_route.py:277 | 是 | ssp_control_implementation_service.add_ao_reference_documents | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:559 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementation/&lt;control_identifier&gt;/objective/&lt;statement_identifier&gt;/reference-document/&lt;doc_uid&gt; | DELETE | api/oscal/routes/ssp/ssp_control_implementation_route.py:299 | 是 | ssp_control_implementation_service.delete_reference_document | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_implementation_service.py:540 | |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementations/export | GET | api/oscal/routes/ssp/ssp_control_impl_import_route.py:34 | 是 | ssp_control_impl_import_service.export_excel | 已有: SspPermissionChecker.require_participant @ app/oscal/service/ssp_control_impl_import_service.py:112 | 敏感 GET(匯出 Excel) |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementations/import | POST | api/oscal/routes/ssp/ssp_control_impl_import_route.py:57 | 是 | ssp_control_impl_import_service.validate_import | 已有: SspPermissionChecker.require_participant @ app/oscal/service/ssp_control_impl_import_service.py:214 | 上傳 Excel 驗證（讀預覽，守門為 participant 而非 manager） |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementations/import/validate | POST | api/oscal/routes/ssp/ssp_control_impl_import_route.py:80 | 是 | ssp_control_impl_import_service.revalidate_items | 已有: SspPermissionChecker.require_participant @ app/oscal/service/ssp_control_impl_import_service.py:328 | JSON 重新驗證（守門為 participant） |
| /api/1.0/ssp/&lt;ssp_uid&gt;/control-implementations/import/confirm | POST | api/oscal/routes/ssp/ssp_control_impl_import_route.py:101 | 是 | ssp_control_impl_import_service.confirm_import | 已有: SspPermissionChecker.require_manager @ app/oscal/service/ssp_control_impl_import_service.py:371 | 批次寫入 |
| /api/1.0/ssp/&lt;ssp_uid&gt;/export | GET | api/oscal/routes/ssp/ssp_export_route.py:54 | 是 | ssp_export_app_service.export_from_ssp_version | 僅 JWT | 敏感 GET(匯出 docx/pdf/odt/json/yaml/xml)；service 內無授權守門 |
