@spfn/auth 0.3.0-beta.21 → 0.3.0-beta.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/errors.d.ts CHANGED
@@ -686,6 +686,91 @@ declare class OAuth2GrantNotFoundError extends NotFoundError {
686
686
  details?: Record<string, any>;
687
687
  });
688
688
  }
689
+ /**
690
+ * MFA Already Enrolled Error (409)
691
+ *
692
+ * Thrown when `totp/enroll` is called on an account whose TOTP is already
693
+ * confirmed. Replacing a working second factor is `disable` followed by a fresh
694
+ * enrolment, both step-up gated — an enrol that quietly overwrote a confirmed
695
+ * secret would be a way to swap someone's authenticator for your own.
696
+ */
697
+ declare class MfaAlreadyEnrolledError extends ConflictError {
698
+ constructor(data?: {
699
+ message?: string;
700
+ details?: Record<string, any>;
701
+ });
702
+ }
703
+ /**
704
+ * MFA Not Enrolled Error (400)
705
+ *
706
+ * Thrown when a call needs an enrolment that is not there: `totp/confirm` with
707
+ * no pending secret — including the row its own five failed attempts deleted —
708
+ * or `recovery/regenerate` on an account with no second factor. `disable` is
709
+ * deliberately not one of them; it answers 204 either way, because "make sure
710
+ * MFA is off" has already succeeded.
711
+ */
712
+ declare class MfaNotEnrolledError extends ValidationError {
713
+ constructor(data?: {
714
+ message?: string;
715
+ details?: Record<string, any>;
716
+ });
717
+ }
718
+ /**
719
+ * MFA Verification Failed Error (401)
720
+ *
721
+ * Thrown when a submitted code does not verify: a wrong or stale TOTP, a code
722
+ * from a step already spent, a recovery code that is used, from an older
723
+ * generation or another account's, or an assertion from a passkey the owner
724
+ * never marked as a second factor.
725
+ *
726
+ * One body for all of them. Which one applies describes state the caller is
727
+ * guessing at, and the remedy — look at the authenticator again — is the same.
728
+ */
729
+ declare class MfaVerificationFailedError extends UnauthorizedError {
730
+ constructor(data?: {
731
+ message?: string;
732
+ details?: Record<string, any>;
733
+ });
734
+ }
735
+ /**
736
+ * Step Up Required Error (403)
737
+ *
738
+ * Thrown when an enrolled account asks for a sensitive change from a device
739
+ * whose second factor was last verified longer ago than the step-up window. A
740
+ * stolen session alone therefore cannot change a password, sign every device
741
+ * out, or take the second factor off.
742
+ *
743
+ * 403 and not 401, on the same reasoning as `RecentAuthenticationRequiredError`,
744
+ * which it sits beside: a 401 on an authenticated route is what a web client
745
+ * reads as "the session is gone", so it would sign the user out instead of
746
+ * asking for a code. Clients branch on `code` to send the user to
747
+ * `POST /_auth/mfa/step-up` and retry.
748
+ */
749
+ declare class StepUpRequiredError extends ForbiddenError {
750
+ readonly code = "STEP_UP_REQUIRED";
751
+ constructor(data?: {
752
+ message?: string;
753
+ details?: Record<string, any>;
754
+ });
755
+ }
756
+ /**
757
+ * MFA Config Error (500)
758
+ *
759
+ * Thrown when the at-rest keyring cannot serve a second factor:
760
+ * `SPFN_AUTH_TOKEN_ENCRYPTION_KEYS` is unset, or a stored secret names a key id
761
+ * that has been dropped from it.
762
+ *
763
+ * Deliberately not the 401 a wrong code gets. The two have nothing in common: a
764
+ * wrong code is one person looking at the wrong line of their authenticator,
765
+ * and a broken keyring is every enrolled user locked out at once by a deploy.
766
+ * An operator has to be able to tell them apart from the response alone.
767
+ */
768
+ declare class MfaConfigError extends HttpError {
769
+ constructor(data: {
770
+ message: string;
771
+ details?: Record<string, any>;
772
+ });
773
+ }
689
774
 
690
775
  type authErrors_AccountAlreadyExistsError = AccountAlreadyExistsError;
691
776
  declare const authErrors_AccountAlreadyExistsError: typeof AccountAlreadyExistsError;
@@ -737,6 +822,14 @@ type authErrors_KeyNotFoundError = KeyNotFoundError;
737
822
  declare const authErrors_KeyNotFoundError: typeof KeyNotFoundError;
738
823
  type authErrors_LastRecoveryCredentialError = LastRecoveryCredentialError;
739
824
  declare const authErrors_LastRecoveryCredentialError: typeof LastRecoveryCredentialError;
825
+ type authErrors_MfaAlreadyEnrolledError = MfaAlreadyEnrolledError;
826
+ declare const authErrors_MfaAlreadyEnrolledError: typeof MfaAlreadyEnrolledError;
827
+ type authErrors_MfaConfigError = MfaConfigError;
828
+ declare const authErrors_MfaConfigError: typeof MfaConfigError;
829
+ type authErrors_MfaNotEnrolledError = MfaNotEnrolledError;
830
+ declare const authErrors_MfaNotEnrolledError: typeof MfaNotEnrolledError;
831
+ type authErrors_MfaVerificationFailedError = MfaVerificationFailedError;
832
+ declare const authErrors_MfaVerificationFailedError: typeof MfaVerificationFailedError;
740
833
  type authErrors_NativeSignInUnsupportedError = NativeSignInUnsupportedError;
741
834
  declare const authErrors_NativeSignInUnsupportedError: typeof NativeSignInUnsupportedError;
742
835
  type authErrors_NonceKeyBindingError = NonceKeyBindingError;
@@ -771,6 +864,8 @@ type authErrors_ReservedUsernameError = ReservedUsernameError;
771
864
  declare const authErrors_ReservedUsernameError: typeof ReservedUsernameError;
772
865
  type authErrors_RevokeAllLinkError = RevokeAllLinkError;
773
866
  declare const authErrors_RevokeAllLinkError: typeof RevokeAllLinkError;
867
+ type authErrors_StepUpRequiredError = StepUpRequiredError;
868
+ declare const authErrors_StepUpRequiredError: typeof StepUpRequiredError;
774
869
  type authErrors_TokenExpiredError = TokenExpiredError;
775
870
  declare const authErrors_TokenExpiredError: typeof TokenExpiredError;
776
871
  type authErrors_UnverifiedEmailLinkError = UnverifiedEmailLinkError;
@@ -782,7 +877,7 @@ declare const authErrors_VerificationTokenPurposeMismatchError: typeof Verificat
782
877
  type authErrors_VerificationTokenTargetMismatchError = VerificationTokenTargetMismatchError;
783
878
  declare const authErrors_VerificationTokenTargetMismatchError: typeof VerificationTokenTargetMismatchError;
784
879
  declare namespace authErrors {
785
- export { authErrors_AccountAlreadyExistsError as AccountAlreadyExistsError, authErrors_AccountDisabledError as AccountDisabledError, authErrors_AccountPendingDeletionError as AccountPendingDeletionError, authErrors_DeletionAlreadyRequestedError as DeletionAlreadyRequestedError, authErrors_DeletionNotRequestedError as DeletionNotRequestedError, authErrors_DeviceAuthAlreadyHandledError as DeviceAuthAlreadyHandledError, authErrors_DeviceAuthDeniedError as DeviceAuthDeniedError, authErrors_DeviceAuthExpiredError as DeviceAuthExpiredError, authErrors_DeviceAuthNotFoundError as DeviceAuthNotFoundError, authErrors_ImmediateDeletionNotAllowedError as ImmediateDeletionNotAllowedError, authErrors_InsufficientPermissionsError as InsufficientPermissionsError, authErrors_InsufficientRoleError as InsufficientRoleError, authErrors_InvalidCredentialsError as InvalidCredentialsError, authErrors_InvalidKeyFingerprintError as InvalidKeyFingerprintError, authErrors_InvalidSignupLinkError as InvalidSignupLinkError, authErrors_InvalidSignupSetupSessionError as InvalidSignupSetupSessionError, authErrors_InvalidSocialTokenError as InvalidSocialTokenError, authErrors_InvalidTokenError as InvalidTokenError, authErrors_InvalidVerificationCodeError as InvalidVerificationCodeError, authErrors_InvalidVerificationTokenError as InvalidVerificationTokenError, authErrors_KeyAlgorithmMismatchError as KeyAlgorithmMismatchError, authErrors_KeyExpiredError as KeyExpiredError, authErrors_KeyIdAlreadyRegisteredError as KeyIdAlreadyRegisteredError, authErrors_KeyNotFoundError as KeyNotFoundError, authErrors_LastRecoveryCredentialError as LastRecoveryCredentialError, authErrors_NativeSignInUnsupportedError as NativeSignInUnsupportedError, authErrors_NonceKeyBindingError as NonceKeyBindingError, authErrors_OAuth2AuthorizeRedirectError as OAuth2AuthorizeRedirectError, authErrors_OAuth2GrantNotFoundError as OAuth2GrantNotFoundError, authErrors_OAuth2RedirectUriMismatchError as OAuth2RedirectUriMismatchError, authErrors_OAuth2UnknownClientError as OAuth2UnknownClientError, authErrors_PasskeyAlreadyRegisteredError as PasskeyAlreadyRegisteredError, authErrors_PasskeyChallengeError as PasskeyChallengeError, authErrors_PasskeyConfigError as PasskeyConfigError, authErrors_PasskeyNotFoundError as PasskeyNotFoundError, authErrors_PasskeyVerificationError as PasskeyVerificationError, authErrors_PasswordResetLinkError as PasswordResetLinkError, authErrors_PasswordResetSessionError as PasswordResetSessionError, authErrors_RecentAuthenticationRequiredError as RecentAuthenticationRequiredError, authErrors_RegistrationRejectedError as RegistrationRejectedError, authErrors_ReservedUsernameError as ReservedUsernameError, authErrors_RevokeAllLinkError as RevokeAllLinkError, authErrors_TokenExpiredError as TokenExpiredError, authErrors_UnverifiedEmailLinkError as UnverifiedEmailLinkError, authErrors_UsernameAlreadyTakenError as UsernameAlreadyTakenError, authErrors_VerificationTokenPurposeMismatchError as VerificationTokenPurposeMismatchError, authErrors_VerificationTokenTargetMismatchError as VerificationTokenTargetMismatchError };
880
+ export { authErrors_AccountAlreadyExistsError as AccountAlreadyExistsError, authErrors_AccountDisabledError as AccountDisabledError, authErrors_AccountPendingDeletionError as AccountPendingDeletionError, authErrors_DeletionAlreadyRequestedError as DeletionAlreadyRequestedError, authErrors_DeletionNotRequestedError as DeletionNotRequestedError, authErrors_DeviceAuthAlreadyHandledError as DeviceAuthAlreadyHandledError, authErrors_DeviceAuthDeniedError as DeviceAuthDeniedError, authErrors_DeviceAuthExpiredError as DeviceAuthExpiredError, authErrors_DeviceAuthNotFoundError as DeviceAuthNotFoundError, authErrors_ImmediateDeletionNotAllowedError as ImmediateDeletionNotAllowedError, authErrors_InsufficientPermissionsError as InsufficientPermissionsError, authErrors_InsufficientRoleError as InsufficientRoleError, authErrors_InvalidCredentialsError as InvalidCredentialsError, authErrors_InvalidKeyFingerprintError as InvalidKeyFingerprintError, authErrors_InvalidSignupLinkError as InvalidSignupLinkError, authErrors_InvalidSignupSetupSessionError as InvalidSignupSetupSessionError, authErrors_InvalidSocialTokenError as InvalidSocialTokenError, authErrors_InvalidTokenError as InvalidTokenError, authErrors_InvalidVerificationCodeError as InvalidVerificationCodeError, authErrors_InvalidVerificationTokenError as InvalidVerificationTokenError, authErrors_KeyAlgorithmMismatchError as KeyAlgorithmMismatchError, authErrors_KeyExpiredError as KeyExpiredError, authErrors_KeyIdAlreadyRegisteredError as KeyIdAlreadyRegisteredError, authErrors_KeyNotFoundError as KeyNotFoundError, authErrors_LastRecoveryCredentialError as LastRecoveryCredentialError, authErrors_MfaAlreadyEnrolledError as MfaAlreadyEnrolledError, authErrors_MfaConfigError as MfaConfigError, authErrors_MfaNotEnrolledError as MfaNotEnrolledError, authErrors_MfaVerificationFailedError as MfaVerificationFailedError, authErrors_NativeSignInUnsupportedError as NativeSignInUnsupportedError, authErrors_NonceKeyBindingError as NonceKeyBindingError, authErrors_OAuth2AuthorizeRedirectError as OAuth2AuthorizeRedirectError, authErrors_OAuth2GrantNotFoundError as OAuth2GrantNotFoundError, authErrors_OAuth2RedirectUriMismatchError as OAuth2RedirectUriMismatchError, authErrors_OAuth2UnknownClientError as OAuth2UnknownClientError, authErrors_PasskeyAlreadyRegisteredError as PasskeyAlreadyRegisteredError, authErrors_PasskeyChallengeError as PasskeyChallengeError, authErrors_PasskeyConfigError as PasskeyConfigError, authErrors_PasskeyNotFoundError as PasskeyNotFoundError, authErrors_PasskeyVerificationError as PasskeyVerificationError, authErrors_PasswordResetLinkError as PasswordResetLinkError, authErrors_PasswordResetSessionError as PasswordResetSessionError, authErrors_RecentAuthenticationRequiredError as RecentAuthenticationRequiredError, authErrors_RegistrationRejectedError as RegistrationRejectedError, authErrors_ReservedUsernameError as ReservedUsernameError, authErrors_RevokeAllLinkError as RevokeAllLinkError, authErrors_StepUpRequiredError as StepUpRequiredError, authErrors_TokenExpiredError as TokenExpiredError, authErrors_UnverifiedEmailLinkError as UnverifiedEmailLinkError, authErrors_UsernameAlreadyTakenError as UsernameAlreadyTakenError, authErrors_VerificationTokenPurposeMismatchError as VerificationTokenPurposeMismatchError, authErrors_VerificationTokenTargetMismatchError as VerificationTokenTargetMismatchError };
786
881
  }
