Skip to content
bitzorcas
中EN

Reference

Authorization configuration, persistence, and caching

Reference for Host composition, production adapters, owner-local tables, dual-ORM contracts, seeds, events, cache keys, and invalidation ownership.

Last updated

Authorization has no single options section that explains production behavior. Composition, persistence provider, cache infrastructure, audit backend, seeds, and policy data are the real control plane.

1. Host composition order

AddBitzOrcasCoreRuntime

RBAC + AppScope
Null ABAC / ReBAC
Unavailable Feature

AddBitzOrcasPersistenceAdapters

Generated ORM / persistence adapters

AddBitzOrcasAuthorizationPlatform

Real ABAC / ReBAC / Feature
DataScope + four caches

Audit backend registration

Real IAuthorizationAuditSink

Final evaluator collection

CoreRuntime installs a resolvable, restricted graph: real RBAC and AppScope; Neutral ABAC and ReBAC placeholders; a false-returning Feature provider; simplified DataScope; and a possible Null audit sink.

The persistence path chooses generated SqlSugar or EF Core stores, registers the audit backend, and then adds real policy evaluators and cache adapters.

Relevant production composition
// 1. Install the API-shell graph and fail-closed defaults.
services.AddBitzOrcasCoreRuntime(configuration);
// 2. The public persistence extension selects ORM, audit store, generated adapters,
// and Authorization infrastructure in its reviewed internal order.
services.AddBitzOrcasPersistenceAdapters(configuration);
// These calls occur inside PersistenceRegistration after provider selection.
services.AddBitzOrcasAuditStore(configuration);
services.AddBitzOrcasGeneratedPersistenceAdapters(persistenceProvider);
services.AddBitzOrcasAuthorizationPlatform();

Business Hosts should call the public composition extensions, not repeat scoped evaluator registration.

2. Service inventory

ServiceCoreRuntimeProduction registrationLifetime
IAuthorizationDecisionServiceAuthorizationDecisionServiceSame implementation with closed dependenciesScoped
RBAC / AppScopeRealRetainedSingleton
ABAC / ReBACNeutral placeholdersReal evaluators appendedScoped
Feature providerUnavailable=falseFeatureStoreGenerated-adapter lifetime
IDataScopeResolverSimplifiedFull resolverScoped
Four cache portsBase portsCacheStore*CacheSingleton
IAuthorizationAuditSinkNull defaultAuditLoggerDispatcherSingleton

Identity Infrastructure implements the narrow IOrganizationUnitMemberRepository consumed by the full DataScope resolver. This is port collaboration, not a project reference from Authorization to Identity Infrastructure.

3. Persistence ownership

TableTenantSoft deleteKey contract
SysRoleTypeGlobalYesUnique RoleType
SysRoleYesYesUnique TenantId + Name
SysUserRoleYesYesUnique TenantId + UserId + RoleId
SysPermissionGlobalNoUnique permission Code
SysRoleModulePermissionYesYesFiltered unique role/user + module + permission relations
SysAbacRuleYesYesRead by tenant + module + resource type
SysFeatureDefinitionGlobalYesUnique FeatureCode and global DefaultState
SysFeatureOverrideYesYesUnique TenantId + FeatureCode, stores only OverrideState
SysResourceRelationYesYesUnique tenant + resource type/ID + user

These records are owner-local persistence models, not one-for-one legacy entity/mapper copies. Compile-time Fluent Configuration consumes their table, index, and column metadata.

3.1 Stable keys

  • SysRole.Id is a management ID; Name is the tenant-local relation key.
  • SysUserRole.UserId references an Identity-owned subject key.
  • SysPermission.Code is the global permission code; Mid identifies its Menu module.
  • Resource relations keep external type and ID only, with no cross-context CLR navigation.
  • Removing a tenant Feature override falls back to the global default without copying the definition.

4. Store roles

PortResponsibilityFailure contract
IRoleStoreManage and read role, user-role, role-permission dataFailClosed + BusinessClosedDefault
IAbacRuleManagementStoreABAC CRUDFail closed
IAbacRuleStoreRead enabled rules for evaluationException becomes evaluator Deny
IFeatureManagementStoreDefinitions and tenant override upsertFail closed
IFeatureStore / providerRead merged tenant stateMissing or failure becomes disabled / empty
IRelationStoreInstance relation and member readsFailure becomes ReBAC Deny
IAuthorizationAssignmentReaderSubject-projection role and permission readsOwner-local read port
IAuthorizationSubjectReaderConfirm the target Identity subjectPrevent orphan and cross-tenant UserRole writes

