import { z } from "zod"; // --------------------------------------------------------------------------- // Admin / Authorization: roles, policies, catalogue // --------------------------------------------------------------------------- const slug = z .string() .regex(/^[a-z][a-z0-9-]{1,63}$/, "Lowercase letters, digits and hyphens, starting with a letter"); const stringList = z.array(z.string().min(1)).max(500); export const policyRulesBody = z .object({ routes: stringList.optional(), permissions: stringList.optional(), adminPages: stringList.optional(), ownOnly: z.boolean().optional(), collections: stringList.optional(), mcpTools: stringList.optional(), deny: z .object({ routes: stringList.optional(), permissions: stringList.optional(), adminPages: stringList.optional(), }) .strict() .optional(), }) .strict() .meta({ id: "PolicyRules" }); export const roleCreateBody = z .object({ slug, name: z.string().min(1).max(100), description: z.string().max(500).nullable().optional(), level: z .union([z.literal(10), z.literal(20), z.literal(30), z.literal(40), z.literal(50)]) .optional(), policies: z.array(slug).max(100).optional(), }) .meta({ id: "RoleCreateBody" }); export const roleUpdateBody = roleCreateBody.partial().meta({ id: "RoleUpdateBody" }); export const policyCreateBody = z .object({ slug, name: z.string().min(1).max(100), description: z.string().max(500).nullable().optional(), rules: policyRulesBody, }) .meta({ id: "PolicyCreateBody" }); export const policyUpdateBody = policyCreateBody.partial().meta({ id: "PolicyUpdateBody" }); /** `roleId` is a role id or slug; `role` is the legacy level (mapped to a built-in). */ export const roleRef = z.object({ roleId: z.string().min(1).optional(), });