787
882
 
788
883
  /**
@@ -791,4 +886,4 @@ declare namespace authErrors {
791
886
 
792
887
  declare const authErrorRegistry: ErrorRegistry;
793
888
 
794
- export { AccountAlreadyExistsError, AccountDisabledError, AccountPendingDeletionError, authErrors as AuthError, DeletionAlreadyRequestedError, DeletionNotRequestedError, DeviceAuthAlreadyHandledError, DeviceAuthDeniedError, DeviceAuthExpiredError, DeviceAuthNotFoundError, ImmediateDeletionNotAllowedError, InsufficientPermissionsError, InsufficientRoleError, InvalidCredentialsError, InvalidKeyFingerprintError, InvalidSignupLinkError, InvalidSignupSetupSessionError, InvalidSocialTokenError, InvalidTokenError, InvalidVerificationCodeError, InvalidVerificationTokenError, KeyAlgorithmMismatchError, KeyExpiredError, KeyIdAlreadyRegisteredError, KeyNotFoundError, LastRecoveryCredentialError, NativeSignInUnsupportedError, NonceKeyBindingError, OAuth2AuthorizeRedirectError, OAuth2GrantNotFoundError, OAuth2RedirectUriMismatchError, OAuth2UnknownClientError, PasskeyAlreadyRegisteredError, PasskeyChallengeError, PasskeyConfigError, PasskeyNotFoundError, PasskeyVerificationError, PasswordResetLinkError, PasswordResetSessionError, RecentAuthenticationRequiredError, RegistrationRejectedError, ReservedUsernameError, RevokeAllLinkError, TokenExpiredError, UnverifiedEmailLinkError, UsernameAlreadyTakenError, VerificationTokenPurposeMismatchError, VerificationTokenTargetMismatchError, authErrorRegistry };
889
+ export { AccountAlreadyExistsError, AccountDisabledError, AccountPendingDeletionError, authErrors as AuthError, DeletionAlreadyRequestedError, DeletionNotRequestedError, DeviceAuthAlreadyHandledError, DeviceAuthDeniedError, DeviceAuthExpiredError, DeviceAuthNotFoundError, ImmediateDeletionNotAllowedError, InsufficientPermissionsError, InsufficientRoleError, InvalidCredentialsError, InvalidKeyFingerprintError, InvalidSignupLinkError, InvalidSignupSetupSessionError, InvalidSocialTokenError, InvalidTokenError, InvalidVerificationCodeError, InvalidVerificationTokenError, KeyAlgorithmMismatchError, KeyExpiredError, KeyIdAlreadyRegisteredError, KeyNotFoundError, LastRecoveryCredentialError, MfaAlreadyEnrolledError, MfaConfigError, MfaNotEnrolledError, MfaVerificationFailedError, NativeSignInUnsupportedError, NonceKeyBindingError, OAuth2AuthorizeRedirectError, OAuth2GrantNotFoundError, OAuth2RedirectUriMismatchError, OAuth2UnknownClientError, PasskeyAlreadyRegisteredError, PasskeyChallengeError, PasskeyConfigError, PasskeyNotFoundError, PasskeyVerificationError, PasswordResetLinkError, PasswordResetSessionError, RecentAuthenticationRequiredError, RegistrationRejectedError, ReservedUsernameError, RevokeAllLinkError, StepUpRequiredError, TokenExpiredError, UnverifiedEmailLinkError, UsernameAlreadyTakenError, VerificationTokenPurposeMismatchError, VerificationTokenTargetMismatchError, authErrorRegistry };
package/dist/errors.js CHANGED
@@ -35,6 +35,10 @@ __export(auth_errors_exports, {
35
35
  KeyIdAlreadyRegisteredError: () => KeyIdAlreadyRegisteredError,
36
36
  KeyNotFoundError: () => KeyNotFoundError,
37
37
  LastRecoveryCredentialError: () => LastRecoveryCredentialError,
38
+ MfaAlreadyEnrolledError: () => MfaAlreadyEnrolledError,
39
+ MfaConfigError: () => MfaConfigError,
40
+ MfaNotEnrolledError: () => MfaNotEnrolledError,
41
+ MfaVerificationFailedError: () => MfaVerificationFailedError,
38
42
  NativeSignInUnsupportedError: () => NativeSignInUnsupportedError,
39
43
  NonceKeyBindingError: () => NonceKeyBindingError,
40
44
  OAuth2AuthorizeRedirectError: () => OAuth2AuthorizeRedirectError,
@@ -52,6 +56,7 @@ __export(auth_errors_exports, {
52
56
  RegistrationRejectedError: () => RegistrationRejectedError,
53
57
  ReservedUsernameError: () => ReservedUsernameError,
54
58
  RevokeAllLinkError: () => RevokeAllLinkError,
59
+ StepUpRequiredError: () => StepUpRequiredError,
55
60
  TokenExpiredError: () => TokenExpiredError,
56
61
  UnverifiedEmailLinkError: () => UnverifiedEmailLinkError,
57
62
  UsernameAlreadyTakenError: () => UsernameAlreadyTakenError,
@@ -461,6 +466,53 @@ var OAuth2GrantNotFoundError = class extends NotFoundError {
461
466
  this.name = "OAuth2GrantNotFoundError";
462
467
  }
463
468
  };
469
+ var MfaAlreadyEnrolledError = class extends ConflictError {
470
+ constructor(data = {}) {
471
+ super({
472
+ message: data.message || "A second factor is already enrolled on this account",
473
+ details: data.details
474
+ });
475
+ this.name = "MfaAlreadyEnrolledError";
476
+ }
477
+ };
478
+ var MfaNotEnrolledError = class extends ValidationError {
479
+ constructor(data = {}) {
480
+ super({
481
+ message: data.message || "No second-factor enrolment is in progress on this account",
482
+ details: data.details
483
+ });
484
+ this.name = "MfaNotEnrolledError";
485
+ }
486
+ };
487
+ var MfaVerificationFailedError = class extends UnauthorizedError {
488
+ constructor(data = {}) {
489
+ super({
490
+ message: data.message || "That code did not verify",
491
+ details: data.details
492
+ });
493
+ this.name = "MfaVerificationFailedError";
494
+ }
495
+ };
496
+ var StepUpRequiredError = class extends ForbiddenError {
497
+ code = "STEP_UP_REQUIRED";
498
+ constructor(data = {}) {
499
+ super({
500
+ message: data.message || "Confirm your second factor before making this change.",
501
+ details: data.details
502
+ });
503
+ this.name = "StepUpRequiredError";
504
+ }
505
+ };
506
+ var MfaConfigError = class extends HttpError {
507
+ constructor(data) {
508
+ super({
509
+ message: data.message,
510
+ statusCode: 500,
511
+ details: data.details
512
+ });
513
+ this.name = "MfaConfigError";
514
+ }
515
+ };
464
516
 
465
517
  // src/errors/index.ts
466
518
  var authErrorRegistry = new ErrorRegistry();
@@ -511,7 +563,12 @@ authErrorRegistry.append([
511
563
  OAuth2UnknownClientError,
512
564
  OAuth2RedirectUriMismatchError,
513
565
  OAuth2AuthorizeRedirectError,
514
- OAuth2GrantNotFoundError
566
+ OAuth2GrantNotFoundError,
567
+ MfaAlreadyEnrolledError,
568
+ MfaNotEnrolledError,
569
+ MfaVerificationFailedError,
570
+ StepUpRequiredError,
571
+ MfaConfigError
515
572
  ]);
516
573
  export {
517
574
  AccountAlreadyExistsError,
@@ -540,6 +597,10 @@ export {
540
597
  KeyIdAlreadyRegisteredError,
541
598
  KeyNotFoundError,
542
599
  LastRecoveryCredentialError,
600
+ MfaAlreadyEnrolledError,
601
+ MfaConfigError,
602
+ MfaNotEnrolledError,
603
+ MfaVerificationFailedError,
543
604
  NativeSignInUnsupportedError,
544
605
  NonceKeyBindingError,
545
606
  OAuth2AuthorizeRedirectError,
@@ -557,6 +618,7 @@ export {
557
618
  RegistrationRejectedError,
558
619
  ReservedUsernameError,
559
620
  RevokeAllLinkError,
621
+ StepUpRequiredError,
560
622
  TokenExpiredError,
561
623
  UnverifiedEmailLinkError,
562
624
  UsernameAlreadyTakenError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/index.ts","../src/errors/auth-errors.ts"],"sourcesContent":["/**\n * Auth Error Exports\n */\n\nimport { ErrorRegistry } from '@spfn/core/errors';\n\nimport {\n InvalidCredentialsError,\n InvalidTokenError,\n InvalidSocialTokenError,\n TokenExpiredError,\n KeyExpiredError,\n AccountDisabledError,\n AccountPendingDeletionError,\n DeletionAlreadyRequestedError,\n DeletionNotRequestedError,\n ImmediateDeletionNotAllowedError,\n AccountAlreadyExistsError,\n RegistrationRejectedError,\n ReservedUsernameError,\n UsernameAlreadyTakenError,\n InvalidVerificationCodeError,\n InvalidVerificationTokenError,\n InvalidKeyFingerprintError,\n KeyAlgorithmMismatchError,\n NonceKeyBindingError,\n NativeSignInUnsupportedError,\n UnverifiedEmailLinkError,\n InvalidSignupLinkError,\n InvalidSignupSetupSessionError,\n PasswordResetLinkError,\n PasswordResetSessionError,\n KeyNotFoundError,\n KeyIdAlreadyRegisteredError,\n RevokeAllLinkError,\n DeviceAuthNotFoundError,\n DeviceAuthExpiredError,\n DeviceAuthAlreadyHandledError,\n DeviceAuthDeniedError,\n VerificationTokenPurposeMismatchError,\n VerificationTokenTargetMismatchError,\n InsufficientPermissionsError,\n InsufficientRoleError,\n PasskeyChallengeError,\n PasskeyVerificationError,\n PasskeyNotFoundError,\n PasskeyAlreadyRegisteredError,\n RecentAuthenticationRequiredError,\n LastRecoveryCredentialError,\n PasskeyConfigError,\n OAuth2UnknownClientError,\n OAuth2RedirectUriMismatchError,\n OAuth2AuthorizeRedirectError,\n OAuth2GrantNotFoundError,\n} from './auth-errors';\n\nexport {\n InvalidCredentialsError,\n InvalidTokenError,\n InvalidSocialTokenError,\n TokenExpiredError,\n KeyExpiredError,\n AccountDisabledError,\n AccountPendingDeletionError,\n DeletionAlreadyRequestedError,\n DeletionNotRequestedError,\n ImmediateDeletionNotAllowedError,\n AccountAlreadyExistsError,\n RegistrationRejectedError,\n ReservedUsernameError,\n UsernameAlreadyTakenError,\n InvalidVerificationCodeError,\n InvalidVerificationTokenError,\n InvalidKeyFingerprintError,\n KeyAlgorithmMismatchError,\n NonceKeyBindingError,\n NativeSignInUnsupportedError,\n UnverifiedEmailLinkError,\n InvalidSignupLinkError,\n InvalidSignupSetupSessionError,\n PasswordResetLinkError,\n PasswordResetSessionError,\n KeyNotFoundError,\n KeyIdAlreadyRegisteredError,\n RevokeAllLinkError,\n DeviceAuthNotFoundError,\n DeviceAuthExpiredError,\n DeviceAuthAlreadyHandledError,\n DeviceAuthDeniedError,\n VerificationTokenPurposeMismatchError,\n VerificationTokenTargetMismatchError,\n InsufficientPermissionsError,\n InsufficientRoleError,\n PasskeyChallengeError,\n PasskeyVerificationError,\n PasskeyNotFoundError,\n PasskeyAlreadyRegisteredError,\n RecentAuthenticationRequiredError,\n LastRecoveryCredentialError,\n PasskeyConfigError,\n OAuth2UnknownClientError,\n OAuth2RedirectUriMismatchError,\n OAuth2AuthorizeRedirectError,\n OAuth2GrantNotFoundError,\n} from './auth-errors';\n\nexport const authErrorRegistry = new ErrorRegistry();\nauthErrorRegistry.append([\n InvalidCredentialsError,\n InvalidTokenError,\n InvalidSocialTokenError,\n TokenExpiredError,\n KeyExpiredError,\n AccountDisabledError,\n AccountPendingDeletionError,\n DeletionAlreadyRequestedError,\n DeletionNotRequestedError,\n ImmediateDeletionNotAllowedError,\n AccountAlreadyExistsError,\n RegistrationRejectedError,\n ReservedUsernameError,\n UsernameAlreadyTakenError,\n InvalidVerificationCodeError,\n InvalidVerificationTokenError,\n InvalidKeyFingerprintError,\n KeyAlgorithmMismatchError,\n NonceKeyBindingError,\n NativeSignInUnsupportedError,\n UnverifiedEmailLinkError,\n InvalidSignupLinkError,\n InvalidSignupSetupSessionError,\n PasswordResetLinkError,\n PasswordResetSessionError,\n KeyNotFoundError,\n KeyIdAlreadyRegisteredError,\n RevokeAllLinkError,\n DeviceAuthNotFoundError,\n DeviceAuthExpiredError,\n DeviceAuthAlreadyHandledError,\n DeviceAuthDeniedError,\n VerificationTokenPurposeMismatchError,\n VerificationTokenTargetMismatchError,\n InsufficientPermissionsError,\n InsufficientRoleError,\n PasskeyChallengeError,\n PasskeyVerificationError,\n PasskeyNotFoundError,\n PasskeyAlreadyRegisteredError,\n RecentAuthenticationRequiredError,\n LastRecoveryCredentialError,\n PasskeyConfigError,\n OAuth2UnknownClientError,\n OAuth2RedirectUriMismatchError,\n OAuth2AuthorizeRedirectError,\n OAuth2GrantNotFoundError,\n]);\n\nexport * as AuthError from './auth-errors';\n","/**\n * Authentication & Authorization Error Classes\n *\n * Custom error classes for auth-specific scenarios\n */\n\nimport {\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n NotFoundError,\n HttpError,\n} from '@spfn/core/errors';\n\n/**\n * Invalid Credentials Error (401)\n *\n * Thrown when login credentials are incorrect\n */\nexport class InvalidCredentialsError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid credentials', details: data.details });\n this.name = 'InvalidCredentialsError';\n }\n}\n\n/**\n * Invalid Token Error (401)\n *\n * Thrown when authentication token is invalid or malformed\n */\nexport class InvalidTokenError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid authentication token', details: data.details });\n this.name = 'InvalidTokenError';\n }\n}\n\n/**\n * Invalid Social Token Error (401)\n *\n * Thrown when a social provider id_token fails verification\n * (bad signature, wrong issuer/audience, expired, or nonce mismatch).\n */\nexport class InvalidSocialTokenError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid social id_token', details: data.details });\n this.name = 'InvalidSocialTokenError';\n }\n}\n\n/**\n * Token Expired Error (401)\n *\n * Thrown when authentication token has expired\n */\nexport class TokenExpiredError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Authentication token has expired', details: data.details });\n this.name = 'TokenExpiredError';\n }\n}\n\n/**\n * Key Expired Error (401)\n *\n * Thrown when public key has expired\n */\nexport class KeyExpiredError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Public key has expired', details: data.details });\n this.name = 'KeyExpiredError';\n }\n}\n\n/**\n * Account Disabled Error (403)\n *\n * Thrown when user account is disabled or inactive\n */\nexport class AccountDisabledError extends ForbiddenError\n{\n constructor(data: { status?: string; message?: string; details?: Record<string, any> } = {})\n {\n const status = data.status || 'disabled';\n super({\n message: data.message || `Account is ${status}`,\n details: { status, ...data.details },\n });\n this.name = 'AccountDisabledError';\n }\n}\n\n/**\n * Account Pending Deletion Error (403)\n *\n * Thrown on login (password/OAuth/authenticate) when the account is within its\n * deletion grace period. Carries `purgeScheduledAt` so the client can offer a\n * recovery flow instead of a generic \"disabled\" message.\n */\nexport class AccountPendingDeletionError extends ForbiddenError\n{\n constructor(data: { purgeScheduledAt?: string; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Account is scheduled for deletion',\n details: { status: 'pending_deletion', purgeScheduledAt: data.purgeScheduledAt, ...data.details },\n });\n this.name = 'AccountPendingDeletionError';\n }\n}\n\n/**\n * Deletion Already Requested Error (409)\n *\n * Thrown when requesting deletion for an account that already has a pending\n * deletion request (or has already been purged).\n */\nexport class DeletionAlreadyRequestedError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Account deletion has already been requested', details: data.details });\n this.name = 'DeletionAlreadyRequestedError';\n }\n}\n\n/**\n * Deletion Not Requested Error (404)\n *\n * Thrown when trying to cancel/purge a deletion for an account that has no\n * pending deletion request.\n */\nexport class DeletionNotRequestedError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'No pending account deletion request found', details: data.details });\n this.name = 'DeletionNotRequestedError';\n }\n}\n\n/**\n * Immediate Deletion Not Allowed Error (403)\n *\n * Thrown when a self-service caller requests `immediate: true` but the server\n * has not enabled `deletion.allowSelfImmediate`.\n */\nexport class ImmediateDeletionNotAllowedError extends ForbiddenError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Immediate self-service deletion is not enabled', details: data.details });\n this.name = 'ImmediateDeletionNotAllowedError';\n }\n}\n\n/**\n * Account Already Exists Error (409)\n *\n * Thrown when trying to register with existing email/phone\n */\nexport class AccountAlreadyExistsError extends ConflictError\n{\n constructor(data: { identifier?: string; identifierType?: 'email' | 'phone'; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Account already exists',\n details: {\n identifier: data.identifier,\n identifierType: data.identifierType,\n ...data.details,\n },\n });\n this.name = 'AccountAlreadyExistsError';\n }\n}\n\n/**\n * Registration Rejected Error (403)\n *\n * Thrown by the app-injected beforeRegister hook to reject a registration\n * (age gate, domain restriction, block list, ...)\n */\nexport class RegistrationRejectedError extends ForbiddenError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Registration rejected', details: data.details });\n this.name = 'RegistrationRejectedError';\n }\n}\n\n/**\n * Invalid Verification Code Error (400)\n *\n * Thrown when verification code is invalid, expired, or already used\n */\nexport class InvalidVerificationCodeError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid verification code', details: data.details });\n this.name = 'InvalidVerificationCodeError';\n }\n}\n\n/**\n * Invalid Verification Token Error (400)\n *\n * Thrown when verification token is invalid or expired\n */\nexport class InvalidVerificationTokenError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid or expired verification token', details: data.details });\n this.name = 'InvalidVerificationTokenError';\n }\n}\n\n/**\n * Key ID Already Registered Error (409)\n *\n * Thrown when a sign-in submits a keyId that is already taken — the client's own\n * revoked keyId, or a keyId belonging to another user. `keyId` is unique across\n * all users, so either case would collide on insert.\n *\n * The same error covers both cases on purpose: a distinguishable response would\n * let a caller probe whether an arbitrary keyId exists. Revoked stays revoked —\n * the client must generate a fresh keyId and retry.\n */\nexport class KeyIdAlreadyRegisteredError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This keyId is already registered. Generate a new keyId and retry.',\n details: data.details,\n });\n this.name = 'KeyIdAlreadyRegisteredError';\n }\n}\n\n/**\n * Invalid Key Fingerprint Error (400)\n *\n * Thrown when public key fingerprint doesn't match the public key\n */\nexport class InvalidKeyFingerprintError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid key fingerprint', details: data.details });\n this.name = 'InvalidKeyFingerprintError';\n }\n}\n\n/**\n * Key Algorithm Mismatch Error (400)\n *\n * Thrown when the submitted public key's SPKI type is not the one its declared\n * algorithm needs — a P-256 EC key declared RS256, an RSA key declared ES256, a\n * curve other than P-256 declared ES256, or bytes that are no SPKI key at all.\n *\n * The algorithm is stored beside the key and read back at proof verification;\n * nothing re-derives it from the key material. So a mismatch accepted here\n * surfaces only after the device believes it is enrolled, on every request it\n * then makes. It is refused at registration instead, wherever key material is\n * stored: register, login, rotate, invitation acceptance and device start.\n */\nexport class KeyAlgorithmMismatchError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Public key type does not match the declared algorithm',\n details: data.details,\n });\n this.name = 'KeyAlgorithmMismatchError';\n }\n}\n\n/**\n * Key Not Found Error (404)\n *\n * Thrown when a key operation names a keyId the caller does not own. It says\n * nothing about whether that keyId exists on another account — the repository\n * scopes every lookup by userId, so the answer is only ever \"not yours\".\n */\nexport class KeyNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Key not found', details: data.details });\n this.name = 'KeyNotFoundError';\n }\n}\n\n/**\n * Revoke-All Link Error (404)\n *\n * Thrown when a signed sign-out-everywhere link cannot be acted on: unknown,\n * expired, already spent, superseded by a newer one, issued against a key\n * generation that has since moved, or belonging to an account that is not\n * active.\n *\n * One error for every one of those, and the same body for each. Telling an\n * expired link from an unknown one would tell whoever is holding a random value\n * that it named a real outstanding link, and the sibling link flows refuse the\n * same way for the same reason. The specific cause is logged.\n *\n * 404 rather than the 401 the password-reset link answers with: there is no\n * credential here to have been wrong. The address the mail went to is the proof,\n * and what the caller presented either names an outstanding link or names\n * nothing.\n */\nexport class RevokeAllLinkError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This sign-out link is no longer valid. Request a new one.',\n details: data.details,\n });\n this.name = 'RevokeAllLinkError';\n }\n}\n\n/**\n * Device Auth Not Found Error (404)\n *\n * Thrown when a device-code operation names a code the server cannot act on: one\n * that was never issued, and one whose record has already been consumed.\n *\n * Those two are answered identically on purpose. A consumed record is a login\n * that finished, and saying so would tell whoever holds the code that it was\n * real — which is the difference between guessing at random and knowing a guess\n * landed. Every route that accepts a code is rate limited for the same reason.\n */\nexport class DeviceAuthNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Device authorization not found', details: data.details });\n this.name = 'DeviceAuthNotFoundError';\n }\n}\n\n/**\n * Device Auth Expired Error (400)\n *\n * Thrown when a device-code operation names a record whose TTL has run out,\n * whatever state it is in. The waiting device starts again; the approver is told\n * the code on the other screen is stale.\n *\n * 400 rather than 401: on the approve and deny routes the caller's own session is\n * fine, and answering 401 would send a signed-in user to a login screen over a\n * code that simply sat too long.\n */\nexport class DeviceAuthExpiredError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This device code has expired. Start again on the other device.',\n details: data.details,\n });\n this.name = 'DeviceAuthExpiredError';\n }\n}\n\n/**\n * Device Auth Already Handled Error (409)\n *\n * Thrown when an approve, deny or info call names a record that has already been\n * approved or denied. A decision on a device is made once — a second approval\n * would let one code be answered twice, and re-approving a record the owner\n * denied would undo the refusal.\n *\n * This is also what the loser of two concurrent approvals sees, since the\n * transition names the state it moves from and only one call can match it.\n */\nexport class DeviceAuthAlreadyHandledError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This device request has already been answered',\n details: data.details,\n });\n this.name = 'DeviceAuthAlreadyHandledError';\n }\n}\n\n/**\n * Device Auth Denied Error (403)\n *\n * Thrown when the waiting device polls a record its owner refused. Distinct from\n * a pending answer, and distinct from a code that does not exist: the device\n * asked a person and the person said no, so it should stop polling and say so\n * rather than time out looking like a network fault.\n */\nexport class DeviceAuthDeniedError extends ForbiddenError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This device request was denied',\n details: data.details,\n });\n this.name = 'DeviceAuthDeniedError';\n }\n}\n\n/**\n * Nonce Key Binding Error (400)\n *\n * Thrown when a native id_token sign-in submits a nonce that is not the public\n * key's fingerprint. The nonce is what the provider echoed back inside the\n * id_token, so tying it to the key is what proves the id_token and the key came\n * from the same device — see the native section of the README.\n */\nexport class NonceKeyBindingError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'nonce must be the fingerprint of the submitted public key',\n details: data.details,\n });\n this.name = 'NonceKeyBindingError';\n }\n}\n\n/**\n * Native Sign-In Unsupported Error (400)\n *\n * Thrown when a provider is asked for native id_token sign-in and has no\n * implementation for it — a server configuration fact, not something the user\n * did. A client reading this hides that provider's native button instead of\n * asking the user to try again.\n *\n * Split out of ValidationError because the other native-enrollment refusal\n * (linking to an account whose email the provider never verified) needs a\n * different response from the app, and one code cannot ask for two.\n */\nexport class NativeSignInUnsupportedError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This provider does not support native id_token sign-in.',\n details: data.details,\n });\n this.name = 'NativeSignInUnsupportedError';\n }\n}\n\n/**\n * Invalid Signup Link Error (400)\n *\n * Thrown when an emailed signup confirmation link is unknown, expired, already\n * consumed, or superseded by a newer request for the same address.\n *\n * One error for all four states, on purpose. Distinguishing \"expired\" from\n * \"unknown\" tells a caller holding a random token whether it named a real\n * pending signup, which is exactly the enumeration the request step avoids. The\n * specific reason is logged.\n */\nexport class InvalidSignupLinkError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This signup link is no longer valid. Request a new one.',\n details: data.details,\n });\n this.name = 'InvalidSignupLinkError';\n }\n}\n\n/**\n * Invalid Signup Setup Session Error (401)\n *\n * Thrown when the password-setup session backing a verified-email signup is\n * missing, unknown, expired, superseded or already used.\n *\n * One error for every one of those, on purpose: telling a caller which of them\n * applies tells them whether an address is mid-signup, which is the same\n * enumeration the request step is careful not to leak.\n */\nexport class InvalidSignupSetupSessionError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Password setup session is invalid or has expired. Start the signup again.',\n details: data.details,\n });\n this.name = 'InvalidSignupSetupSessionError';\n }\n}\n\n/**\n * Password Reset Link Error (401)\n *\n * Thrown when an emailed password reset link is unknown, expired, already\n * consumed, superseded by a newer request, or belongs to an account that is no\n * longer active.\n *\n * One error for every one of those, on purpose. Distinguishing \"expired\" from\n * \"unknown\" tells a caller holding a random token whether it named a real\n * pending reset, which is exactly the enumeration the request step avoids. The\n * specific reason is logged.\n */\nexport class PasswordResetLinkError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This password reset link is no longer valid. Request a new one.',\n details: data.details,\n });\n this.name = 'PasswordResetLinkError';\n }\n}\n\n/**\n * Password Reset Session Error (401)\n *\n * Thrown when the password-setup session backing a reset is missing, unknown,\n * expired, superseded or already used.\n *\n * One error for every one of those, for the same reason the link error is one\n * error: which of them applies tells a caller whether an account is mid-reset,\n * and that is the enumeration the request step is careful not to leak.\n */\nexport class PasswordResetSessionError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Password reset session is invalid or has expired. Request a new link.',\n details: data.details,\n });\n this.name = 'PasswordResetSessionError';\n }\n}\n\n/**\n * Unverified Email Link Error (400)\n *\n * Thrown when a social identity carries an email that already belongs to an\n * account, but the provider never verified it. Linking on an unverified email\n * is account takeover, so the refusal stands and the user is sent to a path\n * that proves the address.\n *\n * This says an account exists for that address. It is not a leak introduced\n * here: the message this replaces already stated the same fact in prose, and\n * the paths that must not disclose account existence (password login, deletion\n * re-auth, verification issuance) answer uniformly and are untouched.\n */\nexport class UnverifiedEmailLinkError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message\n || 'Cannot link to existing account with unverified email. Please verify your email with the provider first.',\n details: data.details,\n });\n this.name = 'UnverifiedEmailLinkError';\n }\n}\n\n/**\n * Verification Token Purpose Mismatch Error (400)\n *\n * Thrown when verification token purpose doesn't match expected purpose\n */\nexport class VerificationTokenPurposeMismatchError extends ValidationError\n{\n constructor(data: { expected?: string; actual?: string; message?: string; details?: Record<string, any> } = {})\n {\n const expected = data.expected || 'unknown';\n const actual = data.actual || 'unknown';\n super({\n message: data.message || `Verification token is for ${actual}, but ${expected} was expected`,\n details: { expected, actual, ...data.details },\n });\n this.name = 'VerificationTokenPurposeMismatchError';\n }\n}\n\n/**\n * Verification Token Target Mismatch Error (400)\n *\n * Thrown when verification token target doesn't match provided email/phone\n */\nexport class VerificationTokenTargetMismatchError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Verification token does not match provided email/phone',\n details: data.details,\n });\n this.name = 'VerificationTokenTargetMismatchError';\n }\n}\n\n/**\n * Reserved Username Error (400)\n *\n * Thrown when trying to use a reserved/prohibited username\n */\nexport class ReservedUsernameError extends ValidationError\n{\n constructor(data: { username?: string; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This username is reserved',\n details: { username: data.username, ...data.details },\n });\n this.name = 'ReservedUsernameError';\n }\n}\n\n/**\n * Username Already Taken Error (409)\n *\n * Thrown when trying to set a username that is already in use\n */\nexport class UsernameAlreadyTakenError extends ConflictError\n{\n constructor(data: { username?: string; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Username is already taken',\n details: { username: data.username, ...data.details },\n });\n this.name = 'UsernameAlreadyTakenError';\n }\n}\n\n/**\n * Insufficient Permissions Error (403)\n *\n * Thrown when user lacks required permissions for the operation\n */\nexport class InsufficientPermissionsError extends ForbiddenError\n{\n constructor(data: { requiredPermissions?: string[]; message?: string; details?: Record<string, any> } = {})\n {\n const requiredPermissions = data.requiredPermissions || [];\n super({\n message: data.message || `Missing required permissions: ${requiredPermissions.join(', ')}`,\n details: { requiredPermissions, ...data.details },\n });\n this.name = 'InsufficientPermissionsError';\n }\n}\n\n/**\n * Insufficient Role Error (403)\n *\n * Thrown when user lacks required role for the operation\n */\nexport class InsufficientRoleError extends ForbiddenError\n{\n constructor(data: { requiredRoles?: string[]; message?: string; details?: Record<string, any> } = {})\n {\n const requiredRoles = data.requiredRoles || [];\n super({\n message: data.message || `Required roles: ${requiredRoles.join(', ')}`,\n details: { requiredRoles, ...data.details },\n });\n this.name = 'InsufficientRoleError';\n }\n}\n\n/**\n * Passkey Challenge Error (401)\n *\n * Thrown when the challenge a WebAuthn ceremony presents is unknown, expired,\n * already spent, minted for the other ceremony, or minted for another account.\n *\n * One error for all five, on purpose. Telling a caller which applies tells them\n * whether a challenge they did not mint exists and what it was for, and the\n * remedy is the same in every case: start the ceremony again.\n */\nexport class PasskeyChallengeError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This passkey challenge is no longer valid. Try again.',\n details: data.details,\n });\n this.name = 'PasskeyChallengeError';\n }\n}\n\n/**\n * Passkey Verification Error (401)\n *\n * Thrown when an assertion or attestation does not verify: wrong origin, wrong\n * rpId, a bad signature, a regressed signature counter — or, on login, a\n * credential that is unknown or has been revoked.\n *\n * Those last two share this error with the cryptographic failures deliberately.\n * A distinct \"no such passkey\" would answer, to anyone holding a credential id,\n * whether it is enrolled here — and a revoked credential answering differently\n * from an unknown one would say the account once had it.\n */\nexport class PasskeyVerificationError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Passkey verification failed.',\n details: data.details,\n });\n this.name = 'PasskeyVerificationError';\n }\n}\n\n/**\n * Passkey Not Found Error (404)\n *\n * Thrown when a management operation names a passkey the caller does not own,\n * or one already revoked. Every lookup is owner-scoped, so the answer is only\n * ever \"not yours\" and says nothing about other accounts.\n */\nexport class PasskeyNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Passkey not found',\n details: data.details,\n });\n this.name = 'PasskeyNotFoundError';\n }\n}\n\n/**\n * Passkey Already Registered Error (409)\n *\n * Thrown when the credential presented for enrollment is already on file for\n * some account — including one that revoked it. A credential id is reserved for\n * good once used, so this is also the answer to re-enrolling one's own revoked\n * passkey.\n */\nexport class PasskeyAlreadyRegisteredError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This passkey is already registered',\n details: data.details,\n });\n this.name = 'PasskeyAlreadyRegisteredError';\n }\n}\n\n/**\n * Recent Authentication Required Error (403)\n *\n * Thrown when enrolling or revoking a passkey from a session that proved itself\n * too long ago and carried no password. Clients branch on `code` to know to\n * prompt for the password rather than to show a generic refusal, so the code is\n * a stable field rather than a message they would have to match on.\n */\nexport class RecentAuthenticationRequiredError extends ForbiddenError\n{\n readonly code = 'RECENT_AUTH_REQUIRED';\n\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Confirm it is you before changing passkeys. Sign in again or send your current password.',\n details: data.details,\n });\n this.name = 'RecentAuthenticationRequiredError';\n }\n}\n\n/**\n * Last Recovery Credential Error (409)\n *\n * Thrown when revoking a passkey would leave the account with no way back in:\n * no other live passkey, no password, and no linked social account. There is no\n * password reset in this package, so that state is not recoverable by support\n * either — the refusal is the only thing standing between the owner and a\n * locked account.\n *\n * Clients branch on `code` to offer \"set a password first\" instead of a generic\n * refusal.\n */\nexport class LastRecoveryCredentialError extends ConflictError\n{\n readonly code = 'LAST_RECOVERY_CREDENTIAL';\n\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message\n || 'This is the only way you can sign in. Set a password or link a social account before removing it.',\n details: data.details,\n });\n this.name = 'LastRecoveryCredentialError';\n }\n}\n\n/**\n * Passkey Config Error (500)\n *\n * Thrown at boot when the passkey relying-party configuration cannot be honoured\n * — an origin that is not https outside localhost, an origin off the rpId, an\n * unsupported user-verification value.\n *\n * A refusal at boot rather than at the first ceremony: every one of these makes\n * every passkey operation fail, and the drift is between environments, so the\n * deploy that introduces it is where it has to surface.\n */\nexport class PasskeyConfigError extends HttpError\n{\n constructor(data: { message: string; details?: Record<string, any> })\n {\n super({\n message: data.message,\n statusCode: 500,\n details: data.details,\n });\n this.name = 'PasskeyConfigError';\n }\n}\n\n/**\n * OAuth2 Unknown Client Error (400)\n *\n * Thrown by the API authorize endpoints when `client_id` names no registered\n * client. One of the two refusals that must NOT be turned into a redirect: with\n * no client there is no registered redirect URI, so the only place left to send\n * the error is the one the request supplied — which is exactly the open redirect\n * this rule exists to close. The consent screen shows it instead.\n */\nexport class OAuth2UnknownClientError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Unknown OAuth client',\n details: { error: 'unknown_client', ...data.details },\n });\n this.name = 'OAuth2UnknownClientError';\n }\n}\n\n/**\n * OAuth2 Redirect URI Mismatch Error (400)\n *\n * Thrown when `redirect_uri` is not one the client registered. The second\n * non-redirectable refusal, for the same reason as the first: redirecting the\n * error to an unregistered URI is the attack.\n */\nexport class OAuth2RedirectUriMismatchError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'redirect_uri does not match a registered URI for this client',\n details: { error: 'redirect_uri_mismatch', ...data.details },\n });\n this.name = 'OAuth2RedirectUriMismatchError';\n }\n}\n\n/**\n * OAuth2 Authorize Redirect Error (400)\n *\n * Every other authorize-time refusal — `invalid_request`, `invalid_scope`,\n * `invalid_target`, `access_denied`. The client and its redirect URI are both\n * known by the time these are decided, so RFC 6749 §4.1.2.1 says the error goes\n * back to the client as query parameters on that URI rather than to the person.\n *\n * The API cannot perform that redirect — it is answering the web app's consent\n * handler, not the browser — so it carries the pieces in `details` and the\n * handler builds the 302. `redirectUri` is the registered-and-matched value, not\n * the raw parameter, which is what makes it safe to send somebody to.\n */\nexport class OAuth2AuthorizeRedirectError extends ValidationError\n{\n constructor(data: {\n error: string;\n redirectUri: string;\n state?: string;\n message?: string;\n details?: Record<string, any>;\n })\n {\n super({\n message: data.message || `OAuth authorize request refused: ${data.error}`,\n details: {\n error: data.error,\n redirectUri: data.redirectUri,\n state: data.state,\n ...data.details,\n },\n });\n this.name = 'OAuth2AuthorizeRedirectError';\n }\n}\n\n/**\n * OAuth2 Grant Not Found Error (404)\n *\n * Thrown by `DELETE /_auth/oauth2/grants/:id` when the caller owns no live grant\n * of that id. A grant belonging to somebody else answers the same way as one\n * that never existed — the id is a number in a URL, and telling the two apart\n * would let anyone count other people's connected clients.\n */\nexport class OAuth2GrantNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'No such connected application', details: data.details });\n this.name = 'OAuth2GrantNotFoundError';\n }\n}\n"],"mappings":";;;;;;;AAIA,SAAS,qBAAqB;;;ACJ9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAOA,IAAM,0BAAN,cAAsC,kBAC7C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,uBAAuB,SAAS,KAAK,QAAQ,CAAC;AAC/E,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,oBAAN,cAAgC,kBACvC;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,gCAAgC,SAAS,KAAK,QAAQ,CAAC;AACxF,SAAK,OAAO;AAAA,EAChB;AACJ;AAQO,IAAM,0BAAN,cAAsC,kBAC7C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,2BAA2B,SAAS,KAAK,QAAQ,CAAC;AACnF,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,oBAAN,cAAgC,kBACvC;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,oCAAoC,SAAS,KAAK,QAAQ,CAAC;AAC5F,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,kBAAN,cAA8B,kBACrC;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,0BAA0B,SAAS,KAAK,QAAQ,CAAC;AAClF,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,uBAAN,cAAmC,eAC1C;AAAA,EACI,YAAY,OAA6E,CAAC,GAC1F;AACI,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM;AAAA,MACF,SAAS,KAAK,WAAW,cAAc,MAAM;AAAA,MAC7C,SAAS,EAAE,QAAQ,GAAG,KAAK,QAAQ;AAAA,IACvC,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AASO,IAAM,8BAAN,cAA0C,eACjD;AAAA,EACI,YAAY,OAAuF,CAAC,GACpG;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,EAAE,QAAQ,oBAAoB,kBAAkB,KAAK,kBAAkB,GAAG,KAAK,QAAQ;AAAA,IACpG,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAQO,IAAM,gCAAN,cAA4C,cACnD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,+CAA+C,SAAS,KAAK,QAAQ,CAAC;AACvG,SAAK,OAAO;AAAA,EAChB;AACJ;AAQO,IAAM,4BAAN,cAAwC,cAC/C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,6CAA6C,SAAS,KAAK,QAAQ,CAAC;AACrG,SAAK,OAAO;AAAA,EAChB;AACJ;AAQO,IAAM,mCAAN,cAA+C,eACtD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,kDAAkD,SAAS,KAAK,QAAQ,CAAC;AAC1G,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,4BAAN,cAAwC,cAC/C;AAAA,EACI,YAAY,OAAqH,CAAC,GAClI;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS;AAAA,QACL,YAAY,KAAK;AAAA,QACjB,gBAAgB,KAAK;AAAA,QACrB,GAAG,KAAK;AAAA,MACZ;AAAA,IACJ,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAQO,IAAM,4BAAN,cAAwC,eAC/C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,yBAAyB,SAAS,KAAK,QAAQ,CAAC;AACjF,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,+BAAN,cAA2C,gBAClD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,6BAA6B,SAAS,KAAK,QAAQ,CAAC;AACrF,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,gCAAN,cAA4C,gBACnD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,yCAAyC,SAAS,KAAK,QAAQ,CAAC;AACjG,SAAK,OAAO;AAAA,EAChB;AACJ;AAaO,IAAM,8BAAN,cAA0C,cACjD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,6BAAN,cAAyC,gBAChD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,2BAA2B,SAAS,KAAK,QAAQ,CAAC;AACnF,SAAK,OAAO;AAAA,EAChB;AACJ;AAeO,IAAM,4BAAN,cAAwC,gBAC/C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AASO,IAAM,mBAAN,cAA+B,cACtC;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,iBAAiB,SAAS,KAAK,QAAQ,CAAC;AACzE,SAAK,OAAO;AAAA,EAChB;AACJ;AAoBO,IAAM,qBAAN,cAAiC,cACxC;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAaO,IAAM,0BAAN,cAAsC,cAC7C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,kCAAkC,SAAS,KAAK,QAAQ,CAAC;AAC1F,SAAK,OAAO;AAAA,EAChB;AACJ;AAaO,IAAM,yBAAN,cAAqC,gBAC5C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAaO,IAAM,gCAAN,cAA4C,cACnD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAUO,IAAM,wBAAN,cAAoC,eAC3C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAUO,IAAM,uBAAN,cAAmC,gBAC1C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAcO,IAAM,+BAAN,cAA2C,gBAClD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAaO,IAAM,yBAAN,cAAqC,gBAC5C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAYO,IAAM,iCAAN,cAA6C,kBACpD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAcO,IAAM,yBAAN,cAAqC,kBAC5C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAYO,IAAM,4BAAN,cAAwC,kBAC/C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAeO,IAAM,2BAAN,cAAuC,gBAC9C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WACP;AAAA,MACP,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,wCAAN,cAAoD,gBAC3D;AAAA,EACI,YAAY,OAAgG,CAAC,GAC7G;AACI,UAAM,WAAW,KAAK,YAAY;AAClC,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM;AAAA,MACF,SAAS,KAAK,WAAW,6BAA6B,MAAM,SAAS,QAAQ;AAAA,MAC7E,SAAS,EAAE,UAAU,QAAQ,GAAG,KAAK,QAAQ;AAAA,IACjD,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,uCAAN,cAAmD,gBAC1D;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,wBAAN,cAAoC,gBAC3C;AAAA,EACI,YAAY,OAA+E,CAAC,GAC5F;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,EAAE,UAAU,KAAK,UAAU,GAAG,KAAK,QAAQ;AAAA,IACxD,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,4BAAN,cAAwC,cAC/C;AAAA,EACI,YAAY,OAA+E,CAAC,GAC5F;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,EAAE,UAAU,KAAK,UAAU,GAAG,KAAK,QAAQ;AAAA,IACxD,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,+BAAN,cAA2C,eAClD;AAAA,EACI,YAAY,OAA4F,CAAC,GACzG;AACI,UAAM,sBAAsB,KAAK,uBAAuB,CAAC;AACzD,UAAM;AAAA,MACF,SAAS,KAAK,WAAW,iCAAiC,oBAAoB,KAAK,IAAI,CAAC;AAAA,MACxF,SAAS,EAAE,qBAAqB,GAAG,KAAK,QAAQ;AAAA,IACpD,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAOO,IAAM,wBAAN,cAAoC,eAC3C;AAAA,EACI,YAAY,OAAsF,CAAC,GACnG;AACI,UAAM,gBAAgB,KAAK,iBAAiB,CAAC;AAC7C,UAAM;AAAA,MACF,SAAS,KAAK,WAAW,mBAAmB,cAAc,KAAK,IAAI,CAAC;AAAA,MACpE,SAAS,EAAE,eAAe,GAAG,KAAK,QAAQ;AAAA,IAC9C,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAYO,IAAM,wBAAN,cAAoC,kBAC3C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAcO,IAAM,2BAAN,cAAuC,kBAC9C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AASO,IAAM,uBAAN,cAAmC,cAC1C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAUO,IAAM,gCAAN,cAA4C,cACnD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAUO,IAAM,oCAAN,cAAgD,eACvD;AAAA,EACa,OAAO;AAAA,EAEhB,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAcO,IAAM,8BAAN,cAA0C,cACjD;AAAA,EACa,OAAO;AAAA,EAEhB,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WACP;AAAA,MACP,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAaO,IAAM,qBAAN,cAAiC,UACxC;AAAA,EACI,YAAY,MACZ;AACI,UAAM;AAAA,MACF,SAAS,KAAK;AAAA,MACd,YAAY;AAAA,MACZ,SAAS,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAWO,IAAM,2BAAN,cAAuC,gBAC9C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,EAAE,OAAO,kBAAkB,GAAG,KAAK,QAAQ;AAAA,IACxD,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AASO,IAAM,iCAAN,cAA6C,gBACpD;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,EAAE,OAAO,yBAAyB,GAAG,KAAK,QAAQ;AAAA,IAC/D,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAeO,IAAM,+BAAN,cAA2C,gBAClD;AAAA,EACI,YAAY,MAOZ;AACI,UAAM;AAAA,MACF,SAAS,KAAK,WAAW,oCAAoC,KAAK,KAAK;AAAA,MACvE,SAAS;AAAA,QACL,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,OAAO,KAAK;AAAA,QACZ,GAAG,KAAK;AAAA,MACZ;AAAA,IACJ,CAAC;AACD,SAAK,OAAO;AAAA,EAChB;AACJ;AAUO,IAAM,2BAAN,cAAuC,cAC9C;AAAA,EACI,YAAY,OAA4D,CAAC,GACzE;AACI,UAAM,EAAE,SAAS,KAAK,WAAW,iCAAiC,SAAS,KAAK,QAAQ,CAAC;AACzF,SAAK,OAAO;AAAA,EAChB;AACJ;;;ADp0BO,IAAM,oBAAoB,IAAI,cAAc;AACnD,kBAAkB,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/errors/index.ts","../src/errors/auth-errors.ts"],"sourcesContent":["/**\n * Auth Error Exports\n */\n\nimport { ErrorRegistry } from '@spfn/core/errors';\n\nimport {\n InvalidCredentialsError,\n InvalidTokenError,\n InvalidSocialTokenError,\n TokenExpiredError,\n KeyExpiredError,\n AccountDisabledError,\n AccountPendingDeletionError,\n DeletionAlreadyRequestedError,\n DeletionNotRequestedError,\n ImmediateDeletionNotAllowedError,\n AccountAlreadyExistsError,\n RegistrationRejectedError,\n ReservedUsernameError,\n UsernameAlreadyTakenError,\n InvalidVerificationCodeError,\n InvalidVerificationTokenError,\n InvalidKeyFingerprintError,\n KeyAlgorithmMismatchError,\n NonceKeyBindingError,\n NativeSignInUnsupportedError,\n UnverifiedEmailLinkError,\n InvalidSignupLinkError,\n InvalidSignupSetupSessionError,\n PasswordResetLinkError,\n PasswordResetSessionError,\n KeyNotFoundError,\n KeyIdAlreadyRegisteredError,\n RevokeAllLinkError,\n DeviceAuthNotFoundError,\n DeviceAuthExpiredError,\n DeviceAuthAlreadyHandledError,\n DeviceAuthDeniedError,\n VerificationTokenPurposeMismatchError,\n VerificationTokenTargetMismatchError,\n InsufficientPermissionsError,\n InsufficientRoleError,\n PasskeyChallengeError,\n PasskeyVerificationError,\n PasskeyNotFoundError,\n PasskeyAlreadyRegisteredError,\n RecentAuthenticationRequiredError,\n LastRecoveryCredentialError,\n PasskeyConfigError,\n OAuth2UnknownClientError,\n OAuth2RedirectUriMismatchError,\n OAuth2AuthorizeRedirectError,\n OAuth2GrantNotFoundError,\n MfaAlreadyEnrolledError,\n MfaNotEnrolledError,\n MfaVerificationFailedError,\n StepUpRequiredError,\n MfaConfigError,\n} from './auth-errors';\n\nexport {\n InvalidCredentialsError,\n InvalidTokenError,\n InvalidSocialTokenError,\n TokenExpiredError,\n KeyExpiredError,\n AccountDisabledError,\n AccountPendingDeletionError,\n DeletionAlreadyRequestedError,\n DeletionNotRequestedError,\n ImmediateDeletionNotAllowedError,\n AccountAlreadyExistsError,\n RegistrationRejectedError,\n ReservedUsernameError,\n UsernameAlreadyTakenError,\n InvalidVerificationCodeError,\n InvalidVerificationTokenError,\n InvalidKeyFingerprintError,\n KeyAlgorithmMismatchError,\n NonceKeyBindingError,\n NativeSignInUnsupportedError,\n UnverifiedEmailLinkError,\n InvalidSignupLinkError,\n InvalidSignupSetupSessionError,\n PasswordResetLinkError,\n PasswordResetSessionError,\n KeyNotFoundError,\n KeyIdAlreadyRegisteredError,\n RevokeAllLinkError,\n DeviceAuthNotFoundError,\n DeviceAuthExpiredError,\n DeviceAuthAlreadyHandledError,\n DeviceAuthDeniedError,\n VerificationTokenPurposeMismatchError,\n VerificationTokenTargetMismatchError,\n InsufficientPermissionsError,\n InsufficientRoleError,\n PasskeyChallengeError,\n PasskeyVerificationError,\n PasskeyNotFoundError,\n PasskeyAlreadyRegisteredError,\n RecentAuthenticationRequiredError,\n LastRecoveryCredentialError,\n PasskeyConfigError,\n OAuth2UnknownClientError,\n OAuth2RedirectUriMismatchError,\n OAuth2AuthorizeRedirectError,\n OAuth2GrantNotFoundError,\n MfaAlreadyEnrolledError,\n MfaNotEnrolledError,\n MfaVerificationFailedError,\n StepUpRequiredError,\n MfaConfigError,\n} from './auth-errors';\n\nexport const authErrorRegistry = new ErrorRegistry();\nauthErrorRegistry.append([\n InvalidCredentialsError,\n InvalidTokenError,\n InvalidSocialTokenError,\n TokenExpiredError,\n KeyExpiredError,\n AccountDisabledError,\n AccountPendingDeletionError,\n DeletionAlreadyRequestedError,\n DeletionNotRequestedError,\n ImmediateDeletionNotAllowedError,\n AccountAlreadyExistsError,\n RegistrationRejectedError,\n ReservedUsernameError,\n UsernameAlreadyTakenError,\n InvalidVerificationCodeError,\n InvalidVerificationTokenError,\n InvalidKeyFingerprintError,\n KeyAlgorithmMismatchError,\n NonceKeyBindingError,\n NativeSignInUnsupportedError,\n UnverifiedEmailLinkError,\n InvalidSignupLinkError,\n InvalidSignupSetupSessionError,\n PasswordResetLinkError,\n PasswordResetSessionError,\n KeyNotFoundError,\n KeyIdAlreadyRegisteredError,\n RevokeAllLinkError,\n DeviceAuthNotFoundError,\n DeviceAuthExpiredError,\n DeviceAuthAlreadyHandledError,\n DeviceAuthDeniedError,\n VerificationTokenPurposeMismatchError,\n VerificationTokenTargetMismatchError,\n InsufficientPermissionsError,\n InsufficientRoleError,\n PasskeyChallengeError,\n PasskeyVerificationError,\n PasskeyNotFoundError,\n PasskeyAlreadyRegisteredError,\n RecentAuthenticationRequiredError,\n LastRecoveryCredentialError,\n PasskeyConfigError,\n OAuth2UnknownClientError,\n OAuth2RedirectUriMismatchError,\n OAuth2AuthorizeRedirectError,\n OAuth2GrantNotFoundError,\n MfaAlreadyEnrolledError,\n MfaNotEnrolledError,\n MfaVerificationFailedError,\n StepUpRequiredError,\n MfaConfigError,\n]);\n\nexport * as AuthError from './auth-errors';\n","/**\n * Authentication & Authorization Error Classes\n *\n * Custom error classes for auth-specific scenarios\n */\n\nimport {\n ValidationError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n NotFoundError,\n HttpError,\n} from '@spfn/core/errors';\n\n/**\n * Invalid Credentials Error (401)\n *\n * Thrown when login credentials are incorrect\n */\nexport class InvalidCredentialsError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid credentials', details: data.details });\n this.name = 'InvalidCredentialsError';\n }\n}\n\n/**\n * Invalid Token Error (401)\n *\n * Thrown when authentication token is invalid or malformed\n */\nexport class InvalidTokenError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid authentication token', details: data.details });\n this.name = 'InvalidTokenError';\n }\n}\n\n/**\n * Invalid Social Token Error (401)\n *\n * Thrown when a social provider id_token fails verification\n * (bad signature, wrong issuer/audience, expired, or nonce mismatch).\n */\nexport class InvalidSocialTokenError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid social id_token', details: data.details });\n this.name = 'InvalidSocialTokenError';\n }\n}\n\n/**\n * Token Expired Error (401)\n *\n * Thrown when authentication token has expired\n */\nexport class TokenExpiredError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Authentication token has expired', details: data.details });\n this.name = 'TokenExpiredError';\n }\n}\n\n/**\n * Key Expired Error (401)\n *\n * Thrown when public key has expired\n */\nexport class KeyExpiredError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Public key has expired', details: data.details });\n this.name = 'KeyExpiredError';\n }\n}\n\n/**\n * Account Disabled Error (403)\n *\n * Thrown when user account is disabled or inactive\n */\nexport class AccountDisabledError extends ForbiddenError\n{\n constructor(data: { status?: string; message?: string; details?: Record<string, any> } = {})\n {\n const status = data.status || 'disabled';\n super({\n message: data.message || `Account is ${status}`,\n details: { status, ...data.details },\n });\n this.name = 'AccountDisabledError';\n }\n}\n\n/**\n * Account Pending Deletion Error (403)\n *\n * Thrown on login (password/OAuth/authenticate) when the account is within its\n * deletion grace period. Carries `purgeScheduledAt` so the client can offer a\n * recovery flow instead of a generic \"disabled\" message.\n */\nexport class AccountPendingDeletionError extends ForbiddenError\n{\n constructor(data: { purgeScheduledAt?: string; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Account is scheduled for deletion',\n details: { status: 'pending_deletion', purgeScheduledAt: data.purgeScheduledAt, ...data.details },\n });\n this.name = 'AccountPendingDeletionError';\n }\n}\n\n/**\n * Deletion Already Requested Error (409)\n *\n * Thrown when requesting deletion for an account that already has a pending\n * deletion request (or has already been purged).\n */\nexport class DeletionAlreadyRequestedError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Account deletion has already been requested', details: data.details });\n this.name = 'DeletionAlreadyRequestedError';\n }\n}\n\n/**\n * Deletion Not Requested Error (404)\n *\n * Thrown when trying to cancel/purge a deletion for an account that has no\n * pending deletion request.\n */\nexport class DeletionNotRequestedError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'No pending account deletion request found', details: data.details });\n this.name = 'DeletionNotRequestedError';\n }\n}\n\n/**\n * Immediate Deletion Not Allowed Error (403)\n *\n * Thrown when a self-service caller requests `immediate: true` but the server\n * has not enabled `deletion.allowSelfImmediate`.\n */\nexport class ImmediateDeletionNotAllowedError extends ForbiddenError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Immediate self-service deletion is not enabled', details: data.details });\n this.name = 'ImmediateDeletionNotAllowedError';\n }\n}\n\n/**\n * Account Already Exists Error (409)\n *\n * Thrown when trying to register with existing email/phone\n */\nexport class AccountAlreadyExistsError extends ConflictError\n{\n constructor(data: { identifier?: string; identifierType?: 'email' | 'phone'; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Account already exists',\n details: {\n identifier: data.identifier,\n identifierType: data.identifierType,\n ...data.details,\n },\n });\n this.name = 'AccountAlreadyExistsError';\n }\n}\n\n/**\n * Registration Rejected Error (403)\n *\n * Thrown by the app-injected beforeRegister hook to reject a registration\n * (age gate, domain restriction, block list, ...)\n */\nexport class RegistrationRejectedError extends ForbiddenError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Registration rejected', details: data.details });\n this.name = 'RegistrationRejectedError';\n }\n}\n\n/**\n * Invalid Verification Code Error (400)\n *\n * Thrown when verification code is invalid, expired, or already used\n */\nexport class InvalidVerificationCodeError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid verification code', details: data.details });\n this.name = 'InvalidVerificationCodeError';\n }\n}\n\n/**\n * Invalid Verification Token Error (400)\n *\n * Thrown when verification token is invalid or expired\n */\nexport class InvalidVerificationTokenError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid or expired verification token', details: data.details });\n this.name = 'InvalidVerificationTokenError';\n }\n}\n\n/**\n * Key ID Already Registered Error (409)\n *\n * Thrown when a sign-in submits a keyId that is already taken — the client's own\n * revoked keyId, or a keyId belonging to another user. `keyId` is unique across\n * all users, so either case would collide on insert.\n *\n * The same error covers both cases on purpose: a distinguishable response would\n * let a caller probe whether an arbitrary keyId exists. Revoked stays revoked —\n * the client must generate a fresh keyId and retry.\n */\nexport class KeyIdAlreadyRegisteredError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This keyId is already registered. Generate a new keyId and retry.',\n details: data.details,\n });\n this.name = 'KeyIdAlreadyRegisteredError';\n }\n}\n\n/**\n * Invalid Key Fingerprint Error (400)\n *\n * Thrown when public key fingerprint doesn't match the public key\n */\nexport class InvalidKeyFingerprintError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Invalid key fingerprint', details: data.details });\n this.name = 'InvalidKeyFingerprintError';\n }\n}\n\n/**\n * Key Algorithm Mismatch Error (400)\n *\n * Thrown when the submitted public key's SPKI type is not the one its declared\n * algorithm needs — a P-256 EC key declared RS256, an RSA key declared ES256, a\n * curve other than P-256 declared ES256, or bytes that are no SPKI key at all.\n *\n * The algorithm is stored beside the key and read back at proof verification;\n * nothing re-derives it from the key material. So a mismatch accepted here\n * surfaces only after the device believes it is enrolled, on every request it\n * then makes. It is refused at registration instead, wherever key material is\n * stored: register, login, rotate, invitation acceptance and device start.\n */\nexport class KeyAlgorithmMismatchError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Public key type does not match the declared algorithm',\n details: data.details,\n });\n this.name = 'KeyAlgorithmMismatchError';\n }\n}\n\n/**\n * Key Not Found Error (404)\n *\n * Thrown when a key operation names a keyId the caller does not own. It says\n * nothing about whether that keyId exists on another account — the repository\n * scopes every lookup by userId, so the answer is only ever \"not yours\".\n */\nexport class KeyNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Key not found', details: data.details });\n this.name = 'KeyNotFoundError';\n }\n}\n\n/**\n * Revoke-All Link Error (404)\n *\n * Thrown when a signed sign-out-everywhere link cannot be acted on: unknown,\n * expired, already spent, superseded by a newer one, issued against a key\n * generation that has since moved, or belonging to an account that is not\n * active.\n *\n * One error for every one of those, and the same body for each. Telling an\n * expired link from an unknown one would tell whoever is holding a random value\n * that it named a real outstanding link, and the sibling link flows refuse the\n * same way for the same reason. The specific cause is logged.\n *\n * 404 rather than the 401 the password-reset link answers with: there is no\n * credential here to have been wrong. The address the mail went to is the proof,\n * and what the caller presented either names an outstanding link or names\n * nothing.\n */\nexport class RevokeAllLinkError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This sign-out link is no longer valid. Request a new one.',\n details: data.details,\n });\n this.name = 'RevokeAllLinkError';\n }\n}\n\n/**\n * Device Auth Not Found Error (404)\n *\n * Thrown when a device-code operation names a code the server cannot act on: one\n * that was never issued, and one whose record has already been consumed.\n *\n * Those two are answered identically on purpose. A consumed record is a login\n * that finished, and saying so would tell whoever holds the code that it was\n * real — which is the difference between guessing at random and knowing a guess\n * landed. Every route that accepts a code is rate limited for the same reason.\n */\nexport class DeviceAuthNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'Device authorization not found', details: data.details });\n this.name = 'DeviceAuthNotFoundError';\n }\n}\n\n/**\n * Device Auth Expired Error (400)\n *\n * Thrown when a device-code operation names a record whose TTL has run out,\n * whatever state it is in. The waiting device starts again; the approver is told\n * the code on the other screen is stale.\n *\n * 400 rather than 401: on the approve and deny routes the caller's own session is\n * fine, and answering 401 would send a signed-in user to a login screen over a\n * code that simply sat too long.\n */\nexport class DeviceAuthExpiredError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This device code has expired. Start again on the other device.',\n details: data.details,\n });\n this.name = 'DeviceAuthExpiredError';\n }\n}\n\n/**\n * Device Auth Already Handled Error (409)\n *\n * Thrown when an approve, deny or info call names a record that has already been\n * approved or denied. A decision on a device is made once — a second approval\n * would let one code be answered twice, and re-approving a record the owner\n * denied would undo the refusal.\n *\n * This is also what the loser of two concurrent approvals sees, since the\n * transition names the state it moves from and only one call can match it.\n */\nexport class DeviceAuthAlreadyHandledError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This device request has already been answered',\n details: data.details,\n });\n this.name = 'DeviceAuthAlreadyHandledError';\n }\n}\n\n/**\n * Device Auth Denied Error (403)\n *\n * Thrown when the waiting device polls a record its owner refused. Distinct from\n * a pending answer, and distinct from a code that does not exist: the device\n * asked a person and the person said no, so it should stop polling and say so\n * rather than time out looking like a network fault.\n */\nexport class DeviceAuthDeniedError extends ForbiddenError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This device request was denied',\n details: data.details,\n });\n this.name = 'DeviceAuthDeniedError';\n }\n}\n\n/**\n * Nonce Key Binding Error (400)\n *\n * Thrown when a native id_token sign-in submits a nonce that is not the public\n * key's fingerprint. The nonce is what the provider echoed back inside the\n * id_token, so tying it to the key is what proves the id_token and the key came\n * from the same device — see the native section of the README.\n */\nexport class NonceKeyBindingError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'nonce must be the fingerprint of the submitted public key',\n details: data.details,\n });\n this.name = 'NonceKeyBindingError';\n }\n}\n\n/**\n * Native Sign-In Unsupported Error (400)\n *\n * Thrown when a provider is asked for native id_token sign-in and has no\n * implementation for it — a server configuration fact, not something the user\n * did. A client reading this hides that provider's native button instead of\n * asking the user to try again.\n *\n * Split out of ValidationError because the other native-enrollment refusal\n * (linking to an account whose email the provider never verified) needs a\n * different response from the app, and one code cannot ask for two.\n */\nexport class NativeSignInUnsupportedError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This provider does not support native id_token sign-in.',\n details: data.details,\n });\n this.name = 'NativeSignInUnsupportedError';\n }\n}\n\n/**\n * Invalid Signup Link Error (400)\n *\n * Thrown when an emailed signup confirmation link is unknown, expired, already\n * consumed, or superseded by a newer request for the same address.\n *\n * One error for all four states, on purpose. Distinguishing \"expired\" from\n * \"unknown\" tells a caller holding a random token whether it named a real\n * pending signup, which is exactly the enumeration the request step avoids. The\n * specific reason is logged.\n */\nexport class InvalidSignupLinkError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This signup link is no longer valid. Request a new one.',\n details: data.details,\n });\n this.name = 'InvalidSignupLinkError';\n }\n}\n\n/**\n * Invalid Signup Setup Session Error (401)\n *\n * Thrown when the password-setup session backing a verified-email signup is\n * missing, unknown, expired, superseded or already used.\n *\n * One error for every one of those, on purpose: telling a caller which of them\n * applies tells them whether an address is mid-signup, which is the same\n * enumeration the request step is careful not to leak.\n */\nexport class InvalidSignupSetupSessionError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Password setup session is invalid or has expired. Start the signup again.',\n details: data.details,\n });\n this.name = 'InvalidSignupSetupSessionError';\n }\n}\n\n/**\n * Password Reset Link Error (401)\n *\n * Thrown when an emailed password reset link is unknown, expired, already\n * consumed, superseded by a newer request, or belongs to an account that is no\n * longer active.\n *\n * One error for every one of those, on purpose. Distinguishing \"expired\" from\n * \"unknown\" tells a caller holding a random token whether it named a real\n * pending reset, which is exactly the enumeration the request step avoids. The\n * specific reason is logged.\n */\nexport class PasswordResetLinkError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This password reset link is no longer valid. Request a new one.',\n details: data.details,\n });\n this.name = 'PasswordResetLinkError';\n }\n}\n\n/**\n * Password Reset Session Error (401)\n *\n * Thrown when the password-setup session backing a reset is missing, unknown,\n * expired, superseded or already used.\n *\n * One error for every one of those, for the same reason the link error is one\n * error: which of them applies tells a caller whether an account is mid-reset,\n * and that is the enumeration the request step is careful not to leak.\n */\nexport class PasswordResetSessionError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Password reset session is invalid or has expired. Request a new link.',\n details: data.details,\n });\n this.name = 'PasswordResetSessionError';\n }\n}\n\n/**\n * Unverified Email Link Error (400)\n *\n * Thrown when a social identity carries an email that already belongs to an\n * account, but the provider never verified it. Linking on an unverified email\n * is account takeover, so the refusal stands and the user is sent to a path\n * that proves the address.\n *\n * This says an account exists for that address. It is not a leak introduced\n * here: the message this replaces already stated the same fact in prose, and\n * the paths that must not disclose account existence (password login, deletion\n * re-auth, verification issuance) answer uniformly and are untouched.\n */\nexport class UnverifiedEmailLinkError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message\n || 'Cannot link to existing account with unverified email. Please verify your email with the provider first.',\n details: data.details,\n });\n this.name = 'UnverifiedEmailLinkError';\n }\n}\n\n/**\n * Verification Token Purpose Mismatch Error (400)\n *\n * Thrown when verification token purpose doesn't match expected purpose\n */\nexport class VerificationTokenPurposeMismatchError extends ValidationError\n{\n constructor(data: { expected?: string; actual?: string; message?: string; details?: Record<string, any> } = {})\n {\n const expected = data.expected || 'unknown';\n const actual = data.actual || 'unknown';\n super({\n message: data.message || `Verification token is for ${actual}, but ${expected} was expected`,\n details: { expected, actual, ...data.details },\n });\n this.name = 'VerificationTokenPurposeMismatchError';\n }\n}\n\n/**\n * Verification Token Target Mismatch Error (400)\n *\n * Thrown when verification token target doesn't match provided email/phone\n */\nexport class VerificationTokenTargetMismatchError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Verification token does not match provided email/phone',\n details: data.details,\n });\n this.name = 'VerificationTokenTargetMismatchError';\n }\n}\n\n/**\n * Reserved Username Error (400)\n *\n * Thrown when trying to use a reserved/prohibited username\n */\nexport class ReservedUsernameError extends ValidationError\n{\n constructor(data: { username?: string; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This username is reserved',\n details: { username: data.username, ...data.details },\n });\n this.name = 'ReservedUsernameError';\n }\n}\n\n/**\n * Username Already Taken Error (409)\n *\n * Thrown when trying to set a username that is already in use\n */\nexport class UsernameAlreadyTakenError extends ConflictError\n{\n constructor(data: { username?: string; message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Username is already taken',\n details: { username: data.username, ...data.details },\n });\n this.name = 'UsernameAlreadyTakenError';\n }\n}\n\n/**\n * Insufficient Permissions Error (403)\n *\n * Thrown when user lacks required permissions for the operation\n */\nexport class InsufficientPermissionsError extends ForbiddenError\n{\n constructor(data: { requiredPermissions?: string[]; message?: string; details?: Record<string, any> } = {})\n {\n const requiredPermissions = data.requiredPermissions || [];\n super({\n message: data.message || `Missing required permissions: ${requiredPermissions.join(', ')}`,\n details: { requiredPermissions, ...data.details },\n });\n this.name = 'InsufficientPermissionsError';\n }\n}\n\n/**\n * Insufficient Role Error (403)\n *\n * Thrown when user lacks required role for the operation\n */\nexport class InsufficientRoleError extends ForbiddenError\n{\n constructor(data: { requiredRoles?: string[]; message?: string; details?: Record<string, any> } = {})\n {\n const requiredRoles = data.requiredRoles || [];\n super({\n message: data.message || `Required roles: ${requiredRoles.join(', ')}`,\n details: { requiredRoles, ...data.details },\n });\n this.name = 'InsufficientRoleError';\n }\n}\n\n/**\n * Passkey Challenge Error (401)\n *\n * Thrown when the challenge a WebAuthn ceremony presents is unknown, expired,\n * already spent, minted for the other ceremony, or minted for another account.\n *\n * One error for all five, on purpose. Telling a caller which applies tells them\n * whether a challenge they did not mint exists and what it was for, and the\n * remedy is the same in every case: start the ceremony again.\n */\nexport class PasskeyChallengeError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This passkey challenge is no longer valid. Try again.',\n details: data.details,\n });\n this.name = 'PasskeyChallengeError';\n }\n}\n\n/**\n * Passkey Verification Error (401)\n *\n * Thrown when an assertion or attestation does not verify: wrong origin, wrong\n * rpId, a bad signature, a regressed signature counter — or, on login, a\n * credential that is unknown or has been revoked.\n *\n * Those last two share this error with the cryptographic failures deliberately.\n * A distinct \"no such passkey\" would answer, to anyone holding a credential id,\n * whether it is enrolled here — and a revoked credential answering differently\n * from an unknown one would say the account once had it.\n */\nexport class PasskeyVerificationError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Passkey verification failed.',\n details: data.details,\n });\n this.name = 'PasskeyVerificationError';\n }\n}\n\n/**\n * Passkey Not Found Error (404)\n *\n * Thrown when a management operation names a passkey the caller does not own,\n * or one already revoked. Every lookup is owner-scoped, so the answer is only\n * ever \"not yours\" and says nothing about other accounts.\n */\nexport class PasskeyNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Passkey not found',\n details: data.details,\n });\n this.name = 'PasskeyNotFoundError';\n }\n}\n\n/**\n * Passkey Already Registered Error (409)\n *\n * Thrown when the credential presented for enrollment is already on file for\n * some account — including one that revoked it. A credential id is reserved for\n * good once used, so this is also the answer to re-enrolling one's own revoked\n * passkey.\n */\nexport class PasskeyAlreadyRegisteredError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'This passkey is already registered',\n details: data.details,\n });\n this.name = 'PasskeyAlreadyRegisteredError';\n }\n}\n\n/**\n * Recent Authentication Required Error (403)\n *\n * Thrown when enrolling or revoking a passkey from a session that proved itself\n * too long ago and carried no password. Clients branch on `code` to know to\n * prompt for the password rather than to show a generic refusal, so the code is\n * a stable field rather than a message they would have to match on.\n */\nexport class RecentAuthenticationRequiredError extends ForbiddenError\n{\n readonly code = 'RECENT_AUTH_REQUIRED';\n\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Confirm it is you before changing passkeys. Sign in again or send your current password.',\n details: data.details,\n });\n this.name = 'RecentAuthenticationRequiredError';\n }\n}\n\n/**\n * Last Recovery Credential Error (409)\n *\n * Thrown when revoking a passkey would leave the account with no way back in:\n * no other live passkey, no password, and no linked social account. There is no\n * password reset in this package, so that state is not recoverable by support\n * either — the refusal is the only thing standing between the owner and a\n * locked account.\n *\n * Clients branch on `code` to offer \"set a password first\" instead of a generic\n * refusal.\n */\nexport class LastRecoveryCredentialError extends ConflictError\n{\n readonly code = 'LAST_RECOVERY_CREDENTIAL';\n\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message\n || 'This is the only way you can sign in. Set a password or link a social account before removing it.',\n details: data.details,\n });\n this.name = 'LastRecoveryCredentialError';\n }\n}\n\n/**\n * Passkey Config Error (500)\n *\n * Thrown at boot when the passkey relying-party configuration cannot be honoured\n * — an origin that is not https outside localhost, an origin off the rpId, an\n * unsupported user-verification value.\n *\n * A refusal at boot rather than at the first ceremony: every one of these makes\n * every passkey operation fail, and the drift is between environments, so the\n * deploy that introduces it is where it has to surface.\n */\nexport class PasskeyConfigError extends HttpError\n{\n constructor(data: { message: string; details?: Record<string, any> })\n {\n super({\n message: data.message,\n statusCode: 500,\n details: data.details,\n });\n this.name = 'PasskeyConfigError';\n }\n}\n\n/**\n * OAuth2 Unknown Client Error (400)\n *\n * Thrown by the API authorize endpoints when `client_id` names no registered\n * client. One of the two refusals that must NOT be turned into a redirect: with\n * no client there is no registered redirect URI, so the only place left to send\n * the error is the one the request supplied — which is exactly the open redirect\n * this rule exists to close. The consent screen shows it instead.\n */\nexport class OAuth2UnknownClientError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Unknown OAuth client',\n details: { error: 'unknown_client', ...data.details },\n });\n this.name = 'OAuth2UnknownClientError';\n }\n}\n\n/**\n * OAuth2 Redirect URI Mismatch Error (400)\n *\n * Thrown when `redirect_uri` is not one the client registered. The second\n * non-redirectable refusal, for the same reason as the first: redirecting the\n * error to an unregistered URI is the attack.\n */\nexport class OAuth2RedirectUriMismatchError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'redirect_uri does not match a registered URI for this client',\n details: { error: 'redirect_uri_mismatch', ...data.details },\n });\n this.name = 'OAuth2RedirectUriMismatchError';\n }\n}\n\n/**\n * OAuth2 Authorize Redirect Error (400)\n *\n * Every other authorize-time refusal — `invalid_request`, `invalid_scope`,\n * `invalid_target`, `access_denied`. The client and its redirect URI are both\n * known by the time these are decided, so RFC 6749 §4.1.2.1 says the error goes\n * back to the client as query parameters on that URI rather than to the person.\n *\n * The API cannot perform that redirect — it is answering the web app's consent\n * handler, not the browser — so it carries the pieces in `details` and the\n * handler builds the 302. `redirectUri` is the registered-and-matched value, not\n * the raw parameter, which is what makes it safe to send somebody to.\n */\nexport class OAuth2AuthorizeRedirectError extends ValidationError\n{\n constructor(data: {\n error: string;\n redirectUri: string;\n state?: string;\n message?: string;\n details?: Record<string, any>;\n })\n {\n super({\n message: data.message || `OAuth authorize request refused: ${data.error}`,\n details: {\n error: data.error,\n redirectUri: data.redirectUri,\n state: data.state,\n ...data.details,\n },\n });\n this.name = 'OAuth2AuthorizeRedirectError';\n }\n}\n\n/**\n * OAuth2 Grant Not Found Error (404)\n *\n * Thrown by `DELETE /_auth/oauth2/grants/:id` when the caller owns no live grant\n * of that id. A grant belonging to somebody else answers the same way as one\n * that never existed — the id is a number in a URL, and telling the two apart\n * would let anyone count other people's connected clients.\n */\nexport class OAuth2GrantNotFoundError extends NotFoundError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({ message: data.message || 'No such connected application', details: data.details });\n this.name = 'OAuth2GrantNotFoundError';\n }\n}\n\n/**\n * MFA Already Enrolled Error (409)\n *\n * Thrown when `totp/enroll` is called on an account whose TOTP is already\n * confirmed. Replacing a working second factor is `disable` followed by a fresh\n * enrolment, both step-up gated — an enrol that quietly overwrote a confirmed\n * secret would be a way to swap someone's authenticator for your own.\n */\nexport class MfaAlreadyEnrolledError extends ConflictError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'A second factor is already enrolled on this account',\n details: data.details,\n });\n this.name = 'MfaAlreadyEnrolledError';\n }\n}\n\n/**\n * MFA Not Enrolled Error (400)\n *\n * Thrown when a call needs an enrolment that is not there: `totp/confirm` with\n * no pending secret — including the row its own five failed attempts deleted —\n * or `recovery/regenerate` on an account with no second factor. `disable` is\n * deliberately not one of them; it answers 204 either way, because \"make sure\n * MFA is off\" has already succeeded.\n */\nexport class MfaNotEnrolledError extends ValidationError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'No second-factor enrolment is in progress on this account',\n details: data.details,\n });\n this.name = 'MfaNotEnrolledError';\n }\n}\n\n/**\n * MFA Verification Failed Error (401)\n *\n * Thrown when a submitted code does not verify: a wrong or stale TOTP, a code\n * from a step already spent, a recovery code that is used, from an older\n * generation or another account's, or an assertion from a passkey the owner\n * never marked as a second factor.\n *\n * One body for all of them. Which one applies describes state the caller is\n * guessing at, and the remedy — look at the authenticator again — is the same.\n */\nexport class MfaVerificationFailedError extends UnauthorizedError\n{\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'That code did not verify',\n details: data.details,\n });\n this.name = 'MfaVerificationFailedError';\n }\n}\n\n/**\n * Step Up Required Error (403)\n *\n * Thrown when an enrolled account asks for a sensitive change from a device\n * whose second factor was last verified longer ago than the step-up window. A\n * stolen session alone therefore cannot change a password, sign every device\n * out, or take the second factor off.\n *\n * 403 and not 401, on the same reasoning as `RecentAuthenticationRequiredError`,\n * which it sits beside: a 401 on an authenticated route is what a web client\n * reads as \"the session is gone\", so it would sign the user out instead of\n * asking for a code. Clients branch on `code` to send the user to\n * `POST /_auth/mfa/step-up` and retry.\n */\nexport class StepUpRequiredError extends ForbiddenError\n{\n readonly code = 'STEP_UP_REQUIRED';\n\n constructor(data: { message?: string; details?: Record<string, any> } = {})\n {\n super({\n message: data.message || 'Confirm your second factor before making this change.',\n details: data.details,\n });\n this.name = 'StepUpRequiredError';\n }\n}\n\n/**\n * MFA Config Error (500)\n *\n * Thrown when the at-rest keyring cannot serve a second factor:\n * `SPFN_AUTH_TOKEN_ENCRYPTION_KEYS` is unset, or a stored secret names a key id\n * that has been dropped from it.\n *\n * Deliberately not the 401 a wrong code gets. The two have nothing in common: a\n * wrong code is one person looking at the wrong line of their authenticator,\n * and a broken keyring is every enrolled user locked out at once by a deploy.\n * An operator has to be able to tell them apart from the response alone.\n */\nexport class MfaConfigError extends HttpError\n{\n constructor(data: { message: string; details?: Record<string, any> })\n {\n super({\n message: data.message,\n statusCode: 500,\n details: data.details,\n });\n this.name = 'MfaConfigError';\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _spfn_core_nextjs from '@spfn/core/nextjs';
2
- import { P as PermissionConfig, R as RoleConfig, m as mainAuthRouter, S as SendVerificationCodeResult, a as RegisterResult, b as RequestSignupLinkResult, C as ConfirmSignupLinkResult, c as RequestPasswordResetResult, d as ConfirmPasswordResetResult, L as LoginResult, e as StartDeviceAuthResult, D as DeviceAuthInfoResult, F as FinishPasskeyEnrollmentResult, f as PasskeySummary, g as RotateKeyResult, K as KeySummary, h as RevokeAllKeysResult, I as IssueOneTimeTokenResult, O as OAuthStartResult, i as OAuthNativeResult, U as UserProfile, j as ProfileInfo, k as OAuth2ConsentView, l as OAuth2AuthorizationCodeIssued, n as OAuth2GrantSummary } from './machine-principals-B7N8gux0.js';
3
- export { A as AuthInitOptions, o as AuthSession, p as PERMISSION_CATEGORIES, q as PermissionCategory, V as VERIFICATION_PURPOSES, r as VERIFICATION_TARGET_TYPES, s as VerificationPurpose, t as VerificationTargetType } from './machine-principals-B7N8gux0.js';
2
+ import { P as PermissionConfig, R as RoleConfig, m as mainAuthRouter, S as SendVerificationCodeResult, a as RegisterResult, b as RequestSignupLinkResult, C as ConfirmSignupLinkResult, c as RequestPasswordResetResult, d as ConfirmPasswordResetResult, L as LoginResult, e as StartDeviceAuthResult, D as DeviceAuthInfoResult, F as FinishPasskeyEnrollmentResult, f as PasskeySummary, T as TotpEnrolmentResult, g as ConfirmTotpResult, M as MfaStatus, h as RotateKeyResult, K as KeySummary, i as RevokeAllKeysResult, I as IssueOneTimeTokenResult, O as OAuthStartResult, j as OAuthNativeResult, U as UserProfile, k as ProfileInfo, l as OAuth2ConsentView, n as OAuth2AuthorizationCodeIssued, o as OAuth2GrantSummary } from './machine-principals-CaEFq61K.js';
3
+ export { A as AuthInitOptions, p as AuthSession, q as PERMISSION_CATEGORIES, r as PermissionCategory, V as VERIFICATION_PURPOSES, s as VERIFICATION_TARGET_TYPES, t as VerificationPurpose, u as VerificationTargetType } from './machine-principals-CaEFq61K.js';
4
4
  import * as _simplewebauthn_server from '@simplewebauthn/server';
5
5
  import * as _spfn_core_route from '@spfn/core/route';
6
6
  import { HttpMethod } from '@spfn/core/route';
@@ -289,6 +289,39 @@ declare const authApi: _spfn_core_nextjs.Client<_spfn_core_route.Router<{
289
289
  }, {}, {
290
290
  passkeyId: string;
291
291
  }>;
292
+ mfaTotpEnroll: _spfn_core_route.RouteDef<{
293
+ body: _sinclair_typebox.TObject<{}>;
294
+ }, {}, TotpEnrolmentResult>;
295
+ mfaTotpConfirm: _spfn_core_route.RouteDef<{
296
+ body: _sinclair_typebox.TObject<{
297
+ code: _sinclair_typebox.TString;
298
+ }>;
299
+ }, {}, ConfirmTotpResult>;
300
+ mfaDisable: _spfn_core_route.RouteDef<{
301
+ body: _sinclair_typebox.TObject<{}>;
302
+ }, {}, void>;
303
+ mfaMarkPasskey: _spfn_core_route.RouteDef<{
304
+ body: _sinclair_typebox.TObject<{
305
+ passkeyId: _sinclair_typebox.TString;
306
+ secondFactor: _sinclair_typebox.TBoolean;
307
+ }>;
308
+ }, {}, MfaStatus>;
309
+ mfaRegenerateRecoveryCodes: _spfn_core_route.RouteDef<{
310
+ body: _sinclair_typebox.TObject<{}>;
311
+ }, {}, {
312
+ recoveryCodes: string[];
313
+ }>;
314
+ mfaStatus: _spfn_core_route.RouteDef<{}, {}, MfaStatus>;
315
+ mfaStepUp: _spfn_core_route.RouteDef<{
316
+ body: _sinclair_typebox.TObject<{
317
+ code: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
318
+ recoveryCode: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
319
+ response: _sinclair_typebox.TOptional<_sinclair_typebox.TUnknown>;
320
+ }>;
321
+ }, {}, void>;
322
+ mfaStepUpOptions: _spfn_core_route.RouteDef<{
323
+ body: _sinclair_typebox.TObject<{}>;
324
+ }, {}, _simplewebauthn_server.PublicKeyCredentialRequestOptionsJSON>;
292
325
  logout: _spfn_core_route.RouteDef<{}, {}, void>;
293
326
  rotateKey: _spfn_core_route.RouteDef<{}, {
294
327
  body: _sinclair_typebox.TObject<{
package/dist/index.js CHANGED
@@ -414,6 +414,53 @@ var OAuth2GrantNotFoundError = class extends NotFoundError {
414
414
  this.name = "OAuth2GrantNotFoundError";
415
415
  }
416
416
  };
417
+ var MfaAlreadyEnrolledError = class extends ConflictError {
418
+ constructor(data = {}) {
419
+ super({
420
+ message: data.message || "A second factor is already enrolled on this account",
421
+ details: data.details
422
+ });
423
+ this.name = "MfaAlreadyEnrolledError";
424
+ }
425
+ };
426
+ var MfaNotEnrolledError = class extends ValidationError {
427
+ constructor(data = {}) {
428
+ super({
429
+ message: data.message || "No second-factor enrolment is in progress on this account",
430
+ details: data.details
431
+ });
432
+ this.name = "MfaNotEnrolledError";
433
+ }
434
+ };
435
+ var MfaVerificationFailedError = class extends UnauthorizedError {
436
+ constructor(data = {}) {
437
+ super({
438
+ message: data.message || "That code did not verify",
439
+ details: data.details
440
+ });
441
+ this.name = "MfaVerificationFailedError";
442
+ }
443
+ };
444
+ var StepUpRequiredError = class extends ForbiddenError {
445
+ code = "STEP_UP_REQUIRED";
446
+ constructor(data = {}) {
447
+ super({
448
+ message: data.message || "Confirm your second factor before making this change.",
449
+ details: data.details
450
+ });
451
+ this.name = "StepUpRequiredError";
452
+ }
453
+ };
454
+ var MfaConfigError = class extends HttpError {
455
+ constructor(data) {
456
+ super({
457
+ message: data.message,
458
+ statusCode: 500,
459
+ details: data.details
460
+ });
461
+ this.name = "MfaConfigError";
462
+ }
463
+ };
417
464
 
418
465
  // src/errors/index.ts
419
466
  var authErrorRegistry = new ErrorRegistry();
@@ -464,7 +511,12 @@ authErrorRegistry.append([
464
511
  OAuth2UnknownClientError,
465
512
  OAuth2RedirectUriMismatchError,
466
513
  OAuth2AuthorizeRedirectError,
467
- OAuth2GrantNotFoundError
514
+ OAuth2GrantNotFoundError,
515
+ MfaAlreadyEnrolledError,
516
+ MfaNotEnrolledError,
517
+ MfaVerificationFailedError,
518
+ StepUpRequiredError,
519
+ MfaConfigError
468
520
  ]);
469
521
 
470
522
  // src/generated/route-map.ts
@@ -494,6 +546,14 @@ var routeMap = {
494
546
  completePasswordReset: { method: "POST", path: "/_auth/password/reset/complete" },
495
547
  confirmRevokeAllLink: { method: "POST", path: "/_auth/keys/revoke-all/confirm" },
496
548
  consumeRevokeAllLink: { method: "POST", path: "/_auth/keys/revoke-all/consume" },
549
+ mfaTotpEnroll: { method: "POST", path: "/_auth/mfa/totp/enroll" },
550
+ mfaTotpConfirm: { method: "POST", path: "/_auth/mfa/totp/confirm" },
551
+ mfaDisable: { method: "POST", path: "/_auth/mfa/disable" },
552
+ mfaMarkPasskey: { method: "POST", path: "/_auth/mfa/passkey/mark" },
553
+ mfaRegenerateRecoveryCodes: { method: "POST", path: "/_auth/mfa/recovery/regenerate" },
554
+ mfaStatus: { method: "GET", path: "/_auth/mfa/status" },
555
+ mfaStepUp: { method: "POST", path: "/_auth/mfa/step-up" },
556
+ mfaStepUpOptions: { method: "POST", path: "/_auth/mfa/step-up/options" },
497
557
  passkeyRegisterOptions: { method: "POST", path: "/_auth/passkeys/register/options" },
498
558
  passkeyRegisterVerify: { method: "POST", path: "/_auth/passkeys/register/verify" },
499
559
  passkeyLoginOptions: { method: "POST", path: "/_auth/passkeys/login/options" },