ADR-003: 方法論的 Headless 契約驅動 API 軌
ADR 編號: 003 狀態: 已接受 (Accepted) 決策日期: 2026-06-21 決策者: AppFuse Team + AI Assistant 範圍: docs-methodology(開發方法論)
摘要
AppFuse 方法論原本以「UI 業務功能」為唯一中心——US 經 Prototype(web-mockup)→ Server → Integration(web) 三階段驗證。本 ADR 新增一條一級的 Headless 軌,給「無內部 UI、由契約驅動、被外部系統消費」的 API 服務:平台服務、應用對外開放的 API(ERP 交換、官網取資料)、以及無 UI 的應用專屬外部整合。Headless 軌只走方法論的 Server 階段(/api-spec + JUnit API 測試 + Bruno),跳過 Prototype 與 Integration,並繼承 wire-only 的契約穩定紀律。
背景 (Context)
問題陳述
方法論的三階段骨幹本質是「一個 UI 功能的驗證流程」:Prototype 驗 UI/UX(mock API)、Server 驗後端、Integration 驗前後端整合。但實務上有一整類服務沒有內部 UI、也不被 US/UI 驅動:
- 平台服務:整合外部權威來源,對下游 app 開 API。
- 應用對外開放的 API:app-server 把自有資料開給外部系統(ERP 交換帳務、客戶官網取資料)。
- 無 UI 的應用專屬外部整合:後端對接第三方系統,無畫面。
這些服務的「使用者」是外部系統或契約,不是人在點畫面。它們今天的處境是:
- 這類平台服務過去被列為方法論豁免,用 spike / RFC / ADR / Bruno ad-hoc 開發——等於把這類工作流放逐到方法論之外。
- app-server 的對外 API 則落入三階段的退化路徑:Prototype 與 Integration 兩階段是空的(沒有內部 UI 可原型 / 整合)。
核心張力
方法論只有「UI 軌」一條脊。headless 工作要嘛被放逐(平台服務),要嘛硬塞進退化的三階段(app-server 對外 API)。缺一條一級的 headless 軌,導致:進度狀態機從 P.* 起算不合理、US 被迫填前端 module 欄、scaffold 拉進無用的 web 模組、且「對外契約 API」與「對內 UI API」混為一談、心智模型不清。
關鍵識別:區分服務的是「驅動軸」,不是功能
區分一個服務屬哪條軌,不是看它有沒有帳號 / JPA / 多租戶(那是共用基底,UI 應用與平台服務都有),而是看它被什麼驅動:
| 驅動來源 | 軌道 | 驗證方式 |
|---|---|---|
| US + web/mockup(內部 UI 功能) | UI 軌(三階段) | Playwright e2e + UI UAT |
| 契約 + 外部消費者(對外邊界,消費或提供) | Headless 軌(Server 階段) | JUnit API 測試 + Bruno |
所有跨外部邊界的 API(無論是消費外部、還是提供給外部)都是契約驅動。 同一個模組可同時擁有兩種 API 面(對內 UI / 對外契約),按驅動軸分區。
限制條件
- 方法論既有的 Server 階段工具(
/e2e-script產 JUnit API 測試、/uat走 Bruno)本就是契約驅動——能力已存在,缺的是一條正式軌道把它組織起來。 - US 的
module(前端模組家族)欄對「無前端」的 US 已允許省略(跨切面 / 系統頁先例,見m-dev-guardrails.md)。 - 對外發布的 API 一旦有外部消費者,契約穩定性的要求遠高於內部 API(外部系統無法跟著內部 refactor)。
考量的方案 (Options Considered)
方案 A: 新增一級的 Headless 軌(本案)
說明:
在方法論中明列第二條脊——Headless 軌。複用 Server 階段工具,跳過 Prototype / Integration;US 重定義為「消費者 / 契約故事」(視角為外部系統)、module 欄省略;/api-spec(OpenAPI)為主交付物;進度從 S.E2E 起算、終於 ✅。
優點:
- ✅ 把已存在的 Server 階段能力組織成正式軌道,零新工具
- ✅ headless 工作(平台服務、對外 API)取得文檔先行 / 契約測試 / 可追蹤的一致紀律
- ✅ 產品級 headless 服務可成為方法論公民,不必當化外之民
- ✅ 對外契約 API 與對內 UI API 心智模型分離,紀律各自清晰
缺點:
- ❌ 需更新數個 rules / skills(進度狀態機、US、scaffold)以一級支援
評分: 5/5
方案 B: 維持現狀——headless 走三階段退化路徑
說明: 不新增軌道,headless 工作沿用三階段,Prototype / Integration 階段留空。
優點:
- ✅ 不動方法論
缺點:
- ❌ 進度狀態機從
P.E2E起算對無 UI 工作不合理 - ❌ US 被迫填前端
module欄、scaffold 拉無用前端模組 - ❌ 「對外契約 API」與「對內 UI API」混淆,缺契約穩定紀律
- ❌ 退化路徑無人明文規範,各自摸索
評分: 2/5
方案 C: headless 工作一律方法論豁免(ad-hoc 開發)
說明: 所有 headless 服務都走 spike / RFC / ADR / Bruno,不納入方法論。
優點:
- ✅ 對框架基礎建設合適——它本就不被 scaffold
缺點:
- ❌ 放棄文檔先行 / 可追蹤性 / 進度盤點的好處
- ❌ 產品級 headless 服務被迫當化外之民,與其「下游產品」身分矛盾
- ❌ 各 headless 專案各自為政,無一致紀律
評分: 1/5
決策 (Decision)
選擇方案: A — 新增一級的 Headless 契約驅動 API 軌
核心理由:
- 方法論的 Server 階段(JUnit + Bruno)本就是契約驅動,新增軌道是「組織既有能力」而非發明新流程。
- headless 工作(平台服務、對外 API、無 UI 整合)是真實且普遍的一類,值得一條一級軌,而非放逐或退化路徑。
- 區分軌道的是驅動軸(契約 vs US/UI),不是功能——此判準清楚、可操作。
- 讓產品級 headless 服務成為方法論公民,同時把這類服務一直以來的開發方式正名為一條軌(而非例外)。
權衡分析 (Trade-offs)
我們獲得什麼 (Gains)
- ✅ 一條明確的 headless 軌:US(契約故事)→
/api-spec→/impl(server)→ JUnit → Bruno →S.UAT→✅ - ✅ 對外 API 取得契約穩定紀律(OpenAPI source-of-truth、Bruno 守門、版本化、棄用政策)
- ✅ 「對內 UI / 對外契約」雙 API 面在同一模組內可清楚分軌
- ✅ 產品級 headless 服務可正式採用方法論
我們放棄什麼 (Losses)
- ❌ 方法論不再是「單一 UI 三階段脊」的簡單模型——多一條軌、多一份心智負擔
- ❌ 需投入更新 rules / skills
風險與緩解措施 (Risks & Mitigations)
| 風險 | 嚴重性 | 機率 | 緩解措施 |
|---|---|---|---|
| 團隊誤把對外 API 當對內 API 開發、隨意 refactor 破壞外部消費者 | 高 | 中 | 本 ADR 明訂「對外邊界繼承 wire-only 契約紀律」;/api-spec 對外端點要求版本化 + Bruno 守門 |
| headless 與 UI 軌判斷錯誤 | 中 | 中 | 以「驅動軸」單一判準:被 US/UI 驅動 → UI 軌;被契約/外部消費者驅動 → Headless 軌 |
| 通用外部整合被各 app 自建連接器(god-service 反面) | 中 | 中 | 框架先行:通用權威來源整合進共用平台服務、由 consumer 消費 client |
| rules/skills 未更新,headless 軌停在紙上 | 中 | 中 | 下方「待辦事項」逐項追蹤 |
實作指南 (Implementation Guidelines)
1. 適用判準
服務由「契約 + 外部消費者」驅動、無內部 UI 時,走 Headless 軌。典型:
- 平台服務的能力 API
- 應用把自有資料對外開放的 API(ERP 交換、官網取資料)
- 無 UI 的應用專屬外部整合
反面:被某個有畫面的 US 驅動的 API(即使背後接外部來源),仍屬 UI 軌;外部整合只是該 US 的 Server 階段管線。
2. 軌道流程
/roadmap → /feature-list → 「消費者 / 契約故事」US(module 欄省略)→ /sbe
→ /api-spec(★ 主交付物:對外契約 / OpenAPI)→ /domain-model(若有自有實體)
→ /impl(server) → /e2e(JUnit API) → /uat(Bruno API) → /progress(S.E2E → S.UAT → ✅)
跳過 Prototype(P.E2E / P.UAT)與 Integration(web,I.E2E / I.UAT)。
3. US 適配:消費者 / 契約故事
- 視角為外部系統而非人:「As the ERP system, 我要
GET /api/v1/...,schema 為 X」。 module(前端模組家族)欄省略(沿用跨切面 / 系統頁先例)。- 主交付物是 API Spec(契約),不是 UI。
4. 進度狀態機
headless US 從 S.E2E 起算(不經 P.*),通過 S.UAT 後直接 ✅(無 I.* 整合階段)。/progress 需支援此縮短軌。
5. 契約穩定紀律(繼承 wire-only)
對外 API 一旦發布,外部消費者無法跟著內部 refactor,故:
- API Spec(OpenAPI)= source of truth(不是附屬文件,是對外承諾)
- Bruno / 契約測試 = 守門員,攔「內部一改、外部即壞」
/api/v{n}版本化 + 棄用政策,像對待發布的產品- 同一模組內,對內 UI API 可隨 US 演進、對外契約 API 一旦發布即凍結契約——心智模型分開
6. 框架先行
headless 整合需求若屬「通用權威來源」,應進共用平台服務、由 consumer 消費 client,不在各 app 自建連接器。「app 自有資料對外開放」則正當留在該 app。
7. 雙軌共存與 admin console 例外
- 同一模組可同時有 UI 軌(對內)與 Headless 軌(對外)的 API,按驅動軸分區、各走各軌。
- headless 服務若長出管理 UI(如 service account 管理、Excel 上傳、手動維護資料),那一塊回到 UI 軌(完整三階段),消費 server 既有的管理 API。
8. 模組身分與 scaffold
- 框架基礎建設:not scaffold、方法論豁免——它是框架的一部分。
- 產品(建在框架上的 app):可被 scaffold、用 Headless 軌當方法論公民。
- headless 產品 scaffold 時可不拉 web-mockup / web 模組(按需要日後再加 admin console)。
影響 (Consequences)
正面影響
- ➕ 方法論從「UI app 專用」一般化為「也涵蓋 headless 平台 / 整合 API」
- ➕ 這類服務的既有開發方式被正名為一條軌;產品級 headless 服務可正式採用
- ➕ 對外 API 的契約穩定紀律被明文化
負面影響
- ➖ 方法論複雜度上升(兩條軌)
- ➖ 多個 rules / skills 需更新以一級支援 headless 軌
待辦事項
-
m-methodology.md:全景流程新增 Headless 軌分支與「驅動軸」判準(2026-06-21 完成:核心理念 #3 改為兩軌、全景流程加 Headless 軌、新增「兩條軌:依驅動軸分流」節、三階段設計邏輯補 Headless 變體註) -
m-dev-guardrails.md:明文 headless US 省略module欄、其「必要輸入」改以 API Spec + 契約測試為主(2026-06-21 完成:輸入文檔表分 UI 軌 / Headless 軌、加 Headless 列與必要輸入差異註、module 必填規則納入契約故事、文檔準備流程補 Headless 變體) -
/progress:支援 headless US 從S.E2E起算、S.UAT後直接✅(無I.*)(2026-06-21 完成:Step 4.0 軌道判定讀 US frontmattertrack:、雙軌合法序列、序列內相鄰驗證、Headless 回退表、防呆與錯誤處理;新增track:欄定義於 m-dev-guardrails;v1.2.0) -
/us:Step 5.6 加「決定軌道(track)」(驅動軸自適應:無 mockup 專案預設 headless、對外 API 描述確認、其餘 ui)、headless 寫track: headless並省略module、frontmatter 範本分 UI/Headless 兩變體 + 共用本體(2026-06-21,v1.0.0→1.1.0) -
/next:工作項分類軌道感知(讀 US frontmattertrack:),拆 UI 軌 / Headless 軌兩張「階段→工作」對照表(headless:🔲→server E2E、S.UAT→✅)、設計文檔就緒檢查補 Headless server 列(2026-06-21,v2.0.0→2.1.0) -
/sbe:支援「消費者 / 契約故事」視角(headless US 的 SBE 場景以外部系統為主體)(2026-06-21 完成:軌道感知原則、新增「Headless 軌變體」對照——Given 改呼叫端/M2M、省租戶與 UI 操作流程、Then 焦點為對外契約、錯誤場景以契約語意為主;v1.0.0→1.1.0) -
/api-spec:對外端點強化契約穩定的引導(2026-06-21 完成:新增「對外契約穩定(Headless 軌 / 對外開放 API)」節——/api/v{n}版本化、棄用而非移除、Bruno 即 wire 契約守門員、契約凍結心智;v5.3.0→5.4.0) -
/design-language:澄清 headless US(無 UI、無 composition)不適用設計語言 precedent,add顯式傳入 headless 時報錯(2026-06-21;修正原待辦措辭——非「放寬接受 headless」,而是 headless 本就不該是 UI precedent;v4.0.0→4.1.0) -
/scaffold-project、/scaffold-module:headless 產品可不拉前端模組(2026-06-21 完成:scaffold-project 後續步驟加指引「Headless 產品通常只需 server(+docs)、不拉 web-mockup/web,admin console 日後再加」,v4.0.0→4.1.0;scaffold-module 無需改——模組選擇本就是顯式 opt-in,不加即不拉) - 評估是否新增 headless 軌專屬引導 skill → 決定:不新增。headless 軌由既有 skill 各自軌道感知(
/us//sbe//next//progress//api-spec讀track:分流)承載,符合方法論「skills as methodology」精神;另立專屬 skill 會割裂流程。--headless旗標亦不需——track:frontmatter 已是單一事實來源(2026-06-21)
相關文檔 (References)
內部文檔
- ADR-002: User Story 需求變更管理策略
- 開發流程指南
- 方法論定義:
.claude/rules/m-methodology.md、m-dev-guardrails.md、m-server-common.md
背景脈絡
- 本 ADR 源於釐清「app-server 的 service 由 US + web/mockup 驅動,平台服務的(大部分)由契約驅動」這條驅動軸,進而認定 headless 工作該有一級軌而非放逐 / 退化路徑。
變更歷史 (Change Log)
| 日期 | 變更內容 | 變更者 |
|---|---|---|
| 2026-06-21 | 初版:新增 Headless 契約驅動 API 軌,定義驅動軸判準、軌道流程、契約穩定紀律與 rules/skills 待辦 | AppFuse Team + AI Assistant |
| 2026-06-21 | 全部待辦落地:rules(m-methodology、m-dev-guardrails 含新增 track: 欄)+ skills(/progress 縮短狀態機、/us 寫 track、/next 工作項軌道感知、/sbe 契約視角、/api-spec 對外契約穩定、/design-language 排除 headless precedent、scaffold 指引)皆軌道感知。決定不另立 headless 專屬 skill(軌道感知內建於既有 skill)。Headless 軌成方法論一級公民 | AppFuse Team + AI Assistant |
文檔維護者: AppFuse Team + AI Assistant 最後審閱: 2026-06-21