@useoneauth/policies
v1.0.0
Published
> Phase 6 — Policy Engine. Centralized authorization: `can(request)` over composable RBAC / ABAC / ReBAC.
Downloads
300
Readme
@useoneauth/policies
Phase 6 — Policy Engine. Centralized authorization:
can(request)over composable RBAC / ABAC / ReBAC.
Pure TypeScript. One PolicyEngine composes pluggable evaluators — each returns
permit / deny / abstain — and combines them with deny-overrides + default-deny.
Decisions carry obligations (step-up auth, scope restriction) and emit
POLICY_ALLOWED / POLICY_DENIED. Stores are in-memory behind ports.
Install
// package.json
{ "dependencies": { "@useoneauth/policies": "workspace:*" } }Usage
import {
PolicyEngine, RbacEvaluator, AbacEvaluator, RebacEvaluator,
InMemoryRoleStore, InMemoryRelationshipResolver,
} from "@useoneauth/policies"
import { EventBus, InMemoryEventStore } from "@useoneauth/events"
const roles = new InMemoryRoleStore()
roles.assignRole("u1", "editor")
roles.defineRole("editor", [{ action: "edit", resourceType: "document", effect: "permit" }])
const rels = new InMemoryRelationshipResolver()
rels.addRelationship("u1", "owns", "d1")
const engine = new PolicyEngine({
evaluators: [
new RbacEvaluator(roles),
new AbacEvaluator([
{ id: "owner", effect: "permit", condition: (r) => r.resource.attributes?.ownerId === r.subject.id },
]),
new RebacEvaluator(rels, [{ action: "edit", resourceType: "document", relation: "owns" }]),
],
events: new EventBus(new InMemoryEventStore()), // durable, auditable decisions
})
const decision = await engine.can({
subject: { id: "u1" },
action: "edit",
resource: { type: "document", id: "d1", attributes: { ownerId: "u1" } },
})
// { effect: "allow", reason: "permitted by ...", obligations: {}, results: [...] }Models
- RBAC —
RbacEvaluator(RoleStore): subject's roles →Permission { action, resourceType, effect }, with"*"wildcards; deny-overrides within the evaluator. - ABAC —
AbacEvaluator(AbacPolicy[]): typed predicate policies{ id, effect, appliesTo?, condition(request) }(programmatic — no string DSL). - ReBAC —
RebacEvaluator(RelationshipResolver, RebacRule[]): one-hop relationship check (subject —relation→ resource.id). Multi-hop is a future phase.
Decision model
Each evaluator returns permit | deny | abstain. The engine: any deny → deny;
else any permit → allow (merging obligations: stepUp OR, scope union); else
(all abstain) → default deny. Every decision includes a per-evaluator results
trace for audit.
Events
POLICY_ALLOWED, POLICY_DENIED via the @useoneauth/events-core EventPublisher
(wire the Phase-5 EventBus for a durable, replayable authorization audit trail).
Scope
RBAC + ABAC full; ReBAC one-hop only; no expression-language DSL; no policy-admin API;
no DB/HTTP/CLI. Subjects/resources are string ids — no dependency on @useoneauth/identity.
See ARCHITECTURE.md.
