@fleetless/sdk 4.2.0 → 4.4.0-next.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.d.cts CHANGED
@@ -282,6 +282,7 @@ declare const jobRun: z.ZodObject<{
282
282
  }>;
283
283
  id: z.ZodUUID;
284
284
  label: z.ZodString;
285
+ name: z.ZodNullable<z.ZodString>;
285
286
  }, z.core.$strip>;
286
287
  seq: z.ZodNumber;
287
288
  progress: z.ZodNullable<z.ZodNumber>;
@@ -323,6 +324,7 @@ declare const jobRunListResponse: z.ZodObject<{
323
324
  }>;
324
325
  id: z.ZodUUID;
325
326
  label: z.ZodString;
327
+ name: z.ZodNullable<z.ZodString>;
326
328
  }, z.core.$strip>;
327
329
  seq: z.ZodNumber;
328
330
  progress: z.ZodNullable<z.ZodNumber>;
@@ -506,14 +508,23 @@ type SessionTokens = z.infer<typeof sessionTokens>;
506
508
  * `provider_misconfigured`, `provider_disabled` — the provider's or the
507
509
  * developer's to fix, and the app can say so.
508
510
  * - `invalid_request` — the start parameters did not hold up.
509
- * - `quota_exceeded` — the org has as many app users as its `max_end_users`
510
- * quota allows, so no account can be created for this identity. Named rather
511
- * than folded into `no_access`, for `domain_not_allowed`'s reason: it is not
512
- * about the person, the app can say what happened, and the remedy belongs to
513
- * the developer rather than to whoever is trying to sign in. It is raised
511
+ * - `quota_exceeded` — the org is at the protection ceiling: it has as many
512
+ * app users as its `max_end_users` quota allows, so no account can be
513
+ * created for this identity. This also covers an org still on the beta,
514
+ * whose plan is not enforced yet. Named rather than folded into
515
+ * `no_access`, for `domain_not_allowed`'s reason: it is not about the
516
+ * person, the app can say what happened, and the remedy belongs to the
517
+ * developer rather than to whoever is trying to sign in. It is raised
514
518
  * **only where an account would be created** — an identity that already has
515
519
  * one signs in at the quota exactly as it does under it, because refusing a
516
520
  * sign-in would turn a protection limit into an outage.
521
+ * - `plan_limit` — the org's plan has no room for another app user: it is at
522
+ * its plan's `app_users` limit (fleetless/fleetless#103), counted across
523
+ * every app of the org with pending invitations included. Checked before
524
+ * the protection ceiling, and raised, like `quota_exceeded`, **only where
525
+ * an account would be created**. The remedy is a higher plan or an add-on,
526
+ * which is why it is not `quota_exceeded`. It is the same code the other
527
+ * app-user doors answer as `409 plan_limit`.
517
528
  */
