Data access
RBAC in Django: who may see which tables, columns, and rows. Session authentication and org membership are not that grant. A manager may run conversations without being entitled to payroll or customer data.
The sandbox does not query GenBI. chat/nono_profile.py still records a genbi entitlement bit
when the user has a UserDataRole, and the action log stores it, but that bit does not add a
tool or a server. fetch_memory still refuses memory entries whose source is genbi, so old
staged rows are not copied into the model's context.
What is still enforced
DataRole, DataPolicy, and UserDataRole are independent of org membership. DataPolicy
grants one role access to one table:
allowed_columnsis an explicit list, or["*"].row_filteris empty for all rows, a leaf predicate, or nestedall/anypredicates.- table
"*"with columns["*"]is the unrestricted grant used bybi_admin. - users with no matching grant have no policy for that table.
Supported leaf operations are eq, neq, in, not_in, lt, lte, gt, gte, and
is_null. Values may use $user_id or $username. Example:
{
"allowed_columns": ["EmployeeId", "FirstName", "Title", "ReportsTo"],
"row_filter": {
"column": "ReportsTo",
"op": "eq",
"value": "$user_id"
}
}
Policies are grants. Multiple roles union their columns and row access; an unrestricted row grant therefore dominates a restricted grant for the same table. Keep roles small and avoid assigning a broad role alongside a restricted one.
The policy DSL is validated in chat/data_authorization.py. Arbitrary SQL is not accepted. There
is no SQLite process and no sqlglot rewrite step behind it anymore: nothing in the sandbox
executes a GenBI query.
Administration
The migration creates bi_admin, grants it wildcard access, and assigns it to existing
superusers. New users have no data role until one is assigned. Data roles, table policies,
assignments, and audit events are visible in Django admin.
The session-authenticated management API is under /api/data-authorization/ and is superuser-only:
GET/POST /rolesPATCH/DELETE /roles/{role_id}GET /roles/{role_id}/policiesPUT/DELETE /roles/{role_id}/policies/{table_name}GET/POST /assignmentsDELETE /assignments/{assignment_id}GET /users/{user_id}/effective-policy
GET /api/internal/genbi-policy/{user_id} and POST /api/internal/genbi-audit still exist.
Only a caller holding MCP_INTERNAL_SECRET can use them. The sandbox never receives that
secret. A denied query recorded through the audit endpoint is stored as a critical
genbi.denied action event. SQL text and result values are not logged.
Deployment
Set PI_USER_TOKEN_SECRET and MCP_INTERNAL_SECRET on the backend. There is no GenBI service
and no mcp-genbi image to rebuild. Assigning or removing a data role does not require a new
sandbox image. It also does not change which tools the agent has, because GenBI is not on the
agent's tool list.