diff --git a/src/discord/targets.test.ts b/src/discord/targets.test.ts index 7ac39450b..ca5a61f80 100644 --- a/src/discord/targets.test.ts +++ b/src/discord/targets.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import type { ClawdbotConfig } from "../config/config.js"; +import type { MoltbotConfig } from "../config/config.js"; import { normalizeDiscordMessagingTarget } from "../channels/plugins/normalize/discord.js"; import { listDiscordDirectoryPeersLive } from "./directory-live.js"; import { parseDiscordTarget, resolveDiscordChannelId, resolveDiscordTarget } from "./targets.js"; @@ -75,7 +75,7 @@ describe("resolveDiscordChannelId", () => { }); describe("resolveDiscordTarget", () => { - const cfg = { channels: { discord: {} } } as ClawdbotConfig; + const cfg = { channels: { discord: {} } } as MoltbotConfig; const listPeers = vi.mocked(listDiscordDirectoryPeersLive); beforeEach(() => { diff --git a/src/security/audit.test.ts b/src/security/audit.test.ts index 40124d39a..cb148ee30 100644 --- a/src/security/audit.test.ts +++ b/src/security/audit.test.ts @@ -732,7 +732,7 @@ describe("security audit", () => { it("does not warn on Venice-style opus-45 model names", async () => { // Venice uses "claude-opus-45" format (no dash between 4 and 5) - const cfg: ClawdbotConfig = { + const cfg: MoltbotConfig = { agents: { defaults: { model: { primary: "venice/claude-opus-45" } } }, }; diff --git a/src/security/rbac.test.ts b/src/security/rbac.test.ts index 7559b05fb..d8854e497 100644 --- a/src/security/rbac.test.ts +++ b/src/security/rbac.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, beforeEach, afterEach } from "vitest"; -import type { ClawdbotConfig } from "../config/types.js"; +import type { MoltbotConfig } from "../config/types.js"; import { isRbacEnabled, getRoleForUser, @@ -42,12 +42,12 @@ describe("rbac", () => { describe("getRoleForUser", () => { it("returns null when RBAC is disabled", () => { - const config: ClawdbotConfig = { rbac: { enabled: false } }; + const config: MoltbotConfig = { rbac: { enabled: false } }; expect(getRoleForUser("user-1", config)).toBeNull(); }); it("returns assigned role when user is assigned", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "admin" }, @@ -59,7 +59,7 @@ describe("rbac", () => { }); it("returns default role when user is not assigned", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, defaultRole: "viewer", @@ -70,14 +70,14 @@ describe("rbac", () => { }); it("returns null when no assignment and no default role", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true }, }; expect(getRoleForUser("user-1", config)).toBeNull(); }); it("uses custom role definitions", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, roles: { @@ -97,21 +97,21 @@ describe("rbac", () => { describe("hasPermission", () => { it("allows everything when RBAC is disabled", () => { - const config: ClawdbotConfig = { rbac: { enabled: false } }; + const config: MoltbotConfig = { rbac: { enabled: false } }; const result = hasPermission("user-1", "exec.elevated", config); expect(result.allowed).toBe(true); expect(result.reason).toBe("rbac-disabled"); }); it("denies when user has no role", () => { - const config: ClawdbotConfig = { rbac: { enabled: true } }; + const config: MoltbotConfig = { rbac: { enabled: true } }; const result = hasPermission("user-1", "exec", config); expect(result.allowed).toBe(false); expect(result.reason).toBe("no-role-assigned"); }); it("allows when user has the permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -123,7 +123,7 @@ describe("rbac", () => { }); it("denies when user lacks the permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -135,7 +135,7 @@ describe("rbac", () => { }); it("admin role grants all permissions", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "admin" }, @@ -150,7 +150,7 @@ describe("rbac", () => { describe("canExecuteCommand", () => { it("allows basic commands with exec permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -161,7 +161,7 @@ describe("rbac", () => { }); it("denies elevated commands without exec.elevated permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -172,7 +172,7 @@ describe("rbac", () => { }); it("allows elevated commands with exec.elevated permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "admin" }, @@ -183,7 +183,7 @@ describe("rbac", () => { }); it("detects sudo in various positions", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -198,7 +198,7 @@ describe("rbac", () => { describe("canAccessAgent", () => { it("allows all agents when no restrictions", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -210,7 +210,7 @@ describe("rbac", () => { }); it("denies access to restricted agents", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, roles: { @@ -228,7 +228,7 @@ describe("rbac", () => { }); it("admin bypasses agent restrictions", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "admin" }, @@ -242,7 +242,7 @@ describe("rbac", () => { describe("canUseTool", () => { it("allows all tools when no restrictions", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -253,7 +253,7 @@ describe("rbac", () => { }); it("denies tools on deny list", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, roles: { @@ -271,7 +271,7 @@ describe("rbac", () => { }); it("only allows tools on allow list when specified", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, roles: { @@ -289,7 +289,7 @@ describe("rbac", () => { }); it("deny takes precedence over allow", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, roles: { @@ -307,7 +307,7 @@ describe("rbac", () => { }); it("read-only role cannot use tools", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "viewer" }, @@ -321,7 +321,7 @@ describe("rbac", () => { describe("canApproveExec", () => { it("allows with exec.approve permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "operator" }, @@ -332,7 +332,7 @@ describe("rbac", () => { }); it("denies without exec.approve permission", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "user" }, @@ -345,14 +345,14 @@ describe("rbac", () => { describe("getUserPermissionSummary", () => { it("returns disabled when RBAC is off", () => { - const config: ClawdbotConfig = { rbac: { enabled: false } }; + const config: MoltbotConfig = { rbac: { enabled: false } }; const summary = getUserPermissionSummary("user-1", config); expect(summary.enabled).toBe(false); expect(summary.roleId).toBeUndefined(); }); it("returns role details when RBAC is on", () => { - const config: ClawdbotConfig = { + const config: MoltbotConfig = { rbac: { enabled: true, assignments: { "user-1": "admin" }, @@ -366,7 +366,7 @@ describe("rbac", () => { }); it("returns enabled with no role when user unassigned", () => { - const config: ClawdbotConfig = { rbac: { enabled: true } }; + const config: MoltbotConfig = { rbac: { enabled: true } }; const summary = getUserPermissionSummary("user-1", config); expect(summary.enabled).toBe(true); expect(summary.roleId).toBeUndefined(); diff --git a/src/security/rbac.ts b/src/security/rbac.ts index 7eee300f6..adb1eb77c 100644 --- a/src/security/rbac.ts +++ b/src/security/rbac.ts @@ -5,7 +5,7 @@ * When RBAC is disabled, all permissions are granted (backwards compatible). */ -import type { ClawdbotConfig } from "../config/types.js"; +import type { MoltbotConfig } from "../config/types.js"; import type { RbacConfig, RbacPermission, RbacRoleDefinition } from "../config/types.rbac.js"; import { auditRbacDenied } from "./audit-log.js"; @@ -43,7 +43,7 @@ const DEFAULT_ROLES: Record = { /** * Check if RBAC is enabled in the config. */ -export function isRbacEnabled(config?: ClawdbotConfig): boolean { +export function isRbacEnabled(config?: MoltbotConfig): boolean { return config?.rbac?.enabled === true; } @@ -54,7 +54,7 @@ export function isRbacEnabled(config?: ClawdbotConfig): boolean { * SECURITY: Call this during gateway startup to catch configuration * errors early rather than failing silently at runtime. */ -export function validateRbacConfig(config?: ClawdbotConfig): string[] | null { +export function validateRbacConfig(config?: MoltbotConfig): string[] | null { if (!isRbacEnabled(config)) { return null; // RBAC disabled, no validation needed } @@ -85,9 +85,10 @@ export function validateRbacConfig(config?: ClawdbotConfig): string[] | null { if (rbacConfig?.assignments) { const roles = { ...DEFAULT_ROLES, ...rbacConfig.roles }; for (const [userId, roleId] of Object.entries(rbacConfig.assignments)) { - if (roleId && !roles[roleId]) { + const roleIdStr = String(roleId); + if (roleId && !roles[roleIdStr]) { errors.push( - `RBAC assignment for user '${userId}' references unknown role '${roleId}'. ` + + `RBAC assignment for user '${userId}' references unknown role '${roleIdStr}'. ` + `Available roles: ${Object.keys(roles).join(", ")}`, ); } @@ -100,7 +101,7 @@ export function validateRbacConfig(config?: ClawdbotConfig): string[] | null { /** * Get the RBAC config with defaults applied. */ -function getRbacConfig(config?: ClawdbotConfig): RbacConfig { +function getRbacConfig(config?: MoltbotConfig): RbacConfig { return { enabled: false, roles: DEFAULT_ROLES, @@ -125,7 +126,7 @@ function getRoles(rbacConfig: RbacConfig): Record { */ export function getRoleForUser( senderId: string, - config?: ClawdbotConfig, + config?: MoltbotConfig, ): { roleId: string; role: RbacRoleDefinition } | null { const rbacConfig = getRbacConfig(config); const roles = getRoles(rbacConfig); @@ -151,7 +152,7 @@ export function getRoleForUser( export function hasPermission( senderId: string, permission: RbacPermission, - config?: ClawdbotConfig, + config?: MoltbotConfig, ): RbacCheckResult { // If RBAC is disabled, allow everything if (!isRbacEnabled(config)) { @@ -190,7 +191,7 @@ export function hasPermission( export function canExecuteCommand( senderId: string, command: string, - config?: ClawdbotConfig, + config?: MoltbotConfig, ): RbacCheckResult { // If RBAC is disabled, allow everything if (!isRbacEnabled(config)) { @@ -244,7 +245,7 @@ function isElevatedCommand(command: string): boolean { export function canAccessAgent( senderId: string, agentId: string, - config?: ClawdbotConfig, + config?: MoltbotConfig, ): RbacCheckResult { // If RBAC is disabled, allow everything if (!isRbacEnabled(config)) { @@ -298,7 +299,7 @@ export function canAccessAgent( export function canUseTool( senderId: string, toolName: string, - config?: ClawdbotConfig, + config?: MoltbotConfig, ): RbacCheckResult { // If RBAC is disabled, allow everything if (!isRbacEnabled(config)) { @@ -364,7 +365,7 @@ export function canUseTool( /** * Check if a user can approve exec requests. */ -export function canApproveExec(senderId: string, config?: ClawdbotConfig): RbacCheckResult { +export function canApproveExec(senderId: string, config?: MoltbotConfig): RbacCheckResult { return hasPermission(senderId, "exec.approve", config); } @@ -373,7 +374,7 @@ export function canApproveExec(senderId: string, config?: ClawdbotConfig): RbacC */ export function getUserPermissionSummary( senderId: string, - config?: ClawdbotConfig, + config?: MoltbotConfig, ): { enabled: boolean; roleId?: string;