整案四階段全部驗收通過,決策者手測完畢。BE 20 支 commit + FE 7 支,兩 repo 均已 push。
2026-09-18 決策者二度手測後追加三張卡(CM-1912/CM-1913/CM-1940),全數 Done,本檔已含其內容(§2 commit 清單、§4 行為差異、§9 追加卡明細、§10 已知事項)。
把「Guidant AI 這套系統在 Google 登記的那組應用程式帳號」從主機的 .env 搬到畫面上:平台管理員登入 → 側邊選單「系統設定 → Google Drive 應用程式設定」→ 填編號與密鑰 → 按「驗證憑證」當場知道填對沒有 → 複製畫面上算好的回呼網址貼進 Google 後台 → 存檔。密鑰加密落庫,改完不必重啟服務。
compliance-manager-be,branch feature/review,20 支)| Hash | 卡 | 內容 |
|---|---|---|
2e41513e |
CM-1895 | T-1.1 GOOGLE_DRIVE_APP_CONFIG 群組落地——密鑰遮罩、寫入合併、平台管理員守門 |
bb4aba21 |
CM-1896 | T-1.2 憑證解析器——整組切換、繞 RLS 讀 ROOT、網址推導 |
784917f7 |
CM-1897 | T-1.3 GoogleOAuthClient 改成每次呼叫才解析憑證 + DI 接線改造 |
f00cab28 |
CM-1910 | T-1.3b OAuth 用戶端測試 fixture 跟上新簽章(補卡) |
5f51315a |
CM-1911 | T-1.5 通知頻道對外網址改成向解析器要(補卡,設計遺漏補接) |
5e4396b6 |
CM-1899 | T-2.1 讀/存回應帶上推導後的兩個網址 |
f3840d1f |
CM-1900 | T-2.2 驗證憑證端點——三態判定 |
292700ab |
CM-1900 | 清掉測試檔未使用 import |
0c1b1c00 |
CM-1902 | T-3.2 選單登記 migration |
3c04dfc3 |
CM-1903 | T-3.3 平台憑證未設定時擋下租戶連接,回 GRC_412053 |
6e580e8f |
CM-1903 | 凍結碼表補登 GRC_412053(驗收補正) |
7bca3b32 |
CM-1904 | T-4.1 設定檔範本與部署文件退場 |
60be8007 |
CM-1905 | T-4.2 離線 Drive 分類腳本停用而非炸 TypeError |
f5cf8bfb |
— | 收尾文件(2026-09-17):spec 兩頁、SUMMARY、STATE、analysis、FR 登記、memory 同步 |
1fda5f46 |
CM-1912 | T-3.4 資料夾初始化子執行緒補回身分——修「授權成功但 0 個子資料夾」的靜默失敗 |
844e9d87 |
CM-1913 | T-3.5 通知登記失敗不再帶掉授權 + 兩個覆寫欄位後端擋格式 + 手冊補「在 Google 取憑證」六步 |
a0ae4f37 |
CM-1940 | T-3.6 專案總覽可一鍵開啟該輪 Drive 資料夾(新增唯讀端點) |
a8b906cf |
CM-1940 | spec:專案總覽 14b 入口改名「證據雲端資料夾」(決策者回饋,供應商中性) |
dbee2d9b |
CM-1940 | spec:專案雲端整合頁補「證據雲端資料夾」入口一段 |
8cc99148 |
CM-1902 | 出貨基線重產——選單 migration 進 02-schema.sql(與 FR-071 一支同批,共用 commit) |
| (本次) | — | 收尾補正:本檔、STATE、FR 站 README、FR 登記表,重 build 兩站 |
另有一支 design commit(設計定案,早於實作)。8cc99148 是與 FR-071 共用的基線重產 commit,兩案各一支 migration。
compliance-manager-fe,7 支)| Hash | 卡 | 內容 |
|---|---|---|
4bcb361 |
CM-1901 | T-3.1 設定頁——五欄位、複製鈕、驗證鈕、換帳號確認框、路由守衛、選單過濾、i18n |
7380674 |
CM-1903 | 平台憑證未設定時租戶頁停用連接鈕並留住提示 |
0f48c0d |
CM-1901 | 密鑰欄標籤列撐高導致與 ID 欄輸入框不對齊(手測回饋) |
4ccbc25 |
CM-1913 | 對外網址非 HTTPS 當場警告 + 兩個覆寫欄位格式檢查 + 整合卡顯示降級提示 |
93b1dc7 |
CM-1940 | 專案總覽動作列新增開啟 Drive 資料夾按鈕 |
9d8c140 |
CM-1940 | 按鈕改名「證據雲端資料夾」並換供應商中性圖示(決策者回饋) |
5f42099 |
CM-1940 | 專案規劃頁雲端整合 Tab 也加同一個入口 |
BE 新增:app/system_config/service/google_drive_app_config_resolver.py(憑證解析器,224 行)、app/cloud_integration/service/drive_app_credential_verify_service.py、api/cloud_integration/routes/drive_app_credential_verify_route.py、common/constant/drive_app_config.py、scripts/sql/2026-09-17-fr110-google-drive-app-config-menu.sql,以及五支測試檔。
BE 修改:app/system_config/service/guarded_system_config_service.py(加 Drive 群組分支)、infra/cloud_integration/google_drive/google_oauth_client.py(改每次呼叫解析 + probe_credentials)、app/cloud_integration/service/google_drive_integration_service.py(未設定時擋)、app/notification/service/webhook_channel_manager.py(對外網址改向解析器要)、di_containers/cloud_integration/、common/code/flow_control_error_code.py、common/middleware/app_mw.py、config/config.py、.env.sample。
FE 新增:src/views/google-drive-app-config/GoogleDriveAppConfigForm.vue(404 行)、src/config/driveAppConfig.js、兩份 i18n。FE 修改:router、AppMenu、CloudIntegrationService、axios interceptor、GoogleDriveIntegrationCard.vue、error-code i18n。
無新表、無新 repository、無新 domain service——設定進共用的 system_configs,只多一個 group。
/system/drive-app-config)。只有平台管理員看得到,一般租戶管理員完全看不到(有能力點也擋)。guidant.env 再 guidant start,現在改成登入畫面填。手冊另補一節「怎麼去 Google 拿到這組資訊」六步(建專案 → 啟用 Drive API → OAuth 同意畫面 → 建用戶端 → 貼回呼網址 → 複製編號與密鑰),含三個踩過的坑:同意畫面停在「測試中」要把帳號加進測試使用者、回呼網址兩邊必須逐字一樣、密鑰只顯示一次。/api/1.0/integrations/google-drive/callback 結尾、通知用對外網址覆寫不可帶路徑,前後端各擋一層(SYSTEM_CONFIG_400002 / 400003)。原本填錯存得進去,症狀要等別人按授權時撞 Google 的英文 redirect_uri_mismatch 才浮現。GET /integrations/google-drive/projects/<uid>/folders?round_uid=。| 文件 | 狀態 |
|---|---|
docs/spec-site/current/system-admin/google-drive-app-config.md |
本次新增(13 節完整頁面 spec) |
docs/spec-site/current/evidence/cloud-integrations.md |
本次更新(連接前提、UC-CI-01 前置條件、錯誤碼、變更紀錄各一處) |
docs/spec-site/mkdocs.yml |
本次更新(nav「系統設定」群組新增一列) |
docs/user-manual/onprem/10-optional-features.md |
T-4.1 已改(7bca3b32)——操作步驟由「改設定檔+重啟」改為「登入畫面填」 |
.env.sample |
T-4.1 已改——四項標註「改由畫面設定,此處僅開發機後備」,並補上一直漏掉的 DRIVE_WEBHOOK_PUBLIC_BASE_URL |
docs/features/FR-063-2608-nuitka-packaging/deployment-env.md |
T-4.1 已改(同一支 commit) |
docs/spec-site/current/project-management/project-overview.md |
CM-1940 已改(a0ae4f37 / a8b906cf)——§1.1 功能總覽表新增「證據雲端資料夾」入口一列 |
docs/spec-site/current/evidence/project-cloud-integration.md |
CM-1940 已改(dbee2d9b)——雲端整合 Tab 補「證據雲端資料夾」入口一段 |
docs/user-manual/onprem/10-optional-features.md(第二次) |
CM-1913 已改(844e9d87)——補一節「前置:在 Google 取得這組應用程式憑證」六步 |
docs/analysis/2026-09-17-drive-app-credential-db-first-env-fallback.md |
本次新增(設計取捨與兩個遺漏的教訓) |
test_error_code_mirror_parity 紅:主專案的 flow_control_error_code 碼表比 jedi_compliance_audit 多三碼(含本案新增的 GRC_400122 / GRC_412053)。決策者裁下次發套件時一併補,本案不動。memory:followup_error_code_mirror_parity_jedi_compliance_audit_lagging。classify_evidence_drive.py 現為停用狀態(60be8007),屬 FR-107 舊 Drive 分類線的一部分,待下一版隨該線一併移除。memory:followup_fr107_remove_legacy_drive_classification_line。| 項目 | 內容 |
|---|---|
| Migration | scripts/sql/2026-09-17-fr110-google-drive-app-config-menu.sql(一支,選單登記)。已套 DEV。STG / POC 走 init image 的 migrate 模式(GUIDANT_INIT_MODE=migrate),不手動 psql 逐支套 |
| 出貨基線 | 已重產(8cc99148)——選單 migration 已進 scripts/init/02-schema.sql 與 99-stamp.sql,新裝機器側邊選單看得到這一項 |
| 環境變數 | GOOGLE_DRIVE_OAUTH_CLIENT_ID / ..._SECRET / ..._REDIRECT_URI / DRIVE_WEBHOOK_PUBLIC_BASE_URL 四項可留作後備(資料庫沒設定時整組退回讀它們),開發機仍靠它們;DRIVE_TOKEN_ENCRYPTION_KEY 必留——密文與鑰匙必須分開放,鑰匙進資料庫等於沒加密。這把是空的時候,本頁存檔會直接拋錯(沒有存明文這條路) |
| 裝機不 seed | 刻意不把設定檔的值寫進資料庫:「資料庫裡有=有人設過」是個乾淨的判準,日後做「未開通」提示要靠它 |
| 升級既有機器 | 既有客戶的 .env 不動照樣運作(後備層讀得到);要改用畫面設定就在畫面上填一次,填完資料庫那組即接管 |
| # | 發現 | 處置 |
|---|---|---|
| 1 | T-1.3 改了 GoogleOAuthClient 簽章,但既有 12 支測試沒跟著改,在啟動階段就錯 |
補卡 CM-1910,f00cab28 |
| 2 | 設計漏了「Google 變更通知的對外網址」這個消費端——它另有一條取值路徑,不跟著改就仍讀舊環境變數 | 補卡 CM-1911,5f51315a |
| 3 | T-3.3 新增 GRC_412053 但沒同步凍結碼表,守衛測試紅 |
首腦補正 6e580e8f |
| 4 | FE 密鑰欄因多了狀態標記把標籤列撐高,與編號欄輸入框上緣不齊 | 手測回饋,0f48c0d |
| 5 | common/middleware/app_mw.py 的 request body log 原本沒有遮罩 |
T-2.2 順手接上(client_secret 落在 mark_password 的 secret 樣式內) |
決策者 2026-09-18 實際拿這頁去開通 Drive,連撞多關,追加三張卡全部 Done。
| 卡 | 問題 | 處置 |
|---|---|---|
| CM-1912(T-3.4) | 重新授權後,資料夾骨架只建出最上兩層,底下 0 APs, 0 CGs, 0 CONTROLs, 0 AOs, 0 TASKs,而背景工作標成成功。授權畫面顯示已連結,雲端硬碟裡卻沒有可放證據的資料夾,整條路徑沒有任何錯誤訊息 |
根因是既有潛伏 bug 被本案手測暴露:建資料夾用 ThreadPoolExecutor 扇出,子執行緒不繼承 ContextVar 裡的身分,session_scope() 讀不到身分走 fail-closed,PostgreSQL RLS 把 tenant_drive_integrations 整張擋成 0 列。改成每個 task 各 contextvars.copy_context().run(...) 帶一份 context 進去;整批全滅時新增 DriveFolderBatchFailedError 讓工作記 FAILED(不再假裝成功);部分失敗維持不中斷、下次冪等補齊。修後同一專案從 0 個變成 1 AP/6 CG/17 控制項/59 AO/59 任務。1fda5f46 |
| CM-1913(T-3.5) | 三個缺口都是「沒有訊息或只有 Google 的英文原文」:①租戶走完授權卻整個失敗,畫面丟英文「WebHook callback must be HTTPS」;②設定頁填 http 對外網址存檔顯示成功,要等別人按授權才爆;③回呼網址覆寫少填路徑段照樣存得進去,症狀是使用者撞 Google 的 redirect_uri_mismatch |
①通知登記包 try/except,失敗記 WARNING + 白話降級訊息寫進該租戶的 last_sync_error,授權本體與權杖保住(沿用既有的獨立 session 寫法,不另造);②設定頁對實際生效的通知網址判 https,不是就在該欄位下顯示黃色警告,不擋存檔;③兩個覆寫欄位前後端各擋一層。另補手冊一節。BE 844e9d87、FE 4ccbc25 |
| CM-1940(T-3.6) | Drive 都設定好了,但系統裡找不到路走到雲端硬碟,證據檔在哪只能自己翻 | 新增唯讀端點 GET /integrations/google-drive/projects/<uid>/folders?round_uid=(查 drive_folder_mapping,查不到或已失聯一律回 null,不拋錯);專案總覽與專案規劃頁雲端整合 Tab 各加一顆按鈕,有輪次資料夾就開它、否則退開專案資料夾、兩個都沒有就不顯示。按鈕原名「開啟 Google Drive」,決策者改名「證據雲端資料夾」並換供應商中性圖示——日後接別的雲端硬碟不必再改文案。BE a0ae4f37、FE 93b1dc7 / 9d8c140 / 5f42099 |
redirect_uri_mismatch,那是正常的、等一下再試,不是設定填錯。手冊那一節已寫進這個提醒。webhook_channel_id:那支 DTO 本來就沒有這個欄位,不是漏填。要看頻道編號直接查 tenant_drive_integrations。