<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Signing on Tarragon</title><link>https://tarrragon.github.io/blog/tags/signing/</link><description>Recent content in Signing on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 21 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/signing/index.xml" rel="self" type="application/rss+xml"/><item><title>App 簽章、商店審核與分批發布流程</title><link>https://tarrragon.github.io/blog/ci/app-deploy/signing-store-rollout-flow/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/ci/app-deploy/signing-store-rollout-flow/</guid><description>&lt;p>App 發布流程的核心責任是把可安裝 artifact 送進受控發行通道。App 與 web 最大差異是使用者裝置會長期保留舊版本；CI/CD 需要把 build number、簽章、審核、分批發布與服務端相容性一起管理。&lt;/p>
&lt;h2 id="流程定位">流程定位&lt;/h2>
&lt;p>App 部署的風險集中在不可變 artifact 與外部 gate。IPA、APK、AAB 或桌面安裝包一旦被使用者安裝，團隊需要靠 hotfix、remote config、kill switch 或服務端相容性止血；store review、簽章憑證與 phased rollout 會決定錯誤版本能否快速收斂。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>責任&lt;/th>
 &lt;th>判讀訊號&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Version&lt;/td>
 &lt;td>管理 version 與 build number&lt;/td>
 &lt;td>每次上傳是否可唯一追溯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App signing&lt;/a>&lt;/td>
 &lt;td>產生可信 artifact&lt;/td>
 &lt;td>certificate / keystore 是否安全&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Test&lt;/td>
 &lt;td>驗證裝置與 OS matrix&lt;/td>
 &lt;td>高風險裝置、權限與離線情境&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Store review&lt;/td>
 &lt;td>通過商店或企業發行 gate&lt;/td>
 &lt;td>審核時間、拒審理由、metadata&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/rollout-strategy/" data-link-title="Rollout Strategy" data-link-desc="說明新版本如何以可控節奏推進到全部流量">Rollout strategy&lt;/a>&lt;/td>
 &lt;td>控制使用者取得比例&lt;/td>
 &lt;td>crash-free rate、conversion、回報&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Recovery&lt;/td>
 &lt;td>hotfix、remote config、kill switch&lt;/td>
 &lt;td>是否能處理已安裝版本&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Version 階段負責讓 artifact 可追溯。App crash report、客服回報與 store console 都依賴 version / build number；版本號對應 commit 與 workflow run 時，事故定位可以直接回到發布紀錄。&lt;/p>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App signing&lt;/a> 階段負責維持發布信任鏈。簽章憑證、provisioning profile、keystore 與 notarization credential 都是發布能力；它們要用 secret 管理、權限隔離、輪替與備援流程保護。&lt;/p>
&lt;p>Test 階段負責覆蓋目標裝置條件。App 測試要依實際使用者分佈選擇 OS、裝置、權限狀態、網路條件與升級路徑；只跑 emulator smoke test，通常抓不到真機權限、背景限制或升級資料遷移問題。&lt;/p>
&lt;p>Store review 階段負責處理外部 gate。審核可能因 metadata、隱私揭露、權限使用、付款政策或 crash 被拒；CI/CD 文件要記錄誰能處理審核回覆、哪些變更需要重新提交。&lt;/p>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/rollout-strategy/" data-link-title="Rollout Strategy" data-link-desc="說明新版本如何以可控節奏推進到全部流量">Rollout strategy&lt;/a> 階段負責控制新版本擴散速度。分批發布的觀察指標包含 crash rate、登入、購買、同步、推播與核心流程完成率；達到停損條件時應暫停 rollout，先讓已受影響範圍維持可控。&lt;/p>
&lt;p>Recovery 階段負責處理已安裝版本。App 常見止血工具是 remote config、feature flag、kill switch、server-side compatibility、hotfix build 與要求使用者升級；每個工具都要在事故前實作，事故時才有路可走。&lt;/p>
&lt;h2 id="多版本共存契約">多版本共存契約&lt;/h2>
&lt;p>多版本共存是 App 發布的基本前提。後端 API、資料格式、推播 payload 與 remote config 都要支援一段時間的新舊 client，因為使用者更新節奏不受團隊完全控制。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>契約&lt;/th>
 &lt;th>判讀問題&lt;/th>
 &lt;th>常見風險&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>API response&lt;/td>
 &lt;td>舊 app 看到新增欄位是否能正常處理&lt;/td>
 &lt;td>刪欄位或改語意造成舊版 crash&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Auth / session&lt;/td>
 &lt;td>更新前後 token 是否仍可使用&lt;/td>
 &lt;td>強制登出或登入狀態破壞&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Local storage&lt;/td>
 &lt;td>app upgrade 是否能遷移本機資料&lt;/td>
 &lt;td>新版寫入後舊版讀取契約失效&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Push payload&lt;/td>
 &lt;td>舊版是否能忽略未知 action&lt;/td>
 &lt;td>推播點擊進入不存在頁面&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Remote config&lt;/td>
 &lt;td>config key 是否有預設值與版本條件&lt;/td>
 &lt;td>未支援版本收到新功能開關&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這些契約要在 CI 或 release checklist 裡被驗證。若只靠後端「盡量相容」，App 發布失敗會在使用者更新後才暴露，回復成本會比 web 或後端高。&lt;/p>