518
529
  declare const clientOidcErrorCode: z.ZodEnum<{
519
530
  no_access: "no_access";
@@ -528,13 +539,15 @@ declare const clientOidcErrorCode: z.ZodEnum<{
528
539
  provider_disabled: "provider_disabled";
529
540
  invalid_request: "invalid_request";
530
541
  quota_exceeded: "quota_exceeded";
542
+ plan_limit: "plan_limit";
531
543
  }>;
532
544
  type ClientOidcErrorCode = z.infer<typeof clientOidcErrorCode>;
533
545
  /**
534
- * **A pending MCP authorization, as the app's own consent screen reads it**
535
- * Fleetless renders no page here either: `authorize` redirects to the
536
- * app's `mcp_login_url` with an interaction id, the app authenticates the user
537
- * with its normal UI, shows this, and approves or denies through the API.
546
+ * **A pending MCP authorization, as the app's own consent screen reads it.**
547
+ * `authorize` redirects to the app's `mcp_login_url` with an interaction id,
548
+ * the app authenticates the user with its normal UI, shows this, and approves
549
+ * or denies through the API. An app with no `mcp_login_url` gets the hosted
550
+ * MCP sign-in instead, which reads and decides the same interaction.
538
551
  *
539
552
  * `client_name_verified` is `z.literal(false)`, and that is the whole point of
540
553
  * the field. The name comes from an **unauthenticated** dynamic registration —
@@ -624,6 +637,7 @@ declare const clientIdentity: z.ZodObject<{
624
637
  app_id: z.ZodNullable<z.ZodUUID>;
625
638
  role_id: z.ZodNullable<z.ZodUUID>;
626
639
  email: z.ZodNullable<z.ZodEmail>;
640
+ two_factor_enabled: z.ZodNullable<z.ZodBoolean>;
627
641
  }, z.core.$strip>;
628
642
  type ClientIdentity = z.infer<typeof clientIdentity>;
629
643
 
@@ -850,7 +864,7 @@ type CancelRejectedDetails = z.infer<typeof cancelRejectedDetails>;
850
864
  * list is the shared vocabulary, not a closed set, so a new refusal never
851
865
  * needs a contracts release before it can be reported honestly.
852
866
  */
853
- declare const ERROR_CODES: readonly ["not_found", "validation_error", "bad_request", "unknown_datapoint", "invalid_token", "protocol_mismatch", "bridge_too_old", "invalid_frame", "duplicate_slug", "reserved_slug", "unknown_slug", "unknown_field_path", "unknown_type", "unknown_topic", "invalid_rate", "invalid_range", "config_conflict", "no_data", "robot_offline", "bridge_timeout", "unauthorized", "forbidden", "invalid_credentials", "token_expired", "token_revoked", "email_taken", "identifier_taken", "weak_password", "account_blocked", "busy", "parameter_invalid", "cancel_rejected", "job_lost", "job_unknown_to_bridge", "action_server_lost", "action_failed", "goal_rejected", "goal_send_failed", "result_failed", "goal_uncontrollable", "bridge_disconnected", "config_changed", "publisher_busy", "unknown_command", "not_subscribable", "camera_offline", "no_snapshot_yet", "live_unavailable", "wrong_kind", "not_recorded", "not_aggregatable", "quota_exceeded", "credential_in_use", "goal_timeout", "robot_in_use", "robot_deletion_partial", "job_queue_full", "invalid_uuid", "rate_limited", "tier_required", "token_spent", "service_timeout", "asset_missing", "dynamic_registration_disabled", "client_limit_reached", "idp_unavailable", "mcp_disabled", "tool_not_available", "capability_required", "last_owner", "target_state_conflict", "signup_closed", "draft_not_a_document", "internal_error", "not_cancellable", "unsupported_media_type", "wrong_browser", "invalid_yaml", "unstorable_yaml", "registration_closed", "domain_not_allowed", "email_unverified", "origin_not_allowed", "template_invalid", "provider_disabled", "provider_misconfigured", "invalid_redirect_uri", "interaction_expired"];
867
+ declare const ERROR_CODES: readonly ["not_found", "validation_error", "bad_request", "unknown_datapoint", "invalid_token", "protocol_mismatch", "bridge_too_old", "invalid_frame", "duplicate_slug", "reserved_slug", "unknown_slug", "unknown_field_path", "unknown_type", "unknown_topic", "invalid_rate", "invalid_range", "config_conflict", "no_data", "robot_offline", "bridge_timeout", "unauthorized", "forbidden", "invalid_credentials", "token_expired", "token_revoked", "email_taken", "identifier_taken", "weak_password", "account_blocked", "busy", "parameter_invalid", "cancel_rejected", "job_lost", "job_unknown_to_bridge", "action_server_lost", "action_failed", "goal_rejected", "goal_send_failed", "result_failed", "goal_uncontrollable", "bridge_disconnected", "config_changed", "publisher_busy", "unknown_command", "not_subscribable", "camera_offline", "no_snapshot_yet", "live_unavailable", "wrong_kind", "not_recorded", "not_aggregatable", "quota_exceeded", "credential_in_use", "goal_timeout", "robot_in_use", "robot_deletion_partial", "job_queue_full", "invalid_uuid", "rate_limited", "tier_required", "token_spent", "service_timeout", "asset_missing", "dynamic_registration_disabled", "client_limit_reached", "idp_unavailable", "mcp_disabled", "tool_not_available", "capability_required", "last_owner", "role_name_taken", "role_in_use", "last_role", "target_state_conflict", "signup_closed", "draft_not_a_document", "internal_error", "not_cancellable", "unsupported_media_type", "wrong_browser", "invalid_yaml", "unstorable_yaml", "registration_closed", "domain_not_allowed", "email_unverified", "origin_not_allowed", "template_invalid", "provider_disabled", "provider_misconfigured", "invalid_redirect_uri", "interaction_expired", "invalid_code", "method_not_allowed", "plan_limit", "plan_required", "org_locked", "file_too_large"];
854
868
  type ErrorCode = (typeof ERROR_CODES)[number];
855
869
 
856
870
  /**
@@ -1577,8 +1591,15 @@ declare class InMemoryTokenStore implements TokenStore {
1577
1591
  interface RegisterOptions {
1578
1592
  /** The address the verification mail goes to. Nothing works until that link is spent. */
1579
1593
  email: string;
1580
- /** At least 12 characters — `clientRegisterRequest` refuses less with a `validation_error`. */
1581
- password: string;
1594
+ /**
1595
+ * At least 12 characters — `clientRegisterRequest` refuses less with a
1596
+ * `validation_error`. **Optional, and omitted from the request entirely**
1597
+ * when you do not pass it: an app whose `sign_in_methods` is email-code
1598
+ * only has no password to set, and sending the key at all (even as
1599
+ * `undefined`) would be a `422` against the strict schema — same reason as
1600
+ * `displayName` below.
1601
+ */
1602
+ password?: string;
1582
1603
  /**
1583
1604
  * What the app should call this person. Optional, and **omitted from the
1584
1605
  * request entirely** when you do not pass it — `clientRegisterRequest` is a
@@ -1591,11 +1612,105 @@ interface RegisterOptions {
1591
1612
  interface AcceptInvitationOptions {
1592
1613
  /** The `token` from the invitation link the developer's app was linked to. */
1593
1614
  token: string;
1594
- /** At least 12 characters. The invitation fixes the role; this call fixes the credential. */
1595
- password: string;
1615
+ /**
1616
+ * At least 12 characters. The invitation fixes the role; this call fixes
1617
+ * the credential. **Optional, and omitted from the request entirely** when
1618
+ * you do not pass it — same email-code-only reason as `RegisterOptions.password`.
1619
+ */
1620
+ password?: string;
1596
1621
  /** Optional, and omitted from the request entirely when absent — same strict-schema reason as `RegisterOptions.displayName`. */
1597
1622
  displayName?: string;
1598
1623
  }
