Notes on RBAC, architecture, and transparency
When an access incident hits, the first question is never "how did the bug happen" — it's "who could do this, and who approved it." Here's why most teams can't answer that in under an hour, and what changes when the answer is a grep.
2026's agent security data says the dominant failure mode is over-permissioning, not model behavior — here's an honest look at where folder-scoped RBAC actually helps, and where it runs out.
The specific chokidar configuration and cache-invalidation ordering that keep rbac-fs's live-reload from ever serving a role it just wrote itself, or missing an edit from someone else.
SOC 2 doesn't just want you to review access quarterly — it wants evidence for every quarter, and most teams are paying for that in engineering-manager hours nobody budgeted.
The concrete symptoms that separate "this needs a condition" from "this needs a relationship graph" — and the honest, incremental path if you're actually in the second category.
OPA/Rego and Zanzibar-style engines like OpenFGA and SpiceDB solve real problems rbac-fs doesn't — here's what each actually costs to operate, and an honest line for where rbac-fs stops being the right tool.
The build-vs-buy literature treats authorization as a choice between building a service and buying one, but the cost data both sides cite actually argues for a third option neither names.
2026's npm supply-chain attacks got names and dates — here's why the code path that decides who's allowed to do what is the worst place to carry that exposure, and what rbac-fs does about it specifically.
Infrastructure teams spent years naming and tooling against "drift" — the gap between declared and enforced state. Most RBAC systems have the exact same failure mode and no name for it.
SOC 2 auditors and acquisition due-diligence teams both eventually ask who can do what and prove it — here's what they check, and how rbac-fs answers most of it without extra tooling.
Git-diffable roles aren't a gimmick — they change who can review a permission change, and when, compared to an opaque policy blob in a database.
Three real libraries, three different trade-offs — storage model, framework coverage, and what happens when you need to audit a permission change.
Folder isolation instead of a WHERE clause — what that structurally buys you for tenant isolation, and where it stops being enough at real scale.
What actually happens between calling can() and getting true or false back — role loading, inheritance, and condition evaluation, in order.
A tutorial-paced walkthrough of installing rbac-fs, creating a role, and running your first can() check, in both JavaScript and TypeScript.
A permission system that requires a deploy to add one role is solving the wrong problem — how rbac-fs makes role changes a runtime operation instead.
A hands-on walkthrough of every dynamic role management call in rbac-fs, with the actual file contents shown at each step.
How rbac-fs's built-in audit trail works — JSONL format, why not a single JSON array, and what's actually in each record.
A hands-on walkthrough of configuring log rotation and querying audit history in rbac-fs, including what each rotation option actually controls.
Beyond allow or deny — how rbac-fs's condition system handles "approve your own expense report" without reaching for eval() or a rules engine.
Step-by-step construction of an AND/OR condition tree in rbac-fs, from a single clause to a nested, real-world approval rule.
A hands-on walkthrough of tenant-scoped and shared roles in rbac-fs, including the path-sanitization behavior you should verify yourself.
Role files are cached in memory for speed — here's how rbac-fs's chokidar-backed watcher keeps that cache honest when someone edits a file by hand.
A step-by-step demo of rbac-fs's live-reload — edit a role JSON file directly and see the permission change without restarting anything.
rbac-fs's Node core never belongs in a browser bundle — here's how RBACClient gives the frontend the same can() call without any filesystem dependency.
A vanilla-JS walkthrough of RBACClient — useful on its own, and as the mental model underneath every rbac-fs frontend framework adapter.
rbac-fs bakes path sanitization, schema validation, reserved names, and circular-inheritance detection into Core Engine, not left to consumers.
Don't take the docs' word for it — four runnable snippets proving path sanitization and circular-inheritance detection actually reject what they claim to.
rbac-fs's NestJS adapter is opt-in per route via @RequirePermission() — a route with no decorator is allowed through unchecked, deliberately.
A runnable walkthrough of rbac-fs's NestJS guard and decorator, driving RbacGuard directly so you can see every outcome without booting a full Nest app.
rbac-fs's Express, Koa, and Fastify adapters share the same rbacMiddleware shape — here's what stays the same and what each framework forces to differ.
A runnable, curl-able Express example — one guarded route, three requests, three different outcomes, and the auth-ordering rule that makes it work.
rbac-fs's Fastify adapter must be registered at the root app, not inside an encapsulated sub-plugin — the encapsulation rule that makes that a hard requirement.
A runnable Fastify example covering plugin registration, per-route rbac config, and both the allowed and denied response paths.
rbac-fs's Koa adapter shares Express's rbacMiddleware signature but reads the user from ctx.state — Koa's own documented convention, not an arbitrary choice.
A runnable Koa example — same rbacMiddleware shape as Express, ctx.state instead of req.user, three requests and three outcomes.
rbac-fs's React adapter follows CASL's I/a naming convention on purpose — one less thing to relearn if your team already knows CASL's mental model.
A headless react-test-renderer walkthrough of <Can>, RbacProvider, and usePermission() — the same technique the adapter's own test suite uses.
rbac-fs's v-can directive toggles display:none like v-show — a deliberate choice, different from the true unmount you get from rbac-fs's Angular and React adapters.
A runnable, no-browser walkthrough of rbac-fs's Vue plugin, v-can directive, and usePermission() composable using the same verification approach as its test suite.
rbac-fs's Angular adapter does a real ViewContainerRef unmount/remount, matching *ngIf's own public API instead of a display:none toggle.
A runnable walkthrough that drives RbacService and RbacCanDirective directly with a fake ViewContainerRef — the same approach the adapter's own test suite uses.
rbac-fs's Svelte adapter closes over an explicit RBACClient instead of Svelte's context API — favoring traceability over implicit wiring.
A runnable, no-browser walkthrough of createPermissionStore and createCanAction — the store and action primitives underneath rbac-fs's Svelte adapter.