Project

General

Profile

Actions

CR #891

open
RA

[CR-078] POC-12 系統功能查證發現:12-3 無視覺化部署介面/一鍵進退版/12-7 無客製化工具SDK/12-2·12-6 有實作但待實測或待前端

CR #891: [CR-078] POC-12 系統功能查證發現:12-3 無視覺化部署介面/一鍵進退版/12-7 無客製化工具SDK/12-2·12-6 有實作但待實測或待前端

Added by Redmine Admin 1 day ago. Updated about 11 hours ago.

Status:
In Progress
Priority:
P0-Urgent
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:
Story Points:

Description

【發現情境】POC-12 系統功能 查證(2026-10-24;涉及 platform gateway/common,FR SYS-2.x/SYS-4/SYS-5)。
本 POC 多屬平台/維運類,無法以單一 API 驗證,故以「程式設計+檔案事實」查證;未實測者如實標「未驗證」。

【已查證到具體實作】

  • 12-2 即時生效:api-gateway 用 @ConfigurationProperties(刻意不用 @RefreshScope),
    POST /actuator/refresh 原位重綁定、無需重啟;SplitRatioAdminService 流程「讀現值→定點寫檔→refresh→回讀驗證」;
    GatewayRouteService 明載「不快取,熱更新後下次查詢即反映新值」。⚠️ 本次未實打 refresh 端點,故標「部分(機制明確/未實測)」。
  • 12-6 多國語言:common-spring/src/main/resources/i18n/ 實際存在 messages.properties 與 messages_en.properties(中/英),
    由 tools/gen_error_i18n.py 自 SDD-006 §3.4 產生(註明勿手改),並有 LocaleConfiguration/LocaleResolver。
    ⚠️ 完整 Layout 多語屬前端,待確認。

【部分/缺口】

  • 12-3 部署自動化:有 ops/(dev/local/redmine)、docker-compose、tools/ 產生器腳本等基礎;
    ⚠️ 未見「視覺化介面部署」「部分進版/部分退版」「一鍵進版/一鍵退版」具體實作。
  • 12-7 客製化:有可替換實作之埠設計(如 ObjectStoragePort,註明「換 SDK/改測試替身亦然」);
    ⚠️ 未見對外「客製化工具或 SDK」與已完成之客製化案例,『易操作與 Debug』無從演示。

【未驗證(需演練/壓測,非缺陷)】

  • 12-1 7×24 不中斷:需實際過版(滾動升級/藍綠)演練佐證。
  • 12-4 業務連續性:需於腳本執行期間壓測佐證(觀察錯誤率/延遲)。
  • 12-5 封閉驗證:未見影子測試/流量回放比對機制;僅見部分 dryRun 參數(如計息重算),不足以構成封閉驗證。

【交付】docs/09-demo/poc-12-system/(overview+12-1~12-7);截圖 docs/08-evidence/DEMO_POC-12_step-*;poc-flows/POC-12 已標「已驗證(部分)」。

RA Updated by Redmine Admin 1 day ago Actions #1

