fix: honor agent rolePermissionConfig in record CRUD (#23248)

## Summary
- Agent tools were built with the agent’s `rolePermissionConfig`, but
record CRUD ignored it and re-resolved permissions from `authContext`
(app `defaultRoleId`)
- CRUD services now pass `rolePermissionConfig` through
`CommonApiContextBuilder` and the common query runner, so repository
access matches the agent role
- Workflow/chat paths already use the same role for auth and
`rolePermissionConfig`, so their behavior should be unchanged

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/23248?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Abdul Rahman
2026-07-24 20:51:27 +05:30
committed by GitHub
parent 70e1e94e55
commit 7067f6ef88
18 changed files with 193 additions and 60 deletions
@@ -132,7 +132,7 @@ describe('AgentAsyncExecutorService — workflow agent role-scoped tool resoluti
service = module.get<AgentAsyncExecutorService>(AgentAsyncExecutorService);
});
it('passes unionOf: [agentRoleId] when the agent has a role assigned', async () => {
it('passes intersectionOf: [agentRoleId] when the agent has a role assigned', async () => {
roleTargetRepository.findOne.mockResolvedValueOnce({ roleId: agentRoleId });
await service.executeAgent({
@@ -145,7 +145,7 @@ describe('AgentAsyncExecutorService — workflow agent role-scoped tool resoluti
expect(toolRegistry.getToolsByCategories).toHaveBeenCalledWith(
expect.objectContaining({
roleId: agentRoleId,
rolePermissionConfig: { unionOf: [agentRoleId] },
rolePermissionConfig: { intersectionOf: [agentRoleId] },
workspaceId,
}),
expect.objectContaining({ wrapWithErrorContext: false }),
@@ -176,7 +176,7 @@ export class AgentAsyncExecutorService {
// permission-tab role. No role means no registry tools.
if (isDefined(agentRoleId)) {
const agentRolePermissionConfig: RolePermissionConfig = {
unionOf: [agentRoleId],
intersectionOf: [agentRoleId],
};
const toolProviderContext: ToolProviderContext = {