<?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>Contract on Tarragon</title><link>https://tarrragon.github.io/blog/tags/contract/</link><description>Recent content in Contract on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 03 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/contract/index.xml" rel="self" type="application/rss+xml"/><item><title>11.1 API 作為服務邊界的責任</title><link>https://tarrragon.github.io/blog/backend/11-api-design/api-boundary-responsibility/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/11-api-design/api-boundary-responsibility/</guid><description>&lt;p>API 設計的核心責任是管理一組對外承諾的成本結構。服務內部的實作可以隨時重構、成本收在自己團隊；對外語意一旦被消費者依賴、每次變更都要付出跨組織的遷移協調成本。這個不對稱決定了 API 設計的所有下游議題：版本策略在決定承諾怎麼分期、相容紀律在決定承諾怎麼守、錯誤模型在決定失敗時承諾什麼。本章建立這個責任框架；框架本身是從 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">案例庫&lt;/a> 跨案例合成的推導、非單一案例原文。&lt;/p>
&lt;h2 id="承諾的範圍比-schema-大">承諾的範圍比 schema 大&lt;/h2>
&lt;p>對外承諾的範圍涵蓋所有消費者觀察得到、且會寫進程式碼依賴的介面性質 — 欄位與型別只是最顯眼的一層。錯誤碼、HTTP status 的使用慣例、欄位預設值、回應時序、分頁行為、ID 字串的長度與格式、甚至欄位在 JSON 裡的順序、都可能被某個消費者拿去依賴。這個現象有個常被引用的名字：Hyrum&amp;rsquo;s Law — 使用者夠多時、介面的每個可觀察行為都會被某人依賴、無論服務端是否承諾過。&lt;/p>
&lt;p>契約邊界的有效管理方式是把「消費者不可依賴的性質」明文寫出來、而非留給雙方猜。Stripe 的 upgrade 文件明列了一份相容變更清單、劃出服務端保留變更自由的軸（清單逐項與它在變更審查裡的用法、主寫在 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6&lt;/a>；案例見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/versioning-stripe-named-major-releases/" data-link-title="11.C11 Stripe 現行方案：具名 major release 與相容變更清單" data-link-desc="同一家公司版本策略隨規模演進的第二個時間切片、附「什麼算 backwards-compatible」的明文清單">11.C11&lt;/a>）。這份清單的作用是雙向的：服務端保留這些軸上的變更自由、消費者拿到「寫 client 時什麼可以依賴」的明確指引。缺少這種明文劃界時、每個未宣告的性質都處於灰色地帶 — 變更的權責只能事後協商。&lt;/p>
&lt;h2 id="變更成本的兩種分配設計">變更成本的兩種分配設計&lt;/h2>
&lt;p>承諾確立之後、變更成本的分配有兩種本質設計：由服務端吸收、或攤給所有消費者。這是 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5 版本策略&lt;/a> 背後的經濟結構、在本章先建立判讀框架。&lt;/p>
&lt;p>服務端吸收的極端案例是 Stripe：服務端的轉換層一次吸收了約 100 個 backwards-incompatible 升級、同時維持與 2011 年以來每一版相容（轉換層機制的展開見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5&lt;/a>；案例見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/versioning-stripe-rolling-date-versions/" data-link-title="11.C10 Stripe：日期滾動版本與 version change module" data-link-desc="把相容性從路由層搬進轉換層、breaking change 成本由服務端一次吸收；date-based versioning 的原型案例">11.C10&lt;/a>）。這個設計把變更成本收在服務端的基礎設施投資裡、換來的是消費者幾乎永遠不被迫遷移。&lt;/p>
&lt;p>攤給消費者的設計則以「版本 + 遷移窗口」的形式出現：服務端宣告新版、給一段支援期、到期消費者必須完成遷移。成本較低、但把協調負擔外部化 — 適合消費者數量有限、或平台對生態有強制力的情境。兩種設計的選擇判準是消費者的數量、異質性、跟服務端對消費者的控制力：內部服務間的 API 可以直接協調升級、公開平台的十萬個 integration 只能靠承諾與窗口。&lt;/p>
&lt;h2 id="承諾違約的模式">承諾違約的模式&lt;/h2>
&lt;p>違約的傷害大小跟違約的模式有關、明確的失敗優於靜默的行為改變。Facebook Graph API v1.0 退場時、到期的 v1.0 請求被靜默改以 v2.0 語意處理、而非回傳明確錯誤 — v2.0 移除了 friends 資料等大範圍權限、未遷移的 app 不會炸在認證層、而是拿到形狀不同的資料默默壞掉（見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/versioning-facebook-graph-v1-forced-upgrade/" data-link-title="11.C17 Facebook Graph API v1.0 退場：靜默語意切換（反例）" data-link-desc="反例：到期後把 v1.0 請求靜默當 v2.0 處理而非回明確錯誤、長尾 app 默默壞掉">11.C17&lt;/a>、反例）。對照組是明確錯誤：消費者立刻知道、監控立刻報警、修復路徑清楚。設計退場行為時的判準是「消費者發現問題的延遲」— 靜默切換把發現延遲拉到不可控、明確錯誤把它壓到第一個請求。&lt;/p>
&lt;h2 id="判讀訊號">判讀訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>判讀&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>消費者回報「你們沒改版但行為變了」&lt;/td>
 &lt;td>有未明文的介面性質被依賴、契約劃界不完整&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>團隊內對「這個改動要不要發版本」反覆爭論&lt;/td>
 &lt;td>缺「什麼算 breaking」的明文清單、先補清單再談流程&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>改一個欄位要跨三個團隊開會&lt;/td>
 &lt;td>變更成本已攤給消費者、評估是否值得投資服務端吸收層&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>消費者停在舊版不動、新功能推不出去&lt;/td>
 &lt;td>遷移壓力設計缺位、看 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5&lt;/a> 的 deprecation 執行工具&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這些訊號的共同根因是承諾範圍或成本分配沒有被當成明確的設計對象。修法從明文化開始：先有相容變更清單、再有版本與退場政策、最後才是工具。&lt;/p>
