@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
351 lines • 12.2 kB
TypeScript
/**
* FGA (Fine-Grained Authorization) provider interface for EE authentication.
* Enables relationship-based, resource-level authorization.
*
* FGA complements RBAC by answering "Can this user do this action on this specific resource?"
* rather than "Can this role do this action?"
*
* @license Mastra Enterprise License - see ee/LICENSE
*/
import type { RequestContext } from '../../../di/index.js';
import type { MastraFGAPermissionInput } from './permissions.generated.js';
/**
* Optional context for an authorization check.
*/
export interface FGACheckContext {
/**
* The owning application resource ID for the target resource.
* Useful when the authorization resource ID differs from the route-level ID,
* such as thread checks scoped by a thread's owning tenant/resource.
*/
resourceId?: string;
/**
* Optional request context for providers that need additional request-scoped
* data to derive the authorization resource identifier.
*/
requestContext?: RequestContext<any>;
/**
* Optional provider-specific metadata about the attempted action.
*/
metadata?: Record<string, unknown>;
}
/**
* Parameters for an authorization check.
*/
export interface FGACheckParams {
/** The resource being accessed */
resource: {
type: string;
id: string;
};
/**
* The permission(s) being checked.
* When an array is provided, the user needs ANY ONE of the listed permissions
* (the check passes if any single permission resolves to allow).
*/
permission: MastraFGAPermissionInput | MastraFGAPermissionInput[];
/** Optional provider-specific context for resource resolution */
context?: FGACheckContext;
}
/**
* Route-level FGA metadata.
*/
export interface FGARouteConfig {
/** Resource type slug to authorize against, e.g. `agent`, `workflow`, or `thread`. */
resourceType: string;
/** Path/body/query parameter name that contains the resource ID. */
resourceIdParam?: string;
/** Static or dynamic resource ID resolver. */
resourceId?: string | ((params: Record<string, unknown>, context: {
requestContext?: RequestContext<any>;
}) => string | undefined);
/**
* Permission(s) to check for this route. Falls back to the route permission when omitted.
* When an array is provided, the user needs ANY ONE of the listed permissions.
*/
permission?: MastraFGAPermissionInput | MastraFGAPermissionInput[];
}
/**
* Minimal route information exposed to global FGA route resolvers.
*/
export interface FGARouteInfo {
path: string;
method: string;
requiresAuth?: boolean;
/**
* Permission(s) required by this route.
* When an array is provided, the user needs ANY ONE of the listed permissions.
*/
requiresPermission?: MastraFGAPermissionInput | MastraFGAPermissionInput[];
fga?: FGARouteConfig;
}
/**
* Context passed to global FGA route resolvers.
*/
export interface FGARouteResolverContext {
route: FGARouteInfo;
params: Record<string, unknown>;
requestContext?: RequestContext<any>;
}
/**
* Resolves route-level FGA metadata without mutating each route registration.
*/
export type FGARouteResolver = (context: FGARouteResolverContext) => FGARouteConfig | null | undefined | Promise<FGARouteConfig | null | undefined>;
/**
* An authorization resource in the FGA system.
*/
export interface FGAResource {
/** Internal resource ID */
id: string;
/** External ID (your application's resource identifier) */
externalId: string;
/** Display name */
name: string;
/** Optional description */
description?: string | null;
/** Resource type slug (e.g., 'team', 'project', 'workspace') */
resourceTypeSlug: string;
/** Organization ID the resource belongs to */
organizationId: string;
/** Parent resource ID for hierarchical resources */
parentResourceId?: string | null;
}
/**
* Parameters for creating an authorization resource.
*/
export interface FGACreateResourceParams {
/** External ID (your application's resource identifier) */
externalId: string;
/** Display name */
name: string;
/** Optional description */
description?: string | null;
/** Resource type slug */
resourceTypeSlug: string;
/** Organization ID */
organizationId: string;
/** Parent resource ID (by internal ID) */
parentResourceId?: string;
/** Parent resource external ID (alternative to parentResourceId) */
parentResourceExternalId?: string;
/** Parent resource type slug (required with parentResourceExternalId) */
parentResourceTypeSlug?: string;
}
/**
* Parameters for updating an authorization resource.
*/
export interface FGAUpdateResourceParams {
/** Internal resource ID */
resourceId: string;
/** New name */
name?: string;
/** New description */
description?: string | null;
}
/**
* Parameters for deleting an authorization resource.
*/
export interface FGADeleteResourceParams {
/** Delete by internal resource ID */
resourceId?: string;
/** Delete by external ID (use with resourceTypeSlug and organizationId) */
externalId?: string;
/** Resource type slug (required when using externalId) */
resourceTypeSlug?: string;
/** Organization ID (required when using externalId) */
organizationId?: string;
}
/**
* A role assignment binding a membership to a role on a resource.
*/
export interface FGARoleAssignment {
/** Assignment ID */
id: string;
/** The role */
role: {
slug: string;
};
/** The resource the role is assigned on */
resource: {
id: string;
externalId: string;
resourceTypeSlug: string;
};
}
/**
* Parameters for assigning or removing a role on a resource.
*/
export interface FGARoleParams {
/** Organization membership ID */
organizationMembershipId: string;
/** Role slug to assign/remove */
roleSlug: string;
/** Resource ID to scope the role to */
resourceId?: string;
/** Resource external ID (alternative to resourceId) */
resourceExternalId?: string;
/** Resource type slug (required when using resourceExternalId) */
resourceTypeSlug?: string;
}
/**
* Options for listing role assignments.
*/
export interface FGAListRoleAssignmentsOptions {
/** Organization membership ID */
organizationMembershipId: string;
/** Pagination limit */
limit?: number;
/** Pagination cursor */
after?: string;
}
/**
* Options for listing authorization resources.
*/
export interface FGAListResourcesOptions {
/** Filter by organization */
organizationId?: string;
/** Filter by resource type */
resourceTypeSlug?: string;
/** Filter by parent resource */
parentResourceId?: string;
/** Search by name */
search?: string;
/** Pagination limit */
limit?: number;
/** Pagination cursor */
after?: string;
}
/**
* Provider interface for fine-grained authorization (read-only).
*
* This interface follows a user-centric model:
* - `check()` answers "Can this user perform this permission on this resource?"
* - `require()` throws if the user lacks permission
* - `filterAccessible()` filters a list of resources to only those the user can access
*
* The provider is responsible for translating between Mastra's resource/permission
* model and the underlying FGA provider's API (e.g., WorkOS Authorization).
*
* @example
* ```typescript
* import { MastraFGAPermissions } from '@mastra/core/auth/ee';
*
* const fga = new MastraFGAWorkos({
* resourceMapping: {
* agent: { fgaResourceType: 'team', deriveId: (ctx) => ctx.user.teamId },
* workflow: { fgaResourceType: 'team', deriveId: (ctx) => ctx.user.teamId },
* thread: { fgaResourceType: 'user', deriveId: (ctx) => ctx.resourceId ?? ctx.user.userId },
* },
* permissionMapping: {
* [MastraFGAPermissions.AGENTS_READ]: 'read',
* [MastraFGAPermissions.AGENTS_EXECUTE]: 'manage-workflows',
* [MastraFGAPermissions.WORKFLOWS_EXECUTE]: 'manage-workflows',
* [MastraFGAPermissions.MEMORY_READ]: 'read',
* [MastraFGAPermissions.MEMORY_WRITE]: 'update',
* },
* });
*
* // Check if a user can execute an agent
* const allowed = await fga.check(user, {
* resource: { type: 'agent', id: 'chef-agent' },
* permission: MastraFGAPermissions.AGENTS_EXECUTE,
* });
* ```
*/
export interface IFGAProvider<TUser = unknown> {
/**
* When true, protected routes without route-level FGA metadata or resolver
* output are denied instead of being allowed through.
*
* @default false
*/
requireForProtectedRoutes?: boolean;
/**
* Audits protected routes that do not have built-in FGA metadata.
* Use `true` or `'warn'` to log a startup warning, `'error'` to fail startup,
* or `false` to disable the audit.
*
* @default false
*/
auditProtectedRoutes?: boolean | 'warn' | 'error';
/**
* Global route FGA resolver. This can derive resource type, resource ID, and
* permission from the route, parsed params, and request context.
*/
resolveRouteFGA?: FGARouteResolver;
/**
* Optional startup validation for provider-specific permission mappings.
* Providers can throw when a permission Mastra may emit is not mapped.
*/
validatePermissions?: (permissions: MastraFGAPermissionInput[]) => void | Promise<void>;
/**
* Check if a user has a specific permission on a resource.
*
* @param user - The user to check
* @param params - The resource and permission to check
* @returns true if the user has permission, false otherwise
*/
check(user: TUser, params: FGACheckParams): Promise<boolean>;
/**
* Require that a user has a specific permission on a resource.
* Throws FGADeniedError if the user does not have permission.
*
* @param user - The user to check
* @param params - The resource and permission to check
* @throws FGADeniedError if the user does not have permission
*/
require(user: TUser, params: FGACheckParams): Promise<void>;
/**
* Filter a list of resources to only those the user can access.
*
* @param user - The user to check
* @param resources - The resources to filter
* @param resourceType - The type of resources being filtered
* @param permission - The permission to check for
* @returns The filtered list of resources the user can access
*/
filterAccessible<T extends {
id: string;
}>(user: TUser, resources: T[], resourceType: string, permission: MastraFGAPermissionInput): Promise<T[]>;
}
/**
* Extended FGA interface with write operations for managing resources and role assignments.
*
* Implement this interface when the FGA provider also manages the authorization
* model (creating resources, assigning roles, etc.).
*/
export interface IFGAManager<TUser = unknown> extends IFGAProvider<TUser> {
/**
* Create an authorization resource.
*/
createResource(params: FGACreateResourceParams): Promise<FGAResource>;
/**
* Get an authorization resource by ID.
*/
getResource(resourceId: string): Promise<FGAResource>;
/**
* List authorization resources.
*/
listResources(options?: FGAListResourcesOptions): Promise<FGAResource[]>;
/**
* Update an authorization resource.
*/
updateResource(params: FGAUpdateResourceParams): Promise<FGAResource>;
/**
* Delete an authorization resource.
*/
deleteResource(params: FGADeleteResourceParams): Promise<void>;
/**
* Assign a role to an organization membership on a specific resource.
*/
assignRole(params: FGARoleParams): Promise<FGARoleAssignment>;
/**
* Remove a role assignment.
*/
removeRole(params: FGARoleParams): Promise<void>;
/**
* List role assignments for an organization membership.
*/
listRoleAssignments(options: FGAListRoleAssignmentsOptions): Promise<FGARoleAssignment[]>;
}
//# sourceMappingURL=fga.d.ts.map