Core resources and relations
- organization — the bank tenant.
- account — has an
owner, optionalco_owners, and anaccount_managerassigned by the bank. - transaction — initiated against an
account, subject to a per-actor amount limit.
ownerandco_owneronaccount— full read and full transaction rights up to a personal limit.account_manageronaccount— bank staff who can view the account and initiate transactions, but only up to a manager-specific limit that may differ from the owner’s.delegateonaccount— owners can delegate a subset of rights to another person (a spouse, a bookkeeper) with a separate, lower limit.
Why this is hard in role-only systems
A typical “manager”, “owner”, “delegate” RBAC scheme answers what action is allowed but not up to what amount. Hard-coding the amount in application logic means:- The auth decision is split across two systems (an RBAC check + an
if amount > Xbranch). - Audit can’t answer “who could have wired more than $50k from account A on date D” without joining application code with role tables.
- Delegation expiry, per-transaction overrides, and dual-control approvals each become bespoke features.
can_initiate_transfer takes the transaction amount as a contextual parameter and returns a single allow/deny.
Where this maps to OpenFGA features
Common extensions
The base sample covers individual accounts. Adopters typically extend it with:- Joint accounts and trusts. Add a
beneficiaryrelation that grants read access only. - Corporate accounts. Introduce a
companytype; assign signatories viasignatoryand require N-of-M via your application callingCheckfor each required signer. - Step-up authentication. When the transaction amount exceeds a threshold, pass a contextual tuple
mfa_verified=trueand gate the relevant relation on it.