&lt;h2 id="邊界">邊界&lt;/h2>
&lt;p>本章的框架適用於「有外部消費者」的介面 — 外部指組織邊界或部署邊界之外、修正代價無法用一次 refactor 收掉的情境。同一個 repo 內、同一次部署一起上線的模組間介面、變更成本結構完全不同、用內部重構紀律處理即可、套用本章框架是過度設計。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>選風格與建模：&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/api-style-selection/" data-link-title="11.2 風格選型總覽" data-link-desc="REST 式 HTTP&amp;#43;JSON、GraphQL、gRPC、tRPC、JSON-RPC、event 之間選哪個 — 用消費者形狀、演進成本、操作可及性三軸判讀">11.2 風格選型總覽&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/resource-modeling-operation-semantics/" data-link-title="11.3 資源建模與操作語意" data-link-desc="endpoint 該建模成資源還是動作、HTTP method 與 status 承諾了什麼、available actions 由誰計算 — 建模決策的判準">11.3 資源建模與操作語意&lt;/a>&lt;/li>
&lt;li>承諾怎麼分期、什麼算 breaking：&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5 版本策略與 deprecation&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6 向後相容的變更紀律&lt;/a>&lt;/li>
&lt;li>契約的驗證手段（consumer-driven contract test）：&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/contract-testing/" data-link-title="6.10 Contract Testing 與 Schema 演進" data-link-desc="把跨服務 / API / event schema 的隱性期待變成可驗證契約，控制演進相容性">6.10 契約測試&lt;/a>&lt;/li>
&lt;li>名詞層：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/contract/" data-link-title="Boundary Contract" data-link-desc="說明跨邊界約定如何維持相容與可驗證">Contract&lt;/a> 知識卡&lt;/li>
&lt;li>案例原文：&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">模組十一案例庫&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>API 設計的核心責任是管理一組對外承諾的成本結構。服務內部的實作可以隨時重構、成本收在自己團隊；對外語意一旦被消費者依賴、每次變更都要付出跨組織的遷移協調成本。這個不對稱決定了 API 設計的所有下游議題：版本策略在決定承諾怎麼分期、相容紀律在決定承諾怎麼守、錯誤模型在決定失敗時承諾什麼。本章建立這個責任框架；框架本身是從 <a href="/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">案例庫</a> 跨案例合成的推導、非單一案例原文。</p>
<h2 id="承諾的範圍比-schema-大">承諾的範圍比 schema 大</h2>
<p>對外承諾的範圍涵蓋所有消費者觀察得到、且會寫進程式碼依賴的介面性質 — 欄位與型別只是最顯眼的一層。錯誤碼、HTTP status 的使用慣例、欄位預設值、回應時序、分頁行為、ID 字串的長度與格式、甚至欄位在 JSON 裡的順序、都可能被某個消費者拿去依賴。這個現象有個常被引用的名字：Hyrum&rsquo;s Law — 使用者夠多時、介面的每個可觀察行為都會被某人依賴、無論服務端是否承諾過。</p>
<p>契約邊界的有效管理方式是把「消費者不可依賴的性質」明文寫出來、而非留給雙方猜。Stripe 的 upgrade 文件明列了一份相容變更清單、劃出服務端保留變更自由的軸（清單逐項與它在變更審查裡的用法、主寫在 <a href="/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6</a>；案例見 <a href="/blog/backend/11-api-design/cases/versioning-stripe-named-major-releases/" data-link-title="11.C11 Stripe 現行方案：具名 major release 與相容變更清單" data-link-desc="同一家公司版本策略隨規模演進的第二個時間切片、附「什麼算 backwards-compatible」的明文清單">11.C11</a>）。這份清單的作用是雙向的：服務端保留這些軸上的變更自由、消費者拿到「寫 client 時什麼可以依賴」的明確指引。缺少這種明文劃界時、每個未宣告的性質都處於灰色地帶 — 變更的權責只能事後協商。</p>
<h2 id="變更成本的兩種分配設計">變更成本的兩種分配設計</h2>
<p>承諾確立之後、變更成本的分配有兩種本質設計：由服務端吸收、或攤給所有消費者。這是 <a href="/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5 版本策略</a> 背後的經濟結構、在本章先建立判讀框架。</p>
<p>服務端吸收的極端案例是 Stripe：服務端的轉換層一次吸收了約 100 個 backwards-incompatible 升級、同時維持與 2011 年以來每一版相容（轉換層機制的展開見 <a href="/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5</a>；案例見 <a href="/blog/backend/11-api-design/cases/versioning-stripe-rolling-date-versions/" data-link-title="11.C10 Stripe：日期滾動版本與 version change module" data-link-desc="把相容性從路由層搬進轉換層、breaking change 成本由服務端一次吸收；date-based versioning 的原型案例">11.C10</a>）。這個設計把變更成本收在服務端的基礎設施投資裡、換來的是消費者幾乎永遠不被迫遷移。</p>
<p>攤給消費者的設計則以「版本 + 遷移窗口」的形式出現：服務端宣告新版、給一段支援期、到期消費者必須完成遷移。成本較低、但把協調負擔外部化 — 適合消費者數量有限、或平台對生態有強制力的情境。兩種設計的選擇判準是消費者的數量、異質性、跟服務端對消費者的控制力：內部服務間的 API 可以直接協調升級、公開平台的十萬個 integration 只能靠承諾與窗口。</p>
<h2 id="承諾違約的模式">承諾違約的模式</h2>
<p>違約的傷害大小跟違約的模式有關、明確的失敗優於靜默的行為改變。Facebook Graph API v1.0 退場時、到期的 v1.0 請求被靜默改以 v2.0 語意處理、而非回傳明確錯誤 — v2.0 移除了 friends 資料等大範圍權限、未遷移的 app 不會炸在認證層、而是拿到形狀不同的資料默默壞掉（見 <a href="/blog/backend/11-api-design/cases/versioning-facebook-graph-v1-forced-upgrade/" data-link-title="11.C17 Facebook Graph API v1.0 退場：靜默語意切換（反例）" data-link-desc="反例：到期後把 v1.0 請求靜默當 v2.0 處理而非回明確錯誤、長尾 app 默默壞掉">11.C17</a>、反例）。對照組是明確錯誤：消費者立刻知道、監控立刻報警、修復路徑清楚。設計退場行為時的判準是「消費者發現問題的延遲」— 靜默切換把發現延遲拉到不可控、明確錯誤把它壓到第一個請求。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>消費者回報「你們沒改版但行為變了」</td>
          <td>有未明文的介面性質被依賴、契約劃界不完整</td>
      </tr>
      <tr>
          <td>團隊內對「這個改動要不要發版本」反覆爭論</td>
          <td>缺「什麼算 breaking」的明文清單、先補清單再談流程</td>
      </tr>
      <tr>
          <td>改一個欄位要跨三個團隊開會</td>
          <td>變更成本已攤給消費者、評估是否值得投資服務端吸收層</td>
      </tr>
      <tr>
          <td>消費者停在舊版不動、新功能推不出去</td>
          <td>遷移壓力設計缺位、看 <a href="/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5</a> 的 deprecation 執行工具</td>
      </tr>
  </tbody>
