每一頁都有一道進入門檻,定義在後端 ui_routes+route_capabilities,前端只讀 /users/me/capabilities 的 routes 名單、不寫死哪頁要哪顆。這張表是 FE 路由檔(src/config/router/index.js)每條具名路由的登記結果,登記 SQL 是 scripts/sql/2026-10-07-fr132-route-entry-capabilities.sql,守衛測試 test/test_fr132_route_entry_registered.py 逐條核對。
is_menu=false:不上側欄,但照樣進可進頁名單與角色「可見頁面」預覽(標「非選單頁」)。pid 掛母頁、不掛分組:母頁取 FE 路由 breadcrumb 的 parent,一律是側欄頁或已登記的內頁(可多層)。角色樹靠它長「分組 › 側欄頁 › 內頁」;掛分組時內頁會跟側欄頁並排,看起來像重複權限。側欄 /user/web-menu 先濾 is_menu、可見判定只看 route_capabilities,都不受 pid 影響。沒有單一母頁的 home、survey-v2-fill 刻意留在分組下。母頁登記在 scripts/sql/2026-10-08-fr132-inner-page-parent.sql,守衛測試核「每支內頁都有母頁、母頁是頁不是分組」。ui_routes.name 一字不差。FE name 與 DB name 不同的五支,FE 改名對齊 DB(DB 名已被三個套件的 home_route 引用):project-my-tasks→my-tasks、project-my-audits→audit-manage、project-summary-report→report-manage、survey-v2-manage→survey-manage、smtp-config-manage→smtp-config(原本叫 smtp-config 的表單頁改名 smtp-config-form)。麵包屑顯示文字的 i18n key 不動。
| route name | 進入權限(ALL) |
|---|---|
| project-dashboard、my-tasks、license-status | 無(刻意全登入者可見) |
| project-list | grc.project.read |
| audit-manage | grc.audit.read |
| report-manage | grc.summary-report.read |
| module-frame | oscal.resource-library.read |
| compliance-framework-manage | oscal.framework.read |
| tool-plugin-manage | detection.plugin.read |
| detection-profile-manage | detection.profile.read |
| flow-template-manage | flow.template.read |
| bulletin-list | workspace.bulletin.read |
| bulletin-manage | workspace.bulletin.create |
| survey-manage | survey.survey.read |
| system-feedback-manage | workspace.feedback.read |
| system-feedback-view | workspace.feedback-review.read |
| tenant-manage | iam.tenant.read |
| department-manage | iam.org-unit.read |
| user-manage | iam.user.read |
| access-roles | iam.role.read |
| access-assignments | iam.user.read |
| system-menu-manage | system.system-menu.read |
| information-system-manage | asset.information-system.read |
| device-manage | asset.device.read |
| scan-zone | detection.scan-zone.read |
| remote-agent-manage | detection.remote-agent.read |
| user-log | platform.api-log.read |
| ai-call-log | ai.call-log.read |
| support、storage-config、drive-app-config | system.storage-config.read |
| smtp-config | system.smtp-config.read |
| security-policy | system.security-policy.read |
| ldap-config | system.ldap-config.read |
| log-forwarding | system.log-forwarding.read |
| ai-service-config | ai.ai-provider-config.read |
| ai-quota | ai.quota.read |
| issue-integrate-config | system.issue-integrate-config.read |
| notify-config | system.notify-config.read |
| cloud-integrations | evidence.cloud-integration.read |
| ai-dashboard | ai.dashboard.read |
| license-manage | platform.license.read |
不需要權限就該進得去的頁。前端 src/config/router/routeAccess.js 的 ROUTE_ACCESS_EXEMPT 與 BE 守衛測試的 EXEMPT 是同一份,改一邊要改兩邊。
| route name | 理由 |
|---|---|
| login、otp-verify、reset-password、forget-password | 尚未完成登入 |
| setup-wizard | 落地版首次開通,系統還沒有帳號 |
| system-locked | 完整性鎖定頁,可能拿不到 token |
| notfound、forbidden | 404/無權限頁本身 |
| license-activation | 無照租戶登入後被導來開通,此時沒有任何模組權限 |
| user-profile | 本人資料,任何登入者都要能改自己的密碼與暱稱 |
| about | 版本資訊 |
| sitemap | 只列 web-menu 已過濾的頁,本身不洩漏資料 |
| analysis | 前端假資料展示頁,不打 API ⚠ 疑似孤兒頁 |
| role-manage、role-form | 舊網址 redirect,由目的頁把關 |
grc.project.read(13 條):稽核員只要有專案讀取就進得去,專案角色交給頁內判斷。另一種做法是規劃頁要 grc.job.read、輪次三頁要 grc.audit.read 外加 project.read,但「每頁恰一顆 ALL」放不下兩顆。survey-v2-fill 用 grc.job.read:填答者是任務執行者,沒有問卷管理權限。project-settings 用 grc.project.update:只有讀取權限的參與者連看設定都進不去。flow-template-edit 用 update:內建範本的唯讀檢視也走這頁,只有 flow.template.read 的人點「檢視」會被擋;若要放行,改成 ALL read+頁內唯讀。workflow-setup 用 oscal.resource-library.read:專案規劃頁也會開它(看任務流程),持 grc.project.read 但沒有資源庫讀取的人會被擋。home、analysis、sitemap 是否為孤兒頁:home 渲染資源庫列表、無任何程式導向;analysis 是假資料展示頁。建議另開清理卡。