Management and evaluation ports are intentionally separate: management returns typed results, while security evaluation converts unavailable state into a stable denial.

5. Deterministic seeds

PrefixAssetContent
200200-sys_role_type.csvGlobal role types
210210-sys_role.csvInitial tenant roles
230230-sys_permission.csvBusiness permission catalog
240240-sys_role_module_permission.csvInitial role-to-module-permission relations
410410-sys_feature_definition.csvGlobal Feature definitions
520520-sys_user_role.csvInitial user-role bindings

Governance Generator also collects module contributions from permission catalog attributes. The generated and seeded catalogs need a union-consistency check so a code constant cannot exist without a database catalog row.

Review generated and seeded facts
# All permission codes must be globally unique and follow the naming convention.
rg -n "PermissionDefinition|public const string" \
src/Platform/Authorization/BitzOrcas.Platform.Authorization.Contracts -g '*.cs'
# A new permission or Feature needs a migration and idempotent seed coverage.
rg -n "authorization\.|platform\." \
src/Platform/Authorization/BitzOrcas.Platform.Authorization.Infrastructure/Seeders/Assets -g '*.csv'

6. Four independent caches

CachePolicyCore key factsInvalidation
Permission decisionMedium, 15 minutesFull identity + resource + action hashUser, tenant
ReBAC relationShort, 60 secondsTenant + resource + user + actionResource
DataScopeMedium, 15 minutesTenant + user + officeUser
FeatureMedium, 15 minutesTenant + FeatureCodeTenant

Permission decision get/set is best-effort at both adapter and service layers. Cache invalidation calls directly remove by tag and can fail a management request.

Cache responsibility after a relation write
await relations.UpsertAsync(relation, cancellationToken);
// Positive and negative ReBAC results are cached, so every relation change invalidates the resource.
await reBacCache.InvalidateByResourceAsync(
relation.ResourceType,
relation.ResourceId,
cancellationToken);
// If the relation also changes organization scope, invalidate that independent cache.
await dataScopeCache.InvalidateByUserAsync(
relation.TenantId,
relation.UserId,
cancellationToken);

This is the write-side protocol to implement. The module currently has no public relation write store.

7. Global Feature invalidation

UpdateFeatureState upserts a tenant override for tenant-scoped definitions and invalidates that tenant. For a global definition it updates DefaultState and calls InvalidateAllAsync. The invalidation scope now matches the write scope. Keep a two-tenant, multi-instance convergence test so a future optimization does not reintroduce stale global values or over-invalidate tenant overrides.

8. Integration events

EventChangesKey data
RoleChangedIntegrationEventCreated, Updated, DeletedEvent, tenant, role, type, actor, time
PermissionChangedIntegrationEventRoleAssigned, RoleRevoked, RolePermissionChangedUser, role, permission, change type
FeatureChangedIntegrationEventFeature state updateFeature code, enabled state, tenant, actor, time

These event types have no [IntegrationTopic]; runtime topic names use the full event type name. Consumers must not invent a short topic, and namespace/type changes require versioned integration handling.

9. Dual-ORM contract

For SqlSugar and EF Core, verify trusted tenant filters, equivalent filtered unique indexes, exclusion of soft-deleted rows, distinct empty-versus-failure semantics, idempotent stable-key seeding, and equivalent write-plus-event transaction behavior.

10. Production verification

Terminal window
# Confirm real stores and evaluators enter the persistence branch.
rg -n "AddBitzOrcasGeneratedPersistenceAdapters|AddBitzOrcasAuthorizationPlatform" \
src/Hosts/BitzOrcas.Api/Composition -g '*.cs'
# A real audit backend removes the Null authorization sink.
rg -n "RemoveAll<IAuthorizationAuditSink>|NullAuthorizationAuditSink" \
src/Framework -g '*.cs'
# Every owner relation needs explicit tenant, soft-delete, and unique-index metadata.
rg -n "BitzTable|BitzIndex" \
src/Platform/Authorization/BitzOrcas.Platform.Authorization.Infrastructure/Persistence -g '*.cs'

Previous: ABAC, ReBAC, and Feature · Next: testing and operations

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%