Advanced
Audit logging
Capture access checks and changes (upserts/deletes) by registering a custom audit sink.
using PrimusSaaS.Rbac;
public sealed class ConsoleRbacAuditSink : IRbacAuditSink
{
public void Record(RbacAuditEvent auditEvent)
{
Console.WriteLine($"{auditEvent.Timestamp:o} {auditEvent.EventType} {auditEvent.TargetType}:{auditEvent.TargetId}");
}
}
builder.Services.AddSingleton<IRbacAuditSink, ConsoleRbacAuditSink>();
Decision cache
RBAC can cache Evaluate() results through IRbacDecisionCache. If no implementation is
registered, RBAC uses a no-op default (NullRbacDecisionCache).
using PrimusSaaS.Rbac;
builder.Services.AddSingleton<IRbacDecisionCache, MyRbacDecisionCache>();
Implementations should include principal, scope, action, resource, roles, and relevant attributes in cache keys to avoid cross-scope contamination.
Tenant context provider
RBAC resolves tenant scope from IRbacTenantIdProvider when request tenant is omitted. For
Multi-Tenancy apps, use the bridge package:
using PrimusSaaS.MultiTenancy.Composition;
builder.Services.AddTenantRbacBridge();
This wires ambient tenant context into RBAC decisions automatically.
Role hierarchy (multiple parents)
By default, RBAC uses a strict tree (a role can inherit from a single parent). If you need multiple parents, enable it in configuration.
{
"Rbac": {
"AllowMultipleInheritance": true
}
}
Condition operators
These operators are supported for permission conditions:
eq,equals,=ne,neq,not_equals,!=incontainsstarts_withends_withgt,gte,gelt,lte,leexists,not_exists
Decision trace context
RbacDecision.Context contains trace metadata for each decision:
scope_keyscope_chain_lengthtoken_roles_countresolved_groupsevaluated_permissions
Use these values for troubleshooting authorization outcomes and dashboard metrics.