← 全部文章
應用搭建 開發者 已釋出 · · 作者 ObjectStack Team

Retool 與受治理 AI 應用平臺:能否審查業務許可權

Retool 的 RBAC、審計日誌、SSO 和自託管能力很強。真正要比較的是業務許可權層:退款、審批、寫入動作如果散落在 JavaScript 繫結裡,AI 改動就很難被業務負責人用 diff 審查。

Retool 與受治理 AI 應用平臺:能否審查業務許可權
  • Retool
  • 低程式碼
  • 內部工具
  • 治理
  • AI 原生

TL;DR: Retool 的訪問治理很強:RBAC、審計日誌、SSO、原始碼管理、Enterprise 自託管都是真實能力。問題不在“Retool 沒治理”,而在治理的。RBAC 控制某個角色能觸及哪些資源;真正的業務許可權——這個人能不能發起一筆 1.2 萬美元的退款?——往往分散在按鈕 Hidden、輸入框 disabled、查詢 transformer 和腳本里。工程團隊可以通過規範和程式碼審查管理它,但 AI 參與修改後,業務負責人很難只看一份 diff 就判斷“誰能做什麼”是否改變。缺口不叫安全功能缺失;它叫業務許可權沒有被宣告成可審查的事實。

設想世上最尋常的那個 Retool 應用:一個退款控制台。一位工程師花一個下午就把它建好——一張訂單表、一個“退款”按鈕、幾條查詢。客服在用。它很棒。這正是 Retool 最出彩的樣子,而 Retool 在這件事上確實是品類裡最好的。

如今半年過去了。當初構建它的工程師已經換了團隊。安全團隊正在做訪問審查,向新的負責人丟擲一個一句話的問題:“哪些角色能發起超過 1 萬美元的退款,以及它究竟在哪裡被強制執行?”

看看新負責人為了回答得做些什麼。沒有一個單一的地方可供檢視。他開啟應用,開始讀 JavaScript。

grep 測試

“它在哪裡被強制執行”,在一個真實的 Retool 應用裡實際長這樣。發起一筆大額退款的許可權,至少散落在三處彼此獨立的表示式中,每一處都是手寫的,每一處形狀都不同:

// 1. refundButton → “Hidden” 屬性
{{ currentUser.groups.includes('admin') ||
   (currentUser.groups.includes('support_lead') && refundAmount.value <= 10000) }}

// 2. refundAmount input → “disabled” 屬性
{{ !currentUser.groups.includes('support_lead') }}

// 3. issueRefund query → transformer(這才是真正寫入的那部分)
if (refundAmount.value > 10000 && !currentUser.groups.includes('finance')) {
  throw new Error('Refunds over $10k require finance');
}

三個地方。三個微妙不同的條件。按鈕對某些使用者隱藏自己;輸入框對另一些使用者停用自己;查詢則對第三組人丟擲錯誤。它們本應加總成一條自洽的規則——“二級客服可退到 1 萬美元,更高的歸財務”——但沒有任何東西保證它們會如此。把一個按鈕隱藏掉,只要有人換條路觸發,底下那條查詢照樣會跑。下個季度新增第二條寫入路徑卻忘了那道 finance 檢查,你就有了一個任何螢幕都不會暴露的漏洞。

把這叫作 grep 測試:要回答“誰能做 X”,你是讀一條宣告過的規則,還是得對整個應用 grep?如果是 grep,那麼這個應用在許可權層就沒有被治理——它僅僅是被編碼出來的,而訪問治理(Retool 做得無可挑剔)所在的那一層,恰好高過真正能傷到你的那個東西一層。

作為對照,這裡是同一份許可權作為一項宣告過的事實——一條規則,無論你是從哪個按鈕或哪條查詢進來的,執行時都會在每一條路徑上強制執行:

action: issue_refund
  who_can_run:
    - role: SupportLead   when: amount <= 10000
    - role: Finance       when: amount  > 10000
  requires_approval:      when: amount > 10000      # 一道預防性的閘門,而非一個被丟擲的錯誤
  audit: always

只有一處可讀。只有一處可改。只有一件事要讓審查者——或一個 AI——去推敲。三處手工維護的表示式與一條宣告過的規則之間的差別,正是“應用是被編碼出來的”與“應用的許可權是被治理的”之間的全部差別。

為什麼原始碼管理填不上這道缺口

精明的 Retool 工程師的反駁很在理,你得精確地回應它:“我們有 Git 支撐的原始碼管理、審計日誌和 RBAC。改動會在 PR 裡審查。訪問是被治理的。還缺什麼?”

具體缺三樣東西。

