Skip to Content
核心概念JSONL IaCJSONL IaC 概念

JSONL IaC 概念

JSONL IaC 把一組彼此關聯的表格、欄位、規則、觸發器、檢視、授權、用戶端存取設定、資料列、組合式指令、逐室洞察選擇與免驗證公開讀取 token,寫成一份可版本控制的宣告。它適合管理「多個資源共同構成一個系統」的情境,不必把一連串命令的執行順序當成唯一真相。

IaC 是無條件可用的。Plan、apply、state 與 export 永遠開啟;沒有需要先啟用的 feature flag,舊有的「flag 關閉時回 400」回應也已經在所有 scope 上消失。CUSTOM_TABLE_IAC_MAX_BYTESCUSTOM_TABLE_IAC_MAX_LINESCUSTOM_TABLE_IAC_MAX_TABLESCUSTOM_TABLE_IAC_MAX_RECORDSCUSTOM_TABLE_IAC_SYNC_RECORD_LIMIT 仍然存在,但它們是容量調節參數,不是開關。

有一項輸入限制刻意屬於它們:每個實體行的 JSON 巢狀深度上限是 128 層 [/{,由寫死在 parser 內的防護擋下,沒有任何環境變數可以調高或調低。深度是就整行測量的,包含行本身的外框 —— record line 最外層的 { 就是第 1 層 —— 字串字面值內的括號不計入。它同時是每行的第一道檢查,排在 JSON 解碼、header 唯一性規則與 record/line/table 各項 cap 之前,因此一個過深的行即使同時是壞掉的 JSON、或本來也會撞破某個 cap,回報的仍是巢狀中止:

line 3: excessively nested JSON structure (max depth 128)

只有文件層級的位元組上限與 UTF-8 檢查比它更早執行。parse 階段其餘的錯誤目錄見錯誤階段

為什麼使用 IaC

一般 API 呼叫描述「現在做一件事」;IaC 文件描述「最後應該長成什麼樣子」。穩定的 ref 讓規劃器在環境間解析同一套關係,而 plan 先把 live 狀態與宣告的差異攤開。這帶來三個實際好處:

  • 可審查:JSONL 與 plan diff 都能進入變更審查,建立、更新、移動與刪除不再藏在腳本控制流程裡。
  • 可重複:相同文件可套用到新的 chatroom scope;套用完成後再 plan,既有資源應收斂為 noop,資料列則為 skip
  • 可組合:一份文件可以宣告多張表與跨表欄位,規則、檢視和授權再以 ref 指向它們。

注意: IaC 不會因為資源從文件消失就刪除它。刪除必須以 state: "absent" 明確宣告,讓破壞性變更保持可見。

system 是狀態命名空間與自動標籤

第一行的 header.system 同時扮演兩個角色:

  1. 它是伺服器 IaC state 的命名空間。ref 只在這個 system 內代表穩定身分,plan/apply 會用它把宣告與 live resource 對上。
  2. 非空的 system 會成為受管理表格的 IaC 自動標籤,方便辨認資源由哪個宣告系統管理。

system 最長 100 個字元;空字串是合法值,但不會同步自動標籤。請為長期維護的系統選一個穩定名稱,不要把部署時間或環境產生的 ID 放進去。

JSONL 心智模型

JSONL(newline-delimited JSON)的規則很小,但很嚴格:

  • Content-Type 使用 application/x-ndjson;每個非空白實體行只能是一個完整 JSON object。
  • header 可省略;若提供,它必須是第一個非空白行且只能出現一次,版本目前固定為 1。省略時 system 是空字串。
  • 空白行會忽略;# 註解不是 JSON,不能放進文件。
  • 後續行依文件順序規劃。先宣告 table,再宣告使用該表的子資源;跨表欄位也應在目標表 ref 可解析後出現。
  • 頂層未知欄位與各 kind 不接受的欄位都會被拒絕,而不是靜默忽略。

十二種 line kind 是 headertablecolumnruletriggerviewgrantclient_accessrecordcommandinsight_selectionpublic_read。這也是 discriminated union 宣告它們的順序,而 custom_table_iac_state.resource_type 同樣新增了這三個值。

三種 scope 都提供經驗證的 GET .../tables/iac/contract authored-contract 路由:

  • /private/module/custom_tables/chatroom/{chatroom_id}/tables/iac/contract
  • /private/module/custom_tables/department/{department_id}/tables/iac/contract
  • /private/module/custom_tables/company/tables/iac/contract

IacDocumentContractResponse 包含 versionkindsresource_typesline。Runtime 的 line 值是一條合法 header;更重要的 OpenAPI 用途,是讓 schema 帶出完整的 discriminated IacLine union——plan/apply 接收的是原始 JSONL bytes,無法自行讓 request model 出現在 OpenAPI。生成工具應讀 contract/OpenAPI schema,但 apply 前仍必須對 live state 執行 plan。

其中三種不遵循其他 kind 共用的 {table}.{ref} 形狀。command 屬於 scope 層級,使用 command:{ref}insight_selection 使用 insight.{chatroom uuid} 且完全沒有 specpublic_read 雖是資料表子資源,但與單例的 client_access 不同,同一張表可以有多個。

一個小型系統

下列每一行都是獨立 JSON object;contactsemail 是作者選定的穩定 ref,不是伺服器 ID。

{"kind":"header","version":1,"system":"crm","description":"Shared contact workflow"} {"kind":"table","ref":"contacts","spec":{"name":"Contacts","description":"Managed by JSONL IaC","key":"email"}} {"kind":"column","table":"contacts","ref":"email","spec":{"name":"Email","type":"text","required":true}} {"kind":"view","table":"contacts","ref":"directory","spec":{"name":"Directory","is_shared":true,"config":{"columns":["email"]}}} {"kind":"record","table":"contacts","data":{"email":"alex@example.com"},"on_drift":"skip"}

Plan 會先解析這些 ref,再產生 createadoptmoveupdatenoopdeleteorphanedinsertskip action。這份文件只是 desired state;真正的 live 差異仍以伺服器 plan 為準。

接著閱讀

完整部署還需要幾個 REST 呼叫:用 REST 補完 列出六項文件裝不了的設定,以及每一項之後由哪一邊擁有。

動手試試

把上面的五行貼到 IaC 工作台。先用本機驗證確認 JSONL 與 ref,再選擇一個測試 chatroom 執行唯讀 plan;不要在第一次看見 diff 前 apply。

Last updated on