</table>
<p>這些訊號的共同根因是承諾範圍或成本分配沒有被當成明確的設計對象。修法從明文化開始：先有相容變更清單、再有版本與退場政策、最後才是工具。</p>
<h2 id="邊界">邊界</h2>
<p>本章的框架適用於「有外部消費者」的介面 — 外部指組織邊界或部署邊界之外、修正代價無法用一次 refactor 收掉的情境。同一個 repo 內、同一次部署一起上線的模組間介面、變更成本結構完全不同、用內部重構紀律處理即可、套用本章框架是過度設計。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>選風格與建模：<a href="/blog/backend/11-api-design/api-style-selection/" data-link-title="11.2 風格選型總覽" data-link-desc="REST 式 HTTP&#43;JSON、GraphQL、gRPC、tRPC、JSON-RPC、event 之間選哪個 — 用消費者形狀、演進成本、操作可及性三軸判讀">11.2 風格選型總覽</a>、<a href="/blog/backend/11-api-design/resource-modeling-operation-semantics/" data-link-title="11.3 資源建模與操作語意" data-link-desc="endpoint 該建模成資源還是動作、HTTP method 與 status 承諾了什麼、available actions 由誰計算 — 建模決策的判準">11.3 資源建模與操作語意</a></li>
<li>承諾怎麼分期、什麼算 breaking：<a href="/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5 版本策略與 deprecation</a>、<a href="/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6 向後相容的變更紀律</a></li>
<li>契約的驗證手段（consumer-driven contract test）：<a href="/blog/backend/06-reliability/contract-testing/" data-link-title="6.10 Contract Testing 與 Schema 演進" data-link-desc="把跨服務 / API / event schema 的隱性期待變成可驗證契約，控制演進相容性">6.10 契約測試</a></li>
<li>名詞層：<a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a>、<a href="/blog/backend/knowledge-cards/contract/" data-link-title="Boundary Contract" data-link-desc="說明跨邊界約定如何維持相容與可驗證">Contract</a> 知識卡</li>
<li>案例原文：<a href="/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">模組十一案例庫</a></li>
</ul>
]]></content:encoded></item><item><title>模組十一：API 設計與對外契約</title><link>https://tarrragon.github.io/blog/backend/11-api-design/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/11-api-design/</guid><description>&lt;p>API 設計的核心目標是管理對外承諾的成本結構。服務內部的實作可以隨時重構、對外語意一旦被消費者依賴、每次變更都要付出遷移協調的代價；API 設計把「哪些介面行為要承諾、承諾到什麼程度、承諾怎麼分期演進」變成可推導的決策。本模組的判別問題是「這個議題出錯時、修正代價是否落在外部消費者身上」——代價落在外部的進本模組、代價收在服務內部的留在各服務模組。&lt;/p>
&lt;h2 id="讀者定位">讀者定位&lt;/h2>
&lt;p>本模組同時服務兩種深度的讀者。尚未建立 API 設計判準的讀者走主章：每章原則先行、用中性判準說明爭論在爭什麼、自己的情境該看哪些訊號。已熟悉主流做法的讀者直接進流派層：API 設計是長期存在爭論的領域、主流業界做法之外、hypermedia、型別共享 RPC、統一格式標準等流派持續被推廣或重新發明；流派層讓每個流派用自己的語言陳述論證、含該流派的失敗案例與適用邊界、判準層維持中性。&lt;/p>
&lt;h2 id="跟其他模組的責任分工">跟其他模組的責任分工&lt;/h2>
&lt;p>本模組收「決策還沒變成 code 之前」的設計推導；契約的驗證手段、gateway 的執行機制、事件 schema 的操作分別已有承接模組。&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>contract 怎麼驗證（pact、CI gate）&lt;/td>
 &lt;td>06 留（contract test）&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>contract 該承諾什麼、怎麼演進&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>版本策略、相容紀律章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>gateway 的路由、auth、限流實作&lt;/td>
 &lt;td>05 留（限流實作章屬 05 backlog）&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>限流的對外語意與錯誤承諾&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>對外流量語意章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>event schema registry 操作&lt;/td>
 &lt;td>03 留&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>同步 API 與 event 的風格選型&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>風格選型章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>retry / replay 的內部處理與驗證&lt;/td>
 &lt;td>03 留（處理）、06 留（驗證）&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>idempotency key 的對外介面設計&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>API 層冪等章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料表結構與 schema migration&lt;/td>
 &lt;td>01 留&lt;/td>
 &lt;td>—&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API 資源建模與資料形狀的交接&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>資源建模章&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="模組結構">模組結構&lt;/h2>
