@astram/guard 0.8.0 → 0.10.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.
@@ -38,13 +38,14 @@
38
38
  * `DELETE /account/mfa/devices/:id` (code-gated), `POST
39
39
  * /account/mfa/recovery-codes/regenerate` (code-gated).
40
40
  *
41
- * ── NO ORACLE ── a wrong current password is an indistinguishable generic 401
42
- * (same body as no-token). We never reveal whether the principal exists, nor which
43
- * check failed. Passwords/hashes are NEVER logged.
41
+ * ── NO ORACLE ── no-token / bad token is one generic 401. A wrong current password is a
42
+ * 400 (Phase 9 #3; never 401, which clients read as "token expired" and replay), the
43
+ * same for a missing stored hash. Passwords/hashes are NEVER logged.
44
44
  */
45
45
  import type { FactorVerifier, PasswordHasher } from '@astram/core';
46
46
  import type { SessionTokenBinder } from '../request-auth/session-token-binder.js';
47
47
  import type { SessionRestrictionStore } from '../session/session-restriction-store.js';
48
+ import type { AttemptLimiter } from './rate-limit/attempt-limiter.js';
48
49
  import type { CredentialWriter } from './ports/credential-writer.js';
49
50
  import type { MfaDevice, MfaDeviceStore } from './ports/mfa-device-store.js';
50
51
  import type { CurrentUserProfile, ProfileResolver } from './profile-resolver.js';
@@ -62,7 +63,10 @@ export declare class AccountController {
62
63
  private readonly profileWriter?;
63
64
  private readonly mfaDevices?;
64
65
  private readonly sessionRestrictions?;
65
- constructor(binder?: SessionTokenBinder | undefined, hasher?: PasswordHasher | undefined, writer?: (CredentialWriter | null) | undefined, sweeper?: (SessionSweeper | null) | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, totpVerifier?: (FactorVerifier | null) | undefined, profileResolver?: (ProfileResolver | null) | undefined, profileWriter?: (ProfileWriter | null) | undefined, mfaDevices?: (MfaDeviceStore | null) | undefined, sessionRestrictions?: (SessionRestrictionStore | null) | undefined);
66
+ private readonly loginTotpVerifier?;
67
+ private readonly mfaLimiter?;
68
+ private readonly loginLimiter?;
69
+ constructor(binder?: SessionTokenBinder | undefined, hasher?: PasswordHasher | undefined, writer?: (CredentialWriter | null) | undefined, sweeper?: (SessionSweeper | null) | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, totpVerifier?: (FactorVerifier | null) | undefined, profileResolver?: (ProfileResolver | null) | undefined, profileWriter?: (ProfileWriter | null) | undefined, mfaDevices?: (MfaDeviceStore | null) | undefined, sessionRestrictions?: (SessionRestrictionStore | null) | undefined, loginTotpVerifier?: (FactorVerifier | null) | undefined, mfaLimiter?: (AttemptLimiter | null) | undefined, loginLimiter?: (AttemptLimiter | null) | undefined);
66
70
  /**
67
71
  * Resolve a human-readable otpauth account LABEL for the caller (email, else display
68
72
  * name) via the profile resolver. Best-effort: no resolver / null profile / a thrown
@@ -111,8 +115,16 @@ export declare class AccountController {
111
115
  * • no/invalid token → 401 (generic)
112
116
  * • newPassword shorter than the minimum → 422 `{ error: 'weak_password' }`
113
117
  * • writer/hasher seam absent → 501 `{ error: 'not_available' }`
114
- * • wrong current password → 401 (generic, no write)
115
- * • success → 204 (no body)
118
+ * • wrong current password → 400 `{ error: 'invalid_current_password' }`
119
+ * (no write; counted; also for no stored hash)
120
+ * • account login budget exhausted → 429 `{ error: 'too_many_requests' }`
121
+ * (not verified, no write)
122
+ * • attempt limiter (Redis) unreachable → 503 `{ error: 'authentication_unavailable' }`
123
+ * (fail closed, not verified, no write)
124
+ *
125
+ * 401 is reserved for a missing/invalid session (Phase 9 #3): the client's refresh
126
+ * wrapper refreshes and replays on a bearer 401, so a credential mismatch must not use it.
127
+ * • success → 204 (no body; counter reset)
116
128
  */
117
129
  changePassword(authorization: string | undefined, body: {
118
130
  currentPassword?: string;
@@ -156,10 +168,25 @@ export declare class AccountController {
156
168
  private replaceRecoveryCodes;
157
169
  /**
158
170
  * Verify a presented `code` against ANY of the caller's CONFIRMED device secrets
159
- * (TOTP), returning true on the first match. Used by remove/regenerate where the
160
- * proof may come from any live device (not a specific one). NEVER logs the code.
171
+ * (TOTP) through the replay-guarded login verifier: the secrets are bundled
172
+ * newline-joined (the `OrTotpVerifier` contract) and an accepted code is claimed in
173
+ * Redis, so it cannot be reused on this or any other MFA path inside the window. A
174
+ * Redis error on the claim → 503 (fail closed; never an unguarded accept, never a
175
+ * fall-through to the recovery-code check). Guarded verifier not wired → `false`.
176
+ * NEVER logs the code.
161
177
  */
162
178
  private verifyAgainstAnyDevice;
179
+ /**
180
+ * The shared second-factor proof for the code-gated account routes (Phase 8 #1),
181
+ * mirroring `/auth/mfa`: the attempt is counted against `mfa:pid:<principalId>` BEFORE
182
+ * any TOTP or recovery-code verification (Phase 9 #10: atomic increment-first, so
183
+ * parallel guesses cannot all pass; a locked caller never triggers the Argon2 recovery
184
+ * scan) → a TOTP from any confirmed device, else a recovery code (consumed) → a failed
185
+ * proof keeps its count (400), a good one resets the counter. Locked → 429. A Redis
186
+ * error on the gate fails closed (503), as does the TOTP replay claim; an attempt that
187
+ * ended in such an error (no verdict) is given back.
188
+ */
189
+ private requireMfaProof;
163
190
  /**
164
191
  * `GET /account/mfa/devices` — list the caller's CONFIRMED authenticator devices.
165
192
  * `mfaEnabled` reflects whether any confirmed device exists. Pending (unconfirmed)
@@ -225,7 +252,7 @@ export declare class AccountController {
225
252
  * and additionally wipes the account's recovery codes.
226
253
  *
227
254
  * Outcomes: 401; store absent → 501; wrong code → 400 (no remove); not found/owned →
228
- * 404; success → 204.
255
+ * 404; MFA budget exhausted → 429; limiter/replay guard unreachable → 503; success → 204.
229
256
  */
230
257
  removeDevice(authorization: string | undefined, id: string, body: {
231
258
  code?: string;
@@ -236,6 +263,7 @@ export declare class AccountController {
236
263
  * — a TOTP from any confirmed device OR an existing recovery code.
237
264
  *
238
265
  * Outcomes: 401; store/recovery/hasher absent → 501; MFA off → 400; wrong code → 400;
266
+ * MFA budget exhausted → 429; limiter/replay guard unreachable → 503;
239
267
  * success → 200 `{ recoveryCodes }`.
240
268
  */
241
269
  regenerateRecoveryCodes(authorization: string | undefined, body: {
@@ -1 +1 @@
1
- {"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"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"}
@@ -39,9 +39,9 @@
39
39
  * `DELETE /account/mfa/devices/:id` (code-gated), `POST
40
40
  * /account/mfa/recovery-codes/regenerate` (code-gated).
41
41
  *
42
- * ── NO ORACLE ── a wrong current password is an indistinguishable generic 401
43
- * (same body as no-token). We never reveal whether the principal exists, nor which
44
- * check failed. Passwords/hashes are NEVER logged.
42
+ * ── NO ORACLE ── no-token / bad token is one generic 401. A wrong current password is a
43
+ * 400 (Phase 9 #3; never 401, which clients read as "token expired" and replay), the
44
+ * same for a missing stored hash. Passwords/hashes are NEVER logged.
45
45
  */
46
46
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
47
47
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -62,6 +62,7 @@ const classification_decorator_js_1 = require("../enforcement/classification.dec
62
62
  const request_principal_js_1 = require("../request-auth/request-principal.js");
63
63
  const tokens_js_1 = require("../request-auth/tokens.js");
64
64
  const tokens_js_2 = require("./tokens.js");
65
+ const canonical_hint_js_1 = require("./rate-limit/canonical-hint.js");
65
66
  const totp_enrollment_js_1 = require("./totp-enrollment.js");
66
67
  /** Max length of a device name (matches the `md_name VARCHAR(120)` column). */
67
68
  const MAX_DEVICE_NAME_LEN = 120;
@@ -82,14 +83,22 @@ const TOTP_ISSUER = 'Astram';
82
83
  */
83
84
  const FALLBACK_OTPAUTH_LABEL = 'account';
84
85
  /**
85
- * The SINGLE generic 401 for EVERY unauthenticated/bad-credential path here (no
86
- * token, no binder, resolve→null, wrong current password). Deliberately
87
- * non-distinguishing — never leaks whether the principal exists or which check
88
- * failed.
86
+ * The SINGLE generic 401 for EVERY unauthenticated path here (no token, no binder,
87
+ * resolve→null). Deliberately non-distinguishing — never leaks whether the principal
88
+ * exists. Never used for a credential mismatch by an authenticated caller (Phase 9 #3):
89
+ * clients treat a bearer 401 as an expired token and refresh + replay.
89
90
  */
90
91
  function unauthorized() {
91
92
  throw new common_1.HttpException({ error: 'unauthorized' }, common_1.HttpStatus.UNAUTHORIZED);
92
93
  }
94
+ /**
95
+ * The 400 for a wrong (or unset) current password on change-password (Phase 9 #3). The
96
+ * caller is authenticated and acting on their own account, so naming the field is safe;
97
+ * a missing stored hash gives the same answer (no "has no password" oracle).
98
+ */
99
+ function invalidCurrentPassword() {
100
+ throw new common_1.HttpException({ error: 'invalid_current_password' }, common_1.HttpStatus.BAD_REQUEST);
101
+ }
93
102
  /** The honest 501 when a required seam is unplugged (fail-closed, no mutation). */
94
103
  function notAvailable() {
95
104
  throw new common_1.HttpException({ error: 'not_available' }, common_1.HttpStatus.NOT_IMPLEMENTED);
@@ -103,6 +112,38 @@ function notAvailable() {
103
112
  function badRequest() {
104
113
  throw new common_1.HttpException({ error: 'invalid_request' }, common_1.HttpStatus.BAD_REQUEST);
105
114
  }
115
+ /**
116
+ * The 429 for a caller whose proof budget is exhausted (Phase 8 #1). These routes are
117
+ * self-scoped and already authenticated, so the throttle signal reveals nothing about
118
+ * another account; a 401 here would read as "session expired" to the client's refresh logic.
119
+ */
120
+ function tooManyRequests() {
121
+ throw new common_1.HttpException({ error: 'too_many_requests' }, common_1.HttpStatus.TOO_MANY_REQUESTS);
122
+ }
123
+ /**
124
+ * The retryable 503 when the replay guard or the attempt limiter (Redis) cannot answer:
125
+ * fail closed, no mutation.
126
+ */
127
+ function retryableUnavailable() {
128
+ throw new common_1.HttpException({ error: 'authentication_unavailable' }, common_1.HttpStatus.SERVICE_UNAVAILABLE);
129
+ }
130
+ /**
131
+ * Phase 9 #10 — count this attempt BEFORE verifying anything (atomic increment-first).
132
+ * Over budget → 429; limiter unreachable → 503 (fail closed). No limiter wired → no-op.
133
+ */
134
+ async function consumeAttempt(limiter, key) {
135
+ if (limiter == null)
136
+ return;
137
+ let allowed;
138
+ try {
139
+ ({ allowed } = await limiter.consume(key));
140
+ }
141
+ catch {
142
+ retryableUnavailable();
143
+ }
144
+ if (!allowed)
145
+ tooManyRequests();
146
+ }
106
147
  /**
107
148
  * The 422 for a semantically invalid profile edit — an empty change (`no_changes`)
108
149
  * or a malformed email (`invalid_email`). Distinct from {@link badRequest}: this is
@@ -123,7 +164,10 @@ let AccountController = class AccountController {
123
164
  profileWriter;
124
165
  mfaDevices;
125
166
  sessionRestrictions;
126
- constructor(binder, hasher, writer, sweeper, recoveryCodes, totpVerifier, profileResolver, profileWriter, mfaDevices, sessionRestrictions) {
167
+ loginTotpVerifier;
168
+ mfaLimiter;
169
+ loginLimiter;
170
+ constructor(binder, hasher, writer, sweeper, recoveryCodes, totpVerifier, profileResolver, profileWriter, mfaDevices, sessionRestrictions, loginTotpVerifier, mfaLimiter, loginLimiter) {
127
171
  this.binder = binder;
128
172
  this.hasher = hasher;
129
173
  this.writer = writer;
@@ -134,6 +178,9 @@ let AccountController = class AccountController {
134
178
  this.profileWriter = profileWriter;
135
179
  this.mfaDevices = mfaDevices;
136
180
  this.sessionRestrictions = sessionRestrictions;
181
+ this.loginTotpVerifier = loginTotpVerifier;
182
+ this.mfaLimiter = mfaLimiter;
183
+ this.loginLimiter = loginLimiter;
137
184
  }
138
185
  /**
139
186
  * Resolve a human-readable otpauth account LABEL for the caller (email, else display
@@ -220,8 +267,16 @@ let AccountController = class AccountController {
220
267
  * • no/invalid token → 401 (generic)
221
268
  * • newPassword shorter than the minimum → 422 `{ error: 'weak_password' }`
222
269
  * • writer/hasher seam absent → 501 `{ error: 'not_available' }`
223
- * • wrong current password → 401 (generic, no write)
224
- * • success → 204 (no body)
270
+ * • wrong current password → 400 `{ error: 'invalid_current_password' }`
271
+ * (no write; counted; also for no stored hash)
272
+ * • account login budget exhausted → 429 `{ error: 'too_many_requests' }`
273
+ * (not verified, no write)
274
+ * • attempt limiter (Redis) unreachable → 503 `{ error: 'authentication_unavailable' }`
275
+ * (fail closed, not verified, no write)
276
+ *
277
+ * 401 is reserved for a missing/invalid session (Phase 9 #3): the client's refresh
278
+ * wrapper refreshes and replays on a bearer 401, so a credential mismatch must not use it.
279
+ * • success → 204 (no body; counter reset)
225
280
  */
226
281
  async changePassword(authorization, body) {
227
282
  const claims = await this.requireClaims(authorization);
@@ -240,14 +295,38 @@ let AccountController = class AccountController {
240
295
  }
241
296
  const writer = this.writer;
242
297
  const hasher = this.hasher;
298
+ // Phase 8 #8: the current-password check spends the SAME per-account budget as
299
+ // password login (`login:pid:<principalId>`, shared counter): checked BEFORE the
300
+ // verify (a locked account never reaches the hasher), a wrong current password records
301
+ // a failure, and a success resets it — exactly as a completed login does. Locked → 429
302
+ // (Phase 9 #3), like the MFA account routes: the caller is authenticated, so the
303
+ // throttle reveals nothing about another account, and a 401 would make the client
304
+ // refresh and replay the request.
305
+ //
306
+ // Phase 9 #10: the attempt is counted FIRST (atomic), so parallel guesses cannot all
307
+ // slip past a read-only check; a wrong password simply keeps its count. A Redis error
308
+ // fails closed (503).
309
+ const loginKey = (0, canonical_hint_js_1.loginHintKey)('', claims.id);
310
+ await consumeAttempt(this.loginLimiter, loginKey);
243
311
  // Verify the current password: read the stored hash BY PRINCIPAL ID via the writer
244
312
  // seam's `getPasswordHash` (change-password holds the principal id from the token,
245
313
  // whereas CredentialResolver keys by identityHint). A missing hash or a mismatch is
246
- // the SAME generic 401 (no oracle), and no write happens.
247
- const stored = await writer.getPasswordHash(claims.id);
248
- if (stored === null || !(await hasher.verify(stored, currentPassword))) {
249
- unauthorized();
314
+ // the SAME 400 (no oracle), and no write happens. NOT 401 (Phase 9 #3): the session is
315
+ // valid, and the client's refresh wrapper treats a bearer 401 as an expired token —
316
+ // refresh + replay, which counted every typo twice against the shared login budget.
317
+ let matches;
318
+ try {
319
+ const stored = await writer.getPasswordHash(claims.id);
320
+ matches = stored !== null && (await hasher.verify(stored, currentPassword));
321
+ }
322
+ catch (err) {
323
+ // No verdict (store/hasher fault): give the attempt back, then surface the error.
324
+ await this.loginLimiter?.refund(loginKey);
325
+ throw err;
250
326
  }
327
+ if (!matches)
328
+ invalidCurrentPassword(); // the consumed attempt stays counted
329
+ await this.loginLimiter?.reset(loginKey);
251
330
  const newHash = await hasher.hash(newPassword);
252
331
  await writer.setPassword(claims.id, newHash);
253
332
  // Revoke the caller's OTHER sessions (keep the current one live). Best-effort:
@@ -339,16 +418,56 @@ let AccountController = class AccountController {
339
418
  }
340
419
  /**
341
420
  * Verify a presented `code` against ANY of the caller's CONFIRMED device secrets
342
- * (TOTP), returning true on the first match. Used by remove/regenerate where the
343
- * proof may come from any live device (not a specific one). NEVER logs the code.
421
+ * (TOTP) through the replay-guarded login verifier: the secrets are bundled
422
+ * newline-joined (the `OrTotpVerifier` contract) and an accepted code is claimed in
423
+ * Redis, so it cannot be reused on this or any other MFA path inside the window. A
424
+ * Redis error on the claim → 503 (fail closed; never an unguarded accept, never a
425
+ * fall-through to the recovery-code check). Guarded verifier not wired → `false`.
426
+ * NEVER logs the code.
344
427
  */
345
428
  async verifyAgainstAnyDevice(store, principalId, code) {
429
+ if (this.loginTotpVerifier === undefined || this.loginTotpVerifier === null)
430
+ return false;
346
431
  const secrets = await store.listConfirmedSecrets(principalId);
347
- for (const secret of secrets) {
348
- if (await this.verifyTotp(secret, code))
349
- return true;
432
+ if (secrets.length === 0)
433
+ return false;
434
+ try {
435
+ const verdict = await this.loginTotpVerifier.verify({ factor: 'totp', payload: { code } }, secrets.join('\n'));
436
+ return verdict.satisfied;
437
+ }
438
+ catch {
439
+ retryableUnavailable();
350
440
  }
351
- return false;
441
+ }
442
+ /**
443
+ * The shared second-factor proof for the code-gated account routes (Phase 8 #1),
444
+ * mirroring `/auth/mfa`: the attempt is counted against `mfa:pid:<principalId>` BEFORE
445
+ * any TOTP or recovery-code verification (Phase 9 #10: atomic increment-first, so
446
+ * parallel guesses cannot all pass; a locked caller never triggers the Argon2 recovery
447
+ * scan) → a TOTP from any confirmed device, else a recovery code (consumed) → a failed
448
+ * proof keeps its count (400), a good one resets the counter. Locked → 429. A Redis
449
+ * error on the gate fails closed (503), as does the TOTP replay claim; an attempt that
450
+ * ended in such an error (no verdict) is given back.
451
+ */
452
+ async requireMfaProof(store, principalId, code) {
453
+ const mfaKey = `mfa:pid:${principalId}`;
454
+ await consumeAttempt(this.mfaLimiter, mfaKey);
455
+ let proven;
456
+ try {
457
+ const byTotp = await this.verifyAgainstAnyDevice(store, principalId, code);
458
+ proven =
459
+ byTotp ||
460
+ (this.recoveryCodes !== undefined &&
461
+ this.recoveryCodes !== null &&
462
+ (await this.recoveryCodes.consume(principalId, code)));
463
+ }
464
+ catch (err) {
465
+ await this.mfaLimiter?.refund(mfaKey);
466
+ throw err;
467
+ }
468
+ if (!proven)
469
+ badRequest(); // the consumed attempt stays counted
470
+ await this.mfaLimiter?.reset(mfaKey);
352
471
  }
353
472
  /**
354
473
  * `GET /account/mfa/devices` — list the caller's CONFIRMED authenticator devices.
@@ -490,7 +609,7 @@ let AccountController = class AccountController {
490
609
  * and additionally wipes the account's recovery codes.
491
610
  *
492
611
  * Outcomes: 401; store absent → 501; wrong code → 400 (no remove); not found/owned →
493
- * 404; success → 204.
612
+ * 404; MFA budget exhausted → 429; limiter/replay guard unreachable → 503; success → 204.
494
613
  */
495
614
  async removeDevice(authorization, id, body) {
496
615
  const claims = await this.requireClaims(authorization);
@@ -504,14 +623,9 @@ let AccountController = class AccountController {
504
623
  const store = this.mfaDevices;
505
624
  const code = typeof body?.code === 'string' ? body.code : '';
506
625
  // Proof BEFORE the delete: a TOTP from any confirmed device (incl. the one being
507
- // removed — legit for the last-device disable) OR a valid recovery code.
508
- const byTotp = await this.verifyAgainstAnyDevice(store, claims.id, code);
509
- const byRecovery = !byTotp &&
510
- this.recoveryCodes !== undefined &&
511
- this.recoveryCodes !== null &&
512
- (await this.recoveryCodes.consume(claims.id, code));
513
- if (!byTotp && !byRecovery)
514
- badRequest();
626
+ // removed — legit for the last-device disable) OR a valid recovery code. Rate-limited
627
+ // and replay-guarded like `/auth/mfa` (Phase 8 #1).
628
+ await this.requireMfaProof(store, claims.id, code);
515
629
  const removed = await store.remove(claims.id, id);
516
630
  if (!removed) {
517
631
  throw new common_1.HttpException({ error: 'not_found' }, common_1.HttpStatus.NOT_FOUND);
@@ -529,6 +643,7 @@ let AccountController = class AccountController {
529
643
  * — a TOTP from any confirmed device OR an existing recovery code.
530
644
  *
531
645
  * Outcomes: 401; store/recovery/hasher absent → 501; MFA off → 400; wrong code → 400;
646
+ * MFA budget exhausted → 429; limiter/replay guard unreachable → 503;
532
647
  * success → 200 `{ recoveryCodes }`.
533
648
  */
534
649
  async regenerateRecoveryCodes(authorization, body) {
@@ -551,11 +666,9 @@ let AccountController = class AccountController {
551
666
  // MFA must be on — else there's nothing to protect / no code source → generic 400.
552
667
  if ((await store.countConfirmed(claims.id)) === 0)
553
668
  badRequest();
554
- // Proof: a TOTP from any confirmed device OR an existing recovery code.
555
- const byTotp = await this.verifyAgainstAnyDevice(store, claims.id, code);
556
- const byRecovery = !byTotp && (await recoveryStore.consume(claims.id, code));
557
- if (!byTotp && !byRecovery)
558
- badRequest();
669
+ // Proof: a TOTP from any confirmed device OR an existing recovery code (rate-limited
670
+ // and replay-guarded like `/auth/mfa`, Phase 8 #1).
671
+ await this.requireMfaProof(store, claims.id, code);
559
672
  const recoveryCodes = await this.replaceRecoveryCodes(claims.id, recoveryStore, hasher);
560
673
  return { recoveryCodes };
561
674
  }
@@ -664,7 +777,13 @@ exports.AccountController = AccountController = __decorate([
664
777
  __param(8, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_DEVICE_STORE)),
665
778
  __param(9, (0, common_1.Optional)()),
666
779
  __param(9, (0, common_1.Inject)(tokens_js_2.SHIELD_SESSION_RESTRICTIONS)),
667
- __metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object, Object, Object, Object, Object])
780
+ __param(10, (0, common_1.Optional)()),
781
+ __param(10, (0, common_1.Inject)(tokens_js_2.SHIELD_LOGIN_TOTP_VERIFIER)),
782
+ __param(11, (0, common_1.Optional)()),
783
+ __param(11, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_LIMITER)),
784
+ __param(12, (0, common_1.Optional)()),
785
+ __param(12, (0, common_1.Inject)(tokens_js_2.SHIELD_LOGIN_LIMITER)),
786
+ __metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object])
668
787
  ], AccountController);
669
788
  /**
670
789
  * A deliberately-minimal email shape check (non-empty, a single `@`, a `.` in the
@@ -379,11 +379,12 @@ export declare class AuthController {
379
379
  * {@link MfaStepUp} (same `OrTotpVerifier` + replay guard as the authenticator, principal
380
380
  * minted by the identity broker).
381
381
  *
382
- * - `mfa:pid:<principalId>` is checked BEFORE verifying: locked → generic 401 and the
383
- * step-up is never consulted.
384
- * - a rejected code records a failure; the edge where the count first reaches the
385
- * threshold audits `auth.mfa.locked` ONCE (no notify — pre-auth, see recovery lockout).
386
- * - a transient outage → 503, never counted.
382
+ * - the attempt is counted against `mfa:pid:<principalId>` BEFORE verifying (Phase 9
383
+ * #10, atomic increment-first): over budget → generic 401 and the step-up is never
384
+ * consulted; limiter unreachable → 503 (fail closed).
385
+ * - a rejected code stays counted; the attempt whose count equals the threshold audits
386
+ * `auth.mfa.locked` ONCE (no notify — pre-auth, see recovery lockout).
387
+ * - a transient outage → 503, the attempt is given back (never counted).
387
388
  * - success → establish + bind, then reset the TOTP counter AND the login counter (the
388
389
  * login counter is reset only here, once authentication fully succeeded).
389
390
  */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}