Permissions apply to AI too
A useful assistant has to read a lot: if it only reads one folder it answers badly. But reading a lot cannot mean reading everything. borc has one rule: the model only sees what the user could already open, and permissions are applied inside the search, before any text reaches the model.
Two layers that intersect
On Windows network shares both are needed:
| Layer | Where it lives | Applies to |
|---|---|---|
| Share permissions | On the share | Every file of that source |
| NTFS ACLs | On each file and folder | That file |
A user sees a file only when both allow it. Only data read rights count (FILE_READ_DATA, GENERIC_READ, GENERIC_ALL): traversing folders or reading attributes is not enough.
A deny always wins, even where Windows would apply entry order: it is a prudent choice, declared to the customer. And when in doubt the file is invisible: any error while reading permissions removes it from the index instead of adding it by mistake.
The cases almost everyone gets wrong
- Everyone and Authenticated Users apply to domain users. A local borc account, or a Google user with no AD link, was never authenticated by the file server: it only sees what is explicitly granted.
- Local groups of the file server (BUILTIN\Users, groups created on the server) are not in tokenGroups: their members are read from the server over RPC during the scan and expanded into the domain groups that contain them.
- NAS boxes with their own users (say a Synology with no domain): groups are mapped by hand to AD groups at install time. Without a mapping the files stay invisible.
- CREATOR OWNER only matters for inheritance: on the file it is already replaced by the real user.
The filter lives in the query
The filter is not an instruction to the model, it is a condition in the search, identical for the vector leg and the text leg:
WHERE share_allow && $principals AND NOT (share_deny && $principals)
AND acl_allow && $principals AND NOT (acl_deny && $principals)
With pgvector 0.8 the vector search uses hnsw.iterative_scan, so the permission filter does not empty the result set. When permissions change, the lists are rewritten without recomputing embeddings, and opening a cited source re-checks the permission at that moment.
Administrators can see the list of documents with no known users: files whose permissions name SIDs that resolve to nobody. It is the honest way to say "these were excluded out of caution".