&lt;h2 id="release-checklist">Release checklist&lt;/h2>
&lt;p>Release checklist 的責任是把外部 gate 與內部 gate 接起來。App 發布牽涉商店、憑證、客服、行銷與後端相容，因此 checklist 應該是流程契約，不只是提醒清單。&lt;/p></description><content:encoded><![CDATA[<p>App 發布流程的核心責任是把可安裝 artifact 送進受控發行通道。App 與 web 最大差異是使用者裝置會長期保留舊版本；CI/CD 需要把 build number、簽章、審核、分批發布與服務端相容性一起管理。</p>
<h2 id="流程定位">流程定位</h2>
<p>App 部署的風險集中在不可變 artifact 與外部 gate。IPA、APK、AAB 或桌面安裝包一旦被使用者安裝，團隊需要靠 hotfix、remote config、kill switch 或服務端相容性止血；store review、簽章憑證與 phased rollout 會決定錯誤版本能否快速收斂。</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>責任</th>
          <th>判讀訊號</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Version</td>
          <td>管理 version 與 build number</td>
          <td>每次上傳是否可唯一追溯</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App signing</a></td>
          <td>產生可信 artifact</td>
          <td>certificate / keystore 是否安全</td>
      </tr>
      <tr>
          <td>Test</td>
          <td>驗證裝置與 OS matrix</td>
          <td>高風險裝置、權限與離線情境</td>
      </tr>
      <tr>
          <td>Store review</td>
          <td>通過商店或企業發行 gate</td>
          <td>審核時間、拒審理由、metadata</td>
      </tr>
      <tr>
          <td><a href="/blog/ci/knowledge-cards/rollout-strategy/" data-link-title="Rollout Strategy" data-link-desc="說明新版本如何以可控節奏推進到全部流量">Rollout strategy</a></td>
          <td>控制使用者取得比例</td>
          <td>crash-free rate、conversion、回報</td>
      </tr>
      <tr>
          <td>Recovery</td>
          <td>hotfix、remote config、kill switch</td>
          <td>是否能處理已安裝版本</td>
      </tr>
  </tbody>
</table>
<p>Version 階段負責讓 artifact 可追溯。App crash report、客服回報與 store console 都依賴 version / build number；版本號對應 commit 與 workflow run 時，事故定位可以直接回到發布紀錄。</p>
<p><a href="/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App signing</a> 階段負責維持發布信任鏈。簽章憑證、provisioning profile、keystore 與 notarization credential 都是發布能力；它們要用 secret 管理、權限隔離、輪替與備援流程保護。</p>
<p>Test 階段負責覆蓋目標裝置條件。App 測試要依實際使用者分佈選擇 OS、裝置、權限狀態、網路條件與升級路徑；只跑 emulator smoke test，通常抓不到真機權限、背景限制或升級資料遷移問題。</p>
<p>Store review 階段負責處理外部 gate。審核可能因 metadata、隱私揭露、權限使用、付款政策或 crash 被拒；CI/CD 文件要記錄誰能處理審核回覆、哪些變更需要重新提交。</p>
<p><a href="/blog/ci/knowledge-cards/rollout-strategy/" data-link-title="Rollout Strategy" data-link-desc="說明新版本如何以可控節奏推進到全部流量">Rollout strategy</a> 階段負責控制新版本擴散速度。分批發布的觀察指標包含 crash rate、登入、購買、同步、推播與核心流程完成率；達到停損條件時應暫停 rollout，先讓已受影響範圍維持可控。</p>
<p>Recovery 階段負責處理已安裝版本。App 常見止血工具是 remote config、feature flag、kill switch、server-side compatibility、hotfix build 與要求使用者升級；每個工具都要在事故前實作，事故時才有路可走。</p>
<h2 id="多版本共存契約">多版本共存契約</h2>
<p>多版本共存是 App 發布的基本前提。後端 API、資料格式、推播 payload 與 remote config 都要支援一段時間的新舊 client，因為使用者更新節奏不受團隊完全控制。</p>
<table>
  <thead>
      <tr>
          <th>契約</th>
          <th>判讀問題</th>
          <th>常見風險</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>API response</td>
          <td>舊 app 看到新增欄位是否能正常處理</td>
          <td>刪欄位或改語意造成舊版 crash</td>
      </tr>
      <tr>
          <td>Auth / session</td>
          <td>更新前後 token 是否仍可使用</td>
          <td>強制登出或登入狀態破壞</td>
      </tr>
      <tr>
          <td>Local storage</td>
          <td>app upgrade 是否能遷移本機資料</td>
          <td>新版寫入後舊版讀取契約失效</td>
      </tr>
      <tr>
          <td>Push payload</td>
          <td>舊版是否能忽略未知 action</td>
          <td>推播點擊進入不存在頁面</td>
      </tr>
      <tr>
          <td>Remote config</td>
          <td>config key 是否有預設值與版本條件</td>
          <td>未支援版本收到新功能開關</td>
      </tr>
  </tbody>
</table>
<p>這些契約要在 CI 或 release checklist 裡被驗證。若只靠後端「盡量相容」，App 發布失敗會在使用者更新後才暴露，回復成本會比 web 或後端高。</p>
<h2 id="release-checklist">Release checklist</h2>
<p>Release checklist 的責任是把外部 gate 與內部 gate 接起來。App 發布牽涉商店、憑證、客服、行銷與後端相容，因此 checklist 應該是流程契約，不只是提醒清單。</p>
<ol>
<li>確認 version、build number、commit 與 artifact 對應。</li>
<li>確認 signing secret、profile 或 keystore 仍有效。</li>
<li>跑 unit、UI、device matrix 與 upgrade test。</li>
<li>檢查 API / remote config / push payload 多版本相容。</li>
<li>上傳 internal / beta track，跑 smoke test。</li>
<li>提交 store review，記錄審核狀態。</li>
<li>用 phased rollout 推進，觀察 crash-free rate 與核心指標。</li>
<li>觸發停損條件時暫停 rollout、關閉功能或準備 hotfix。</li>
</ol>
<p>這個順序讓 App 發布從「把包丟上去」變成可觀測流程。每一步都對應一個失敗路由，事故時能知道下一個可執行動作。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>App 部署總覽：回 <a href="../">App 部署 CI/CD</a>。</li>
<li>簽章概念：讀 <a href="/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App Signing</a>。</li>
<li>Gate 原理：讀 <a href="../../ci-gate-workflow-boundary/">CI gate 與 workflow 邊界</a>。</li>
</ul>
]]></content:encoded></item><item><title>Desktop client 簽章、公證與自動更新流程</title><link>https://tarrragon.github.io/blog/ci/desktop-client-deploy/signing-notarization-update-flow/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/ci/desktop-client-deploy/signing-notarization-update-flow/</guid><description>&lt;p>Desktop client 發布流程的核心責任是讓多平台安裝包可信、可更新、可回復。桌面應用和 web 不同，使用者會下載 installer 或 package 到本機；CI/CD 需要處理平台差異、code signing、notarization、auto-update feed、delta package 與多版本共存。&lt;/p>
&lt;h2 id="流程定位">流程定位&lt;/h2>
&lt;p>Desktop client 的風險集中在作業系統信任鏈與更新通道。macOS、Windows、Linux 對簽章、安裝包格式與安全提示的要求不同；同一份 source 通常會產生多個平台 artifact，因此 workflow 要把平台 matrix、簽章 secret 與 &lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/release-channel/" data-link-title="Release Channel" data-link-desc="說明 stable、beta、internal 等發行通道如何控制 artifact 接觸到的使用者範圍">Release Channel&lt;/a> 拆清楚。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>階段&lt;/th>
 &lt;th>責任&lt;/th>
 &lt;th>判讀訊號&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Build&lt;/td>
 &lt;td>產生 &lt;code>.dmg&lt;/code>、&lt;code>.pkg&lt;/code>、&lt;code>.msi&lt;/code>、AppImage 等&lt;/td>
 &lt;td>平台 matrix 是否完整&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Signing&lt;/td>
 &lt;td>建立 OS 信任&lt;/td>
 &lt;td>certificate、timestamp、keychain&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Notarize&lt;/td>
 &lt;td>通過 macOS 公證或平台審查&lt;/td>
 &lt;td>staple、gatekeeper 是否通過&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Release&lt;/td>
 &lt;td>發布到 channel 或 download page&lt;/td>
 &lt;td>stable / beta / internal 分流&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Update&lt;/td>
 &lt;td>推送 &lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed&lt;/a> 或 delta package&lt;/td>
 &lt;td>feed 簽章、版本相容、回退策略&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Recovery&lt;/td>
 &lt;td>hotfix、rollback channel、停用更新&lt;/td>
 &lt;td>是否能阻止錯誤版本擴散&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Build 階段負責產生平台專屬 artifact。Flutter Desktop、Electron 與 Tauri 的輸出格式不同，但共同要求是每個 artifact 都能追到 commit、workflow run 與 dependency lock。&lt;/p>
