@nifrajs/auth 2.9.1 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Session primitives for nifra - signed-cookie + server-store sessions, CSRF, and route guards. Bring your own identity (Better Auth / Lucia / OAuth); nifra owns the session.
4
4
 
5
+ `Authorizer`/`requireAuthorization` provide a small public policy seam. The application or data layer
6
+ must decide ownership and permissions; Nifra stores no policy, tenant, or subject data.
7
+
5
8
  Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework - one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
6
9
 
7
10
  ## Install
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Public authorization seam. Nifra supplies the control-flow contract; the application or data layer
3
+ * supplies the actual policy. No subject/resource data is persisted or interpreted here.
4
+ */
5
+ export interface AuthorizationRequest<Subject = unknown, Resource = unknown> {
6
+ readonly subject: Subject;
7
+ readonly action: string;
8
+ readonly resource?: Resource;
9
+ }
10
+ export type Authorizer<Subject = unknown, Resource = unknown> = (request: AuthorizationRequest<Subject, Resource>) => boolean | Promise<boolean>;
11
+ /** Evaluate a policy, failing closed for any non-true result. */
12
+ export declare function isAuthorized<Subject, Resource>(authorizer: Authorizer<Subject, Resource>, request: AuthorizationRequest<Subject, Resource>): Promise<boolean>;
13
+ /** Require an application/data-layer policy to allow an action; denied requests throw a 403 Response. */
14
+ export declare function requireAuthorization<Subject, Resource>(authorizer: Authorizer<Subject, Resource>, request: AuthorizationRequest<Subject, Resource>): Promise<void>;
15
+ //# sourceMappingURL=authorization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,oBAAoB,CAAC,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAC7B;AAED,MAAM,MAAM,UAAU,CAAC,OAAO,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO,IAAI,CAC9D,OAAO,EAAE,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,KAC7C,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/B,iEAAiE;AACjE,wBAAsB,YAAY,CAAC,OAAO,EAAE,QAAQ,EAClD,UAAU,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,EACzC,OAAO,EAAE,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,GAC/C,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,yGAAyG;AACzG,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,QAAQ,EAC1D,UAAU,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,EACzC,OAAO,EAAE,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -0,0 +1,11 @@
1
+ /** Evaluate a policy, failing closed for any non-true result. */
2
+ export async function isAuthorized(authorizer, request) {
3
+ return (await authorizer(request)) === true;
4
+ }
5
+ /** Require an application/data-layer policy to allow an action; denied requests throw a 403 Response. */
6
+ export async function requireAuthorization(authorizer, request) {
7
+ if (await isAuthorized(authorizer, request))
8
+ return;
9
+ throw Response.json({ ok: false, error: "forbidden" }, { status: 403 });
10
+ }
11
+ //# sourceMappingURL=authorization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization.js","sourceRoot":"","sources":["../src/authorization.ts"],"names":[],"mappings":"AAcA,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAyC,EACzC,OAAgD;IAEhD,OAAO,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,CAAA;AAC7C,CAAC;AAED,yGAAyG;AACzG,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAyC,EACzC,OAAgD;IAEhD,IAAI,MAAM,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC;QAAE,OAAM;IACnD,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;AACzE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * pluggable-store + prod-guard discipline as the ISR cache. **Bring your own identity** (Better Auth,
4
4
  * Lucia, your own OAuth/password logic); nifra owns the session cookie, store, CSRF, and route guards.
5
5
  */
6
+ export { type AuthorizationRequest, type Authorizer, isAuthorized, requireAuthorization, } from "./authorization.js";
6
7
  export { type CsrfOptions, csrf } from "./csrf.js";
7
8
  export { type GuardOptions, requireSession, requireUser } from "./guards.js";
