Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

Role-Based Authorization Policies

Authorisation that lives scattered through if (user.role === 'admin') checks is authorisation that drifts. @frenchexdev/ddd-rbac reifies authorisation as a port: policies are typed predicates over (subject, action, resource), the application calls policy.check(...) at every guarded entry point, and the adapter decides how the policy actually evaluates — static role table, OPA (Open Policy Agent) external service, custom rule engine.


What RBAC Reifies

The RBAC port enforces three things. Authorisation lives in named policies, not in scattered conditionals. A policy named CanCancelSubscription is its own typed object; consumers ask it policy.check(user, 'cancel', subscription) and get a Result<Allow | Deny, Reason>. The named policy is what shows up in the audit trail; the conditional was anonymous.

The check is a Result, not a boolean. A denied check returns the reason — not subscriber's owner, role missing required scope, resource locked — so the application can produce a meaningful error message instead of a generic 403. The reason is structured, typed, and audit-friendly.

The substrate is replaceable. A small system has a static RolePermissionTable adapter — three roles, a hard-coded permission list. A larger system replaces it with an OPA adapter that pulls policies from a centralised governance repo. The application code does not change; the conformance suite verifies that both adapters answer the same checks the same way.


The Runtime: ddd-rbac and adapter

Two packages — ddd-rbac, ddd-rbac-static-adapter — both M4/M5 stubs pinned to RbacPolicyExpressedRequirement. The static adapter ships first because it covers the common case — a system with a handful of roles and a fixed permission matrix — without forcing an OPA deployment on small teams.


The Analyzer: ddd-rbac-analyzer

Spec-first (spec.ts). Priority Medium. Two rules — DDD-RBAC-001 recommends the Policy suffix at info severity; DDD-RBAC-002 enforces single-per-file at error severity. A future cross-AST rule could verify that every @CommandHandler calls at least one policy before mutating an aggregate; the spec is where that rule will land.


  • Called by @CommandHandler and @QueryHandler before any aggregate is touched.
  • Every check, allowed or denied, is recorded in @AuditTrail — authorisation decisions are compliance-relevant.
  • The named policy plus the Reason typed enum compose with @DomainEvent failure events when a denial needs to be propagated.
  • Lives behind @Port/@Adapter; static, OPA, and custom-engine adapters satisfy the same conformance suite.

Back to the series index.

⬇ Download