<?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>Dependency on Tarragon</title><link>https://tarrragon.github.io/blog/tags/dependency/</link><description>Recent content in Dependency on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 26 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/dependency/index.xml" rel="self" type="application/rss+xml"/><item><title>熔斷器</title><link>https://tarrragon.github.io/blog/devops/03-traffic-management/circuit-breaker/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/03-traffic-management/circuit-breaker/</guid><description>&lt;p>熔斷器保護的是「呼叫外部依賴」的路徑。當外部依賴（資料庫、第三方 API、通知服務）持續失敗時，熔斷器讓後續的呼叫立即失敗（回傳預設值或錯誤），而非每次都等待逾時。等待逾時的代價是佔住 goroutine / thread 不釋放，積累到一定數量就拖垮整個服務。&lt;/p>
&lt;h2 id="三狀態模型">三狀態模型&lt;/h2>
&lt;h3 id="closed正常">Closed（正常）&lt;/h3>
&lt;p>所有呼叫正常通過。熔斷器記錄成功和失敗的計數。&lt;/p>
&lt;h3 id="open熔斷">Open（熔斷）&lt;/h3>
&lt;p>當失敗率或連續失敗次數超過閾值時，熔斷器進入 open 狀態。此後所有呼叫&lt;strong>立即回傳錯誤&lt;/strong>，不實際呼叫外部依賴。&lt;/p>
&lt;p>Open 狀態持續固定時間（如 30 秒），時間到後進入 half-open。&lt;/p>
&lt;h3 id="half-open探測">Half-open（探測）&lt;/h3>
&lt;p>允許少量呼叫（如 1 個）實際通過到外部依賴。如果成功 → 回到 closed；如果失敗 → 回到 open（重設計時器）。&lt;/p>
&lt;p>Half-open 的目的是自動探測依賴是否恢復，不需要人工介入。&lt;/p>
&lt;h2 id="熔斷判斷條件">熔斷判斷條件&lt;/h2>
&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>連續 N 次失敗&lt;/td>
 &lt;td>依賴完全不可用&lt;/td>
 &lt;td>N = 5-10&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>失敗率 &amp;gt; X%&lt;/td>
 &lt;td>依賴間歇性失敗&lt;/td>
 &lt;td>X = 50%，統計窗口 = 10 秒&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>平均延遲 &amp;gt; Y ms&lt;/td>
 &lt;td>依賴變慢但未失敗&lt;/td>
 &lt;td>Y = 依據 SLA 設定&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>「失敗」的定義需要明確：HTTP 5xx 是失敗、4xx 通常不是（client 的問題）、timeout 是失敗、connection refused 是失敗。&lt;/p>
&lt;h2 id="熔斷時的-fallback">熔斷時的 fallback&lt;/h2>
&lt;p>熔斷觸發後，呼叫端收到的是「快速失敗」而非逾時。呼叫端需要有 fallback 策略：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>依賴&lt;/th>
 &lt;th>Fallback&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>通知服務（Slack webhook）&lt;/td>
 &lt;td>記錄到本地 log、恢復後補發&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>外部 API（enrichment）&lt;/td>
 &lt;td>回傳無 enrichment 的原始資料&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>認證服務&lt;/td>
 &lt;td>用本地 cache 的 token 驗證（短暫降級）&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>沒有 fallback 的依賴被熔斷 = 對應功能完全不可用。熔斷器保護的是「不讓不可用的功能拖垮整個服務」。&lt;/p>
&lt;h2 id="監控系統的應用">監控系統的應用&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/monitoring/04-collector/" data-link-title="模組四：Collector 設計" data-link-desc="收 → 驗 → 存 → 查 → 觸發的完整鏈路 — Go 單一 binary、可插拔 Storage Backend、rule engine">Collector&lt;/a> 的 rule engine 在規則命中時可能呼叫外部服務（Slack webhook、HTTP POST 到 alert endpoint）。如果外部服務掛了，每個命中的規則都會等待逾時 — 大量規則命中時 goroutine 積壓。&lt;/p>
&lt;p>熔斷器包在 rule engine 的「執行外部動作」環節：連續 5 次外部呼叫失敗 → 熔斷 → 後續規則命中不再嘗試外部呼叫、改寫本地 log → 30 秒後探測一次 → 外部服務恢復 → 恢復正常呼叫。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>被動的流量控制 → &lt;a href="https://tarrragon.github.io/blog/devops/03-traffic-management/backpressure/" data-link-title="背壓機制" data-link-desc="下游處理慢時上游怎麼減速 — 有限 buffer &amp;#43; 回壓訊號的設計、和 rate limit 的區別">背壓機制&lt;/a>&lt;/li>
&lt;li>主動的速率限制 → &lt;a href="https://tarrragon.github.io/blog/devops/03-traffic-management/rate-limiting/" data-link-title="Rate Limiting" data-link-desc="主動限制每個來源的請求速率 — per-client vs global、token bucket vs sliding window、優先級豁免">Rate Limiting&lt;/a>&lt;/li>
&lt;li>不同工作負載的資源隔離 → &lt;a href="https://tarrragon.github.io/blog/devops/03-traffic-management/bulkhead/" data-link-title="Bulkhead 隔離" data-link-desc="不同工作負載的資源池隔離 — 一個功能過載不拖垮其他功能的隔艙設計">Bulkhead 隔離&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>熔斷器保護的是「呼叫外部依賴」的路徑。當外部依賴（資料庫、第三方 API、通知服務）持續失敗時，熔斷器讓後續的呼叫立即失敗（回傳預設值或錯誤），而非每次都等待逾時。等待逾時的代價是佔住 goroutine / thread 不釋放，積累到一定數量就拖垮整個服務。</p>
<h2 id="三狀態模型">三狀態模型</h2>
<h3 id="closed正常">Closed（正常）</h3>
<p>所有呼叫正常通過。熔斷器記錄成功和失敗的計數。</p>
<h3 id="open熔斷">Open（熔斷）</h3>
<p>當失敗率或連續失敗次數超過閾值時，熔斷器進入 open 狀態。此後所有呼叫<strong>立即回傳錯誤</strong>，不實際呼叫外部依賴。</p>
<p>Open 狀態持續固定時間（如 30 秒），時間到後進入 half-open。</p>
<h3 id="half-open探測">Half-open（探測）</h3>
<p>允許少量呼叫（如 1 個）實際通過到外部依賴。如果成功 → 回到 closed；如果失敗 → 回到 open（重設計時器）。</p>
<p>Half-open 的目的是自動探測依賴是否恢復，不需要人工介入。</p>
<h2 id="熔斷判斷條件">熔斷判斷條件</h2>
<table>
  <thead>
      <tr>
          <th>條件</th>
          <th>適用場景</th>
          <th>參數</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>連續 N 次失敗</td>
          <td>依賴完全不可用</td>
          <td>N = 5-10</td>
      </tr>
      <tr>
          <td>失敗率 &gt; X%</td>
          <td>依賴間歇性失敗</td>
          <td>X = 50%，統計窗口 = 10 秒</td>
      </tr>
      <tr>
          <td>平均延遲 &gt; Y ms</td>
          <td>依賴變慢但未失敗</td>
          <td>Y = 依據 SLA 設定</td>
      </tr>
  </tbody>
