Second small package in a series I started last week (first one was rule-lite, a JSON rule evaluator). This one's about permissions.
Here's the thing about "can this user edit this invoice" - it sounds like a yes/no role question but it almost never is. It's really "can this user edit this invoice, AND do they own it, AND is it under some approval limit." Plain role-based permissions handle the first half fine. Then the second half turns into random if-checks scattered across the codebase, and six months later nobody remembers why that one check exists.
So I made entitlement-lite. Small idea: roles hold permissions like normal, but any permission can also carry an optional condition.
const engine = new EntitlementEngine([
{
name: 'contributor',
permissions: [{
action: 'edit',
resource: 'invoice',
condition: { field: 'resource.ownerId', operator: 'eq', value: 'u1' }
}]
}
]);
engine.can(subject, 'edit', 'invoice', { resource: { ownerId: 'u1' } }); // true
No condition on a permission? It's just a normal role check. Condition present? It gets evaluated at request time using rule-lite (the package I put out last week). I didn't want to write a second rule engine just for this, so it reuses the first one.
Also supports wildcards so you're not stuck writing { action: 'view' }, { action: 'edit' }, { action: 'delete' }... for an admin role - { action: '*', resource: '*' } covers it.
It's deliberately not trying to be OPA or Casbin. Those are the right call for big multi-service auth systems. This is for the much more common case: one app, a handful of roles, a few conditions that need actual logic instead of hardcoded ifs.
Repo: https://github.com/tejas821/entitlement-lite
npm: https://www.npmjs.com/package/entitlement-lite
If you've built something similar or have opinions on the API (especially the wildcard matching or how conditions merge into context), I'd like to hear it.
Top comments (0)