Actor
A person, an agent, an API key, or an external auditor. Each holds its own identity and permission set — nothing acts on behalf of something else with borrowed credentials.
AI governance
Most systems have a role model for users and a separate, vaguer arrangement for automation and API keys. That split is how automated activity ends up outside the control framework. Here there is one model, and an agent is simply another actor within it.
Send your current role structure and approval matrix. We will map it and flag the conflicts.
Six dimensions
Every grant answers six questions at once. Systems that collapse this to a role name are the ones where "can this person do that" turns out to be unanswerable.
A person, an agent, an API key, or an external auditor. Each holds its own identity and permission set — nothing acts on behalf of something else with borrowed credentials.
Tenant, entity, department, location, and project. Permissions are granted within a scope, so a controller of two subsidiaries in a group of nine sees exactly two.
Bills, invoices, journal entries, contracts, vendors, employees, and reports as distinct object types with their own verbs rather than one blanket read-write flag.
Read, draft, post, approve, release, administer. Deliberately more granular than create-read-update-delete, because financial verbs are not CRUD.
Monetary limits per verb per scope. Approve up to $10,000 in one entity and $50,000 in another is a normal configuration, not an edge case.
An invoice has a total, a cost, and a margin. A portal user sees the first and cannot request the others at any layer of the API, including exports.
The common architecture checks permissions in the application layer: an endpoint asks whether this user may do this thing, and proceeds if the answer is yes. It works until somebody adds an endpoint that forgets to ask — which is the single most common cause of data exposure in multi-tenant systems, and it is a class of bug that code review catches inconsistently.
Ours is enforced in the data access layer. Every query carries an actor and a scope, and a query without them is rejected rather than executed. A developer cannot write an unscoped read and have it succeed, because it fails below the code they are writing.
Row-level security in Postgres sits underneath that as defence in depth, so a mistake in the access layer itself does not become a cross-tenant read.
Generic permission models offer create, read, update, and delete. Finance does not work that way. The difference between drafting a bill, posting it, approving it, and releasing payment against it is not a difference in CRUD verbs — they are four distinct authorities that a control framework deliberately separates.
Modelling them as distinct verbs is what makes segregation of duties expressible at all. Where a system maps them onto update-and-delete, the conflict matrix cannot be represented in the permission model and has to live in a policy document instead, which is to say nowhere enforceable.
Object-level permissions answer whether you can see an invoice. They do not answer whether you can see its cost and margin, which are on the same record. For customer portals, external auditors, and junior staff, that distinction is the whole requirement — and a system that can only grant or deny the whole object forces you to choose between over-exposure and building a separate reporting copy.
A small number of our engineers can access production under time-bound break-glass that requires a second approver, is logged, and is reported to you. Routine support does not include production data access, and the log of every break-glass event is available in the security pack.
Conflicts
Questions
We will map it into the model and flag the conflicts before anything is implemented.