&lt;p>主章承擔判準層：原則先行、每章結尾附「爭論地圖」段路由到流派層與爭論深度文章。&lt;code>styles/&lt;/code> 承擔流派層、對應其他模組的 &lt;code>vendors/&lt;/code> 慣例：每個流派一個目錄、深度文章用該流派自己的詞彙 steelman。單一爭議需要跨流派攤開時、寫成獨立的爭論深度文章、掛在對應主章之下。&lt;/p>
&lt;h2 id="章節規劃">章節規劃&lt;/h2>
&lt;p>主章（判準層）與 styles/rest、styles/graphql 兩個流派批已完成；其餘流派層與爭論深度文章是 backlog、完成後逐篇補站內連結。案例支撐欄的 C 編號對應 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">案例庫&lt;/a>；標「合成」的章節沒有專屬 case、內容從全庫推導、寫作時依 fact vs derive 紀律標明。案例編號慣例：章節內文首次引用寫 &lt;code>[11.C&amp;lt;n&amp;gt;]&lt;/code> 連結、同章後續與索引表可用 &lt;code>C&amp;lt;n&amp;gt;&lt;/code> 裸編號。&lt;/p>
&lt;h3 id="主章判準層">主章（判準層）&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>章節&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>案例支撐&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/api-boundary-responsibility/" data-link-title="11.1 API 作為服務邊界的責任" data-link-desc="介面變更該由誰付成本、哪些介面性質算對外承諾、承諾違約有哪些模式 — 動手設計 endpoint 前的責任框架">11.1&lt;/a>&lt;/td>
 &lt;td>API 作為服務邊界的責任&lt;/td>
 &lt;td>承諾的成本結構：改內部便宜、改對外語意昂貴；違約模式與成本分配&lt;/td>
 &lt;td>合成（全庫）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/api-style-selection/" data-link-title="11.2 風格選型總覽" data-link-desc="REST 式 HTTP&amp;#43;JSON、GraphQL、gRPC、tRPC、JSON-RPC、event 之間選哪個 — 用消費者形狀、演進成本、操作可及性三軸判讀">11.2&lt;/a>&lt;/td>
 &lt;td>風格選型總覽&lt;/td>
 &lt;td>消費者形狀、演進成本、操作可及性的判準軸；各風格深度收在 &lt;code>styles/&lt;/code>&lt;/td>
 &lt;td>合成（C18-C34 為主）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/resource-modeling-operation-semantics/" data-link-title="11.3 資源建模與操作語意" data-link-desc="endpoint 該建模成資源還是動作、HTTP method 與 status 承諾了什麼、available actions 由誰計算 — 建模決策的判準">11.3&lt;/a>&lt;/td>
 &lt;td>資源建模與操作語意&lt;/td>
 &lt;td>資源導向與動作導向的取捨、HTTP method / status 的承諾意義、跨資源操作&lt;/td>
 &lt;td>C1、C3、C5（偏論證型）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/error-model-design/" data-link-title="11.4 錯誤模型設計" data-link-desc="錯誤該分幾類、格式怎麼定才有演化空間、機器判讀跟人類訊息怎麼分工 — 錯誤作為契約一級公民的設計判準">11.4&lt;/a>&lt;/td>
 &lt;td>錯誤模型設計&lt;/td>
 &lt;td>可重試與終態的分類、錯誤碼 taxonomy、錯誤格式的演進空間&lt;/td>
 &lt;td>C35、C36、C45&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5&lt;/a>&lt;/td>
 &lt;td>版本策略與 deprecation&lt;/td>
 &lt;td>版本是承諾的分期方式；deprecation 生命週期與 sunset 量測&lt;/td>
 &lt;td>C10-C16、C26&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6&lt;/a>&lt;/td>
 &lt;td>向後相容的變更紀律&lt;/td>
 &lt;td>什麼算 breaking（欄位、預設值、錯誤碼、時序）、變更審查 gate&lt;/td>
 &lt;td>C11、C13、C26、C28、C29&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/collection-interface-design/" data-link-title="11.7 集合介面設計" data-link-desc="分頁方案的承諾差異、批次操作的部分失敗語意、超過請求逾時的長時操作怎麼回 — 集合與長時操作的介面判準">11.7&lt;/a>&lt;/td>
 &lt;td>集合介面設計&lt;/td>
 &lt;td>分頁與批次的部分失敗語意、長時操作的非同步模式&lt;/td>
 &lt;td>C37、C44&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/api-idempotency-design/" data-link-title="11.8 API 層冪等設計" data-link-desc="idempotency key 誰生成、存多久、replay 回什麼、衝突怎麼回 — 對外冪等契約的條款設計與無標準現況">11.8&lt;/a>&lt;/td>
 &lt;td>API 層冪等設計&lt;/td>
 &lt;td>idempotency key 的對外語意：誰生成、存多久、衝突怎麼回&lt;/td>
 &lt;td>C38-C41、C45&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/external-traffic-semantics/" data-link-title="11.9 對外流量語意" data-link-desc="rate limit 對消費者承諾什麼、429 與 Retry-After 怎麼設計、配額 header 該不該信 — 限流作為契約的語意設計">11.9&lt;/a>&lt;/td>
 &lt;td>對外流量語意&lt;/td>
 &lt;td>rate limit / quota 作為契約：429 / Retry-After 的承諾、承諾邊界&lt;/td>
 &lt;td>C19、C42、C43&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/api-governance/" data-link-title="11.10 API 規範治理" data-link-desc="設計規範怎麼讓幾十個團隊持續遵守 — 提案制、Guild 制、分軌制的治理模式比較、linting 進 CI、規範失敗的成因">11.10&lt;/a>&lt;/td>
 &lt;td>API 規範治理&lt;/td>
 &lt;td>style guide 與 design review 作為組織能力：提案制 / Guild 制 / 分軌制三型比較、linting 進 CI、治理缺席的失敗模式&lt;/td>
 &lt;td>C46-C54&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="流派層styles">流派層（&lt;code>styles/&lt;/code>）&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>目錄&lt;/th>
 &lt;th>文章候選&lt;/th>
 &lt;th>深度重點&lt;/th>
 &lt;th>案例支撐&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/styles/rest/" data-link-title="REST 流派：語意學之爭與 hypermedia 復興" data-link-desc="REST 這個詞的定義權爭奪、hypermedia 路線的復興論證與業界拒絕的理由、成熟度模型的實用讀法">styles/rest/&lt;/a>（已完成）&lt;/td>
 &lt;td>REST 語意學之爭、hypermedia 與 HATEOAS 復興、Richardson 成熟度的實用讀法&lt;/td>
 &lt;td>Fielding 原義與業界 pragmatic JSON-over-HTTP 的落差、HAL / Siren 到 htmx&lt;/td>
 &lt;td>C1-C9&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/styles/graphql/" data-link-title="GraphQL 流派：schema 演進、執行成本與公開 API 進退" data-link-desc="versionless 演進的紀律代價、resolver 執行模型的成本與攻擊面、大平台採用與撤退的情境差異">styles/graphql/&lt;/a>（已完成）&lt;/td>
 &lt;td>schema 演進、執行成本與安全、公開 API 的 GraphQL 進退&lt;/td>
 &lt;td>同一技術在 GitHub、Shopify 與撤退團隊的不同結局、各自的情境差異&lt;/td>
 &lt;td>C18-C27&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>styles/grpc/&lt;/code>&lt;/td>
 &lt;td>proto 演進紀律、streaming 語意與部署邊界、內部 RPC 的選型位置&lt;/td>
 &lt;td>field number 紀律、buf breaking check、瀏覽器邊界的妥協&lt;/td>
 &lt;td>C28-C32&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>styles/rpc-revival/&lt;/code>&lt;/td>
 &lt;td>tRPC 與型別共享、JSON-RPC 的重生場景&lt;/td>
 &lt;td>tRPC 的 monorepo 前提與語言耦合代價；JSON-RPC 在 LSP 與 MCP 的存活場景&lt;/td>
 &lt;td>C23、C33、C34&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>styles/standards/&lt;/code>&lt;/td>
 &lt;td>JSON:API 與 OData 的標準化嘗試、OpenAPI 與 AsyncAPI 生態&lt;/td>
 &lt;td>「統一 response 格式」的標準每隔一段時間重來一次、每次留下部分遺產的原因&lt;/td>
 &lt;td>C50-C53&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>styles/realtime/&lt;/code>&lt;/td>
 &lt;td>WebSocket / SSE / long-polling / webhook 的對外承諾差異&lt;/td>
 &lt;td>同是 server 推 client、各機制的失敗模式與重連語意差異&lt;/td>
 &lt;td>缺、寫作前補採集&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="爭論深度文章">爭論深度文章&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>掛在&lt;/th>
 &lt;th>爭議&lt;/th>
 &lt;th>交鋒各方&lt;/th>
 &lt;th>案例支撐&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>11.5&lt;/td>
 &lt;td>版本策略流派之爭&lt;/td>
 &lt;td>URI 版本、header、Stripe date-based、Fielding 的 no-versioning 派&lt;/td>
 &lt;td>C10、C12、C14、C26&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>11.4&lt;/td>
 &lt;td>錯誤格式之爭&lt;/td>
 &lt;td>RFC 9457 problem+json、envelope 包裝、GraphQL 的 200-with-errors 慣例&lt;/td>
 &lt;td>C35、C36&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>11.7&lt;/td>
 &lt;td>分頁之爭&lt;/td>
 &lt;td>offset、cursor、keyset；cursor 不透明性算承諾還是逃生門&lt;/td>
 &lt;td>C37&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>11.8&lt;/td>
 &lt;td>idempotency key 標準化&lt;/td>
 &lt;td>IETF draft 與 Stripe / PayPal 各自實作的語意差異&lt;/td>
 &lt;td>C39-C41&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="交付節奏">交付節奏&lt;/h2>
