.agents/rules/modules/identity.md
Auth (JWT + ASP.NET Identity), users, roles, permissions, sessions, impersonation, 2FA.
IUserService is a facade that delegates to focused single-responsibility services — change behavior in the specific service, not the facade:
| Interface | Concern |
|---|---|
IUserRegistrationService | register, external-principal create, email/phone confirm |
IUserProfileService | get/list/count, update profile, image, existence checks |
IUserStatusService | activate/deactivate (DeleteAsync == deactivate), audited toggles |
IUserRoleService | role assignment, admin-role guards |
IUserPasswordService | forgot/reset/change password, history + expiry |
IUserPermissionService | effective permissions, cache invalidation |
ChangePassword/Update/Delete etc. flow facade → service → EF/UserManager. CancellationToken is = default on these interfaces and propagated into EF sinks (note: UserManager/RoleManager have no CT overloads, so private helpers that only call them don't take one).
RequiredPermissionAttribute implements FSH.Framework.Shared.Identity.Authorization.IRequiredPermissionMetadata. Never let a second/duplicate IRequiredPermissionMetadata appear — it silently disables all .RequirePermission() gates across the app. Permission constants live in Shared/Identity/*Permissions.cs.
RolePermissionSyncHostedService — best-effort sync of the permission catalog; loops, catches Exception with an OperationCanceledException filter, logs and continues.SessionCleanupHostedService — hourly expired-session purge; OCE handled by a preceding catch.These are the model for background loops: stay alive, log with context, never swallow cancellation. See api-conventions.md.
Login POST /api/v1/identity/token/issue (header X-FSH-App enforces the operator/tenant app boundary). Refresh POST /api/v1/identity/token/refresh cross-checks subject. Session rows are written best-effort during login — failures log a warning and login still succeeds. Admin can't demote/deactivate the last admin or the root-tenant seed admin (guards in UserRoleService/UserStatusService).
Identity.Tests is the largest unit suite. When asserting a forwarded CancellationToken, assert the specific token (see testing.md).