mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 20:53:06 +00:00
86f8fd5ace
Let a GlobalAdmin define a named Tenant Template (a bundle of tenants) and assign a delegated-admin UPN to the template instead of to each tenant. A UPN's effective scope = union of direct grants + every tenant in every assigned template, resolved in DelegatedAdminService.GetScopeAsync — so middleware enforcement, /auth/me delegatedTenantIds and MCP all inherit it unchanged. Adding a tenant to a template grants it to all assignees at once (membership- driven MSP management). Fully app-internal: no Entra group claim / Graph. - Storage: TenantTemplates (PK=templateId; meta + membership rows) and TenantTemplateAssignments (PK=upn) tables; meta-backed existence invariant in both management reads AND the auth hot path (no ghost templates, no scope from stray rows). - Offboarding hygiene: property-only wipe now purges TenantTemplates membership AND DelegatedAdmins rows for the offboarded tenant (closes a pre-existing orphaned-grant gap). - Management API: GlobalAdminOnly /api/global/tenant-templates/* (8 routes); per-affected-tenant audit; all mutations route through the service so the delegated-scope cache is invalidated in lockstep; existence/membership invariant owned by the service (no ghost create, no false revoke audits); templateId normalized case-insensitively at the service boundary. - Web: SectionTenantTemplates management UI (create/rename/delete, add/remove tenants, assign/unassign), triple-registered + api.ts block. Backend 2538 tests green; web tsc clean + vitest 488 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>