@finueva/auth 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/device.js CHANGED
@@ -198,7 +198,18 @@ const messages = {
198
198
  platform_target_unavailable: "The platform administration target is unavailable.",
199
199
  platform_quorum_unavailable: "Platform administration quorum is unavailable.",
200
200
  platform_recovery_required: "Platform administration requires separate recovery.",
201
- identity_authority_unavailable: "Authentication is temporarily unavailable."
201
+ identity_authority_unavailable: "Authentication is temporarily unavailable.",
202
+ two_factor_required: "A second authentication factor is required.",
203
+ two_factor_code_invalid: "The verification code is invalid.",
204
+ two_factor_challenge_expired: "The second-factor challenge has ended. Sign in again.",
205
+ two_factor_locked: "Second-factor verification is temporarily locked.",
206
+ recent_sign_in_required: "A recent sign-in is required.",
207
+ enterprise_recovery_required: "Enterprise administration evidence requires operator recovery.",
208
+ recent_authentication_required: "A ready recent-authentication action is required.",
209
+ organization_closure_confirmation_mismatch: "The confirmation does not match the organization.",
210
+ organization_closure_cancellation_ended: "The closure cancellation period has ended.",
211
+ ceremony_return_refused: "The return address is not registered for this application.",
212
+ password_sign_in_required: "A password sign-in method is required for this passkey change."
202
213
  };
