visionA/local-tool/.autoflow/04-architecture/risks-and-mitigations.md
jim800121chen c54f16fca0 Initial commit: visionA monorepo with local-tool subproject
local-tool/: visionA-local desktop app
- M1: Wails shell + Go server + Next.js UI + Mock mode (macOS dmg ready)
- M2: i18n (zh-TW/en) + Settings 4-tab refactor
- M3: Embedded Python 3.12 runtime (python-build-standalone) + KneronPLUS wheels
- M4: Windows Inno Setup script (build on Windows runner)
- M5: Linux AppImage script + udev rule (build on Linux runner)
- M6: ffmpeg (GPL, pending legal review) + yt-dlp bundled
- Lifecycle: watchServer health check, fatal native dialog,
            Wails IPC raise endpoint, stale process cleanup

.autoflow/: full PRD / Design Spec / Architecture / Testing docs
            (4 rounds tri-party discussion + cross review)
.github/workflows/: macOS / Windows / Linux build CI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:10:38 +08:00

13 KiB
Raw Permalink Blame History

Risks & Mitigations — visionA-local

重大技術風險總覽與緩解計畫。 優先級P0 = 會擋住發布、P1 = 嚴重影響使用者體驗、P2 = 可接受但需監控


R1KneronPLUS Linux wheel 的 glibc 相容性

  • 優先級P0
  • 可能性:高
  • 影響:高
  • 描述: KneronPLUS-3.1.2 Linux wheel 內的 .so 綁定特定 glibc 版本manylinux2014 = glibc 2.17+。Ubuntu 22.04 是 glibc 2.35、Ubuntu 24.04 是 glibc 2.39,理論上沒問題,但 .so 還依賴 libusb-1.0 的 ABI若系統 libusb 版本太舊或太新都可能炸。
  • 緩解:
    1. AppImage 內帶 libusb-1.0.so.0,透過 LD_LIBRARY_PATH 優先載入,避免依賴系統 libusb
    2. M1 階段就在 Ubuntu 22.04 + 24.04 實測,若不過則降級為只支援其中一版
    3. 提供明確錯誤訊息:「你的 Linux 發行版 libusb 版本不相容,請安裝 libusb-1.0.0」
  • 驗證時機: M5 Linux build

R2Windows WinUSB driver 安裝需要 UAC使用者拒絕就無法連裝置

  • 優先級P0
  • 可能性:中
  • 影響:高
  • 描述: Inno Setup 跑 pnputil /add-driver 需要 admin 權限,使用者拒絕 UAC 就裝不起來。安裝後第一次跑 app 再跳 UAC 的體驗也很差。
  • 緩解:
    1. Inno Setup 設定 PrivilegesRequired=admin,讓使用者在啟動安裝檔時就先提權一次(比跑到一半才跳好)
    2. 若使用者拒絕 → 顯示明確訊息「driver 未安裝app 仍可跑 Mock 模式,但無法連真實 Kneron 裝置」
    3. 提供「稍後手動安裝」的備援 scripttools/install-winusb-driver.bat
  • 驗證時機: M4 Windows build