8
9
  export { createSessions, type Session, type SessionContext, type SessionCookieOptions, type SessionManager, type SessionOptions, } from "./session.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,WAAW,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EACL,cAAc,EACd,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,KAAK,eAAe,EACpB,cAAc,EACd,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,YAAY,EACZ,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,KAAK,WAAW,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EACL,cAAc,EACd,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,KAAK,eAAe,EACpB,cAAc,EACd,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * pluggable-store + prod-guard discipline as the ISR cache. **Bring your own identity** (Better Auth,
4
4
  * Lucia, your own OAuth/password logic); nifra owns the session cookie, store, CSRF, and route guards.
5
5
  */
6
+ export { isAuthorized, requireAuthorization, } from "./authorization.js";
6
7
  export { csrf } from "./csrf.js";
7
8
  export { requireSession, requireUser } from "./guards.js";
8
9
  export { createSessions, } from "./session.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAoB,IAAI,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAqB,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EACL,cAAc,GAMf,MAAM,cAAc,CAAA;AACrB,OAAO,EAEL,cAAc,EACd,kBAAkB,GAInB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,YAAY,EACZ,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAoB,IAAI,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAqB,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC5E,OAAO,EACL,cAAc,GAMf,MAAM,cAAc,CAAA;AACrB,OAAO,EAEL,cAAc,EACd,kBAAkB,GAInB,MAAM,YAAY,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/auth",
3
- "version": "2.9.1",
3
+ "version": "2.11.0",
4
4
  "description": "Session primitives for nifra - signed-cookie + server-store sessions, CSRF, and route guards. Bring your own identity (Better Auth / Lucia / OAuth); nifra owns the session.",
5
5
  "keywords": [
6
6
  "bun",
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "peerDependencies": {
38
- "@nifrajs/core": "^2.9.1"
38
+ "@nifrajs/core": "^2.11.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@nifrajs/core": "workspace:*"
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Public authorization seam. Nifra supplies the control-flow contract; the application or data layer
3
+ * supplies the actual policy. No subject/resource data is persisted or interpreted here.
4
+ */
5
+ export interface AuthorizationRequest<Subject = unknown, Resource = unknown> {
6
+ readonly subject: Subject
7
+ readonly action: string
8
+ readonly resource?: Resource
9
+ }
10
+
11
+ export type Authorizer<Subject = unknown, Resource = unknown> = (
12
+ request: AuthorizationRequest<Subject, Resource>,
13
+ ) => boolean | Promise<boolean>
14
+
15
+ /** Evaluate a policy, failing closed for any non-true result. */
16
+ export async function isAuthorized<Subject, Resource>(
17
+ authorizer: Authorizer<Subject, Resource>,
18
+ request: AuthorizationRequest<Subject, Resource>,
19
+ ): Promise<boolean> {
20
+ return (await authorizer(request)) === true
21
+ }
22
+
23
+ /** Require an application/data-layer policy to allow an action; denied requests throw a 403 Response. */
24
+ export async function requireAuthorization<Subject, Resource>(
25
+ authorizer: Authorizer<Subject, Resource>,
26
+ request: AuthorizationRequest<Subject, Resource>,
27
+ ): Promise<void> {
28
+ if (await isAuthorized(authorizer, request)) return
29
+ throw Response.json({ ok: false, error: "forbidden" }, { status: 403 })
30
+ }
package/src/index.ts CHANGED
@@ -3,6 +3,13 @@
3
3
  * pluggable-store + prod-guard discipline as the ISR cache. **Bring your own identity** (Better Auth,
4
4
  * Lucia, your own OAuth/password logic); nifra owns the session cookie, store, CSRF, and route guards.
5
5
  */
6
+
7
+ export {
8
+ type AuthorizationRequest,
9
+ type Authorizer,
10
+ isAuthorized,
11
+ requireAuthorization,
12
+ } from "./authorization.ts"
6
13
  export { type CsrfOptions, csrf } from "./csrf.ts"
7
14
  export { type GuardOptions, requireSession, requireUser } from "./guards.ts"
8
15
  export {