1624
+ /**
1625
+ * `verifyTwoFactor()`'s input — the `challenge` a sign-in step answered with
1626
+ * `two_factor_required`, plus exactly one of the authenticator's current
1627
+ * code or a recovery code. Sending both, or neither, is a `400
1628
+ * validation_error` the cloud answers (`clientTwoFactorVerifyRequest` is a
1629
+ * strict schema with both fields optional) — this SDK does not duplicate
1630
+ * that check client-side, it only serializes whichever one the caller gave.
1631
+ */
1632
+ interface VerifyTwoFactorOptions {
1633
+ /** The handle a sign-in step (`login`, `verifyLoginCode`, …) answered. Five minutes, five wrong codes. */
1634
+ challenge: string;
1635
+ /** The authenticator's current six digits. Accepted at most once — the same code sent twice signs in exactly once. */
1636
+ code?: string;
1637
+ /** One of the ten recovery codes, spent by its use. Use this instead of `code` when the authenticator itself is unavailable. */
1638
+ recoveryCode?: string;
1639
+ }
1640
+ /**
1641
+ * `beginTwoFactorSetup()`'s input. **Two ways in, decided by what is
1642
+ * passed**: a `challenge` from a `two_factor_setup_required` sign-in step
1643
+ * (no session exists yet, so the challenge itself is the credential), or
1644
+ * nothing at all — from the app's own account settings, where the caller's
1645
+ * *current session* is the credential instead. Passing neither a challenge
1646
+ * nor holding a session is `401 unauthorized` from the cloud, not a
1647
+ * client-side refusal: this SDK has no way to tell "forgot to pass a
1648
+ * challenge" apart from "forgot to sign in first" without asking the server.
1649
+ */
1650
+ interface BeginTwoFactorSetupOptions {
1651
+ challenge?: string;
1652
+ }
1653
+ /** What `beginTwoFactorSetup()` resolves with — not yet in use until `confirmTwoFactorSetup` accepts a code from it. */
1654
+ interface TwoFactorSetup {
1655
+ /** The shared secret, for a manual "enter this key" fallback. */
1656
+ secret: string;
1657
+ /** The full `otpauth://` URI, for rendering as a QR code. */
1658
+ otpauthUrl: string;
1659
+ }
1660
+ /** `confirmTwoFactorSetup()`'s input — same two ways in as `beginTwoFactorSetup`, plus the code from the new authenticator. */
1661
+ interface ConfirmTwoFactorSetupOptions {
1662
+ /** A code from the authenticator `beginTwoFactorSetup` just started. A mismatch is `invalid_code`. */
1663
+ code: string;
1664
+ /** The same challenge `beginTwoFactorSetup` was given, during a sign-in. Omit it when setting up from account settings instead. */
1665
+ challenge?: string;
1666
+ }
1667
+ /**
1668
+ * What `confirmTwoFactorSetup()` resolves with: the ten recovery codes,
1669
+ * shown this once — any earlier set is void. The session itself is not
1670
+ * here; it is saved to the token store the same way every other sign-in
1671
+ * step saves one, not handed back for the caller to do that itself.
1672
+ */
1673
+ interface TwoFactorSetupConfirmation {
1674
+ recoveryCodes: string[];
1675
+ }
1676
+ /**
1677
+ * What every sign-in step (`login`, `verifyEmail`, `confirmPasswordReset`,
1678
+ * `acceptInvitation`, `verifyLoginCode`) resolves with — the session may not be ready yet.
1679
+ *
1680
+ * `'signed_in'` means exactly that: the session was stored, same as these
1681
+ * calls always did. The other two mean the cloud is still waiting on a
1682
+ * second factor — no session exists yet, nothing was stored, and `challenge`
1683
+ * is a short-lived handle (five minutes) for the next call:
1684
+ * `'two_factor_required'` when the person already has an authenticator
1685
+ * (`POST /api/client/two-factor/verify`), `'two_factor_setup_required'` when
1686
+ * the app requires one and the person has none yet
1687
+ * (`POST /api/client/two-factor/setup` then `…/setup/confirm`). An app
1688
+ * without two-factor on at all never sees either — every sign-in step
1689
+ * resolves `{ status: 'signed_in' }`.
1690
+ */
1691
+ type SignInResult = {
1692
+ status: 'signed_in';
1693
+ } | {
1694
+ status: 'two_factor_required';
1695
+ challenge: string;
1696
+ } | {
1697
+ status: 'two_factor_setup_required';
1698
+ challenge: string;
1699
+ };
1700
+ /**
1701
+ * Which credential-based ways in the app's login screen should draw, as
1702
+ * `signInMethods()` answers it: a password field, a "mail me a code" link, or
1703
+ * both. Federated buttons are `listProviders()`'s own answer, not this one —
1704
+ * the two routes share one response on the wire (`GET /api/client/providers`)
1705
+ * but ask different questions, so the SDK answers them separately rather than
1706
+ * handing every caller a shape with fields it did not ask about.
1707
+ */
1708
+ interface SignInMethods {
1709
+ /** Whether `login(email, password)` is on for this app. */
1710
+ password: boolean;
1711
+ /** Whether `requestLoginCode`/`verifyLoginCode` is on for this app. */
1712
+ emailCode: boolean;
1713
+ }
1599
1714
  /** One sign-in button on the app's own login screen, as `listProviders()` lists it. */
