| name | langfuse-enterprise-rbac |
| description | Configure Langfuse enterprise organization management and access control.
Use when implementing team access controls, configuring organization settings,
or setting up role-based permissions for Langfuse projects.
Trigger with phrases like "langfuse RBAC", "langfuse teams",
"langfuse organization", "langfuse access control", "langfuse permissions".
|
| allowed-tools | Read, Write, Edit |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Langfuse Enterprise RBAC
Overview
Configure enterprise-grade access control for Langfuse projects and organizations.
Prerequisites
- Langfuse organization/team account
- Understanding of role-based access patterns
- SSO provider (optional, for enterprise SSO)
Role Definitions
| Role | Dashboard | API Read | API Write | Settings | Billing |
|---|
| Owner | Full | Full | Full | Full | Full |
| Admin | Full | Full | Full | Full | View |
| Member | Full | Full | Full | None | None |
| Viewer | View | Read | None | None | None |
| API Only | None | Full | Full | None | None |
Instructions
Step 1: Implement Role-Based Access in Your Application
enum LangfuseRole {
Owner = "owner",
Admin = "admin",
Member = "member",
Viewer = "viewer",
ApiOnly = "api_only",
}
interface LangfusePermissions {
canViewDashboard: boolean;
canReadTraces: boolean;
canWriteTraces: boolean;
canManageSettings: boolean;
canManageMembers: boolean;
canManageBilling: boolean;
canCreateApiKeys: boolean;
canDeleteData: boolean;
}
const ROLE_PERMISSIONS: Record<LangfuseRole, LangfusePermissions> = {
[LangfuseRole.Owner]: {
canViewDashboard: true,
canReadTraces: true,
canWriteTraces: true,
canManageSettings: true,
canManageMembers: true,
canManageBilling: true,
canCreateApiKeys: ,
: ,
},
[.]: {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
},
[.]: {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
},
[.]: {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
},
[.]: {
: ,
: ,
: ,
: ,
: ,
: ,
: ,
: ,
},
};
(): {
[role][permission];
}
(): {
(!(role, permission)) {
(
);
}
}
Step 2: Implement API Key Scoping
interface ScopedApiKey {
id: string;
publicKey: string;
secretKey: string;
name: string;
scope: ApiKeyScope;
createdAt: Date;
createdBy: string;
expiresAt?: Date;
}
interface ApiKeyScope {
permissions: ("read" | "write")[];
projects?: string[];
environments?: string[];
ipAllowlist?: string[];
rateLimit?: number;
}
class ScopedLangfuseClient {
private langfuse: Langfuse;
private scope: ApiKeyScope;
constructor(apiKey: ScopedApiKey) {
this.langfuse = new Langfuse({
: apiKey.,
: apiKey.,
});
. = apiKey.;
}
() {
(!...()) {
();
}
(..?.) {
projectId = params.?.;
(projectId && !...(projectId)) {
();
}
}
..(params);
}
() {
(!...()) {
();
}
..(params);
}
}
Step 3: Implement Project-Based Access Control
interface LangfuseProject {
id: string;
name: string;
organizationId: string;
environment: "development" | "staging" | "production";
members: ProjectMember[];
}
interface ProjectMember {
userId: string;
email: string;
role: LangfuseRole;
addedAt: Date;
addedBy: string;
}
class ProjectAccessController {
private projects: Map<string, LangfuseProject> = new Map();
async getUserProjects(userId: string): Promise<LangfuseProject[]> {
return Array.from(this.projects.values()).filter((project) =>
project.members.( m. === userId)
);
}
(: , : ): < | > {
project = ..(projectId);
(!project) ;
member = project..( m. === userId);
member?. || ;
}
(
: ,
: <, >,
:
): <> {
adderRole = .(addedBy, projectId);
(!adderRole || !(adderRole, )) {
();
}
(.(member., adderRole)) {
();
}
project = ..(projectId);
(!project) ();
project..({
...member,
: (),
addedBy,
});
}
(: , : ): {
hierarchy = [
.,
.,
.,
.,
.,
];
hierarchy.(role1) > hierarchy.(role2);
}
}
Step 4: Implement SSO Integration
interface SSOConfig {
provider: "okta" | "azure" | "google" | "saml";
domain: string;
clientId: string;
clientSecret: string;
callbackUrl: string;
groupMapping: Record<string, LangfuseRole>;
}
class LangfuseSSO {
private config: SSOConfig;
constructor(config: SSOConfig) {
this.config = config;
}
mapGroupsToRole(groups: string[]): LangfuseRole {
for (const group of groups) {
if (this.config.groupMapping[group]) {
return this.config.groupMapping[group];
}
}
return LangfuseRole.Viewer;
}
(: ): <{
: ;
: ;
: ;
: [];
}> {
email = assertion..;
groups = assertion.. || [];
(!email.()) {
();
}
{
: assertion..,
email,
: .(groups),
groups,
};
}
}
: = {
: ,
: ,
: process..!,
: process..!,
: ,
: {
: .,
: .,
: .,
},
};
Step 5: Implement Audit Logging for RBAC
interface RBACEvent {
timestamp: Date;
action:
| "member_added"
| "member_removed"
| "role_changed"
| "api_key_created"
| "api_key_revoked"
| "permission_denied";
actor: string;
target: string;
projectId?: string;
details: Record<string, any>;
}
class RBACAuditLogger {
async log(event: Omit<RBACEvent, "timestamp">) {
const auditEvent: RBACEvent = {
...event,
timestamp: new Date(),
};
console.log("[RBAC Audit]", JSON.stringify(auditEvent));
await this.persist(auditEvent);
if (event.action === ) {
.(auditEvent);
}
}
() {
}
() {
}
(: {
?: ;
?: ;
?: ;
?: ;
?: ;
}): <[]> {
[];
}
}
rbacAudit = ();
Output
- Role-based permission system
- Scoped API key implementation
- Project-based access control
- SSO integration
- RBAC audit logging
Access Control Matrix
| Action | Owner | Admin | Member | Viewer | API Only |
|---|
| View traces | Yes | Yes | Yes | Yes | No |
| Create traces | Yes | Yes | Yes | No | Yes |
| Delete traces | Yes | Yes | No | No | No |
| Manage members | Yes | Yes | No | No | No |
| Create API keys | Yes | Yes | No | No | No |
| Manage billing | Yes | No | No | No | No |
Error Handling
| Issue | Cause | Solution |
|---|
| Permission denied | Insufficient role | Request role upgrade |
| SSO login fails | Wrong group mapping | Update group mapping |
| API key rejected | Expired or scoped | Create new key |
| Project not found | No access | Request project access |
Resources
Next Steps
For complex migrations, see langfuse-migration-deep-dive.