跳至主要内容

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 驅動

  1. 平台服務:整合外部權威來源,對下游 app 開 API。
  2. 應用對外開放的 API:app-server 把自有資料開給外部系統(ERP 交換帳務、客戶官網取資料)。
  3. 無 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 軌

核心理由:

  1. 方法論的 Server 階段(JUnit + Bruno)本就是契約驅動,新增軌道是「組織既有能力」而非發明新流程。
  2. headless 工作(平台服務、對外 API、無 UI 整合)是真實且普遍的一類,值得一條一級軌,而非放逐或退化路徑。
  3. 區分軌道的是驅動軸(契約 vs US/UI),不是功能——此判準清楚、可操作。
  4. 讓產品級 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 frontmatter track:、雙軌合法序列、序列內相鄰驗證、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 frontmatter track:),拆 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-spectrack: 分流)承載,符合方法論「skills as methodology」精神;另立專屬 skill 會割裂流程。--headless 旗標亦不需——track: frontmatter 已是單一事實來源(2026-06-21)

相關文檔 (References)

內部文檔

背景脈絡

  • 本 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