我的稽核(My Audits)
功能群:稽核執行|階段轉換、AP→AR→POA&M 資料模型、AO 判定粒度先讀 功能群總覽
事實基準:2026-07-05 從 FE / BE code 掃出(FR-038 v2 round-based 架構;
infra/grc/repository/auditor_dashboard_query.py已改寫為直查compliance.project_audit_rounds,取代 2A dark stub 時期的OscalAssessmentPlanORM 查詢);API schema 逐條對照 marshmallow serializer 與 service 組裝碼
1. 功能描述
我的稽核頁是稽核員(auditor)的跨專案稽核收件匣:不進單一專案,而是彙整登入者在所有專案中被指派為 auditor(或以 manager 身分全域代行)的稽核輪次,讓稽核員一眼看到「有哪些稽核在等我」,並依判定進度、逾期狀態快速排優先序、直接跳進判定頁。是 我的任務(受評方證據蒐集收件匣)的稽核員鏡像版本。
主要使用者:稽核員(auditor)、可代行的專案經理(manager)。頁面本身不做角色寫入操作,純檢視 + 導航。
角色速覽(完整定義見 _overview §3;本頁主角是 auditor):
| 角色 | 一句話 |
|---|---|
| auditor | 稽核員 — 本頁清單資料的擁有者,點卡片進判定頁 |
| manager | 專案經理 — 若同時掛 manager 角色,該專案的輪次也會列入清單(見 §3 檢查點) |
| viewer | 一般參與者 — 不會出現在本頁清單來源(無 auditor/manager 角色) |
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 狀態分頁篩選 | 全部/稽核中/矯正中/已結案 四個分頁,點擊即重打 API | Header 篩選列 | UC-MA-01 |
| 2 | 關鍵字搜尋 | 依專案名稱模糊搜尋(ILIKE),輸入 300ms debounce
後查詢 |
Header 篩選列 | UC-MA-01 |
| 3 | 稽核卡片列表 | 每張卡片 = 一個稽核輪次:專案名 / AP 標題 / 輪次徽章 / 狀態標籤 | 卡片區 | §5 |
| 4 | 判定進度條 | 該輪次 finding 判定完成度(已判定/總數 + 百分比) | 卡片中段 | §10 |
| 5 | Verdict 四色圓點統計 | pass / fail / partial / na 四種判定計數(圓點 + 數字) | 卡片下段左側 | §10 |
| 6 | 缺失數徽章 | finding_count > 0 時顯示「N 個發現」紅色標籤 |
卡片下段左側 | §10 |
| 7 | 起訖日期 + 逾期提示 | 顯示 started_at ~ deadline;逾期或剩 ≤30
天顯示警示標籤 |
卡片下段右側 | §10 |
| 8 | 進入稽核 / 檢視結果按鈕 | 依 ap_status 切換文案與 icon,導向 round-scoped
稽核執行頁 |
卡片右下角 + 整卡可點 | UC-MA-02 |
| 9 | 空狀態提示 | 無資料時顯示「目前沒有待稽核的任務」+ 說明文字 | 卡片區 | §5 |
| 10 | 專案儀表板嵌入摘要 | DashboardView.vue 內「我的稽核」區塊複用同一
API,僅顯示 status=auditing 前 5 筆 + 「查看全部」連結 |
專案儀表板(另頁) | §11 |
UC(§2)展開 1(篩選載入)與 8(進入判定)這兩條核心操作路徑;本頁無寫入型操作,其餘功能均為純顯示邏輯,已在總覽表描述完整。
2. Use Case
角色速覽(完整定義見 _overview §3;本頁主角是 auditor):
| 角色 | 一句話 |
|---|---|
| auditor | 稽核員 — 本頁清單資料的擁有者,點卡片進判定頁 |
| manager | 專案經理 — 若同時掛 manager 角色,該專案的輪次也會列入清單(見 §3 檢查點) |
| viewer | 一般參與者 — 不會出現在本頁清單來源(無 auditor/manager 角色) |
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-MA-01 篩選 / 搜尋稽核清單
| 項目 | 內容 |
|---|---|
| 角色 | auditor(或掛 manager 角色的使用者) |
| 前置條件 | 已登入;至少一個專案的
project_participants.role IN ('auditor','manager') |
| 產出 / 後置條件 | 無寫入;回傳輪次清單 + 判定統計,供卡片渲染 |
UC-MA-02 進入稽核判定頁
| 項目 | 內容 |
|---|---|
| 角色 | auditor(manager 可代行) |
| 前置條件 | 卡片對應的輪次存在(round_uid 非空) |
| 產出 / 後置條件 | 導航到
project-audit-review-round(無資料異動);後續判定寫入行為見
稽核執行頁 / AR 判定 |
本頁不展開「Finalize」等寫入型 UC——那些屬於稽核執行頁(稽核執行頁 / AR 判定)的判定範疇,本頁只是入口。
3. 權限矩陣
專案層角色基調見 _overview §3。本頁的實際檢查點:
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 選單 / 頁面可見性 | hasCap('audit.read')(登入時載入的 capability
集合) |
⚠️ 無——POST /grc/audits/my/list 僅
@jwt_required(),未做 capability 二次驗證 |
api/grc/routes/auditor_dashboard_route.py:25 |
| 清單資料範圍 | 無額外判定(BE 回什麼就顯示什麼) | SQL
JOIN project_participants ON role IN ('auditor','manager')——資料範圍由這條
join 決定,非顯式角色檢查函式 |
infra/grc/repository/auditor_dashboard_query.py:43-46 |
| 進入判定頁 | 無額外判定,直接導航 | 由目的頁(稽核執行頁)的
_check_auditor + assert_round_phase 把關 |
見 audit-review.md §3 |
⚠️ 權限面比照說明:本頁屬「跨專案彙整檢視」,沒有寫入操作,因此 BE 沒有比照寫入 API 加角色檢查——這點與寫入類頁面(如稽核執行頁)不同,不是遺漏,是頁面性質(純讀)決定的。唯一要留意的是
audit.readcapability 只在 FE 選單 / 路由層擋,若使用者已知 API path,任何登入者都能打這隻 API 拿到「自己是 auditor/manager 的輪次清單」——因為 join 條件本身就限制在使用者自己的user_id,即使繞過 capability gate 也看不到別人的資料,故非資安缺口。
4. 狀態機與前置條件
輪次 7 態狀態機見 專案管理群 _overview §2。本頁相關 gate(BE 端白名單而非 FE 判定):
| 條件 | 效果 | 出處 |
|---|---|---|
輪次狀態白名單 {auditing, remediation, closed} |
只有這三態的輪次會出現在清單;planning /
audit_planning 一律排除(尚未有
AP/AR,點進去會找不到資料) |
auditor_dashboard_query.py:15(_VISIBLE_ROUND_STATUSES) |
FE 分頁值 all |
不帶 status 篩選給 BE,BE
仍套用上述白名單(白名單恆套用,不受 caller 傳值影響) |
同檔 :50 |
pe.deleted_at IS NULL |
排除已軟刪除專案的輪次(避免列出「殭屍」稽核卡片) | 同檔 :47(mirror list_projects
的過濾邏輯) |
| 關鍵字搜尋 | ILIKE 比對
projects.name;空字串等同不篩選 |
同檔 :52 |
5. UI 設計
版面骨架與區塊職責(單欄卡片列表,無左樹、無 Tab;本頁純讀無寫入;彩色區塊可點跳對應小節錨點,API 僅標代表性):
實機截圖(STG,亮色模式,2026-07-05,帳號 blspan/稽核人員):


