Changelog - 2026-06-02
Scoped RBAC Authorization
Breaking Change EnhancementIn one line. The authorize module is rebuilt around a single edge table and a scoped Casbin model with role, resource, action, and domain hierarchies - replacing the per-app adapter with a generic, configuration-driven one and closing a concurrency race in the enforcer.
The problem it solves
Before this release, every application added Casbin RBAC by subclassing DrizzleCasbinAdapter and sharing one Casbin enforcer across requests. Concurrent requests could interleave on that shared enforcer and corrupt policy state mid-check.
Turn on the new model with three options on ICasbinEnforcerOptions:
{ isScoped: true, poolSize: 16, poolAcquireTimeoutMs: 5000 }Each request now borrows its own enforcer from a pool instead of racing on a shared one.
What changed
ScopedCasbinAdapter- a generic, read-onlyFilteredAdapter. It reads one principal's edges (role assignments, memberships, grants) plus the shared structural hierarchy from a singlePolicyDefinitionedge table. Configure it viaIScopedCasbinEntities- no subclassing required.- Scoped Casbin model (
CASBIN_RBAC_DOMAIN_SCOPED_MODEL) -r = sub, dom, obj, act, default-deny with explicit-deny-wins, and five grouping relations:grole,g2domain membership,g3domain hierarchy,g4resource hierarchy,g5action hierarchy. Domain scoping usesSYSTEM_WIDEandANY_MEMBERsentinels. BaseFilteredAdapter<TFilter>rewritten thin - it owns datasource/connector plumbing, theisFiltered()flag, and the no-op write methods. Subclasses implement onlyloadFilteredPolicy.- Per-request enforcer pool - each request borrows an enforcer from a pool, loads only that user's lines, and enforces - all inside one atomic
pool.use. The pool destroys the enforcer on any error (fail-closed). - Redis-only line cache - per-user Casbin lines are cached in Redis with a TTL and single-flight dedup of concurrent cache misses. A corrupt entry is discarded and refetched rather than causing a 500.
- Optional
invalidateUserCache/rebuildUserCacheevict or rebuild a user's cached lines.
- Optional
Options
New fields on ICasbinEnforcerOptions:
| Option | Default | Meaning |
|---|---|---|
isScoped | false | Enables the 4-token scoped model |
poolSize | 16 | Enforcers held in the per-request pool |
poolAcquireTimeoutMs | 5000 | Wait for a pooled enforcer before failing closed |
Who is affected
- Applications that subclassed
DrizzleCasbinAdapter- must migrate toScopedCasbinAdapteror the new thinBaseFilteredAdapter(breaking, see below). - Applications using the in-memory Casbin cache driver - must switch to Redis (breaking, see below).
- Applications that built a custom
ICasbinPolicyFilter- the filter shape changed (breaking, see below). - Applications referencing
CasbinRuleVariants.GROUPor.POLICY- those members are removed (breaking, see below). - Applications using
IAuthorizationCacheInvalidator- removed; cache management is now optional methods onIAuthorizationEnforcer(breaking, see below). - Applications not using Casbin authorization at all - no action needed.
Breaking changes
WARNING
Apps that subclassed DrizzleCasbinAdapter, used the in-memory cache driver, or referenced CasbinRuleVariants.GROUP/.POLICY must migrate. See the Scoped RBAC Migration Guide for both supported migration paths with full before/after code.
1. DrizzleCasbinAdapter removed
DrizzleCasbinAdapter and IDrizzleCasbinAdapterOptions are gone. Use ScopedCasbinAdapter (generic, edge-table) or subclass the new thin BaseFilteredAdapter.
2. Filter shape changed
// Before
interface ICasbinPolicyFilter { principalType: string; principalValue: string | number; }
// After
interface ICasbinPolicyFilter { principal: { type: string; id: IdType }; }3. CasbinRuleVariants trimmed
// Before: GROUP ('group'), POLICY ('policy'), SCHEME_SET, isValid all existed
// After: only Casbin prefixes remain
CasbinRuleVariants = { P, G, G2, G3, G4, G5 };The database variant discriminator now lives on AuthorizationPolicyVariants.*.action (grant, assign_role, join_domain, role_inherits, resource_inherits, action_inherits, domain_inherits).
4. In-memory cache driver removed
// Before
cached: { use: true, driver: CasbinEnforcerCachedDrivers.IN_MEMORY }
// After
cached: { use: false } | (ICasbinEnforcerCachedRedis & { use: true })Provide Redis for caching, or { use: false } for none.
5. IAuthorizationCacheInvalidator removed
IAuthorizationCacheInvalidator / TAuthorizationCacheInvalidator are gone. Cache management is now expressed as optional members of IAuthorizationEnforcer (invalidateUserCache?, rebuildUserCache?), which the registry feature-detects.
See also
- Scoped RBAC Migration Guide - the two supported paths, bridging with no data migration or adopting the scoped model, with exact before/after code for each
- Authorization - the
AuthorizeComponentoverview