203
214
  var AuthError = class extends Error {
204
215
  code;
@@ -327,7 +338,7 @@ function normalizeIdInput(value) {
327
338
  return value;
328
339
  }
329
340
  function normalizeOrganization(value) {
330
- exact(value, [
341
+ exact$2(value, [
331
342
  "capabilities",
332
343
  "id",
333
344
  "lifecycle",
@@ -337,7 +348,7 @@ function normalizeOrganization(value) {
337
348
  "slug"
338
349
  ]);
339
350
  if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 255) || value.lifecycle !== "ordinary" && value.lifecycle !== "managed" || !role(value.role) || !isObject(value.capabilities)) throw authorityUnavailable();
340
- exact(value.capabilities, [
351
+ exact$2(value.capabilities, [
341
352
  "readInvitations",
342
353
  "readMembers",
343
354
  "readTeams"
@@ -399,7 +410,7 @@ function normalizeOrganizationCreationInput(name, slug, idempotencyKey) {
399
410
  };
400
411
  }
401
412
  function normalizeCreatedOrganization(value) {
402
- exact(value, [
413
+ exact$2(value, [
403
414
  "id",
404
415
  "name",
405
416
  "slug"
@@ -419,7 +430,7 @@ function normalizeOrganizationTeamCreationInput(name, idempotencyKey) {
419
430
  };
420
431
  }
421
432
  function normalizeCreatedOrganizationTeam(value) {
422
- exact(value, ["id", "name"]);
433
+ exact$2(value, ["id", "name"]);
423
434
  if (!isId(value.id) || !boundedString(value.name, 255)) throw authorityUnavailable();
424
435
  return {
425
436
  id: value.id,
@@ -446,7 +457,7 @@ function normalizeOrganizationMemberInvitationCreationInput(value) {
446
457
  };
447
458
  }
448
459
  function normalizeCreatedOrganizationMemberInvitation(value) {
449
- exact(value, ["expiresAt", "id"]);
460
+ exact$2(value, ["expiresAt", "id"]);
450
461
  if (!isId(value.id)) throw authorityUnavailable();
451
462
  return {
452
463
  id: value.id,
@@ -454,7 +465,7 @@ function normalizeCreatedOrganizationMemberInvitation(value) {
454
465
  };
455
466
  }
456
467
  function normalizeOrganizations(value) {
457
- exact(value, ["nextCursor", "organizations"]);
468
+ exact$2(value, ["nextCursor", "organizations"]);
458
469
  if (!Array.isArray(value.organizations) || value.organizations.length > 100) throw authorityUnavailable();
459
470
  return {
460
471
  organizations: unique(value.organizations.map(normalizeOrganization), (item) => item.id),
@@ -462,11 +473,11 @@ function normalizeOrganizations(value) {
462
473
  };
463
474
  }
464
475
  function normalizeOrganizationMembers(value) {
465
- exact(value, ["members", "nextCursor"]);
476
+ exact$2(value, ["members", "nextCursor"]);
466
477
  if (!Array.isArray(value.members) || value.members.length > 100) throw authorityUnavailable();
467
478
  return {
468
479
  members: unique(value.members.map((member) => {
469
- exact(member, [
480
+ exact$2(member, [
470
481
  "email",
471
482
  "id",
472
483
  "image",
@@ -495,11 +506,11 @@ function normalizeOrganizationMembers(value) {
495
506
  };
496
507
  }
497
508
  function normalizeOrganizationTeams(value) {
498
- exact(value, ["nextCursor", "teams"]);
509
+ exact$2(value, ["nextCursor", "teams"]);
499
510
  if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
500
511
  return {
501
512
  teams: unique(value.teams.map((team) => {
502
- exact(team, [
513
+ exact$2(team, [
503
514
  "category",
504
515
  "createdAt",
505
516
  "id",
@@ -517,7 +528,7 @@ function normalizeOrganizationTeams(value) {
517
528
  };
518
529
  }
519
530
  function normalizeOrganizationTeamMembers(value) {
520
- exact(value, ["memberIds", "nextCursor"]);
531
+ exact$2(value, ["memberIds", "nextCursor"]);
521
532
  if (!Array.isArray(value.memberIds) || value.memberIds.length > 100) throw authorityUnavailable();
522
533
  return {
523
534
  memberIds: unique(value.memberIds.map((item) => normalizeResponseId(item)), (item) => item),
@@ -525,7 +536,7 @@ function normalizeOrganizationTeamMembers(value) {
525
536
  };
526
537
  }
527
538
  function normalizeOrganizationInvitation(value) {
528
- exact(value, [
539
+ exact$2(value, [
529
540
  "createdAt",
530
541
  "email",
531
542
  "expiresAt",
@@ -536,7 +547,7 @@ function normalizeOrganizationInvitation(value) {
536
547
  "teamIds"
537
548
  ]);
538
549
  if (!isId(value.id) || typeof value.email !== "string" || value.email.length > 320 || !email.test(value.email) || !role(value.role) || value.status !== "pending" || !Array.isArray(value.teamIds) || value.teamIds.length > 100 || !isObject(value.inviter)) throw authorityUnavailable();
539
- exact(value.inviter, ["membershipId", "name"]);
550
+ exact$2(value.inviter, ["membershipId", "name"]);
540
551
  if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
541
552
  return {
542
553
  id: value.id,
@@ -553,7 +564,7 @@ function normalizeOrganizationInvitation(value) {
553
564
  };
554
565
  }
555
566
  function normalizeOrganizationInvitations(value) {
556
- exact(value, ["invitations", "nextCursor"]);
567
+ exact$2(value, ["invitations", "nextCursor"]);
557
568
  if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
558
569
  return {
559
570
  invitations: unique(value.invitations.map(normalizeOrganizationInvitation), (item) => item.id),
@@ -561,7 +572,7 @@ function normalizeOrganizationInvitations(value) {
561
572
  };
562
573
  }
563
574
  function normalizeReceivedInvitation(value) {
564
- exact(value, [
575
+ exact$2(value, [
565
576
  "expiresAt",
566
577
  "id",
567
578
  "inviterName",
@@ -570,7 +581,7 @@ function normalizeReceivedInvitation(value) {
570
581
  "teams"
571
582
  ]);
572
583
  if (!isId(value.id) || !boundedString(value.inviterName, 255) || !role(value.role) || !Array.isArray(value.teams) || value.teams.length > 100 || !isObject(value.organization)) throw authorityUnavailable();
573
- exact(value.organization, [
584
+ exact$2(value.organization, [
574
585
  "id",
575
586
  "logo",
576
587
  "name",
@@ -587,7 +598,7 @@ function normalizeReceivedInvitation(value) {
587
598
  },
588
599
  role: value.role,
589
600
  teams: unique(value.teams.map((team) => {
590
- exact(team, ["id", "name"]);
601
+ exact$2(team, ["id", "name"]);
591
602
  if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
592
603
  return {
593
604
  id: team.id,
@@ -599,7 +610,7 @@ function normalizeReceivedInvitation(value) {
599
610
  };
600
611
  }
601
612
  function normalizeReceivedInvitations(value) {
602
- exact(value, ["invitations", "nextCursor"]);
613
+ exact$2(value, ["invitations", "nextCursor"]);
603
614
  if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
604
615
  return {
605
616
  invitations: unique(value.invitations.map(normalizeReceivedInvitation), (item) => item.id),
@@ -657,8 +668,35 @@ function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
657
668
  if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
658
669
  return fromOrganizationReadAuthorityError(value, status);
659
670
  }
671
+ function normalizeOrganizationClosureStartInput(value) {
672
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "confirmationName,idempotencyKey") throw new TypeError("organization closure input is invalid");
673
+ if (!boundedString(value.confirmationName, 255)) throw new TypeError("confirmationName is invalid");
674
+ return {
675
+ confirmationName: value.confirmationName,
676
+ idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
677
+ };
678
+ }
679
+ function normalizeOrganizationClosureCancelInput(value) {
680
+ if (!isObject(value) || Object.keys(value).join(",") !== "idempotencyKey") throw new TypeError("organization closure cancellation input is invalid");
681
+ return { idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey) };
682
+ }
683
+ function normalizeOrganizationOwnershipTransferInput(value) {
684
+ if (!isObject(value) || Object.keys(value).sort().join(",") !== "expectedActorAuthorityRevision,expectedOutgoingOwnerAuthorityRevision,expectedSuccessorAuthorityRevision,idempotencyKey,outgoingOwnerMembershipId,outgoingOwnerRole,successorMembershipId") throw new TypeError("organization ownership transfer input is invalid");
685
+ if (!isId(value.outgoingOwnerMembershipId) || !isId(value.successorMembershipId)) throw new TypeError("ownership transfer membership is invalid");
686
+ if (value.outgoingOwnerMembershipId === value.successorMembershipId) throw new TypeError("ownership transfer memberships must differ");
687
+ if (value.outgoingOwnerRole !== "admin" && value.outgoingOwnerRole !== "member") throw new TypeError("outgoingOwnerRole is invalid");
688
+ return {
689
+ outgoingOwnerMembershipId: value.outgoingOwnerMembershipId,
690
+ successorMembershipId: value.successorMembershipId,
691
+ outgoingOwnerRole: value.outgoingOwnerRole,
692
+ expectedActorAuthorityRevision: normalizeAuthorityRevision(value.expectedActorAuthorityRevision, "expectedActorAuthorityRevision"),
693
+ expectedOutgoingOwnerAuthorityRevision: normalizeAuthorityRevision(value.expectedOutgoingOwnerAuthorityRevision, "expectedOutgoingOwnerAuthorityRevision", true),
694
+ expectedSuccessorAuthorityRevision: normalizeAuthorityRevision(value.expectedSuccessorAuthorityRevision, "expectedSuccessorAuthorityRevision", true),
695
+ idempotencyKey: normalizeAuthorityIdempotencyKey(value.idempotencyKey)
696
+ };
697
+ }
660
698
  function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
661
- exact(value, [
699
+ exact$2(value, [
662
700
  "organizationId",
663
701
  "actor",
664
702
  "target"
@@ -676,7 +714,7 @@ function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
676
714
  };
677
715
  }
678
716
  function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = false) {
679
- exact(value, [
717
+ exact$2(value, [
680
718
  "memberId",
681
719
  "manualRole",
682
720
  "role",
@@ -691,10 +729,18 @@ function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = fal
691
729
  authorityRevision: normalizeAuthorityResultRevision(value.authorityRevision)
692
730
  };
693
731
  }
732
+ function normalizeAuthorityRevision(value, name, incremented = false) {
733
+ if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER - (incremented ? 1 : 0)) throw new TypeError(`${name} is invalid`);
734
+ return value;
735
+ }
694
736
  function normalizeAuthorityResultRevision(value) {
695
737
  if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER) throw authorityUnavailable();
696
738
  return value;
697
739
  }
740
+ function normalizeAuthorityIdempotencyKey(value) {
741
+ if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(value)) throw new TypeError("idempotencyKey is invalid");
742
+ return value;
743
+ }
698
744
  function mapError(code, status) {
699
745
  if (code === "authentication_required") return {
700
746
  code,
@@ -769,7 +815,7 @@ function normalizeProfileImage(value) {
769
815
  function isId(value) {
770
816
  return typeof value === "string" && id.test(value);
771
817
  }
772
- function exact(value, keys) {
818
+ function exact$2(value, keys) {
773
819
  if (!isObject(value) || Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) throw authorityUnavailable();
774
820
  }
775
821
  function boundedString(value, maximum) {
@@ -1230,6 +1276,237 @@ async function readJson(response, maximum = MAX_RESPONSE_BYTES) {
1230
1276
  }
1231
1277
  }
1232
1278
  //#endregion
1279
+ //#region src/two-factor.ts
1280
+ function isTwoFactorChallenge(value) {
1281
+ return isObject(value) && value.twoFactorRedirect === true;
1282
+ }
1283
+ function normalizeTwoFactorStatus(value) {
1284
+ if (value === null) throw new AuthError("authentication_required", 401);
1285
+ if (!isObject(value) || !isObject(value.user) || typeof value.user.twoFactorEnabled !== "boolean") throw authorityUnavailable();
1286
+ return { enabled: value.user.twoFactorEnabled };
1287
+ }
1288
+ //#endregion
1289
+ //#region src/sessions.ts
1290
+ const idPattern$1 = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
1291
+ const MAX_SESSIONS = 50;
1292
+ const itemKeys$1 = [
1293
+ "createdAt",
1294
+ "current",
1295
+ "expiresAt",
1296
+ "id",
1297
+ "ipAddress",
1298
+ "updatedAt",
1299
+ "userAgent"
1300
+ ];
1301
+ function exact$1(value, keys) {
1302
+ return isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
1303
+ }
1304
+ function date$1(value) {
1305
+ if (typeof value !== "string") throw authorityUnavailable();
1306
+ const parsed = new Date(value);
1307
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) throw authorityUnavailable();
1308
+ return parsed;
1309
+ }
1310
+ function text(value, maximum) {
1311
+ if (value === null) return null;
1312
+ if (typeof value !== "string" || value.length === 0 || value.length > maximum || /[^\x20-\x7e]/.test(value)) throw authorityUnavailable();
1313
+ return value;
1314
+ }
1315
+ function normalizeSessionId(value) {
1316
+ if (typeof value !== "string" || !idPattern$1.test(value)) throw new TypeError("sessionId is invalid");
1317
+ return value;
1318
+ }
1319
+ function normalizeSessionSummary(value) {
1320
+ if (!exact$1(value, itemKeys$1) || typeof value.id !== "string" || !idPattern$1.test(value.id)) throw authorityUnavailable();
1321
+ if (typeof value.current !== "boolean") throw authorityUnavailable();
1322
+ return {
1323
+ id: value.id,
1324
+ current: value.current,
1325
+ createdAt: date$1(value.createdAt),
1326
+ updatedAt: date$1(value.updatedAt),
1327
+ expiresAt: date$1(value.expiresAt),
1328
+ userAgent: text(value.userAgent, 512),
1329
+ ipAddress: text(value.ipAddress, 64)
1330
+ };
1331
+ }
1332
+ function normalizeSessionInventory(value) {
1333
+ if (!exact$1(value, ["sessions", "truncated"]) || !Array.isArray(value.sessions) || value.sessions.length > MAX_SESSIONS || typeof value.truncated !== "boolean") throw authorityUnavailable();
1334
+ const sessions = value.sessions.map(normalizeSessionSummary);
1335
+ if (new Set(sessions.map((session) => session.id)).size !== sessions.length) throw authorityUnavailable();
1336
+ if (sessions.filter((session) => session.current).length !== 1) throw authorityUnavailable();
1337
+ return {
1338
+ sessions,
1339
+ truncated: value.truncated
1340
+ };
1341
+ }
1342
+ function normalizeSessionRevocation(value) {
1343
+ if (!exact$1(value, ["status"]) || value.status !== "revoked") throw authorityUnavailable();
1344
+ }
1345
+ function normalizeOtherSessionRevocation(value) {
1346
+ if (!exact$1(value, ["revoked"]) || !Number.isSafeInteger(value.revoked) || value.revoked < 0) throw authorityUnavailable();
1347
+ return { revoked: value.revoked };
1348
+ }
1349
+ function fromSessionInventoryError(_value, status, retryAfter) {
1350
+ if (status === 400) return new AuthError("invalid_request", 400);
1351
+ if (status === 401) return new AuthError("authentication_required", 401);
1352
+ if (status === 403) return new AuthError("request_origin_denied", 403);
1353
+ if (status === 404 || status === 409) return new AuthError("state_conflict", 409);
1354
+ if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
1355
+ return authorityUnavailable();
1356
+ }
1357
+ //#endregion
1358
+ //#region src/passkeys.ts
1359
+ const idPattern = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
1360
+ const MAX_PASSKEYS = 50;
1361
+ const MAX_RETURN_BYTES = 2048;
1362
+ const PASSKEY_NAME_MAX_LENGTH = 64;
1363
+ const itemKeys = [
1364
+ "backedUp",
1365
+ "createdAt",
1366
+ "deviceType",
1367
+ "id",
1368
+ "name"
1369
+ ];
1370
+ function exact(value, keys) {
1371
+ return isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
1372
+ }
1373
+ function date(value) {
1374
+ if (typeof value !== "string") throw authorityUnavailable();
1375
+ const parsed = new Date(value);
1376
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== value) throw authorityUnavailable();
1377
+ return parsed;
1378
+ }
1379
+ function returnInput(value) {
1380
+ if (!isObject(value)) throw new TypeError("ceremony input is invalid");
1381
+ const { applicationId, returnTo } = value;
1382
+ if (typeof applicationId !== "string" || !idPattern.test(applicationId)) throw new TypeError("applicationId is invalid");
1383
+ if (typeof returnTo !== "string" || new TextEncoder().encode(returnTo).byteLength > MAX_RETURN_BYTES || !URL.canParse(returnTo) || new URL(returnTo).toString() !== returnTo) throw new TypeError("returnTo is invalid");
1384
+ return {
1385
+ applicationId,
1386
+ returnTo
1387
+ };
1388
+ }
1389
+ function normalizeCeremonyHandoffInput(value) {
1390
+ const base = returnInput(value);
1391
+ const input = value;
1392
+ switch (input.purpose) {
1393
+ case "passkey_enrollment": return {
1394
+ purpose: input.purpose,
1395
+ ...base
1396
+ };
1397
+ case "passkey_removal": return {
1398
+ purpose: input.purpose,
1399
+ ...base,
1400
+ passkeyId: normalizePasskeyId(input.passkeyId)
1401
+ };
1402
+ case "recent_authentication": {
1403
+ const request = input.request;
1404
+ if (!isObject(request)) throw new TypeError("request is invalid");
1405
+ const organizationId = normalizeIdInput(request.organizationId);
1406
+ if (request.action === "organization_ownership_transfer") {
1407
+ const { action: _action, organizationId: _organizationId, ...transfer } = request;
1408
+ return {
1409
+ purpose: input.purpose,
1410
+ ...base,
1411
+ request: {
1412
+ action: request.action,
1413
+ organizationId,
1414
+ ...normalizeOrganizationOwnershipTransferInput(transfer)
1415
+ }
1416
+ };
1417
+ }
1418
+ if (request.action === "organization_closure_start") {
1419
+ const { action: _action, organizationId: _organizationId, ...closure } = request;
1420
+ return {
1421
+ purpose: input.purpose,
1422
+ ...base,
1423
+ request: {
1424
+ action: request.action,
1425
+ organizationId,
1426
+ ...normalizeOrganizationClosureStartInput(closure)
1427
+ }
1428
+ };
1429
+ }
1430
+ if (request.action === "organization_closure_cancel") {
1431
+ const { action: _action, organizationId: _organizationId, ...closure } = request;
1432
+ return {
1433
+ purpose: input.purpose,
1434
+ ...base,
1435
+ request: {
1436
+ action: request.action,
1437
+ organizationId,
1438
+ ...normalizeOrganizationClosureCancelInput(closure)
1439
+ }
1440
+ };
1441
+ }
1442
+ throw new TypeError("request action is invalid");
1443
+ }
1444
+ default: throw new TypeError("purpose is invalid");
1445
+ }
1446
+ }
1447
+ function normalizeCeremonyHandoff(value) {
1448
+ if (!exact(value, ["expiresAt", "url"]) || typeof value.url !== "string") throw authorityUnavailable();
1449
+ let url;
1450
+ try {
1451
+ url = new URL(value.url);
1452
+ } catch {
1453
+ throw authorityUnavailable();
1454
+ }
1455
+ const local = url.hostname === "localhost" || url.hostname.endsWith(".localhost");
1456
+ if (url.protocol !== "https:" && !(local && url.protocol === "http:") || url.username || url.password || url.pathname !== "/api/v1/auth/ceremony/start" || url.search || !/^#code=[A-Za-z0-9_-]{43}$/.test(url.hash)) throw authorityUnavailable();
1457
+ return {
1458
+ url: url.toString(),
1459
+ expiresAt: date(value.expiresAt)
1460
+ };
1461
+ }
1462
+ function normalizePasskeyId(value) {
1463
+ if (typeof value !== "string" || !idPattern.test(value)) throw new TypeError("passkeyId is invalid");
1464
+ return value;
1465
+ }
1466
+ function normalizePasskeyName(value) {
1467
+ if (typeof value !== "string") throw new TypeError("name is invalid");
1468
+ const name = value.trim();
1469
+ if (!name || name.length > PASSKEY_NAME_MAX_LENGTH || /[\p{Cc}\p{Cf}]/u.test(name)) throw new TypeError("name is invalid");
1470
+ return name;
1471
+ }
1472
+ function normalizePasskeySummary(value) {
1473
+ if (!exact(value, itemKeys) || typeof value.id !== "string" || !idPattern.test(value.id)) throw authorityUnavailable();
1474
+ if (value.name !== null && (typeof value.name !== "string" || value.name.length > PASSKEY_NAME_MAX_LENGTH)) throw authorityUnavailable();
1475
+ if (value.deviceType !== "singleDevice" && value.deviceType !== "multiDevice") throw authorityUnavailable();
1476
+ if (typeof value.backedUp !== "boolean") throw authorityUnavailable();
1477
+ return {
1478
+ id: value.id,
1479
+ name: value.name,
1480
+ createdAt: value.createdAt === null ? null : date(value.createdAt),
1481
+ deviceType: value.deviceType,
1482
+ backedUp: value.backedUp
1483
+ };
1484
+ }
1485
+ function normalizePasskeyInventory(value) {
1486
+ if (!exact(value, ["passkeys", "truncated"]) || !Array.isArray(value.passkeys) || value.passkeys.length > MAX_PASSKEYS || typeof value.truncated !== "boolean") throw authorityUnavailable();
1487
+ const passkeys = value.passkeys.map(normalizePasskeySummary);
1488
+ if (new Set(passkeys.map((passkey) => passkey.id)).size !== passkeys.length) throw authorityUnavailable();
1489
+ return {
1490
+ passkeys,
1491
+ truncated: value.truncated
1492
+ };
1493
+ }
1494
+ function normalizePasskeyRename(value) {
1495
+ if (!exact(value, ["status"]) || value.status !== "renamed") throw authorityUnavailable();
1496
+ }
1497
+ function fromCeremonyHandoffError(value, status, retryAfter) {
1498
+ const code = isObject(value) ? value.code : void 0;
1499
+ if (status === 400 && code === "RETURN_ADDRESS_REFUSED") return new AuthError("ceremony_return_refused", 400);
1500
+ if (status === 400) return new AuthError("invalid_request", 400);
1501
+ if (status === 401) return new AuthError("authentication_required", 401);
1502
+ if (status === 403) return new AuthError("request_origin_denied", 403);
1503
+ if (status === 404) return new AuthError("state_conflict", 409);
1504
+ if (status === 409 && code === "PASSWORD_REQUIRED") return new AuthError("password_sign_in_required", 409);
1505
+ if (status === 409) return new AuthError("state_conflict", 409);
1506
+ if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
1507
+ return authorityUnavailable();
1508
+ }
1509
+ //#endregion
1233
1510
  //#region src/device.ts
1234
1511
  const DEVICE_SCOPE = "openid";
1235
1512
  const GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
@@ -1438,6 +1715,34 @@ function createDeviceAuth(options) {
1438
1715
  mapError: fromAccountAuthorityError
1439
1716
  });
1440
1717
  }
1718
+ async function sessionInventoryRequest(method, path, normalize) {
1719
+ const current = await readToken();
1720
+ if (!current) throw new AuthError("authentication_required", 401);
1721
+ return normalize((await requestJsonResponse(joinURL(authOrigin, "api/v1/auth/sessions", path), {
1722
+ fetch: requestFetch,
1723
+ timeoutMs,
1724
+ method,
1725
+ credentials: "omit",
1726
+ headers: { authorization: `Bearer ${current.accessToken}` },
1727
+ mapError: fromSessionInventoryError
1728
+ })).value);
1729
+ }
1730
+ async function ceremonyRequest(method, path, body, normalize) {
1731
+ const current = await readToken();
1732
+ if (!current) throw new AuthError("authentication_required", 401);
1733
+ return normalize((await requestJsonResponse(joinURL(authOrigin, "api/v1/auth", path), {
1734
+ fetch: requestFetch,
1735
+ timeoutMs,
1736
+ method,
1737
+ credentials: "omit",
1738
+ headers: {
1739
+ authorization: `Bearer ${current.accessToken}`,
1740
+ ...body ? { "content-type": "application/json" } : {}
1741
+ },
1742
+ ...body ? { body } : {},
1743
+ mapError: fromCeremonyHandoffError
1744
+ })).value);
1745
+ }
1441
1746
  async function revoke(path) {
1442
1747
  const current = await readToken();
1443
1748
  if (!current) return;
@@ -1840,9 +2145,60 @@ function createDeviceAuth(options) {
1840
2145
  }
1841
2146
  return serializeAuthority(async () => {
1842
2147
  const previous = await readToken();
1843
- return replaceIssuedResponse((await accountRequest("sign-in/email", body)).value, previous);
2148
+ const response = await accountRequest("sign-in/email", body);
2149
+ if (isTwoFactorChallenge(response.value)) throw new AuthError("two_factor_required", 401);
2150
+ return replaceIssuedResponse(response.value, previous);
1844
2151
  }, true);
1845
2152
  },
2153
+ listSessions() {
2154
+ return serializeAuthority(() => sessionInventoryRequest("GET", "", normalizeSessionInventory));
2155
+ },
2156
+ revokeSession(sessionId) {
2157
+ let id;
2158
+ try {
2159
+ id = normalizeSessionId(sessionId);
2160
+ } catch (error) {
2161
+ return Promise.reject(error);
2162
+ }
2163
+ return serializeAuthority(async () => {
2164
+ await sessionInventoryRequest("POST", `${id}/revoke`, normalizeSessionRevocation);
2165
+ });
2166
+ },
2167
+ revokeOtherSessions() {
2168
+ return serializeAuthority(() => sessionInventoryRequest("POST", "revoke-others", normalizeOtherSessionRevocation));
2169
+ },
2170
+ createCeremonyHandoff(input) {
2171
+ let body;
2172
+ try {
2173
+ body = normalizeCeremonyHandoffInput(input);
2174
+ } catch (error) {
2175
+ return Promise.reject(error);
2176
+ }
2177
+ return serializeAuthority(() => ceremonyRequest("POST", "ceremony-handoffs", body, normalizeCeremonyHandoff));
2178
+ },
2179
+ listPasskeys() {
2180
+ return serializeAuthority(() => ceremonyRequest("GET", "passkeys", void 0, normalizePasskeyInventory));
2181
+ },
2182
+ renamePasskey(passkeyId, name) {
2183
+ let path;
2184
+ let body;
2185
+ try {
2186
+ path = `passkeys/${normalizePasskeyId(passkeyId)}/name`;
2187
+ body = { name: normalizePasskeyName(name) };
2188
+ } catch (error) {
2189
+ return Promise.reject(error);
2190
+ }
2191
+ return serializeAuthority(async () => {
2192
+ await ceremonyRequest("POST", path, body, normalizePasskeyRename);
2193
+ });
2194
+ },
2195
+ getTwoFactorStatus() {
2196
+ return serializeAuthority(async () => {
2197
+ const current = await readToken();
2198
+ if (!current) throw new AuthError("authentication_required", 401);
2199
+ return normalizeTwoFactorStatus((await authenticated("get-session", current)).value);
2200
+ });
2201
+ },
1846
2202
  signInWithSocialIdToken(input) {
1847
2203
  let body;
1848
2204
  try {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as AuthError, A as OrganizationTeamPage, B as ReceivedOrganizationInvitation, C as OrganizationMemberAuthority, D as OrganizationTeam, E as OrganizationPageInput, F as PlatformRoleApplied, G as SendVerificationEmailInput, H as RecentAuthenticationStatus, I as PlatformRoleApproval, J as SocialIdTokenProvider, K as SignInInput, L as PlatformRoleChangeRecentAuthenticationInput, M as PersonalWorkspaceSelection, N as PlatformBootstrapRoleChangeInput, O as OrganizationTeamDisplay, P as PlatformRole, Q as WorkspaceSelection, R as PlatformRoleFirstApproval, S as OrganizationMember, T as OrganizationPage, U as RemovedOrganizationMember, V as ReceivedOrganizationInvitationPage, W as ResentOrganizationInvitation, X as UpdateOrganizationTeamDisplayInput, Y as UpdateOrganizationDisplayInput, Z as UpdateProfileInput, _ as InvitationAcceptance, a as AuthPersistenceDriver, b as OrganizationInvitation, c as AuthUser, d as CreatedOrganization, et as AuthErrorCode, f as CreatedOrganizationMemberInvitation, g as FinuevaAuthClient, h as DriveCredentialInput, i as AuthPersistence, j as OrganizationWorkspaceSelection, k as OrganizationTeamMemberPage, l as CanceledOrganizationInvitation, m as DriveCredential, n as AuthClientOptions, nt as UserApiCredential, o as AuthSession, p as CreatedOrganizationTeam, q as SocialIdTokenInput, r as AuthOrganization, rt as UserApiCredentialInput, s as AuthState, t as AcceptInvitationInput, tt as AuthErrorStatus, u as CreateOrganizationMemberInvitationInput, v as OrganizationDeparture, w as OrganizationMemberPage, x as OrganizationInvitationPage, y as OrganizationDisplay, z as PlatformStatus } from "./types-CrdIcEJ3.js";
1
+ import { $ as PlatformBootstrapRoleChangeInput, A as FinuevaAuthClient, At as AuthError, B as OrganizationMember, C as DeclineInvitationInput, Ct as TwoFactorEnrollment, D as DriveCredential, Dt as UpdateOrganizationTeamDisplayInput, E as DepartedOrganizationMemberPage, Et as UpdateOrganizationDisplayInput, F as OrganizationClosureStartInput, G as OrganizationTeam, H as OrganizationMemberPage, I as OrganizationDeparture, J as OrganizationTeamPage, K as OrganizationTeamDisplay, L as OrganizationDisplay, M as InvitationDecline, Mt as AuthErrorStatus, N as OrganizationClosure, Nt as UserApiCredential, O as DriveCredentialInput, Ot as UpdateProfileInput, P as OrganizationClosureCancelInput, Pt as UserApiCredentialInput, Q as PersonalWorkspaceSelection, R as OrganizationInvitation, S as CreatedOrganizationTeam, St as SuspendedOrganizationMemberStatus, T as DepartedOrganizationMember, Tt as TwoFactorStepUpInput, U as OrganizationPage, V as OrganizationMemberAuthority, W as OrganizationPageInput, X as PasskeyInventory, Y as OrganizationWorkspaceSelection, Z as PasskeySummary, _ as ClosingOrganization, _t as SignInInput, a as AuthPersistence, at as PlatformStatus, b as CreatedOrganization, bt as SuspendedOrganizationMember, c as AuthSessionInventory, ct as RecentAuthenticationStatus, d as AuthUser, dt as ResentOrganizationInvitation, et as PlatformRole, f as CanceledOrganizationInvitation, ft as RestoredOrganizationMember, g as CeremonyReturnInput, gt as SendVerificationEmailInput, h as CeremonyRecentAuthenticationRequest, ht as ScimCredentialState, i as AuthOrganization, it as PlatformRoleFirstApproval, j as InvitationAcceptance, jt as AuthErrorCode, k as EnterpriseConnection, kt as WorkspaceSelection, l as AuthSessionSummary, lt as RemovedOrganizationMember, m as CeremonyHandoffInput, mt as ScimCredentialIssuance, n as AddedOrganizationTeamMember, nt as PlatformRoleApproval, o as AuthPersistenceDriver, ot as ReceivedOrganizationInvitation, p as CeremonyHandoff, pt as RotateScimCredentialInput, q as OrganizationTeamMemberPage, r as AuthClientOptions, rt as PlatformRoleChangeRecentAuthenticationInput, s as AuthSession, st as ReceivedOrganizationInvitationPage, t as AcceptInvitationInput, tt as PlatformRoleApplied, u as AuthState, ut as RemovedOrganizationTeamMember, v as ClosingOrganizationList, vt as SocialIdTokenInput, w as DeletedOrganizationTeam, wt as TwoFactorStatus, x as CreatedOrganizationMemberInvitation, xt as SuspendedOrganizationMemberPage, y as CreateOrganizationMemberInvitationInput, yt as SocialIdTokenProvider, z as OrganizationInvitationPage } from "./types-BEgD_Js1.js";
2
2
  //#region src/client.d.ts
3
3
  declare function createAuthClient(options: AuthClientOptions): FinuevaAuthClient;
4
4
  //#endregion
5
- export { type AcceptInvitationInput, type AuthClientOptions, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthPersistence, type AuthPersistenceDriver, type AuthSession, type AuthState, type AuthUser, type CanceledOrganizationInvitation, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type FinuevaAuthClient, type InvitationAcceptance, type OrganizationDeparture, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationPage, type OrganizationPageInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, type OrganizationWorkspaceSelection, type PersonalWorkspaceSelection, type PlatformBootstrapRoleChangeInput, type PlatformRole, type PlatformRoleApplied, type PlatformRoleApproval, type PlatformRoleChangeRecentAuthenticationInput, type PlatformRoleFirstApproval, type PlatformStatus, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RecentAuthenticationStatus, type RemovedOrganizationMember, type ResentOrganizationInvitation, type SendVerificationEmailInput, type SignInInput, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type UserApiCredential, type UserApiCredentialInput, type WorkspaceSelection, createAuthClient };
5
+ export { type AcceptInvitationInput, type AddedOrganizationTeamMember, type AuthClientOptions, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthPersistence, type AuthPersistenceDriver, type AuthSession, type AuthSessionInventory, type AuthSessionSummary, type AuthState, type AuthUser, type CanceledOrganizationInvitation, type CeremonyHandoff, type CeremonyHandoffInput, type CeremonyRecentAuthenticationRequest, type CeremonyReturnInput, type ClosingOrganization, type ClosingOrganizationList, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DeclineInvitationInput, type DeletedOrganizationTeam, type DepartedOrganizationMember, type DepartedOrganizationMemberPage, type DriveCredential, type DriveCredentialInput, type EnterpriseConnection, type FinuevaAuthClient, type InvitationAcceptance, type InvitationDecline, type OrganizationClosure, type OrganizationClosureCancelInput, type OrganizationClosureStartInput, type OrganizationDeparture, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationPage, type OrganizationPageInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, type OrganizationWorkspaceSelection, type PasskeyInventory, type PasskeySummary, type PersonalWorkspaceSelection, type PlatformBootstrapRoleChangeInput, type PlatformRole, type PlatformRoleApplied, type PlatformRoleApproval, type PlatformRoleChangeRecentAuthenticationInput, type PlatformRoleFirstApproval, type PlatformStatus, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RecentAuthenticationStatus, type RemovedOrganizationMember, type RemovedOrganizationTeamMember, type ResentOrganizationInvitation, type RestoredOrganizationMember, type RotateScimCredentialInput, type ScimCredentialIssuance, type ScimCredentialState, type SendVerificationEmailInput, type SignInInput, type SocialIdTokenInput, type SocialIdTokenProvider, type SuspendedOrganizationMember, type SuspendedOrganizationMemberPage, type SuspendedOrganizationMemberStatus, type TwoFactorEnrollment, type TwoFactorStatus, type TwoFactorStepUpInput, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UpdateProfileInput, type UserApiCredential, type UserApiCredentialInput, type WorkspaceSelection, createAuthClient };