Three decisions#
- Authentication: who are you?
- Permission: may you use it?
- Approval: may this request proceed?
Authentication creates an identity/session. Role permissions determine access to capabilities. Approval binds authorization to a particular execution and does not create a permanent permission grant.
Roles and the administrator#
Roles and assignments persist in SQLite. The verified system role is ControlHub Administrators; it is synchronized to allow active module permissions and protected against recovery lockout. This is not an unconditional authorization-engine bypass. Safety approvals remain independent.
No other named default role, role hierarchy or wildcard inheritance is verified.
Effect precedence#
| Effect | Meaning |
|---|---|
deny | Blocks execution; takes precedence over other applicable effects |
require_approval | Raises approval requirements when an execution request can be bound |
allow | Allows the capability, subject to other runtime policy/ownership checks |
Precedence is DENY → REQUIRE_APPROVAL → ALLOW. Inactive users/permissions are denied. Missing assignments use the authorization mode's fallback; the web defaults to enforcing, while the service constructor defaults to permissive.
Scopes and tool checks#
Stored scopes compare normalized type/value against request scopes; any matching stored scope is sufficient. Resolver/provider read permissions can be required in addition to target resolution.
Before-handler and after-handler checks cover discovery, returned execution requests/batches and local-return tools. Denial prevents provider execution. Approved actions recheck current RBAC.
Permission matrix#
| Permission | Exact tools | Resolver kinds |
|---|---|---|
action1.organizations.read | action1.list_organizations | None declared |
action1.endpoints.read | action1.list_endpoints, action1.get_endpoint, action1.get_endpoint_status | managed_endpoint, endpoint, computer, windows_endpoint, pc, user, person, employee, worker, endpoint_group, group, endpoint_metadata |
action1.software.read | action1.search_software_packages, action1.list_software_packages, action1.get_software_package, action1.list_installed_software, action1.list_endpoint_installed_software | None declared |
action1.software.deploy | action1.deploy_software | None declared |
action1.software.uninstall | action1.uninstall_software | None declared |
action1.scripts.read | action1.search_scripts, action1.list_scripts, action1.get_script | None declared |
action1.scripts.run | action1.run_library_script | None declared |
action1.powershell.run | action1.run_powershell | None declared |
ad.health.read | ad.health | None declared |
ad.users.read | ad.search_users, ad.get_user, ad.get_user_groups | ad_user |
ad.computers.read | ad.search_computers, ad.get_computer | ad_computer |
ad.groups.read | ad.search_groups, ad.get_group, ad.get_group_members | ad_group |
ad.ous.read | ad.search_ous | ad_ou |
codex.use | No static tool mapping | None declared |
codex.manage | codex.bootstrap | None declared |
files.create | files.create | None declared |
files.upload | No static tool mapping | None declared |
files.read | files.read, files.query_table | None declared |
files.delete | No static tool mapping | None declared |
mcp.use | No static tool mapping | None declared |
onec.schema.read | onec.describe_schema | None declared |
onec.query.read | onec.query | None declared |
onec.health.read | onec.ping | onec_infobase, infobase, onec_database |
onec.warehouses.read | onec.list_warehouses | warehouse, onec_warehouse, location |
onec.nomenclature.read | onec.find_items | nomenclature, onec_nomenclature, inventory_item, item |
onec.images.read | onec.get_item_images | None declared |
onec.document_text.read | onec.search_document_text | None declared |
onec.search.read | onec.search | None declared |
onec.stock.read | onec.get_stock, onec.get_stock_summary | None declared |
onec.movements.read | onec.get_movements | None declared |
targets.resolve | targets.resolve | None declared |
31 static identifiers. Backend capabilities such as ad.read are not permission identifiers. MCP per-tool permissions are generated dynamically.
Dynamic MCP permissions#
Dynamic identifiers follow mcp.<server_token>.tool.<remote_token>. They are discovered from connected tools, not a permanent built-in list. See MCP tool permissions.
Important boundaries#
Codex has a specific no_applicable_assignment fallback for codex.use; explicit deny/require_approval and no-role denial remain blocked. See Codex before configuring its access.