Effects Composition¶
The IdentityModule is an [EffectsModule(typeof(IIdentityStore))] that generates Eff<RT, T> effect methods for identity and role management. ICurrentUser is a per-request context (not effects-based) provided by middleware.
Capability Interface¶
Effect Methods¶
public static partial class IdentityModule
{
public static partial class Identity
{
public static Eff<RT, Option<UserIdentity>> GetAsync<RT>(string userId)
where RT : IHasIdentityStore => ...
public static Eff<RT, IReadOnlyList<RoleAssignment>> GetRolesAsync<RT>(string userId)
where RT : IHasIdentityStore => ...
public static Eff<RT, Unit> AssignRoleAsync<RT>(string userId, string roleName)
where RT : IHasIdentityStore => ...
public static Eff<RT, Unit> RevokeRoleAsync<RT>(string userId, string roleName)
where RT : IHasIdentityStore => ...
}
}
ICurrentUser (Non-Effects)¶
ICurrentUser is resolved from the HTTP context per-request, not through effects. Access it directly in handlers:
public interface ICurrentUser
{
string UserId { get; }
string Email { get; }
string Name { get; }
IReadOnlySet<string> Roles { get; }
IReadOnlySet<int> Permissions { get; }
bool IsAuthenticated { get; }
bool HasPermission<TPermission>(TPermission permission) where TPermission : Enum;
bool HasRole(string roleName);
}
Effect Pipeline Examples¶
Assign a role¶
var promoteToAdmin =
from user in IdentityModule.Identity.GetAsync<AppRuntime>(userId)
.Require(Error.New(404, "User not found"))
from _ in IdentityModule.Identity.AssignRoleAsync<AppRuntime>(userId, "admin")
from __ in AuditModule.Audit.SaveAsync<AppRuntime>(new AuditEntry
{
EntityType = "User",
EntityId = userId,
Action = "role_assigned:admin",
Actor = CorrelationContext.Current?.UserId ?? "system"
})
select unit;
Check roles in an effect pipeline¶
var adminOnlyOperation =
from roles in IdentityModule.Identity.GetRolesAsync<AppRuntime>(userId)
from _ in Guard<AppRuntime>(roles.Any(r => r.RoleName == "admin"),
Error.New(403, "Admin role required"))
from result in PerformAdminAction()
select result;
Integration with Dispatch Authorization¶
The [Authorize], [Role], and [Permissions] attributes on dispatch handlers are evaluated before the handler runs — they use ICurrentUser automatically. Effects-based identity queries are for programmatic role management, not handler authorization. See Authorization for attribute-based access control.