@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.
@@ -148,6 +148,14 @@ interface LogoutParams {
148
148
  }
149
149
  interface ChangePasswordParams {
150
150
  userId: number;
151
+ /**
152
+ * The device key this request is signed with.
153
+ *
154
+ * Only read to measure the second-factor window of an enrolled account —
155
+ * an account with nothing enrolled is answered exactly as before, so this
156
+ * adds no refusal for anybody who has not opted in.
157
+ */
158
+ keyId: string;
151
159
  currentPassword?: string;
152
160
  newPassword: string;
153
161
  passwordHash?: string;
@@ -166,6 +174,11 @@ declare function loginService(params: LoginParams): Promise<LoginResult>;
166
174
  declare function logoutService(params: LogoutParams): Promise<void>;
167
175
  /**
168
176
  * Change user password
177
+ *
178
+ * An enrolled account steps up first (#95): a stolen session must not be able
179
+ * to take the account over by setting a new password. An unenrolled account is
180
+ * unaffected — including the OAuth-only account with no password and a key
181
+ * older than ten minutes, which still sets a first password and gets a 200.
169
182
  */
170
183
  declare function changePasswordService(params: ChangePasswordParams): Promise<void>;
171
184
 
@@ -822,6 +835,21 @@ declare const passkeys: drizzle_orm_pg_core.PgTableWithColumns<{
822
835
  identity: undefined;
823
836
  generated: undefined;
824
837
  }>;
838
+ secondFactor: drizzle_orm_pg_core.PgBuildColumn<"passkeys", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBooleanBuilder>>, {
839
+ name: string;
840
+ tableName: "passkeys";
841
+ dataType: "boolean";
842
+ data: boolean;
843
+ driverParam: boolean;
844
+ notNull: true;
845
+ hasDefault: true;
846
+ isPrimaryKey: false;
847
+ isAutoincrement: false;
848
+ hasRuntimeDefault: false;
849
+ enumValues: undefined;
850
+ identity: undefined;
851
+ generated: undefined;
852
+ }>;
825
853
  lastUsedAt: drizzle_orm_pg_core.PgBuildColumn<"passkeys", drizzle_orm_pg_core.PgTimestampBuilder, {
826
854
  name: string;
827
855
  tableName: "passkeys";
@@ -953,6 +981,11 @@ interface StartPasskeyEnrollmentParams {
953
981
  /**
954
982
  * Step 1 of enrollment — options for `navigator.credentials.create()`.
955
983
  *
984
+ * An enrolled account steps up first, and every account then meets the
985
+ * recent-authentication rule this route has always had (#95). The order is what
986
+ * makes the two independent: `assertStepUp` is a no-op for an unenrolled
987
+ * account, so the answer such a caller gets is byte-for-byte today's.
988
+ *
956
989
  * `excludeCredentials` lists the caller's **live** passkeys only, so the
957
990
  * authenticator quietly refuses one already enrolled here. Revoked ones are left
958
991
  * out on purpose: they must not be re-enrolled either, and the check that
@@ -1040,8 +1073,10 @@ interface RevokePasskeyParams {
1040
1073
  /**
1041
1074
  * Retire a passkey.
1042
1075
  *
1043
- * Gated on recent authentication, because someone who walked up to an unlocked
1044
- * laptop should not be able to strip the account's credentials; and on the
1076
+ * Gated on the second factor for an enrolled account, and then — for every
1077
+ * account, enrolled or not — on recent authentication, because someone who
1078
+ * walked up to an unlocked laptop should not be able to strip the account's
1079
+ * credentials; and on the
1045
1080
  * last-recovery-credential guard, because there is no undo for the state that
1046
1081
  * would leave.
1047
1082
  *
@@ -1056,6 +1091,318 @@ declare function revokePasskeyService(params: RevokePasskeyParams): Promise<{
1056
1091
  passkeyId: string;
1057
1092
  }>;
1058
1093
 
1094
+ /**
1095
+ * @spfn/auth - Second-Factor Verification Entity
1096
+ *
1097
+ * When each device last proved the account's second factor. One row per device
1098
+ * key, which is what makes the step-up window mean "this device, recently"
1099
+ * rather than "somebody, somewhere, recently".
1100
+ *
1101
+ * `key_id` is the primary key and a foreign key onto `user_public_keys.key_id`,
1102
+ * so the row dies with the device it belongs to — a revoked key cannot leave a
1103
+ * verification behind for the next key that reuses its id, and deleting an
1104
+ * account takes these with it. A rotation is the one moment the row moves
1105
+ * rather than dying: rotating is already proof of the same device, so
1106
+ * `rotateKeyService` and the login rotation carry the verification across, or
1107
+ * the window would silently expire every time the proxy rotated a key.
1108
+ */
1109
+ /**
1110
+ * Which credential satisfied the step-up.
1111
+ *
1112
+ * Recorded for the owner-facing audit an app may build on it, and for support:
1113
+ * "recovery" is the one that should be rare, and an account stepping up with
1114
+ * recovery codes repeatedly has lost its authenticator.
1115
+ */
1116
+ declare const MFA_VERIFICATION_METHODS: readonly ["totp", "recovery", "passkey"];
1117
+ type MfaVerificationMethod = typeof MFA_VERIFICATION_METHODS[number];
1118
+ declare const mfaVerifications: drizzle_orm_pg_core.PgTableWithColumns<{
1119
+ name: "mfa_verifications";
1120
+ schema: string;
1121
+ columns: {
1122
+ keyId: drizzle_orm_pg_core.PgBuildColumn<"mfa_verifications", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
1123
+ name: string;
1124
+ tableName: "mfa_verifications";
1125
+ dataType: "string";
1126
+ data: string;
1127
+ driverParam: string;
1128
+ notNull: true;
1129
+ hasDefault: false;
1130
+ isPrimaryKey: false;
1131
+ isAutoincrement: false;
1132
+ hasRuntimeDefault: false;
1133
+ enumValues: undefined;
1134
+ identity: undefined;
1135
+ generated: undefined;
1136
+ }>;
1137
+ userId: drizzle_orm_pg_core.PgBuildColumn<"mfa_verifications", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgBigInt53Builder>, {
1138
+ name: string;
1139
+ tableName: "mfa_verifications";
1140
+ dataType: "number int53";
1141
+ data: number;
1142
+ driverParam: string | number;
1143
+ notNull: true;
1144
+ hasDefault: false;
1145
+ isPrimaryKey: false;
1146
+ isAutoincrement: false;
1147
+ hasRuntimeDefault: false;
1148
+ enumValues: undefined;
1149
+ identity: undefined;
1150
+ generated: undefined;
1151
+ }>;
1152
+ method: drizzle_orm_pg_core.PgBuildColumn<"mfa_verifications", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<["totp", "recovery", "passkey"] & [string, ...string[]]>>, {
1153
+ name: string;
1154
+ tableName: "mfa_verifications";
1155
+ dataType: "string enum";
1156
+ data: "totp" | "recovery" | "passkey";
1157
+ driverParam: string;
1158
+ notNull: true;
1159
+ hasDefault: false;
1160
+ isPrimaryKey: false;
1161
+ isAutoincrement: false;
1162
+ hasRuntimeDefault: false;
1163
+ enumValues: ["totp", "recovery", "passkey"] & [string, ...string[]];
1164
+ identity: undefined;
1165
+ generated: undefined;
1166
+ }>;
1167
+ verifiedAt: drizzle_orm_pg_core.PgBuildColumn<"mfa_verifications", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>>, {
1168
+ name: string;
1169
+ tableName: "mfa_verifications";
1170
+ dataType: "object date";
1171
+ data: Date;
1172
+ driverParam: string;
1173
+ notNull: true;
1174
+ hasDefault: true;
1175
+ isPrimaryKey: false;
1176
+ isAutoincrement: false;
1177
+ hasRuntimeDefault: false;
1178
+ enumValues: undefined;
1179
+ identity: undefined;
1180
+ generated: undefined;
1181
+ }>;
1182
+ };
1183
+ dialect: "pg";
1184
+ }>;
1185
+ type MfaVerification = typeof mfaVerifications.$inferSelect;
1186
+ type NewMfaVerification = typeof mfaVerifications.$inferInsert;
1187
+
1188
+ /**
1189
+ * @spfn/auth - Second Factor Service
1190
+ *
1191
+ * An optional second step the owner enrols, that the package then asks for at
1192
+ * the moments a stolen first credential would be used. Two forms: a TOTP
1193
+ * authenticator app, or a passkey the owner already enrolled and has marked as
1194
+ * satisfying a step-up. Ten single-use recovery codes come with either.
1195
+ *
1196
+ * The rule the whole feature hangs on is the one in `assertStepUp`: an account
1197
+ * that never enrolled is answered exactly as it is today, on every route. That
1198
+ * is why the enrolment check comes first and returns, before any passkey
1199
+ * configuration is read and before any second query is made — an app with no
1200
+ * passkeys configured must still be able to change a password.
1201
+ *
1202
+ * The step-up window is per **device key**, not per account: "this device
1203
+ * proved the second factor recently" is the claim a sensitive change needs, and
1204
+ * a verification made on a phone must not authorize a change from a laptop. A
1205
+ * key rotation carries the row across, because rotating is already proof of the
1206
+ * same device.
1207
+ *
1208
+ * A secret and a recovery code appear in exactly three response bodies —
1209
+ * `totp/enroll`, `totp/confirm` and `recovery/regenerate` — and nowhere else:
1210
+ * not in `status`, not in an event, and not in a log line.
1211
+ */
1212
+
1213
+ /**
1214
+ * Does this account have a second factor at all?
1215
+ *
1216
+ * One statement (`repositories/mfa-enrolment.repository.ts`), because every
1217
+ * sensitive route and every device registration asks it, including the
1218
+ * overwhelming majority that will answer false.
1219
+ */
1220
+ declare function mfaEnrolledForUser(userId: number): Promise<boolean>;
1221
+ interface AssertStepUpParams {
1222
+ userId: number;
1223
+ /** The device key this request is signed with — the window is its window. */
1224
+ keyId: string;
1225
+ /** Override the configured window. Callers needing a tighter one pass it. */
1226
+ maxAgeMs?: number;
1227
+ }
1228
+ /**
1229
+ * Refuse a sensitive change unless this device proved the second factor recently.
1230
+ *
1231
+ * **No-op for an account with no second factor.** That is the contract of the
1232
+ * whole feature: `changePassword` and `revokeAllKeys` have no recency gate
1233
+ * today, and adding one for people who never opted in would be a new refusal on
1234
+ * routes that never had one. Two of the callers do have a gate of their own —
1235
+ * the passkey routes' `assertRecentAuthentication` — and they still run it
1236
+ * afterwards; this adds a rule for enrolled accounts rather than replacing one.
1237
+ *
1238
+ * The unenrolled path therefore costs one indexed lookup and touches no passkey
1239
+ * configuration, which is what lets an app with no passkeys at all call it.
1240
+ *
1241
+ * @throws StepUpRequiredError when the account is enrolled and the window has passed
1242
+ */
1243
+ declare function assertStepUp(params: AssertStepUpParams): Promise<void>;
1244
+ /**
1245
+ * Carry a device's verification onto the key that replaces it.
1246
+ *
1247
+ * Called from the two rotation seams — `rotateKeyService`, and the `oldKeyId`
1248
+ * rotation every login path runs through `registerPublicKeyService`. Without
1249
+ * it the window would expire silently on every rotation, which the web proxy
1250
+ * does at each login: a user who stepped up a minute ago would be asked again
1251
+ * with nothing to connect it to.
1252
+ */
1253
+ declare function carryStepUpVerification(userId: number, fromKeyId: string, toKeyId: string): Promise<void>;
1254
+ interface TotpEnrolmentResult {
1255
+ /** The base32 secret, shown once. Never logged, never returned again. */
1256
+ secret: string;
1257
+ /** The same secret as the URI an authenticator app scans. */
1258
+ otpauthUri: string;
1259
+ }
1260
+ /**
1261
+ * Mint a secret and park it unconfirmed.
1262
+ *
1263
+ * Calling this twice replaces the unconfirmed row and its failure counter — a
1264
+ * user who closed the app before scanning starts over, which is also the
1265
+ * documented remedy for a row that spent its five confirm attempts. A
1266
+ * **confirmed** enrolment is refused instead: replacing a working second factor
1267
+ * is `disable` followed by a fresh enrolment, both step-up gated, so nobody
1268
+ * holding only a stolen session can swap an authenticator for their own.
1269
+ *
1270
+ * @throws MfaAlreadyEnrolledError when a confirmed enrolment already exists
1271
+ */
1272
+ declare function startTotpEnrolmentService(userId: number): Promise<TotpEnrolmentResult>;
1273
+ interface ConfirmTotpParams {
1274
+ userId: number;
1275
+ /** The device this enrolment is being confirmed from — it gets the first verification. */
1276
+ keyId: string;
1277
+ code: string;
1278
+ }
1279
+ interface ConfirmTotpResult {
1280
+ /** The ten plaintext codes, shown once. */
1281
+ recoveryCodes: string[];
1282
+ }
1283
+ /**
1284
+ * Spend the first code, which is what turns an enrolment into a second factor.
1285
+ *
1286
+ * Five wrong codes delete the unconfirmed row: at that point the person is
1287
+ * reading the wrong entry in their app, and a fresh `enroll` is both the remedy
1288
+ * and what resets the counter. A confirmed row is never deleted this way.
1289
+ *
1290
+ * The route deliberately runs this outside a transaction, so the counter
1291
+ * survives the refusal that raised it; the success path opens its own, because
1292
+ * the confirmation, the first verification and the recovery codes have to
1293
+ * commit together or not at all.
1294
+ *
1295
+ * @throws MfaNotEnrolledError | MfaVerificationFailedError
1296
+ */
1297
+ declare function confirmTotpEnrolmentService(params: ConfirmTotpParams): Promise<ConfirmTotpResult>;
1298
+ /**
1299
+ * Replace the account's recovery codes, retiring every earlier one.
1300
+ *
1301
+ * The old generation's rows stay, unspent and unreachable: a code written down
1302
+ * last year is refused with the same body as one that never existed, and the
1303
+ * record of which generation a spent code came from survives.
1304
+ *
1305
+ * @throws MfaNotEnrolledError on an account with no second factor
1306
+ */
1307
+ declare function regenerateRecoveryCodesService(userId: number): Promise<{
1308
+ recoveryCodes: string[];
1309
+ }>;
1310
+ /**
1311
+ * Take the second factor off the account entirely.
1312
+ *
1313
+ * Idempotent: an account with nothing enrolled is a success, because "make sure
1314
+ * MFA is off" has already happened. The passkeys themselves are untouched —
1315
+ * only their second-factor marks go, since a credential that signs the owner in
1316
+ * is not something this route may remove.
1317
+ */
1318
+ declare function disableMfaService(userId: number): Promise<void>;
1319
+ interface MarkPasskeyParams {
1320
+ userId: number;
1321
+ passkeyId: string;
1322
+ secondFactor: boolean;
1323
+ }
1324
+ /**
1325
+ * Mark or unmark one of the caller's passkeys as their second factor.
1326
+ *
1327
+ * Unmarking the last one is allowed, and leaves the account unenrolled. It is
1328
+ * deliberately independent of `assertNotLastRecoveryCredential`, which guards
1329
+ * `passkeys/revoke`: that rule protects a way *into* the account, and a
1330
+ * second-factor mark is not one — the credential still signs the owner in
1331
+ * afterwards, unchanged.
1332
+ *
1333
+ * @throws PasskeyNotFoundError for a credential that is not theirs, or revoked
1334
+ */
1335
+ declare function markPasskeySecondFactorService(params: MarkPasskeyParams): Promise<MfaStatus>;
1336
+ /** What the account surface shows about the second factor. No secret is in it. */
1337
+ interface MfaStatus {
1338
+ enrolled: boolean;
1339
+ /** Which second factors are live: `'totp'`, `'passkey'`, or both. */
1340
+ methods: ('totp' | 'passkey')[];
1341
+ /** Unspent codes of the current generation, for the "2 left" warning. */
1342
+ recoveryCodesRemaining: number;
1343
+ }
1344
+ /**
1345
+ * The account's second-factor state.
1346
+ *
1347
+ * Carries no secret, no otpauth URI and no recovery code — only the counts and
1348
+ * names an account screen needs. An unconfirmed enrolment is not a method: it
1349
+ * gates nothing, so reporting it would tell the owner they are protected when
1350
+ * they are not.
1351
+ */
1352
+ declare function mfaStatusService(userId: number): Promise<MfaStatus>;
1353
+ /**
1354
+ * Options for a step-up by passkey assertion.
1355
+ *
1356
+ * `allowCredentials` is empty, as it is for a sign-in and for the same reason
1357
+ * (D3): the discoverable credential on the device names itself, and the owner
1358
+ * and the second-factor mark are checked when the assertion comes back. The
1359
+ * challenge is minted with kind `'mfa'` and this account's id, so it cannot be
1360
+ * presented to `passkeys/login/verify` and a sign-in challenge cannot be
1361
+ * presented here.
1362
+ */
1363
+ declare function startStepUpService(userId: number): Promise<PublicKeyCredentialRequestOptionsJSON>;
1364
+ interface StepUpParams {
1365
+ userId: number;
1366
+ /** The device the verification is recorded against. */
1367
+ keyId: string;
1368
+ code?: string;
1369
+ recoveryCode?: string;
1370
+ response?: AuthenticationResponseJSON;
1371
+ }
1372
+ /**
1373
+ * Re-prove the second factor on this device, refreshing its window.
1374
+ *
1375
+ * The escape hatch the exempt registration channels need: a device-code
1376
+ * approval and a passkey sign-in register a key with no verification against
1377
+ * it, by design, so the session they create would otherwise fail every
1378
+ * sensitive change with no way forward.
1379
+ *
1380
+ * @throws ValidationError when the body names none or more than one input
1381
+ * @throws MfaNotEnrolledError | MfaVerificationFailedError
1382
+ */
1383
+ declare function stepUpService(params: StepUpParams): Promise<void>;
1384
+ /**
1385
+ * Check exactly one of the three proofs, and say which one it was.
1386
+ *
1387
+ * Exactly one: two inputs in a body is a caller trying combinations, and none
1388
+ * is a malformed request. Neither is a failed verification, so both are a 400
1389
+ * rather than the uniform 401 a wrong proof gets.
1390
+ *
1391
+ * @throws ValidationError | MfaVerificationFailedError
1392
+ */
1393
+ declare function verifySecondFactor(params: StepUpParams): Promise<MfaVerificationMethod>;
1394
+ /**
1395
+ * Drop enrolments nobody ever confirmed.
1396
+ *
1397
+ * A secret handed out and abandoned is a credential sitting in a table doing
1398
+ * nothing; a day is long enough for anyone who meant to finish.
1399
+ *
1400
+ * @returns number of rows deleted
1401
+ */
1402
+ declare function sweepUnconfirmedMfaService(): Promise<{
1403
+ deleted: number;
1404
+ }>;
1405
+
1059
1406
  /**
1060
1407
  * Auth provider type
1061
1408
  *
@@ -1070,10 +1417,16 @@ declare const AuthProviderSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TL
1070
1417
  * - OAuth 기존 사용자 로그인 시
1071
1418
  * - 기기 코드 승인이 소비되어 새 기기 키가 등록될 때 (provider: 'device')
1072
1419
  *
1420
+ * `mfaEnrolled` is computed as the event is emitted (#95) and is the whole of
1421
+ * the package's opinion about the second factor: it never blocks an account
1422
+ * that has none, and this is the hook an app uses to offer enrolment at a first
1423
+ * login. It says nothing about *which* factor and carries no secret.
1424
+ *
1073
1425
  * @example
1074
1426
  * ```typescript
1075
1427
  * authLoginEvent.subscribe(async (payload) => {
1076
1428
  * await analytics.trackLogin(payload.userId, payload.provider);
1429
+ * if (!payload.mfaEnrolled) await suggestSecondFactor(payload.userId);
1077
1430
  * });
1078
1431
  * ```
1079
1432
  */
@@ -1081,7 +1434,8 @@ declare const authLoginEvent: _spfn_core_event.EventDef<{
1081
1434
  email?: string | undefined;
1082
1435
  phone?: string | undefined;
1083
1436
  userId: string;
1084
- provider: "email" | "phone" | "google" | "apple" | "github" | "kakao" | "naver" | "superself" | "device" | "passkey";
1437
+ provider: "email" | "phone" | "google" | "apple" | "github" | "kakao" | "naver" | "superself" | "passkey" | "device";
1438
+ mfaEnrolled: boolean;
1085
1439
  }>;
1086
1440
  /**
1087
1441
  * Where a device key was registered — the door the new device came through.
@@ -1116,6 +1470,10 @@ type DeviceRegistrationChannel = Static<typeof DeviceRegistrationChannelSchema>;
1116
1470
  * Neither the full fingerprint nor the public key is carried. The prefix is
1117
1471
  * enough to point at one entry of `listKeys`, which is what a notice needs.
1118
1472
  *
1473
+ * `mfaEnrolled` is computed as the event is emitted (#95), so a notice about a
1474
+ * new device can also be the moment an app offers a second factor to the
1475
+ * accounts that have none.
1476
+ *
1119
1477
  * @example
1120
1478
  * ```typescript
1121
1479
  * authDeviceRegisteredEvent.subscribe(async ({ userId, deviceName, ip, channel }) => {
@@ -1133,7 +1491,8 @@ declare const authDeviceRegisteredEvent: _spfn_core_event.EventDef<{
1133
1491
  userId: string;
1134
1492
  fingerprintPrefix: string;
1135
1493
  createdAtMillis: number;
1136
- channel: "password" | "register" | "oauth-native" | "oauth" | "invitation" | "signup-link" | "password-reset" | "passkey" | "device-code";
1494
+ mfaEnrolled: boolean;
1495
+ channel: "password" | "register" | "oauth-native" | "passkey" | "oauth" | "invitation" | "signup-link" | "password-reset" | "device-code";
1137
1496
  }>;
1138
1497
  /**
1139
1498
  * auth.register - 회원가입 성공 이벤트
@@ -2272,6 +2631,39 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
2272
2631
  }, {}, {
2273
2632
  passkeyId: string;
2274
2633
  }>;
2634
+ mfaTotpEnroll: _spfn_core_route.RouteDef<{
2635
+ body: _sinclair_typebox.TObject<{}>;
2636
+ }, {}, TotpEnrolmentResult>;
2637
+ mfaTotpConfirm: _spfn_core_route.RouteDef<{
2638
+ body: _sinclair_typebox.TObject<{
2639
+ code: _sinclair_typebox.TString;
2640
+ }>;
2641
+ }, {}, ConfirmTotpResult>;
2642
+ mfaDisable: _spfn_core_route.RouteDef<{
2643
+ body: _sinclair_typebox.TObject<{}>;
2644
+ }, {}, void>;
2645
+ mfaMarkPasskey: _spfn_core_route.RouteDef<{
2646
+ body: _sinclair_typebox.TObject<{
2647
+ passkeyId: _sinclair_typebox.TString;
2648
+ secondFactor: _sinclair_typebox.TBoolean;
2649
+ }>;
2650
+ }, {}, MfaStatus>;
2651
+ mfaRegenerateRecoveryCodes: _spfn_core_route.RouteDef<{
2652
+ body: _sinclair_typebox.TObject<{}>;
2653
+ }, {}, {
2654
+ recoveryCodes: string[];
2655
+ }>;
2656
+ mfaStatus: _spfn_core_route.RouteDef<{}, {}, MfaStatus>;
2657
+ mfaStepUp: _spfn_core_route.RouteDef<{
2658
+ body: _sinclair_typebox.TObject<{
2659
+ code: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2660
+ recoveryCode: _sinclair_typebox.TOptional<_sinclair_typebox.TString>;
2661
+ response: _sinclair_typebox.TOptional<_sinclair_typebox.TUnknown>;
2662
+ }>;
2663
+ }, {}, void>;
2664
+ mfaStepUpOptions: _spfn_core_route.RouteDef<{
2665
+ body: _sinclair_typebox.TObject<{}>;
2666
+ }, {}, _simplewebauthn_server.PublicKeyCredentialRequestOptionsJSON>;
2275
2667
  logout: _spfn_core_route.RouteDef<{}, {}, void>;
2276
2668
  rotateKey: _spfn_core_route.RouteDef<{}, {
2277
2669
  body: _sinclair_typebox.TObject<{
@@ -3084,4 +3476,4 @@ declare const machineAuth: _spfn_core_route.NamedMiddleware<"machineAuth">;
3084
3476
  */
3085
3477
  declare const requireMachineScope: _spfn_core_route.NamedMiddlewareFactory<"machineScope", string[]>;
3086
3478
 
3087
- export { type DenyDeviceAuthParams as $, type AuthInitOptions as A, type AuthDeletionRequestedPayload as B, type ConfirmSignupLinkResult as C, type DeviceAuthInfoResult as D, type AuthDeviceRegisteredPayload as E, type FinishPasskeyEnrollmentResult as F, type AuthLoginPayload as G, type AuthPasswordResetPayload as H, type IssueOneTimeTokenResult as I, type AuthProfileOutcome as J, type KeySummary as K, type LoginResult as L, type AuthProfileVerifier as M, type NewPasskey as N, type OAuthStartResult as O, type PermissionConfig as P, AuthProviderSchema as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type AuthRegisterPayload as T, type UserProfile as U, VERIFICATION_PURPOSES as V, type ChangePasswordParams as W, type CompletePasswordResetParams as X, type CompleteSignupParams as Y, type ConfirmPasswordResetParams as Z, type ConfirmSignupLinkParams as _, type RegisterResult as a, assertRecentAuthentication as a$, type DeviceAuthApprovedResult as a0, type DeviceAuthInfoParams as a1, type DeviceAuthPendingResult as a2, DeviceAuthPollResponseSchema as a3, DeviceNameSchema as a4, type DeviceRegistrationChannel as a5, EmailSchema as a6, FingerprintSchema as a7, type FinishPasskeyEnrollmentParams as a8, type FinishPasskeyLoginParams as a9, type PollDeviceAuthResult as aA, PublicKeySchema as aB, type RecentAuthenticationParams as aC, type RegisterParams as aD, type RegisterPublicKeyParams as aE, type RenamePasskeyParams as aF, type RequestPasswordResetParams as aG, type RequestSignupLinkParams as aH, type RevokeAllKeysParams as aI, type RevokeKeyParams as aJ, type RevokePasskeyParams as aK, type RotateKeyParams as aL, type SendVerificationCodeParams as aM, type StartDeviceAuthParams as aN, type StartPasskeyEnrollmentParams as aO, TargetTypeSchema as aP, type UnlinkNotification as aQ, UnlinkNotifyRejection as aR, type UnlinkNotifyRequest as aS, type UnlinkNotifyResult as aT, UserCodeSchema as aU, VerificationPurposeSchema as aV, type VerifyCodeParams as aW, type VerifyCodeResult as aX, approveDeviceAuthService as aY, approveOAuth2AuthorizeService as aZ, assertNotLastRecoveryCredential as a_, type InvitationAcceptedPayload as aa, type InvitationCreatedPayload as ab, KEY_FINGERPRINT_PREFIX_LENGTH as ac, KeyIdSchema as ad, type LoginParams as ae, type LogoutParams as af, type MachinePrincipal as ag, type MachineVerifierRegistration as ah, type NativeVerifyOptions as ai, type NormalizedIdentity as aj, type OAuth2AuthorizeParams as ak, type OAuth2ScopeDescription as al, type OAuthCallbackParams as am, type OAuthCallbackResult as an, type OAuthCodeExchangeOptions as ao, type OAuthNativeParams as ap, type OAuthStartParams as aq, type OAuthTokens as ar, type OAuthUnlinkedPayload as as, PASSKEY_DEVICE_TYPES as at, PASSKEY_LABEL_MAX_LENGTH as au, type PasskeyDeviceType as av, PasswordSchema as aw, PhoneSchema as ax, PlatformSchema as ay, type PollDeviceAuthParams as az, type RequestSignupLinkResult as b, startDeviceAuthService as b$, authDeletionCancelledEvent as b0, authDeletionCompletedEvent as b1, authDeletionRequestedEvent as b2, authDeviceRegisteredEvent as b3, authLoginEvent as b4, authPasswordResetEvent as b5, authRegisterEvent as b6, authenticate as b7, buildOAuthErrorUrl as b8, changePasswordService as b9, oauthNativeService as bA, oauthStartService as bB, oauthUnlinkNotifyService as bC, oauthUnlinkedEvent as bD, optionalAuth as bE, passkeys as bF, pollDeviceAuthService as bG, registerAuthProfile as bH, registerMachineVerifier as bI, registerOAuthProvider as bJ, registerPublicKeyService as bK, registerService as bL, renamePasskeyService as bM, requestPasswordResetService as bN, requestSignupLinkService as bO, requireEnabledProvider as bP, requireMachineScope as bQ, resolveAuthenticatedUser as bR, revokeAllKeysService as bS, revokeAllOAuth2GrantsForUser as bT, revokeKeyService as bU, revokeOAuth2GrantService as bV, revokePasskeyService as bW, rotateKeyService as bX, runAuthProfile as bY, selectAuthProfile as bZ, sendVerificationCodeService as b_, completePasswordResetService as ba, completeSignupService as bb, confirmPasswordResetService as bc, confirmSignupLinkService as bd, denyDeviceAuthService as be, denyOAuth2AuthorizeService as bf, describeOAuth2AuthorizeRequestService as bg, finishPasskeyEnrollmentService as bh, finishPasskeyLoginService as bi, getDeviceAuthInfoService as bj, getEnabledOAuthProviders as bk, getGoogleAccessToken as bl, getMachinePrincipal as bm, getOAuthProvider as bn, getRegisteredProviders as bo, invitationAcceptedEvent as bp, invitationCreatedEvent as bq, isOAuthProviderEnabled as br, issueOneTimeTokenService as bs, listKeysService as bt, listOAuth2GrantsService as bu, listPasskeysService as bv, loginService as bw, logoutService as bx, machineAuth as by, oauthCallbackService as bz, type RequestPasswordResetResult as c, startPasskeyEnrollmentService as c0, startPasskeyLoginService as c1, verifyCodeService as c2, verifyOneTimeTokenService as c3, type ConfirmPasswordResetResult as d, type StartDeviceAuthResult as e, type PasskeySummary as f, type RotateKeyResult as g, type RevokeAllKeysResult as h, type OAuthNativeResult as i, type ProfileInfo as j, type OAuth2ConsentView as k, type OAuth2AuthorizationCodeIssued as l, mainAuthRouter as m, type OAuth2GrantSummary as n, type AuthSession as o, PERMISSION_CATEGORIES as p, type PermissionCategory as q, VERIFICATION_TARGET_TYPES as r, type VerificationPurpose as s, type VerificationTargetType as t, type OAuthProvider as u, type Passkey as v, type AuthContext as w, type ApproveDeviceAuthParams as x, type AuthDeletionCancelledPayload as y, type AuthDeletionCompletedPayload as z };
3479
+ export { type AuthRegisterPayload as $, type AuthInitOptions as A, type ApproveDeviceAuthParams as B, type ConfirmSignupLinkResult as C, type DeviceAuthInfoResult as D, type AssertStepUpParams as E, type FinishPasskeyEnrollmentResult as F, type AuthDeletionCancelledPayload as G, type AuthDeletionCompletedPayload as H, type IssueOneTimeTokenResult as I, type AuthDeletionRequestedPayload as J, type KeySummary as K, type LoginResult as L, type MfaStatus as M, type NewPasskey as N, type OAuthStartResult as O, type PermissionConfig as P, type AuthDeviceRegisteredPayload as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type TotpEnrolmentResult as T, type UserProfile as U, VERIFICATION_PURPOSES as V, type AuthLoginPayload as W, type AuthPasswordResetPayload as X, type AuthProfileOutcome as Y, type AuthProfileVerifier as Z, AuthProviderSchema as _, type RegisterResult as a, type UnlinkNotification as a$, type ChangePasswordParams as a0, type CompletePasswordResetParams as a1, type CompleteSignupParams as a2, type ConfirmPasswordResetParams as a3, type ConfirmSignupLinkParams as a4, type ConfirmTotpParams as a5, type DenyDeviceAuthParams as a6, type DeviceAuthApprovedResult as a7, type DeviceAuthInfoParams as a8, type DeviceAuthPendingResult as a9, type OAuthStartParams as aA, type OAuthTokens as aB, type OAuthUnlinkedPayload as aC, PASSKEY_DEVICE_TYPES as aD, PASSKEY_LABEL_MAX_LENGTH as aE, type PasskeyDeviceType as aF, PasswordSchema as aG, PhoneSchema as aH, PlatformSchema as aI, type PollDeviceAuthParams as aJ, type PollDeviceAuthResult as aK, PublicKeySchema as aL, type RecentAuthenticationParams as aM, type RegisterParams as aN, type RegisterPublicKeyParams as aO, type RenamePasskeyParams as aP, type RequestPasswordResetParams as aQ, type RequestSignupLinkParams as aR, type RevokeAllKeysParams as aS, type RevokeKeyParams as aT, type RevokePasskeyParams as aU, type RotateKeyParams as aV, type SendVerificationCodeParams as aW, type StartDeviceAuthParams as aX, type StartPasskeyEnrollmentParams as aY, type StepUpParams as aZ, TargetTypeSchema as a_, DeviceAuthPollResponseSchema as aa, DeviceNameSchema as ab, type DeviceRegistrationChannel as ac, EmailSchema as ad, FingerprintSchema as ae, type FinishPasskeyEnrollmentParams as af, type FinishPasskeyLoginParams as ag, type InvitationAcceptedPayload as ah, type InvitationCreatedPayload as ai, KEY_FINGERPRINT_PREFIX_LENGTH as aj, KeyIdSchema as ak, type LoginParams as al, type LogoutParams as am, MFA_VERIFICATION_METHODS as an, type MachinePrincipal as ao, type MachineVerifierRegistration as ap, type MarkPasskeyParams as aq, type NativeVerifyOptions as ar, type NewMfaVerification as as, type NormalizedIdentity as at, type OAuth2AuthorizeParams as au, type OAuth2ScopeDescription as av, type OAuthCallbackParams as aw, type OAuthCallbackResult as ax, type OAuthCodeExchangeOptions as ay, type OAuthNativeParams as az, type RequestSignupLinkResult as b, registerAuthProfile as b$, UnlinkNotifyRejection as b0, type UnlinkNotifyRequest as b1, type UnlinkNotifyResult as b2, UserCodeSchema as b3, VerificationPurposeSchema as b4, type VerifyCodeParams as b5, type VerifyCodeResult as b6, approveDeviceAuthService as b7, approveOAuth2AuthorizeService as b8, assertNotLastRecoveryCredential as b9, getGoogleAccessToken as bA, getMachinePrincipal as bB, getOAuthProvider as bC, getRegisteredProviders as bD, invitationAcceptedEvent as bE, invitationCreatedEvent as bF, isOAuthProviderEnabled as bG, issueOneTimeTokenService as bH, listKeysService as bI, listOAuth2GrantsService as bJ, listPasskeysService as bK, loginService as bL, logoutService as bM, machineAuth as bN, markPasskeySecondFactorService as bO, mfaEnrolledForUser as bP, mfaStatusService as bQ, mfaVerifications as bR, oauthCallbackService as bS, oauthNativeService as bT, oauthStartService as bU, oauthUnlinkNotifyService as bV, oauthUnlinkedEvent as bW, optionalAuth as bX, passkeys as bY, pollDeviceAuthService as bZ, regenerateRecoveryCodesService as b_, assertRecentAuthentication as ba, assertStepUp as bb, authDeletionCancelledEvent as bc, authDeletionCompletedEvent as bd, authDeletionRequestedEvent as be, authDeviceRegisteredEvent as bf, authLoginEvent as bg, authPasswordResetEvent as bh, authRegisterEvent as bi, authenticate as bj, buildOAuthErrorUrl as bk, carryStepUpVerification as bl, changePasswordService as bm, completePasswordResetService as bn, completeSignupService as bo, confirmPasswordResetService as bp, confirmSignupLinkService as bq, confirmTotpEnrolmentService as br, denyDeviceAuthService as bs, denyOAuth2AuthorizeService as bt, describeOAuth2AuthorizeRequestService as bu, disableMfaService as bv, finishPasskeyEnrollmentService as bw, finishPasskeyLoginService as bx, getDeviceAuthInfoService as by, getEnabledOAuthProviders as bz, type RequestPasswordResetResult as c, registerMachineVerifier as c0, registerOAuthProvider as c1, registerPublicKeyService as c2, registerService as c3, renamePasskeyService as c4, requestPasswordResetService as c5, requestSignupLinkService as c6, requireEnabledProvider as c7, requireMachineScope as c8, resolveAuthenticatedUser as c9, revokeAllKeysService as ca, revokeAllOAuth2GrantsForUser as cb, revokeKeyService as cc, revokeOAuth2GrantService as cd, revokePasskeyService as ce, rotateKeyService as cf, runAuthProfile as cg, selectAuthProfile as ch, sendVerificationCodeService as ci, startDeviceAuthService as cj, startPasskeyEnrollmentService as ck, startPasskeyLoginService as cl, startStepUpService as cm, startTotpEnrolmentService as cn, stepUpService as co, sweepUnconfirmedMfaService as cp, verifyCodeService as cq, verifyOneTimeTokenService as cr, verifySecondFactor as cs, type ConfirmPasswordResetResult as d, type StartDeviceAuthResult as e, type PasskeySummary as f, type ConfirmTotpResult as g, type RotateKeyResult as h, type RevokeAllKeysResult as i, type OAuthNativeResult as j, type ProfileInfo as k, type OAuth2ConsentView as l, mainAuthRouter as m, type OAuth2AuthorizationCodeIssued as n, type OAuth2GrantSummary as o, type AuthSession as p, PERMISSION_CATEGORIES as q, type PermissionCategory as r, VERIFICATION_TARGET_TYPES as s, type VerificationPurpose as t, type VerificationTargetType as u, type OAuthProvider as v, type Passkey as w, type MfaVerification as x, type MfaVerificationMethod as y, type AuthContext as z };