Role Policy Guide
VM-X AI uses a policy-based access control system for fine-grained permissions. This guide is a comprehensive reference for the policy schema, the available modules and actions, and the rules used by the API to evaluate a request.
Policy Structure
A role policy is a JSON document with a $schema URL and one or more
statements. Each statement decides whether a given action is allowed or
denied on a given resource.
Basic Policy Format
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["module:operation"],
"resources": ["resource:pattern"]
}
]
}
Policy Components
Effect
The effect field must be one of:
"allow"— Permits the specified actions on the specified resources"deny"— Explicitly blocks the specified actions on the specified resources
effect values are lowercase strings. The API rejects "ALLOW"/"DENY".
A matching deny statement always wins over an allow statement, regardless
of their order in the document.
Actions
Actions follow the pattern {module}:{operation}. The set of operations
varies by module — there is no fixed CRUD vocabulary. Some modules have
custom operations such as completion:execute, completion-batch:cancel,
workspace:get-members, role:assign, or
completion-metrics:get-error-rate. The full canonical list is at
Available Modules below.
Wildcards (apply to action and resource strings alike):
*matches any sequence of characters (including the empty string)?matches a single character
Examples:
*matches every action*:getmatches everygetoperation across all modulesworkspace:*matches every workspace action*:listmatches everylistoperation
Resources
Resources follow a hierarchical pattern that nests parent → child:
{module}:{identifier}:{submodule}:{identifier}:.... The identifiers are
substituted at request time by the API: workspace and environment use their
name, AI Connection uses connection.name, AI Resource uses
resource.name, API Key uses apiKey.name, Completion Batch uses
batch.id, User uses user.email, and Role uses role.name.
Examples:
workspace:*— all workspacesworkspace:production— workspace namedproductionworkspace:*:environment:*— every environment in every workspaceworkspace:production:environment:staging— specific environmentworkspace:*:environment:*:ai-connection:*— every AI connection everywhereworkspace:production:environment:staging:ai-connection:openai— specific AI connection
Available Modules
The API exposes the canonical module list at GET /role/permissions. The
table below mirrors that endpoint.
Workspace Module
Base Resource: workspace
Item Resource: workspace:${workspace.name}
Actions:
workspace:listworkspace:getworkspace:get-membersworkspace:createworkspace:updateworkspace:update-member-roleworkspace:deleteworkspace:assignworkspace:unassign
Example:
{
"effect": "allow",
"actions": ["workspace:get", "workspace:list"],
"resources": ["workspace:*"]
}
Environment Module
Base Resource: workspace:${workspace.name}:environment
Item Resource: workspace:${workspace.name}:environment:${environment.name}
Actions:
environment:listenvironment:getenvironment:createenvironment:updateenvironment:delete
Example:
{
"effect": "allow",
"actions": ["environment:list", "environment:get", "environment:create", "environment:update", "environment:delete"],
"resources": ["workspace:production:environment:*"]
}
AI Connection Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:ai-connection
Item Resource: workspace:${workspace.name}:environment:${environment.name}:ai-connection:${connection.name}
Actions:
ai-connection:listai-connection:getai-connection:createai-connection:updateai-connection:delete
Example:
{
"effect": "allow",
"actions": ["ai-connection:create", "ai-connection:get", "ai-connection:list"],
"resources": ["workspace:*:environment:*:ai-connection:*"]
}
AI Resource Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:ai-resource
Item Resource: workspace:${workspace.name}:environment:${environment.name}:ai-resource:${resource.name}
Actions:
ai-resource:listai-resource:getai-resource:createai-resource:updateai-resource:delete
Example:
{
"effect": "allow",
"actions": ["ai-resource:list", "ai-resource:get", "ai-resource:create", "ai-resource:update", "ai-resource:delete"],
"resources": ["workspace:*:environment:*:ai-resource:*"]
}
API Key Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:api-key
Item Resource: workspace:${workspace.name}:environment:${environment.name}:api-key:${apiKey.name}
Actions:
api-key:listapi-key:getapi-key:createapi-key:updateapi-key:delete
API keys themselves do not use role policies to authorise traffic — they authorise via a per-key allow-list of AI Resource UUIDs and SHA-256 hash verification. The actions above only govern who can manage the API key records (list, create, rotate, etc.).
Pool Definition Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:pool-definition
Item Resource: workspace:${workspace.name}:environment:${environment.name}:pool-definition
Actions:
pool-definition:getpool-definition:updatepool-definition:delete
Completion Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:completion
Item Resource: workspace:${workspace.name}:environment:${environment.name}:completion:${completion.id}
Actions:
completion:execute
Example:
{
"effect": "allow",
"actions": ["completion:execute"],
"resources": ["workspace:*:environment:*:completion"]
}
Completion Batch Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:completion-batch
Item Resource: workspace:${workspace.name}:environment:${environment.name}:completion-batch:${batch.id}
Actions:
completion-batch:listcompletion-batch:getcompletion-batch:createcompletion-batch:cancel
Completion Metrics Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:completion-metrics
Item Resource: workspace:${workspace.name}:environment:${environment.name}:completion-metrics
Actions:
completion-metrics:get-error-rate
Request Audit Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:request-audit
Item Resource: workspace:${workspace.name}:environment:${environment.name}:request-audit:${requestAudit.id}
Actions:
request-audit:list
Request Usage Module
Base Resource: workspace:${workspace.name}:environment:${environment.name}:request-usage
Item Resource: workspace:${workspace.name}:environment:${environment.name}:request-usage:${requestUsage.id}
Actions:
request-usage:query
User Module
Base Resource: user
Item Resource: user:${user.email}
Actions:
user:listuser:getuser:createuser:updateuser:delete
Role Module
Base Resource: role
Item Resource: role:${role.name}
Actions:
role:listrole:getrole:get-membersrole:createrole:updaterole:deleterole:assignrole:unassign
Policy Examples
Example 1: Read-Only Role
Allow read-only access to all resources:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["*:get", "*:list"],
"resources": ["*"]
}
]
}
Example 2: Developer Role
Allow developers to create and manage resources, but not delete workspaces or manage users/roles:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "deny",
"actions": ["workspace:delete", "user:create", "user:update", "user:delete", "role:create", "role:update", "role:delete"],
"resources": ["*"]
},
{
"effect": "allow",
"actions": ["*"],
"resources": ["*"]
}
]
}
Example 3: Environment-Specific Access
Allow full access to the production environment only:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["*"],
"resources": ["workspace:*:environment:production", "workspace:*:environment:production:*"]
}
]
}
Example 4: Restricted AI Connection Access
Allow viewing and creating AI connections, but not updating or deleting:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["ai-connection:create", "ai-connection:get", "ai-connection:list"],
"resources": ["workspace:*:environment:*:ai-connection:*"]
},
{
"effect": "deny",
"actions": ["ai-connection:update", "ai-connection:delete"],
"resources": ["workspace:*:environment:*:ai-connection:*"]
}
]
}
Example 5: Workspace Owner
Allow all actions except user and role management:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "deny",
"actions": ["user:create", "user:update", "user:delete", "role:create", "role:update", "role:delete"],
"resources": ["*"]
},
{
"effect": "allow",
"actions": ["*"],
"resources": ["*"]
}
]
}
Policy Evaluation
Every protected request resolves to an (action, resource) pair. The API
walks the user's roles statement-by-statement and returns the first match it
finds. The full algorithm:
- For each role assigned to the user:
- For each statement in the role's policy:
- If any of the statement's
actions(regex-matched with*/?) matches the request's action and any of the statement'sresourcesmatches the request's resource:- If
effectis"deny"→ return 403 Forbidden immediately. - If
effectis"allow"→ return allowed immediately.
- If
- If any of the statement's
- For each statement in the role's policy:
- If no statement matched in any role → return 403 Forbidden.
Because the loop short-circuits on the first match (deny or allow) inside a
single role, ordering inside a role's statements array matters: put your
deny rules first if you want them to override allow rules in the same
role. (The default seeded power-user role does exactly this.)
Evaluation Logic
Matching Rules
- Action matching: the requested action must regex-match one of the
statement's
actionsstrings (after*→.*and?→.substitution). - Resource matching: the requested resource must regex-match one of the
statement's
resourcesstrings, using the same wildcard rules. - Effect application: when both action and resource match, the
statement's
effectis applied immediately.
Best Practices
1. Principle of Least Privilege
Grant only the minimum permissions needed:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["ai-connection:get", "ai-connection:list"],
"resources": ["workspace:production:environment:*:ai-connection:*"]
}
]
}
2. Use deny for Explicit Restrictions
Use deny to fence off dangerous actions even when allow is broad:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "deny",
"actions": ["workspace:delete"],
"resources": ["*"]
},
{
"effect": "allow",
"actions": ["*"],
"resources": ["*"]
}
]
}
3. Organize by Function
Create roles for specific job functions:
- Viewer: Read-only access
- Developer: Create and update resources
- Operator: Manage resources but not users/roles
- Admin: Full access
4. Test Policies
Test policies before assigning to users:
- Create a test role with the policy
- Assign to a test user
- Verify permissions work as expected
- Remove test role and user
5. Document Policies
Document the purpose and scope of each policy:
{
"name": "developer",
"description": "Developer role with limited permissions",
"policy": {
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
// ... statements
]
}
}
Common Patterns
Pattern 1: Environment Isolation
Restrict access to specific environments:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["*"],
"resources": ["workspace:*:environment:production", "workspace:*:environment:production:*", "workspace:*:environment:staging", "workspace:*:environment:staging:*"]
}
]
}
Pattern 2: Module-Specific Access
Allow access to specific modules only:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "allow",
"actions": ["ai-connection:*", "ai-resource:*"],
"resources": ["workspace:*:environment:*:ai-connection:*", "workspace:*:environment:*:ai-resource:*"]
}
]
}
Pattern 3: Read-Only with Exceptions
Read-only access with the ability to create:
{
"$schema": "https://vm-x.ai/schema/role-policy.json",
"statements": [
{
"effect": "deny",
"actions": ["*:update", "*:delete"],
"resources": ["*"]
},
{
"effect": "allow",
"actions": ["*:get", "*:list", "*:create"],
"resources": ["*"]
}
]
}
Troubleshooting
Access Denied Errors
If you get access denied errors:
- Check Role Assignment: Verify the user has at least one role assigned
- Check Policy Statements: Review the role's policy statements
- Check Action Match: Verify the request's action regex-matches a statement action
- Check Resource Match: Verify the request's resource regex-matches a statement resource — including every level of the hierarchy
- Check
denyStatements: Look fordenystatements that might be matching first
Policy Not Working
If a policy is not working as expected:
- Check Statement Order: The first matching statement wins. Put
denyrules first if you want them to overrideallowrules in the same role. - Check Wildcards:
*only expands to.*; it doesn't grant permission across siblings if the rest of the path doesn't match. - Check Resource Patterns: Ensure resource patterns match every level of the actual resource ARN (workspace + environment + module + item).
- Test Incrementally: Start with simple policies and add complexity.
Common Mistakes
- Wrong case for
effect: must be"allow"/"deny"lowercase. - Too permissive: using
*for actions and resources grants too much access. - Missing
deny: not usingdenystatements for explicit restrictions. - Incorrect patterns: resource patterns don't match the actual ARN structure.
- Statement order inside a role:
denymust come beforeallowif both match the same request.
UI Policy Editor
The VM-X AI UI provides a visual policy editor backed by the
GET /role/permissions endpoint:
- Permission Table: Lists every module, action, base resource, and item resource
- JSON Editor: Direct JSON editing
- Examples: Pre-built policy snippets
- Validation: Real-time validation against the schema
Access the policy editor when creating or editing roles in the UI.
Next Steps
- Roles - Learn about role management
- Users - Learn about user management
- Workspaces and Environments - Understand workspace isolation
- AI Connections - Create AI provider connections