FR-191 · 定版交付

定版交付:Agent 安裝包自助下載

已上線:正式更新站 80ccaecb(2026-11-10);主系統、前端、手冊已合回 feature/FR-172,客戶升到含本案的主系統版本即可使用

客戶還沒裝 Agent 時,管理員在主系統點「取得安裝包」,拿到原廠 Cloudflare R2 上 Agent 最新相容版安裝包與 .sha256 的預簽下載網址。網址有效時間由原廠在更新站後台設定,客戶畫面沒有這個欄位。

正式更新站已部署 正式站實打通過 手冊截圖待補

一句話

管理員在更新中心 Agent 區按「取得安裝包」,或建完註冊 token 時看對話框下方,就拿到兩條 R2 預簽網址(安裝包、.sha256),直接下載或複製給裝機的人。主系統只向原廠更新站換網址、原樣轉交,不存包、不供檔;網址時限由原廠在更新站後台設定。


1. 交付物

Repo 內容 位置
update-center /v1/download-url 認 artifact=sha256;預簽網址帶下載檔名;有效時間讀 D1 site_settings(預設 900 秒,範圍 300~86400);後台「設定」分頁與 GET/PUT /admin/settings。正式站已部署:版本 80ccaecb(2026-11-10),正式 D1 已套 0007 src/settings.ts、src/routes/client.ts、src/routes/admin.ts、migrations/0007_site_settings.sql
主系統 BE POST /api/1.0/system/product-update/agents/bundle-links:節流 → 查最新相容版(唯讀,不寫 agent_last_check)→ 換兩條網址 → 稽核 6251 api/product_update/routes/agent_bundle_link_route.py(32 行)、app/product_update/service/agent_bundle_link_service.py(101 行)、update_site_client.py 的 download_url_info、agent_release_service.py 的 query_latest 與常數 NO_AGENT_BASE
主系統 FE 共用對話框顯示版號、大小、SHA-256、兩列網址與到期時間;兩個入口;沒有時限欄位 AgentBundleLinks.vue、AgentBundleButton.vue、useAgentBundleLinks.js
手冊 快速版第 3 步與 03 章 3.2 的取包標準句;04 章 token 對話框提示;07/10/11/README 的重新取包句 docs/user-manual/agent/、FR-189 site/index.html

2. 流程

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
  autonumber
  actor A as 管理員(瀏覽器)
  participant B as 主系統 API
  participant U as 更新站(Cloudflare Worker)
  participant R as Cloudflare R2
  actor C as 裝機人員
  A->>B: POST agents/bundle-links
  B->>B: 每人每分鐘 10 次節流
  B->>U: /v1/check product=agent current=1.0.0(主機授權身分)
  U-->>B: latest 與簽章清單
  B->>B: 驗章、比 min_host_version
  B->>U: /v1/download-url 整包+artifact=sha256
  U-->>B: 兩條 R2 預簽網址、expires_in
  B-->>A: 版號、大小、SHA-256、兩條網址;寫稽核
  A->>C: 下載,或複製網址交給裝機人員
  C->>R: GET 預簽網址(不需帳號)
  R-->>C: 檔案
  C->>C: sha256sum -c
圖 1 管理員產生 R2 下載網址。主系統以主機授權身分向更新站換網址;檔案下載完全不經主系統。

第 3 步送 current=1.0.0(常數 NO_AGENT_BASE):更新站 Agent 版本的可直升起始版一律是 <主版>.0.0,送 0.0.0 會把所有版本濾掉、回「沒有新版」。第 6 步任一失敗,或兩條網址只換到一條,整個回失敗,不給半組網址。


