@astram/guard 0.1.1 → 0.3.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.
Files changed (183) hide show
  1. package/dist/auth/account.controller.d.ts +245 -0
  2. package/dist/auth/account.controller.d.ts.map +1 -0
  3. package/dist/auth/account.controller.js +673 -0
  4. package/dist/auth/account.controller.js.map +1 -0
  5. package/dist/auth/auth.controller.d.ts +316 -0
  6. package/dist/auth/auth.controller.d.ts.map +1 -0
  7. package/dist/auth/auth.controller.js +1091 -0
  8. package/dist/auth/auth.controller.js.map +1 -0
  9. package/dist/auth/auth.module.d.ts +202 -0
  10. package/dist/auth/auth.module.d.ts.map +1 -0
  11. package/dist/auth/auth.module.js +610 -0
  12. package/dist/auth/auth.module.js.map +1 -0
  13. package/dist/auth/connections.d.ts +61 -0
  14. package/dist/auth/connections.d.ts.map +1 -0
  15. package/dist/auth/connections.js +116 -0
  16. package/dist/auth/connections.js.map +1 -0
  17. package/dist/auth/dto.d.ts +154 -0
  18. package/dist/auth/dto.d.ts.map +1 -0
  19. package/dist/auth/dto.js +29 -0
  20. package/dist/auth/dto.js.map +1 -0
  21. package/dist/auth/pending-mfa-store.d.ts +72 -0
  22. package/dist/auth/pending-mfa-store.d.ts.map +1 -0
  23. package/dist/auth/pending-mfa-store.js +106 -0
  24. package/dist/auth/pending-mfa-store.js.map +1 -0
  25. package/dist/auth/persistence.module.d.ts +42 -0
  26. package/dist/auth/persistence.module.d.ts.map +1 -0
  27. package/dist/auth/persistence.module.js +94 -0
  28. package/dist/auth/persistence.module.js.map +1 -0
  29. package/dist/auth/ports/audit-sink.d.ts +47 -0
  30. package/dist/auth/ports/audit-sink.d.ts.map +1 -0
  31. package/dist/auth/ports/audit-sink.js +20 -0
  32. package/dist/auth/ports/audit-sink.js.map +1 -0
  33. package/dist/auth/ports/credential-writer.d.ts +23 -0
  34. package/dist/auth/ports/credential-writer.d.ts.map +1 -0
  35. package/dist/auth/ports/credential-writer.js +2 -0
  36. package/dist/auth/ports/credential-writer.js.map +1 -0
  37. package/dist/auth/ports/email-sender.d.ts +14 -0
  38. package/dist/auth/ports/email-sender.d.ts.map +1 -0
  39. package/dist/auth/ports/email-sender.js +2 -0
  40. package/dist/auth/ports/email-sender.js.map +1 -0
  41. package/dist/auth/ports/mfa-device-store.d.ts +45 -0
  42. package/dist/auth/ports/mfa-device-store.d.ts.map +1 -0
  43. package/dist/auth/ports/mfa-device-store.js +13 -0
  44. package/dist/auth/ports/mfa-device-store.js.map +1 -0
  45. package/dist/auth/ports/profile-writer.d.ts +12 -0
  46. package/dist/auth/ports/profile-writer.d.ts.map +1 -0
  47. package/dist/auth/ports/profile-writer.js +2 -0
  48. package/dist/auth/ports/profile-writer.js.map +1 -0
  49. package/dist/auth/ports/recovery-code-store.d.ts +10 -0
  50. package/dist/auth/ports/recovery-code-store.d.ts.map +1 -0
  51. package/dist/auth/ports/recovery-code-store.js +2 -0
  52. package/dist/auth/ports/recovery-code-store.js.map +1 -0
  53. package/dist/auth/ports/reset-token-store.d.ts +12 -0
  54. package/dist/auth/ports/reset-token-store.d.ts.map +1 -0
  55. package/dist/auth/ports/reset-token-store.js +2 -0
  56. package/dist/auth/ports/reset-token-store.js.map +1 -0
  57. package/dist/auth/ports/session-facts-projector.d.ts +44 -0
  58. package/dist/auth/ports/session-facts-projector.d.ts.map +1 -0
  59. package/dist/auth/ports/session-facts-projector.js +30 -0
  60. package/dist/auth/ports/session-facts-projector.js.map +1 -0
  61. package/dist/auth/ports/session-sweeper.d.ts +12 -0
  62. package/dist/auth/ports/session-sweeper.d.ts.map +1 -0
  63. package/dist/auth/ports/session-sweeper.js +2 -0
  64. package/dist/auth/ports/session-sweeper.js.map +1 -0
  65. package/dist/auth/profile-resolver.d.ts +73 -0
  66. package/dist/auth/profile-resolver.d.ts.map +1 -0
  67. package/dist/auth/profile-resolver.js +28 -0
  68. package/dist/auth/profile-resolver.js.map +1 -0
  69. package/dist/auth/rate-limit/attempt-limiter.d.ts +91 -0
  70. package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -0
  71. package/dist/auth/rate-limit/attempt-limiter.js +133 -0
  72. package/dist/auth/rate-limit/attempt-limiter.js.map +1 -0
  73. package/dist/auth/tokens.d.ts +236 -0
  74. package/dist/auth/tokens.d.ts.map +1 -0
  75. package/dist/auth/tokens.js +254 -0
  76. package/dist/auth/tokens.js.map +1 -0
  77. package/dist/auth/totp-enrollment.d.ts +42 -0
  78. package/dist/auth/totp-enrollment.d.ts.map +1 -0
  79. package/dist/auth/totp-enrollment.js +96 -0
  80. package/dist/auth/totp-enrollment.js.map +1 -0
  81. package/dist/authentication/argon2id-password-hasher.js.map +1 -0
  82. package/dist/authentication/mariadb-credential-resolver.d.ts +110 -0
  83. package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -0
  84. package/dist/authentication/mariadb-credential-resolver.js +170 -0
  85. package/dist/authentication/mariadb-credential-resolver.js.map +1 -0
  86. package/dist/authz/cross-tenant-grant-writer.d.ts +259 -0
  87. package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -0
  88. package/dist/authz/cross-tenant-grant-writer.js +397 -0
  89. package/dist/authz/cross-tenant-grant-writer.js.map +1 -0
  90. package/dist/authz/manifest-operation-authority-adapter.d.ts +65 -0
  91. package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -0
  92. package/dist/authz/manifest-operation-authority-adapter.js +108 -0
  93. package/dist/authz/manifest-operation-authority-adapter.js.map +1 -0
  94. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts +90 -0
  95. package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -0
  96. package/dist/authz/mariadb-cross-tenant-grant-adapter.js +211 -0
  97. package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +1 -0
  98. package/dist/authz/mariadb-record-rule-adapter.d.ts +60 -0
  99. package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -0
  100. package/dist/authz/mariadb-record-rule-adapter.js +154 -0
  101. package/dist/authz/mariadb-record-rule-adapter.js.map +1 -0
  102. package/dist/authz/mariadb-record-share-adapter.d.ts +75 -0
  103. package/dist/authz/mariadb-record-share-adapter.d.ts.map +1 -0
  104. package/dist/authz/mariadb-record-share-adapter.js +106 -0
  105. package/dist/authz/mariadb-record-share-adapter.js.map +1 -0
  106. package/dist/authz/record-share-cascade.d.ts +52 -0
  107. package/dist/authz/record-share-cascade.d.ts.map +1 -0
  108. package/dist/authz/record-share-cascade.js +49 -0
  109. package/dist/authz/record-share-cascade.js.map +1 -0
  110. package/dist/authz/record-share-writer.d.ts +175 -0
  111. package/dist/authz/record-share-writer.d.ts.map +1 -0
  112. package/dist/authz/record-share-writer.js +225 -0
  113. package/dist/authz/record-share-writer.js.map +1 -0
  114. package/dist/authz/wire-record-authorization.d.ts +66 -0
  115. package/dist/authz/wire-record-authorization.d.ts.map +1 -0
  116. package/dist/authz/wire-record-authorization.js +34 -0
  117. package/dist/authz/wire-record-authorization.js.map +1 -0
  118. package/dist/boot/boot-sequence.js.map +1 -0
  119. package/dist/boot/boot.module.js.map +1 -0
  120. package/dist/completeness/catalog-reconciler.d.ts +21 -0
  121. package/dist/completeness/catalog-reconciler.d.ts.map +1 -0
  122. package/dist/completeness/catalog-reconciler.js +74 -0
  123. package/dist/completeness/catalog-reconciler.js.map +1 -0
  124. package/dist/completeness/operation-inventory-scanner.d.ts +17 -0
  125. package/dist/completeness/operation-inventory-scanner.d.ts.map +1 -0
  126. package/dist/completeness/operation-inventory-scanner.js +79 -0
  127. package/dist/completeness/operation-inventory-scanner.js.map +1 -0
  128. package/dist/completeness/ports/catalog-store.d.ts +33 -0
  129. package/dist/completeness/ports/catalog-store.d.ts.map +1 -0
  130. package/dist/completeness/ports/catalog-store.js +2 -0
  131. package/dist/completeness/ports/catalog-store.js.map +1 -0
  132. package/dist/config/app-config.d.ts +134 -1
  133. package/dist/config/app-config.d.ts.map +1 -1
  134. package/dist/config/app-config.js +144 -2
  135. package/dist/config/app-config.js.map +1 -0
  136. package/dist/config/config.module.js.map +1 -0
  137. package/dist/enforcement/classification.decorator.d.ts +33 -14
  138. package/dist/enforcement/classification.decorator.d.ts.map +1 -1
  139. package/dist/enforcement/classification.decorator.js +34 -14
  140. package/dist/enforcement/classification.decorator.js.map +1 -0
  141. package/dist/enforcement/core-seam.js.map +1 -0
  142. package/dist/enforcement/enforcement.module.js.map +1 -0
  143. package/dist/enforcement/global-enforcement.guard.d.ts +29 -19
  144. package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
  145. package/dist/enforcement/global-enforcement.guard.js +108 -25
  146. package/dist/enforcement/global-enforcement.guard.js.map +1 -0
  147. package/dist/enforcement/reenroll-allowlist.d.ts +49 -0
  148. package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -0
  149. package/dist/enforcement/reenroll-allowlist.js +77 -0
  150. package/dist/enforcement/reenroll-allowlist.js.map +1 -0
  151. package/dist/index.d.ts +43 -3
  152. package/dist/index.d.ts.map +1 -1
  153. package/dist/index.js +198 -1
  154. package/dist/index.js.map +1 -0
  155. package/dist/module/shield-tokens.d.ts +15 -0
  156. package/dist/module/shield-tokens.d.ts.map +1 -0
  157. package/dist/module/shield-tokens.js +17 -0
  158. package/dist/module/shield-tokens.js.map +1 -0
  159. package/dist/module/shield.module.d.ts +203 -8
  160. package/dist/module/shield.module.d.ts.map +1 -1
  161. package/dist/module/shield.module.js +232 -14
  162. package/dist/module/shield.module.js.map +1 -0
  163. package/dist/request-auth/request-principal.d.ts +42 -0
  164. package/dist/request-auth/request-principal.d.ts.map +1 -0
  165. package/dist/request-auth/request-principal.js +87 -0
  166. package/dist/request-auth/request-principal.js.map +1 -0
  167. package/dist/request-auth/session-facts-als.d.ts +65 -0
  168. package/dist/request-auth/session-facts-als.d.ts.map +1 -0
  169. package/dist/request-auth/session-facts-als.js +57 -0
  170. package/dist/request-auth/session-facts-als.js.map +1 -0
  171. package/dist/request-auth/session-token-binder.d.ts +130 -0
  172. package/dist/request-auth/session-token-binder.d.ts.map +1 -0
  173. package/dist/request-auth/session-token-binder.js +277 -0
  174. package/dist/request-auth/session-token-binder.js.map +1 -0
  175. package/dist/request-auth/tokens.d.ts +14 -0
  176. package/dist/request-auth/tokens.d.ts.map +1 -0
  177. package/dist/request-auth/tokens.js +16 -0
  178. package/dist/request-auth/tokens.js.map +1 -0
  179. package/dist/session/crypto-adapters.js.map +1 -0
  180. package/dist/session/index.js.map +1 -0
  181. package/dist/session/mariadb-session-record-store.js.map +1 -0
  182. package/dist/session/redis-hot-session-store.js.map +1 -0
  183. package/package.json +2 -2
