Preserve task assignment grants for joined agents

This commit is contained in:
dotta 2026-03-24 08:52:36 -05:00
parent 694c2922d0
commit e4a114331e
2 changed files with 78 additions and 11 deletions

View file

@ -0,0 +1,57 @@
import { describe, expect, it } from "vitest";
import { agentJoinGrantsFromDefaults } from "../routes/access.js";
describe("agentJoinGrantsFromDefaults", () => {
it("adds tasks:assign when invite defaults do not specify agent grants", () => {
expect(agentJoinGrantsFromDefaults(null)).toEqual([
{
permissionKey: "tasks:assign",
scope: null,
},
]);
});
it("preserves invite agent grants and appends tasks:assign", () => {
expect(
agentJoinGrantsFromDefaults({
agent: {
grants: [
{
permissionKey: "agents:create",
scope: null,
},
],
},
}),
).toEqual([
{
permissionKey: "agents:create",
scope: null,
},
{
permissionKey: "tasks:assign",
scope: null,
},
]);
});
it("does not duplicate tasks:assign when invite defaults already include it", () => {
expect(
agentJoinGrantsFromDefaults({
agent: {
grants: [
{
permissionKey: "tasks:assign",
scope: { projectId: "project-1" },
},
],
},
}),
).toEqual([
{
permissionKey: "tasks:assign",
scope: { projectId: "project-1" },
},
]);
});
});

View file

@ -1411,6 +1411,25 @@ function grantsFromDefaults(
return result;
}
export function agentJoinGrantsFromDefaults(
defaultsPayload: Record<string, unknown> | null | undefined
): Array<{
permissionKey: (typeof PERMISSION_KEYS)[number];
scope: Record<string, unknown> | null;
}> {
const grants = grantsFromDefaults(defaultsPayload, "agent");
if (grants.some((grant) => grant.permissionKey === "tasks:assign")) {
return grants;
}
return [
...grants,
{
permissionKey: "tasks:assign",
scope: null
}
];
}
type JoinRequestManagerCandidate = {
id: string;
role: string;
@ -2618,17 +2637,8 @@ export function accessRoutes(
"member",
"active"
);
await access.setPrincipalPermission(
companyId,
"agent",
created.id,
"tasks:assign",
true,
req.actor.userId ?? null
);
const grants = grantsFromDefaults(
invite.defaultsPayload as Record<string, unknown> | null,
"agent"
const grants = agentJoinGrantsFromDefaults(
invite.defaultsPayload as Record<string, unknown> | null
);
await access.setPrincipalGrants(
companyId,