maintainx-enterprise-rbac
Tools to manage and implement RBAC policies for MaintainX API integrations.
Install
mkdir -p .claude/skills/maintainx-enterprise-rbac && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7270" && unzip -o skill.zip -d .claude/skills/maintainx-enterprise-rbac && rm skill.zipInstalls to .claude/skills/maintainx-enterprise-rbac
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Configure enterprise role-based access control for MaintainX integrations.Key capabilities
- →Define role-based access control hierarchies
- →Implement Express middleware for API authorization
- →Apply location-scoped query filtering
- →Configure scoped API keys per role
- →Generate audit logs for access control decisions
How it works
It uses role-based permission mappings and middleware to enforce access control and filter API queries based on user scope.
Inputs & outputs
When to use maintainx-enterprise-rbac
- →Implementing SSO access controls
- →Setting up location-scoped permissions
- →Defining custom user roles
- →Configuring audit logging for enterprise
About this skill
MaintainX Enterprise RBAC
Overview
Configure enterprise role-based access control for MaintainX integrations with role definitions, location-scoped permissions, and audit logging.
Prerequisites
- MaintainX Enterprise plan
- Understanding of RBAC concepts
- Node.js 18+
MaintainX Role Hierarchy
Organization Admin
├── can manage all locations, users, teams, and settings
├── Full API access
│
Location Manager
├── can manage work orders, assets at assigned locations
├── API: filtered by locationId
│
Technician
├── can view/update assigned work orders
├── API: filtered by assigneeId
│
Viewer (Read-Only)
└── can view work orders, assets, locations
└── API: GET endpoints only
Instructions
Step 1: Role Definitions
// src/rbac/roles.ts
export type Role = 'admin' | 'manager' | 'technician' | 'viewer';
interface Permission {
resource: string;
actions: Array<'create' | 'read' | 'update' | 'delete'>;
scope?: 'all' | 'location' | 'assigned';
}
export const ROLE_PERMISSIONS: Record<Role, Permission[]> = {
admin: [
{ resource: 'workorders', actions: ['create', 'read', 'update', 'delete'], scope: 'all' },
{ resource: 'assets', actions: ['create', 'read', 'update', 'delete'], scope: 'all' },
{ resource: 'locations', actions: ['create', 'read', 'update', 'delete'], scope: 'all' },
{ resource: 'users', actions: ['create', 'read', 'update', 'delete'], scope: 'all' },
{ resource: 'teams', actions: ['create', 'read', 'update', 'delete'], scope: 'all' },
],
manager: [
{ resource: 'workorders', actions: ['create', 'read', 'update'], scope: 'location' },
{ resource: 'assets', actions: ['create', 'read', 'update'], scope: 'location' },
{ resource: 'locations', actions: ['read'], scope: 'location' },
{ resource: 'users', actions: ['read'], scope: 'all' },
{ resource: 'teams', actions: ['read'], scope: 'all' },
],
technician: [
{ resource: 'workorders', actions: ['read', 'update'], scope: 'assigned' },
{ resource: 'assets', actions: ['read'], scope: 'location' },
{ resource: 'locations', actions: ['read'], scope: 'location' },
],
viewer: [
{ resource: 'workorders', actions: ['read'], scope: 'all' },
{ resource: 'assets', actions: ['read'], scope: 'all' },
{ resource: 'locations', actions: ['read'], scope: 'all' },
],
};
Step 2: Permission Middleware
// src/rbac/middleware.ts
import express from 'express';
interface AuthContext {
userId: number;
role: Role;
locationIds: number[]; // Locations this user can access
}
function authorize(resource: string, action: 'create' | 'read' | 'update' | 'delete') {
return (req: express.Request, res: express.Response, next: express.NextFunction) => {
const auth = req.user as AuthContext;
if (!auth) return res.status(401).json({ error: 'Not authenticated' });
const perms = ROLE_PERMISSIONS[auth.role];
const match = perms.find(
(p) => p.resource === resource && p.actions.includes(action),
);
if (!match) {
return res.status(403).json({
error: 'Insufficient permissions',
required: { resource, action },
role: auth.role,
});
}
// Apply scope filtering
if (match.scope === 'location') {
req.query.locationId = auth.locationIds.join(',');
} else if (match.scope === 'assigned') {
req.query.assigneeId = String(auth.userId);
}
next();
};
}
// Usage in routes
const router = express.Router();
router.get('/api/workorders', authorize('workorders', 'read'), async (req, res) => {
const client = new MaintainXClient();
const { data } = await client.getWorkOrders(req.query as any);
res.json(data);
});
router.post('/api/workorders', authorize('workorders', 'create'), async (req, res) => {
const client = new MaintainXClient();
const { data } = await client.createWorkOrder(req.body);
res.json(data);
});
Step 3: Scoped API Keys
Create separate API keys per role to enforce server-side access control:
// src/rbac/scoped-clients.ts
const scopedClients: Record<Role, MaintainXClient> = {
admin: new MaintainXClient(process.env.MAINTAINX_API_KEY_ADMIN),
manager: new MaintainXClient(process.env.MAINTAINX_API_KEY_MANAGER),
technician: new MaintainXClient(process.env.MAINTAINX_API_KEY_TECH),
viewer: new MaintainXClient(process.env.MAINTAINX_API_KEY_VIEWER),
};
function getClientForRole(role: Role): MaintainXClient {
const client = scopedClients[role];
if (!client) throw new Error(`No client configured for role: ${role}`);
return client;
}
Step 4: User and Team Management
// Fetch all users and their roles
async function listUsersWithRoles(client: MaintainXClient) {
const { data } = await client.getUsers({ limit: 100 });
const { data: teams } = await client.request('GET', '/teams');
const userTeams = new Map<number, string[]>();
for (const team of teams.teams) {
for (const member of team.members || []) {
const existing = userTeams.get(member.id) || [];
existing.push(team.name);
userTeams.set(member.id, existing);
}
}
for (const user of data.users) {
const teamList = userTeams.get(user.id) || [];
console.log(` ${user.firstName} ${user.lastName} (${user.email})`);
console.log(` Role: ${user.role || 'N/A'} | Teams: ${teamList.join(', ') || 'None'}`);
}
}
Step 5: Audit Logging
// src/rbac/audit.ts
function logAccess(auth: AuthContext, resource: string, action: string, result: 'allow' | 'deny') {
const entry = {
timestamp: new Date().toISOString(),
type: 'access_control',
userId: auth.userId,
role: auth.role,
resource,
action,
result,
locationScope: auth.locationIds,
};
// Send to your log aggregation (CloudWatch, Datadog, etc.)
console.log(JSON.stringify(entry));
}
Output
- Role definitions mapping roles to resource permissions and scopes
- Express middleware enforcing RBAC on all API proxy routes
- Location-scoped and assignee-scoped query filtering
- Scoped API keys per role for defense in depth
- Audit logging for all access control decisions
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| 403 on valid user | Missing permission for action | Check ROLE_PERMISSIONS mapping |
| Empty results for manager | Location scope filter too narrow | Verify locationIds in auth context |
| Scoped key missing | Environment variable not set | Add MAINTAINX_API_KEY_{ROLE} to env |
| Audit log gaps | Middleware not applied to route | Ensure authorize() is on all routes |
Resources
- MaintainX Enterprise
- OWASP Access Control Cheat Sheet
- MaintainX API Reference
Next Steps
For complete platform migration, see maintainx-migration-deep-dive.
Examples
Check if a user can perform an action:
function canPerform(role: Role, resource: string, action: string): boolean {
const perms = ROLE_PERMISSIONS[role];
return perms.some((p) => p.resource === resource && p.actions.includes(action as any));
}
console.log(canPerform('technician', 'workorders', 'update')); // true
console.log(canPerform('technician', 'workorders', 'delete')); // false
console.log(canPerform('viewer', 'workorders', 'read')); // true
When not to use it
- →Standard user-level work order management
- →Basic API integration setup
Prerequisites
Limitations
- →Requires MaintainX Enterprise plan
- →Middleware must be applied to all routes
How it compares
It enforces granular, server-side access control policies compared to simple client-side API calls.
Compared to similar skills
maintainx-enterprise-rbac side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| maintainx-enterprise-rbac (this skill) | 1 | 27d | Review | Advanced |
| auth-implementation-patterns | 1 | 4mo | No flags | Advanced |
| openevidence-security-basics | 0 | 27d | Review | Intermediate |
| jwt-auth | 1 | 6mo | Caution | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
auth-implementation-patterns
sickn33
Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.
openevidence-security-basics
jeremylongshore
Apply OpenEvidence security best practices for HIPAA compliance and PHI protection. Use when securing API keys, implementing PHI handling, or auditing OpenEvidence security configuration. Trigger with phrases like "openevidence security", "openevidence hipaa", "openevidence phi", "secure openevidence", "openevidence compliance".
jwt-auth
dadbodgeoff
Implement secure JWT authentication with refresh token rotation, secure storage, and automatic renewal. Use when building authentication for SPAs, mobile apps, or APIs that need stateless auth with refresh capabilities.
maintainx-security-basics
jeremylongshore
Configure MaintainX API security, credential management, and access control. Use when securing API keys, implementing access controls, or hardening your MaintainX integration. Trigger with phrases like "maintainx security", "maintainx api key security", "secure maintainx", "maintainx credentials", "maintainx access control".
license-impl
lakshamanr
Use when implementing any part of the Cortex Notes license/KeyGen system. Loads full plan context, phase checklist, and implementation rules specific to the license feature.
security-header-generator
Dexploarer
Generates security HTTP headers (CSP, HSTS, CORS, etc.) for web applications to prevent common attacks. Use when user asks to "add security headers", "setup CSP", "configure CORS", "secure headers", or "HSTS setup".