術語

宣告與強制執行的落差

「宣告 vs 強制執行」(declared vs. enforced)指的是一個系統的配置允許你寫下什麼、與它的執行時在執行時真正檢查什麼之間的那道落差——一條沒有任何東西去強制的宣告,讀起來像一個保證,行為上卻只是一句註釋。

又稱 declared vs enforced聲明瞭但不強制紙面權限要麼強制要麼刪除

在實踐中

任何帶 schema、策略語言或設定介面的系統,都同時存在兩個集合:你被允許宣告的鍵,和真的有東西會依據它行動的鍵。它們一開始完全重合,然後悄悄分叉。一個標了「必填」、卻只有瀏覽器表單在遵守的欄位,於是 API 接受它為空。一項沒有任何任務會去讀的保留期。一個只有某一條程式碼路徑會檢查、而匯出介面不檢查的權限開關。它們被寫下時都是真的,然後在沒有任何東西報錯的情況下不再是真的——而這恰恰是這道落差能挺過審計的原因:沒有東西壞掉,設定還在那兒,介面上還顯示著「已開啟」。

一旦配置由模型來寫、而不是由建這個執行時的人來寫,這道落差在結構上就更危險了。模型是從示例和文件裡學會一種配置格式的,而這些材料裡沒有任何東西能區分「執行時會強制的鍵」和「執行時只是解析一下的鍵」:兩者都出現在示例裡,都能通過校驗,讀起來都很權威。於是 agent 會非常自信地宣告一項什麼都不做的控制——而最扎手的一點是,評審這份 diff 的人看到的是一行看上去完全正確的配置,然後批准了它。這就是 AI 編寫配置的典型失效形態:不是語法錯誤(那個每個校驗器都攔得住),而是合法、可信、卻不起作用的宣告。它在訪問控制上的特例有自己的名字——紙面權限:讀起來像一道邊界、實際什麼都不強制的後設資料。一個相關的跡象是,請求層面的過濾與服務端強制的邊界從外部看是無法區分的,因為它們都讓兩個測試賬戶看到正確的東西。

有一個問題能把這兩個集合分開,而且可以對任何一條聲明發問:如果我違反它,什麼會失敗、在哪裡失敗、動靜有多大?如果答案是「什麼都不會」,那這一行就是文件而不是控制,就該照文件來標註。於是任何一個可宣告的鍵只剩兩條站得住的出路——要麼強制它,要麼刪掉它。留著一個不被強制的鍵是第三條路,也是真正消耗信譽的那條,因為下游每個人都把它讀成一個保證:批准改動的評審者、抽查控制項的審計員,以及現在正從你的示例裡生成下一個應用的那個 agent。

ObjectStack 的做法是在編寫時點、而不是執行時關掉這道落差:定義面經過 schema 校驗,一條執行時不會去強制的宣告會在校驗門禁上被拒絕,而不是作為一個虛假保證釋出出去。而在「檢查本身可能悄悄降級」的地方——比如一條行級規則的謂詞引擎編譯不了——門禁呼叫的是執行時自己的判定函式,而不是去模擬它的行為,因此「被 linter 拒絕」和「被丟棄、不產生任何強制」是同一個布林值,不可能漂移成兩個不同的答案。

這個術語用在哪裡

真正用到這個術語的頁面與文章。