Whose permissions does your AI read with?
TechnoVision
Publication date pending · 7 min read
Ask an AI assistant bolted onto an ERP a question, and something has to run a query. The interesting question is not which model answered. It is which database user ran that query.
Almost every integration answers "the administrator’s", because that is the answer that always works. Nothing is ever refused, no demo ever fails, and the feature ships. Then it goes into a business where the warehouse team is not supposed to see payroll, and it cannot be installed at all.
This is not a prompt problem
The usual response is to instruct the model: "only answer questions about stock". That is asking a language model to enforce a permission boundary using good manners.
It will hold most of the time. It will not hold when somebody asks a question that is genuinely ambiguous, or when a model update changes how literally it reads its instructions, or when someone phrases a question the way an auditor would. And when it fails, it fails silently: the answer looks like every other answer.
A permission boundary that depends on the model choosing to respect it is not a boundary. It is a preference.
The architectural answer
Run the query as the person asking. In Odoo that is one expression - env[model].with_user(the asker) - and the effect is that enforcement stops being yours. Model access rules, record rules, group inheritance and the accounts that bypass all of it are applied by the same code that protects every other screen.
Two consequences follow, and both are correct:
- Two people asking the same question get different answers. That is not a bug to be smoothed over; it is the whole point.
- Records somebody cannot see are absent from the result, not marked as withheld. Telling a user "3 records hidden" leaks the fact that they exist, which for a customer list is often the sensitive part.
Readable and sendable are different decisions
Running as the asker is necessary and not sufficient. An accountant can read your user table. That is no reason for a question about invoices to ship it to a model vendor in the United States.
So there are two boundaries, and the outer one is not about permissions at all. Somebody decides which models the assistant may read from in the first place - a data-egress decision, made once, by a person who is thinking about where data goes rather than who may see it. Inside that, each question is still bounded by the asker’s own rights.
The field nobody thinks about
Then prove what it read
The objection that stops most AI pilots in a regulated business is not "it might be wrong". It is "we would not know what it had seen".
That is answerable. Every query the assistant runs can be a record: the model, the operation, the record ids, the count, whether it was refused. A refusal is the enforcement working and is worth keeping for exactly that reason. Add the group that entitled the person, and the log reads "read as Sara, entitled by Billing Manager via Accounting / Billing" rather than a row of ids.
A test for any assistant you are offered
- Ask the same question as two people with different access. If the answers are identical, it is reading as somebody else.
- Ask for something one of them cannot see. If it refuses politely rather than not finding it, it is filtering after the fact.
- Ask what it read last Tuesday. If nobody can answer, you cannot install it anywhere that matters.
We built AI Assistant for Odoo around exactly this, because the alternative was a demo that could not be sold to anybody with an auditor.