</table>
<p>「失敗」的定義需要明確：HTTP 5xx 是失敗、4xx 通常不是（client 的問題）、timeout 是失敗、connection refused 是失敗。</p>
<h2 id="熔斷時的-fallback">熔斷時的 fallback</h2>
<p>熔斷觸發後，呼叫端收到的是「快速失敗」而非逾時。呼叫端需要有 fallback 策略：</p>
<table>
  <thead>
      <tr>
          <th>依賴</th>
          <th>Fallback</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>通知服務（Slack webhook）</td>
          <td>記錄到本地 log、恢復後補發</td>
      </tr>
      <tr>
          <td>外部 API（enrichment）</td>
          <td>回傳無 enrichment 的原始資料</td>
      </tr>
      <tr>
          <td>認證服務</td>
          <td>用本地 cache 的 token 驗證（短暫降級）</td>
      </tr>
  </tbody>
</table>
<p>沒有 fallback 的依賴被熔斷 = 對應功能完全不可用。熔斷器保護的是「不讓不可用的功能拖垮整個服務」。</p>
<h2 id="監控系統的應用">監控系統的應用</h2>
<p><a href="/blog/monitoring/04-collector/" data-link-title="模組四：Collector 設計" data-link-desc="收 → 驗 → 存 → 查 → 觸發的完整鏈路 — Go 單一 binary、可插拔 Storage Backend、rule engine">Collector</a> 的 rule engine 在規則命中時可能呼叫外部服務（Slack webhook、HTTP POST 到 alert endpoint）。如果外部服務掛了，每個命中的規則都會等待逾時 — 大量規則命中時 goroutine 積壓。</p>
<p>熔斷器包在 rule engine 的「執行外部動作」環節：連續 5 次外部呼叫失敗 → 熔斷 → 後續規則命中不再嘗試外部呼叫、改寫本地 log → 30 秒後探測一次 → 外部服務恢復 → 恢復正常呼叫。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>被動的流量控制 → <a href="/blog/devops/03-traffic-management/backpressure/" data-link-title="背壓機制" data-link-desc="下游處理慢時上游怎麼減速 — 有限 buffer &#43; 回壓訊號的設計、和 rate limit 的區別">背壓機制</a></li>
<li>主動的速率限制 → <a href="/blog/devops/03-traffic-management/rate-limiting/" data-link-title="Rate Limiting" data-link-desc="主動限制每個來源的請求速率 — per-client vs global、token bucket vs sliding window、優先級豁免">Rate Limiting</a></li>
<li>不同工作負載的資源隔離 → <a href="/blog/devops/03-traffic-management/bulkhead/" data-link-title="Bulkhead 隔離" data-link-desc="不同工作負載的資源池隔離 — 一個功能過載不拖垮其他功能的隔艙設計">Bulkhead 隔離</a></li>
</ul>
]]></content:encoded></item><item><title>Stateful 資源保護與跨服務依賴表達</title><link>https://tarrragon.github.io/blog/infra/05-core-services/stateful-protection-dependency/</link><pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/infra/05-core-services/stateful-protection-dependency/</guid><description>&lt;p>核心服務寫進 IaC 之後，stateful 資源需要一套與 stateless 截然不同的保護與操作規範。資料庫、裝了正式資料的 S3 bucket、持久化 volume 這類資源的共同特性是：重建代價極高甚至不可逆。運算節點掛了重開一台，資料刪了就是刪了。這個差別會傳導到 IaC 的描述方式、變更的審查強度、以及 drift 的處理策略。&lt;/p>
&lt;p>本篇同時處理服務之間依賴的表達方式 — output 與 data source — 因為依賴表達直接影響 stateful 資源的爆炸半徑：同一份 state 裡的資料庫跟運算綁在一起 apply，還是拆成獨立 state 各自演進，決定了一次 apply 失敗會波及多少資源。&lt;/p>
&lt;h2 id="stateful-資源的保護策略">stateful 資源的保護策略&lt;/h2>
&lt;p>stateful 資源的 IaC 描述要把「保護狀態」當成第一類需求，而非事後補上的選項。保護的三個面向 — 可用性、可還原性、防誤刪 — 各自對應不同的機制，混在一起談會讓判斷失焦。&lt;/p>
&lt;h3 id="multi-az-的職責邊界">multi-AZ 的職責邊界&lt;/h3>
&lt;p>multi-AZ 用一個布林屬性開啟，背後是 RDS 在另一個可用區維護同步副本。它承擔的是可用性：主庫所在的可用區故障時，RDS 自動 failover 到 standby，服務在秒級到一兩分鐘的窗口後恢復。&lt;/p>
&lt;p>multi-AZ 的邊界要明確界定，因為把它當成超出職責的工具會在事故裡踩空：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>standby 是熱備不可讀&lt;/strong>。multi-AZ 的 standby 不接受任何查詢流量，所以它不提供讀取擴展。要分攤讀流量得另開 read replica，這是另一個資源、另一個端點、另一套複寫延遲要管。&lt;/li>
&lt;li>&lt;strong>failover 有切換窗口&lt;/strong>。切換期間應用的資料庫連線會中斷、需要重連。應用層如果沒有處理連線中斷的重試邏輯，failover 就會變成一段可見的服務中斷，而非透明切換。&lt;/li>
&lt;li>&lt;strong>它不防邏輯損壞&lt;/strong>。誤刪一張 table、一筆錯誤的批次 UPDATE、一段有 bug 的 migration script — 這些操作會同步複製到 standby。multi-AZ 防的是硬體與可用區故障，邏輯損壞的防線是備份與時間點還原（PITR）。&lt;/li>
&lt;/ul>
&lt;p>這三條邊界說明 multi-AZ 和 backup 的職責正交：前者解可用性，後者解可還原性。兩者要分別配置、分別驗證。成本參考：multi-AZ RDS 的費用約為 single-AZ 的兩倍（standby instance 按相同規格計費）。這筆費用對應的能力是可用區故障時的分鐘級自動 failover——判斷值不值得時，用主庫所承載的服務停機每小時的商業代價來衡量。&lt;/p>
&lt;h3 id="備份保留與時間點還原">備份保留與時間點還原&lt;/h3>
&lt;p>backup 用保留天數與備份視窗描述。RDS 依此每日自動快照並保留交易日誌，以支援還原到任意時間點（PITR）。自動備份的保留上限是 35 天，更長的留存要靠手動快照或匯出到 S3 自行管理。&lt;/p>
&lt;p>&lt;code>backup_retention_period&lt;/code> 取多少天，以 RPO（Recovery Point Objective）與合規要求反推。RPO 問的是「出事時最多能接受遺失多久的資料」— PITR 能還原到最近 5 分鐘內的時間點，但前提是自動備份有開、交易日誌有保留。保留天數決定的是「能回溯多遠」：14 天是 AWS RDS 自動備份 35 天上限的保守折衷，足以涵蓋多數營運場景下「發現問題到決定還原」的時間差；受監理的服務往 30 天推，以滿足稽核追溯窗口。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-hcl" data-lang="hcl">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="k">resource&lt;/span> &lt;span class="s2">&amp;#34;aws_db_instance&amp;#34; &amp;#34;primary&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="n"> multi_az&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kt">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="n"> backup_retention_period&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="m">14&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="n"> backup_window&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;03:00-04:00&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="n"> deletion_protection&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kt">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="n"> skip_final_snapshot&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kt">false&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="n"> final_snapshot_identifier&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;app-prod-final-${formatdate(&amp;#34;YYYYMMDD&amp;#34;, timestamp())}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>備份視窗選在流量低谷（如 UTC 凌晨），避免快照 IO 跟尖峰流量競爭。手動快照用獨立資源描述，常見用途是重大變更前的保險點 — 大版本升級、schema migration、或任何會改變資料結構的操作。&lt;/p>
&lt;h3 id="刪除保護與-final-snapshot">刪除保護與 final snapshot&lt;/h3>
&lt;p>&lt;code>deletion_protection = true&lt;/code> 讓 &lt;code>terraform destroy&lt;/code> 無法直接刪除這個 instance — 要先用另一次 apply 把保護關掉，這一步本身就會出現在 plan 裡、被 review 攔住。&lt;code>skip_final_snapshot = false&lt;/code> 確保即使確實要刪，也會先拍一份最終快照。兩者搭配是正式資料庫的硬性下限。&lt;/p>
&lt;p>該在 review 攔下的訊號是：正式環境的 stateful 資源若 &lt;code>backup_retention_period&lt;/code> 為 0 或 &lt;code>deletion_protection&lt;/code> 為 false，代表狀態保護沒有寫進程式碼。把這些屬性視為正式資料庫的預設值，而非可調的偏好。&lt;/p>
&lt;p>S3 bucket 的保護同理但機制不同。versioning 讓覆寫或刪除的物件可以回到先前版本；MFA delete 要求刪除前提供第二因素驗證；lifecycle rule 控制舊版本的保留時間 — 這三者分別對應「可還原」「防誤刪」「控成本」三個職責，見&lt;a href="https://tarrragon.github.io/blog/infra/05-core-services/storage-s3/" data-link-title="儲存上 IaC — S3 bucket 的安全與生命週期" data-link-desc="S3 bucket 的加密、版本控制、公開存取封鎖、生命週期規則、bucket policy 與事件通知怎麼寫進 IaC，讓儲存的安全與成本防線可審查可追蹤">儲存（S3）&lt;/a>。&lt;/p>
&lt;h3 id="跨-region-災難復原的邊界">跨 region 災難復原的邊界&lt;/h3>
&lt;p>multi-AZ 解的是可用區級故障 — 單一資料中心出問題時，同 region 的另一個可用區接手。跨 region 的災難復原（cross-region read replica、S3 cross-region replication、Route 53 failover routing）屬於更高級的可用性投資，解的是整個 region 不可用的極端情境。它的成本與複雜度顯著上升：跨 region 複寫有延遲、failover routing 需要健康檢查與 DNS TTL 配合、兩個 region 的 infra 要各自維護。多數服務在單 region 的 multi-AZ + 備份做完之後再評估是否需要跨 region，依據是業務的 RTO（Recovery Time Objective）對 region 級故障的容忍度。&lt;/p></description><content:encoded><![CDATA[<p>核心服務寫進 IaC 之後，stateful 資源需要一套與 stateless 截然不同的保護與操作規範。資料庫、裝了正式資料的 S3 bucket、持久化 volume 這類資源的共同特性是：重建代價極高甚至不可逆。運算節點掛了重開一台，資料刪了就是刪了。這個差別會傳導到 IaC 的描述方式、變更的審查強度、以及 drift 的處理策略。</p>
<p>本篇同時處理服務之間依賴的表達方式 — output 與 data source — 因為依賴表達直接影響 stateful 資源的爆炸半徑：同一份 state 裡的資料庫跟運算綁在一起 apply，還是拆成獨立 state 各自演進，決定了一次 apply 失敗會波及多少資源。</p>
<h2 id="stateful-資源的保護策略">stateful 資源的保護策略</h2>
<p>stateful 資源的 IaC 描述要把「保護狀態」當成第一類需求，而非事後補上的選項。保護的三個面向 — 可用性、可還原性、防誤刪 — 各自對應不同的機制，混在一起談會讓判斷失焦。</p>
<h3 id="multi-az-的職責邊界">multi-AZ 的職責邊界</h3>
<p>multi-AZ 用一個布林屬性開啟，背後是 RDS 在另一個可用區維護同步副本。它承擔的是可用性：主庫所在的可用區故障時，RDS 自動 failover 到 standby，服務在秒級到一兩分鐘的窗口後恢復。</p>
<p>multi-AZ 的邊界要明確界定，因為把它當成超出職責的工具會在事故裡踩空：</p>
<ul>
<li><strong>standby 是熱備不可讀</strong>。multi-AZ 的 standby 不接受任何查詢流量，所以它不提供讀取擴展。要分攤讀流量得另開 read replica，這是另一個資源、另一個端點、另一套複寫延遲要管。</li>
<li><strong>failover 有切換窗口</strong>。切換期間應用的資料庫連線會中斷、需要重連。應用層如果沒有處理連線中斷的重試邏輯，failover 就會變成一段可見的服務中斷，而非透明切換。</li>
<li><strong>它不防邏輯損壞</strong>。誤刪一張 table、一筆錯誤的批次 UPDATE、一段有 bug 的 migration script — 這些操作會同步複製到 standby。multi-AZ 防的是硬體與可用區故障，邏輯損壞的防線是備份與時間點還原（PITR）。</li>
</ul>
<p>這三條邊界說明 multi-AZ 和 backup 的職責正交：前者解可用性，後者解可還原性。兩者要分別配置、分別驗證。成本參考：multi-AZ RDS 的費用約為 single-AZ 的兩倍（standby instance 按相同規格計費）。這筆費用對應的能力是可用區故障時的分鐘級自動 failover——判斷值不值得時，用主庫所承載的服務停機每小時的商業代價來衡量。</p>
<h3 id="備份保留與時間點還原">備份保留與時間點還原</h3>
<p>backup 用保留天數與備份視窗描述。RDS 依此每日自動快照並保留交易日誌，以支援還原到任意時間點（PITR）。自動備份的保留上限是 35 天，更長的留存要靠手動快照或匯出到 S3 自行管理。</p>
<p><code>backup_retention_period</code> 取多少天，以 RPO（Recovery Point Objective）與合規要求反推。RPO 問的是「出事時最多能接受遺失多久的資料」— PITR 能還原到最近 5 分鐘內的時間點，但前提是自動備份有開、交易日誌有保留。保留天數決定的是「能回溯多遠」：14 天是 AWS RDS 自動備份 35 天上限的保守折衷，足以涵蓋多數營運場景下「發現問題到決定還原」的時間差；受監理的服務往 30 天推，以滿足稽核追溯窗口。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">resource</span> <span class="s2">&#34;aws_db_instance&#34; &#34;primary&#34;</span> {
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">  multi_az</span>                  <span class="o">=</span> <span class="kt">true</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">  backup_retention_period</span>   <span class="o">=</span> <span class="m">14</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">  backup_window</span>             <span class="o">=</span> <span class="s2">&#34;03:00-04:00&#34;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="n">  deletion_protection</span>       <span class="o">=</span> <span class="kt">true</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="n">  skip_final_snapshot</span>       <span class="o">=</span> <span class="kt">false</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="n">  final_snapshot_identifier</span> <span class="o">=</span> <span class="s2">&#34;app-prod-final-${formatdate(&#34;YYYYMMDD&#34;, timestamp())}&#34;</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">}</span></span></code></pre></div><p>備份視窗選在流量低谷（如 UTC 凌晨），避免快照 IO 跟尖峰流量競爭。手動快照用獨立資源描述，常見用途是重大變更前的保險點 — 大版本升級、schema migration、或任何會改變資料結構的操作。</p>
<h3 id="刪除保護與-final-snapshot">刪除保護與 final snapshot</h3>
<p><code>deletion_protection = true</code> 讓 <code>terraform destroy</code> 無法直接刪除這個 instance — 要先用另一次 apply 把保護關掉，這一步本身就會出現在 plan 裡、被 review 攔住。<code>skip_final_snapshot = false</code> 確保即使確實要刪，也會先拍一份最終快照。兩者搭配是正式資料庫的硬性下限。</p>
<p>該在 review 攔下的訊號是：正式環境的 stateful 資源若 <code>backup_retention_period</code> 為 0 或 <code>deletion_protection</code> 為 false，代表狀態保護沒有寫進程式碼。把這些屬性視為正式資料庫的預設值，而非可調的偏好。</p>
<p>S3 bucket 的保護同理但機制不同。versioning 讓覆寫或刪除的物件可以回到先前版本；MFA delete 要求刪除前提供第二因素驗證；lifecycle rule 控制舊版本的保留時間 — 這三者分別對應「可還原」「防誤刪」「控成本」三個職責，見<a href="/blog/infra/05-core-services/storage-s3/" data-link-title="儲存上 IaC — S3 bucket 的安全與生命週期" data-link-desc="S3 bucket 的加密、版本控制、公開存取封鎖、生命週期規則、bucket policy 與事件通知怎麼寫進 IaC，讓儲存的安全與成本防線可審查可追蹤">儲存（S3）</a>。</p>
<h3 id="跨-region-災難復原的邊界">跨 region 災難復原的邊界</h3>
<p>multi-AZ 解的是可用區級故障 — 單一資料中心出問題時，同 region 的另一個可用區接手。跨 region 的災難復原（cross-region read replica、S3 cross-region replication、Route 53 failover routing）屬於更高級的可用性投資，解的是整個 region 不可用的極端情境。它的成本與複雜度顯著上升：跨 region 複寫有延遲、failover routing 需要健康檢查與 DNS TTL 配合、兩個 region 的 infra 要各自維護。多數服務在單 region 的 multi-AZ + 備份做完之後再評估是否需要跨 region，依據是業務的 RTO（Recovery Time Objective）對 region 級故障的容忍度。</p>
<p>跨 region 的 infra 投資在 B2B SaaS 的合約義務下更容易成立。<a href="/blog/backend/09-performance-capacity/cases/genesys-dynamodb-99999-availability/" data-link-title="9.C24 Genesys：用 DynamoDB 在 15 region 跑出 99.999% 可用性" data-link-desc="Genesys 客服平台用 DynamoDB 為預設資料層、跨 15 主 region &#43; 5 衛星 region、達成 12 個月 99.999% 可用性">Genesys 的客服平台跨 15 個 region 用 DynamoDB 達成 99.999% 可用性</a>——年停機只有 5 分鐘。對 B2B SaaS 來說，客戶服務中斷等於客戶的終端使用者打不通電話，可用性是合約義務而非行銷敘述。infra 層的判斷依據是：multi-AZ 不夠用（業務需要跨 region failover）的情況通常由合約 SLA 驅動，而非技術判斷驅動。</p>
<h2 id="stateful-與-stateless-的操作差異">stateful 與 stateless 的操作差異</h2>
<p>stateful 與 stateless 資源的根本差別在重建代價。這個差別傳導到三個操作後果，每一個都影響日常的 PR review 與 apply 流程。</p>
<h3 id="刪除保護的必要性">刪除保護的必要性</h3>
<p>stateless 資源（ECS service、ALB、無狀態運算）重建只是換一組新實例，幾分鐘內恢復、沒有資料損失，所以它們可以被頻繁地 destroy 與 recreate — 這是 IaC 最擅長的對象。stateful 資源重建意味著資料遺失或漫長的還原，代價可能是數小時的停機與不可逆的損失。開啟 deletion protection 讓「不小心 destroy」需要先顯式關閉保護這一步，多一道人為確認。</p>
<h3 id="drift-容忍度">drift 容忍度</h3>
<p>stateless 資源的 drift 可以靠重建抹平 — apply 一次就回到程式碼的狀態，副作用只是新實例的短暫滾動更新。stateful 資源的 drift 要謹慎處理，因為 IaC 的「修正回程式碼狀態」動作可能觸發重啟甚至重建。</p>
<p>一個常見的情境：某人手動改了 RDS 的 parameter group，Terraform plan 顯示要把它改回程式碼的版本。這個改回動作是 <code>update in-place</code>（改設定、不重建）還是 <code>replace</code>（先刪後建），取決於哪個參數被改了 — 某些 parameter 的修改需要重啟，而某些需要整個 instance 重建。判讀方式是先跑 plan、看 drift 修正的結果，<code>update in-place</code> 通常安全（可能觸發重啟），<code>replace</code> 對資料庫意味著先刪後建，在 prod 上需要額外的確認。</p>
<h3 id="變更審查強度">變更審查強度</h3>
<p>改動 stateful 資源的 plan 輸出要逐行看，特別警惕任何顯示為 <code>replace</code>（<code>-/+</code>）或標記 <code>forces replacement</code> 的項目。某些欄位的改動看似無害但會觸發 replace：</p>
<table>
  <thead>
      <tr>
          <th>欄位</th>
          <th>預期行為</th>
          <th>實際行為</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>RDS <code>identifier</code> 改名</td>
          <td>改個名字而已</td>
          <td>forces replacement</td>
      </tr>
      <tr>
          <td>RDS <code>engine_version</code> 大版本</td>
          <td>升級引擎版本</td>
          <td>可能 replace 或 in-place</td>
      </tr>
      <tr>
          <td>RDS <code>storage_type</code> 變更</td>
          <td>換儲存類型</td>
          <td>部分組合 forces replacement</td>
      </tr>
      <tr>
          <td>S3 bucket <code>bucket</code> 改名</td>
          <td>改個名字而已</td>
          <td>forces replacement</td>
      </tr>
  </tbody>
</table>
<p>Review 時看到 stateful 資源出現 <code>forces replacement</code>，在 prod 路徑上幾乎都該先暫停、確認回退路徑（手動快照是否已拍）再決定是否繼續。常見做法是把這個差別寫進流程：stateful 資源的變更走更嚴格的 PR review 與分階段套用（先在 dev apply 驗證、確認是 in-place 後再推 prod），自動化護欄在<a href="/blog/infra/07-infra-as-pr/" data-link-title="模組七：infra 走 PR 流程與自動化護欄" data-link-desc="infra 變更走 PR → plan → review diff → 合併 → apply，配 fmt / validate / tflint / checkov / tfsec 與 Atlantis 自動化，讓基礎設施可審查、可回溯、可交接">模組七：infra 走 PR 流程</a>展開。</p>
<h2 id="服務之間的依賴怎麼表達">服務之間的依賴怎麼表達</h2>
<p>服務間依賴用 output 與 data source 表達，讓引用關係成為程式碼裡可追蹤的邊，而非靠人記憶的隱性約定。引用方式的選擇直接影響 state 的大小與爆炸半徑。</p>
<h3 id="同-state-內的引用">同 state 內的引用</h3>
<p>同一個 state 內，直接引用資源屬性即可建立依賴。運算資源引用資料庫的端點，IaC 自動推導出「資料庫先於運算」的邊，也讓端點變更時上層自動取得新值：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">resource</span> <span class="s2">&#34;aws_ecs_task_definition&#34; &#34;api&#34;</span> {
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">  container_definitions</span> <span class="o">=</span> <span class="k">jsonencode</span><span class="p">([</span>{
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">    environment</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">      { name</span> <span class="o">=</span><span class="n"> &#34;DB_HOST&#34;, value</span> <span class="o">=</span> <span class="k">aws_db_instance</span><span class="p">.</span><span class="k">primary</span><span class="p">.</span><span class="k">endpoint</span> }
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">  }<span class="p">])</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">}</span></span></code></pre></div><p>同 state 引用的好處是依賴圖最完整 — apply 一次就把所有引用解析到正確的值。代價是 state 越大、單次 apply 的爆炸半徑越大。一份包含網路、資料庫、運算、LB 的 state，一次 apply 失敗可能讓所有資源處於半完成狀態。</p>
<h3 id="跨-state-的-data-source">跨 state 的 data source</h3>
<p>跨 state（例如網路地基與核心服務分屬不同 Terraform state，呼應<a href="/blog/infra/04-environment-separation/" data-link-title="模組四：環境分離與模組化" data-link-desc="dev / staging / prod 切分、目錄結構 vs workspace、用可重用 module 避免環境漂移">模組四：環境分離與模組化</a>的拆分）時，下游用 data source 唯讀地讀取上游已建立的資源：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-hcl" data-lang="hcl"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">data</span> <span class="s2">&#34;aws_vpc&#34; &#34;main&#34;</span> {
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">  tags</span> <span class="o">=</span><span class="n"> { Name</span> <span class="o">=</span> <span class="s2">&#34;app-${var.env}&#34;</span> }
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">}
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">data</span> <span class="s2">&#34;aws_subnets&#34; &#34;private&#34;</span> {
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="k">filter</span> {
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">    name</span>   <span class="o">=</span> <span class="s2">&#34;vpc-id&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">    values</span> <span class="o">=</span> <span class="p">[</span><span class="k">data</span><span class="p">.</span><span class="k">aws_vpc</span><span class="p">.</span><span class="k">main</span><span class="p">.</span><span class="k">id</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  }
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">  tags</span> <span class="o">=</span><span class="n"> { tier</span> <span class="o">=</span> <span class="s2">&#34;private&#34;</span> }
</span></span><span class="line"><span class="ln">11</span><span class="cl">}</span></span></code></pre></div><p>下游查詢上游的 VPC 與 subnet，取得 ID 來放置自己的資源，而不複製貼上硬編碼的值。</p>
<h3 id="同-state-vs-跨-state-的取捨">同 state vs 跨 state 的取捨</h3>
<p>兩種方式的取捨在耦合與隔離之間：</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>同 state 引用</th>
          <th>跨 state data source</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>依賴圖</td>
          <td>完整、自動推導</td>
          <td>跨 state 邊界，需約定上游先 apply</td>
      </tr>
      <tr>
          <td>爆炸半徑</td>
          <td>state 越大、單次 apply 越大</td>
          <td>各 state 獨立、爆炸半徑小</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>少量緊密耦合的資源</td>
          <td>地基層與服務層分離</td>
      </tr>
      <tr>
          <td>drift 風險</td>
          <td>低（引用自動追蹤）</td>
          <td>中（上游重建後 data source 可能查不到）</td>
      </tr>
  </tbody>
</table>
<p>用 grep 搜一遍核心服務的 HCL：如果出現大量寫死的 subnet ID 或 VPC ID，代表該用 data source 而沒用。這些硬編碼是日後上游重建時 drift 與 broken reference 的來源。把它們換成 data source，依賴關係才會在程式碼裡顯性化、可被工具與 review 看見。</p>
<p>data source 查詢的可靠性取決於查詢條件的穩定度。用 <code>tags</code> 查比用 <code>Name</code> 查更穩 — tag 是自己定義的、可控的值，而某些資源的 Name 可能在重建時改變。用 <code>terraform_remote_state</code> data source 直接讀上游的 state output 是最精確的方式，但它把兩份 state 的 backend 設定耦合在一起，上游搬 state 時下游也要跟著改。在團隊規模小、state 拆分不多的階段，<code>terraform_remote_state</code> 的耦合代價通常可接受；團隊變大後，用 tag-based data source 或 SSM Parameter Store 當中間層，能讓上下游各自獨立演進。</p>
<h2 id="跨分類引用">跨分類引用</h2>
<ul>
<li>→ <a href="/blog/infra/03-network-foundation/" data-link-title="模組三：網路地基 — VPC 與分層" data-link-desc="VPC、public / private subnet 切分、route table、NAT、security group 設計">模組三：網路地基</a>：核心服務落在哪些 subnet、security group 怎麼引用</li>
<li>→ <a href="/blog/infra/04-environment-separation/" data-link-title="模組四：環境分離與模組化" data-link-desc="dev / staging / prod 切分、目錄結構 vs workspace、用可重用 module 避免環境漂移">模組四：環境分離與模組化</a>：跨 state 的拆分策略</li>
<li>→ <a href="/blog/infra/07-infra-as-pr/" data-link-title="模組七：infra 走 PR 流程與自動化護欄" data-link-desc="infra 變更走 PR → plan → review diff → 合併 → apply，配 fmt / validate / tflint / checkov / tfsec 與 Atlantis 自動化，讓基礎設施可審查、可回溯、可交接">模組七：infra 走 PR 流程</a>：stateful 變更的自動化護欄</li>
</ul>
]]></content:encoded></item><item><title>Dependabot</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/dependabot/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/dependabot/</guid><description>&lt;p>Dependabot 是 GitHub 內建的 &lt;em>依賴更新自動化&lt;/em> 工具、原為 Dependabot Inc.、2019 年被 GitHub 收購後改為 GitHub native feature、目前 public repo 免費、private repo 部分功能 (Alerts / Security Update) 也免費、Version Update 跟進階治理納入 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security&lt;/a> 套餐。它做三件事：&lt;em>Dependabot version updates&lt;/em>（定期 PR 升級依賴到最新 compatible 版本）、&lt;em>Dependabot security updates&lt;/em>（CVE 觸發的緊急 PR 升級到 fix version）、&lt;em>Dependabot alerts&lt;/em>（看到漏洞列在 Security tab、不一定自動 PR）。它的設計目標 &lt;em>狹窄而深&lt;/em> — 只做 GitHub repo 的依賴 PR 自動化、不做容器掃描、不做 IaC 掃描、不跨 SCM。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Dependabot 的核心定位是 &lt;em>把依賴升級從人工 ritual 變成 PR review 工作流&lt;/em>。它把「找新版」「跑 manifest update」「開 PR」「附 release note」自動化、剩下的 &lt;em>是否合併&lt;/em> 留給人類 / CI 判斷。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &amp;#43; Code (SAST) &amp;#43; Container &amp;#43; IaC &amp;#43; Cloud (CSPM)、Reachability analysis">Snyk&lt;/a> 看似重疊 — 兩者都會自動發升級 PR — 但 Snyk 是 &lt;em>跨 SCM + 多 stack&lt;/em>（GitHub / GitLab / Bitbucket、SCA + 容器 + IaC + Code）、Dependabot 是 &lt;em>GitHub-only + 純依賴&lt;/em>。多數組織選一個、混用兩者會在同一個 manifest 上各自開 PR、造成 noise。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &amp;#43; Secret Scanning &amp;#43; Dependency Review &amp;#43; Dependabot、跟 PR / Security tab 深度整合">GHAS&lt;/a> 的關係比較細：Dependabot Alerts 跟 Security Updates 本身是 GHAS &lt;em>Dependabot&lt;/em> 子模組的核心、但功能上 &lt;em>Alerts 對所有 repo 免費&lt;/em>、Security Update 也免費自動發 PR、Version Update 也免費；GHAS 提供的是 &lt;em>Dependency Review&lt;/em>（PR-time gate、阻擋 PR 引入新漏洞依賴）、&lt;em>Security Overview&lt;/em>（org-wide dashboard）跟 enterprise-level 控制。Dependabot 是 &lt;em>background PR 工廠&lt;/em>、GHAS Dependency Review 是 &lt;em>PR-time blocker&lt;/em>、兩者互補不重疊。&lt;/p></description><content:encoded><![CDATA[<p>Dependabot 是 GitHub 內建的 <em>依賴更新自動化</em> 工具、原為 Dependabot Inc.、2019 年被 GitHub 收購後改為 GitHub native feature、目前 public repo 免費、private repo 部分功能 (Alerts / Security Update) 也免費、Version Update 跟進階治理納入 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a> 套餐。它做三件事：<em>Dependabot version updates</em>（定期 PR 升級依賴到最新 compatible 版本）、<em>Dependabot security updates</em>（CVE 觸發的緊急 PR 升級到 fix version）、<em>Dependabot alerts</em>（看到漏洞列在 Security tab、不一定自動 PR）。它的設計目標 <em>狹窄而深</em> — 只做 GitHub repo 的依賴 PR 自動化、不做容器掃描、不做 IaC 掃描、不跨 SCM。</p>
<h2 id="服務定位">服務定位</h2>
<p>Dependabot 的核心定位是 <em>把依賴升級從人工 ritual 變成 PR review 工作流</em>。它把「找新版」「跑 manifest update」「開 PR」「附 release note」自動化、剩下的 <em>是否合併</em> 留給人類 / CI 判斷。這跟 <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> 看似重疊 — 兩者都會自動發升級 PR — 但 Snyk 是 <em>跨 SCM + 多 stack</em>（GitHub / GitLab / Bitbucket、SCA + 容器 + IaC + Code）、Dependabot 是 <em>GitHub-only + 純依賴</em>。多數組織選一個、混用兩者會在同一個 manifest 上各自開 PR、造成 noise。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS</a> 的關係比較細：Dependabot Alerts 跟 Security Updates 本身是 GHAS <em>Dependabot</em> 子模組的核心、但功能上 <em>Alerts 對所有 repo 免費</em>、Security Update 也免費自動發 PR、Version Update 也免費；GHAS 提供的是 <em>Dependency Review</em>（PR-time gate、阻擋 PR 引入新漏洞依賴）、<em>Security Overview</em>（org-wide dashboard）跟 enterprise-level 控制。Dependabot 是 <em>background PR 工廠</em>、GHAS Dependency Review 是 <em>PR-time blocker</em>、兩者互補不重疊。</p>
<p>跟 <a href="https://docs.renovatebot.com/">Renovate</a>（Mend 維護的 OSS）的差異：Renovate 配置更彈性、跨 SCM、支援 ecosystem 數量多（含 Helm chart、Docker tag、ArgoCD 等）、Grouped Updates 規則更細；Dependabot 整合 GitHub 原生 UI（Security tab、Dependency graph、PR diff）更深、設定簡單。需要 <em>跨 SCM</em> 或 <em>Helm / ArgoCD / 自訂 ecosystem</em> 走 Renovate；單純 GitHub-only 加 npm / Maven / pip 等主流 ecosystem、Dependabot 配置成本更低。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Dependabot 在 supply chain 防護裡承擔哪一段（背景 PR 升級）、哪些不在它責任內（容器掃描、IaC 掃描、PR-time gate）</li>
<li><code>dependabot.yml</code> 的關鍵配置面：ecosystem、schedule、open-pull-requests-limit、groups、reviewers</li>
<li>Version Update vs Security Update vs Alerts 三個功能何時開、PR noise 怎麼控制</li>
<li>Auto-merge 政策的邊界：哪種更新可以全自動、哪種要保留 human approval</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷一個 repo 的 Dependabot 配置是否健康、最少看四件事：</p>
<ul>
<li><strong><code>dependabot.yml</code> 配置</strong>：repo 是否有 <code>.github/dependabot.yml</code>、ecosystem 是否覆蓋所有 manifest（npm / Maven / pip / Docker / GitHub Actions / Terraform）、<code>directory</code> 路徑對不對（monorepo 各 sub-package 是否獨立配置）</li>
<li><strong>Update Schedule</strong>：<code>schedule.interval</code> 是 daily / weekly / monthly、<code>open-pull-requests-limit</code> 是否合理（預設 5、太低會卡住 backlog、太高會 PR noise）、Grouped Updates 是否啟用（減少 minor / patch PR 數量）</li>
<li><strong>Auto-merge 政策</strong>：branch protection 是否設「CI green + required reviewer」、auto-merge 是否限定 <em>patch + minor</em> 自動、<em>major</em> 強制 human review、production 跟 staging branch 是否有差異化規則</li>
<li><strong>Token 治理</strong>：repo secrets 是否被 Dependabot PR 誤用、Dependabot secrets（私有 registry credential）是否獨立配置、PR 觸發的 Actions 是否假設 read-only token</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">Supply Chain Integrity</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong><code>dependabot.yml</code> 是版控的配置檔</strong>：放在 <code>.github/dependabot.yml</code>、跟 manifest 同 repo、所有變更走 PR review。不在 GitHub UI 直接改 — UI 只能 <em>啟用 / 停用</em> Dependabot 本身、細節必須 commit 進 repo。Monorepo 結構（例：<code>/services/api</code>、<code>/services/web</code> 各自 <code>package.json</code>）每個 sub-package 寫一個 entry、<code>directory</code> 指到 sub-package 根目錄、<code>package-ecosystem</code> 標 manifest 類型。<code>schedule.interval</code> 一般 weekly 開始、daily 適合高活躍度團隊但 PR noise 高、monthly 適合穩定 lib 但 CVE 延遲風險高。</p>
<p><strong>Version Update vs Security Update 分開</strong>：Version Update 是 <em>定期掃 manifest 看有沒有 newer compatible 版本</em>、不分 CVE、是 hygiene 工作；Security Update 是 <em>Dependabot 偵測到 CVE 且 manifest 指到 vulnerable 範圍時自動發 PR 升級到 fix version</em>、是 incident 工作。多數組織開 Security Update 全 repo + 選擇性開 Version Update（核心服務開、archived repo 不開）— 避免 PR noise 淹沒緊急 PR。Security Update 預設啟用、Version Update 要 explicit 在 <code>dependabot.yml</code> 寫 entry 才會跑。</p>
<p><strong>Grouped Updates</strong>：2023 推出、單一 PR 含多個 minor / patch 升級（例：一個 PR 升 10 個 npm package）、PR 數量從 10 個降到 1 個。配置在 <code>dependabot.yml</code> 的 <code>groups</code> 區、可以按 dependency name pattern（例：<code>@types/*</code> 一組、<code>eslint*</code> 一組）或 update-type（<code>patch</code> / <code>minor</code> 分組）。Major version 仍分開 PR — 因 breaking change 風險、需要單獨 review。Grouped Updates 配 auto-merge 是 <em>minor / patch 全自動</em> 的標準配置。</p>
<p><strong>Auto-merge 是 PR 級、不是 commit 級</strong>：Dependabot 發 PR、搭配 GitHub branch protection 設「CI green + 1 approver」就 auto-merge — GitHub <code>gh pr merge --auto</code> 或 Actions workflow（<code>peter-evans/enable-pull-request-automerge</code>）都行。production 環境應該保留 human approval（至少對 major version）、staging / dev 可以全自動。常見模式：staging branch 全自動合（patch + minor）+ 自動 deploy；production branch 走 staging → cherry-pick / promote 流程、human approve。</p>
<p><strong>Reviewer / Assignee / Label 自動標記</strong>：<code>dependabot.yml</code> 的 <code>reviewers</code> / <code>assignees</code> / <code>labels</code> 欄位讓 Dependabot 開 PR 時自動標 reviewer 跟 label。實務上配 <code>labels: [&quot;dependencies&quot;]</code> 讓 Dependabot PR 在 PR list 跟一般 feature PR 分開、CI workflow 可以針對 <code>dependencies</code> label 跑特化 lint（例：跑完整 e2e、不只 unit test）。</p>
<p><strong>Token 治理</strong>：Dependabot PR 跑 GitHub Actions 時、<code>secrets.GITHUB_TOKEN</code> 是 <em>read-only</em>（GitHub 設計上限制、防 PR 觸發 supply chain attack）— 這代表 Dependabot PR 不能跑需要 write permission 的 job（推 image / 改 status / comment）。需要的話用 <code>pull_request_target</code> event（用 base branch 的 workflow + 完整 secrets）、但這也是 supply chain attack 高風險面、必須 <em>最少 permission</em>。私有 registry credential（npm private registry token、Maven private repo password）用 <em>Dependabot secrets</em>（org / repo level）配置、跟 GitHub Actions secrets 是 <em>不同 namespace</em>、不會互相讀到。</p>
<p><strong>跟 GHAS Dependency Review 搭配</strong>：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Dependency Review</a> 在 PR-time 看 manifest diff 阻擋 <em>引入新漏洞依賴</em>、Dependabot Security Update 在 background <em>升級舊有漏洞依賴</em>、兩個方向互補。production repo 標準配置：GHAS Dependency Review 設 high severity block + Dependabot Security Update 全開 + Dependabot Version Update 選擇性開。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Dependabot</th>
          <th>Snyk</th>
          <th>Renovate</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SCM 範圍</td>
          <td>GitHub only</td>
          <td>GitHub / GitLab / Bitbucket / Azure DevOps</td>
          <td>GitHub / GitLab / Bitbucket / Azure DevOps / Gitea</td>
      </tr>
      <tr>
          <td>涵蓋面</td>
          <td>純依賴（SCA）</td>
          <td>SCA + 容器 + IaC + Code</td>
          <td>純依賴（SCA）+ Docker tag / Helm / 自訂</td>
      </tr>
      <tr>
          <td>Ecosystem 數量</td>
          <td>主流（npm / Maven / pip / Docker / Actions / Terraform 等 20+）</td>
          <td>主流相近 + 商業資料庫優先</td>
          <td>多（含 Helm / ArgoCD / preCommit / 自訂 regex）</td>
      </tr>
      <tr>
          <td>Grouped Updates</td>
          <td>有（2023+、按 pattern / update-type）</td>
          <td>有（按 type）</td>
          <td>有（規則最細、按 manager / depType / pattern）</td>
      </tr>
      <tr>
          <td>Auto-merge</td>
          <td>走 GitHub branch protection + auto-merge</td>
          <td>Snyk 自家 PR + 走 SCM auto-merge</td>
          <td>內建 <code>automerge</code> 配置、規則細</td>
      </tr>
      <tr>
          <td>漏洞資料庫</td>
          <td>GitHub Advisory Database（公開 + 私有）</td>
          <td>Snyk Intel（商業、揭露快、加入專屬 advisory）</td>
          <td>OSV / NVD / GitHub Advisory（聚合）</td>
      </tr>
      <tr>
          <td>PR 整合深度</td>
          <td>GitHub Security tab / Dependency graph 原生</td>
          <td>Snyk UI 為主、SCM PR 是延伸</td>
          <td>SCM PR 原生、Renovate dashboard issue 集中管理</td>
      </tr>
      <tr>
          <td>設定方式</td>
          <td><code>dependabot.yml</code>（簡單）</td>
          <td>UI + <code>.snyk</code> policy file（漏洞例外）</td>
          <td><code>renovate.json</code>（極彈性、配置複雜）</td>
      </tr>
      <tr>
          <td>商業成本</td>
          <td>GitHub 免費（Version Update / Security Update / Alerts 都免費）</td>
          <td>商業授權（含免費 tier、規模上來付費）</td>
          <td>OSS 免費、Mend 商業版加分析 dashboard</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>GitHub-only + 純依賴 + 設定要簡單</td>
          <td>跨 SCM、要容器 / IaC、商業 advisory 加值</td>
          <td>跨 SCM 或要 Helm / ArgoCD / 自訂 ecosystem</td>
      </tr>
  </tbody>
</table>
<p>選 Dependabot 的核心訴求：<em>GitHub-only</em> + 只要依賴 PR 自動化、不要容器 / IaC scan、配置成本要低、整合 GitHub Security tab。要跨 SCM 或多 stack 走 Snyk、要彈性 ecosystem / Helm chart / ArgoCD 走 Renovate。混用 Dependabot + Snyk 對同一 manifest 自動 PR 會 noise、二選一。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Multi-ecosystem repo</strong>：一個 repo 同時有 npm + Docker + Terraform + GitHub Actions、<code>dependabot.yml</code> 寫四個 entry、各自 schedule。實務常見配置：application 依賴（npm / pip）weekly、base image（Docker）weekly、IaC（Terraform provider）monthly、GitHub Actions（CI workflow）weekly。Actions ecosystem 要特別注意 — Dependabot 升級 <code>uses:</code> 指向的 action version、可以同時 pin commit hash（防 tag re-publish 攻擊）、但 pin hash 後 release note 看不到 — 取捨 <em>安全 vs 可讀性</em>。</p>
<p><strong>Private registry support</strong>：私有 npm registry（GitHub Packages / Artifactory / Nexus）、私有 Maven repo、私有 PyPI mirror、私有 container registry 都要在 <code>dependabot.yml</code> 配置 <code>registries</code> 區、credential 走 Dependabot secrets。Dependabot 從私有 registry 抓 package metadata 跟 release info、否則只能看 public registry、會誤判 internal lib 沒新版。Org-level Dependabot secrets 適合共用 credential、repo-level 適合特殊 credential 隔離。</p>
<p><strong>Self-hosted runner 隔離</strong>：Dependabot PR 觸發的 Actions 預設跑在 GitHub-hosted runner、跟 Dependabot 本身的 sandbox 不同。如果 CI 跑在 self-hosted runner（內網資源 / 大 build cache）、Dependabot PR 也會跑在 self-hosted runner — 要確認 runner 不會被 PR 注入的惡意 manifest 攻擊（npm install 跑 postinstall script 是經典攻擊路徑）。Mitigation：Dependabot PR 用 ephemeral runner（每次新 VM）、隔離 build cache、不掛 sensitive volume。</p>
<p><strong>Auto-merge 風險</strong>：auto-merge 加速合併、但也放寬 <em>攻擊者升級 dep 攻擊我</em> 的窗口。<a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a> 的攻擊路徑就是攻擊者花兩年取得 upstream maintainer 信任、發 release 帶 backdoor — 如果下游 auto-merge 升級、攻擊就直達 production。Mitigation：major version 永不 auto-merge、critical infra dep（auth / crypto / network 函式庫）pin commit hash + 手動 review、auto-merge 範圍縮到 patch + minor + low-criticality dep。</p>
<p><strong>GitHub Actions 跟 Dependabot 互動</strong>：Dependabot PR 觸發的 workflow 預設 <code>GITHUB_TOKEN</code> 是 <em>read-only</em>、<code>secrets.*</code> 是 <em>empty</em>（Dependabot context）— 防止 PR 注入腳本竊取 secret。需要在 Dependabot PR 跑帶 secret 的 job、用 <code>pull_request_target</code> event（workflow 從 base branch 取、有完整 secret）— 但這會 <em>讀 PR 的 code 跑 workflow</em>、必須先 <code>checkout</code> base 然後最小化 PR code 的執行（不跑 PR 的 install script、只跑既有 lint）。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>PR noise 淹沒緊急 PR</strong>：Version Update 全開 + 沒 Grouped Updates、一週 30+ PR — 啟用 <code>groups</code> 按 pattern 分組（<code>@types/*</code> / <code>eslint*</code> / <code>dev-dependencies</code>）、<code>open-pull-requests-limit</code> 設 5、archived repo 關 Version Update</li>
<li><strong>Security Update 沒發 PR</strong>：CVE 公告了但 Dependabot 沒動 — 確認 manifest 真的指到 vulnerable 範圍、<code>dependabot.yml</code> 沒 <code>ignore</code> 該 dependency、Security Updates 在 repo settings 是啟用、Dependency graph 有抓到該 manifest</li>
<li><strong>私有 registry 抓不到</strong>：Dependabot 在私有 npm / Maven repo 失敗 — <code>dependabot.yml</code> 配 <code>registries</code> 區、credential 進 Dependabot secrets（不是 Actions secrets）、URL 跟 token 範圍對齊</li>
<li><strong>Auto-merge 不觸發</strong>：PR 開了 CI 也綠了但沒合 — 確認 branch protection required check 跟 CI workflow 名稱對齊、<code>gh pr merge --auto</code> 在 PR comment / workflow 有觸發、reviewer count 達標</li>
<li><strong>Dependabot PR 跑 Actions 失敗</strong>：PR 的 workflow 報 permission denied — <code>GITHUB_TOKEN</code> 在 Dependabot context read-only、改用 <code>pull_request_target</code> 或拆 job（push secret 的部分跑在 merge 後 main branch event）</li>
<li><strong>Major version 被 auto-merge</strong>：規則沒寫對、major 也自動合進 production — <code>dependabot.yml</code> 的 <code>ignore</code> 加 <code>update-types: [&quot;version-update:semver-major&quot;]</code> 或 auto-merge 條件改 <code>${{ steps.metadata.outputs.update-type == 'version-update:semver-minor' }}</code></li>
<li><strong>Monorepo 漏掃</strong>：<code>/services/api/package.json</code> 沒掃 — <code>dependabot.yml</code> 每個 sub-package 寫一個 entry、<code>directory</code> 指到正確路徑、不是只在 root 一個 entry</li>
<li><strong>GitHub Actions ecosystem 升級拿掉 commit hash pin</strong>：原本 <code>uses: actions/checkout@a12b3c4</code> 被升成 <code>uses: actions/checkout@v5</code> — Dependabot 會 follow 既有 reference 風格、想要 hash pin 設 <code>dependabot.yml</code> 的 ecosystem-level config 但目前限制較多、實務常另用 <a href="https://github.com/suzuki-shunsuke/pinact">pinact</a> 或 Renovate 處理 Actions hash pinning</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨 SCM（GitLab / Bitbucket）</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="https://docs.renovatebot.com/">Renovate</a></td>
      </tr>
      <tr>
          <td>容器 / IaC scan</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a> / <a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a></td>
      </tr>
      <tr>
          <td>Helm / ArgoCD / 自訂 ecosystem</td>
          <td><a href="https://docs.renovatebot.com/">Renovate</a></td>
      </tr>
      <tr>
          <td>PR-time block 引入新漏洞</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Dependency Review</a></td>
      </tr>
      <tr>
          <td>SAST / Code scanning</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Code Scanning</a> / <a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk Code</a></td>
      </tr>
      <tr>
          <td>SBOM 生成 / 簽章</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>（含 Sigstore cosign 整合段落）</td>
      </tr>
      <tr>
          <td>Secret scanning</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS Secret Scanning</a> / GitGuardian</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li><code>dependabot.yml</code> 完整欄位 reference（看 <a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file">GitHub 官方文件</a>）</li>
<li>GitHub Advisory Database 詳細運作（CVE 來源、curation 流程）</li>
<li>GHAS 其他模組（Code Scanning / Secret Scanning / Dependency Review）細節 — 看 <a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GHAS 頁</a></li>
<li>Renovate / Snyk 完整配置 — 看各自 vendor 頁</li>
<li>Container base image 升級的 multi-stage Dockerfile 處理</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Dependabot 沒有自身 vendor-level case、但在 supply chain case 中是 <em>標準 mitigation</em> 或 <em>風險面</em>：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Dependabot 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — Dependabot Security Update 在 Log4Shell 期間自動發 log4j-core 升級 PR、auto-merge 必須有 functional + security 雙重 CI verify、不能單看 build pass</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/github-oauth-2022-token-supply-chain/" data-link-title="7.R7.2.2 GitHub OAuth 2022：第三方 token 供應鏈風險" data-link-desc="第三方整合 token 被竊後，如何形成跨組織存取風險">GitHub OAuth 2022 Token Supply Chain</a></td>
          <td>對照啟示 — Dependabot 自己用 GitHub token、需確認 Dependabot PR 不能讀 production secrets（GitHub 設計上已 read-only / empty secrets）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/circleci-2023-secrets-rotation/" data-link-title="7.R7.2.3 CircleCI 2023：CI secrets 輪替壓力" data-link-desc="工程端點入侵後，CI 平台 secrets 如何成為高風險擴散點">CircleCI 2023 Secrets Rotation</a></td>
          <td>對照啟示 — CI 出事時 Dependabot secrets（私有 registry credential）也要 rotate、不是只 rotate Actions secrets</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/xz-backdoor-2024-open-source-supply-chain/" data-link-title="7.R7.2.4 XZ Backdoor 2024：開源供應鏈長期滲透" data-link-desc="開源維護鏈遭滲透後，為何會直接影響廣泛 Linux 發行流程">XZ Backdoor 2024</a></td>
          <td>對照啟示 — Dependabot auto-merge 隱含 maintainer trust、攻擊者控制 upstream 後升級 = 自動進 production；major 不 auto-merge + 重要 dep pin commit hash</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">7.12 供應鏈完整性與 Artifact 信任</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/github-advanced-security/" data-link-title="GitHub Advanced Security" data-link-desc="GitHub 內建 4 大模組：Code Scanning (CodeQL) &#43; Secret Scanning &#43; Dependency Review &#43; Dependabot、跟 PR / Security tab 深度整合">GitHub Advanced Security</a>、<a href="/blog/backend/07-security-data-protection/vendors/snyk/" data-link-title="Snyk" data-link-desc="跨 SCM 多模組 application security platform：Open Source (SCA) &#43; Code (SAST) &#43; Container &#43; IaC &#43; Cloud (CSPM)、Reachability analysis">Snyk</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/vendors/trivy/" data-link-title="Trivy" data-link-desc="Aqua Security 開源 all-in-one scanner：Container / Filesystem / K8s / IaC &#43; Secret &#43; License &#43; SBOM、Apache 2.0、CI 友善">Trivy</a>（容器 scan）、<a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype</a>（SBOM）</li>
<li>跨類：artifact 簽章（Sigstore cosign）見 <a href="/blog/backend/07-security-data-protection/vendors/syft-grype/" data-link-title="Syft &#43; Grype" data-link-desc="Anchore 開源姐妹工具：Syft 產 SBOM (CycloneDX / SPDX) &#43; Grype scan 漏洞、Unix philosophy、cosign attestation 整合">Syft / Grype 頁的 SBOM attestation 段</a></li>
<li>跨模組：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">6 可靠性驗證流程</a>（Dependabot PR 進 release flow 的 gate 設計）、<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a></li>
<li>官方：<a href="https://docs.github.com/en/code-security/dependabot">Dependabot Documentation</a></li>
</ul>
]]></content:encoded></item></channel></rss>