逾期 / 剩餘天數警示標籤特寫從缺:該標籤依輪次起訖日期(
start_at/end_at)計算,2026-07-05 盤點 STG 全庫無任何存活輪次填有起訖日期,暫無真實資料可拍。
狀態呈現:卡片載入時全頁 ProgressSpinner(非局部
loading);無 per-卡片 spinner(本頁無寫入動作,不需要);無
socket,篩選 /
搜尋動作皆重打整份清單(無本地增量更新)。statusFilter
預設值為 auditing(非
all),對齊「稽核員登入後優先看到進行中稽核」的設計意圖。
6. API 規格
Envelope:成功 {"status": true, "data": …}、失敗
{"status": false, "error_code": "…", "msg": "…"}(common/util/response_util.py:return_response)。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 載入 | POST /grc/audits/my/list |
稽核輪次清單 + 判定統計(本頁唯一 API,篩選/搜尋皆重打此支) | §6.2 |
本頁只有單一 endpoint;無分頁(回傳全量陣列,未見
limit/offset)、無獨立 menu API、無詳情 API(點卡片直接導航到既有的稽核執行頁,不另外打 detail)。
6.2 稽核清單類
[POST] /grc/audits/my/list
Request:
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| filters.status | string|null | 否 | auditing / remediation /
closed;省略或 null = 套用 BE 預設白名單(見
§4) |
| filters.keyword | string|null | 否 | 專案名稱關鍵字(ILIKE 模糊比對) |
出處:AuditorDashboardRequestSchema /
AuditorDashboardFiltersSchema(api/grc/serializers/auditor_dashboard.py:5-18)
Response data.items[](每項一個稽核輪次):
| 欄位 | 型別 | 說明 |
|---|---|---|
| project_uid / project_name | string | 專案識別 / 名稱 |
| round_uid | string | 輪次 uid(FR-038 v2 導航用,進入稽核走此欄位) |
| ap_uid | string | 相容欄位,值等於 round_uid(v2
已無獨立 AP 實體,沿用舊 FE :key 與 fallback
導航參數) |
| ap_title | string | v2 無獨立 AP 標題,直接沿用
project_name |
| run_no | int | 輪次序號(對應 project_audit_rounds.round_no) |
| ap_status | string | 輪次狀態(auditing/remediation/closed
三者之一,白名單保證) |
| total_controls | int | 該輪 AR 判定總筆數(assessment_findings 依
ar_result_id 分組計數) |
| verdict_completed | int | 已判定(satisfied +
not-satisfied)筆數 |
| verdict_pending | int | 未判定筆數 |
| verdict_summary | object | {pass, fail, partial, na}(皆 int)——目前只有
pass/fail
會被賦值,partial/na 恆為 0(見 §12 坑
1) |
| finding_count | int | 缺失數,直接等於 verdict_summary.fail |
| evidence_ready_count / evidence_total_count | int | 恆為 0——v2 證據統計尚未接上(見 §12 坑 2) |
| started_at / deadline | string|null | ISO 8601(對應 start_at / end_at),無 tz
資訊 |
出處:AuditorDashboardItemSchema(api/grc/serializers/auditor_dashboard.py:28-44)、組裝邏輯
infra/grc/repository/auditor_dashboard_query.py::get_auditor_ap_list:25-103
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/project/MyAuditsView.vue |
主檢視(233 行;篩選列、卡片列表、進度條、verdict 圓點、逾期提示、導航) |
src/config/router/index.js:882-886 |
route project-my-audits(path
/project/audit-manage;非
/project/my-audits,命名與 path 不一致,見 §12 坑 3) |
src/config/api/api.js:201 |
GRC_MY_AUDITS_LIST 常數 →
/grc/audits/my/list |
src/service/BaseService.js |
axios 封裝(post(),本頁唯一呼叫方式) |
src/views/project/DashboardView.vue:340-393 |
專案儀表板「我的稽核」區塊,複用同一
API(status=auditing 固定、前 5 筆) |
src/utils/userUtil.js:43 |
hasCap() — 選單可見性判斷依據 audit.read
capability |
src/config/locales/i18n/{zh-tw,en}/my-audits.json |
頁面 i18n(namespace lang.my_audits.*,含
evidence_ready 等目前未使用的殘留 key,見 §12 坑 4) |
src/config/locales/i18n/{zh-tw,en}/menu.json:94-95,217-218 |
選單顯示名稱與說明文字(audit-manage /
project-my-audits 兩個 key 皆存在) |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| 稽核清單 | api/grc/routes/auditor_dashboard_route.py::AuditorDashboardRoute(POST
/audits/my/list) |
app/grc/service/auditor_dashboard_service.py::AuditorDashboardService.get_my_audit_list(@transaction,僅轉呼叫,無額外業務邏輯) |
infra/grc/repository/auditor_dashboard_query.py::AuditorDashboardQuery.get_auditor_ap_list(raw
SQL:project_audit_rounds join
projects/project_extensions/project_participants,逐輪再查
assessment_findings 統計) |
DDD 提醒:本鏈路 app service 未經過 domain service /
repository interface 抽象層,是直接呼叫 infra 層的 query
class(AuditorDashboardQuery)——這是專案內既有的簡化模式(純讀、跨表聚合統計、無寫入),並非違規(DB
存取仍完全限縮在 infra 層,符合「app 不碰
ORM/session」的鐵則)。新增類似「跨專案彙整統計」的唯讀 API
可比照此輕量模式,但若之後本頁長出寫入操作,仍須補 domain
service 層與角色檢查函式,不要在這個 query class 上直接加寫入邏輯。
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
| 表 | 讀/寫 | 說明 | 欄位詳述 |
|---|---|---|---|
| compliance.project_audit_rounds | 讀 | 稽核輪次主檔(狀態白名單過濾來源) | §9.3 |
| compliance.projects | 讀 | 專案主檔(名稱、搜尋關鍵字比對對象) | 見 project-planning §9.3 |
| compliance.project_extensions | 讀 | 專案擴展(僅用 deleted_at 過濾軟刪除專案) |
見 project-planning §9.3 |
| compliance.project_participants | 讀 | 使用者於各專案的角色(role IN ('auditor','manager')
決定資料範圍) |
見 project-planning §9.3 |
| oscal.assessment_findings | 讀 | 逐輪判定統計來源(target_status_state 分組計數) |
§9.3 |
本頁完全無寫入——是本群唯一純讀頁面(對照稽核執行頁 / 稽核計畫填寫頁皆有寫入表)。
9.2 ER 圖(本頁讀取範圍)
9.3 核心表欄位(取自 DEV DB dump,含 DB comment)
compliance.project_audit_rounds — 稽核輪次主檔(本頁只讀)
完整欄位見 project-planning §9.3。本頁用到的欄位:
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | varchar(36) | 對外識別碼 → response round_uid |
| status | varchar(20) | 白名單
auditing/remediation/closed →
response ap_status |
| round_no | int | → response run_no |
| ar_result_id | bigint|null | 本輪對應 AR result;null 時 total_controls
等統計欄位皆為 0(尚未開始填判定) |
| start_at / end_at | timestamptz | → response started_at / deadline |
oscal.assessment_findings — 逐 AO 判定(本頁只讀,聚合用)
完整欄位見 audit-review.md
§9.3。本頁只讀 ar_result_id(分組鍵)與
target_status_state(計數依據)兩欄,依
satisfied / not-satisfied / 其餘(視為
pending)三分聚合成 verdict_summary。
10. 頁面邏輯與資料對應
載入時序:
關鍵欄位對應(API ↔︎ 畫面):
| 畫面元素 | FE state / computed | API 欄位 |
|---|---|---|
| 分頁篩選 | statusFilter(預設 'auditing') |
request filters.status('all'
時不送) |
| 搜尋框 | keyword(300ms debounce) |
request filters.keyword |
| 卡片標題 / 副標 | 直接綁定 | project_name / ap_title |
| 狀態標籤 | AP_STATUS_SEVERITY[item.ap_status] 映射色階 |
ap_status |
| 輪次徽章 | t('round_label', {n: item.run_no}) |
run_no |
| 判定進度條 | verdictPercent(item)(verdict_completed / total_controls * 100
四捨五入,total_controls=0 時給 0) |
verdict_completed / total_controls |
| Verdict 四色圓點 | VERDICT_DOTS 固定 4 種 key 對應顏色 |
verdict_summary.{pass,fail,partial,na} |
| 缺失數標籤 | item.finding_count > 0 才顯示 |
finding_count |
| 起訖日期 | formatDate()(依 locale 轉字串) |
started_at / deadline |
| 逾期 / 剩餘天數標籤 | deadlineInfo(item):deadline 早於今天 →
overdue;diff<=30 → 顯示剩餘天數;否則不顯示 |
deadline |
| 進入按鈕文案 | ap_status==='closed' ? 檢視結果 : 進入稽核 |
ap_status |
儲存流程:無——本頁純讀取展示頁,沒有任何欄位可編輯或儲存。
錯誤對應:本頁 fetch 失敗僅
console.error(fetchAudits failed),不顯示
toast 給使用者、清單維持空陣列——與其他頁面統一走
axios-error event bus + 全域 toast 的慣例不同(見 §12 坑
5)。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 通知 | 無——本頁不觸發、也不消費任何通知 |
| Socket | 無 socket / 輪詢;每次篩選 / 搜尋皆重新 fetch 全量 |
| jedi-* 套件 | 無直接依賴(raw SQL 查詢,未經 jedi-oscal-v2 repository 抽象層) |
| 系統參數 | 無 feature flag;顯示邏輯純由 ap_status 白名單決定 |
| 跨頁複用 | DashboardView.vue「我的稽核」區塊呼叫同一
GRC_MY_AUDITS_LIST API(固定
status: 'auditing'、只取前 5
筆),與本頁共用資料來源但各自獨立 fetch,非共用 store |
12. 邊界情況與已知坑
verdict_summary.partial/.na恆為 0:BE 聚合邏輯(auditor_dashboard_query.py:66-84)只依target_status_state IN (satisfied, not-satisfied)分成pass/fail,其餘(含pending與任何非兩態值)全部只累加到pending計數(verdict_pending),不會寫入summary['partial']或summary['na']。FEVERDICT_DOTS仍畫出 partial / na 兩個圓點,但目前恆顯示 0——UI 沒有 bug,是 BE 資料模型尚未支援 partial/na 兩種判定值(_overview §5 坑 4提到 API 判定值只有met/not_met/pending三種,並無 partial/na)evidence_ready_count/evidence_total_count恆為 0:程式碼註解明寫「v2 證據統計另接(follow-up)」(auditor_dashboard_query.py:98-99),FE 目前也沒有渲染這兩個欄位(evidencePercent已於 FR-038 2026-06-18 移除,見MyAuditsView.vue:80註解),純粹是 API 回傳但 UI 不用的殘留欄位- route path 與 route name
不一致:
name: 'project-my-audits'但path: '/project/audit-manage'(compliance-manager-fe/src/config/router/index.js:882-886);ui_routes選單資料庫記錄的name也是audit-manage(見 §3 /docs/changelog/2026-04-27-tweak-add-audit-cloud-integration-to-permissions.md歷史記錄)。之後找這個頁面不要假設 URL 含my-audits字樣,改用 route name 或選單顯示文字「我的稽核」定位 - i18n 檔內有未使用的殘留
key:
my-audits.json的evidence_ready/progress_label/deadline_label三個 key 目前MyAuditsView.vue沒有任何t(...)呼叫引用(進度條文案改用verdict_progress,日期不帶 label 直接顯示區間字串)——動這份 i18n 檔前先確認哪些 key 真的活著,避免誤刪還在用的或誤留死 key - fetch 失敗不顯示 toast:
fetchAudits的catch只console.error,不像其他頁面透過 axios interceptor 的axios-errorevent bus 觸發全域 toast;使用者網路異常時只會看到清單維持空白(或維持上次結果),沒有任何提示——這是本頁的既有行為,不是本次盤點發現的新 bug,但排查「使用者說清單載入卡住」類回報時要記得這點 ap_uid/ap_title是相容欄位,非真實 AP 概念:FR-038 v2 已無獨立 AP 實體(v2 是 round-based),ap_uid實際值等於round_uid、ap_title直接沿用project_name——純為了保留舊 FE:key與相容導航參數命名,不代表系統仍有「AP 標題」這個獨立欄位可編輯- 無分頁:
items[]一次回傳全量,未見limit/offset或游標機制;若稽核員同時掛很多輪次的 auditor/manager 角色,理論上會一次載入全部(目前未見資料量問題回報,但擴充篩選功能時要留意) - capability 只在 FE 擋,BE 無 route-level 檢查:見
§3 ⚠️——
audit.read未反映在 BE route 的 decorator 上,僅 JWT 驗證。因 SQL join 條件已把資料範圍鎖在呼叫者自己的user_id,此設計目前不構成資安風險,但若日後有「查看他人稽核清單」的管理者功能需求,必須另開支援 admin 範圍查詢的 API,不能直接放寬這支的權限
13. 開發與驗證
- 跑起來:BE
python main_socketio.py(port 8000,log 在log/app.log);FE 在compliance-manager-fe/起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload) - 測試帳號:dev 環境稽核員角色帳號(密碼見
.env/ 部署文件) - 導航路徑:登入 →
側邊選單「我的稽核」(
audit-manage);或專案儀表板「我的稽核」區塊「查看全部」連結 - 前置資料:使用者需在至少一個專案的
project_participants掛auditor或manager角色,且該專案已有輪次推進到auditing/remediation/closed之一(planning/audit_planning階段的輪次不會出現) - E2E:
compliance-manager-test/repo(Cucumber + Playwright);本頁相關 feature 檔以我的稽核/my-audits/audit-manage搜尋 - 相關文件:FR-038(v2
遷移,
docs/features/FR-038-2606-oscal-redesign/);歷史 bug 修復脈絡(已改寫,僅供背景參考)docs/changelog/2026-04-27-fix-my-audits-closed-status-empty.md、權限納管docs/changelog/2026-04-27-tweak-add-audit-cloud-integration-to-permissions.md;稽核判定寫入行為見 稽核執行頁 / AR 判定;受評方鏡像頁見 我的任務;DB / API 全量見 GAI-SD-02/03