&lt;p>Signing 階段負責讓 OS 信任安裝包。Windows code signing certificate、macOS Developer ID、timestamp server 與 Linux package signing key 都是發布能力；secret 應放在受控環境，並限制能觸發 signing job 的分支與 reviewer。&lt;/p>
&lt;p>Notarize 階段負責處理 macOS 信任 gate。macOS app 即使完成簽章，也常需要 notarization 與 stapling；CI 要把 notarization log 保存下來，否則使用者看到 Gatekeeper 警告時很難回溯。&lt;/p>
&lt;p>Release 階段負責把 artifact 放到正確 &lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/release-channel/" data-link-title="Release Channel" data-link-desc="說明 stable、beta、internal 等發行通道如何控制 artifact 接觸到的使用者範圍">Release Channel&lt;/a>。Internal、beta、stable 與 enterprise channel 的 gate 不同；CI/CD 要避免未審核的 beta artifact 被 stable feed 取用。&lt;/p>
&lt;p>Update 階段負責維持升級路徑。&lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed&lt;/a>、delta package、signature、minimum supported version 與 rollback channel 要一起設計；更新壞掉時，使用者可能卡在需要人工修復的版本。&lt;/p>
&lt;p>Recovery 階段負責止血。桌面客戶端常用方式是撤下 update feed、發布 hotfix、切換 rollback channel、停用 remote feature 或要求最低版本；每種方式都依賴 app 內建相容支援。&lt;/p>
&lt;h2 id="平台差異判讀">平台差異判讀&lt;/h2>
&lt;p>平台差異判讀的責任是讓 CI matrix 對應真實發布風險。桌面發布除了確認「三平台都 build 成功」，還要確認每個平台的安裝、啟動、更新與卸載行為。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>平台&lt;/th>
 &lt;th>高風險點&lt;/th>
 &lt;th>驗證方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>macOS&lt;/td>
 &lt;td>Developer ID、notarization、universal binary&lt;/td>
 &lt;td>Gatekeeper、arm64 / x64 啟動&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Windows&lt;/td>
 &lt;td>Authenticode、SmartScreen、installer 權限&lt;/td>
 &lt;td>安裝、更新、卸載、權限提示&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Linux&lt;/td>
 &lt;td>AppImage、deb、rpm、repository key&lt;/td>
 &lt;td>dependency、desktop entry、sandbox&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表的用途是避免平台細節被單一「desktop build」欄位抹平。每個 OS 的失敗代價不同，CI 應保留平台專屬 gate。&lt;/p></description><content:encoded><![CDATA[<p>Desktop client 發布流程的核心責任是讓多平台安裝包可信、可更新、可回復。桌面應用和 web 不同，使用者會下載 installer 或 package 到本機；CI/CD 需要處理平台差異、code signing、notarization、auto-update feed、delta package 與多版本共存。</p>
<h2 id="流程定位">流程定位</h2>
<p>Desktop client 的風險集中在作業系統信任鏈與更新通道。macOS、Windows、Linux 對簽章、安裝包格式與安全提示的要求不同；同一份 source 通常會產生多個平台 artifact，因此 workflow 要把平台 matrix、簽章 secret 與 <a href="/blog/ci/knowledge-cards/release-channel/" data-link-title="Release Channel" data-link-desc="說明 stable、beta、internal 等發行通道如何控制 artifact 接觸到的使用者範圍">Release Channel</a> 拆清楚。</p>
<table>
  <thead>
      <tr>
          <th>階段</th>
          <th>責任</th>
          <th>判讀訊號</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Build</td>
          <td>產生 <code>.dmg</code>、<code>.pkg</code>、<code>.msi</code>、AppImage 等</td>
          <td>平台 matrix 是否完整</td>
      </tr>
      <tr>
          <td>Signing</td>
          <td>建立 OS 信任</td>
          <td>certificate、timestamp、keychain</td>
      </tr>
      <tr>
          <td>Notarize</td>
          <td>通過 macOS 公證或平台審查</td>
          <td>staple、gatekeeper 是否通過</td>
      </tr>
      <tr>
          <td>Release</td>
          <td>發布到 channel 或 download page</td>
          <td>stable / beta / internal 分流</td>
      </tr>
      <tr>
          <td>Update</td>
          <td>推送 <a href="/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed</a> 或 delta package</td>
          <td>feed 簽章、版本相容、回退策略</td>
      </tr>
      <tr>
          <td>Recovery</td>
          <td>hotfix、rollback channel、停用更新</td>
          <td>是否能阻止錯誤版本擴散</td>
      </tr>
  </tbody>
</table>
<p>Build 階段負責產生平台專屬 artifact。Flutter Desktop、Electron 與 Tauri 的輸出格式不同，但共同要求是每個 artifact 都能追到 commit、workflow run 與 dependency lock。</p>
<p>Signing 階段負責讓 OS 信任安裝包。Windows code signing certificate、macOS Developer ID、timestamp server 與 Linux package signing key 都是發布能力；secret 應放在受控環境，並限制能觸發 signing job 的分支與 reviewer。</p>
<p>Notarize 階段負責處理 macOS 信任 gate。macOS app 即使完成簽章，也常需要 notarization 與 stapling；CI 要把 notarization log 保存下來，否則使用者看到 Gatekeeper 警告時很難回溯。</p>
<p>Release 階段負責把 artifact 放到正確 <a href="/blog/ci/knowledge-cards/release-channel/" data-link-title="Release Channel" data-link-desc="說明 stable、beta、internal 等發行通道如何控制 artifact 接觸到的使用者範圍">Release Channel</a>。Internal、beta、stable 與 enterprise channel 的 gate 不同；CI/CD 要避免未審核的 beta artifact 被 stable feed 取用。</p>
<p>Update 階段負責維持升級路徑。<a href="/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed</a>、delta package、signature、minimum supported version 與 rollback channel 要一起設計；更新壞掉時，使用者可能卡在需要人工修復的版本。</p>
<p>Recovery 階段負責止血。桌面客戶端常用方式是撤下 update feed、發布 hotfix、切換 rollback channel、停用 remote feature 或要求最低版本；每種方式都依賴 app 內建相容支援。</p>
<h2 id="平台差異判讀">平台差異判讀</h2>
<p>平台差異判讀的責任是讓 CI matrix 對應真實發布風險。桌面發布除了確認「三平台都 build 成功」，還要確認每個平台的安裝、啟動、更新與卸載行為。</p>
<table>
  <thead>
      <tr>
          <th>平台</th>
          <th>高風險點</th>
          <th>驗證方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>macOS</td>
          <td>Developer ID、notarization、universal binary</td>
          <td>Gatekeeper、arm64 / x64 啟動</td>
      </tr>
      <tr>
          <td>Windows</td>
          <td>Authenticode、SmartScreen、installer 權限</td>
          <td>安裝、更新、卸載、權限提示</td>
      </tr>
      <tr>
          <td>Linux</td>
          <td>AppImage、deb、rpm、repository key</td>
          <td>dependency、desktop entry、sandbox</td>
      </tr>
  </tbody>
</table>
<p>這張表的用途是避免平台細節被單一「desktop build」欄位抹平。每個 OS 的失敗代價不同，CI 應保留平台專屬 gate。</p>
<h2 id="update-feed-契約">Update feed 契約</h2>
<p><a href="/blog/ci/knowledge-cards/update-feed/" data-link-title="Update Feed" data-link-desc="說明桌面與客戶端應用如何透過更新來源取得已簽章版本與回復路徑">Update Feed</a> 契約的責任是讓已安裝使用者安全升級。Auto-update 需要簽章、版本比較、channel、最低版本與回退策略共同成立，才能讓新版本 URL 進入 feed。</p>
<ol>
<li>Feed 只指向已簽章且已驗證的 artifact。</li>
<li>Stable feed 只接收 stable release，beta feed 只接收 beta release。</li>
<li>App 啟動時能處理 feed 暫時不可用。</li>
<li>Delta update 失敗時能 fallback 到 full installer。</li>
<li>錯誤版本要能從 feed 撤下，並讓未更新使用者停止取得。</li>
<li>已更新使用者要有 hotfix 或 rollback channel。</li>
</ol>
<p>這些條件讓更新通道具備操作性。若 app 只知道「看到新版就下載」，錯誤 feed 會把事故放大到所有啟動中的使用者。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Desktop 部署總覽：回 <a href="../">Desktop Client 部署 CI/CD</a>。</li>
<li>App 發布通用觀念：讀 <a href="../../app-deploy/signing-store-rollout-flow/">App 簽章、商店審核與分批發布流程</a>。</li>
<li>簽章術語：讀 <a href="/blog/ci/knowledge-cards/app-signing/" data-link-title="App Signing" data-link-desc="說明行動與桌面應用的簽章憑證如何影響發布能力">App Signing</a>。</li>
</ul>
]]></content:encoded></item><item><title>App Signing</title><link>https://tarrragon.github.io/blog/ci/knowledge-cards/app-signing/</link><pubDate>Wed, 06 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/ci/knowledge-cards/app-signing/</guid><description>&lt;p>App Signing 的核心概念是「簽章憑證即發布能力」。它決定 artifact 是否被平台接受與使用者裝置信任。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>App Signing 位在 app build 與 release channel 之間，涉及 certificate、provisioning profile、keystore 與 secret 管理。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;ul>
&lt;li>發布因簽章失敗中斷。&lt;/li>
&lt;li>憑證過期導致發版中斷。&lt;/li>
&lt;li>金鑰輪替缺乏演練造成交付風險。&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實服務的例子">接近真實服務的例子&lt;/h2>
&lt;p>iOS 發版需匹配正確 certificate 與 provisioning profile，Android 發版需維護 keystore 一致性與安全儲存。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>App Signing 要定義密鑰保存、輪替節奏、權限分離與緊急回復流程，確保發布能力可持續。&lt;/p></description><content:encoded><![CDATA[<p>App Signing 的核心概念是「簽章憑證即發布能力」。它決定 artifact 是否被平台接受與使用者裝置信任。</p>
<h2 id="概念位置">概念位置</h2>
<p>App Signing 位在 app build 與 release channel 之間，涉及 certificate、provisioning profile、keystore 與 secret 管理。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<ul>
<li>發布因簽章失敗中斷。</li>
<li>憑證過期導致發版中斷。</li>
<li>金鑰輪替缺乏演練造成交付風險。</li>
</ul>
<h2 id="接近真實服務的例子">接近真實服務的例子</h2>
<p>iOS 發版需匹配正確 certificate 與 provisioning profile，Android 發版需維護 keystore 一致性與安全儲存。</p>
<h2 id="設計責任">設計責任</h2>
<p>App Signing 要定義密鑰保存、輪替節奏、權限分離與緊急回復流程，確保發布能力可持續。</p>
]]></content:encoded></item></channel></rss>