@productcraft/auth 0.5.2 → 0.7.1

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/index.cjs CHANGED
@@ -765,11 +765,15 @@ function getApiKeyControllerListApiKeysUrl({
765
765
  const res = { method: "GET", url: `/v1/apps/${app_id}/api-keys` };
766
766
  return res;
767
767
  }
768
- async function apiKeyControllerListApiKeys({ appId }, config = {}) {
768
+ async function apiKeyControllerListApiKeys({
769
+ appId,
770
+ params
771
+ }, config = {}) {
769
772
  const { client: request = client, ...requestConfig } = config;
770
773
  const res = await request({
771
774
  method: "GET",
772
775
  url: getApiKeyControllerListApiKeysUrl({ appId }).url.toString(),
776
+ params,
773
777
  ...requestConfig
774
778
  });
775
779
  return res.data;
@@ -1031,7 +1035,9 @@ async function appAuditControllerGetAuditLogs({
1031
1035
  limit: params.limit,
1032
1036
  cursor: params.cursor,
1033
1037
  action: params.action,
1034
- actor_id: params.actorId
1038
+ actor_id: params.actorId,
1039
+ since: params.since,
1040
+ until: params.until
1035
1041
  } : void 0;
1036
1042
  const res = await request({
1037
1043
  method: "GET",
@@ -1361,6 +1367,36 @@ async function consumerAuthControllerRequestPasswordReset({
1361
1367
  return res.data;
1362
1368
  }
1363
1369
 
1370
+ // src/_generated/clients/consumerAuth/consumerAuthControllerSendPasswordResetEmail.ts
1371
+ function getConsumerAuthControllerSendPasswordResetEmailUrl({
1372
+ appSlug
1373
+ }) {
1374
+ const app_slug = appSlug;
1375
+ const res = {
1376
+ method: "POST",
1377
+ url: `/${app_slug}/v1/auth/send-password-reset-email`
1378
+ };
1379
+ return res;
1380
+ }
1381
+ async function consumerAuthControllerSendPasswordResetEmail({
1382
+ appSlug,
1383
+ data,
1384
+ headers
1385
+ }, config = {}) {
1386
+ const { client: request = client, ...requestConfig } = config;
1387
+ const requestData = data;
1388
+ const res = await request({
1389
+ method: "POST",
1390
+ url: getConsumerAuthControllerSendPasswordResetEmailUrl({
1391
+ appSlug
1392
+ }).url.toString(),
1393
+ data: requestData,
1394
+ ...requestConfig,
1395
+ headers: { ...headers, ...requestConfig.headers }
1396
+ });
1397
+ return res.data;
1398
+ }
1399
+
1364
1400
  // src/_generated/clients/consumerAuth/consumerAuthControllerResetPassword.ts
1365
1401
  function getConsumerAuthControllerResetPasswordUrl({
1366
1402
  appSlug
@@ -1527,6 +1563,220 @@ async function consumerIdpControllerNativeSignIn({
1527
1563
  return res.data;
1528
1564
  }
1529
1565
 
1566
+ // src/_generated/clients/consumerAuth/consumerAuthControllerPasskeyOptions.ts
1567
+ function getConsumerAuthControllerPasskeyOptionsUrl({
1568
+ appSlug
1569
+ }) {
1570
+ const app_slug = appSlug;
1571
+ const res = {
1572
+ method: "POST",
1573
+ url: `/${app_slug}/v1/auth/passkey/options`
1574
+ };
1575
+ return res;
1576
+ }
1577
+ async function consumerAuthControllerPasskeyOptions({
1578
+ appSlug,
1579
+ data
1580
+ }, config = {}) {
1581
+ const { client: request = client, ...requestConfig } = config;
1582
+ const requestData = data;
1583
+ const res = await request({
1584
+ method: "POST",
1585
+ url: getConsumerAuthControllerPasskeyOptionsUrl({ appSlug }).url.toString(),
1586
+ data: requestData,
1587
+ ...requestConfig
1588
+ });
1589
+ return res.data;
1590
+ }
1591
+
1592
+ // src/_generated/clients/consumerAuth/consumerAuthControllerPasskeyVerify.ts
1593
+ function getConsumerAuthControllerPasskeyVerifyUrl({
1594
+ appSlug
1595
+ }) {
1596
+ const app_slug = appSlug;
1597
+ const res = {
1598
+ method: "POST",
1599
+ url: `/${app_slug}/v1/auth/passkey/verify`
1600
+ };
1601
+ return res;
1602
+ }
1603
+ async function consumerAuthControllerPasskeyVerify({
1604
+ appSlug,
1605
+ data
1606
+ }, config = {}) {
1607
+ const { client: request = client, ...requestConfig } = config;
1608
+ const requestData = data;
1609
+ const res = await request({
1610
+ method: "POST",
1611
+ url: getConsumerAuthControllerPasskeyVerifyUrl({ appSlug }).url.toString(),
1612
+ data: requestData,
1613
+ ...requestConfig
1614
+ });
1615
+ return res.data;
1616
+ }
1617
+
1618
+ // src/_generated/clients/consumerAuth/consumerAuthControllerMfaWebauthnOptions.ts
1619
+ function getConsumerAuthControllerMfaWebauthnOptionsUrl({
1620
+ appSlug
1621
+ }) {
1622
+ const app_slug = appSlug;
1623
+ const res = {
1624
+ method: "POST",
1625
+ url: `/${app_slug}/v1/auth/mfa/webauthn/options`
1626
+ };
1627
+ return res;
1628
+ }
1629
+ async function consumerAuthControllerMfaWebauthnOptions({
1630
+ appSlug,
1631
+ data
1632
+ }, config = {}) {
1633
+ const { client: request = client, ...requestConfig } = config;
1634
+ const requestData = data;
1635
+ const res = await request({
1636
+ method: "POST",
1637
+ url: getConsumerAuthControllerMfaWebauthnOptionsUrl({
1638
+ appSlug
1639
+ }).url.toString(),
1640
+ data: requestData,
1641
+ ...requestConfig
1642
+ });
1643
+ return res.data;
1644
+ }
1645
+
1646
+ // src/_generated/clients/consumerAuth/consumerAuthControllerMfaVerify.ts
1647
+ function getConsumerAuthControllerMfaVerifyUrl({
1648
+ appSlug
1649
+ }) {
1650
+ const app_slug = appSlug;
1651
+ const res = {
1652
+ method: "POST",
1653
+ url: `/${app_slug}/v1/auth/mfa/verify`
1654
+ };
1655
+ return res;
1656
+ }
1657
+ async function consumerAuthControllerMfaVerify({
1658
+ appSlug,
1659
+ data
1660
+ }, config = {}) {
1661
+ const { client: request = client, ...requestConfig } = config;
1662
+ const requestData = data;
1663
+ const res = await request({
1664
+ method: "POST",
1665
+ url: getConsumerAuthControllerMfaVerifyUrl({ appSlug }).url.toString(),
1666
+ data: requestData,
1667
+ ...requestConfig
1668
+ });
1669
+ return res.data;
1670
+ }
1671
+
1672
+ // src/_generated/clients/consumerMfa/consumerMfaControllerStartEnrollment.ts
1673
+ function getConsumerMfaControllerStartEnrollmentUrl({
1674
+ appSlug
1675
+ }) {
1676
+ const app_slug = appSlug;
1677
+ const res = {
1678
+ method: "POST",
1679
+ url: `/${app_slug}/v1/me/mfa/factors`
1680
+ };
1681
+ return res;
1682
+ }
1683
+ async function consumerMfaControllerStartEnrollment({
1684
+ appSlug,
1685
+ data
1686
+ }, config = {}) {
1687
+ const { client: request = client, ...requestConfig } = config;
1688
+ const requestData = data;
1689
+ const res = await request({
1690
+ method: "POST",
1691
+ url: getConsumerMfaControllerStartEnrollmentUrl({ appSlug }).url.toString(),
1692
+ data: requestData,
1693
+ ...requestConfig
1694
+ });
1695
+ return res.data;
1696
+ }
1697
+
1698
+ // src/_generated/clients/consumerMfa/consumerMfaControllerConfirmEnrollment.ts
1699
+ function getConsumerMfaControllerConfirmEnrollmentUrl({
1700
+ id,
1701
+ appSlug
1702
+ }) {
1703
+ const app_slug = appSlug;
1704
+ const res = {
1705
+ method: "POST",
1706
+ url: `/${app_slug}/v1/me/mfa/factors/${id}/verify`
1707
+ };
1708
+ return res;
1709
+ }
1710
+ async function consumerMfaControllerConfirmEnrollment({
1711
+ id,
1712
+ appSlug,
1713
+ data
1714
+ }, config = {}) {
1715
+ const { client: request = client, ...requestConfig } = config;
1716
+ const requestData = data;
1717
+ const res = await request({
1718
+ method: "POST",
1719
+ url: getConsumerMfaControllerConfirmEnrollmentUrl({
1720
+ id,
1721
+ appSlug
1722
+ }).url.toString(),
1723
+ data: requestData,
1724
+ ...requestConfig
1725
+ });
1726
+ return res.data;
1727
+ }
1728
+
1729
+ // src/_generated/clients/consumerMfa/consumerMfaControllerStepUpWebauthnOptions.ts
1730
+ function getConsumerMfaControllerStepUpWebauthnOptionsUrl({
1731
+ appSlug
1732
+ }) {
1733
+ const app_slug = appSlug;
1734
+ const res = {
1735
+ method: "POST",
1736
+ url: `/${app_slug}/v1/me/mfa/step-up/webauthn/options`
1737
+ };
1738
+ return res;
1739
+ }
1740
+ async function consumerMfaControllerStepUpWebauthnOptions({
1741
+ appSlug
1742
+ }, config = {}) {
1743
+ const { client: request = client, ...requestConfig } = config;
1744
+ const res = await request({
1745
+ method: "POST",
1746
+ url: getConsumerMfaControllerStepUpWebauthnOptionsUrl({
1747
+ appSlug
1748
+ }).url.toString(),
1749
+ ...requestConfig
1750
+ });
1751
+ return res.data;
1752
+ }
1753
+
1754
+ // src/_generated/clients/consumerMfa/consumerMfaControllerStepUp.ts
1755
+ function getConsumerMfaControllerStepUpUrl({
1756
+ appSlug
1757
+ }) {
1758
+ const app_slug = appSlug;
1759
+ const res = {
1760
+ method: "POST",
1761
+ url: `/${app_slug}/v1/me/mfa/step-up`
1762
+ };
1763
+ return res;
1764
+ }
1765
+ async function consumerMfaControllerStepUp({
1766
+ appSlug,
1767
+ data
1768
+ }, config = {}) {
1769
+ const { client: request = client, ...requestConfig } = config;
1770
+ const requestData = data;
1771
+ const res = await request({
1772
+ method: "POST",
1773
+ url: getConsumerMfaControllerStepUpUrl({ appSlug }).url.toString(),
1774
+ data: requestData,
1775
+ ...requestConfig
1776
+ });
1777
+ return res.data;
1778
+ }
1779
+
1530
1780
  // src/_generated/clients/consumerVerify/consumerVerifyControllerVerify.ts
1531
1781
  function getConsumerVerifyControllerVerifyUrl({
1532
1782
  appSlug
@@ -1632,6 +1882,165 @@ async function consumerOAuthControllerClientCredentials({
1632
1882
  return res.data;
1633
1883
  }
1634
1884
 
1885
+ // src/passkeys.ts
1886
+ function toB64u(buf) {
1887
+ const bytes = buf instanceof ArrayBuffer ? new Uint8Array(buf) : new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
1888
+ let bin = "";
1889
+ for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
1890
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1891
+ }
1892
+ function fromB64u(s) {
1893
+ const b64 = s.replace(/-/g, "+").replace(/_/g, "/");
1894
+ const bin = atob(b64.padEnd(Math.ceil(b64.length / 4) * 4, "="));
1895
+ return Uint8Array.from(bin, (c) => c.charCodeAt(0));
1896
+ }
1897
+ var snakeToCamel = (k) => k.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
1898
+ function camelizeKeys(value) {
1899
+ if (Array.isArray(value)) return value.map(camelizeKeys);
1900
+ if (value && typeof value === "object" && !(value instanceof Uint8Array)) {
1901
+ const out = {};
1902
+ for (const [k, v] of Object.entries(value)) {
1903
+ out[snakeToCamel(k)] = camelizeKeys(v);
1904
+ }
1905
+ return out;
1906
+ }
1907
+ return value;
1908
+ }
1909
+ function decodeOptions(publicKey) {
1910
+ const pk = camelizeKeys(publicKey);
1911
+ const out = {
1912
+ ...pk,
1913
+ challenge: fromB64u(pk.challenge)
1914
+ };
1915
+ if (pk.user) {
1916
+ out.user = { ...pk.user, id: fromB64u(pk.user.id) };
1917
+ }
1918
+ for (const list of ["excludeCredentials", "allowCredentials"]) {
1919
+ const entries = pk[list];
1920
+ if (entries) {
1921
+ out[list] = entries.map((c) => ({ ...c, id: fromB64u(c.id) }));
1922
+ }
1923
+ }
1924
+ return out;
1925
+ }
1926
+ function encodeCredential(cred) {
1927
+ const r = cred.response;
1928
+ const response = {
1929
+ clientDataJSON: toB64u(r.clientDataJSON)
1930
+ };
1931
+ if (r.attestationObject) response.attestationObject = toB64u(r.attestationObject);
1932
+ if (r.authenticatorData) response.authenticatorData = toB64u(r.authenticatorData);
1933
+ if (r.signature) response.signature = toB64u(r.signature);
1934
+ if (r.userHandle) response.userHandle = toB64u(r.userHandle);
1935
+ return { id: cred.id, response };
1936
+ }
1937
+ var PasskeyError = class extends Error {
1938
+ code;
1939
+ cause;
1940
+ constructor(code, message, cause) {
1941
+ super(message);
1942
+ this.name = "PasskeyError";
1943
+ this.code = code;
1944
+ this.cause = cause;
1945
+ }
1946
+ };
1947
+ function browserCredentials() {
1948
+ const nav = globalThis.navigator;
1949
+ const creds = nav?.credentials;
1950
+ if (!creds || typeof creds.create !== "function" || typeof creds.get !== "function") {
1951
+ return void 0;
1952
+ }
1953
+ return creds;
1954
+ }
1955
+ function isPasskeySupported() {
1956
+ const g = globalThis;
1957
+ if (typeof g.window === "undefined") return false;
1958
+ if (typeof g.PublicKeyCredential !== "function") return false;
1959
+ if (g.isSecureContext === false) return false;
1960
+ return browserCredentials() !== void 0;
1961
+ }
1962
+ function mapDomError(err) {
1963
+ const name = err?.name;
1964
+ const message = err?.message ?? String(err);
1965
+ switch (name) {
1966
+ case "NotAllowedError":
1967
+ return new PasskeyError(
1968
+ "cancelled",
1969
+ `Passkey prompt was cancelled, timed out, or no passkey matched: ${message}`,
1970
+ err
1971
+ );
1972
+ case "InvalidStateError":
1973
+ return new PasskeyError("invalid_state", `Authenticator refused: ${message}`, err);
1974
+ case "SecurityError":
1975
+ return new PasskeyError(
1976
+ "security",
1977
+ `Page origin does not match the app's rp_id: ${message}`,
1978
+ err
1979
+ );
1980
+ case "AbortError":
1981
+ return new PasskeyError("cancelled", `Passkey ceremony aborted: ${message}`, err);
1982
+ case "TimeoutError":
1983
+ return new PasskeyError(
1984
+ "timeout",
1985
+ `Passkey prompt timed out before a credential was produced: ${message}`,
1986
+ err
1987
+ );
1988
+ default:
1989
+ return new PasskeyError("unknown", `navigator.credentials failed: ${message}`, err);
1990
+ }
1991
+ }
1992
+ function resolveCredentials(opts = {}) {
1993
+ const creds = opts.credentials ?? browserCredentials();
1994
+ if (!creds) {
1995
+ throw new PasskeyError(
1996
+ "unsupported",
1997
+ "navigator.credentials is not available \u2014 passkeys need a browser with WebAuthn (check isPasskeySupported())"
1998
+ );
1999
+ }
2000
+ return creds;
2001
+ }
2002
+ function isCredentialLike(value) {
2003
+ if (!value || typeof value !== "object") return false;
2004
+ const v = value;
2005
+ return typeof v.id === "string" && !!v.response && typeof v.response === "object";
2006
+ }
2007
+ async function createPasskeyCredential(publicKey, opts = {}) {
2008
+ const creds = resolveCredentials(opts);
2009
+ let cred;
2010
+ try {
2011
+ cred = await creds.create({ publicKey: decodeOptions(publicKey), signal: opts.signal });
2012
+ } catch (err) {
2013
+ throw mapDomError(err);
2014
+ }
2015
+ if (!isCredentialLike(cred)) {
2016
+ throw new PasskeyError(
2017
+ "no_credential",
2018
+ "navigator.credentials.create() returned no usable credential"
2019
+ );
2020
+ }
2021
+ return encodeCredential(cred);
2022
+ }
2023
+ async function getPasskeyCredential(publicKey, opts = {}) {
2024
+ const creds = resolveCredentials(opts);
2025
+ let cred;
2026
+ try {
2027
+ cred = await creds.get({
2028
+ publicKey: decodeOptions(publicKey),
2029
+ mediation: opts.mediation,
2030
+ signal: opts.signal
2031
+ });
2032
+ } catch (err) {
2033
+ throw mapDomError(err);
2034
+ }
2035
+ if (!isCredentialLike(cred)) {
2036
+ throw new PasskeyError(
2037
+ "no_credential",
2038
+ "navigator.credentials.get() returned no usable credential"
2039
+ );
2040
+ }
2041
+ return encodeCredential(cred);
2042
+ }
2043
+
1635
2044
  // src/jwt/errors.ts
1636
2045
  var JwtVerifyError = class extends Error {
1637
2046
  code;
@@ -1887,7 +2296,17 @@ var ConsumerScope = class {
1887
2296
  { client: this.client }
1888
2297
  ),
1889
2298
  /**
1890
- * PAK-required: caller must instantiate `Auth` with
2299
+ * Mint a 6-digit password-reset code. **Sends no email.** Returns
2300
+ * `{ code, expires_at }` for delivery via your own channel — or
2301
+ * `{}` when the contact doesn't match a verified account (uniform
2302
+ * shape — no account enumeration).
2303
+ *
2304
+ * If you want Mail to deliver the code for you, call
2305
+ * {@link sendPasswordResetEmail} instead. Calling this one and
2306
+ * discarding the `code` means the user never hears anything.
2307
+ *
2308
+ * PAK-required with `auth.user.password-reset.create`: caller must
2309
+ * instantiate `Auth` with
1891
2310
  * `auth: { type: "apiKey", key: "pcft_live_..." }`. The
1892
2311
  * kubb-generated `headers.authorization` slot is a stub — the
1893
2312
  * HTTP client's auth middleware overrides whatever's passed.
@@ -1896,6 +2315,31 @@ var ConsumerScope = class {
1896
2315
  { appSlug: this.appSlug, data, headers: { authorization: "" } },
1897
2316
  { client: this.client }
1898
2317
  ),
2318
+ /**
2319
+ * Mint + dispatch a password-reset email via Mail in one call.
2320
+ * Returns `{ expires_at }` on success; the plaintext code is NOT
2321
+ * returned. Returns `{}` when the contact is missing or unverified
2322
+ * (same enumeration defence as {@link requestReset}).
2323
+ *
2324
+ * This is the counterpart to {@link sendVerificationEmail} for the
2325
+ * reset slot, and the method you want for a plain "forgot
2326
+ * password" flow — {@link requestReset} only mints, it does not
2327
+ * email.
2328
+ *
2329
+ * PAK-required with `auth.user.password-reset.send-email` —
2330
+ * distinct permission from the bare mint so customers can enable
2331
+ * mint without enabling outbound Mail traffic. Surfaces typed 412
2332
+ * precondition errors (e.g. `ENVOI_NOT_ENABLED`,
2333
+ * `ENVOI_TEMPLATE_NOT_CONFIGURED`) rather than failing silently.
2334
+ */
2335
+ sendPasswordResetEmail: (data) => consumerAuthControllerSendPasswordResetEmail(
2336
+ {
2337
+ appSlug: this.appSlug,
2338
+ data,
2339
+ headers: { authorization: "" }
2340
+ },
2341
+ { client: this.client }
2342
+ ),
1899
2343
  resetPassword: (data) => consumerAuthControllerResetPassword(
1900
2344
  { appSlug: this.appSlug, data },
1901
2345
  { client: this.client }
@@ -2051,6 +2495,141 @@ var ConsumerScope = class {
2051
2495
  )
2052
2496
  };
2053
2497
  // ─────────────────────────────────────────────────────────────
2498
+ // Passkeys — WebAuthn ceremonies, one call each. BROWSER ONLY at
2499
+ // call time (they drive navigator.credentials); importing is safe
2500
+ // anywhere. Base64url in both directions is handled here; the
2501
+ // wire stays snake_case except the spec-fixed response members
2502
+ // (clientDataJSON, attestationObject, authenticatorData, signature,
2503
+ // userHandle), which travel verbatim.
2504
+ // ─────────────────────────────────────────────────────────────
2505
+ passkeys = {
2506
+ /**
2507
+ * Enrol a passkey as an MFA factor for the signed-in end-user.
2508
+ * Requires the scope to carry the user's access token
2509
+ * (`new Auth({ auth: { type: "bearer", token } })`).
2510
+ *
2511
+ * `POST /me/mfa/factors { type: "webauthn" }` →
2512
+ * `navigator.credentials.create()` →
2513
+ * `POST /me/mfa/factors/:id/verify { credential }`.
2514
+ *
2515
+ * Resolves with the now-enabled factor and the user's recovery
2516
+ * codes — show those once, they are not retrievable later. The
2517
+ * factor stays disabled until the verify call succeeds, so an
2518
+ * abandoned prompt leaves nothing usable behind.
2519
+ */
2520
+ enroll: async (opts = {}) => {
2521
+ const credentials = resolveCredentials(opts);
2522
+ const start = await consumerMfaControllerStartEnrollment(
2523
+ {
2524
+ appSlug: this.appSlug,
2525
+ data: { type: "webauthn", ...opts.label ? { label: opts.label } : {} }
2526
+ },
2527
+ { client: this.client }
2528
+ );
2529
+ const publicKey = start.enrollment.public_key;
2530
+ const credential = await createPasskeyCredential(publicKey, { ...opts, credentials });
2531
+ return await consumerMfaControllerConfirmEnrollment(
2532
+ { appSlug: this.appSlug, id: start.factor.id, data: { credential } },
2533
+ { client: this.client }
2534
+ );
2535
+ },
2536
+ /**
2537
+ * Passwordless sign-in with a discoverable passkey. No password,
2538
+ * no email address: the authenticator finds its own passkey for
2539
+ * the app's rp_id.
2540
+ *
2541
+ * `POST /auth/passkey/options {}` → `navigator.credentials.get()`
2542
+ * → `POST /auth/passkey/verify { credential }`.
2543
+ *
2544
+ * Resolves with the session (`access_token`, `refresh_token`,
2545
+ * …; `amr: ["webauthn"]`). Rejects with `PasskeyError`
2546
+ * (`code: "cancelled"`) when the user dismisses the prompt or no
2547
+ * passkey matches, and with `AuthHttpError` 401 for a forged,
2548
+ * unknown, replayed or expired assertion — the server answers
2549
+ * those uniformly on purpose.
2550
+ *
2551
+ * The options call deliberately takes no identifier (it would be
2552
+ * an account-existence oracle); `tenant_id` is the only
2553
+ * accepted body member and only matters for multi-tenant apps.
2554
+ * Pass `mediation: "conditional"` for autofill-style UI.
2555
+ */
2556
+ signIn: async (opts = {}) => {
2557
+ const credentials = resolveCredentials(opts);
2558
+ const { public_key } = await consumerAuthControllerPasskeyOptions(
2559
+ {
2560
+ appSlug: this.appSlug,
2561
+ data: opts.tenant_id ? { tenant_id: opts.tenant_id } : {}
2562
+ },
2563
+ { client: this.client }
2564
+ );
2565
+ const credential = await getPasskeyCredential(
2566
+ public_key,
2567
+ { ...opts, credentials }
2568
+ );
2569
+ return await consumerAuthControllerPasskeyVerify(
2570
+ { appSlug: this.appSlug, data: { credential } },
2571
+ { client: this.client }
2572
+ );
2573
+ },
2574
+ /**
2575
+ * Satisfy the MFA step of a password sign-in with a passkey.
2576
+ * Call it when `auth.signin()` answered
2577
+ * `{ mfa_required: true, mfa_token, factors }` and `factors`
2578
+ * contains a `webauthn` entry.
2579
+ *
2580
+ * `POST /auth/mfa/webauthn/options { mfa_token }` →
2581
+ * `navigator.credentials.get()` →
2582
+ * `POST /auth/mfa/verify { mfa_token, credential }`.
2583
+ *
2584
+ * Resolves with the session (`amr: ["pwd", "webauthn"]`, fresh
2585
+ * `mfa_at`). Possession of the `mfa_token` — a correct password
2586
+ * — is the authority for the options call.
2587
+ */
2588
+ completeMfaChallenge: async (args) => {
2589
+ const { mfa_token, ...browserOpts } = args;
2590
+ const credentials = resolveCredentials(browserOpts);
2591
+ const { public_key } = await consumerAuthControllerMfaWebauthnOptions(
2592
+ { appSlug: this.appSlug, data: { mfa_token } },
2593
+ { client: this.client }
2594
+ );
2595
+ const credential = await getPasskeyCredential(
2596
+ public_key,
2597
+ { ...browserOpts, credentials }
2598
+ );
2599
+ return await consumerAuthControllerMfaVerify(
2600
+ { appSlug: this.appSlug, data: { mfa_token, credential } },
2601
+ { client: this.client }
2602
+ );
2603
+ },
2604
+ /**
2605
+ * Re-confirm the signed-in user's identity inside a live session
2606
+ * (before a sensitive action). Requires the scope to carry the
2607
+ * user's access token.
2608
+ *
2609
+ * `POST /me/mfa/step-up/webauthn/options` →
2610
+ * `navigator.credentials.get()` →
2611
+ * `POST /me/mfa/step-up { credential }`.
2612
+ *
2613
+ * Resolves with `{ amr, mfa_at }`. A passkey assertion is never
2614
+ * tried as a recovery code, so a failed step-up never burns one.
2615
+ */
2616
+ stepUp: async (opts = {}) => {
2617
+ const credentials = resolveCredentials(opts);
2618
+ const { public_key } = await consumerMfaControllerStepUpWebauthnOptions(
2619
+ { appSlug: this.appSlug },
2620
+ { client: this.client }
2621
+ );
2622
+ const credential = await getPasskeyCredential(
2623
+ public_key,
2624
+ { ...opts, credentials }
2625
+ );
2626
+ return await consumerMfaControllerStepUp(
2627
+ { appSlug: this.appSlug, data: { credential } },
2628
+ { client: this.client }
2629
+ );
2630
+ }
2631
+ };
2632
+ // ─────────────────────────────────────────────────────────────
2054
2633
  // OAuth M2M — client_credentials grant for service-to-service tokens
2055
2634
  // ─────────────────────────────────────────────────────────────
2056
2635
  oauth = {
@@ -2069,9 +2648,9 @@ function getAppControllerListMyAppsUrl() {
2069
2648
  async function appControllerListMyApps({ params } = {}, config = {}) {
2070
2649
  const { client: request = client, ...requestConfig } = config;
2071
2650
  const mappedParams = params ? {
2651
+ workspace_id: params.workspaceId,
2072
2652
  limit: params.limit,
2073
- cursor: params.cursor,
2074
- workspace_id: params.workspaceId
2653
+ cursor: params.cursor
2075
2654
  } : void 0;
2076
2655
  const res = await request({
2077
2656
  method: "GET",
@@ -2208,6 +2787,14 @@ exports.JwtInvalidError = JwtInvalidError;
2208
2787
  exports.JwtIssuerMismatchError = JwtIssuerMismatchError;
2209
2788
  exports.JwtNotYetValidError = JwtNotYetValidError;
2210
2789
  exports.JwtVerifyError = JwtVerifyError;
2790
+ exports.PasskeyError = PasskeyError;
2791
+ exports.createPasskeyCredential = createPasskeyCredential;
2792
+ exports.decodeOptions = decodeOptions;
2793
+ exports.encodeCredential = encodeCredential;
2794
+ exports.fromB64u = fromB64u;
2795
+ exports.getPasskeyCredential = getPasskeyCredential;
2796
+ exports.isPasskeySupported = isPasskeySupported;
2797
+ exports.toB64u = toB64u;
2211
2798
  exports.verifyAuthToken = verifyAuthToken;
2212
2799
  //# sourceMappingURL=index.cjs.map
2213
2800
  //# sourceMappingURL=index.cjs.map