fix(auth): align owner grants with board key preset

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
cryppadotta 2026-09-10 00:53:41 +00:00
parent 2bcaf2b7f2
commit 58a0f20070
3 changed files with 36 additions and 1 deletions

View File

@ -74,7 +74,10 @@ describe("human invite roles", () => {
{ permissionKey: "users:invite", scope: null },
{ permissionKey: "users:manage_permissions", scope: null },
{ permissionKey: "tasks:assign", scope: null },
{ permissionKey: "tasks:manage_active_checkouts", scope: null },
{ permissionKey: "joins:approve", scope: null },
{ permissionKey: "pipelines:write", scope: null },
{ permissionKey: "audit:view_agent_actions", scope: null },
{ permissionKey: "tools:manage_connections", scope: null },
{ permissionKey: "tools:manage_runtime", scope: null },
{ permissionKey: "tools:use", scope: null },
@ -90,7 +93,10 @@ describe("human invite roles", () => {
{ permissionKey: "environments:manage", scope: null },
{ permissionKey: "users:invite", scope: null },
{ permissionKey: "tasks:assign", scope: null },
{ permissionKey: "tasks:manage_active_checkouts", scope: null },
{ permissionKey: "joins:approve", scope: null },
{ permissionKey: "pipelines:write", scope: null },
{ permissionKey: "audit:view_agent_actions", scope: null },
{ permissionKey: "tools:manage_connections", scope: null },
{ permissionKey: "tools:manage_runtime", scope: null },
{ permissionKey: "tools:use", scope: null },

View File

@ -6,6 +6,8 @@ import {
principalPermissionGrants,
type Db,
} from "@paperclipai/db";
import { BOARD_API_KEY_SCOPE_PRESETS } from "@paperclipai/shared";
import { grantsForHumanRole } from "./company-member-roles.js";
import { boardAuthService } from "./board-auth.js";
describe("boardAuthService touchBoardApiKey", () => {
@ -58,7 +60,7 @@ describe("boardAuthService createNamedBoardApiKey", () => {
function creationDb(options: {
instanceAdmin?: boolean;
membershipRole?: "viewer" | "operator";
membershipRole?: "viewer" | "operator" | "admin" | "owner";
grants?: string[];
}) {
const insert = vi.fn((table: unknown) => {
@ -139,4 +141,25 @@ describe("boardAuthService createNamedBoardApiKey", () => {
})).rejects.toMatchObject({ status: 403 });
expect(insert).not.toHaveBeenCalled();
});
it("accepts the recommended company-automation preset for a default owner", async () => {
const { db, insert } = creationDb({
membershipRole: "owner",
grants: grantsForHumanRole("owner").map((grant) => grant.permissionKey),
});
const service = boardAuthService(db);
await expect(service.createNamedBoardApiKey({
userId,
name: "automation",
scopeConfig: {
version: 1,
kind: "scoped",
companyIds: [companyId],
permissions: [...BOARD_API_KEY_SCOPE_PRESETS.company_automation.permissions],
instanceCapabilities: [],
},
})).resolves.toMatchObject({ id: "key-1" });
expect(insert).toHaveBeenCalledOnce();
});
});

View File

@ -34,7 +34,10 @@ export function grantsForHumanRole(
{ permissionKey: "users:invite", scope: null },
{ permissionKey: "users:manage_permissions", scope: null },
{ permissionKey: "tasks:assign", scope: null },
{ permissionKey: "tasks:manage_active_checkouts", scope: null },
{ permissionKey: "joins:approve", scope: null },
{ permissionKey: "pipelines:write", scope: null },
{ permissionKey: "audit:view_agent_actions", scope: null },
{ permissionKey: "tools:manage_connections", scope: null },
{ permissionKey: "tools:manage_runtime", scope: null },
{ permissionKey: "tools:use", scope: null },
@ -48,7 +51,10 @@ export function grantsForHumanRole(
{ permissionKey: "environments:manage", scope: null },
{ permissionKey: "users:invite", scope: null },
{ permissionKey: "tasks:assign", scope: null },
{ permissionKey: "tasks:manage_active_checkouts", scope: null },
{ permissionKey: "joins:approve", scope: null },
{ permissionKey: "pipelines:write", scope: null },
{ permissionKey: "audit:view_agent_actions", scope: null },
{ permissionKey: "tools:manage_connections", scope: null },
{ permissionKey: "tools:manage_runtime", scope: null },
{ permissionKey: "tools:use", scope: null },