VoidBot/packages/core/src/permission-engine.ts
2026-04-24 13:17:00 +01:00

86 lines
1.9 KiB
TypeScript

import {
type Actor,
type JobRecord,
type ProviderName,
type TrustTier,
} from "@voidbot/shared";
export interface ProviderAccessDecision {
allowed: boolean;
tier: TrustTier;
reasonKey?: string;
}
export class PermissionEngine {
public constructor(
private readonly ownerDiscordId: string,
private readonly options: {
localLlmAllowPublic?: boolean;
} = {},
) {}
public resolveTrustTier(actor: Actor): TrustTier {
if (actor.id === this.ownerDiscordId) {
return "T2";
}
if (actor.isAdmin) {
return "T1";
}
return "T0";
}
public canUseProvider(actor: Actor, provider: ProviderName): ProviderAccessDecision {
const tier = this.resolveTrustTier(actor);
if (provider === "owner_codex") {
return actor.id === this.ownerDiscordId
? { allowed: true, tier }
: {
allowed: false,
tier,
reasonKey: "permission.owner_codex.denied",
};
}
if (provider === "openai_api") {
return {
allowed: tier === "T0" || tier === "T1" || tier === "T2",
tier,
};
}
if (provider === "local_llm") {
return this.options.localLlmAllowPublic || tier === "T1" || tier === "T2"
? {
allowed: true,
tier,
}
: {
allowed: false,
tier,
reasonKey: "permission.local_llm.denied",
};
}
return {
allowed: true,
tier,
};
}
public canReindex(actor: Actor): boolean {
const tier = this.resolveTrustTier(actor);
return tier === "T1" || tier === "T2";
}
public canManageConfiguration(actor: Actor): boolean {
const tier = this.resolveTrustTier(actor);
return tier === "T1" || tier === "T2";
}
public canApproveJob(actor: Actor, job: JobRecord): boolean {
return actor.id === this.ownerDiscordId && job.requester.id === this.ownerDiscordId;
}
}