table line
table 是其他 line kinds 的父資源。它把作者選定的穩定 ref 對應到 live table ID;顯示名稱可以改,ref 才是 IaC identity。
JSONL Line
{"kind":"table","ref":"orders","spec":{"name":"Orders","description":"Fulfilment queue","key":"order_no","settings":{"default_permissions":{"can_read":"all","can_insert":false,"can_edit":"none"}}}}欄位契約
頂層對應 IacTableLine:
| 欄位 | 必填 | 精確契約 |
|---|---|---|
kind | 是 | 固定 "table" |
ref | 是 | authored ref pattern,最多 64 字元 |
state | 否 | "present" 或 "absent",預設 "present" |
renamed_from | 否 | 舊 table ref;同一 authored ref pattern;可為 null |
spec | 條件式 | IacTableSpec object;present 通常提供,absent 可提供以採用後刪除 |
spec 只接受:
| 欄位 | 必填 | 精確契約 |
|---|---|---|
name | 是 | 非空 string,最多 64 字元 |
description | 否 | string,預設 "",最多 512 字元 |
key | 否 | 本 table 的 column ref 或 null;未提供時由第一個非 computed column 決定 |
settings | 否 | object 或 null;可承載 table create settings,例如 default_permissions、column_acl,以及 agent 寫入治理的 opt-in agent_writes_via_commands_only——既有資料表只能經由此處設定,因為 REST 的 table update 只能改 name 與 description |
moderators | 否 | 原始 user ID 或 $user:<username> token 的陣列,也可為 null;最多 50 個;與順序無關;PUT 語意。禁止 $dept: / $smc: / $room: |
settings.column_mapping 與 settings.iac 由伺服器擁有,禁止 authored。Client access 必須使用 client_access line,而不是藏回 table settings。
Moderator 是取代,不是新增
moderators 宣告的是整個 moderator 集合。Apply 會整批取代,而不是合併,因此一份宣告了 moderator 的文件會靜默移除任何在別處加入的人。三種狀態是真的不同:
- 省略——moderator 不受管理,IaC 完全不碰。
[]——清空 moderator 集合。- 一個清單——moderator 集合變成剛好等於該清單。
重新排序是 noop:兩邊都會正規化成排序後的 ID 清單。Live 集合若偏離 last-applied spec,會像其他欄位一樣以 moderators 出現在 drifted_fields。
Export 只在 live 集合非空時才輸出 moderators,因此 export → import 的往返永遠無法清空 moderator;要清空必須手寫 moderators: []。
每一項可以是供同環境往返使用的原始 user ID,也可以是可攜的 $user:<username> token。其他 identity-token family 不合法,因為 department、social client 與 chatroom 都不能成為 table moderator。Token 在 plan 與 apply 都以文件所屬公司為錨點解析,失敗即關閉;authored token 永不持久化,last-applied state 儲存 canonical user ID,而 export 在有 username 時輸出 $user:<username>,否則退回原始 ID。詳見可攜身分 token。
moderators not found (or deleted): ['<id>']
moderators outside this table's company: ['<id>']
cannot resolve this table's company for moderator validationsettings.default_permissions.audience 只在 department scope 合法
default_permissions 新增了 audience 鍵:"scope"(預設)或 "company"。在 department scope 的資料表上,"company" 會把該表的 defaults 從「只有所屬部門」放寬到「同公司的每一個 internal principal」。在 chatroom 或 company scope 的表上這個值沒有意義——resolver 會忽略它——所以 IaC 選擇拒寫,而不是留下一個「看起來像全公司共享」的 settings 回音。
這道閘對每一個非 state: "absent" 且帶 spec 的 table line 執行,而且會擋兩次:
- 在 plan,以 validate 階段錯誤掛在該行上。Plan 不 applyable,apply 回
422且什麼都不執行。 - 在 apply,改對live 資料表自身的 scope 重驗,而不是文件宣告的 scope。直接呼叫 apply、或拿一份表搬走後已 stale、不再與 live state 相符的 plan,都繞不過去。此時它是
200內該行的 apply 錯誤,其他每一行照常執行。
settings.default_permissions.audience "company" is only valid on department-scoped tables
settings.default_permissions.audience must be "scope" or "company", got '{value}'第二則訊息中的值是以 repr 輸出,因此錯誤字串會帶引號。兩則都出自與 REST 相同的共用驗證器,所以文字逐字相同:POST .../tables 兩則都可能以 400 拋出;PATCH .../default-permissions 只會以 422 拋出「僅部門層有效」那一則——因為該 payload 的 audience 是型別化 literal,超出 scope|company 的值會先被 request validation 以一般的 pydantic literal_error 擋掉。
Key-level settings 合併帶來兩個後果。Export 會原樣輸出 settings,只扣掉 column_mapping、iac 與 client_access,因此 authored 的 audience 能撐過 export → 重新匯入的往返,並重新規劃為 noop。但 apply 是以整個鍵取代 default_permissions,不是逐欄合併:用一個省略 audience 的 default_permissions 物件重新 author 這張表,下一次 apply 就會靜默撤銷該共享。
Ref 與身分規則
ref 與 renamed_from 必須符合 ^[a-z0-9][a-z0-9_-]{0,63}$。它們是 internal-key refs:以小寫 slug 跨環境穩定解析,不是 table display name,也不是 UUID。Table refs 在文件內必須唯一。
Child line 用 table: "orders" 指回這個 ref。Column、rule、trigger、view 與 public_read 的 child ref,加上固定的 client_access identity,再形成 orders.{child};它們在該 qualified namespace 內跨 kind 不可碰撞。Table spec.key 同樣填 column ref,例如 order_no,不得填 col_a1b2c3 internal key,而且既不能是 boolean 也不能是 json 欄位。
生命週期與規劃
- 沒有 state claim 且沒有可唯一採用的 live table:
create。 - 依 spec 能唯一辨認未管理 live table:
adopt。 renamed_from指向既有 state:move,並連帶更新 child qualified refs。- Owned fields 不同:
update;一致:noop。 state: "absent":delete。Table 是唯一可在 absent 時帶 spec 的 kind,以支援 adopt-then-delete;刪除是 soft delete,仍須審查依賴 warning。
單純從文件省略 table line不會刪除它。column_mapping 由伺服器在欄位變更時維護,不屬於 last-applied authored spec。
驗證錯誤
缺少 ref:
[{"type": "missing", "loc": ["table", "ref"], "msg": "Field required", "url": "https://errors.pydantic.dev/2.12/v/missing"}]不合法 ref(以 Bad ref 為輸入):
[{"type": "string_pattern_mismatch", "loc": ["table", "ref"], "msg": "String should match pattern '^[a-z0-9][a-z0-9_-]{0,63}$'", "ctx": {"pattern": "^[a-z0-9][a-z0-9_-]{0,63}$"}, "url": "https://errors.pydantic.dev/2.12/v/string_pattern_mismatch"}]重複 ref 與伺服器擁有 settings:
duplicate table ref 'orders'
settings.column_mapping is server-owned and cannot be set via IaC
settings.iac is server-owned and cannot be set via IaC後兩類是目前僅本機穩定攔截的 validator 訊息之一。精確 detail 來源:components/iac/parse.ts。
動手試試
在 IaC 工作台貼上範例,先把 key 改成尚未宣告的 ref,再加入 settings.column_mapping。修正本機錯誤後,對測試 scope plan 並核對 table action。