@@ -0,0 +1,610 @@
1
+ "use strict";
2
+ /**
3
+ * `AuthModule` — the Phase 0b **composition seam** that assembles the core auth
4
+ * engines from guard's adapters + the live connections, and exposes them under
5
+ * {@link SHIELD_AUTHENTICATOR} / {@link SHIELD_SESSION_AUTHORITY} for Team C's
6
+ * `/auth/*` controllers (spec §4).
7
+ *
8
+ * ─────────────────────────────────────────────────────────────────────────────
9
+ * Team B (connection + composition) OWNS this file. It wires the frozen tokens to
10
+ * the real engines:
11
+ *
12
+ * SHIELD_PASSWORD_HASHER → new Argon2idPasswordHasher() (the flagged fix —
13
+ * the authenticator factory injects it, so THIS module must provide it).
14
+ * SHIELD_CREDENTIAL_RESOLVER → new MariaDbCredentialResolver(pool) (Team A's
15
+ * class; its `resolve()` body is Team A's — until then it throws not-implemented,
16
+ * which the engine treats as fail-closed `authentication_unavailable`).
17
+ * SHIELD_SESSION_RECORD_STORE → new MariaDbSessionRecordStore(pool).
18
+ * SHIELD_HOT_SESSION_STORE → new RedisHotSessionStore(redis).
19
+ * SHIELD_TOKEN_GENERATOR → new CryptoTokenGenerator().
20
+ * SHIELD_CLOCK → new SystemClock().
21
+ * SHIELD_REFRESH_HASHER → new Sha256RefreshTokenHasher(
22
+ * assertRefreshHmacKey(config.refreshHmacKey)) ⛔ FAIL-CLOSED gate:
23
+ * `assertRefreshHmacKey` THROWS on a blank key, so auth can NEVER compose with
24
+ * an unkeyed refresh-token hasher. This is the boot-time fail-closed point for
25
+ * the required secret (loadAppConfig deliberately does NOT throw, so a
26
+ * non-auth scaffold still boots with no `.env` — see app-config.ts).
27
+ *
28
+ * SHIELD_SESSION_AUTHORITY → createSessionAuthority({ recordStore, hotStore,
29
+ * tokenGenerator, refreshHasher, clock, lifetimes: config.lifetimes }).
30
+ * `createSessionAuthority` validates lifetime bounds eagerly (throws LOUD on a
31
+ * nonsensical config — construction-time, correct).
32
+ *
33
+ * SHIELD_AUTHENTICATOR → createAuthenticator({ hasher, resolver,
34
+ * identityBroker: createIdentityBroker(), // default Internal, empty
35
+ * factorVerifiers: [ createTotpFactorVerifier({ hmacSha1 }) ] }). The TOTP
36
+ * verifier is wired so MFA works; `hmacSha1` is the {@link hmacSha1} node:crypto
37
+ * one-liner (guard owns node:crypto, core does not). `createIdentityBroker()`
38
+ * with no args registers the default Internal adapter with an EMPTY root
39
+ * allowlist (default-deny).
40
+ * ─────────────────────────────────────────────────────────────────────────────
41
+ *
42
+ * ⛔ OPT-IN (how the integration owner gates this — for the no-`.env` boot):
43
+ * AuthModule opens live connections (via PersistenceModule) and fires the
44
+ * fail-closed `assertRefreshHmacKey` gate the moment it composes. So it MUST be
45
+ * imported ONLY when a deployment wants auth. `ShieldModule.forRoot(options)`
46
+ * should conditionally add `AuthModule.forRoot()` to its `imports` gated behind an
47
+ * option (e.g. `ShieldModule.forRoot({ auth: true })`) or an env flag:
48
+ *
49
+ * imports: [
50
+ * EnforcementModule, BootModule,
51
+ * ...(options?.auth ? [AuthModule.forRoot()] : []), // ← opt-in
52
+ * ],
53
+ * exports: [APP_CONFIG, SHIELD_DECISION_AUTHORITY,
54
+ * ...(options?.auth ? [SHIELD_AUTHENTICATOR, SHIELD_SESSION_AUTHORITY] : [])],
55
+ *
56
+ * An enforcement-only app that does NOT opt in never imports AuthModule → never
57
+ * opens a pool/redis → never calls `assertRefreshHmacKey` → keeps the no-`.env`
58
+ * boot. An auth-enabled app fails LOUD at boot if `SHIELD_REFRESH_HMAC_KEY` is
59
+ * blank — auth can never compose unkeyed. `APP_CONFIG` is already `@Global` from
60
+ * `ShieldModule`, so AuthModule's config-injecting factories resolve. See DONE.md.
61
+ *
62
+ * ADR-0003: the core factories (`createAuthenticator`/`createSessionAuthority`/
63
+ * `createIdentityBroker`/`createTotpFactorVerifier`) are pure; the adapters + the
64
+ * node:crypto HMAC live in guard. Core stays zero-dep + unchanged.
65
+ */
66
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
67
+ if (k2 === undefined) k2 = k;
68
+ var desc = Object.getOwnPropertyDescriptor(m, k);
69
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
70
+ desc = { enumerable: true, get: function() { return m[k]; } };
71
+ }
72
+ Object.defineProperty(o, k2, desc);
73
+ }) : (function(o, m, k, k2) {
74
+ if (k2 === undefined) k2 = k;
75
+ o[k2] = m[k];
76
+ }));
77
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
78
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
79
+ }) : function(o, v) {
80
+ o["default"] = v;
81
+ });
82
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
83
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
84
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
85
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
86
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
87
+ };
88
+ var __importStar = (this && this.__importStar) || (function () {
89
+ var ownKeys = function(o) {
90
+ ownKeys = Object.getOwnPropertyNames || function (o) {
91
+ var ar = [];
92
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
93
+ return ar;
94
+ };
95
+ return ownKeys(o);
96
+ };
97
+ return function (mod) {
98
+ if (mod && mod.__esModule) return mod;
99
+ var result = {};
100
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
101
+ __setModuleDefault(result, mod);
102
+ return result;
103
+ };
104
+ })();
105
+ var AuthModule_1;
106
+ Object.defineProperty(exports, "__esModule", { value: true });
107
+ exports.AuthModule = exports.hmacSha1 = void 0;
108
+ exports.resolveTotpVerifier = resolveTotpVerifier;
109
+ exports.makeDefaultTotpVerifier = makeDefaultTotpVerifier;
110
+ const common_1 = require("@nestjs/common");
111
+ const node_crypto_1 = require("node:crypto");
112
+ const app_config_js_1 = require("../config/app-config.js");
113
+ const config_module_js_1 = require("../config/config.module.js");
114
+ const argon2id_password_hasher_js_1 = require("../authentication/argon2id-password-hasher.js");
115
+ const mariadb_credential_resolver_js_1 = require("../authentication/mariadb-credential-resolver.js");
116
+ const index_js_1 = require("../session/index.js");
117
+ const persistence_module_js_1 = require("./persistence.module.js");
118
+ const auth_controller_js_1 = require("./auth.controller.js");
119
+ const account_controller_js_1 = require("./account.controller.js");
120
+ const pending_mfa_store_js_1 = require("./pending-mfa-store.js");
121
+ const tokens_js_1 = require("./tokens.js");
122
+ const attempt_limiter_js_1 = require("./rate-limit/attempt-limiter.js");
123
+ const tokens_js_2 = require("../request-auth/tokens.js");
124
+ const session_token_binder_js_1 = require("../request-auth/session-token-binder.js");
125
+ /**
126
+ * The injected HMAC-SHA1 primitive the core TOTP verifier needs (Core is zero-dep
127
+ * + node-type-free, so it cannot import `node:crypto`). Guard owns node:crypto and
128
+ * supplies this one-liner: raw key bytes + message bytes → the 20-byte HMAC-SHA1
129
+ * digest. Never logs the key or message.
130
+ */
131
+ const hmacSha1 = (key, message) => new Uint8Array((0, node_crypto_1.createHmac)('sha1', Buffer.from(key)).update(Buffer.from(message)).digest());
132
+ exports.hmacSha1 = hmacSha1;
133
+ /**
134
+ * Resolve the login `totp` {@link FactorVerifier}: the consumer's `override` when
135
+ * supplied, else the framework's `defaultVerifier`. A pure, infra-free `??` — the
136
+ * ONE decision point of the Phase-2 verifier seam (override wins; absent → the
137
+ * default RFC-6238 single-secret verify, behavior unchanged).
138
+ *
139
+ * The default is passed IN (rather than built here) because the core factory
140
+ * `createTotpFactorVerifier` is loaded LAZILY via {@link loadCore} (the CJS↔ESM
141
+ * invariant, see the file header) — only reachable inside an async provider factory.
142
+ * So the authenticator's async `useFactory` awaits {@link loadCore}, builds the
143
+ * default, and hands it here alongside the injected override.
144
+ */
145
+ function resolveTotpVerifier(override, defaultVerifier) {
146
+ return override ?? defaultVerifier;
147
+ }
148
+ /**
149
+ * Build the framework's DEFAULT single-secret TOTP {@link FactorVerifier}
150
+ * (`createTotpFactorVerifier({ hmacSha1 })`), loading the core factory lazily (the
151
+ * CJS↔ESM invariant, see the file header). Exported so a CONSUMER can obtain the
152
+ * framework's base per-secret verifier to WRAP (e.g. an OR-matching multi-device
153
+ * verifier delegates to it per device secret) WITHOUT importing `@astram/core`
154
+ * directly — which would become a runtime `require` on the ESM-only core in the
155
+ * consumer's built CJS dist. Async because of {@link loadCore}.
156
+ */
157
+ async function makeDefaultTotpVerifier() {
158
+ const { createTotpFactorVerifier } = await loadCore();
159
+ return createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 });
160
+ }
161
+ /**
162
+ * A `Function`-wrapped dynamic `import()` that survives the CommonJS **build**.
163
+ * Under `module: commonjs`, `tsc` rewrites a literal `import()` into
164
+ * `Promise.resolve().then(() => require(...))` — which fails on the ESM-only core.
165
+ * Routing the import through the `Function` constructor hides it from that
166
+ * transform, so the emitted dist keeps a genuine native `import()` and Node's
167
+ * CJS→ESM interop loads core at runtime. (This path is used by the BUILT dist —
168
+ * e.g. example-backend. It does NOT work under vitest, whose sandbox can't resolve
169
+ * a specifier from an eval'd context — hence the two-strategy loadCore() below.)
170
+ */
171
+ const evalImport = new Function('specifier', 'return import(specifier);');
172
+ let cachedCore;
173
+ /**
174
+ * Lazily load `@astram/core`'s four auth factory functions — invoked ONLY inside
175
+ * the two async provider factories (i.e. only when `forRoot()` actually composes
176
+ * auth), NEVER at module top-level. This keeps a runtime `require('@astram/core')`
177
+ * out of the guard barrel's load path (see the top-of-file note), so importing
178
+ * `@astram/guard`'s built dist for the enforcement-only path does not touch core.
179
+ *
180
+ * TWO strategies, so it works in BOTH runtimes:
181
+ * 1. A plain dynamic `import('@astram/core')` — the vitest/SWC source path keeps
182
+ * this native, and vitest's resolver maps the workspace package. (In the
183
+ * tsc-built CJS dist this literal is downleveled to a `require`, which throws on
184
+ * the ESM core — caught below.)
185
+ * 2. On failure, the {@link evalImport} `Function`-wrapped native `import()` — the
186
+ * BUILT dist path (Node CJS→ESM interop), which vitest can't use.
187
+ * Cached after the first success.
188
+ */
189
+ async function loadCore() {
190
+ if (cachedCore !== undefined)
191
+ return cachedCore;
192
+ try {
193
+ // Strategy 1 — native in vitest/SWC; a `require` (that may throw) in the CJS dist.
194
+ cachedCore = (await Promise.resolve().then(() => __importStar(require('@astram/core'))));
195
+ }
196
+ catch {
197
+ // Strategy 2 — the built-dist path: a genuine `import()` via the Function shim.
198
+ cachedCore = (await evalImport('@astram/core'));
199
+ }
200
+ return cachedCore;
201
+ }
202
+ // --- Adapter-backed providers (Team A resolver + session adapters) ----------
203
+ /** Argon2id password hasher (⛔ the flagged fix — provide it HERE so the authenticator factory's `inject` resolves). */
204
+ const passwordHasherProvider = {
205
+ provide: argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER,
206
+ useFactory: () => new argon2id_password_hasher_js_1.Argon2idPasswordHasher(),
207
+ };
208
+ /**
209
+ * Credential resolver (the store login checks against).
210
+ *
211
+ * DEFAULT (no consumer override): a `useFactory` that constructs the framework's
212
+ * {@link MariaDbCredentialResolver} injected with the live {@link SHIELD_DB_POOL}
213
+ * — the historical binding, unchanged.
214
+ *
215
+ * OVERRIDE (Phase 1a seam): when the consumer supplies a `credentialResolver`
216
+ * through {@link ShieldModuleOptions.credentialResolver} → {@link AuthModule.forRoot},
217
+ * the token instead binds a plain **value provider** to that instance, so login
218
+ * authenticates against the consumer's OWN store (e.g. a richer users/roles model)
219
+ * WITHOUT editing the framework. The seam swaps the STORE only — the supplied
220
+ * resolver still flows through the SAME composed authenticator (anti-enumeration
221
+ * decoy verify, MFA, no-secret-leak); its `null`/throw contract is unchanged.
222
+ */
223
+ function makeCredentialResolverProvider(override) {
224
+ return override
225
+ ? { provide: tokens_js_1.SHIELD_CREDENTIAL_RESOLVER, useValue: override }
226
+ : {
227
+ provide: tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
228
+ useFactory: (pool) => new mariadb_credential_resolver_js_1.MariaDbCredentialResolver(pool),
229
+ inject: [tokens_js_1.SHIELD_DB_POOL],
230
+ };
231
+ }
232
+ /** Durable session record store (MariaDB adapter, injected with the live pool). */
233
+ const sessionRecordStoreProvider = {
234
+ provide: index_js_1.SHIELD_SESSION_RECORD_STORE,
235
+ useFactory: (pool) => new index_js_1.MariaDbSessionRecordStore(pool),
236
+ inject: [tokens_js_1.SHIELD_DB_POOL],
237
+ };
238
+ /** Hot session store (Redis adapter, injected with the live client). */
239
+ const hotSessionStoreProvider = {
240
+ provide: index_js_1.SHIELD_HOT_SESSION_STORE,
241
+ useFactory: (redis) => new index_js_1.RedisHotSessionStore(redis),
242
+ inject: [tokens_js_1.SHIELD_REDIS],
243
+ };
244
+ /**
245
+ * The request-auth token binder (the flagged-gap fill): binds an opaque access token
246
+ * to its principal claims in Redis, so the enforcement guard can turn a later
247
+ * request's bearer token back into a `Principal`. Provided only under `auth: true`
248
+ * (it needs the live Redis client); exported so the enforcement guard injects it.
249
+ */
250
+ const sessionTokenBinderProvider = {
251
+ provide: tokens_js_2.SHIELD_SESSION_TOKEN_BINDER,
252
+ useFactory: (redis) => new session_token_binder_js_1.SessionTokenBinder(redis),
253
+ inject: [tokens_js_1.SHIELD_REDIS],
254
+ };
255
+ /**
256
+ * The password-login rate limiter (spec §5 / H1) — a Redis-injected
257
+ * {@link AttemptLimiter}, 10 failures / 15-min window, keyed `login:<hint>`. Same
258
+ * live-Redis provider pattern as {@link sessionTokenBinderProvider} (a `useFactory`
259
+ * injecting {@link SHIELD_REDIS}); provided only under `auth: true`. Fail-open on a
260
+ * Redis outage is the limiter's own behavior (never locks out on a blip).
261
+ */
262
+ const loginLimiterProvider = {
263
+ provide: tokens_js_1.SHIELD_LOGIN_LIMITER,
264
+ useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 10, windowMs: 15 * 60 * 1000 }),
265
+ inject: [tokens_js_1.SHIELD_REDIS],
266
+ };
267
+ /**
268
+ * The recovery-code rate limiter (spec §5) — a Redis-injected {@link AttemptLimiter},
269
+ * 5 failures / 15-min window, keyed `recovery:<principalId>` (a lower ceiling than
270
+ * login: recovery codes don't rotate, so they're higher-value). Same live-Redis
271
+ * provider pattern as {@link sessionTokenBinderProvider}; provided only under
272
+ * `auth: true`.
273
+ */
274
+ const recoveryLimiterProvider = {
275
+ provide: tokens_js_1.SHIELD_RECOVERY_LIMITER,
276
+ useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 5, windowMs: 15 * 60 * 1000 }),
277
+ inject: [tokens_js_1.SHIELD_REDIS],
278
+ };
279
+ /**
280
+ * The forgot-password rate limiter (feature #141) — a Redis-injected
281
+ * {@link AttemptLimiter}, keyed BY CLIENT IP (`forgot:ip:<ip>`, 5 per 15-min window)
282
+ * AND, separately, per-hint (`forgot:<hint>`, provided as {@link forgotHintLimiterProvider}).
283
+ * NOTE the "attempt" semantics here differ from login: forgot-password is ALWAYS 204
284
+ * (returning 429 would itself be an enumeration signal), so this limiter counts every
285
+ * forgot REQUEST (a request-rate cap), and once the budget is exceeded the handler
286
+ * SILENTLY skips the email-send work while still returning 204. Same live-Redis
287
+ * provider pattern as {@link loginLimiterProvider}; provided only under `auth: true`.
288
+ * Fail-open on a Redis outage is the limiter's own behavior (never silently drops a
289
+ * legitimate reset email on a blip). Threshold chosen to stop IP-spray without locking
290
+ * out a genuine user who requests a couple of resets.
291
+ */
292
+ const forgotLimiterProvider = {
293
+ provide: tokens_js_1.SHIELD_FORGOT_LIMITER,
294
+ useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 5, windowMs: 15 * 60 * 1000 }),
295
+ inject: [tokens_js_1.SHIELD_REDIS],
296
+ };
297
+ /**
298
+ * The forgot-password PER-HINT rate limiter (feature #141) — a Redis-injected
299
+ * {@link AttemptLimiter}, keyed by the presented hint (`forgot:<hint>`, 3 per 60-min
300
+ * window). This caps how often ANY caller (across IPs) can trigger a reset email for
301
+ * ONE account, so a single victim's inbox can't be email-bombed even from a rotating
302
+ * IP pool. A GENEROUS per-hint ceiling (a real user rarely needs >3 reset emails/hour)
303
+ * with a longer window than the IP cap. Same request-rate-cap semantics as
304
+ * {@link forgotLimiterProvider}: on exceed, SILENTLY skip the send, still 204.
305
+ */
306
+ const forgotHintLimiterProvider = {
307
+ provide: tokens_js_1.SHIELD_FORGOT_HINT_LIMITER,
308
+ useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 3, windowMs: 60 * 60 * 1000 }),
309
+ inject: [tokens_js_1.SHIELD_REDIS],
310
+ };
311
+ /**
312
+ * The reset-password rate limiter (feature #141) — a Redis-injected
313
+ * {@link AttemptLimiter}, keyed by CLIENT IP (`reset:ip:<ip>`, 10 per 15-min window).
314
+ * Reset is token-gated (a 256-bit single-use token), so this is DoS/abuse throttling,
315
+ * NOT anti-brute-force — and unlike forgot it MAY return a generic 429 on lockout (a
316
+ * token-gated endpoint is not enumeration-sensitive). `recordFailure` on a bad/invalid
317
+ * token (the abuse signal), `reset` on a successful reset. Same live-Redis provider
318
+ * pattern as {@link loginLimiterProvider}; provided only under `auth: true`. Fail-open
319
+ * on a Redis outage (a legitimate reset is never blocked by a blip).
320
+ */
321
+ const resetLimiterProvider = {
322
+ provide: tokens_js_1.SHIELD_RESET_LIMITER,
323
+ useFactory: (redis) => new attempt_limiter_js_1.AttemptLimiter(redis, { maxAttempts: 10, windowMs: 15 * 60 * 1000 }),
324
+ inject: [tokens_js_1.SHIELD_REDIS],
325
+ };
326
+ /** Opaque token generator (node:crypto adapter). */
327
+ const tokenGeneratorProvider = {
328
+ provide: index_js_1.SHIELD_TOKEN_GENERATOR,
329
+ useFactory: () => new index_js_1.CryptoTokenGenerator(),
330
+ };
331
+ /**
332
+ * Keyed refresh hasher (HMAC adapter). ⛔ FAIL-CLOSED HMAC-key gate:
333
+ * `assertRefreshHmacKey` THROWS on a blank key, so auth can never compose with an
334
+ * unkeyed refresh-token hasher.
335
+ */
336
+ const refreshHasherProvider = {
337
+ provide: index_js_1.SHIELD_REFRESH_HASHER,
338
+ useFactory: (config) => new index_js_1.Sha256RefreshTokenHasher((0, app_config_js_1.assertRefreshHmacKey)(config.refreshHmacKey)),
339
+ inject: [config_module_js_1.APP_CONFIG],
340
+ };
341
+ /** System clock. */
342
+ const clockProvider = {
343
+ provide: index_js_1.SHIELD_CLOCK,
344
+ useFactory: () => new index_js_1.SystemClock(),
345
+ };
346
+ // --- Composed core engines --------------------------------------------------
347
+ /** The composed SessionAuthority (core) — establish / rotate / revoke. */
348
+ const sessionAuthorityProvider = {
349
+ provide: tokens_js_1.SHIELD_SESSION_AUTHORITY,
350
+ // async: loads the core factory lazily (CJS→ESM, see loadCore()); Nest awaits it.
351
+ useFactory: async (recordStore, hotStore, tokenGenerator, refreshHasher, clock, config) => {
352
+ const { createSessionAuthority } = await loadCore();
353
+ return createSessionAuthority({
354
+ recordStore,
355
+ hotStore,
356
+ tokenGenerator,
357
+ refreshHasher,
358
+ clock,
359
+ lifetimes: config.lifetimes,
360
+ });
361
+ },
362
+ inject: [
363
+ index_js_1.SHIELD_SESSION_RECORD_STORE,
364
+ index_js_1.SHIELD_HOT_SESSION_STORE,
365
+ index_js_1.SHIELD_TOKEN_GENERATOR,
366
+ index_js_1.SHIELD_REFRESH_HASHER,
367
+ index_js_1.SHIELD_CLOCK,
368
+ config_module_js_1.APP_CONFIG,
369
+ ],
370
+ };
371
+ /**
372
+ * The composed Authenticator (core) — password + TOTP factor, anti-enumeration.
373
+ *
374
+ * The `totp` verifier is the Phase-2 SEAM: {@link resolveTotpVerifier} picks the
375
+ * consumer's `totpOverride` (bound under {@link SHIELD_TOTP_VERIFIER_OVERRIDE}) when
376
+ * supplied, else the framework's default `createTotpFactorVerifier({ hmacSha1 })`.
377
+ * The override reaches this async factory via `inject` (not a captured closure) so
378
+ * the default binding stays exactly as before when no override is plugged.
379
+ */
380
+ const authenticatorProvider = {
381
+ provide: tokens_js_1.SHIELD_AUTHENTICATOR,
382
+ // async: loads the core factories lazily (CJS→ESM, see loadCore()); Nest awaits it.
383
+ useFactory: async (hasher, resolver, totpOverride, rootIds) => {
384
+ const { createAuthenticator, createIdentityBroker, createTotpFactorVerifier } = await loadCore();
385
+ const totp = resolveTotpVerifier(totpOverride, createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 }));
386
+ return createAuthenticator({
387
+ hasher,
388
+ resolver,
389
+ // ROOT SAFETY: the ONLY way a login mints a root is the
390
+ // server-side allowlist wired here (the Internal adapter keys the trusted
391
+ // signal off it, never off a claim). Absent → `[]` → default-deny (the
392
+ // historical `createIdentityBroker()` behavior, exactly unchanged).
393
+ identityBroker: createIdentityBroker({ internalRootIds: rootIds ?? [] }),
394
+ factorVerifiers: [totp],
395
+ });
396
+ },
397
+ inject: [
398
+ argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER,
399
+ tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
400
+ tokens_js_1.SHIELD_TOTP_VERIFIER_OVERRIDE,
401
+ tokens_js_1.SHIELD_ROOT_IDS,
402
+ ],
403
+ };
404
+ /**
405
+ * Bind the OPTIONAL login `totp` verifier override (the Phase-2 multi-device seam).
406
+ * Same value-provider pattern as the other seams: the supplied verifier when present,
407
+ * else `null` so the authenticator factory's inject resolves to "no override" → the
408
+ * default RFC-6238 verifier. Always provided so the DI token exists.
409
+ */
410
+ function makeTotpVerifierOverrideProvider(override) {
411
+ return { provide: tokens_js_1.SHIELD_TOTP_VERIFIER_OVERRIDE, useValue: override ?? null };
412
+ }
413
+ /**
414
+ * Bind the OPTIONAL root allowlist (the {@link SHIELD_ROOT_IDS}
415
+ * seam). Same value-provider pattern as the other seams: the supplied ids when present,
416
+ * else `null` so the authenticator factory's inject resolves to "no allowlist" → the
417
+ * broker's default-deny empty set (nobody is a root — historical behavior). Always
418
+ * provided so the DI token exists. See {@link SHIELD_ROOT_IDS} for the security
419
+ * rationale (the flag is set SOLELY from this trusted list, never from a claim).
420
+ */
421
+ function makeRootIdsProvider(rootIds) {
422
+ return { provide: tokens_js_1.SHIELD_ROOT_IDS, useValue: rootIds ?? null };
423
+ }
424
+ /**
425
+ * The core TOTP {@link FactorVerifier} — the SAME verifier the login MFA branch uses
426
+ * (`createTotpFactorVerifier({ hmacSha1 })`), provided app-wide so
427
+ * `POST /account/mfa/{enroll/confirm,disable}` can verify a presented code against the
428
+ * pending/stored secret. Built via {@link loadCore} (the CJS→ESM lazy load, see the
429
+ * file header) so guard's built CJS dist never eagerly `require`s the ESM-only core.
430
+ * Injected pre-built into {@link AccountController}, which cannot import the core
431
+ * factory at its own top level.
432
+ */
433
+ const totpVerifierProvider = {
434
+ provide: tokens_js_1.SHIELD_TOTP_VERIFIER,
435
+ useFactory: async () => {
436
+ const { createTotpFactorVerifier } = await loadCore();
437
+ return createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 });
438
+ },
439
+ };
440
+ /**
441
+ * Bind the OPTIONAL current-user profile resolver. When the consumer supplies one it
442
+ * is a value provider under {@link SHIELD_PROFILE_RESOLVER}; when absent we bind
443
+ * `null` so the `@Optional()` injection in the controller resolves cleanly to
444
+ * "no seam" (→ `/auth/me` returns 501). Always provided so the DI token exists.
445
+ */
446
+ function makeProfileResolverProvider(override) {
447
+ return { provide: tokens_js_1.SHIELD_PROFILE_RESOLVER, useValue: override ?? null };
448
+ }
449
+ /**
450
+ * Bind each OPTIONAL account/credential-surface seam. Same pattern as
451
+ * {@link makeProfileResolverProvider}: a value provider under the seam's token —
452
+ * the supplied impl when present, else `null` so the route's `@Optional()` injection
453
+ * resolves cleanly to "no seam" (→ 501). Always provided so the DI token exists.
454
+ */
455
+ function makeCredentialWriterProvider(override) {
456
+ return { provide: tokens_js_1.SHIELD_CREDENTIAL_WRITER, useValue: override ?? null };
457
+ }
458
+ function makeResetTokenStoreProvider(override) {
459
+ return { provide: tokens_js_1.SHIELD_RESET_TOKEN_STORE, useValue: override ?? null };
460
+ }
461
+ function makeEmailSenderProvider(override) {
462
+ return { provide: tokens_js_1.SHIELD_EMAIL_SENDER, useValue: override ?? null };
463
+ }
464
+ function makeRecoveryCodeStoreProvider(override) {
465
+ return { provide: tokens_js_1.SHIELD_RECOVERY_CODE_STORE, useValue: override ?? null };
466
+ }
467
+ function makeProfileWriterProvider(override) {
468
+ return { provide: tokens_js_1.SHIELD_PROFILE_WRITER, useValue: override ?? null };
469
+ }
470
+ function makeSessionSweeperProvider(override) {
471
+ return { provide: tokens_js_1.SHIELD_SESSION_SWEEPER, useValue: override ?? null };
472
+ }
473
+ function makeMfaDeviceStoreProvider(override) {
474
+ return { provide: tokens_js_1.SHIELD_MFA_DEVICE_STORE, useValue: override ?? null };
475
+ }
476
+ function makeAuditSinkProvider(override) {
477
+ return { provide: tokens_js_1.SHIELD_AUDIT_SINK, useValue: override ?? null };
478
+ }
479
+ /**
480
+ * Bind the OPTIONAL eager session-facts projector (ADR-0011). Same value-provider
481
+ * pattern as the other seams: the supplied impl when present, else `null` so the auth
482
+ * controller's `@Optional()` injection resolves cleanly to "no projector" (→ it omits
483
+ * `cachedFacts` → gate 5 DB-reloads). Always provided so the DI token exists.
484
+ */
485
+ function makeSessionFactsProjectorProvider(override) {
486
+ return { provide: tokens_js_1.SHIELD_SESSION_FACTS_PROJECTOR, useValue: override ?? null };
487
+ }
488
+ /**
489
+ * The reset-link base URL the forgot-password handler builds the emailed link from
490
+ * (`${base}?token=<rawToken>`). A plain string VALUE (not a seam) resolved from the
491
+ * environment (`RESET_LINK_BASE_URL`) with a dev default, so the framework owns the
492
+ * URL composition and {@link SHIELD_EMAIL_SENDER} stays URL-agnostic. Always
493
+ * provided so the `@Optional()` injection resolves.
494
+ */
495
+ const resetLinkBaseUrlProvider = {
496
+ provide: tokens_js_1.SHIELD_RESET_LINK_BASE_URL,
497
+ useValue: process.env.RESET_LINK_BASE_URL ?? 'http://localhost:5173/reset-password',
498
+ };
499
+ /**
500
+ * The auth composition module. Imports {@link PersistenceModule} (the live
501
+ * connections) and provides the adapters + composed engines. Exports the two
502
+ * engines (Team C consumes them) and the resolver token. Opt-in: imported ONLY by
503
+ * an auth-enabled `ShieldModule.forRoot({ auth: true })` — see the file header +
504
+ * DONE.md for the exact gating the integration owner applies.
505
+ */
506
+ let AuthModule = AuthModule_1 = class AuthModule {
507
+ /**
508
+ * Compose the auth surface. `options.credentialResolver`, when supplied, REPLACES
509
+ * the default MariaDb store with the consumer's own (a value provider under
510
+ * {@link SHIELD_CREDENTIAL_RESOLVER}); omitted → the historical default binding,
511
+ * EXACTLY unchanged (zero behavior change for existing consumers).
512
+ */
513
+ static forRoot(options = {}) {
514
+ return {
515
+ module: AuthModule_1,
516
+ imports: [persistence_module_js_1.PersistenceModule.forRoot()],
517
+ // (providers list below adds the profile-resolver seam)
518
+ // Team C's four `@Public()` /auth/* endpoints. Registered here (integration
519
+ // wiring) so the routes exist the moment auth is opted in — the controller
520
+ // injects the two composed engines (below) + PendingMfaStore.
521
+ controllers: [auth_controller_js_1.AuthController, account_controller_js_1.AccountController],
522
+ providers: [
523
+ passwordHasherProvider,
524
+ makeCredentialResolverProvider(options.credentialResolver),
525
+ // The current-user profile seam backing `GET /auth/me` (null when absent).
526
+ makeProfileResolverProvider(options.profileResolver),
527
+ // The account/credential-surface seams (null when absent → route 501).
528
+ makeCredentialWriterProvider(options.credentialWriter),
529
+ makeResetTokenStoreProvider(options.resetTokenStore),
530
+ makeEmailSenderProvider(options.emailSender),
531
+ makeRecoveryCodeStoreProvider(options.recoveryCodeStore),
532
+ makeProfileWriterProvider(options.profileWriter),
533
+ makeSessionSweeperProvider(options.sessionSweeper),
534
+ // The auth-surface audit sink (null when absent → recovery-login audit no-ops).
535
+ makeAuditSinkProvider(options.auditSink),
536
+ // The multi-device MFA store (null when absent → device routes 501).
537
+ makeMfaDeviceStoreProvider(options.mfaDeviceStore),
538
+ // The login totp-verifier override (null when absent → default RFC-6238
539
+ // single-secret verify). Consumed by the authenticator factory.
540
+ makeTotpVerifierOverrideProvider(options.totpVerifier),
541
+ // The root allowlist (null when absent → broker default-deny).
542
+ // Consumed by the authenticator factory (createIdentityBroker). ROOT
543
+ // SAFETY: the ONLY source of the isRoot flag.
544
+ makeRootIdsProvider(options.rootIds),
545
+ // The eager session-facts projector (ADR-0011; null when absent → the auth
546
+ // controller omits cachedFacts → gate 5 DB-reloads). Consumed by AuthController.
547
+ makeSessionFactsProjectorProvider(options.sessionFactsProjector),
548
+ // The reset-link base URL value the forgot-password handler composes into the
549
+ // emailed link (framework-owned URL composition; EmailSender stays dumb).
550
+ resetLinkBaseUrlProvider,
551
+ sessionRecordStoreProvider,
552
+ hotSessionStoreProvider,
553
+ tokenGeneratorProvider,
554
+ refreshHasherProvider,
555
+ clockProvider,
556
+ sessionAuthorityProvider,
557
+ authenticatorProvider,
558
+ // The core TOTP verifier (login MFA + account MFA enroll/disable share it).
559
+ totpVerifierProvider,
560
+ // Team C's server-side, single-use, TTL'd challenge store backing the
561
+ // login→mfa handoff (a plain class provider the controller injects).
562
+ pending_mfa_store_js_1.PendingMfaStore,
563
+ // The request-auth token binder (access-token → principal claims).
564
+ sessionTokenBinderProvider,
565
+ // The anti-brute-force rate limiters (spec §5): login (H1) + recovery, each
566
+ // a Redis-injected AttemptLimiter with its own threshold. Injected into
567
+ // AuthController (@Optional()).
568
+ loginLimiterProvider,
569
+ recoveryLimiterProvider,
570
+ // The forgot/reset-password limiters (feature #141): forgot keyed by client IP
571
+ // + per-hint (request-rate caps → silently skip the send when exceeded, stays
572
+ // 204); reset keyed by client IP (may 429 on lockout — token-gated, not enum-
573
+ // sensitive). Injected into AuthController (@Optional()).
574
+ forgotLimiterProvider,
575
+ forgotHintLimiterProvider,
576
+ resetLimiterProvider,
577
+ ],
578
+ exports: [
579
+ tokens_js_1.SHIELD_AUTHENTICATOR,
580
+ tokens_js_1.SHIELD_SESSION_AUTHORITY,
581
+ tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
582
+ argon2id_password_hasher_js_1.SHIELD_PASSWORD_HASHER,
583
+ // Exported so the (app-wide) enforcement guard can inject it.
584
+ tokens_js_2.SHIELD_SESSION_TOKEN_BINDER,
585
+ // The account/credential-surface seams — exported so the consumer's impls
586
+ // and the account/auth controllers see them app-wide through @Global Shield.
587
+ tokens_js_1.SHIELD_CREDENTIAL_WRITER,
588
+ tokens_js_1.SHIELD_RESET_TOKEN_STORE,
589
+ tokens_js_1.SHIELD_EMAIL_SENDER,
590
+ tokens_js_1.SHIELD_RECOVERY_CODE_STORE,
591
+ tokens_js_1.SHIELD_PROFILE_WRITER,
592
+ tokens_js_1.SHIELD_SESSION_SWEEPER,
593
+ // The auth-surface audit sink (consumed by the /auth/mfa recovery branch).
594
+ tokens_js_1.SHIELD_AUDIT_SINK,
595
+ // The multi-device MFA store (consumed by /account/mfa/devices/*).
596
+ tokens_js_1.SHIELD_MFA_DEVICE_STORE,
597
+ // The reset-link base URL value (consumed by /auth/forgot-password).
598
+ tokens_js_1.SHIELD_RESET_LINK_BASE_URL,
599
+ // The core TOTP verifier (consumed by /account/mfa/{enroll/confirm,disable}).
600
+ tokens_js_1.SHIELD_TOTP_VERIFIER,
601
+ // The eager session-facts projector (consumed by AuthController).
602
+ tokens_js_1.SHIELD_SESSION_FACTS_PROJECTOR,
603
+ ],
604
+ };
605
+ }
606
+ };
607
+ exports.AuthModule = AuthModule;
608
+ exports.AuthModule = AuthModule = AuthModule_1 = __decorate([
609
+ (0, common_1.Module)({})
610
+ ], AuthModule);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":"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"}