&lt;p>主章先行、流派層分批。第一批交付全部主章、讓判準層完整成立、各章「爭論地圖」段先以文字描述流派層 backlog；第二批起按批次 cadence 補流派層、每批選一個 &lt;code>styles/&lt;/code> 目錄寫完；爭論深度文章跟對應主章同批寫、讓主章的路由段有實際落點。&lt;/p></description><content:encoded><![CDATA[<p>API 設計的核心目標是管理對外承諾的成本結構。服務內部的實作可以隨時重構、對外語意一旦被消費者依賴、每次變更都要付出遷移協調的代價；API 設計把「哪些介面行為要承諾、承諾到什麼程度、承諾怎麼分期演進」變成可推導的決策。本模組的判別問題是「這個議題出錯時、修正代價是否落在外部消費者身上」——代價落在外部的進本模組、代價收在服務內部的留在各服務模組。</p>
<h2 id="讀者定位">讀者定位</h2>
<p>本模組同時服務兩種深度的讀者。尚未建立 API 設計判準的讀者走主章：每章原則先行、用中性判準說明爭論在爭什麼、自己的情境該看哪些訊號。已熟悉主流做法的讀者直接進流派層：API 設計是長期存在爭論的領域、主流業界做法之外、hypermedia、型別共享 RPC、統一格式標準等流派持續被推廣或重新發明；流派層讓每個流派用自己的語言陳述論證、含該流派的失敗案例與適用邊界、判準層維持中性。</p>
<h2 id="跟其他模組的責任分工">跟其他模組的責任分工</h2>
<p>本模組收「決策還沒變成 code 之前」的設計推導；契約的驗證手段、gateway 的執行機制、事件 schema 的操作分別已有承接模組。</p>
<table>
  <thead>
      <tr>
          <th>議題</th>
          <th>留原模組</th>
          <th>進模組十一</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>contract 怎麼驗證（pact、CI gate）</td>
          <td>06 留（contract test）</td>
          <td>—</td>
      </tr>
      <tr>
          <td>contract 該承諾什麼、怎麼演進</td>
          <td>—</td>
          <td>版本策略、相容紀律章</td>
      </tr>
      <tr>
          <td>gateway 的路由、auth、限流實作</td>
          <td>05 留（限流實作章屬 05 backlog）</td>
          <td>—</td>
      </tr>
      <tr>
          <td>限流的對外語意與錯誤承諾</td>
          <td>—</td>
          <td>對外流量語意章</td>
      </tr>
      <tr>
          <td>event schema registry 操作</td>
          <td>03 留</td>
          <td>—</td>
      </tr>
      <tr>
          <td>同步 API 與 event 的風格選型</td>
          <td>—</td>
          <td>風格選型章</td>
      </tr>
      <tr>
          <td>retry / replay 的內部處理與驗證</td>
          <td>03 留（處理）、06 留（驗證）</td>
          <td>—</td>
      </tr>
      <tr>
          <td>idempotency key 的對外介面設計</td>
          <td>—</td>
          <td>API 層冪等章</td>
      </tr>
      <tr>
          <td>資料表結構與 schema migration</td>
          <td>01 留</td>
          <td>—</td>
      </tr>
      <tr>
          <td>API 資源建模與資料形狀的交接</td>
          <td>—</td>
          <td>資源建模章</td>
      </tr>
  </tbody>
</table>
<h2 id="模組結構">模組結構</h2>
<p>主章承擔判準層：原則先行、每章結尾附「爭論地圖」段路由到流派層與爭論深度文章。<code>styles/</code> 承擔流派層、對應其他模組的 <code>vendors/</code> 慣例：每個流派一個目錄、深度文章用該流派自己的詞彙 steelman。單一爭議需要跨流派攤開時、寫成獨立的爭論深度文章、掛在對應主章之下。</p>
<h2 id="章節規劃">章節規劃</h2>
<p>主章（判準層）與 styles/rest、styles/graphql 兩個流派批已完成；其餘流派層與爭論深度文章是 backlog、完成後逐篇補站內連結。案例支撐欄的 C 編號對應 <a href="/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">案例庫</a>；標「合成」的章節沒有專屬 case、內容從全庫推導、寫作時依 fact vs derive 紀律標明。案例編號慣例：章節內文首次引用寫 <code>[11.C&lt;n&gt;]</code> 連結、同章後續與索引表可用 <code>C&lt;n&gt;</code> 裸編號。</p>
<h3 id="主章判準層">主章（判準層）</h3>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>主題</th>
          <th>核心問題</th>
          <th>案例支撐</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/11-api-design/api-boundary-responsibility/" data-link-title="11.1 API 作為服務邊界的責任" data-link-desc="介面變更該由誰付成本、哪些介面性質算對外承諾、承諾違約有哪些模式 — 動手設計 endpoint 前的責任框架">11.1</a></td>
          <td>API 作為服務邊界的責任</td>
          <td>承諾的成本結構：改內部便宜、改對外語意昂貴；違約模式與成本分配</td>
          <td>合成（全庫）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/api-style-selection/" data-link-title="11.2 風格選型總覽" data-link-desc="REST 式 HTTP&#43;JSON、GraphQL、gRPC、tRPC、JSON-RPC、event 之間選哪個 — 用消費者形狀、演進成本、操作可及性三軸判讀">11.2</a></td>
          <td>風格選型總覽</td>
          <td>消費者形狀、演進成本、操作可及性的判準軸；各風格深度收在 <code>styles/</code></td>
          <td>合成（C18-C34 為主）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/resource-modeling-operation-semantics/" data-link-title="11.3 資源建模與操作語意" data-link-desc="endpoint 該建模成資源還是動作、HTTP method 與 status 承諾了什麼、available actions 由誰計算 — 建模決策的判準">11.3</a></td>
          <td>資源建模與操作語意</td>
          <td>資源導向與動作導向的取捨、HTTP method / status 的承諾意義、跨資源操作</td>
          <td>C1、C3、C5（偏論證型）</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/error-model-design/" data-link-title="11.4 錯誤模型設計" data-link-desc="錯誤該分幾類、格式怎麼定才有演化空間、機器判讀跟人類訊息怎麼分工 — 錯誤作為契約一級公民的設計判準">11.4</a></td>
          <td>錯誤模型設計</td>
          <td>可重試與終態的分類、錯誤碼 taxonomy、錯誤格式的演進空間</td>
          <td>C35、C36、C45</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/versioning-and-deprecation/" data-link-title="11.5 版本策略與 deprecation" data-link-desc="版本方案怎麼選（URI/header/date-based）、支援窗口怎麼承諾、舊版怎麼安全退場 — 承諾分期與回收的操作設計">11.5</a></td>
          <td>版本策略與 deprecation</td>
          <td>版本是承諾的分期方式；deprecation 生命週期與 sunset 量測</td>
          <td>C10-C16、C26</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/backward-compatibility-discipline/" data-link-title="11.6 向後相容的變更紀律" data-link-desc="哪些變更算 breaking、相容性檢查放人工還是 CI、檢查粒度怎麼選 — 讓介面變更可審可擋的日常紀律">11.6</a></td>
          <td>向後相容的變更紀律</td>
          <td>什麼算 breaking（欄位、預設值、錯誤碼、時序）、變更審查 gate</td>
          <td>C11、C13、C26、C28、C29</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/collection-interface-design/" data-link-title="11.7 集合介面設計" data-link-desc="分頁方案的承諾差異、批次操作的部分失敗語意、超過請求逾時的長時操作怎麼回 — 集合與長時操作的介面判準">11.7</a></td>
          <td>集合介面設計</td>
          <td>分頁與批次的部分失敗語意、長時操作的非同步模式</td>
          <td>C37、C44</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/api-idempotency-design/" data-link-title="11.8 API 層冪等設計" data-link-desc="idempotency key 誰生成、存多久、replay 回什麼、衝突怎麼回 — 對外冪等契約的條款設計與無標準現況">11.8</a></td>
          <td>API 層冪等設計</td>
          <td>idempotency key 的對外語意：誰生成、存多久、衝突怎麼回</td>
          <td>C38-C41、C45</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/external-traffic-semantics/" data-link-title="11.9 對外流量語意" data-link-desc="rate limit 對消費者承諾什麼、429 與 Retry-After 怎麼設計、配額 header 該不該信 — 限流作為契約的語意設計">11.9</a></td>
          <td>對外流量語意</td>
          <td>rate limit / quota 作為契約：429 / Retry-After 的承諾、承諾邊界</td>
          <td>C19、C42、C43</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/api-governance/" data-link-title="11.10 API 規範治理" data-link-desc="設計規範怎麼讓幾十個團隊持續遵守 — 提案制、Guild 制、分軌制的治理模式比較、linting 進 CI、規範失敗的成因">11.10</a></td>
          <td>API 規範治理</td>
          <td>style guide 與 design review 作為組織能力：提案制 / Guild 制 / 分軌制三型比較、linting 進 CI、治理缺席的失敗模式</td>
          <td>C46-C54</td>
      </tr>
  </tbody>
</table>
<h3 id="流派層styles">流派層（<code>styles/</code>）</h3>
<table>
  <thead>
      <tr>
          <th>目錄</th>
          <th>文章候選</th>
          <th>深度重點</th>
          <th>案例支撐</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/11-api-design/styles/rest/" data-link-title="REST 流派：語意學之爭與 hypermedia 復興" data-link-desc="REST 這個詞的定義權爭奪、hypermedia 路線的復興論證與業界拒絕的理由、成熟度模型的實用讀法">styles/rest/</a>（已完成）</td>
          <td>REST 語意學之爭、hypermedia 與 HATEOAS 復興、Richardson 成熟度的實用讀法</td>
          <td>Fielding 原義與業界 pragmatic JSON-over-HTTP 的落差、HAL / Siren 到 htmx</td>
          <td>C1-C9</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/11-api-design/styles/graphql/" data-link-title="GraphQL 流派：schema 演進、執行成本與公開 API 進退" data-link-desc="versionless 演進的紀律代價、resolver 執行模型的成本與攻擊面、大平台採用與撤退的情境差異">styles/graphql/</a>（已完成）</td>
          <td>schema 演進、執行成本與安全、公開 API 的 GraphQL 進退</td>
          <td>同一技術在 GitHub、Shopify 與撤退團隊的不同結局、各自的情境差異</td>
          <td>C18-C27</td>
      </tr>
      <tr>
          <td><code>styles/grpc/</code></td>
          <td>proto 演進紀律、streaming 語意與部署邊界、內部 RPC 的選型位置</td>
          <td>field number 紀律、buf breaking check、瀏覽器邊界的妥協</td>
          <td>C28-C32</td>
      </tr>
      <tr>
          <td><code>styles/rpc-revival/</code></td>
          <td>tRPC 與型別共享、JSON-RPC 的重生場景</td>
          <td>tRPC 的 monorepo 前提與語言耦合代價；JSON-RPC 在 LSP 與 MCP 的存活場景</td>
          <td>C23、C33、C34</td>
      </tr>
      <tr>
          <td><code>styles/standards/</code></td>
          <td>JSON:API 與 OData 的標準化嘗試、OpenAPI 與 AsyncAPI 生態</td>
          <td>「統一 response 格式」的標準每隔一段時間重來一次、每次留下部分遺產的原因</td>
          <td>C50-C53</td>
      </tr>
      <tr>
          <td><code>styles/realtime/</code></td>
          <td>WebSocket / SSE / long-polling / webhook 的對外承諾差異</td>
          <td>同是 server 推 client、各機制的失敗模式與重連語意差異</td>
          <td>缺、寫作前補採集</td>
      </tr>
  </tbody>
</table>
<h3 id="爭論深度文章">爭論深度文章</h3>
<table>
  <thead>
      <tr>
          <th>掛在</th>
          <th>爭議</th>
          <th>交鋒各方</th>
          <th>案例支撐</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>11.5</td>
          <td>版本策略流派之爭</td>
          <td>URI 版本、header、Stripe date-based、Fielding 的 no-versioning 派</td>
          <td>C10、C12、C14、C26</td>
      </tr>
      <tr>
          <td>11.4</td>
          <td>錯誤格式之爭</td>
          <td>RFC 9457 problem+json、envelope 包裝、GraphQL 的 200-with-errors 慣例</td>
          <td>C35、C36</td>
      </tr>
      <tr>
          <td>11.7</td>
          <td>分頁之爭</td>
          <td>offset、cursor、keyset；cursor 不透明性算承諾還是逃生門</td>
          <td>C37</td>
      </tr>
      <tr>
          <td>11.8</td>
          <td>idempotency key 標準化</td>
          <td>IETF draft 與 Stripe / PayPal 各自實作的語意差異</td>
          <td>C39-C41</td>
      </tr>
  </tbody>
</table>
<h2 id="交付節奏">交付節奏</h2>
<p>主章先行、流派層分批。第一批交付全部主章、讓判準層完整成立、各章「爭論地圖」段先以文字描述流派層 backlog；第二批起按批次 cadence 補流派層、每批選一個 <code>styles/</code> 目錄寫完；爭論深度文章跟對應主章同批寫、讓主章的路由段有實際落點。</p>
<h2 id="目前缺口與後續批次">目前缺口與後續批次</h2>
<p>主章與 rest、graphql 兩個流派批已完成。剩餘工作按依賴關係分四類、前三類的案例支撐都已就緒、可直接開工：</p>
<table>
  <thead>
      <tr>
          <th>缺口</th>
          <th>內容</th>
          <th>前置條件</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>styles/grpc + styles/rpc-revival</td>
          <td>RPC 家族五篇：proto 演進紀律、部署邊界、內部 RPC 選型、tRPC 型別共享、JSON-RPC 重生</td>
          <td>無（C23、C28-C34 就緒；兩目錄主題親緣、適合合併一批寫對照）</td>
      </tr>
      <tr>
          <td>styles/standards</td>
          <td>格式標準化的興衰：JSON:API 與 OData、OpenAPI 與 AsyncAPI 生態</td>
          <td>無（C50-C53 就緒）</td>
      </tr>
      <tr>
          <td>爭論深度文章</td>
          <td>版本策略流派之爭、錯誤格式之爭、分頁之爭、idempotency key 標準化（掛對應主章、見上表）</td>
          <td>無（案例就緒、各主章的路由落點等它們補實）</td>
      </tr>
      <tr>
          <td>styles/realtime</td>
          <td>WebSocket / SSE / long-polling / webhook 的對外承諾差異</td>
          <td><strong>先補一輪案例採集</strong> — stage 0 的六個採集主題未涵蓋 realtime、案例庫現況為零、詳見 <a href="/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">案例覆蓋缺口</a></td>
      </tr>
  </tbody>
</table>
<p>模組外的關聯缺口、記錄備查：知識卡四張候選（見下方知識卡候選段）；05 部署平台模組缺 gateway 限流實作章、<a href="/blog/backend/11-api-design/external-traffic-semantics/" data-link-title="11.9 對外流量語意" data-link-desc="rate limit 對消費者承諾什麼、429 與 Retry-After 怎麼設計、配額 header 該不該信 — 限流作為契約的語意設計">11.9</a> 的執行面交接目前落在該模組首頁（已在責任分工表標 backlog）。</p>
<h2 id="案例庫">案例庫</h2>
<p><a href="/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">模組十一案例庫</a> 已完成 stage 0 採集：54 個經來源驗證的公開案例、按主題分六組（REST 流派 / 版本策略 / GraphQL 進退 / gRPC 與 RPC 復興 / 介面語意 / 治理標準化）、含 8 個反例。來源分兩類：主流做法的一手 guidelines 與演進紀錄（Stripe、GitHub、Google AIP、Zalando、Microsoft）、流派自己的一手論證（Fielding dissertation 與 blog、htmx essays、tRPC 官方文件、LSP 與 MCP spec）— steelman 的前提是讀過該流派自己怎麼說、批評者的轉述只能當對照。覆蓋缺口（realtime 主題、gRPC 退回一手案例、企業治理失敗檢討等）在案例庫索引的「案例覆蓋缺口」段明示、對應章節寫作時改走 standard-driven 或通用工程知識補強。</p>
<h2 id="知識卡候選">知識卡候選</h2>
<p>配套的 <a href="/blog/backend/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理後端服務選型前需要理解的 domain knowhow">前置知識卡片</a> 候選：idempotency-key（對外語意、跟 processing-semantics 拆卡）、pagination-cursor、deprecation-lifecycle、rate-limit-contract。既有的 <a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a>、<a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>、<a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook</a> 卡在主章完成後回補指向本模組的推導層連結。</p>
]]></content:encoded></item></channel></rss>