跳到正文
DEV Community· Talha Waqas·· 3 小時前AI 評分56

Inaya Business Workspace 如何讓 AI 助手操作業務記錄而不超越用戶權限

Letting an AI assistant act on business records without giving it more power than the user

AI 導讀

Inaya Business Workspace 以 guarded execution 處理 AI 對業務記錄的操作,先建立待核準提案,再按審批者實際權限核准後才套用。權限閘門按記錄類型沿用實際操作的權限檢查,提案、核准及拒絕均寫入活動記錄,並可用 node --test 作單元測試。此做法增加人工確認及逐類型補齊檢查的工作,且不保證 AI 建議正確;工作區尚未接受獨立安全審計。

正文

Adding an AI assistant to business software comes with an obvious temptation. You give it a service account, let it call your APIs, and it can "do things": approve a leave request, mark an invoice paid, move a purchase order forward.

The problem is that the assistant now has more power than the person talking to it. A junior employee who can't approve a purchase order can ask the assistant to, and if the assistant runs with broad permissions, it will.

In Inaya Business Workspace we took a stricter approach, which we call guarded execution. Here's how it works and what it costs.

Rule 1: the assistant proposes, it never executes

Every tool that changes something is a propose_* tool. When the assistant decides an invoice should be marked paid, it doesn't mark it paid. It creates an action request: target record, proposed change and reason, stored with status PENDING. Nothing about the real record changes yet.

Rule 2: approval re-checks the real permission

A person approves or rejects the request. Before it's applied, one server-side function decides whether the approver may do this:

// ai-action-approval-gate.js (simplified)
export async function resolveCanApprove({ orgId, targetRecordType, targetRecordId, proposedAction, membership }) {
  if (targetRecordType === "TASK") { /* same check the real task transition uses */ }
  if (targetRecordType === "INVOICE") { /* same check the real invoice transition uses */ }
  // one case per record type
}

For each record type, it re-derives exactly the check the real transitionX() function would apply to whoever runs it. An AI-proposed action can never be approved by someone who couldn't already do that thing by hand.

That gives us one source of truth. We don't keep a separate "AI permissions" model that can drift out of sync with the real one. Adding a new propose_* tool means adding one case to this function, and the review state machine stays the same.

Rule 3: it's a plain module, so it's testable

The gate lives in a plain library module with no dependency on the web framework. That lets us unit-test it with node --test, not only through HTTP round-trips. For a security boundary, fast tests matter: the gate is easy to change, so it needs to be easy to check.

Rule 4: the record is audited

Proposals, approvals and rejections are written to the activity log, so "the AI did it" is never the whole answer. There's always a person who approved it, and a record of what was proposed.

What it costs

  • Friction. Users must confirm actions the assistant could technically just do. We think that's correct for finance and HR, and annoying for trivial tasks.
  • Coverage work. Every record type needs its own case in the gate. An action type without a case can't be approved.
  • Honesty about limits. This protects against privilege escalation through the assistant. It doesn't make the assistant's suggestions correct, which is why a person reviews them.

Where this sits

Inaya encrypts documents on the client (AES-256-GCM) before upload, and its secure chat uses MLS (RFC 9420). The workspace hasn't had an independent security audit yet. We say so in the product, and we're saying it here.

If you've built AI actions into a multi-user app, I'd like to hear how you handled permissions: did you mirror them, or route everything through a human like we did?

來源:DEV Community · dev.to