@c9up/warden 0.1.3 → 0.1.4

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.
Files changed (134) hide show
  1. package/dist/AuthManager.d.ts +98 -0
  2. package/dist/AuthManager.d.ts.map +1 -0
  3. package/dist/AuthManager.js +147 -0
  4. package/dist/AuthManager.js.map +1 -0
  5. package/dist/AuthRateLimiter.d.ts +29 -0
  6. package/dist/AuthRateLimiter.d.ts.map +1 -0
  7. package/dist/AuthRateLimiter.js +88 -0
  8. package/dist/AuthRateLimiter.js.map +1 -0
  9. package/dist/Guard.d.ts +26 -0
  10. package/dist/Guard.d.ts.map +1 -0
  11. package/dist/Guard.js +52 -0
  12. package/dist/Guard.js.map +1 -0
  13. package/dist/RefreshTokenStore.d.ts +34 -0
  14. package/dist/RefreshTokenStore.d.ts.map +1 -0
  15. package/dist/RefreshTokenStore.js +48 -0
  16. package/dist/RefreshTokenStore.js.map +1 -0
  17. package/dist/TokenBlacklist.d.ts +30 -0
  18. package/dist/TokenBlacklist.d.ts.map +1 -0
  19. package/dist/TokenBlacklist.js +50 -0
  20. package/dist/TokenBlacklist.js.map +1 -0
  21. package/dist/WardenProvider.d.ts +19 -0
  22. package/dist/WardenProvider.d.ts.map +1 -0
  23. package/dist/WardenProvider.js +61 -0
  24. package/dist/WardenProvider.js.map +1 -0
  25. package/dist/bouncer/AuthorizationResponse.d.ts +25 -0
  26. package/dist/bouncer/AuthorizationResponse.d.ts.map +1 -0
  27. package/dist/bouncer/AuthorizationResponse.js +31 -0
  28. package/dist/bouncer/AuthorizationResponse.js.map +1 -0
  29. package/dist/bouncer/BasePolicy.d.ts +47 -0
  30. package/dist/bouncer/BasePolicy.d.ts.map +1 -0
  31. package/dist/bouncer/BasePolicy.js +36 -0
  32. package/dist/bouncer/BasePolicy.js.map +1 -0
  33. package/dist/bouncer/Bouncer.d.ts +47 -0
  34. package/dist/bouncer/Bouncer.d.ts.map +1 -0
  35. package/dist/bouncer/Bouncer.js +134 -0
  36. package/dist/bouncer/Bouncer.js.map +1 -0
  37. package/dist/bouncer/PolicyAuthorizer.d.ts +24 -0
  38. package/dist/bouncer/PolicyAuthorizer.d.ts.map +1 -0
  39. package/dist/bouncer/PolicyAuthorizer.js +92 -0
  40. package/dist/bouncer/PolicyAuthorizer.js.map +1 -0
  41. package/dist/bouncer/decorators.d.ts +25 -0
  42. package/dist/bouncer/decorators.d.ts.map +1 -0
  43. package/dist/bouncer/decorators.js +36 -0
  44. package/dist/bouncer/decorators.js.map +1 -0
  45. package/dist/bouncer/evaluate.d.ts +36 -0
  46. package/dist/bouncer/evaluate.d.ts.map +1 -0
  47. package/dist/bouncer/evaluate.js +64 -0
  48. package/dist/bouncer/evaluate.js.map +1 -0
  49. package/dist/bouncer/policyContext.d.ts +29 -0
  50. package/dist/bouncer/policyContext.d.ts.map +1 -0
  51. package/dist/bouncer/policyContext.js +36 -0
  52. package/dist/bouncer/policyContext.js.map +1 -0
  53. package/dist/bouncer/types.d.ts +52 -0
  54. package/dist/bouncer/types.d.ts.map +1 -0
  55. package/dist/bouncer/types.js +9 -0
  56. package/dist/bouncer/types.js.map +1 -0
  57. package/dist/config.d.ts +42 -0
  58. package/dist/config.d.ts.map +1 -0
  59. package/dist/config.js +21 -0
  60. package/dist/config.js.map +1 -0
  61. package/dist/configure.d.ts +10 -0
  62. package/dist/configure.d.ts.map +1 -0
  63. package/dist/configure.js +44 -0
  64. package/dist/configure.js.map +1 -0
  65. package/dist/errors.d.ts +18 -0
  66. package/dist/errors.d.ts.map +1 -0
  67. package/dist/errors.js +21 -0
  68. package/dist/errors.js.map +1 -0
  69. package/dist/firstcontact/FirstContactManager.d.ts +25 -0
  70. package/dist/firstcontact/FirstContactManager.d.ts.map +1 -0
  71. package/dist/firstcontact/FirstContactManager.js +38 -0
  72. package/dist/firstcontact/FirstContactManager.js.map +1 -0
  73. package/dist/firstcontact/drivers/GitHubDriver.d.ts +14 -0
  74. package/dist/firstcontact/drivers/GitHubDriver.d.ts.map +1 -0
  75. package/dist/firstcontact/drivers/GitHubDriver.js +61 -0
  76. package/dist/firstcontact/drivers/GitHubDriver.js.map +1 -0
  77. package/dist/firstcontact/drivers/GoogleDriver.d.ts +14 -0
  78. package/dist/firstcontact/drivers/GoogleDriver.d.ts.map +1 -0
  79. package/dist/firstcontact/drivers/GoogleDriver.js +64 -0
  80. package/dist/firstcontact/drivers/GoogleDriver.js.map +1 -0
  81. package/dist/firstcontact/types.d.ts +34 -0
  82. package/dist/firstcontact/types.d.ts.map +1 -0
  83. package/dist/firstcontact/types.js +5 -0
  84. package/dist/firstcontact/types.js.map +1 -0
  85. package/dist/index.d.ts +38 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +27 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/middleware.d.ts +51 -0
  90. package/dist/middleware.d.ts.map +1 -0
  91. package/dist/middleware.js +201 -0
  92. package/dist/middleware.js.map +1 -0
  93. package/dist/native.d.ts +14 -0
  94. package/dist/native.d.ts.map +1 -0
  95. package/dist/native.js +39 -0
  96. package/dist/native.js.map +1 -0
  97. package/dist/rights/MemoryRightsStore.d.ts +29 -0
  98. package/dist/rights/MemoryRightsStore.d.ts.map +1 -0
  99. package/dist/rights/MemoryRightsStore.js +70 -0
  100. package/dist/rights/MemoryRightsStore.js.map +1 -0
  101. package/dist/rights/RightsResolver.d.ts +29 -0
  102. package/dist/rights/RightsResolver.d.ts.map +1 -0
  103. package/dist/rights/RightsResolver.js +73 -0
  104. package/dist/rights/RightsResolver.js.map +1 -0
  105. package/dist/rights/types.d.ts +55 -0
  106. package/dist/rights/types.d.ts.map +1 -0
  107. package/dist/rights/types.js +18 -0
  108. package/dist/rights/types.js.map +1 -0
  109. package/dist/services/main.d.ts +19 -0
  110. package/dist/services/main.d.ts.map +1 -0
  111. package/dist/services/main.js +32 -0
  112. package/dist/services/main.js.map +1 -0
  113. package/dist/standalone.d.ts +37 -0
  114. package/dist/standalone.d.ts.map +1 -0
  115. package/dist/standalone.js +92 -0
  116. package/dist/standalone.js.map +1 -0
  117. package/dist/strategies/ApiKeyStrategy.d.ts +28 -0
  118. package/dist/strategies/ApiKeyStrategy.d.ts.map +1 -0
  119. package/dist/strategies/ApiKeyStrategy.js +36 -0
  120. package/dist/strategies/ApiKeyStrategy.js.map +1 -0
  121. package/dist/strategies/JwtStrategy.d.ts +51 -0
  122. package/dist/strategies/JwtStrategy.d.ts.map +1 -0
  123. package/dist/strategies/JwtStrategy.js +150 -0
  124. package/dist/strategies/JwtStrategy.js.map +1 -0
  125. package/dist/strategies/SessionStrategy.d.ts +58 -0
  126. package/dist/strategies/SessionStrategy.d.ts.map +1 -0
  127. package/dist/strategies/SessionStrategy.js +70 -0
  128. package/dist/strategies/SessionStrategy.js.map +1 -0
  129. package/index.darwin-arm64.node +0 -0
  130. package/index.darwin-x64.node +0 -0
  131. package/index.linux-arm64-gnu.node +0 -0
  132. package/index.linux-x64-gnu.node +0 -0
  133. package/index.win32-x64-msvc.node +0 -0
  134. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenBlacklist.js","sourceRoot":"","sources":["../src/TokenBlacklist.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,2CAA2C;AAC3C,MAAM,OAAO,qBAAqB;IACzB,OAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEjD,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,SAAiB;QACvC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACpB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC1C,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,OAAO,KAAK,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,GAAG,GAAG,GAAG;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzC,CAAC;IACF,CAAC;CACD;AAED,MAAM,OAAO,cAAc;IACN;IAApB,YAAoB,MAAuB;QAAvB,WAAM,GAAN,MAAM,CAAiB;IAAG,CAAC;IAE/C,uCAAuC;IACvC,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,SAAiB;QAC1C,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,SAAS,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,8BAA8B;IAC9B,KAAK,CAAC,OAAO;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IAC9B,CAAC;CACD"}