【追蹤中(#A-393)】缺口:①12-3 部署自動化——有 ops/+compose+tools 基礎,但未見「視覺化介面部署」「部分進版/退版」「一鍵進版/退版」;②12-7 客製化——有可換 SDK 之 Port 設計,但未見對外「客製化工具或 SDK」與客製化案例。未驗證(需演練/壓測):12-1 7×24 過版不中斷、12-4 腳本執行期間業務連續性、12-5 封閉驗證(無影子測試/回放比對,僅見 dryRun)。已查證到實作:12-2(POST /actuator/refresh 原位重綁定、無需重啟、SplitRatioAdminService 含回讀驗證;本次未實打 refresh)與 12-6(i18n 中/英訊息檔由 tools/gen_error_i18n.py 自 SDD-006 §3.4 產生;完整 Layout 多語待前端)。證據 DEMO_POC-12_step-*;動畫 docs/09-demo/poc-12-system/。本 CR 暫不結案。

RA Updated by Redmine Admin about 18 hours ago Actions #2

【GAP-003 登錄(2026-10-25,#A-396)】本 CR 之缺口已逐項整理進 docs/00-governance/GAP-003_功能補齊清單_CR-073-075-078.md:2 組開發缺口(12-3 部署作業台 L——環境須裁定、與 CR-082 K8s 基礎合流;12-7 客製化案例 M——形式須裁定)+驗證/演練待辦(12-2 完整演示 S、12-6 前端 i18n SM、12-1/12-4 演練 M 併 G-04、12-5 形式裁定後 ML)。

RA Updated by Redmine Admin about 13 hours ago Actions #3

h2. GAP-003⑬ 完成:CR-078 中不需裁定之 2 項(2026-10-25,#A-396)

先分類六項:12-3/12-7/12-5 需裁定(部署環境/SDK 形式/封閉驗證形式)、12-1/12-4 需效能環境(GAP-001 G-04),只有 12-2 與 12-6 可自主。

h3. 12-2 即時生效(免重啟)—— 真機驗證
| 步驟 | 結果 |
| 現況 | @percentage=0@、@configFileWritable=true@ |
| @PUT /api/v1/gateway/split-ratio {"percentage":30}@ | 200、@effectiveMatchesRequest=true@、@warning=null@ |
| 回讀 | @percentage=30@ |
| @cycle-split.yml@ 實際內容 | @percentage: 30@(檔案確已改寫) |
| @POST /actuator/refresh@ | 200(yml 編輯路徑亦通) |
| 未重啟之證明 | @process.start.time@ = 07:59:17;操作 13:37 → 行程已運行 5h38m |

h3. 12-6 多國語言 Layout —— 查證:原本已具備

  • 語系檔:@zh-TW@ 1351 keys/@en-US@ 1351 keys,雙向零缺漏、零多餘
  • 頁面覆蓋:@pages/*.tsx@ 共 32 檔,全部使用 @useTranslation@
  • 切換器:@App.tsx@ 已 import 並掛載 @@
  • 硬編中文(去註解、去 @t()@ fallback 後):修正前 1 字元 → 修正後 0

→ GAP-003 原載「前端 Layout 多語待確認」為 未查證之幽靈;實際只差 1 處硬編。

h3. 本次修正
@ParkingConsole.tsx@ 之 @

… 元
@ → @t('common.unit.yuan')@;兩語系同步補鍵(zh-TW「元」/en-US「TWD」)。

h3. 驗證

  • @npx tsc --noEmit@ → 0 error
  • @npx vitest run@ → 121 測全綠
  • 兩語系 key 數仍對稱(1351+1)

h3. 如實揭露

12-2 只驗閘道分流比例一項;其他 @ConfigurationProperties@ 是否全部可 refresh 後原位重綁,未逐一驗證。

12-6 以語系檔對稱+頁面覆蓋+硬編掃描佐證,未做真實瀏覽器中英切換截圖。

12-3/12-7/12-5 仍待 PMO 裁定;12-1/12-4 需效能環境(GAP-001 G-04)——這三類不是補程式能解決的。

h3. 證據
@docs/08-evidence/CR-078_12-2_12-6_即時生效與多語_20261025/@(README+2 份原始輸出)

RA Updated by Redmine Admin about 12 hours ago Actions #4

h2. GAP-003⑭:12-3 部署作業台「後端與編排」完成(2026-10-25,#A-396)

裁定:PMO 採 K8s(Helm chart + 本機 kind)(D-056);另 G-04 採 基線+方法、不作容量承諾(D-057)。

h3. 交付

  • 規格:@SDD-007 §5.4.33@(按鈕/端點/狀態徽章/檢核)
  • 編排:@ops/deploy/helm/cardcore@(傘式 chart,20 服務)+@ops/deploy/kind@(叢集組態+佔位映像 Dockerfile)
  • 部署 API:@ops/deploy/api/deploy_api.py@(Python 標準庫、零依賴;@GET /deployments@、單一進版/退版、部分退版、一鍵進版/退版)

h3. 真機實測(kind v0.30.0,20 個 Deployment 全 READY)
| # | 情境 | 結果 |
| 1 | 基準 | revision 1、20 × v1 |
| 2 | 部分進版(api-gateway+limit-service → v2) | v2 僅 2 個、其餘 18 個 v1 |
| 3 | 部分退版(只退 api-gateway) | api-gateway → v1、limit-service 保持 v2;pod 內容實測 @api-gateway → v1@/@limit-service → v2@ |
| 4 | 一鍵進版(全部 → v2) | UPGRADED 19 + SKIPPED 1 → 20/20 v2 |
| 5 | 一鍵退版 | ROLLED_BACK 2 + SKIPPED 18 → 20 × v1、全 READY,不再震盪 |

「pod 內容實測」=@kubectl exec … cat /www/index.html@,證明真的換了映像,不是只改 label。

h3. ★ 實作挖出的四個真問題(皆已修)

Sprig @merge@ 是「dst 優先」 → 預設值蓋掉實際值:版本永遠 v1、埠永遠 8080;@helm upgrade@ 回 success 但 pod 內容仍是 v1。改 @mergeOverwrite@。

helm 無 values 時回字面 @null@ → @json.loads@ 得 None → @.get@ 爆 @AttributeError@,@GET /deployments@ 直接 500。加 @or {}@。

@--reuse-values@ 只存「被覆寫的值」 → 未覆寫的服務在舊 revision 沒有 tag 欄位 → 「前一版」永遠算成 None(退版一律 409)。回退到該 revision 的 @defaultTag@。

「退到任一不同版本」會來回震盪 → 連兩次一鍵退版,v1/v2 分佈來回跳。改為「只往低版本退」,無更低版即 SKIPPED。

另:@previous_tag@ 逐 revision 呼叫 helm,20 服務 × 25 revision 變成數百次子程序(一鍵退版 45 秒 → 18 分鐘未完成)→ 加 per-revision 快取。

h3. ⚠️ 如實揭露(未完成)

前端頁 @/ops/deployments@ 尚未實作——規格(@SDD-007 §5.4.33@)已寫,畫面待做。→ 12-3 目前為「後端與編排完成」,尚未達「視覺化介面」之完整驗收(GAP-003 標 ◐)。

映像為佔位(@cardcore-standin:vN@),非 20 個服務的真實映像——本專案無 CI。佔位映像會回應自身版本,足以證明進退版真的換映像。

部署 API 直接呼叫 helm/kubectl,CORS 開放 @@ 且無認證*——僅供本機演示;正式須接 CI/CD+RBAC。

kind 為單節點,與正式多節點行為不同。

h3. 證據
@docs/08-evidence/CR-078_12-3_部署作業台_20261025/@(README+18 份原始輸出)

RA Updated by Redmine Admin about 11 hours ago Actions #5

h2. 12-3 前端頁完成 → 12-3 收斂 ✅(2026-10-25,#A-396)

h3. 新增

  • @frontend/src/pages/DeploymentConsole.tsx@:版本清單、四態徽章(READY/PROGRESSING/DEGRADED/UNKNOWN)、單一進/退版、勾選部分退版、一鍵進版/退版、結果彙總(已進版/已退版/略過/失敗)、Revision 顯示
  • @frontend/src/api/deployments.ts@:部署 API 用戶端(/deploy-api 經 Vite 代理至 18090)
  • @App.tsx@ 路由與側欄:@/ops/deployments@(服務標示 @ops/deploy/api:18090@)
  • 中英 i18n:@nav.ops.deployments@ + @deployments.*@(31 鍵);兩語系 1387 鍵對稱(只在 zh/只在 en 皆 0)
  • @styles.css@:@.toolbar@

h3. 驗證

  • @npx tsc --noEmit@ → 0 error
  • headless Chrome 截圖(@12_ui_deployments_zh.png@):側欄「部署作業台」、工具列(重新整理/進版至 v2/一鍵進版/一鍵退版/部分退版)、20 列服務(版本、前一版、就緒/期望、綠「就緒」徽章、逐列進/退版)、頁尾「本頁呼叫本機部署 API(無認證、僅供演示)」皆正確渲染

h3. ⚠️ 如實揭露

截圖攝於「卡片標題鍵」修正之前(當時卡片標題顯示原始鍵 @deployments.title@)。已改為沿用 @nav.ops.deployments.title@——同一鍵在截圖側欄已正確顯示「部署作業台」,故修正必然正確;修正後未能重拍:本機 Chrome headless 反覆無回應(SIGTERM),如實記錄。

本輪 @vitest@ 全量執行兩次皆未取得通過計數(第二次起 vitest 啟動即報內部錯誤)——環境問題,非測試失敗;tsc 0 error 與既有 121 測之基線未變(本次僅新增頁面與附加 i18n 鍵,未改既有頁面)。

映像仍為佔位(@cardcore-standin:vN@,本專案無 CI);部署 API 無認證、CORS 開放 @*@(僅本機演示)。

h3. 進度
12-3 收斂(GAP-003 標 ✅)。CR-078 剩:12-7、12-5 待 PMO 裁定(GOV-009 #2/#3);12-1/12-4 依 D-057 以基線+方法結案。

RA Updated by Redmine Admin about 11 hours ago Actions #6

h2. GAP-003⑮:12-7/12-5 最小可演示完成(2026-10-25,#A-396)

依 BEAM PMO 指示「先給最小可演示版本、裁定後再對齊」——兩項形式仍待裁定,但已有可跑的東西。

h3. 12-7 客製化(建議選項 A:指引+可執行範例)

  • @docs/09-wiki/05-客製化指引.md@:原理(DIP 埠替換)/怎麼挑埠(112 個)/四步接上(實作→守契約→@Bean@ 註冊→驗證)/Debug 三招/為何不給 SDK jar
  • @examples/custom-storage-adapter/@:@FileSystemObjectStorageAdapter@ 只實作 @ObjectStoragePort@ 兩個方法,未改 cardcore 任何程式碼
  • 真機(@bash examples/custom-storage-adapter/run.sh@):①上傳/取回位元組一致 true ②查無回 @Optional.empty()@ true ③路徑穿越被拒 true → @ALL CHECKS PASSED@
  • 負樣本:@get@ 查無改成回空陣列 → ② 立即失敗(精準轉紅),還原後全過
  • ⚠️ 過程踩坑:@javac@ 用系統 Java 8 → @class file has wrong version 65.0, should be 52.0@;已改為 @source env.sh@ 並印出實際 JDK

h3. 12-5 封閉驗證(建議選項 B:錄製回放)

  • @ops/local/replay/replay.py@(@record@/@replay@,Python 標準庫零依賴)
  • 真機:6 筆唯讀請求錄製(含 1 筆 422 真實錯誤)→ 同版回放差異 0/exit 0
  • 負樣本:回放到不同服務 → 差異 6/6/exit 1;含寫入請求之錄製 → 拒絕/exit 2
  • 設計要點:排除易變欄位(@traceId@/@asOf@/@updatedAt@)否則永遠假紅;唯讀在檔案層強制(@readOnly@ 標記+回放前檢查),不靠使用者自律

h3. ⚠️ 如實揭露

兩項形式仍待裁定(GOV-009 #2/#3):若要求 SDK jar 或指定封閉驗證工具,本批為其內容基礎/可替換核心,需再對齊。

12-7 範例不含 Spring 註冊(刻意與框架無關),指引給出 @Bean@ 接線但未在叢集驗證。

12-5 樣本僅 6 筆、單一服務——足以證明機制,不足以代表流量分佈;未實作影子分流(第二階段,需獨立 schema)。

h3. 證據
@docs/08-evidence/CR-078_12-7_客製化_20261025/@、@docs/08-evidence/CR-078_12-5_封閉驗證_20261025/@

h3. 進度
CR-078:12-2 ✅、12-3 ✅、12-6 ✅、12-7 ◐ 最小可演示、12-5 ◐ 最小可演示、12-1/12-4 依 D-057 以基線+方法結案。

Actions

Also available in: PDF Atom