# Access Control Domain Role and permission rules for servers, including default system roles, role assignment normalization, permission resolution, legacy compatibility mapping, and room-level access-control hydration. ## Module map ``` access-control/ ├── domain/ │ ├── models/ │ │ └── access-control.model.ts MemberIdentity and RoomPermissionDefinition domain types │ ├── constants/ │ │ └── access-control.constants.ts SYSTEM_ROLE_IDS and permission metadata │ ├── util/ │ │ └── access-control.util.ts Internal helpers (normalization, identity matching, sorting) │ └── rules/ │ ├── role.rules.ts Role defaults, normalization, ordering, create/update helpers │ ├── role-assignment.rules.ts Assignment normalization and member-role lookups │ ├── permission.rules.ts Permission resolution and moderation hierarchy checks │ ├── room.rules.ts Legacy compatibility, room hydration, room-level normalization │ └── ban.rules.ts Ban matching and user-ban resolution │ └── index.ts Domain barrel used by other layers ``` ## Domain rules | Function | Purpose | | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `normalizeRoomRoles(room.roles, room.permissions)` | Repairs missing/default roles and keeps role ordering stable | | `normalizeRoomRoleAssignments(...)` | Deduplicates and backfills member role assignments from legacy member role fields | | `normalizeChannelPermissionOverrides(...)` | Deduplicates valid channel overrides and drops invalid references | | `resolveRoomPermission(room, identity, permission, channelId?)` | Resolves effective permission state including overrides | | `canManageMember(...)` | Applies both permission checks and role hierarchy checks | | `canManageRole(...)` | Prevents editing roles at or above the actor's highest role | | `normalizeRoomAccessControl(room)` | Produces a fully hydrated room with normalized roles, assignments, overrides, and legacy compatibility fields | | `hasRoomBanForUser(bans, user, persistedUserId?)` | Returns true when any active ban entry targets the provided user | | `isRoomBanMatch(ban, user, persistedUserId?)` | Returns true when a single ban entry targets the provided user | ## Layering - Domain rules stay pure and only depend on `shared-kernel` contracts plus other files in this domain. - Renderer shells and NgRx effects should keep importing from `src/app/domains/access-control/` instead of internal files. - Legacy `room.permissions` booleans remain compatibility output only; normalized data lives on `roles`, `roleAssignments`, `channelPermissions`, and `slowModeInterval`.