Skip to Content

rule line

rule 把 table 的規則清單拆成可獨立審查、移動與刪除的 IaC resource。IaC ref 提供穩定 identity;apply 會把各 rule lines 合併進通過既有 rules validator 的完整規則集合。

JSONL Line

{"kind":"rule","table":"orders","ref":"unique_order_no","spec":{"type":"unique","name":"Order number is unique","columns":["order_no"]}}

欄位契約

頂層對應 IacRuleLine

欄位必填精確契約
kind固定 "rule"
tableparent table ref
reftable 內的穩定 child ref
statepresent/absent,預設 present
renamed_from舊 child ref 或 null
spec條件式object;present 必填,只有純 rename 可省略;absent 禁止

IacRuleLine.spec 在 IaC Pydantic model 中刻意是 Dict[str, Any],所以本機 parse 不假裝有一個不存在的 typed union。伺服器 apply 會交給既有 TableRulesPayload/shared validator;共同 authored 欄位是必填 type,以及可選 namewhen 與 type-specific fields。作者不要提供 server-minted idconstraint_id;IaC ref 已負責 identity。

type 的精確集合是 compareuniqueno_overlapexistsnot_existstransitioncheckrequirerequire_approvalchannelinvariantimmutable_when。各 type 的必要欄位由 rules validator 決定,例如 unique.columns、compare/check predicates、transition columns、exists/not_exists 的 target/match/where、channel/invariant policy,以及 immutable_whenprior_whencolumns。完整規則 payload 請查閱規則 API

Ref 與身分規則

Qualified identity 是 {table}.{ref},例如 orders.unique_order_no。同一 table 的 column、rule、trigger、view、public_read refs 與固定的 client_access identity 共用這個空間;任何跨 kind 重名都會被拒絕。

Rule spec 裡位於 columnleftrightstart_columnend_columndate_columnsort_byvia 的字串,columns/scope_columns 陣列,以及 filters/data object keys,都被視為同 table 的 column refs。Plan 會 fail closed 地翻成 internal keys;exists/not_exists 的跨表 target/match 語意仍由 server validator 以 live table 關係核對。

由於 differ、executor 與 export 三邊宣告的是同一組 key,immutable_when 的鎖不需要任何特例就能走完整趟:prior_when[].column 由通用的 single-ref walker 接手(column 出現在 spec 任何位置都算 single-ref key,包含巢狀 predicate 清單內),columns 則由 list-ref walker 處理。因此一條鎖能通過 export → plan → apply,並在重新 plan 時是 noop

Rule spec 也可以帶 $row.{column ref} 樣板 token,export 會寫成 ref,匯入時再翻回內部 key。無法解析的 token 會原樣保留而非 fail closed——詳見可攜身分 token

在 rule 的 policy 子樹內,SCP 的 link_membershiplink_target leaf 是以形狀辨識——鍵是否存在,加上各自的允許清單,link_membership{link, op, value, require_present}link_target{link, target, quantifier, require_present}——接著由 plan、apply 與 export 原樣複製過去。

要記住的結果是:link_targettarget 子樹指的是被連結表的欄位,永遠不會對 rule 自身的表解析。過去 ref walker 會依位置比對 target 內裸的 column 鍵,產生誤導性的 unknown column ref '<near table>.<linked column>'——或者當近端表剛好有同名欄位時,靜默把錯誤的 key 寫進儲存的 policy。Leaf 自身的 link 仍會在 apply 時驗證,因此原樣帶過不可能寫入無法解析的東西。

這類 leaf 不會被拒絕。它在 export → plan → apply 之間逐位元組保留,並且是透過 REST 編輯——target.column 無法在 IaC 中撰寫或翻譯。

注意: 這條邊界只適用於 policy 鍵之下。在 policy 之外,link 只是普通的 JSON 鍵——出現在 api_call 的 body 或 headers、invoke_command 的輸入、json 欄位的值——而且欄位本身也可以就叫做 link,並成為 view filters 或 trigger data map 的鍵。那些文件會被正常走訪,不會被拒絕。

生命週期與規劃

Present line 可規劃 createadoptmoveupdatenooprenamed_from 讓同一 stored rule 換 ref;state: "absent" 規劃從完整 rules 集合移除該 rule。Apply 走 validated PUT path,會保留文件未管理的其他 rules,而不是用單一 line 覆蓋整張表。

Rule semantics 可能建立資料庫 constraint、阻擋既有資料或影響 approval/channel policy。Local parser 與 plan 會先驗證文件內可見 refs、live diff 與集合 cap;free-dict 的 type-specific shared validator 仍在 apply 的持久化路徑執行,因此 apply result 可能再出現 per-line error。

驗證錯誤

Lifecycle、parent 與跨 kind collision:

state=absent lines carry no spec (table lines are the sole adopt-then-delete exception) state=present lines require a spec (unless a pure rename via renamed_from) unknown table ref 'orders' duplicate ref 'orders.unique_order_no' (already declared in this document)

columns: ["missing"] 無法解析:

unknown column ref 'orders.missing'

若合併後的 rule 集合會撐破每表 10 條的上限:

rule cap exceeded (12 > 10); unmanaged rules occupying slots: [names]

前兩類 lifecycle detail 目前是工作台的 local-only validator contract;type-specific rules errors 來自 apply 的 downstream shared validator,不屬於工作台 byte-exact 字串。精確本機字串來源:components/iac/parse.ts

動手試試

IaC 工作台宣告 table、order_no column 與範例 unique rule,把 column ref 改成未知值以確認 validate error。修正後對測試 scope plan,再到規則 API核對 type-specific contract。

Last updated on