No field here for a permission your code doesn’t enforce.
04 the grant lands in your own database, and can() answers there, in-process
The arrow runs outward from the code, not inward from a console.
Topologies
Alfiz fits the organization you already have.
One application or a dozen, one database or one each, permissions crossing between them or strictly separate. Every combination below is a supported deployment, and a place deployments stay.
No cross-app accesseach app answers only for itself
Granted cross-app accessroles and permissions compose across apps
In all four, can() answers in your process, from your own tables.
Coding agents
Built to support Agent-driven development.
An agent has two lines to get right when it adds a permission, one search to find every place one is spent, and a verifier that fails the build when it misses a gate.
Adding one
Expanding permissions requires minimal context.
Two lines add a permission: one in the catalog, one at the call site. There is nothing else an agent has to find first.
An agent works on the task in front of it and misses the surface next door. alfiz-verify fails the build when a route ships without a gate.
A surface is not done until all four points hold:
1 · The page
Gated before a row is fetched.
2 · Navigation
Only items the principal matches are rendered at all.
3 · The server action
Gated before any work. The step that gets skipped, so it errors.
4 · Conditional UI
Gated at the scope of the thing it acts on.
ci · every commitbash
$ alfiz-verify✖[ungated-action] app/actions/export.ts:14exported server action "exportDocument" contains no gate✖[visibility-as-gate] app/actions/share.ts:15canAny() is a visibility affordance, never a gate⚠[unreferenced-leaf]"docs.files.read_history"declared, but referenced by no gate or nav item
Your first check, in under ten minutes.
Install two packages, declare a catalog, wire the driver you already have, and call can().