R3macOS 沒有簽章Gatekeeper 會擋

  • 優先級P1
  • 可能性:確定會發生
  • 影響:中(體驗差但可 workaround
  • 描述: 沒有 Developer ID notarization首次開啟 .app 會跳「無法驗證開發者」的警告。需要使用者右鍵 → 開啟。
  • 緩解:
    1. README 與下載頁寫清楚 workaround 步驟
    2. .dmg 內容加入一張 首次開啟說明.png 圖片
    3. 提供一行 terminal 命令的替代方案:xattr -d com.apple.quarantine /Applications/visionA-local.app
  • 不做的事: 不購買 Apple Developer 帳號(使用者決策 Q2 = C
  • 風險接受理由: 目標使用者是內部工程師 + 技術型客戶,可接受一次性摩擦

R4python-build-standalone 可能被防毒軟體誤殺

  • 優先級P1
  • 可能性:中
  • 影響:高
  • 描述: Windows 環境尤其常見 — 防毒軟體(特別是企業版 Symantec / Trend Micro對內嵌 Python interpreter 有時會誤判為惡意軟體,直接刪除 python.exe 或整個資料夾。
  • 緩解:
    1. 策略 A + B 雙保險bundled 被刪時自動 fallback 到 system python使用者決策 Q1 保留 B 就是為了這個)
    2. 安裝完成後驗證 python --version 能跑,失敗立刻 fallback
    3. 提供 --python-mode=system 強制參數供 IT 人員 troubleshoot
    4. 文件說明:若公司防毒擋住,建議白名單 visiona-local 安裝目錄
  • 監控: 若 M4 Windows 測試頻繁遇到此問題,考慮用 pyinstaller 替代 python-build-standalonepyinstaller 更容易被防毒接受)

R5Windows SmartScreen 擋安裝檔下載

  • 優先級P1
  • 可能性:確定會發生
  • 影響:中
  • 描述: 沒有 Authenticode 簽章的 installerWindows SmartScreen 會跳「Windows 已保護您的電腦」並預設把「執行」按鈕隱藏在「更多資訊」後面。新使用者看到可能以為是病毒。
  • 緩解:
    1. README 截圖示範「更多資訊 → 仍要執行」的點擊路徑
    2. 下載頁顯眼標註「首次下載會看到 SmartScreen 警告,這是正常現象」
    3. 盡量從固定 URL 下載(同一個 URL 被 SmartScreen 累積 reputation久了會變成 trusted雖然慢
  • 不做的事: 不購買 EV Code Signing 憑證(使用者決策)

R6不做 auto-update → 後續版本推送困難

  • 優先級P2
  • 可能性:確定
  • 影響:中
  • 描述: 使用者決策 Q6 = 不做 auto-update。這代表未來每次升級都要使用者手動下載新的 installer而且要再次面對 Gatekeeper / SmartScreen 警告。對「內部工具」可接受,但若使用者多到一定規模,升級擴散會很慢。
  • 緩解:
    1. 在 About 頁顯示當前版本 + 一個「開啟下載頁」按鈕(連到 Gitea Release不自動檢查
    2. 內部溝通管道Slack / Email負責通知新版本
    3. 未來若需要時,可改為「手動檢查更新」(按鈕觸發,不自動),比 auto-update 輕量
  • 監控: 使用者回饋是否抱怨升級繁瑣;若變成痛點,優先做「手動檢查更新」功能

R7Apple Silicon 使用者用 Rosetta 跑 x86_64 版 → 效能 / 穩定性風險

  • 優先級P2
  • 可能性:低(使用者決策是先只做 x86_64
  • 影響:中
  • 描述: 使用者決策 Q4 = 三平台都只做 x86_64。對使用 Intel Mac 的使用者沒問題,但 Apple SiliconM1/M2/M3要走 Rosetta。風險點
    • Rosetta 翻譯 Python C extension 可能有邊界情況
    • KneronPLUS .dylib 是 x86_64-only必須走 Rosetta但 pyusb / libusb 的 USB 訊號路徑在 Rosetta 下未驗證過
    • 首次啟動會跳 Rosetta 安裝提示(如果使用者還沒裝)
  • 緩解:
    1. 明確聲明:「本版僅支援 x86_64Apple Silicon 需透過 Rosetta 2 執行」
    2. 第一次啟動偵測 CPU 架構,若是 arm64 → 顯示 Rosetta 提示
    3. 若 M1 階段測試 Rosetta 路徑不穩,評估是否加做 arm64 版本(將是 scope creep
  • 未來工作: 若使用者多為 Apple Silicon → 第二版加 arm64 build需要 KneronPLUS arm64 wheel目前沒有

R8python-build-standalone 下載 URL 可能失效

  • 優先級P2
  • 可能性:低
  • 影響:中
  • 描述: make vendor-sync 依賴 astral-sh/python-build-standalone 的 GitHub Release若他們改變命名慣例或刪除舊 releasebuild 會中斷。
  • 緩解:
    1. vendor/ 目錄用 git-lfs 或存到內部 artifact storage一旦下載成功就 cache 住
    2. 用固定版本號pin 20250317),不用 latest
    3. 備援fallback 到 https://www.python.org/ftp/python/ 官方 tarball雖然不是 standalone但至少保底

R9預置 .nef 模型的 re-distribution 授權

  • 優先級P1(第三輪 Q-B=B4 + 第四輪 R4-1 延續:開發階段先假設可內嵌,使用者決定暫不主動詢問 Kneron 法務,發佈前的 gate 維持必須 check-off屬於 release blocker
  • 可能性:中
  • 影響:高(若 Kneron 不允許 re-distribution會破壞「完全離線」承諾需改為首次啟動線上下載
  • 描述: Kneron 預置模型是 Kneron 官方提供,但「打包在另一個產品裡再發布」的授權條款未確認。可能限制 re-distribution。
  • 第三輪決策Q-B=B4+ 第四輪決策R4-1
    • 開發階段:先假設可以重新散布,繼續把預置 .nef 內嵌進 payload 正常開發
    • 現階段不主動詢問 Kneron(第四輪 R4-1 使用者決定):避免過早引發授權討論影響進度
    • 發佈前M6 或首次公開 release 前)必須由 PM / 使用者向 Kneron 官方(或依循 Innovedus 既有 OEM 合約)正式確認授權條款;若屆時仍無法確認,觸發 Plan B
    • 此項為 P1 release blocker:未確認前不得對外發佈
    • Plan B 對應文件:見 plan-b-online-download.md
  • 緩解:
    1. PM Agent 在 PRD / launch-checklist 追蹤項中列為發佈前必須 check-off 的項目
    2. Architect 在 packaging.md 的 bundle 清單中為預置模型加註「授權待 Kneron 確認」
    3. 若最終不允許 → Plan B改為首次啟動線上下載從 Innovedus 內部 Gitea / CDN打破「完全離線」承諾需再與使用者確認可接受度
    4. About 頁加上「模型版權Kneron Inc.」聲明(不論授權結果都要做)
  • 追蹤項P1 release blocker
    • PM 取得 Kneron 預置模型 re-distribution 書面授權或回信
    • 若無法取得 → 觸發 Plan B重新評估 M6 範圍

R10ffmpeg LGPL 合規要求

  • 優先級P2
  • 可能性:確定要處理
  • 影響:低(文件工作)
  • 描述: LGPL 要求:
    1. 聲明使用 ffmpeg 與版本
    2. 提供 LGPL 全文
    3. 提供取得 source 的方式
    4. (靜態連結時)提供 relink 所需的 object filesstatic build 才需要)
  • 緩解:
    1. 我們是動態呼叫 ffmpeg binary不是 link這個寬鬆很多
    2. About 頁加入聲明 + 連結到 ffmpeg.org 與 LGPL 全文
    3. 產品 Repo 的 THIRD_PARTY_LICENSES.md 列出所有第三方授權
  • 驗證: 法務 review About 頁與 license 文件(使用者決策:不優先,內部工具先發再說)


R11發佈通路基礎設施未確認內部 Gitea Releases / GitHub Releases

  • 優先級P2(追蹤項,發佈前必須解決)
  • 可能性:確定需要處理
  • 影響:中若無對外發佈通路DevOps 需臨時建置或改用其他方式如 S3 + 自製下載頁)
  • 描述: PRD release-strategypackaging.md §7 都假設有「內部 Gitea Release」或「GitHub Release」作為安裝檔分發通路但 progress.md 的「未解決問題」明確列出尚未確認 Innovedus 內部有此基礎設施。
  • 緩解:
    1. PM / 使用者在 M5 前確認 Innovedus 是否已有 Gitea Release 或 GitHub Releasepublic / private repo 皆可)的發佈通路
    2. 若無 → DevOps Agent 評估改走 S3 靜態站 + 自製 latest.json 下載頁,或直接內部檔案伺服器
    3. launch-checklist 列為發佈前必確認項
  • 與 R9 的關係: 若 R9 不允許內嵌Plan B 的線上下載也需要這個通路,兩者共用解決方案。

R12CI runner 三平台是否齊備

  • 優先級P2
  • 可能性:確定需要處理
  • 影響:中(若缺 runnerbuild 只能在開發者機器手動跑,發佈節奏與一致性差)
  • 描述: build-pipeline.md 假設 CI 有 macOS、Windows、Linux 三平台 runner 可分別跑 make installer-macos/windows/linux。實際上 Innovedus 內部 CIGitHub Actions / Gitea Actions / Jenkins是否已有這三種 runner 尚未確認。
  • 緩解:
    1. M4Windows與 M5Linux前確認對應 runner 可用
    2. 若缺 runner → 短期改為開發者本機手動跑,長期補 runner
    3. macOS runner 最棘手GitHub Actions macOS 有用量上限;自架需要實體 Mac→ 可能要採購或借用
    4. launch-checklist 列為發佈前必確認項

風險總表

# 風險 P 可能性 影響 緩解狀態
R1 Linux wheel glibc 相容性 P0 有方案,需 M5 驗證
R2 Windows WinUSB UAC 被拒絕 P0 有方案,需 M4 驗證
R3 macOS 無簽章 Gatekeeper P1 確定 接受,有 workaround
R4 python-build-standalone 被防毒誤殺 P1 雙策略 fallback
R5 Windows SmartScreen 警告 P1 確定 接受,文件說明
R6 不做 auto-update 擴散慢 P2 確定 接受
R7 Apple Silicon 走 Rosetta P2 接受
R8 pbs 下載失敗 P2 vendor cache + pin 版本
R9 .nef 授權Kneron re-distribution P1 Release blocker開發階段內嵌R4-1 決定暫不主動問 Kneron發佈前 gate 維持
R10 ffmpeg LGPL 合規 P2 確定 文件工作
R11 發佈通路基礎設施未確認 P2 確定 追蹤項M5 前確認
R12 CI runner 三平台是否齊備 P2 確定 追蹤項M4/M5 前確認

新發現的風險(相對 round 1

相較於第一輪分析(architect-analysis-round1.md),第二輪多出以下幾個風險:

  • R4python-build-standalone 被防毒誤殺):這是因為決策 Q1 = A 內嵌 Python 後才浮現round 1 當時還傾向用系統 Python 所以沒這個問題
  • R8pbs 下載 URL 失效):同上,由新的內嵌方案引入
  • R7Apple Silicon 走 Rosettaround 1 建議做 Universal BinaryQ4 決策改為只做 x86_64 後Rosetta 路徑未經驗證變成風險點

已解決(相對 round 1

  • R1 Apple Developer 憑證 → 決策 Q2 接受無簽章
  • R2 Windows EV Cert → 決策 Q2 接受 SmartScreen
  • R3 KneronPLUS macOS arm64 → 決策 Q4 只做 x86_64不用管 arm64 wheel
  • R4 離線 wheel vs 線上下載 → 決策 Q1 A 完全離線
  • R5 預置模型精簡 → 決策 Q5 全打包