Skip to content
TypeWire

@tahanabavi/type-permission

v0.1.0

Framework-less, dependency-free capability permissions: one shared bit map, evaluated identically on client and server, with layered resolution, codecs, a lock file and contract-linkable requirements.

Framework-less by design — bindings are snippets, not packages

createStore implements the repo-wide Observable<T>, so every framework binds it in a line of your code:

ts
const store = P.createStore({ global: initialBits });

// React useSyncExternalStore(store.subscribe, () => store.getSnapshot())
// Vue shallowRef + store.subscribe + onScopeDispose
// Svelte store already satisfies the Svelte store contract
// Express (req,res,next) => P.has(req.perms, "x") ? next() : res.sendStatus(403)
// Next mw P.has(P.decode(cookie, "base64url"), "x")

Reads are synchronous (a render can't await); loading is not the store's job — fetch with query-core (or SSR) and push results in via set / setScope. An unknown scope falls back to global, keeping every check total. Scoped resolution memoizes via P.createResolver({ compute, ttl, version }), keyed by actor · scope · version so an epoch bump invalidates an actor's whole scope set at once.

Cross-project & polyglot

ts
P.buildLock();          // permissions.lock.json — a name→bit manifest
P.diffLock(previous); // [] when safe; flags bit-reuse / bit-change / removal — fail CI
P.catalog(); // rows for a role-editor UI (hidden flags omitted)

The lock file is the interop artifact: a Go or Python service needs only it plus three lines of bit math, and CI catches any consumer drifting from it.