1600
1715
  interface ProviderButton {
1601
1716
  /** What `beginOidcLogin` addresses this provider by. */
@@ -1699,10 +1814,10 @@ interface McpInteractionDecision {
1699
1814
  *
1700
1815
  * **A client built with a `serverKey` refuses everything that needs an app
1701
1816
  * user's own session** with `invalid_option`, before any request. `me()`,
1702
- * `listProviders()`, `mcpInteraction()` and `oidcErrorFromCallback()` still
1703
- * work on one: the first is what a server key is *for*, the next two are public
1704
- * reads the cloud answers without any credential at all, and the last touches
1705
- * no network.
1817
+ * `listProviders()`, `signInMethods()`, `mcpInteraction()` and
1818
+ * `oidcErrorFromCallback()` still work on one: the first is what a server key
1819
+ * is *for*, the next three are public reads the cloud answers without any
1820
+ * credential at all, and the last touches no network.
1706
1821
  */
1707
1822
  interface AuthApi {
1708
1823
  /**
@@ -1726,26 +1841,48 @@ interface AuthApi {
1726
1841
  */
1727
1842
  register(input: RegisterOptions): Promise<void>;
1728
1843
  /**
1729
- * Spends a verification token and **stores the session it answers with**, so
1730
- * the person is not asked to log in immediately after proving they can read
1731
- * the mail.
1844
+ * Spends a verification token and **stores the session it answers with**
1845
+ * when the sign-in is complete, so the person is not asked to log in
1846
+ * immediately after proving they can read the mail — see `SignInResult`
1847
+ * for the second-factor case, where nothing is stored yet.
1732
1848
  *
1733
1849
  * `token_spent` covers unknown, expired and already-used alike — one code,
1734
1850
  * because the remedy is one thing: ask for a fresh link with
1735
1851
  * `resendVerification`. An app rendering this refusal should offer that.
1736
1852
  */
1737
- verifyEmail(token: string): Promise<void>;
1853
+ verifyEmail(token: string): Promise<SignInResult>;
1738
1854
  /** Asks for the verification mail again. Resolves on `202` for every policy-allowed request, existing address or not — same reason as `register`. */
1739
1855
  resendVerification(email: string): Promise<void>;
1740
1856
  /**
1741
1857
  * Exchanges email + password, and the client's configured app identifier, for
1742
- * a session.
1858
+ * a session — or a second-factor challenge, see `SignInResult`.
1743
1859
  *
1744
1860
  * `invalid_credentials` is answered identically for a wrong password, a
1745
1861
  * blocked account and one still waiting to verify. Do not try to tell them
1746
1862
  * apart — there is nothing in the answer that does, deliberately.
1747
1863
  */
1748
- login(email: string, password: string): Promise<void>;
1864
+ login(email: string, password: string): Promise<SignInResult>;
1865
+ /**
1866
+ * Mails a six-digit sign-in code to `email`, valid ten minutes — the
1867
+ * password-free alternative to `login`. Resolves on the route's `202` for
1868
+ * every policy-allowed request, whether or not the address names an
1869
+ * account, same discipline as `register`/`resendVerification`/
1870
+ * `requestPasswordReset`: this is no enumeration oracle either. A fresh
1871
+ * request expires the previous code for the same address.
1872
+ */
1873
+ requestLoginCode(email: string): Promise<void>;
1874
+ /**
1875
+ * Spends a mailed sign-in code for a session — or a second-factor
1876
+ * challenge, see `SignInResult`, exactly like `login`.
1877
+ *
1878
+ * A wrong code is `invalid_code`, carrying `details.attempts_left`; five
1879
+ * wrong attempts, or the tenth minute, spend the code the same way a
1880
+ * correct one would, and the recovery is the same either way: call
1881
+ * `requestLoginCode` again. A pending-verification account that spends a
1882
+ * code is activated — reading the mail at that address is the proof
1883
+ * verification asks for.
1884
+ */
1885
+ verifyLoginCode(email: string, code: string): Promise<SignInResult>;
1749
1886
  /**
1750
1887
  * Ends the session: revokes the whole refresh-token family server-side (a
1751
1888
  * stolen refresh token stops working immediately), closes this client's live
@@ -1770,7 +1907,17 @@ interface AuthApi {
1770
1907
  * which Fleetless never did better than it.
1771
1908
  */
1772
1909
  logout(): Promise<void>;
1773
- /** Who the caller turned out to be, without decoding a token client-side — which is how apps end up trusting claims nobody verified. */
1910
+ /**
1911
+ * Who the caller turned out to be, without decoding a token client-side —
1912
+ * which is how apps end up trusting claims nobody verified.
1913
+ *
1914
+ * Throws the SDK's own `no_session` **before any request is sent** when
1915
+ * nothing is stored — which is exactly the state a sign-in step leaves a
1916
+ * caller in while a second factor is still pending (see `SignInResult`):
1917
+ * there is no session yet to ask the cloud about, so this fails the same
1918
+ * way "never logged in" does, rather than round-tripping to a route that
1919
+ * would just answer `unauthorized` for having no bearer at all.
1920
+ */
1774
1921
  me(): Promise<ClientIdentity>;
1775
1922
  /**
1776
1923
  * Changes the current app user's password.
@@ -1792,21 +1939,68 @@ interface AuthApi {
1792
1939
  requestPasswordReset(email: string): Promise<void>;
1793
1940
  /**
1794
1941
  * Spends a reset token, sets the new password and **stores the session it
1795
- * answers with**. Every refresh family of that user is revoked first — a
1796
- * forgotten password is one of the two states where somebody else may be
1797
- * holding a session.
1942
+ * answers with** when the sign-in is complete (see `SignInResult`). Every
1943
+ * refresh family of that user is revoked first — a forgotten password is
1944
+ * one of the two states where somebody else may be holding a session.
1798
1945
  */
1799
- confirmPasswordReset(token: string, newPassword: string): Promise<void>;
1946
+ confirmPasswordReset(token: string, newPassword: string): Promise<SignInResult>;
1800
1947
  /**
1801
1948
  * Accepts an app invitation: creates the account (or activates one invited
1802
1949
  * before it existed) with the role the invitation fixed, and **stores the
1803
- * session**.
1950
+ * session** when the sign-in is complete (see `SignInResult`).
1804
1951
  *
1805
1952
  * An invitation always bypasses the app's domain whitelist — a developer
1806
1953
  * inviting somebody by hand has already made the decision the whitelist
1807
1954
  * automates.
1808
1955
  */
1809
- acceptInvitation(input: AcceptInvitationOptions): Promise<void>;
1956
+ acceptInvitation(input: AcceptInvitationOptions): Promise<SignInResult>;
1957
+ /**
1958
+ * Answers a `two_factor_required` challenge and **saves the session
1959
+ * unconditionally** — unlike `login`/`verifyEmail`/`confirmPasswordReset`/
1960
+ * `acceptInvitation`/`verifyLoginCode`, this call's answer is never a
1961
+ * `SignInResult` union: the second factor is the last step, so the cloud
1962
+ * has nothing left to ask for and always answers tokens.
1963
+ *
1964
+ * A wrong code or recovery code is `invalid_code`, carrying
1965
+ * `details.attempts_left`; five wrong attempts, or the challenge's own
1966
+ * five minutes, spend it the same way a correct answer would — the
1967
+ * sign-in has to start over from `login`/`requestLoginCode`/etc.
1968
+ */
1969
+ verifyTwoFactor(input: VerifyTwoFactorOptions): Promise<void>;
1970
+ /**
1971
+ * Starts an authenticator setup and hands back its secret and `otpauth://`
1972
+ * URL for rendering a QR code. **Two ways in**: pass the `challenge` a
1973
+ * `two_factor_setup_required` sign-in step answered, when the app requires
1974
+ * a second factor and this person has none yet — no session exists at
1975
+ * that point, so the challenge is the credential; or pass nothing at all,
1976
+ * from the app's own account settings, where the *current session* is the
1977
+ * credential instead. The secret is not in use until
1978
+ * `confirmTwoFactorSetup` accepts a code from it — calling this twice
1979
+ * replaces the pending secret, and an account that already has an
1980
+ * authenticator keeps it until the new one is confirmed.
1981
+ */
1982
+ beginTwoFactorSetup(input?: BeginTwoFactorSetupOptions): Promise<TwoFactorSetup>;
1983
+ /**
1984
+ * Confirms the authenticator `beginTwoFactorSetup` just started, with a
1985
+ * code from it, and **saves the session it answers** — same two ways in
1986
+ * as `beginTwoFactorSetup` (a sign-in `challenge`, or the current
1987
+ * session). On success the authenticator is on and ten recovery codes
1988
+ * come back, shown this once; any earlier set is void. A code that does
1989
+ * not match the pending secret is `invalid_code`.
1990
+ *
1991
+ * From account settings, every other session of the account ends and this
1992
+ * call's own session is replaced with the fresh one it answers — the same
1993
+ * discipline `changePassword` already keeps.
1994
+ */
1995
+ confirmTwoFactorSetup(input: ConfirmTwoFactorSetupOptions): Promise<TwoFactorSetupConfirmation>;
1996
+ /**
1997
+ * Turns the signed-in app user's authenticator off — the account's own
1998
+ * door, not the developer's support one (`DELETE
1999
+ * /api/apps/:id/users/:userId/two-factor`, management-side). A current
2000
+ * code proves the person still holds the authenticator before it and
2001
+ * every recovery code are removed; a stolen session alone cannot do this.
2002
+ */
2003
+ disableTwoFactor(code: string): Promise<void>;
1810
2004
  /**
1811
2005
  * The app's **enabled** sign-in providers, for drawing the buttons on your
1812
2006
  * own login screen. A disabled provider is not a button that refuses; it is a
@@ -1818,6 +2012,18 @@ interface AuthApi {
1818
2012
  * is configured.
1819
2013
  */
1820
2014
  listProviders(): Promise<ProviderButton[]>;
2015
+ /**
2016
+ * Which credential-based sign-in methods this app has on, for drawing a
2017
+ * password field, a "get a code by email" link, or both, on your own login
2018
+ * screen — the other half of what the login screen needs, the federated
2019
+ * buttons being `listProviders()`'s own answer.
2020
+ *
2021
+ * Public and unauthenticated, same route as `listProviders()`
2022
+ * (`GET /api/client/providers`) — each call is its own request, picking a
2023
+ * different field out of the same response; call both if your login
2024
+ * screen needs both.
2025
+ */
2026
+ signInMethods(): Promise<SignInMethods>;
1821
2027
  /**
1822
2028
  * Builds the URL that starts a federated sign-in, with a fresh `state` and a
1823
2029
  * fresh PKCE verifier. **Makes no network call and does not navigate** —
@@ -2515,4 +2721,4 @@ interface FleetlessClient {
2515
2721
  */
2516
2722
  declare function createClient(options: FleetlessClientOptions): FleetlessClient;
2517
2723
 
2518
- export { type AcceptInvitationOptions, type ActionsApi, type Asset, type AssetBytes, type AssetListResponse, type AssetsApi, type AuthApi, type BeginOidcLoginOptions, type BusyDetails, CANCEL_RETURN_CODES, type CameraDescriptor, type CameraLiveSession, type CameraSnapshot, type CameraSnapshotMeta, type CamerasApi, type CancelRejectedDetails, type CancelReturnCode, type ClientIdentity, type ClientMcpInteraction, type ClientOidcErrorCode, type ClientRobotListItem, type CompleteOidcLoginOptions, type CreateMeshLoaderOptions, type CredentialSource, type DatapointEvent, type DatapointSubscription, type DatapointSubscriptionHandlers, type DatapointValue, type DatapointsApi, type FleetlessClient, type FleetlessClientConfig, type FleetlessClientOptions, FleetlessError, type FleetlessErrorCode, type FleetlessErrorOptions, type HistoryAggregation, type HistoryBucketsResponse, type HistoryOptions, type HistorySamplesResponse, InMemoryTokenStore, type InvokeOptions, type Job, type JobEvent, type JobHistoryOptions, type JobOrigin, type JobRun, type JobRunListResponse, type JobState, type JobSubscription, type JobSubscriptionHandlers, type JobsApi, type McpCapabilities, type McpConsentGrant, type McpExposure, type McpInteractionDecision, type McpRobotDatasheet, type MeshLoaderDelegate, type OidcLoginRequest, type ParameterInvalidDetails, type ParameterViolation, type PrepareUrdfSceneOptions, type ProviderButton, type PublishersApi, type RateLimitDetails, type RegisterOptions, type RobotsApi, SDK_ERROR_CODES, type SdkErrorCode, type SendCommandOptions, type ServicesApi, type StoredSession, type TokenStore, type UrdfCompleteness, type UrdfSceneManager, type UrdfSceneResources, cancelRejectedDetails, createClient, parameterInvalidDetails };
2724
+ export { type AcceptInvitationOptions, type ActionsApi, type Asset, type AssetBytes, type AssetListResponse, type AssetsApi, type AuthApi, type BeginOidcLoginOptions, type BeginTwoFactorSetupOptions, type BusyDetails, CANCEL_RETURN_CODES, type CameraDescriptor, type CameraLiveSession, type CameraSnapshot, type CameraSnapshotMeta, type CamerasApi, type CancelRejectedDetails, type CancelReturnCode, type ClientIdentity, type ClientMcpInteraction, type ClientOidcErrorCode, type ClientRobotListItem, type CompleteOidcLoginOptions, type ConfirmTwoFactorSetupOptions, type CreateMeshLoaderOptions, type CredentialSource, type DatapointEvent, type DatapointSubscription, type DatapointSubscriptionHandlers, type DatapointValue, type DatapointsApi, type FleetlessClient, type FleetlessClientConfig, type FleetlessClientOptions, FleetlessError, type FleetlessErrorCode, type FleetlessErrorOptions, type HistoryAggregation, type HistoryBucketsResponse, type HistoryOptions, type HistorySamplesResponse, InMemoryTokenStore, type InvokeOptions, type Job, type JobEvent, type JobHistoryOptions, type JobOrigin, type JobRun, type JobRunListResponse, type JobState, type JobSubscription, type JobSubscriptionHandlers, type JobsApi, type McpCapabilities, type McpConsentGrant, type McpExposure, type McpInteractionDecision, type McpRobotDatasheet, type MeshLoaderDelegate, type OidcLoginRequest, type ParameterInvalidDetails, type ParameterViolation, type PrepareUrdfSceneOptions, type ProviderButton, type PublishersApi, type RateLimitDetails, type RegisterOptions, type RobotsApi, SDK_ERROR_CODES, type SdkErrorCode, type SendCommandOptions, type ServicesApi, type SignInMethods, type SignInResult, type StoredSession, type TokenStore, type TwoFactorSetup, type TwoFactorSetupConfirmation, type UrdfCompleteness, type UrdfSceneManager, type UrdfSceneResources, type VerifyTwoFactorOptions, cancelRejectedDetails, createClient, parameterInvalidDetails };