3. 規則

  • 版號=更新站上這張授權看得到的 Agent 最新相容版,管理員不能選。查詢時一律送基準版 1.0.0;更新中心 Agent 區「檢查」與「預先下載」在一台 Agent 都沒有時也送同一個值。最新版要求較新的主系統時回 412(PRODUCT_UPDATE_412014),不給網址。
  • 時限由原廠在更新站後台「設定」分頁調整,所有預簽網址(升級包、維運小檔、Agent 包)共用。陷阱:主系統不再有任何時限欄位,客戶端問時限一律請原廠改後台。
  • sha256、size 取自驗過章的簽章清單,不取 /v1/download-url 回的未簽欄位。
  • 網址主機必須在 DOWNLOAD_HOSTS 白名單(R2 端點),否則拒絕轉交(503001)。
  • 產生網址要 system.product-update.read;每人每分鐘 10 次,超過回 429(PRODUCT_UPDATE_429002)。
  • 稽核事件碼 6251,action AGENT_BUNDLE_LINK_ISSUED,欄位 actor、version、expires_in、source=r2。
  • 錯誤:沒設更新站 412001、連不到或清單驗不過 503001、沒授權照 412003、站上沒有 Agent 版本 404005。
  • 前端只保留「下載」鈕按下後鎖 10 秒;到期判斷用收到網址的本機時刻加 expires_in;不做 HEAD 探測(R2 預簽網址簽的是 GET)。
  • 下載者的電腦要能連 Cloudflare;主系統連不到更新站時畫面提示向原廠索取。

4. 驗證結果

正式更新站實打(2026-11-10,部署 80ccaecb 後,用 190 測試機主機授權身分;190 本身未改動):

項目 結果
健康檢查 {"ok":true}
主系統「檢查更新」(現有功能) 正常
主系統升級包下載網址(現有功能) 正常;expires_in=900;真 R2 下載與續傳(206)成功,檔名正確
Agent 線 current=1.0.0 latest=1.7.4(current=0.0.0 回 none,見第 2 節)
Agent 1.7.4 安裝包與 .sha256 網址 兩條都拿得到,檔名正確;.sha256 實際下載內容與更新站清單 sha256 一致
Agent 線帶 artifact=ops 400,正確擋下
主系統程式(修正後常數+真 update_site_client)打正式站 latest=1.7.4,兩條網址正常,sha256 一致

自動測試:

範圍 結果
update-center typecheck 綠;npm test Worker 187、CLI 101 全綠(含 sha256、content-disposition 簽進章內、設定範圍、CI/GitLab token 403)
主系統 BE FR-191、更新中心、FR-167/172 相關測試與守衛 test_module_boundaries.py 共 495 條綠
主系統 FE vitest 相關 12 檔 145 條綠;全套 86 檔 663 條綠;vite build 過;改動檔無 border-left
手冊 grep「主系統下載/預先下載/30 分鐘內有效」只剩 07 章 7.8 一句(講 Agent 升級,與取包無關)

畫面:本機接模擬更新站(用綁本機的 DEV 身分票)時,後端 API 與無頭瀏覽器都打通;對話框顯示版本 1.7.4、1.7 GB、SHA-256、兩列 R2 網址、「連結 15 分鐘內有效」,沒有時限欄位。模擬環境的 R2 金鑰是假的,網址本身下載不到;真實下載已由上方正式站實打涵蓋。


5. 沒做完的

事項 說明 誰接
手冊截圖 快速版第 3 步與 03 章 3.2 的畫面截圖。現有兩張是模擬環境畫面,不採用 決策者 2026-11-10 裁先不做;有真網址畫面時重截
客戶主系統升級 客戶要升到含 FR-191 v2 與 CM-3819 的主系統版本,才會有新的「取得安裝包」行為。舊版主系統打新版更新站不受影響 隨下一次主系統發版

6. 文件定位

你想知道 看哪份
要做成什麼樣、為什麼、排除了什麼 design-v2.1.md(現行);design-v2.0.md(被 v2.1 取代,只差查詢基準版)
v1.0 當初怎麼設計(稽核用,已推翻) design.md
進度、決策者表態、Notion 卡號 README.md
每一棒做了什麼、v1.0 為什麼被推翻 handoff/FR-191-LOG.md
現在停在哪 handoff/FR-191-STATE.md