第一,對一個 Retool 應用的 PR,審查的是散落在各元件間的 JavaScript 與繫結——你在做程式碼審查,這意味著 (a) 它需要一位工程師,且 (b) 不存在一個結構化的表徵來說明*“這次改動改變了誰能發起一筆大額退款。”* 審查者必須自己察覺到:三個元件之外的某個 Hidden 表示式的一點小改,挪動了一道許可權邊界。散落邏輯的 diff,恰恰把你最需要看見的那個東西藏了起來。

第二,原始碼管理審查的是程式碼,而非作為事實的許可權。“這個 PR 改變了誰能退款超過 1 萬美元嗎?”不是一個 Git diff 能直接回答的問題;這是一個你得在腦子裡追著程式碼去回答的問題。而上面那條宣告過的規則讓這份 diff 變得微不足道:who_can_run 改了,或者沒改。

第三——也是對行業走向最要緊的一點——低程式碼的整個前提,就是非工程師和 AI會去改這個應用,常常是在視覺化編輯器裡,常常不經過傳統 PR。你所倚仗的那種治理(程式碼審查),未必覆蓋低程式碼本來要服務的那些改動。審計日誌會在事後告訴你某個 Hidden 屬性變了——是檢測式的,不是預防式的——但在它上線之前,業務負責人未必看見過它改變了什麼許可權

AI 不會打破這一點。它會成倍放大它。

多年來 grep 測試還能活下去,是因為有一個人寫下 JavaScript,另一個人承載著每條規則存活在何處的知識。散落的邏輯,只要是人構建並記得的,就還摸索得通。

把一個 AI 對準同一個應用,經濟賬便在兩個方向上同時反轉。AI 能在一分鐘內生成五十個繫結和十幾個 transformer——它產出許可權決策的速度比任何審查者能追蹤的速度都快。而要審查它產出的東西,你又回到了一屏接一屏地讀 JavaScript,因為依然沒有一份單一的、結構化的許可權表徵可供 diff。“Retool AI”和智慧體(2025)真實存在且有用,但它們是在同一套手工搭建的底座之上做自動化:智慧體是被治理的(Retool 能限定它可以呼叫什麼),但智慧體所編輯的那個應用卻不是——它在任何一種 AI——或人類——能當作事實而非程式碼來審查的形式上,都沒有被許可權治理。

AI 最擅長快速產出的東西,恰恰也是這種模式下最需要結構化審查的東西。

Retool 才是正確選擇的場合——以及後設資料模型讓你付出代價的場合

兩個方向上都要誠實,因為一篇一邊倒的文章,對一個真要做決定的人毫無價值。

Retool 的訪問治理確實是同類最佳,而且對一大批應用來說,grep 測試很可能咬不到你:一個由可信員工操作、藏在 SSO 之後、由當初編寫它的同一批工程師維護的內部工具,其中“二級客服可退到 1 萬美元”被強制執行在三處恰好彼此一致、又極少改動的地方。對這樣的場合——以及對那種需求一旦古怪就能隨時落到 SQL 和任意 JavaScript 的自由——Retool 都很出色,而“快速接好一個工具”這件事我們是贏不了的。

而宣告式後設資料模型在另一個方向上有實打實的代價:你拿原始的靈活性,換來了可讀性。當模型裡沒有容納它的地方時,你沒法只是往一個屬性裡粘一段任意的 JavaScript;把真正不尋常的邏輯表達成宣告過的規則,比隨處可用的 {{ }} 更受約束。對一個用完即棄的工具來說,這份約束是純粹的額外開銷。只有當“誰能做什麼”是某種你會被要求去證明的東西時——被審計人員、被監管方,或被下一任負責人——並且當做改動的是一個 AI、而非原作者時,這個模型才值回它的代價。

那就是那條線。線之下,Retool 憑實力取勝。線之上,grep 測試正是半年之後、在某個拿著寫字板的人面前,你會栽的那一項。

ObjectStack 的立場

ObjectStack 保留了 Retool 做對的東西——強大的訪問控制、自託管、你自己的基礎設施——並把許可權下沉到同一個被治理的層。應用的邏輯是開放、可讀的後設資料:一個像 issue_refund 這樣的操作,攜帶著它自己的 who_can_run、它自己的審批閘門、它自己的審計要求,宣告一次,由執行時在每一條路徑上強制執行。一次 AI 改動,就是針對那份宣告過的許可權的一份 diff——“這次改動讓 SupportLead 能退到 2.5 萬美元”是一句非工程師能在上線前讀懂並批准的話——而不是一個你日後才靠 grep 發現的 Hidden 表示式。

我們並不打算在“落到 JavaScript、午飯前就釋出一個工具”這件事上勝過 Retool。這個主張更窄,且只在那條線之上才要緊:當 AI 在編寫你的內部軟體時,誰能做什麼應當是一項你能在一個地方讀到、並能當作 diff 來審查的事實——而不是三處表示式的某種湧現屬性,它們必須彼此一致、通常也確實一致,直到它們不一致的那個季度。