feat(master-data): scope detail reads to resource overview

This commit is contained in:
2026-03-30 10:08:44 +02:00
parent 8495b83b3e
commit bd654251f7
6 changed files with 230 additions and 8 deletions
+11
View File
@@ -236,6 +236,12 @@ const PLANNING_READ_TOOLS = new Set([
"find_best_project_resource",
]);
/** Tools that require broad people-directory visibility because the backing routes expose resource-linked counts. */
const RESOURCE_OVERVIEW_TOOLS = new Set([
"get_country",
"list_org_units",
]);
/** Tools that follow controllerProcedure access rules in the main API. */
const CONTROLLER_ONLY_TOOLS = new Set([
"search_projects",
@@ -363,6 +369,8 @@ export function getAvailableAssistantTools(permissions: Set<PermissionKey>, user
return TOOL_DEFINITIONS.filter((tool) => {
const toolName = tool.function.name;
const requiredPerm = TOOL_PERMISSION_MAP[toolName];
const hasResourceOverviewAccess = permissions.has(PermissionKey.VIEW_ALL_RESOURCES)
|| permissions.has(PermissionKey.MANAGE_RESOURCES);
const hasControllerAccess = userRole === SystemRole.ADMIN
|| userRole === SystemRole.MANAGER
|| userRole === SystemRole.CONTROLLER;
@@ -378,6 +386,9 @@ export function getAvailableAssistantTools(permissions: Set<PermissionKey>, user
if (MANAGER_ONLY_TOOLS.has(toolName) && !hasManagerAccess) {
return false;
}
if (RESOURCE_OVERVIEW_TOOLS.has(toolName) && !hasResourceOverviewAccess) {
return false;
}
if (CONTROLLER_ONLY_TOOLS.has(toolName) && !hasControllerAccess) {
return false;
}
+8 -3
View File
@@ -9,7 +9,12 @@ import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import { createAuditEntry } from "../lib/audit.js";
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc.js";
import {
adminProcedure,
createTRPCRouter,
protectedProcedure,
resourceOverviewProcedure,
} from "../trpc.js";
/** Convert nullable JSON to Prisma-compatible value (null → Prisma.JsonNull). */
function jsonOrNull(val: unknown): Prisma.InputJsonValue | typeof Prisma.JsonNull {
@@ -75,7 +80,7 @@ export const countryRouter = createTRPCRouter({
return country;
}),
getByIdentifier: protectedProcedure
getByIdentifier: resourceOverviewProcedure
.input(z.object({ identifier: z.string().trim().min(1) }))
.query(async ({ ctx, input }) => {
const identifier = input.identifier.trim();
@@ -124,7 +129,7 @@ export const countryRouter = createTRPCRouter({
return country;
}),
getById: protectedProcedure
getById: resourceOverviewProcedure
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const country = await findUniqueOrThrow(
+8 -3
View File
@@ -3,7 +3,12 @@ import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import { createAuditEntry } from "../lib/audit.js";
import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc.js";
import {
adminProcedure,
createTRPCRouter,
protectedProcedure,
resourceOverviewProcedure,
} from "../trpc.js";
import type { OrgUnitTree } from "@capakraken/shared";
@@ -61,7 +66,7 @@ export const orgUnitRouter = createTRPCRouter({
return buildTree(all);
}),
getById: protectedProcedure
getById: resourceOverviewProcedure
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const unit = await findUniqueOrThrow(
@@ -128,7 +133,7 @@ export const orgUnitRouter = createTRPCRouter({
return unit;
}),
getByIdentifier: protectedProcedure
getByIdentifier: resourceOverviewProcedure
.input(z.object({ identifier: z.string().trim().min(1) }))
.query(async ({ ctx, input }) => {
const identifier = input.identifier.trim();