@@ -0,0 +1,19 @@
1
+ interface WardenContainer {
2
+ singleton(token: unknown, factory: () => unknown): void;
3
+ resolve(token: unknown): unknown;
4
+ }
5
+ interface WardenConfigStore {
6
+ get<T = unknown>(key: string): T | undefined;
7
+ }
8
+ export interface WardenAppContext {
9
+ container: WardenContainer;
10
+ config: WardenConfigStore;
11
+ }
12
+ export default class WardenProvider {
13
+ protected app: WardenAppContext;
14
+ constructor(app: WardenAppContext);
15
+ register(): void;
16
+ boot(): Promise<void>;
17
+ }
18
+ export {};
19
+ //# sourceMappingURL=WardenProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WardenProvider.d.ts","sourceRoot":"","sources":["../src/WardenProvider.ts"],"names":[],"mappings":"AAQA,UAAU,eAAe;IACxB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACjC;AAED,UAAU,iBAAiB;IAC1B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,eAAe,CAAC;IAC3B,MAAM,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,CAAC,OAAO,OAAO,cAAc;IACtB,SAAS,CAAC,GAAG,EAAE,gBAAgB;gBAArB,GAAG,EAAE,gBAAgB;IAE3C,QAAQ;IAuDF,IAAI;CAGV"}
@@ -0,0 +1,61 @@
1
+ import { AuthManager } from "./AuthManager.js";
2
+ import { WardenError } from "./errors.js";
3
+ import { MemoryRightsStore } from "./rights/MemoryRightsStore.js";
4
+ import { RightsResolver } from "./rights/RightsResolver.js";
5
+ import { setAuth } from "./services/main.js";
6
+ import { JwtStrategy } from "./strategies/JwtStrategy.js";
7
+ export default class WardenProvider {
8
+ app;
9
+ constructor(app) {
10
+ this.app = app;
11
+ }
12
+ register() {
13
+ // Register JwtStrategy first so it's available before AuthManager resolves.
14
+ // The previous version nested the JwtStrategy registration inside the
15
+ // AuthManager factory — that was order-dependent and fragile.
16
+ const config = this.app.config.get("auth");
17
+ // Fail-fast at register-time so the operator gets a clear actionable
18
+ // error during boot instead of an opaque runtime crash on the first
19
+ // protected request. Previously, missing `config.auth` produced an
20
+ // AuthManager with `strategies: {}` and `defaultStrategy: 'jwt'`,
21
+ // passing the (then-permissive) constructor and erroring deep in the
22
+ // middleware loop.
23
+ if (!config?.jwt) {
24
+ throw new WardenError("WARDEN_NO_AUTH_CONFIG", `@c9up/warden: no authentication strategies configured. Set config.warden.auth.jwt (or another strategy) in your reamrc.ts before registering WardenProvider.`);
25
+ }
26
+ const jwt = new JwtStrategy(config.jwt);
27
+ this.app.container.singleton(JwtStrategy, () => jwt);
28
+ // Rights layer (Epic 56): one resolver singleton backs BOTH the coarse
29
+ // RBAC helpers (injected into AuthManager below) and — once 56.6 lands —
30
+ // the Bouncer construction, so a coarse question and a policy question
31
+ // resolve through the SAME instance (single unification point, AC-E3).
32
+ // The store defaults to an in-memory driver and is exposed (by class)
33
+ // so an app can seed roles/grants at boot, or supply its own via
34
+ // `config.auth.rights.store` (AD5).
35
+ const rightsStore = config.rights?.store ?? new MemoryRightsStore();
36
+ const rightsResolver = new RightsResolver(rightsStore);
37
+ this.app.container.singleton(RightsResolver, () => rightsResolver);
38
+ if (rightsStore instanceof MemoryRightsStore) {
39
+ this.app.container.singleton(MemoryRightsStore, () => rightsStore);
40
+ }
41
+ this.app.container.singleton(AuthManager, () => {
42
+ const strategies = { jwt };
43
+ return new AuthManager({
44
+ defaultStrategy: config.defaultStrategy ?? "jwt",
45
+ strategies,
46
+ rights: rightsResolver,
47
+ });
48
+ });
49
+ // String alias so consumers that can't import the AuthManager class
50
+ // (e.g. @c9up/station, which stays agnostic of warden) can resolve
51
+ // it by name. Mirrors the convention other providers follow
52
+ // (events → "bus", rosetta → "i18n"). Without this, Station's
53
+ // `container.resolve("auth")` threw and its admin auth gate
54
+ // silently fell back to open-mode.
55
+ this.app.container.singleton("auth", () => this.app.container.resolve(AuthManager));
56
+ }
57
+ async boot() {
58
+ setAuth(this.app.container.resolve(AuthManager));
59
+ }
60
+ }
61
+ //# sourceMappingURL=WardenProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WardenProvider.js","sourceRoot":"","sources":["../src/WardenProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAgB1D,MAAM,CAAC,OAAO,OAAO,cAAc;IACZ;IAAtB,YAAsB,GAAqB;QAArB,QAAG,GAAH,GAAG,CAAkB;IAAG,CAAC;IAE/C,QAAQ;QACP,4EAA4E;QAC5E,sEAAsE;QACtE,8DAA8D;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAe,MAAM,CAAC,CAAC;QAEzD,qEAAqE;QACrE,oEAAoE;QACpE,mEAAmE;QACnE,kEAAkE;QAClE,qEAAqE;QACrE,mBAAmB;QACnB,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;YAClB,MAAM,IAAI,WAAW,CACpB,uBAAuB,EACvB,8JAA8J,CAC9J,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;QAErD,uEAAuE;QACvE,yEAAyE;QACzE,uEAAuE;QACvE,uEAAuE;QACvE,sEAAsE;QACtE,iEAAiE;QACjE,oCAAoC;QACpC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,IAAI,iBAAiB,EAAE,CAAC;QACpE,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,WAAW,CAAC,CAAC;QACvD,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,CAAC;QACnE,IAAI,WAAW,YAAY,iBAAiB,EAAE,CAAC;YAC9C,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE;YAC9C,MAAM,UAAU,GAAgC,EAAE,GAAG,EAAE,CAAC;YACxD,OAAO,IAAI,WAAW,CAAC;gBACtB,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,KAAK;gBAChD,UAAU;gBACV,MAAM,EAAE,cAAc;aACtB,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,oEAAoE;QACpE,mEAAmE;QACnE,4DAA4D;QAC5D,8DAA8D;QAC9D,4DAA4D;QAC5D,mCAAmC;QACnC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,CACzC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACT,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAgB,CAAC,CAAC;IACjE,CAAC;CACD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * AuthorizationResponse — the value type every Bouncer check resolves to.
3
+ *
4
+ * Layer 2 (EVALUATION) of Warden's unified authorization (Epic 56). Faithful
5
+ * to AdonisJS Bouncer's `AuthorizationResponse`: instances are produced only by
6
+ * the `allow()` / `deny()` static constructors (the constructor is private), a
7
+ * denial defaults to HTTP 403, and a `translation` field is carried for shape
8
+ * parity with Adonis's i18n hook (always `undefined` in 56.2 — D6).
9
+ */
10
+ export declare class AuthorizationResponse {
11
+ readonly authorized: boolean;
12
+ readonly message?: string;
13
+ readonly status?: number;
14
+ /** Parity placeholder for an i18n binding (always undefined in 56.2 — D6). */
15
+ readonly translation?: {
16
+ identifier: string;
17
+ data?: Record<string, unknown>;
18
+ };
19
+ private constructor();
20
+ /** Authorized response (no status). */
21
+ static allow(): AuthorizationResponse;
22
+ /** Denied response; `status` defaults to 403 (D6). */
23
+ static deny(message?: string, status?: number): AuthorizationResponse;
24
+ }
25
+ //# sourceMappingURL=AuthorizationResponse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorizationResponse.d.ts","sourceRoot":"","sources":["../../src/bouncer/AuthorizationResponse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IAE9E,OAAO;IAYP,uCAAuC;IACvC,MAAM,CAAC,KAAK,IAAI,qBAAqB;IAIrC,sDAAsD;IACtD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,qBAAqB;CAGlE"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * AuthorizationResponse — the value type every Bouncer check resolves to.
3
+ *
4
+ * Layer 2 (EVALUATION) of Warden's unified authorization (Epic 56). Faithful
5
+ * to AdonisJS Bouncer's `AuthorizationResponse`: instances are produced only by
6
+ * the `allow()` / `deny()` static constructors (the constructor is private), a
7
+ * denial defaults to HTTP 403, and a `translation` field is carried for shape
8
+ * parity with Adonis's i18n hook (always `undefined` in 56.2 — D6).
9
+ */
10
+ export class AuthorizationResponse {
11
+ authorized;
12
+ message;
13
+ status;
14
+ /** Parity placeholder for an i18n binding (always undefined in 56.2 — D6). */
15
+ translation;
16
+ constructor(authorized, message, status, translation) {
17
+ this.authorized = authorized;
18
+ this.message = message;
19
+ this.status = status;
20
+ this.translation = translation;
21
+ }
22
+ /** Authorized response (no status). */
23
+ static allow() {
24
+ return new AuthorizationResponse(true);
25
+ }
26
+ /** Denied response; `status` defaults to 403 (D6). */
27
+ static deny(message, status = 403) {
28
+ return new AuthorizationResponse(false, message, status);
29
+ }
30
+ }
31
+ //# sourceMappingURL=AuthorizationResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorizationResponse.js","sourceRoot":"","sources":["../../src/bouncer/AuthorizationResponse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,OAAO,qBAAqB;IACxB,UAAU,CAAU;IACpB,OAAO,CAAU;IACjB,MAAM,CAAU;IACzB,8EAA8E;IACrE,WAAW,CAA0D;IAE9E,YACC,UAAmB,EACnB,OAAgB,EAChB,MAAe,EACf,WAAoE;QAEpE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IAChC,CAAC;IAED,uCAAuC;IACvC,MAAM,CAAC,KAAK;QACX,OAAO,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,sDAAsD;IACtD,MAAM,CAAC,IAAI,CAAC,OAAgB,EAAE,MAAM,GAAG,GAAG;QACzC,OAAO,IAAI,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;CACD"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * BasePolicy — extend it to group authorization checks for a resource. Action
3
+ * methods are positional `(user, resource?) => AuthorizerResponse` (D3); decorate
4
+ * a method with `@allowGuest()` / `@action({ allowGuest: true })` to let a guest
5
+ * (null user) reach it. The optional `before` / `after` hooks run around every
6
+ * action in the Adonis evaluation order (D5 — see PolicyAuthorizer).
7
+ */
8
+ import type { UserPayload } from "../AuthManager.js";
9
+ import type { EffectivePermissions, Scope } from "../rights/types.js";
10
+ import type { AuthorizationResponse } from "./AuthorizationResponse.js";
11
+ import type { HookResponse } from "./types.js";
12
+ export declare abstract class BasePolicy {
13
+ /**
14
+ * Runs before the action. A non-`undefined` return short-circuits the action
15
+ * (a `boolean`/`AuthorizationResponse` becomes the result) — this is how a
16
+ * moderator bypass or an early `deny('not found', 404)` works, including for
17
+ * a guest. `undefined`/`void` falls through to the action.
18
+ */
19
+ before?(user: UserPayload | null, action: string, ...args: unknown[]): HookResponse;
20
+ /**
21
+ * Runs after the action (or after a `before` short-circuit), receiving the
22
+ * resolved response. A non-`undefined` return overrides it; `undefined`
23
+ * keeps it.
24
+ */
25
+ after?(user: UserPayload | null, action: string, result: AuthorizationResponse): HookResponse;
26
+ /**
27
+ * The Bouncer's active scope for the in-flight check (56.3). Defaults to
28
+ * `"global"` when the policy is used without a Bouncer context.
29
+ */
30
+ protected get scope(): Scope;
31
+ /**
32
+ * The resolved `EffectivePermissions` for the Bouncer's `(user, scope)` (56.3):
33
+ * role-derived ∪ ACL grants with global→tenant inheritance (per 56.1). A guest,
34
+ * a no-resolver Bouncer, or a standalone policy ⇒ empty permissions.
35
+ */
36
+ protected get permissions(): EffectivePermissions;
37
+ /**
38
+ * Tenant-isolation helper (D5 — enforceable, not automatic). `true` under the
39
+ * `global` scope (single-tenant — no boundary); under `{ tenant: T }` it is
40
+ * `resource.tenantId === T`. A policy enforces explicitly, e.g.
41
+ * `if (!this.sameTenant(post)) return false`.
42
+ */
43
+ protected sameTenant(resource: {
44
+ tenantId?: string | null;
45
+ }): boolean;
46
+ }
47
+ //# sourceMappingURL=BasePolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasePolicy.d.ts","sourceRoot":"","sources":["../../src/bouncer/BasePolicy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,8BAAsB,UAAU;IAC/B;;;;;OAKG;IACH,MAAM,CAAC,CACN,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,GAChB,YAAY;IAEf;;;;OAIG;IACH,KAAK,CAAC,CACL,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,GAC3B,YAAY;IAEf;;;OAGG;IACH,SAAS,KAAK,KAAK,IAAI,KAAK,CAE3B;IAED;;;;OAIG;IACH,SAAS,KAAK,WAAW,IAAI,oBAAoB,CAEhD;IAED;;;;;OAKG;IACH,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO;CAIrE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * BasePolicy — extend it to group authorization checks for a resource. Action
3
+ * methods are positional `(user, resource?) => AuthorizerResponse` (D3); decorate
4
+ * a method with `@allowGuest()` / `@action({ allowGuest: true })` to let a guest
5
+ * (null user) reach it. The optional `before` / `after` hooks run around every
6
+ * action in the Adonis evaluation order (D5 — see PolicyAuthorizer).
7
+ */
8
+ import { emptyPermissions, getPolicyContext } from "./policyContext.js";
9
+ export class BasePolicy {
10
+ /**
11
+ * The Bouncer's active scope for the in-flight check (56.3). Defaults to
12
+ * `"global"` when the policy is used without a Bouncer context.
13
+ */
14
+ get scope() {
15
+ return getPolicyContext(this)?.scope ?? "global";
16
+ }
17
+ /**
18
+ * The resolved `EffectivePermissions` for the Bouncer's `(user, scope)` (56.3):
19
+ * role-derived ∪ ACL grants with global→tenant inheritance (per 56.1). A guest,
20
+ * a no-resolver Bouncer, or a standalone policy ⇒ empty permissions.
21
+ */
22
+ get permissions() {
23
+ return getPolicyContext(this)?.permissions ?? emptyPermissions("global");
24
+ }
25
+ /**
26
+ * Tenant-isolation helper (D5 — enforceable, not automatic). `true` under the
27
+ * `global` scope (single-tenant — no boundary); under `{ tenant: T }` it is
28
+ * `resource.tenantId === T`. A policy enforces explicitly, e.g.
29
+ * `if (!this.sameTenant(post)) return false`.
30
+ */
31
+ sameTenant(resource) {
32
+ const scope = this.scope;
33
+ return scope === "global" ? true : resource.tenantId === scope.tenant;
34
+ }
35
+ }
36
+ //# sourceMappingURL=BasePolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasePolicy.js","sourceRoot":"","sources":["../../src/bouncer/BasePolicy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGxE,MAAM,OAAgB,UAAU;IAwB/B;;;OAGG;IACH,IAAc,KAAK;QAClB,OAAO,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,QAAQ,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACH,IAAc,WAAW;QACxB,OAAO,gBAAgB,CAAC,IAAI,CAAC,EAAE,WAAW,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC1E,CAAC;IAED;;;;;OAKG;IACO,UAAU,CAAC,QAAsC;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,KAAK,KAAK,CAAC,MAAM,CAAC;IACvE,CAAC;CACD"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Bouncer — Layer 2 (EVALUATION) of Warden's unified authorization (Epic 56).
3
+ *
4
+ * A Bouncer-faithful evaluation core (verified context7 `/adonisjs/bouncer`,
5
+ * 2026-06-01): standalone abilities via `Bouncer.ability`, class-based policies
6
+ * via `with(Policy)`, the four verbs `allows`/`denies`/`authorize`/`execute`,
7
+ * and guest-denied-by-default. The user is `UserPayload | null` (guest = null,
8
+ * D3); `authorize` throws `WARDEN_AUTHORIZATION_FAILURE` carrying `status: 403`
9
+ * (D2). 56.2 ships PURE mechanics — it does NOT consult the Layer-1
10
+ * `RightsResolver` (D4); abilities/policy methods receive `(user, ...args)` and
11
+ * the developer writes the predicate, exactly as Adonis does.
12
+ */
13
+ import type { UserPayload } from "../AuthManager.js";
14
+ import type { Scope } from "../rights/types.js";
15
+ import { AuthorizationResponse } from "./AuthorizationResponse.js";
16
+ import type { BasePolicy } from "./BasePolicy.js";
17
+ import { PolicyAuthorizer } from "./PolicyAuthorizer.js";
18
+ import type { Ability, AbilityOptions, AuthorizerResponse, BouncerContext } from "./types.js";
19
+ export declare class Bouncer {
20
+ #private;
21
+ constructor(user: UserPayload | null, abilities?: Record<string, Ability<never[]>>, policies?: Record<string, new () => BasePolicy>, context?: BouncerContext);
22
+ /** The active resolution scope (default `"global"`). */
23
+ get scope(): Scope;
24
+ /**
25
+ * Define a standalone ability. Guest (null user) denied by default; pass
26
+ * `{ allowGuest: true }` to let the callback run for a guest (D5 step 2).
27
+ */
28
+ static ability<Args extends unknown[]>(callback: (user: UserPayload, ...args: Args) => AuthorizerResponse): Ability<Args>;
29
+ static ability<Args extends unknown[]>(options: AbilityOptions, callback: (user: UserPayload | null, ...args: Args) => AuthorizerResponse): Ability<Args>;
30
+ /** Convenience — equivalent to `AuthorizationResponse.deny` (Adonis `bouncer.deny`). */
31
+ deny(message?: string, status?: number): AuthorizationResponse;
32
+ /** Open a policy for checks (D8 — fresh `new PolicyClass()` per check). */
33
+ with(policy: (new () => BasePolicy) | string): PolicyAuthorizer;
34
+ /** Run an ability check and resolve to the full response. */
35
+ execute<Args extends unknown[]>(ability: Ability<Args>, ...args: Args): Promise<AuthorizationResponse>;
36
+ execute(ability: string, ...args: unknown[]): Promise<AuthorizationResponse>;
37
+ /** True iff the ability is authorized. Never throws on denial. */
38
+ allows<Args extends unknown[]>(ability: Ability<Args>, ...args: Args): Promise<boolean>;
39
+ allows(ability: string, ...args: unknown[]): Promise<boolean>;
40
+ /** Boolean negation of {@link allows}. Never throws on denial. */
41
+ denies<Args extends unknown[]>(ability: Ability<Args>, ...args: Args): Promise<boolean>;
42
+ denies(ability: string, ...args: unknown[]): Promise<boolean>;
43
+ /** Resolves on allow; throws `WARDEN_AUTHORIZATION_FAILURE` on deny (D2). */
44
+ authorize<Args extends unknown[]>(ability: Ability<Args>, ...args: Args): Promise<void>;
45
+ authorize(ability: string, ...args: unknown[]): Promise<void>;
46
+ }
47
+ //# sourceMappingURL=Bouncer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Bouncer.d.ts","sourceRoot":"","sources":["../../src/bouncer/Bouncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,KAAK,EAAwB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EACX,OAAO,EACP,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,MAAM,YAAY,CAAC;AAEpB,qBAAa,OAAO;;gBAUlB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,UAAU,CAAC,EAC/C,OAAO,CAAC,EAAE,cAAc;IASzB,wDAAwD;IACxD,IAAI,KAAK,IAAI,KAAK,CAEjB;IAkBD;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,SAAS,OAAO,EAAE,EACpC,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,kBAAkB,GAChE,OAAO,CAAC,IAAI,CAAC;IAChB,MAAM,CAAC,OAAO,CAAC,IAAI,SAAS,OAAO,EAAE,EACpC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,kBAAkB,GACvE,OAAO,CAAC,IAAI,CAAC;IAmChB,wFAAwF;IACxF,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB;IAI9D,2EAA2E;IAC3E,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,UAAU,CAAC,GAAG,MAAM,GAAG,gBAAgB;IAY/D,6DAA6D;IAC7D,OAAO,CAAC,IAAI,SAAS,OAAO,EAAE,EAC7B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EACtB,GAAG,IAAI,EAAE,IAAI,GACX,OAAO,CAAC,qBAAqB,CAAC;IACjC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQ5E,kEAAkE;IAClE,MAAM,CAAC,IAAI,SAAS,OAAO,EAAE,EAC5B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EACtB,GAAG,IAAI,EAAE,IAAI,GACX,OAAO,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ7D,kEAAkE;IAClE,MAAM,CAAC,IAAI,SAAS,OAAO,EAAE,EAC5B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EACtB,GAAG,IAAI,EAAE,IAAI,GACX,OAAO,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ7D,6EAA6E;IAC7E,SAAS,CAAC,IAAI,SAAS,OAAO,EAAE,EAC/B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EACtB,GAAG,IAAI,EAAE,IAAI,GACX,OAAO,CAAC,IAAI,CAAC;IAChB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAwD7D"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Bouncer — Layer 2 (EVALUATION) of Warden's unified authorization (Epic 56).
3
+ *
4
+ * A Bouncer-faithful evaluation core (verified context7 `/adonisjs/bouncer`,
5
+ * 2026-06-01): standalone abilities via `Bouncer.ability`, class-based policies
6
+ * via `with(Policy)`, the four verbs `allows`/`denies`/`authorize`/`execute`,
7
+ * and guest-denied-by-default. The user is `UserPayload | null` (guest = null,
8
+ * D3); `authorize` throws `WARDEN_AUTHORIZATION_FAILURE` carrying `status: 403`
9
+ * (D2). 56.2 ships PURE mechanics — it does NOT consult the Layer-1
10
+ * `RightsResolver` (D4); abilities/policy methods receive `(user, ...args)` and
11
+ * the developer writes the predicate, exactly as Adonis does.
12
+ */
13
+ import { WardenError } from "../errors.js";
14
+ import { AuthorizationResponse } from "./AuthorizationResponse.js";
15
+ import { evaluate, isAction, throwAuthorizationFailure } from "./evaluate.js";
16
+ import { PolicyAuthorizer } from "./PolicyAuthorizer.js";
17
+ import { emptyPermissions } from "./policyContext.js";
18
+ export class Bouncer {
19
+ #user;
20
+ #abilities;
21
+ #policies;
22
+ #scope;
23
+ #resolver;
24
+ /** Memoized resolution — a Bouncer is fixed per `(user, scope)`, so resolve once (D3). */
25
+ #resolved;
26
+ constructor(user, abilities, policies, context) {
27
+ this.#user = user;
28
+ this.#abilities = abilities ?? {};
29
+ this.#policies = policies ?? {};
30
+ this.#scope = context?.scope ?? "global";
31
+ this.#resolver = context?.resolver;
32
+ }
33
+ /** The active resolution scope (default `"global"`). */
34
+ get scope() {
35
+ return this.#scope;
36
+ }
37
+ /**
38
+ * Resolve this Bouncer's `(user, scope)` to `EffectivePermissions`, memoized
39
+ * once per instance (D3). Guest (`user === null`) or no resolver ⇒ empty
40
+ * permissions — `resolve()` is never called for a guest (D9). 56.6 relocates
41
+ * this cache to the request context without changing the policy-facing API.
42
+ */
43
+ #resolvePermissions() {
44
+ if (this.#resolved === undefined) {
45
+ this.#resolved =
46
+ this.#resolver !== undefined && this.#user !== null
47
+ ? this.#resolver.resolve(this.#user, this.#scope)
48
+ : Promise.resolve(emptyPermissions(this.#scope));
49
+ }
50
+ return this.#resolved;
51
+ }
52
+ static ability(optionsOrCallback, maybeCallback) {
53
+ let allowGuest = false;
54
+ let raw;
55
+ if (typeof optionsOrCallback === "function") {
56
+ raw = optionsOrCallback;
57
+ }
58
+ else {
59
+ allowGuest = optionsOrCallback.allowGuest ?? false;
60
+ raw = maybeCallback;
61
+ }
62
+ // The typed overloads above carry the real callback signature for the
63
+ // caller; the impl param is the universal-function supertype so both
64
+ // overloads are accepted. `isAction` reinterprets it as the invokable
65
+ // `Action` shape (a type guard, not a cast — a function's parameter types
66
+ // are not observable at runtime).
67
+ if (!isAction(raw)) {
68
+ throw new WardenError("INVALID_ABILITY", "Bouncer.ability requires a callback alongside the options object.", { hint: "Bouncer.ability({ allowGuest: true }, (user) => ...)" });
69
+ }
70
+ const callback = raw;
71
+ const execute = (user, ...args) => callback(user, ...args);
72
+ return { allowGuest, execute };
73
+ }
74
+ /** Convenience — equivalent to `AuthorizationResponse.deny` (Adonis `bouncer.deny`). */
75
+ deny(message, status) {
76
+ return AuthorizationResponse.deny(message, status);
77
+ }
78
+ /** Open a policy for checks (D8 — fresh `new PolicyClass()` per check). */
79
+ with(policy) {
80
+ const factory = typeof policy === "string"
81
+ ? this.#resolvePolicyClass(policy)
82
+ : () => new policy();
83
+ // The PolicyAuthorizer inherits the Bouncer's scope + the shared memoized
84
+ // resolve so every policy check sees the active `(user, scope)` (AC1/AC3).
85
+ return new PolicyAuthorizer(this.#user, factory, this.#scope, () => this.#resolvePermissions());
86
+ }
87
+ execute(ability, ...args) {
88
+ return this.#evaluateAbility(ability, args);
89
+ }
90
+ async allows(ability, ...args) {
91
+ return (await this.#evaluateAbility(ability, args)).authorized;
92
+ }
93
+ async denies(ability, ...args) {
94
+ return !(await this.#evaluateAbility(ability, args)).authorized;
95
+ }
96
+ async authorize(ability, ...args) {
97
+ const response = await this.#evaluateAbility(ability, args);
98
+ if (!response.authorized) {
99
+ throwAuthorizationFailure(response);
100
+ }
101
+ }
102
+ async #evaluateAbility(ability, args) {
103
+ const resolved = typeof ability === "string" ? this.#resolveAbility(ability) : ability;
104
+ return evaluate({
105
+ user: this.#user,
106
+ action: typeof ability === "string" ? ability : "(ability)",
107
+ allowGuest: resolved.allowGuest,
108
+ run: (user) => resolved.execute(user, ...args),
109
+ args,
110
+ });
111
+ }
112
+ #resolveAbility(name) {
113
+ const found = this.#abilities[name];
114
+ if (found === undefined) {
115
+ throw new WardenError("UNKNOWN_ABILITY", `No ability "${name}" is registered on this Bouncer.`, { hint: "Register it via new Bouncer(user, { [name]: ability })." });
116
+ }
117
+ return found;
118
+ }
119
+ #resolvePolicyClass(name) {
120
+ // Lazy: the lookup runs when a verb constructs the policy, so an unknown
121
+ // name surfaces as a promise rejection (like every other verb error),
122
+ // not a synchronous throw at `with()` time.
123
+ return () => {
124
+ const ctor = this.#policies[name];
125
+ if (ctor === undefined) {
126
+ throw new WardenError("UNKNOWN_POLICY", `No policy "${name}" is registered on this Bouncer.`, {
127
+ hint: "Register it via new Bouncer(user, abilities, { [name]: Policy }).",
128
+ });
129
+ }
130
+ return new ctor();
131
+ };
132
+ }
133
+ }
134
+ //# sourceMappingURL=Bouncer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Bouncer.js","sourceRoot":"","sources":["../../src/bouncer/Bouncer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAQtD,MAAM,OAAO,OAAO;IACV,KAAK,CAAqB;IAC1B,UAAU,CAAmC;IAC7C,SAAS,CAAuC;IAChD,MAAM,CAAQ;IACd,SAAS,CAA6B;IAC/C,0FAA0F;IAC1F,SAAS,CAA4C;IAErD,YACC,IAAwB,EACxB,SAA4C,EAC5C,QAA+C,EAC/C,OAAwB;QAExB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,UAAU,GAAG,SAAS,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,QAAQ,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,KAAK,IAAI,QAAQ,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,QAAQ,CAAC;IACpC,CAAC;IAED,wDAAwD;IACxD,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACH,mBAAmB;QAClB,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC,SAAS;gBACb,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;oBAClD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;oBACjD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAaD,MAAM,CAAC,OAAO,CACb,iBAE6C,EAC7C,aAAwD;QAExD,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,GAAY,CAAC;QACjB,IAAI,OAAO,iBAAiB,KAAK,UAAU,EAAE,CAAC;YAC7C,GAAG,GAAG,iBAAiB,CAAC;QACzB,CAAC;aAAM,CAAC;YACP,UAAU,GAAG,iBAAiB,CAAC,UAAU,IAAI,KAAK,CAAC;YACnD,GAAG,GAAG,aAAa,CAAC;QACrB,CAAC;QACD,sEAAsE;QACtE,qEAAqE;QACrE,sEAAsE;QACtE,0EAA0E;QAC1E,kCAAkC;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,WAAW,CACpB,iBAAiB,EACjB,mEAAmE,EACnE,EAAE,IAAI,EAAE,sDAAsD,EAAE,CAChE,CAAC;QACH,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,CAAC;QACrB,MAAM,OAAO,GAAG,CACf,IAAwB,EACxB,GAAG,IAAe,EACG,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;QACjD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IAChC,CAAC;IAED,wFAAwF;IACxF,IAAI,CAAC,OAAgB,EAAE,MAAe;QACrC,OAAO,qBAAqB,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpD,CAAC;IAED,2EAA2E;IAC3E,IAAI,CAAC,MAAuC;QAC3C,MAAM,OAAO,GACZ,OAAO,MAAM,KAAK,QAAQ;YACzB,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC;YAClC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,0EAA0E;QAC1E,2EAA2E;QAC3E,OAAO,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAClE,IAAI,CAAC,mBAAmB,EAAE,CAC1B,CAAC;IACH,CAAC;IAQD,OAAO,CACN,OAAkC,EAClC,GAAG,IAAe;QAElB,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;IAQD,KAAK,CAAC,MAAM,CACX,OAAkC,EAClC,GAAG,IAAe;QAElB,OAAO,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;IAChE,CAAC;IAQD,KAAK,CAAC,MAAM,CACX,OAAkC,EAClC,GAAG,IAAe;QAElB,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC;IACjE,CAAC;IAQD,KAAK,CAAC,SAAS,CACd,OAAkC,EAClC,GAAG,IAAe;QAElB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC1B,yBAAyB,CAAC,QAAQ,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;IAED,KAAK,CAAC,gBAAgB,CACrB,OAAkC,EAClC,IAAe;QAEf,MAAM,QAAQ,GACb,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACvE,OAAO,QAAQ,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,MAAM,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW;YAC3D,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC;YAC9C,IAAI;SACJ,CAAC,CAAC;IACJ,CAAC;IAED,eAAe,CAAC,IAAY;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,WAAW,CACpB,iBAAiB,EACjB,eAAe,IAAI,kCAAkC,EACrD,EAAE,IAAI,EAAE,yDAAyD,EAAE,CACnE,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,mBAAmB,CAAC,IAAY;QAC/B,yEAAyE;QACzE,sEAAsE;QACtE,4CAA4C;QAC5C,OAAO,GAAG,EAAE;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,WAAW,CACpB,gBAAgB,EAChB,cAAc,IAAI,kCAAkC,EACpD;oBACC,IAAI,EAAE,mEAAmE;iBACzE,CACD,CAAC;YACH,CAAC;YACD,OAAO,IAAI,IAAI,EAAE,CAAC;QACnB,CAAC,CAAC;IACH,CAAC;CACD"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * PolicyAuthorizer — the object returned by `bouncer.with(Policy)`. Exposes the
3
+ * same four verbs as the Bouncer, dispatched to a named action method on a
4
+ * freshly-constructed policy instance (D8 — `new PolicyClass()` per check). The
5
+ * `before`/`after` hooks and the per-method `@allowGuest` rule run through the
6
+ * shared D5 pipeline.
7
+ */
8
+ import type { UserPayload } from "../AuthManager.js";
9
+ import type { EffectivePermissions, Scope } from "../rights/types.js";
10
+ import type { AuthorizationResponse } from "./AuthorizationResponse.js";
11
+ import { BasePolicy } from "./BasePolicy.js";
12
+ export declare class PolicyAuthorizer {
13
+ #private;
14
+ constructor(user: UserPayload | null, factory: () => BasePolicy, scope?: Scope, resolvePermissions?: () => Promise<EffectivePermissions>);
15
+ /** Run a check and resolve to the full response (D8 — fresh policy per check). */
16
+ execute(action: string, ...args: unknown[]): Promise<AuthorizationResponse>;
17
+ /** True iff the action is authorized. Never throws on denial. */
18
+ allows(action: string, ...args: unknown[]): Promise<boolean>;
19
+ /** Boolean negation of {@link allows}. Never throws on denial. */
20
+ denies(action: string, ...args: unknown[]): Promise<boolean>;
21
+ /** Resolves on allow; throws `WARDEN_AUTHORIZATION_FAILURE` on deny (D2). */
22
+ authorize(action: string, ...args: unknown[]): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=PolicyAuthorizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyAuthorizer.d.ts","sourceRoot":"","sources":["../../src/bouncer/PolicyAuthorizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAqD7C,qBAAa,gBAAgB;;gBAO3B,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,UAAU,EACzB,KAAK,GAAE,KAAgB,EACvB,kBAAkB,GAAE,MAAM,OAAO,CAAC,oBAAoB,CACb;IAQ1C,kFAAkF;IAC5E,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,GAChB,OAAO,CAAC,qBAAqB,CAAC;IAmBjC,iEAAiE;IAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,kEAAkE;IAC5D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlE,6EAA6E;IACvE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAMlE"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * PolicyAuthorizer — the object returned by `bouncer.with(Policy)`. Exposes the
3
+ * same four verbs as the Bouncer, dispatched to a named action method on a
4
+ * freshly-constructed policy instance (D8 — `new PolicyClass()` per check). The
5
+ * `before`/`after` hooks and the per-method `@allowGuest` rule run through the
6
+ * shared D5 pipeline.
7
+ */
8
+ import { WardenError } from "../errors.js";
9
+ import { BasePolicy } from "./BasePolicy.js";
10
+ import { getActionMetadata } from "./decorators.js";
11
+ import { evaluate, isAction, throwAuthorizationFailure, } from "./evaluate.js";
12
+ import { emptyPermissions, setPolicyContext } from "./policyContext.js";
13
+ /**
14
+ * Resolve a named action method declared anywhere on the policy's own subclass
15
+ * chain (so an action inherited from an intermediate policy base class still
16
+ * dispatches). Rejects `constructor`, the `before`/`after` hooks, and any
17
+ * `BasePolicy`/`Object.prototype` member so a verb call can never dispatch to a
18
+ * non-action method — a guard the adversarial review specifically probes.
19
+ */
20
+ function resolveActionMethod(policy, action) {
21
+ // Reject the hooks + constructor by name, then accept an action declared
22
+ // anywhere on the policy's own subclass chain — the immediate prototype up to
23
+ // (but not including) BasePolicy.prototype / Object.prototype — so a method
24
+ // inherited from an intermediate policy base class (`class A extends B`) still
25
+ // dispatches, while BasePolicy's own members (scope/permissions getters) and
26
+ // Object.prototype members stay unreachable.
27
+ const isHookOrCtor = action === "constructor" || action === "before" || action === "after";
28
+ let declaredHere = false;
29
+ for (let proto = Object.getPrototypeOf(policy); proto !== null &&
30
+ proto !== BasePolicy.prototype &&
31
+ proto !== Object.prototype; proto = Object.getPrototypeOf(proto)) {
32
+ if (Object.hasOwn(proto, action)) {
33
+ declaredHere = true;
34
+ break;
35
+ }
36
+ }
37
+ const candidate = Reflect.get(policy, action);
38
+ if (isHookOrCtor) {
39
+ declaredHere = false;
40
+ }
41
+ if (!declaredHere || !isAction(candidate)) {
42
+ throw new WardenError("UNKNOWN_POLICY_ACTION", `Policy "${policy.constructor.name}" has no action "${action}"`, { hint: "Declare the action as a method on the policy class." });
43
+ }
44
+ return candidate.bind(policy);
45
+ }
46
+ export class PolicyAuthorizer {
47
+ #user;
48
+ #factory;
49
+ #scope;
50
+ #resolvePermissions;
51
+ constructor(user, factory, scope = "global", resolvePermissions = () => Promise.resolve(emptyPermissions(scope))) {
52
+ this.#user = user;
53
+ this.#factory = factory;
54
+ this.#scope = scope;
55
+ this.#resolvePermissions = resolvePermissions;
56
+ }
57
+ /** Run a check and resolve to the full response (D8 — fresh policy per check). */
58
+ async execute(action, ...args) {
59
+ const policy = this.#factory();
60
+ // Attach the active scope + resolved permissions BEFORE dispatch so the
61
+ // before/method/after pipeline all read `this.scope` / `this.permissions`.
62
+ const permissions = await this.#resolvePermissions();
63
+ setPolicyContext(policy, { scope: this.#scope, permissions });
64
+ const method = resolveActionMethod(policy, action);
65
+ const options = getActionMetadata(policy, action);
66
+ return evaluate({
67
+ user: this.#user,
68
+ action,
69
+ allowGuest: options.allowGuest ?? false,
70
+ run: (user) => method(user, ...args),
71
+ args,
72
+ before: policy.before?.bind(policy),
73
+ after: policy.after?.bind(policy),
74
+ });
75
+ }
76
+ /** True iff the action is authorized. Never throws on denial. */
77
+ async allows(action, ...args) {
78
+ return (await this.execute(action, ...args)).authorized;
79
+ }
80
+ /** Boolean negation of {@link allows}. Never throws on denial. */
81
+ async denies(action, ...args) {
82
+ return !(await this.execute(action, ...args)).authorized;
83
+ }
84
+ /** Resolves on allow; throws `WARDEN_AUTHORIZATION_FAILURE` on deny (D2). */
85
+ async authorize(action, ...args) {
86
+ const response = await this.execute(action, ...args);
87
+ if (!response.authorized) {
88
+ throwAuthorizationFailure(response);
89
+ }
90
+ }
91
+ }
92
+ //# sourceMappingURL=PolicyAuthorizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyAuthorizer.js","sourceRoot":"","sources":["../../src/bouncer/PolicyAuthorizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Bouncer policy decorators — `@allowGuest()` / `@action()` mark policy methods
3
+ * that a guest (null user) may reach. Mirrors the `Guard.ts` idiom (D9):
4
+ * `reflect-metadata` side-effect import, a `Symbol.for` key, the legacy
5
+ * `MethodDecorator` signature, and a `getActionMetadata` reader.
6
+ */
7
+ import "reflect-metadata";
8
+ import type { AbilityOptions } from "./types.js";
9
+ /**
10
+ * `@action({ allowGuest })` — configure a policy method's evaluation options.
11
+ */
12
+ export declare function action(options: AbilityOptions): MethodDecorator;
13
+ /**
14
+ * `@allowGuest()` — let a guest (null user) reach this policy method.
15
+ * Equivalent to `@action({ allowGuest: true })`.
16
+ */
17
+ export declare function allowGuest(): MethodDecorator;
18
+ /**
19
+ * Read a policy method's action metadata. Walks the prototype chain
20
+ * (`Reflect.getMetadata`) so it resolves from a policy INSTANCE — legacy
21
+ * decorators write metadata onto the class prototype, where the instance
22
+ * inherits it. Absent ⇒ `{}` (⇒ `allowGuest` falsy ⇒ guest denied).
23
+ */
24
+ export declare function getActionMetadata(target: object, propertyKey: string | symbol): AbilityOptions;
25
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/bouncer/decorators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjD;;GAEG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CAI/D;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,eAAe,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC1B,cAAc,CAEhB"}