Backend guides
Adding a permission
Define a permission tier, enforce it on an endpoint, and expose it safely in the UI.
Permissions in Slicekit are owned by code. Each protected endpoint declares one
.RequirePermission(Allow.<Name>), and the SPA mirrors names that affect its navigation or actions.
Name and tier
Every name uses three PascalCase segments: Area.Category.Action, for example
User.ApiKeys.List, Staff.Users.SetPermissions, or Admin.Cache.Invalidate.
Add the PermissionDefinition to exactly one catalog in Allow.cs:
UserPermissionCatalogfor self-service capabilities. API keys may carry this tier.AssignablePermissionsforStaff.*capabilities that staff can grant to other users, invitations, and roles.SuperAdminPermissionsforAdmin.*infrastructure and high-impact operations.
Set Delegable: true on a staff permission only when it should be available to scoped API keys.
Superadmin permissions are never delegable.
Set IsReadOnly: true for reads. The shared permission picker uses it for the read-only preset.
Enforce and synchronize
Gate the endpoint with the new constant. Architecture tests fail if a catalog entry gates no endpoint or if an endpoint has no explicit access declaration.
PermissionSyncService reconciles the lookup table on startup and adds required self-service or superadmin grants
to users in pages. If you rename or split an existing permission, add a legacy mapping so user grants, exclusions,
API key scopes, and role presets migrate before the old lookup row is removed.
Decide MCP coverage
For a delegable endpoint, add a tool with the matching permission, or record the exclusion and its
reason in McpToolParityTests. Tool convention tests check names, permissions and read-only hints.
See MCP and connected apps.
Mirror the frontend
Add the exact name to frontend/src/shared/auth/permissions.ts when the UI checks it. Gate the control with
usePermissions().has(...), and add area and category labels to both locale files. The frontend tests parse
Allow.cs and catch missing labels.
The UI gate is for clarity. The API permission filter remains the security boundary.
Verify
dotnet test api/fast.slnf --nologo
cd frontend && pnpm test && pnpm typecheck
Test a caller without the permission and expect a 403 response. Restart the API and confirm the lookup row and any configured legacy migration are applied.