Invect
Plugins

RBAC

Flow-level access control with roles and per-user permissions.

@invect/rbac adds role-based access control on top of @invect/user-auth. It lets you restrict which users can view, edit, or own individual flows — and contributes a Share button and Access Control page to the frontend.

The RBAC plugin requires @invect/user-auth to be configured first. It handles the authorization layer on top of the authentication that better-auth provides.

Installation

npm install @invect/rbac

Add the plugin to Invect

Register rbacPlugin after userAuth in your plugins array:

import { createInvectRouter } from '@invect/express';
import { userAuth } from '@invect/user-auth';
import { rbacPlugin } from '@invect/rbac';
import { auth } from './auth';

app.use('/invect', createInvectRouter({
  baseDatabaseConfig: {
    type: 'sqlite',
    connectionString: process.env.DATABASE_URL || 'file:./dev.db',
    id: 'main',
  },
  plugins: [
    userAuth({ auth }),
    rbacPlugin(),
  ],
}));
InvectModule.forRoot({
  baseDatabaseConfig: {
    type: 'postgresql',
    connectionString: process.env.DATABASE_URL || 'postgresql://localhost:5432/invect',
    id: 'main',
  },
  plugins: [
    userAuth({ auth }),
    rbacPlugin(),
  ],
})
createInvectHandler({
  baseDatabaseConfig: {
    type: 'sqlite',
    connectionString: process.env.DATABASE_URL || 'file:./dev.db',
    id: 'main',
  },
  plugins: [
    userAuth({ auth }),
    rbacPlugin(),
  ],
})

Enable the flow access table

In your Invect config, opt in to per-flow access control:

createInvectRouter({
  baseDatabaseConfig: {
    type: 'sqlite',
    connectionString: process.env.DATABASE_URL || 'file:./dev.db',
    id: 'main',
  },
  auth: {
    useFlowAccessTable: true,
  },
  plugins: [
    userAuth({ auth }),
    rbacPlugin(),
  ],
});

Migrate the database

The RBAC plugin uses the core flow_access table (already included in the base schema). Run migrations if you haven't already:

npx invect-cli generate
npx invect-cli migrate --push

Add the frontend plugin

In your React app, include the RBAC frontend plugin:

App.tsx
import { Invect } from '@invect/frontend';
import { rbacFrontendPlugin } from '@invect/rbac/ui';
import '@invect/frontend/styles';

export default function App() {
  return (
    <Invect
      apiBaseUrl="/invect"
      plugins={[rbacFrontendPlugin]}
    />
  );
}

This adds the Share button to the flow editor header, an Access tab in the node panel, and an Access Control admin page in the sidebar.

Access levels

Each flow access record grants one of three permission levels:

LevelCan viewCan editCan deleteCan manage access
viewer
editor
owner

When a user creates a flow, they are automatically granted owner access.

API Endpoints

All endpoints are mounted under /plugins/rbac/ (or the equivalent path for your framework).

MethodPathDescription
GET/rbac/meCurrent user identity, role, and resolved permissions
GET/rbac/rolesList available roles
GET/rbac/flows/:flowId/accessList access records for a flow
POST/rbac/flows/:flowId/accessGrant access to a user or team
DELETE/rbac/flows/:flowId/access/:accessIdRevoke an access record
GET/rbac/flows/accessibleList flow IDs the current user can access

Granting access

// POST /rbac/flows/:flowId/access
{
  "userId": "user_123",
  "permission": "editor",
  "expiresAt": "2026-12-31T00:00:00Z"  // optional
}

Configuration

rbacPlugin({
  // Enable per-flow access table checks (default: true)
  useFlowAccessTable: true,

  // Permission required to view the Access Control admin page (default: 'admin:*')
  adminPermission: 'admin:*',
})