@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,36 @@
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
+ // Side-effect import: registers `Reflect.defineMetadata` / `getMetadata`. Pulled
8
+ // in here (not transitively) so warden stays self-sufficient when published.
9
+ import "reflect-metadata";
10
+ /** Action metadata key — Symbol.for ensures cross-module accessibility. */
11
+ const ACTION_KEY = Symbol.for("warden:bouncer:action");
12
+ /**
13
+ * `@action({ allowGuest })` — configure a policy method's evaluation options.
14
+ */
15
+ export function action(options) {
16
+ return (target, propertyKey) => {
17
+ Reflect.defineMetadata(ACTION_KEY, options, target, propertyKey);
18
+ };
19
+ }
20
+ /**
21
+ * `@allowGuest()` — let a guest (null user) reach this policy method.
22
+ * Equivalent to `@action({ allowGuest: true })`.
23
+ */
24
+ export function allowGuest() {
25
+ return action({ allowGuest: true });
26
+ }
27
+ /**
28
+ * Read a policy method's action metadata. Walks the prototype chain
29
+ * (`Reflect.getMetadata`) so it resolves from a policy INSTANCE — legacy
30
+ * decorators write metadata onto the class prototype, where the instance
31
+ * inherits it. Absent ⇒ `{}` (⇒ `allowGuest` falsy ⇒ guest denied).
32
+ */
33
+ export function getActionMetadata(target, propertyKey) {
34
+ return Reflect.getMetadata(ACTION_KEY, target, propertyKey) ?? {};
35
+ }
36
+ //# sourceMappingURL=decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/bouncer/decorators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,iFAAiF;AACjF,6EAA6E;AAC7E,OAAO,kBAAkB,CAAC;AAG1B,2EAA2E;AAC3E,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAEvD;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,OAAuB;IAC7C,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC9B,OAAO,CAAC,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAClE,CAAC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACzB,OAAO,MAAM,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAChC,MAAc,EACd,WAA4B;IAE5B,OAAO,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;AACnE,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Shared evaluation pipeline — the single place that encodes the Adonis Bouncer
3
+ * evaluation order (D5), used by BOTH standalone abilities (no hooks) and policy
4
+ * methods (with `before`/`after`). Pinned by `bouncer-parity.test.ts` (AC-E2).
5
+ *
6
+ * Order: (1) `before` — a non-`undefined` return short-circuits the action;
7
+ * (2) guest-deny — `user === null` && !allowGuest ⇒ auto-deny WITHOUT running the
8
+ * action; (3) run the action; (4) `after` — a non-`undefined` return overrides.
9
+ */
10
+ import type { UserPayload } from "../AuthManager.js";
11
+ import { AuthorizationResponse } from "./AuthorizationResponse.js";
12
+ import type { AuthorizerResponse, HookResponse } from "./types.js";
13
+ /** A policy action method / ability callback, structurally. */
14
+ export type Action = (user: UserPayload | null, ...args: unknown[]) => AuthorizerResponse;
15
+ /** Boolean sugar → response; an explicit response passes through (D7). */
16
+ export declare function normalizeResponse(value: boolean | AuthorizationResponse): AuthorizationResponse;
17
+ /**
18
+ * Type guard for a callable action. A function's parameter/return types are not
19
+ * observable at runtime, so this asserts the structural `Action` shape from a
20
+ * `typeof === "function"` check — a type guard (not an `as` cast), the standard
21
+ * escape for dynamic dispatch.
22
+ */
23
+ export declare function isAction(value: unknown): value is Action;
24
+ /** Throw the canonical authorization failure for a denied response (D2). */
25
+ export declare function throwAuthorizationFailure(response: AuthorizationResponse): never;
26
+ /** Run the D5 evaluation pipeline and resolve to the final response. */
27
+ export declare function evaluate(params: {
28
+ user: UserPayload | null;
29
+ action: string;
30
+ allowGuest: boolean;
31
+ run: (user: UserPayload | null) => AuthorizerResponse;
32
+ args: unknown[];
33
+ before?: (user: UserPayload | null, action: string, ...args: unknown[]) => HookResponse;
34
+ after?: (user: UserPayload | null, action: string, result: AuthorizationResponse) => HookResponse;
35
+ }): Promise<AuthorizationResponse>;
36
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/bouncer/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEnE,+DAA+D;AAC/D,MAAM,MAAM,MAAM,GAAG,CACpB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,kBAAkB,CAAC;AAExB,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GACpC,qBAAqB,CAKvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,4EAA4E;AAC5E,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,qBAAqB,GAC7B,KAAK,CASP;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,MAAM,EAAE;IACtC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,kBAAkB,CAAC;IACtD,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,CACR,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,YAAY,CAAC;IAClB,KAAK,CAAC,EAAE,CACP,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,KACzB,YAAY,CAAC;CAClB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA+BjC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Shared evaluation pipeline — the single place that encodes the Adonis Bouncer
3
+ * evaluation order (D5), used by BOTH standalone abilities (no hooks) and policy
4
+ * methods (with `before`/`after`). Pinned by `bouncer-parity.test.ts` (AC-E2).
5
+ *
6
+ * Order: (1) `before` — a non-`undefined` return short-circuits the action;
7
+ * (2) guest-deny — `user === null` && !allowGuest ⇒ auto-deny WITHOUT running the
8
+ * action; (3) run the action; (4) `after` — a non-`undefined` return overrides.
9
+ */
10
+ import { WardenError } from "../errors.js";
11
+ import { AuthorizationResponse } from "./AuthorizationResponse.js";
12
+ /** Boolean sugar → response; an explicit response passes through (D7). */
13
+ export function normalizeResponse(value) {
14
+ if (value instanceof AuthorizationResponse) {
15
+ return value;
16
+ }
17
+ return value ? AuthorizationResponse.allow() : AuthorizationResponse.deny();
18
+ }
19
+ /**
20
+ * Type guard for a callable action. A function's parameter/return types are not
21
+ * observable at runtime, so this asserts the structural `Action` shape from a
22
+ * `typeof === "function"` check — a type guard (not an `as` cast), the standard
23
+ * escape for dynamic dispatch.
24
+ */
25
+ export function isAction(value) {
26
+ return typeof value === "function";
27
+ }
28
+ /** Throw the canonical authorization failure for a denied response (D2). */
29
+ export function throwAuthorizationFailure(response) {
30
+ throw new WardenError("AUTHORIZATION_FAILURE", response.message ?? "Authorization failed", {
31
+ hint: "The current user is not authorized for this action.",
32
+ status: response.status ?? 403,
33
+ });
34
+ }
35
+ /** Run the D5 evaluation pipeline and resolve to the final response. */
36
+ export async function evaluate(params) {
37
+ const { user, action, allowGuest, run, args, before, after } = params;
38
+ let response;
39
+ // (1) before — non-undefined short-circuits the action.
40
+ if (before) {
41
+ const early = await before(user, action, ...args);
42
+ if (early !== undefined) {
43
+ response = normalizeResponse(early);
44
+ }
45
+ }
46
+ // (2) guest-deny + (3) action — only if before did not short-circuit.
47
+ if (response === undefined) {
48
+ if (user === null && !allowGuest) {
49
+ response = AuthorizationResponse.deny();
50
+ }
51
+ else {
52
+ response = normalizeResponse(await run(user));
53
+ }
54
+ }
55
+ // (4) after — non-undefined overrides.
56
+ if (after) {
57
+ const override = await after(user, action, response);
58
+ if (override !== undefined) {
59
+ response = normalizeResponse(override);
60
+ }
61
+ }
62
+ return response;
63
+ }
64
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/bouncer/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AASnE,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAChC,KAAsC;IAEtC,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,CAAC,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC;AACpC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,yBAAyB,CACxC,QAA+B;IAE/B,MAAM,IAAI,WAAW,CACpB,uBAAuB,EACvB,QAAQ,CAAC,OAAO,IAAI,sBAAsB,EAC1C;QACC,IAAI,EAAE,qDAAqD;QAC3D,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,GAAG;KAC9B,CACD,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAgB9B;IACA,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAEtE,IAAI,QAA2C,CAAC;IAEhD,wDAAwD;IACxD,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;IAED,sEAAsE;IACtE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC;aAAM,CAAC;YACP,QAAQ,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;IACF,CAAC;IAED,uCAAuC;IACvC,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC5B,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Internal policy context attach — Layer-2 ⨯ Layer-1 wiring (Epic 56, story 56.3).
3
+ *
4
+ * The active `scope` and the resolved `EffectivePermissions` for the in-flight
5
+ * `(user, scope)` are attached to a freshly-constructed policy via a package-
6
+ * internal `WeakMap` (D2) — NOT a public setter on `BasePolicy` and NOT barrelled.
7
+ * `BasePolicy`'s `this.scope` / `this.permissions` getters read it back; the
8
+ * `PolicyAuthorizer` writes it before dispatch. A policy used without a Bouncer
9
+ * has no entry, so the getters fall back to `global` + {@link emptyPermissions}.
10
+ */
11
+ import type { EffectivePermissions, Scope } from "../rights/types.js";
12
+ import type { BasePolicy } from "./BasePolicy.js";
13
+ /** What the authorizer attaches to a policy instance for one check. */
14
+ export interface PolicyContext {
15
+ readonly scope: Scope;
16
+ readonly permissions: EffectivePermissions;
17
+ }
18
+ /** Attach the active scope + resolved permissions to a policy instance (internal). */
19
+ export declare function setPolicyContext(policy: BasePolicy, context: PolicyContext): void;
20
+ /** Read back a policy's attached context, or `undefined` when used standalone. */
21
+ export declare function getPolicyContext(policy: BasePolicy): PolicyContext | undefined;
22
+ /**
23
+ * The empty `EffectivePermissions` for a guest / no-resolver Bouncer (D9). Built
24
+ * locally — never a `resolve()` call (the resolver requires a non-null user) and
25
+ * never importing 56.1's non-exported `ResolvedPermissions`. `has` → false;
26
+ * `hasAll([])` → true (vacuous); `hasAny` → false; empty sets; `scope` = active.
27
+ */
28
+ export declare function emptyPermissions(scope: Scope): EffectivePermissions;
29
+ //# sourceMappingURL=policyContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policyContext.d.ts","sourceRoot":"","sources":["../../src/bouncer/policyContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;CAC3C;AAID,sFAAsF;AACtF,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,aAAa,GACpB,IAAI,CAEN;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,UAAU,GAChB,aAAa,GAAG,SAAS,CAE3B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,oBAAoB,CASnE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Internal policy context attach — Layer-2 ⨯ Layer-1 wiring (Epic 56, story 56.3).
3
+ *
4
+ * The active `scope` and the resolved `EffectivePermissions` for the in-flight
5
+ * `(user, scope)` are attached to a freshly-constructed policy via a package-
6
+ * internal `WeakMap` (D2) — NOT a public setter on `BasePolicy` and NOT barrelled.
7
+ * `BasePolicy`'s `this.scope` / `this.permissions` getters read it back; the
8
+ * `PolicyAuthorizer` writes it before dispatch. A policy used without a Bouncer
9
+ * has no entry, so the getters fall back to `global` + {@link emptyPermissions}.
10
+ */
11
+ const contexts = new WeakMap();
12
+ /** Attach the active scope + resolved permissions to a policy instance (internal). */
13
+ export function setPolicyContext(policy, context) {
14
+ contexts.set(policy, context);
15
+ }
16
+ /** Read back a policy's attached context, or `undefined` when used standalone. */
17
+ export function getPolicyContext(policy) {
18
+ return contexts.get(policy);
19
+ }
20
+ /**
21
+ * The empty `EffectivePermissions` for a guest / no-resolver Bouncer (D9). Built
22
+ * locally — never a `resolve()` call (the resolver requires a non-null user) and
23
+ * never importing 56.1's non-exported `ResolvedPermissions`. `has` → false;
24
+ * `hasAll([])` → true (vacuous); `hasAny` → false; empty sets; `scope` = active.
25
+ */
26
+ export function emptyPermissions(scope) {
27
+ return {
28
+ has: () => false,
29
+ hasAll: (permissions) => permissions.length === 0,
30
+ hasAny: () => false,
31
+ permissions: new Set(),
32
+ roles: new Set(),
33
+ scope,
34
+ };
35
+ }
36
+ //# sourceMappingURL=policyContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policyContext.js","sourceRoot":"","sources":["../../src/bouncer/policyContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA6B,CAAC;AAE1D,sFAAsF;AACtF,MAAM,UAAU,gBAAgB,CAC/B,MAAkB,EAClB,OAAsB;IAEtB,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAC/B,MAAkB;IAElB,OAAO,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC5C,OAAO;QACN,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;QAChB,MAAM,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;QACjD,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK;QACnB,WAAW,EAAE,IAAI,GAAG,EAAU;QAC9B,KAAK,EAAE,IAAI,GAAG,EAAU;QACxB,KAAK;KACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Bouncer evaluation contract — Layer 2 of Warden's unified authorization.
3
+ *
4
+ * The shapes here are faithful to AdonisJS Bouncer (verified context7
5
+ * `/adonisjs/bouncer`, 2026-06-01): a predicate returns a boolean (sugar for
6
+ * allow / deny) or an explicit `AuthorizationResponse`, sync or async.
7
+ */
8
+ import type { UserPayload } from "../AuthManager.js";
9
+ import type { RightsResolver } from "../rights/RightsResolver.js";
10
+ import type { Scope } from "../rights/types.js";
11
+ import type { AuthorizationResponse } from "./AuthorizationResponse.js";
12
+ /**
13
+ * Optional 4th `Bouncer` ctor argument (56.3, D1) — the scope dimension + the
14
+ * Layer-1 resolver. Both optional; omitting it ⇒ the implicit `global` scope
15
+ * with no resolver (single-tenant zero-config, D7). Additive: every 56.2 call
16
+ * site keeps compiling.
17
+ */
18
+ export interface BouncerContext {
19
+ /** Active resolution scope. Defaults to `"global"`. */
20
+ readonly scope?: Scope;
21
+ /** Layer-1 resolver consulted for this Bouncer's `(user, scope)`. */
22
+ readonly resolver?: RightsResolver;
23
+ }
24
+ /** A predicate's return — bool sugar or an explicit response, sync or async (D7). */
25
+ export type AuthorizerResponse = boolean | AuthorizationResponse | Promise<boolean | AuthorizationResponse>;
26
+ /** A `before`/`after` hook return — like {@link AuthorizerResponse} plus `undefined` (fall-through). */
27
+ export type HookResponse = boolean | AuthorizationResponse | undefined | Promise<boolean | AuthorizationResponse | undefined>;
28
+ /** Options accepted by `Bouncer.ability` and the `@action` decorator. */
29
+ export interface AbilityOptions {
30
+ allowGuest?: boolean;
31
+ }
32
+ /**
33
+ * An opaque ability reference produced by `Bouncer.ability`. Usable by-reference
34
+ * (typed call args via the `Args` phantom) AND by-name (registered in the
35
+ * Bouncer ctor's abilities record).
36
+ *
37
+ * `Args` is carried by the contravariant `__args` phantom — never read at
38
+ * runtime — so a concrete `Ability<[Post]>` is assignable to the universal
39
+ * `Ability<never[]>` storage type while `execute` stays invokable with the real
40
+ * args. This is a branding pattern (carry the type parameter in the signature),
41
+ * not a cast: `execute` itself takes `unknown[]` and the call sites validate
42
+ * args via the phantom at the verb boundary.
43
+ */
44
+ export interface Ability<Args extends unknown[] = unknown[]> {
45
+ /** Whether a guest (null user) may invoke the callback (D5 step 2). */
46
+ readonly allowGuest: boolean;
47
+ /** Runs the ability callback. Guest-deny is applied by the evaluator, not here. */
48
+ readonly execute: (user: UserPayload | null, ...args: unknown[]) => AuthorizerResponse;
49
+ /** Phantom — ties the by-reference call args to `Args`; never read at runtime. */
50
+ readonly __args?: (...args: Args) => void;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/bouncer/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;CACnC;AAED,qFAAqF;AACrF,MAAM,MAAM,kBAAkB,GAC3B,OAAO,GACP,qBAAqB,GACrB,OAAO,CAAC,OAAO,GAAG,qBAAqB,CAAC,CAAC;AAE5C,wGAAwG;AACxG,MAAM,MAAM,YAAY,GACrB,OAAO,GACP,qBAAqB,GACrB,SAAS,GACT,OAAO,CAAC,OAAO,GAAG,qBAAqB,GAAG,SAAS,CAAC,CAAC;AAExD,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,OAAO,CAAC,IAAI,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE;IAC1D,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,CACjB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,GAAG,IAAI,EAAE,OAAO,EAAE,KACd,kBAAkB,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAC1C"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Bouncer evaluation contract — Layer 2 of Warden's unified authorization.
3
+ *
4
+ * The shapes here are faithful to AdonisJS Bouncer (verified context7
5
+ * `/adonisjs/bouncer`, 2026-06-01): a predicate returns a boolean (sugar for
6
+ * allow / deny) or an explicit `AuthorizationResponse`, sync or async.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/bouncer/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Warden configuration — declared in `config/auth.ts` of the user app.
3
+ *
4
+ * @example
5
+ * // config/auth.ts
6
+ * import { defineConfig } from '@c9up/warden/config'
7
+ * export default defineConfig({
8
+ * defaultStrategy: 'jwt',
9
+ * jwt: {
10
+ * secret: env('APP_KEY'),
11
+ * expiresInSeconds: 3600,
12
+ * findUser: (id) => User.find(id),
13
+ * verifyCredentials: (email, password) => User.verifyCredentials(email, password),
14
+ * },
15
+ * })
16
+ */
17
+ import type { UserPayload } from "./AuthManager.js";
18
+ import type { RightsStore } from "./rights/types.js";
19
+ export interface JwtConfig {
20
+ secret: string;
21
+ expiresInSeconds?: number;
22
+ findUser: (id: string) => Promise<UserPayload | null>;
23
+ verifyCredentials: (email: string, password: string) => Promise<UserPayload | null>;
24
+ }
25
+ export interface WardenConfig {
26
+ /** Default auth strategy (default: 'jwt'). */
27
+ defaultStrategy?: string;
28
+ /** JWT strategy configuration. */
29
+ jwt?: JwtConfig;
30
+ /**
31
+ * Rights layer configuration (Epic 56). Supply a custom `store` to back the
32
+ * unified resolver with a DB-backed driver; when omitted, an in-memory
33
+ * `MemoryRightsStore` is registered as the default (AD5 — pluggable store,
34
+ * in-memory shipped).
35
+ */
36
+ rights?: {
37
+ store?: RightsStore;
38
+ };
39
+ }
40
+ /** Typed config helper — identity function for editor inference. */
41
+ export declare function defineConfig(config: WardenConfig): WardenConfig;
42
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,SAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACtD,iBAAiB,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,KACZ,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC5B,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kCAAkC;IAClC,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;CACjC;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D"}
package/dist/config.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Warden configuration — declared in `config/auth.ts` of the user app.
3
+ *
4
+ * @example
5
+ * // config/auth.ts
6
+ * import { defineConfig } from '@c9up/warden/config'
7
+ * export default defineConfig({
8
+ * defaultStrategy: 'jwt',
9
+ * jwt: {
10
+ * secret: env('APP_KEY'),
11
+ * expiresInSeconds: 3600,
12
+ * findUser: (id) => User.find(id),
13
+ * verifyCredentials: (email, password) => User.verifyCredentials(email, password),
14
+ * },
15
+ * })
16
+ */
17
+ /** Typed config helper — identity function for editor inference. */
18
+ export function defineConfig(config) {
19
+ return config;
20
+ }
21
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA6BH,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,MAAoB;IAChD,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,10 @@
1
+ interface Codemods {
2
+ addProvider(importPath: string): Promise<void>;
3
+ addEnvVars(vars: Record<string, string>): Promise<void>;
4
+ writeFile(filePath: string, content: string, options?: {
5
+ force?: boolean;
6
+ }): Promise<void>;
7
+ }
8
+ export declare function configure(codemods: Codemods): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=configure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAEA,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CjE"}
@@ -0,0 +1,44 @@
1
+ import { randomBytes } from "node:crypto";
2
+ export async function configure(codemods) {
3
+ const jwtSecret = randomBytes(32).toString("hex");
4
+ await codemods.addProvider("@c9up/warden/provider");
5
+ await codemods.addEnvVars({
6
+ JWT_SECRET: jwtSecret,
7
+ JWT_EXPIRY: "3600",
8
+ });
9
+ await codemods.writeFile("config/auth.ts", `import { defineConfig } from '@c9up/warden'
10
+
11
+ export default defineConfig({
12
+ defaultStrategy: 'jwt',
13
+ jwt: {
14
+ secret: process.env.JWT_SECRET ?? '',
15
+ expiresInSeconds: Number(process.env.JWT_EXPIRY ?? '3600'),
16
+ // TODO: wire these to your user model (e.g. via your ORM).
17
+ // The JWT strategy needs both to issue and verify tokens.
18
+ findUser: async (_id) => {
19
+ throw new Error('TODO: implement findUser(id) for the JWT strategy in config/auth.ts')
20
+ },
21
+ verifyCredentials: async (_email, _password) => {
22
+ throw new Error('TODO: implement verifyCredentials(email, password) in config/auth.ts')
23
+ },
24
+ },
25
+ })
26
+ `);
27
+ // Announce the TODOs on stderr so `ream add @c9up/warden` doesn't end
28
+ // with a quiet success that the user reads as "auth is wired". The
29
+ // generated config/auth.ts ships with `throw new Error('TODO ...')`
30
+ // stubs for findUser + verifyCredentials — login and JWT verify will
31
+ // fail at the first call until the user fills them in. Surfacing the
32
+ // list here means an operator running the installer sees it
33
+ // immediately, not at the first request that hits the auth path.
34
+ process.stderr.write([
35
+ "",
36
+ "[@c9up/warden] config/auth.ts written with TODO stubs:",
37
+ " - jwt.findUser(id) — wire to your user lookup (ORM)",
38
+ " - jwt.verifyCredentials(email, password) — wire to your sign-in flow",
39
+ "Both throw at runtime until you implement them — login + JWT verify",
40
+ "will fail with `TODO: implement …` errors otherwise.",
41
+ "",
42
+ ].join("\n"));
43
+ }
44
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY1C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,MAAM,SAAS,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,QAAQ,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;IACpD,MAAM,QAAQ,CAAC,UAAU,CAAC;QACzB,UAAU,EAAE,SAAS;QACrB,UAAU,EAAE,MAAM;KAClB,CAAC,CAAC;IACH,MAAM,QAAQ,CAAC,SAAS,CACvB,gBAAgB,EAChB;;;;;;;;;;;;;;;;;CAiBD,CACC,CAAC;IACF,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,qEAAqE;IACrE,qEAAqE;IACrE,4DAA4D;IAC5D,iEAAiE;IACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB;QACC,EAAE;QACF,wDAAwD;QACxD,uDAAuD;QACvD,wEAAwE;QACxE,qEAAqE;QACrE,sDAAsD;QACtD,EAAE;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * WardenError — structured error for Warden auth.
3
+ */
4
+ export declare class WardenError extends Error {
5
+ readonly code: string;
6
+ readonly hint?: string;
7
+ /**
8
+ * Optional HTTP status carried by the error so the HTTP layer can map it
9
+ * (e.g. an authorization failure carries 403 — Epic 56 / story 56.2, D2).
10
+ * Additive and optional: callers that omit it behave exactly as before.
11
+ */
12
+ readonly status?: number;
13
+ constructor(code: string, message: string, options?: {
14
+ hint?: string;
15
+ status?: number;
16
+ });
17
+ }
18
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAGxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAQ7C"}
package/dist/errors.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * WardenError — structured error for Warden auth.
3
+ */
4
+ export class WardenError extends Error {
5
+ code;
6
+ hint;
7
+ /**
8
+ * Optional HTTP status carried by the error so the HTTP layer can map it
9
+ * (e.g. an authorization failure carries 403 — Epic 56 / story 56.2, D2).
10
+ * Additive and optional: callers that omit it behave exactly as before.
11
+ */
12
+ status;
13
+ constructor(code, message, options) {
14
+ super(message);
15
+ this.name = "WardenError";
16
+ this.code = `WARDEN_${code}`;
17
+ this.hint = options?.hint;
18
+ this.status = options?.status;
19
+ }
20
+ }
21
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,IAAI,CAAU;IACvB;;;;OAIG;IACM,MAAM,CAAU;IAEzB,YACC,IAAY,EACZ,OAAe,EACf,OAA4C;QAE5C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;IAC/B,CAAC;CACD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * FirstContactManager — OAuth2 social authentication.
3
+ *
4
+ * Usage:
5
+ * firstContact.use('google').redirectUrl()
6
+ * firstContact.use('google').callback(code)
7
+ */
8
+ import type { FirstContactDriver, OAuthToken, OAuthUser } from "./types.js";
9
+ export declare class FirstContactManager {
10
+ #private;
11
+ use(name: string): FirstContactDriver;
12
+ register(name: string, driver: FirstContactDriver): void;
13
+ redirect(name: string, state?: string): string;
14
+ /**
15
+ * Handle the OAuth callback. Pass `state` (from the query string) and
16
+ * `expectedState` (from the session, stored at redirect time) for CSRF
17
+ * protection. Omitting `expectedState` logs a security warning.
18
+ */
19
+ callback(name: string, code: string, state?: string, expectedState?: string): Promise<{
20
+ user: OAuthUser;
21
+ token: OAuthToken;
22
+ }>;
23
+ get registeredDrivers(): string[];
24
+ }
25
+ //# sourceMappingURL=FirstContactManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FirstContactManager.d.ts","sourceRoot":"","sources":["../../src/firstcontact/FirstContactManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5E,qBAAa,mBAAmB;;IAG/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB;IASrC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAIxD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAI9C;;;;OAIG;IACG,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;IAUlD,IAAI,iBAAiB,IAAI,MAAM,EAAE,CAEhC;CACD"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * FirstContactManager — OAuth2 social authentication.
3
+ *
4
+ * Usage:
5
+ * firstContact.use('google').redirectUrl()
6
+ * firstContact.use('google').callback(code)
7
+ */
8
+ export class FirstContactManager {
9
+ #drivers = new Map();
10
+ use(name) {
11
+ const driver = this.#drivers.get(name);
12
+ if (!driver)
13
+ throw new Error(`OAuth driver '${name}' not registered. Available: ${[...this.#drivers.keys()].join(", ")}`);
14
+ return driver;
15
+ }
16
+ register(name, driver) {
17
+ this.#drivers.set(name, driver);
18
+ }
19
+ redirect(name, state) {
20
+ return this.use(name).redirectUrl(state);
21
+ }
22
+ /**
23
+ * Handle the OAuth callback. Pass `state` (from the query string) and
24
+ * `expectedState` (from the session, stored at redirect time) for CSRF
25
+ * protection. Omitting `expectedState` logs a security warning.
26
+ */
27
+ async callback(name, code, state, expectedState) {
28
+ if (!expectedState) {
29
+ throw new Error(`[warden] OAuth callback for '${name}' requires expectedState for CSRF protection. ` +
30
+ `Store the state from redirect() in the session and pass it here.`);
31
+ }
32
+ return this.use(name).callback(code, state, expectedState);
33
+ }
34
+ get registeredDrivers() {
35
+ return [...this.#drivers.keys()];
36
+ }
37
+ }
38
+ //# sourceMappingURL=FirstContactManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FirstContactManager.js","sourceRoot":"","sources":["../../src/firstcontact/FirstContactManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,OAAO,mBAAmB;IAC/B,QAAQ,GAAoC,IAAI,GAAG,EAAE,CAAC;IAEtD,GAAG,CAAC,IAAY;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YACV,MAAM,IAAI,KAAK,CACd,iBAAiB,IAAI,gCAAgC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3F,CAAC;QACH,OAAO,MAAM,CAAC;IACf,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,MAA0B;QAChD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,KAAc;QACpC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAQ,CACb,IAAY,EACZ,IAAY,EACZ,KAAc,EACd,aAAsB;QAEtB,IAAI,CAAC,aAAa,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACd,gCAAgC,IAAI,gDAAgD;gBACnF,kEAAkE,CACnE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,iBAAiB;QACpB,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;CACD"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * GitHub OAuth2 driver for FirstContact.
3
+ */
4
+ import type { FirstContactDriver, OAuthConfig, OAuthToken, OAuthUser } from "../types.js";
5
+ export declare class GitHubDriver implements FirstContactDriver {
6
+ private config;
7
+ constructor(config: OAuthConfig);
8
+ redirectUrl(state?: string): string;
9
+ callback(code: string, state?: string, expectedState?: string): Promise<{
10
+ user: OAuthUser;
11
+ token: OAuthToken;
12
+ }>;
13
+ }
14
+ //# sourceMappingURL=GitHubDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubDriver.d.ts","sourceRoot":"","sources":["../../../src/firstcontact/drivers/GitHubDriver.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACX,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,SAAS,EACT,MAAM,aAAa,CAAC;AAErB,qBAAa,YAAa,YAAW,kBAAkB;IAC1C,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;IAEvC,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAU7B,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,aAAa,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC;CAiDlD"}