Require Gates
.require() adds a mandatory gate: a condition that must pass for a check to
be granted, independent of any role’s grants.
granted = (a grant matches) AND (every applicable gate passes)Scopes
Section titled “Scopes”A gate applies at one of three scopes. On a check, the applicable gates are the global ones, plus the resource’s category gates, plus the resource gates — all must pass.
ac.require('$.env == prod'); // global: every checkac.category('billing') .require('$.ip cidr 10.0.0.0/8'); // any billing/* resourceac.resource('billing/invoice') .require('$.mfa == true'); // just billing/invoiceExample: Layered Gates
Section titled “Example: Layered Gates”const ac = new AccessControl(grants, { context: { env: process.env.NODE_ENV }});
ac.require('$.env == prod'); // 1) prod onlyac.category('billing').require('$.ip cidr 10.0.0.0/8'); // 2) + from the VPNac.resource('billing/invoice').require('$.mfa == true'); // 3) + MFA
// passes only if prod AND in-VPN AND mfa — on top of a matching grantac.can('accountant', { ip, mfa: true }) .readAny('billing/invoice').granted;A denial by a gate surfaces as reason: 'require_failed' on the
access event.
Inspecting Gates
Section titled “Inspecting Gates”ac.getRequirements();// { global: [...], categories: { billing: [...] }, resources: { 'billing/invoice': [...] } }Async Gates
Section titled “Async Gates”A gate may use a custom { fn, args } condition; like conditional grants, that
moves the check to the async path
(grantedAsync / checkAsync).