@fleetless/contracts 5.3.0-next.1 → 6.0.0-next.2

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +108 -33
  2. package/artifacts/openapi.json +2053 -784
  3. package/artifacts/routes.json +1680 -323
  4. package/artifacts/schema/accept-team-invite-request.schema.json +13 -7
  5. package/artifacts/schema/app-auth-config.schema.json +108 -4
  6. package/artifacts/schema/app-hosted-pages.schema.json +33 -0
  7. package/artifacts/schema/app-invitation.schema.json +5 -12
  8. package/artifacts/schema/app-mail-template-list-response.schema.json +4 -3
  9. package/artifacts/schema/app-mail-template.schema.json +3 -2
  10. package/artifacts/schema/app-sign-in-methods.schema.json +19 -0
  11. package/artifacts/schema/app-user-list-response.schema.json +36 -0
  12. package/artifacts/schema/app-user.schema.json +36 -0
  13. package/artifacts/schema/audit-query.schema.json +0 -6
  14. package/artifacts/schema/auth-me-response.schema.json +27 -0
  15. package/artifacts/schema/auth-ok.schema.json +13 -1
  16. package/artifacts/schema/client-accept-invitation-request.schema.json +3 -4
  17. package/artifacts/schema/client-identity.schema.json +13 -1
  18. package/artifacts/schema/client-login-code-request.schema.json +24 -0
  19. package/artifacts/schema/client-login-code-verify-request.schema.json +30 -0
  20. package/artifacts/schema/client-provider-list-response.schema.json +22 -2
  21. package/artifacts/schema/client-register-request.schema.json +3 -4
  22. package/artifacts/schema/client-sign-in-result.schema.json +55 -0
  23. package/artifacts/schema/client-two-factor-disable-request.schema.json +15 -0
  24. package/artifacts/schema/client-two-factor-setup-confirm-request.schema.json +20 -0
  25. package/artifacts/schema/client-two-factor-setup-confirm-response.schema.json +49 -0
  26. package/artifacts/schema/client-two-factor-setup-request.schema.json +12 -0
  27. package/artifacts/schema/client-two-factor-verify-request.schema.json +25 -0
  28. package/artifacts/schema/create-app-invitation-request.schema.json +1 -1
  29. package/artifacts/schema/create-passkey-request.schema.json +25 -0
  30. package/artifacts/schema/create-passkey-response.schema.json +84 -0
  31. package/artifacts/schema/developer-passkey.schema.json +56 -0
  32. package/artifacts/schema/developer-two-factor.schema.json +105 -0
  33. package/artifacts/schema/fleetless-user-list-response.schema.json +22 -0
  34. package/artifacts/schema/fleetless-user.schema.json +22 -0
  35. package/artifacts/schema/invalid-code-details.schema.json +16 -0
  36. package/artifacts/schema/job-actor.schema.json +1 -15
  37. package/artifacts/schema/job-run-list-response.schema.json +1 -15
  38. package/artifacts/schema/job-run.schema.json +1 -15
  39. package/artifacts/schema/org.schema.json +5 -0
  40. package/artifacts/schema/patch-org-request.schema.json +5 -3
  41. package/artifacts/schema/patch-org-response.schema.json +5 -0
  42. package/artifacts/schema/put-app-auth-look-request.schema.json +22 -0
  43. package/artifacts/schema/put-app-auth-mcp-request.schema.json +1 -14
  44. package/artifacts/schema/put-app-auth-sign-in-request.schema.json +39 -0
  45. package/artifacts/schema/put-app-auth-urls-request.schema.json +31 -4
  46. package/artifacts/schema/recovery-codes-response.schema.json +20 -0
  47. package/artifacts/schema/{role-rename-request.schema.json → rename-passkey-request.schema.json} +2 -2
  48. package/artifacts/schema/role-list-response.schema.json +1 -1
  49. package/artifacts/schema/role.schema.json +1 -1
  50. package/artifacts/schema/totp-confirm-request.schema.json +15 -0
  51. package/artifacts/schema/totp-confirm-response.schema.json +27 -0
  52. package/artifacts/schema/two-factor-challenge.schema.json +24 -0
  53. package/artifacts/schema/two-factor-setup-response.schema.json +21 -0
  54. package/artifacts/schema/webauthn-options-response.schema.json +18 -0
  55. package/dist/app-users.d.ts +154 -35
  56. package/dist/app-users.js +177 -46
  57. package/dist/apps.d.ts +2 -38
  58. package/dist/apps.js +3 -46
  59. package/dist/audit.d.ts +0 -1
  60. package/dist/audit.js +0 -13
  61. package/dist/client-auth.d.ts +133 -24
  62. package/dist/client-auth.js +139 -28
  63. package/dist/config.d.ts +2 -2
  64. package/dist/errors.d.ts +10 -1
  65. package/dist/errors.js +37 -38
  66. package/dist/identity.d.ts +175 -128
  67. package/dist/identity.js +192 -106
  68. package/dist/index.d.ts +11 -13
  69. package/dist/index.js +12 -10
  70. package/dist/jobs.d.ts +0 -3
  71. package/dist/jobs.js +0 -16
  72. package/dist/protocol.d.ts +1 -1
  73. package/dist/realtime.d.ts +1 -0
  74. package/dist/rest.d.ts +2 -2
  75. package/dist/rest.js +17 -28
  76. package/dist/routes.d.ts +26 -0
  77. package/dist/routes.js +528 -234
  78. package/package.json +1 -1
  79. package/artifacts/schema/developer-login-request.schema.json +0 -19
  80. package/artifacts/schema/feedback-request.schema.json +0 -34
  81. package/artifacts/schema/feedback-response.schema.json +0 -27
  82. package/artifacts/schema/password-reset-confirm.schema.json +0 -19
  83. package/artifacts/schema/password-reset-request.schema.json +0 -14
  84. package/artifacts/schema/role-delete-query.schema.json +0 -13
  85. package/artifacts/schema/role-in-use-details.schema.json +0 -28
  86. package/artifacts/schema/sign-up-request.schema.json +0 -26
  87. package/artifacts/schema/sign-up-response.schema.json +0 -127
  88. package/dist/feedback.d.ts +0 -42
  89. package/dist/feedback.js +0 -35
package/dist/identity.js CHANGED
@@ -7,9 +7,10 @@ import { z } from 'zod';
7
7
  * There are two identity spaces now and **nothing joins them**:
8
8
  *
9
9
  * - *Fleetless users*, this file. The people who configure robots in the
10
- * console. Email globally unique, tier `owner | developer`, a Fleetless
11
- * password, login through the auth portal. They always have MCP access, at
12
- * the one central endpoint.
10
+ * console. Email globally unique, tier `owner | developer`, sign-in through
11
+ * the auth portal by a code mailed to them or by a passkey — **no
12
+ * password** — with an optional second factor the organisation may require.
13
+ * They always have MCP access, at the one central endpoint.
13
14
  * - *app users*, `app-users.ts`. The people who use a developer's app. One app
14
15
  * each, email unique per app, authenticated through the JSON client-auth
15
16
  * API that the developer's own UI calls.
@@ -24,25 +25,31 @@ import { z } from 'zod';
24
25
  * the two populations have different lifecycles, and every joining mechanism
25
26
  * was cost without a product reason.
26
27
  *
27
- * What did **not** change: the password rules, the session and token shapes,
28
- * and the enumeration-oracle reasoning on password reset. None of those was
29
- * ever a statement about which space a person lived in.
28
+ * What did **not** change: the session and token shapes, and the
29
+ * enumeration-oracle reasoning. Neither was ever a statement about which space
30
+ * a person lived in.
31
+ *
32
+ * **Developers have no password any more.** They sign in with a six-digit
33
+ * code mailed to them, or with a passkey, which proves possession and user
34
+ * verification at once and so completes a sign-in on its own. After a code,
35
+ * a developer with a second factor — a passkey or an authenticator app —
36
+ * gives it; ten recovery codes are the fallback. The password sign-in, the
37
+ * password change, the reset pages and `POST /api/auth/signup` are gone: the
38
+ * portal's sign-up (email, code, organisation) is the one door in.
30
39
  *
31
40
  * **Email is globally unique here** — `lower(email)` unique across all orgs, so
32
- * one address is exactly one Fleetless user in exactly one org. Every shape
33
- * that identifies a person by a bare address (`developerLoginRequest`,
34
- * `passwordResetRequest`) therefore resolves to at most one account with no org
35
- * context needed. App users are the opposite and say so on their own shape:
36
- * unique **per app**, so one address may be several unrelated app accounts.
41
+ * one address is exactly one Fleetless user in exactly one org. A bare address
42
+ * therefore resolves to at most one account with no org context needed. App
43
+ * users are the opposite and say so on their own shape: unique **per app**, so
44
+ * one address may be several unrelated app accounts.
37
45
  */
38
46
  /**
39
47
  * The password rule, stated once so the cloud, the console and the SDK refuse
40
48
  * the same inputs for the same reason. Length only: a rule a user cannot
41
49
  * predict is a rule they work around.
42
50
  *
43
- * Shared by both identity spaces on purpose. A weaker rule for app users would
44
- * be a second policy for one decision, and the weaker one always wins by
45
- * accident.
51
+ * App users only: Fleetless users sign in by emailed code or passkey and hold
52
+ * no password.
46
53
  */
47
54
  export const password = z.string().min(12).max(256);
48
55
  /** The bound on a Fleetless user's display name; `APP_USER_DISPLAY_NAME_MAX` matches it, so a rename cannot be legal in one space and refused in the other. */
@@ -70,6 +77,9 @@ export const org = z.object({
70
77
  name: z.string().min(1).max(120).meta({
71
78
  description: 'The organisation\'s display name. Free text, changed through `PATCH /api/org`.',
72
79
  }),
80
+ require_two_factor: z.boolean().meta({
81
+ description: 'Whether every member must have a second factor — a passkey or an authenticator app. A member without one sets it up at their next sign-in, before any session exists; nobody is signed out when it is switched on. It covers the console and the central MCP endpoint; server keys and robot bridges are not people and are not affected. Owners change it through `PATCH /api/org`.',
82
+ }),
73
83
  created_at: z.iso.datetime().meta({
74
84
  description: 'When the organisation was created, as an ISO 8601 timestamp.',
75
85
  }),
@@ -81,8 +91,8 @@ export const patchOrgResponse = z.object({
81
91
  }),
82
92
  });
83
93
  /**
84
- * **A member of the org's team.** Console access, a tier, a Fleetless
85
- * password, and no relationship whatsoever to any app's users.
94
+ * **A member of the org's team.** Console access, a tier, a sign-in by
95
+ * emailed code or passkey, and no relationship whatsoever to any app's users.
86
96
  *
87
97
  * `email` is **globally unique** — `lower(email)` unique across every org, a
88
98
  * constraint the cloud enforces in the database; a schema cannot see two rows
@@ -93,10 +103,10 @@ export const patchOrgResponse = z.object({
93
103
  * groups), `mcp_access` (a Fleetless user always has MCP access, at the
94
104
  * central endpoint), and `has_password`. The last is the interesting one — it
95
105
  * existed because a pool user might have been provisioned by an identity
96
- * provider and hold no Fleetless credential. A Fleetless user always holds
97
- * one: the console is password-only by design, which removes the
98
- * IdP-lockout class entirely, so a field reporting whether the credential
99
- * exists would have exactly one value forever.
106
+ * provider and hold no Fleetless credential. Every Fleetless user signs in by
107
+ * a code mailed to their address, so the console has no federated door and
108
+ * no IdP-lockout class, and a field about a password would describe nothing.
109
+ * What varies is the second factor, which `two_factor` reports.
100
110
  */
101
111
  export const fleetlessUser = z.object({
102
112
  id: z.uuid().meta({
@@ -114,6 +124,14 @@ export const fleetlessUser = z.object({
114
124
  tier: orgAdminTier.meta({
115
125
  description: 'The console powers this person holds. **Required** — every Fleetless user has a tier; it was optional only while the org also held people with no console powers to grade, and that pool is gone.',
116
126
  }),
127
+ two_factor: z
128
+ .object({
129
+ passkeys: z.number().int().min(0).meta({ description: 'How many passkeys the person has registered.' }),
130
+ authenticator: z.boolean().meta({ description: 'Whether the person has a confirmed authenticator app.' }),
131
+ })
132
+ .meta({
133
+ description: 'The person\'s second factors, as the team list shows them: none, passkeys, an authenticator, or both. No credential travels here. An owner resets them through `DELETE /api/org/users/:id/two-factor`.',
134
+ }),
117
135
  created_at: z.iso.datetime().meta({
118
136
  description: 'When the account was created, as an ISO 8601 timestamp.',
119
137
  }),
@@ -144,28 +162,43 @@ export const sessionTokens = z.object({
144
162
  }),
145
163
  });
146
164
  export const refreshRequest = z.object({ refresh_token: z.string().min(1) });
165
+ /* ------------------------------------------- codes and second factors --
166
+ * Shared by both identity spaces, like `password` and `sessionTokens`: a
167
+ * six-digit code and a recovery code are the same thing whoever types them,
168
+ * and two spellings would be two rules for one decision.
169
+ */
147
170
  /**
148
- * Registering an org creates the org and its first owner in one step: whoever
149
- * registers the organisation is the owner.
171
+ * **A six-digit code**: the emailed sign-in code (valid ten minutes, five
172
+ * wrong attempts) and an authenticator's time-based code alike. Exactly six
173
+ * digits on the wire, leading zeros included — the portal and hosted forms
174
+ * strip spaces before they send it, the JSON API does not.
150
175
  */
151
- export const signUpRequest = z.object({
152
- org_name: z.string().min(1).max(120),
153
- email: z.email(),
154
- password,
155
- });
176
+ export const loginCode = z.string().regex(/^\d{6}$/, 'must be exactly six digits');
177
+ /** An authenticator app's code (TOTP, RFC 6238: SHA-1, six digits, thirty-second steps). The same shape as `loginCode`. */
178
+ export const totpCode = loginCode;
156
179
  /**
157
- * Registering answers with the founding **Fleetless user**, tier `owner`.
158
- *
159
- * The key is `user` rather than `member` or `owner`, and it has stayed `user`
160
- * through two identity redesigns deliberately: a renamed shape under a
161
- * renamed key would typecheck in every consumer that reads `.user.id` and mean
162
- * something subtly different, which is the quietest way for a cut like this to
163
- * go wrong.
180
+ * **A recovery code as typed**: two groups of five base32 characters,
181
+ * `xxxxx-xxxxx`, in either case — the cloud lower-cases before it compares.
182
+ * Single use.
183
+ */
184
+ export const recoveryCode = z.string().regex(/^[a-zA-Z2-7]{5}-[a-zA-Z2-7]{5}$/, 'must be two groups of five characters, xxxxx-xxxxx');
185
+ /**
186
+ * **The ten recovery codes, as issued**: lowercase, shown once. Generating a
187
+ * new set voids the old one.
164
188
  */
165
- export const signUpResponse = z.object({
166
- org,
167
- user: fleetlessUser,
168
- tokens: sessionTokens,
189
+ export const recoveryCodesList = z.array(z.string().regex(/^[a-z2-7]{5}-[a-z2-7]{5}$/)).length(10);
190
+ /**
191
+ * **An authenticator being set up**: the secret to type in, and the same
192
+ * secret as an `otpauth://` URL for a QR code. Nothing is stored as
193
+ * confirmed until a code from it is confirmed.
194
+ */
195
+ export const twoFactorSetupResponse = z.object({
196
+ secret: z.string().min(1).meta({
197
+ description: 'The shared secret, base32, for an authenticator app that cannot scan a QR code. Shown once; the cloud stores it encrypted.',
198
+ }),
199
+ otpauth_url: z.string().startsWith('otpauth://totp/').meta({
200
+ description: 'The same secret as an `otpauth://totp/` URL, to render as a QR code. It carries the secret: never log it.',
201
+ }),
169
202
  });
170
203
  /**
171
204
  * The landing page's waiting list (public site, 2026-09-04): one address,
@@ -178,24 +211,6 @@ export const signUpResponse = z.object({
178
211
  * turns an unauthenticated public route into a `500`.
179
212
  */
180
213
  export const waitlistRequest = z.object({ email: z.email().max(254) });
181
- /**
182
- * Console login. Fleetless users only, always the Fleetless password — the
183
- * console has no federated door at all, which removes the IdP-lockout
184
- * class entirely.
185
- *
186
- * This resolves a person by address alone, and a Fleetless user's email is
187
- * **globally unique**, so a bare address names at most one account and no org
188
- * context is needed to disambiguate. An org selector was never needed and
189
- * would have told an unauthenticated caller which org an address belongs to.
190
- *
191
- * **It cannot be reached by an app user**, whatever their address: the two
192
- * spaces have separate tables and separate routes, and a credential from one
193
- * never authenticates the other.
194
- */
195
- export const developerLoginRequest = z.object({
196
- email: z.email(),
197
- password: z.string().min(1),
198
- });
199
214
  /**
200
215
  * What happened to the mail, in four words instead of one.
201
216
  *
@@ -210,11 +225,9 @@ export const developerLoginRequest = z.object({
210
225
  * no sender can promise that, and this value must never
211
226
  * be rendered as if it could.
212
227
  * - `not_requested` — no mail was attempted: the caller asked for none
213
- * (`send_mail: false`), or there was no link for one to
214
- * carry (the app has configured no `invite_url`, which
215
- * the `null` `accept_url` beside it says). **A fourth
216
- * word rather than a reuse of `not_configured`**: the
217
- * deployment's mailer is irrelevant in both cases, and a
228
+ * (`send_mail: false`). **A fourth word rather than a
229
+ * reuse of `not_configured`**: the deployment's mailer
230
+ * is irrelevant there, and a
218
231
  * console reading "mail server not configured" beside an
219
232
  * invitation whose mail checkbox was off would send a
220
233
  * developer to fix something that is not broken.
@@ -304,14 +317,18 @@ export const pendingTeamInviteListResponse = z.object({
304
317
  description: 'Pending invitations only. An accepted invitation is history, not something to revoke.',
305
318
  }),
306
319
  });
307
- /** Accepting it: the token proves the invitation, the password creates the login. */
320
+ /**
321
+ * Accepting it: the token proves the invitation, and the mailed link proves
322
+ * the address, so accepting needs no code and takes **no password** — the
323
+ * new member signs in by emailed code from then on.
324
+ */
308
325
  export const acceptTeamInviteRequest = z
309
326
  .object({
310
327
  token: z.string().min(1).meta({
311
328
  description: 'The opaque invitation token from the link. Unknown, expired and already-accepted all collapse into `410 token_spent` — telling them apart would say whether a token ever existed.',
312
329
  }),
313
- password: password.meta({
314
- description: 'The password the new Fleetless account will use. At least 12 characters.',
330
+ display_name: z.string().min(1).max(USER_DISPLAY_NAME_MAX).nullable().optional().meta({
331
+ description: 'An optional name, overriding whatever the invitation pre-filled. Absent keeps it.',
315
332
  }),
316
333
  })
317
334
  .strict();
@@ -366,17 +383,14 @@ export const tierRequiredDetails = z.object({
366
383
  actual: orgAdminTier,
367
384
  });
368
385
  /**
369
- * Changing your own password while logged in.
386
+ * An app user changing their own password while signed in
387
+ * (`POST /api/client/password/change`). Fleetless users have no password.
370
388
  *
371
389
  * `current_password` is required even though the session already proves
372
390
  * identity: it is what makes a stolen *session* insufficient to take the
373
391
  * *account*. Every other session is revoked on success; the one that made the
374
392
  * change survives, because logging someone out of the tab they just used is
375
393
  * indistinguishable from the change having failed.
376
- *
377
- * Shared with the app-user surface (`POST /api/client/password/change`): the
378
- * argument is about credentials and sessions, not about which space the person
379
- * lives in.
380
394
  */
381
395
  export const passwordChangeRequest = z.object({
382
396
  current_password: z.string().min(1).meta({
@@ -386,39 +400,6 @@ export const passwordChangeRequest = z.object({
386
400
  description: 'The replacement password. Every other session is revoked when it is accepted, while the session that made the change survives — logging somebody out of the tab they just used is indistinguishable from the change having failed.',
387
401
  }),
388
402
  });
389
- /**
390
- * Asking for a reset link, **as a Fleetless user**.
391
- *
392
- * **The response never says whether the address exists.** It is unauthenticated
393
- * and would otherwise be an account-enumeration oracle — the one place where
394
- * revealing nothing about what exists is not a preference but the whole point.
395
- * So this answers the same way for a known and an unknown address, in
396
- * status, body **and timing**, and any consumer that renders "no such account"
397
- * from it has reintroduced the oracle.
398
- *
399
- * A bare address resolves to at most one account: a Fleetless user's email is
400
- * **globally unique**, so the reset mails the one match, if any, with a token
401
- * bound to that account.
402
- *
403
- * The app-user equivalent is `clientPasswordResetRequest` in `client-auth.ts`
404
- * and carries an `app_identifier`, because on that surface a person is
405
- * identified by app *and* address. Two shapes rather than one, because the two
406
- * surfaces identify a person differently — not because the reasoning differs.
407
- */
408
- export const passwordResetRequest = z.object({
409
- email: z.email(),
410
- });
411
- /**
412
- * Using the link. The token is **single-use and expires**; spending it revokes
413
- * every session of that subject, because a forgotten password is one of the
414
- * two states where somebody else may be holding one. `token_spent` covers used
415
- * and expired alike — telling them apart tells a stranger whether a token ever
416
- * existed.
417
- */
418
- export const passwordResetConfirm = z.object({
419
- token: z.string().min(1),
420
- new_password: password,
421
- });
422
403
  /**
423
404
  * An IdP issuer URL — **an attacker-supplied string that decides where the
424
405
  * *server* connects.**
@@ -471,8 +452,8 @@ export const idpIssuer = z
471
452
  * here.** `oidcCallbackErrorCode` and `oidcCallbackError` described the page
472
453
  * `GET /mcp/oauth/idp-callback` rendered when a group's identity provider sent
473
454
  * a browser back — `jit_disabled` and `email_collision` name provisioning steps
474
- * only a group provider had. Fleetless users are password-only now, which deletes
475
- * group providers, so the flow that produced these codes cannot start; the
455
+ * only a group provider had. Fleetless users sign in by emailed code or
456
+ * passkey, with no group providers, so the flow that produced these codes cannot start; the
476
457
  * route is gone from this manifest and from the cloud.
477
458
  *
478
459
  * The per-app OIDC vocabulary is `clientOidcErrorCode` in `client-auth.ts`: a
@@ -492,7 +473,112 @@ export const idpIssuer = z
492
473
  * field required on the shape itself.
493
474
  */
494
475
  export const authMeResponse = z.object({ org, user: fleetlessUser });
495
- /** `PATCH /api/org` — rename the org. Owner only. Same bounds as signup's `org_name`. */
496
- export const patchOrgRequest = z.object({ name: z.string().min(1).max(120) }).strict();
476
+ /**
477
+ * `PATCH /api/org` — rename the org, require two-factor for its members, or
478
+ * both. Owner only. At least one field: an empty patch is a refusal rather
479
+ * than a write that changed nothing.
480
+ */
481
+ export const patchOrgRequest = z
482
+ .object({
483
+ name: z.string().min(1).max(120).optional().meta({
484
+ description: 'The organisation\'s new display name. Absent leaves it alone.',
485
+ }),
486
+ require_two_factor: z.boolean().optional().meta({
487
+ description: 'Whether every member must have a second factor. Turning it on signs nobody out: each member without one sets it up at their next sign-in. Absent leaves it alone.',
488
+ }),
489
+ })
490
+ .strict()
491
+ .refine((b) => b.name !== undefined || b.require_two_factor !== undefined, { message: 'Send name, require_two_factor, or both.' });
497
492
  /** `PATCH /api/auth/me` — the caller updates their own display name (null clears it). */
498
493
  export const patchAuthMeRequest = z.object({ display_name: z.string().min(1).max(USER_DISPLAY_NAME_MAX).nullable() }).strict();
494
+ /* ----------------------------------------- a developer's second factors --
495
+ * Settings › Profile › Security in the console. Several passkeys, at most one
496
+ * authenticator app, and ten recovery codes issued with the first factor.
497
+ * Passkeys are for Fleetless users only; app users have the authenticator.
498
+ */
499
+ /**
500
+ * **A WebAuthn JSON document, opaque here.** The `PublicKeyCredential*JSON`
501
+ * shapes of the WebAuthn Level 3 specification — creation and request options
502
+ * going out, the browser's credential coming back. The browser API and the
503
+ * server library define them; a second, hand-written copy here would be one
504
+ * that drifts.
505
+ */
506
+ export const webauthnJson = z.record(z.string(), z.unknown());
507
+ /**
508
+ * **Options for a WebAuthn ceremony**, to hand to the browser as they are.
509
+ * The relying party is `fleetless.dev`, so the auth portal and the console
510
+ * both accept the same passkey; user verification is required.
511
+ */
512
+ export const webauthnOptionsResponse = z.object({
513
+ options: webauthnJson.meta({
514
+ description: 'The `PublicKeyCredentialCreationOptionsJSON` or `PublicKeyCredentialRequestOptionsJSON` to pass to the browser. Its challenge is single-use and short-lived.',
515
+ }),
516
+ });
517
+ /** **One registered passkey**, as Settings › Profile lists it. No key material travels here. */
518
+ export const developerPasskey = z.object({
519
+ id: z.uuid().meta({ description: 'The passkey in the API, as renamed and removed through `/api/auth/passkeys/:id`.' }),
520
+ name: z.string().min(1).max(80).meta({ description: 'What the person called it, such as the device it lives on.' }),
521
+ created_at: z.iso.datetime().meta({ description: 'When it was registered.' }),
522
+ last_used_at: z.iso.datetime().nullable().meta({ description: 'When it last signed the person in or confirmed a sign-in, or `null` if never.' }),
523
+ synced: z.boolean().nullable().meta({
524
+ description: 'Whether the authenticator reported the passkey as syncable across the person\'s devices (the backup-eligible flag), or `null` when it said nothing.',
525
+ }),
526
+ });
527
+ /** **`GET /api/auth/two-factor`** — the caller's own second factors, in full. */
528
+ export const developerTwoFactor = z.object({
529
+ passkeys: z.array(developerPasskey).meta({ description: 'Every passkey the caller has registered, oldest first. Empty when none.' }),
530
+ authenticator: z
531
+ .object({ created_at: z.iso.datetime().meta({ description: 'When the authenticator was confirmed.' }) })
532
+ .nullable()
533
+ .meta({ description: 'The confirmed authenticator app, or `null` when there is none. At most one.' }),
534
+ recovery_codes_left: z.number().int().min(0).max(10).meta({
535
+ description: 'How many of the ten recovery codes are unspent. `0` while the caller has no second factor.',
536
+ }),
537
+ required_by_org: z.boolean().meta({
538
+ description: 'Whether the organisation requires a second factor. While it does, the last one cannot be removed.',
539
+ }),
540
+ });
541
+ /** **Registering a passkey**: the name, and the browser's answer to the creation options. */
542
+ export const createPasskeyRequest = z
543
+ .object({
544
+ name: z.string().min(1).max(80).meta({ description: 'What to call the passkey, such as the device it lives on.' }),
545
+ credential: webauthnJson.meta({ description: 'The browser\'s `RegistrationResponseJSON` for the options `POST /api/auth/passkeys/options` answered.' }),
546
+ })
547
+ .strict();
548
+ /**
549
+ * **The registered passkey**, and the ten recovery codes when it is the
550
+ * account's first second factor — `null` otherwise, since the existing codes
551
+ * stay valid.
552
+ */
553
+ export const createPasskeyResponse = z.object({
554
+ passkey: developerPasskey.meta({ description: 'The passkey as it is now stored.' }),
555
+ recovery_codes: recoveryCodesList.nullable().meta({
556
+ description: 'The ten recovery codes, shown once, when this passkey is the account\'s first second factor; `null` when the account already had one and its codes stay valid.',
557
+ }),
558
+ });
559
+ /** **Renaming a passkey.** The name is the only thing about one that can change. */
560
+ export const renamePasskeyRequest = z
561
+ .object({
562
+ name: z.string().min(1).max(80).meta({ description: 'The new name.' }),
563
+ })
564
+ .strict();
565
+ /** **Confirming a new authenticator** with a code it shows now. */
566
+ export const totpConfirmRequest = z
567
+ .object({
568
+ code: totpCode.meta({ description: 'A code the new authenticator shows now. It proves the secret was copied correctly before anything depends on it.' }),
569
+ })
570
+ .strict();
571
+ /**
572
+ * **The confirmed authenticator.** Ten recovery codes when it is the
573
+ * account's first second factor; `null` when it replaces an authenticator or
574
+ * joins passkeys, whose codes stay valid.
575
+ */
576
+ export const totpConfirmResponse = z.object({
577
+ recovery_codes: recoveryCodesList.nullable().meta({
578
+ description: 'The ten recovery codes, shown once, when this is the account\'s first second factor; `null` otherwise.',
579
+ }),
580
+ });
581
+ /** **A fresh set of ten recovery codes**, shown once. The previous set stops working. */
582
+ export const recoveryCodesResponse = z.object({
583
+ recovery_codes: recoveryCodesList.meta({ description: 'The ten new recovery codes, lowercase, shown once. Every earlier code is void.' }),
584
+ });
package/dist/index.d.ts CHANGED
@@ -29,27 +29,25 @@ export type { UsageMetric, OrgUsageQuery, UsageRow, OrgUsageResponse } from './r
29
29
  export type { Robot, PatchRobotResponse, CreateRobotRequest, CreateRobotResponse, RobotTokenRotateResponse, JointStatePutRequest, JointStatePutResponse, ExposureCounts, ProtocolStatusValue, RobotListItem, RobotListResponse, DatapointValue, RobotDetailResponse, ConfigDraftResponse, PutConfigDraftRequest, PublishConfigResponse, ConfigVersionsResponse, ConfigVersionResponse, IntrospectionResponse, TypesResponse, FetchTypesRequest, FetchTypesResponse, DatapointDescriptor, DatapointListResponse, RobotDetailsDoc, PutRobotDetailsResponse, PutRobotDetailsRequest, InvokeRequest, InvokeResponse, CancelRequest, ReleaseLiveQuery, ServiceCallResponse, InvokeOrServiceResponse, PublishRequest, JobResponse, RobotJobsResponse, RateLimitDetails, Exposure, ExposureListResponse, CameraDescriptor, CameraListResponse, LiveSessionResponse, SnapshotMetaResponse, } from './rest.js';
30
30
  export { clientAuth, authOk, authError, clientInvoke, clientCancel, clientPublish, commandResult, errorFrame, clientSubscribe, clientUnsubscribe, subscribeError, datapointEvent, resourceHealthEvent, resourceHealthCleared, liveSessionEndReason, liveSessionEvent, ORG_EVENT_SAMPLE_INTERVAL_MS, ORG_EVENT_ORG_CEILING_PER_SECOND, ORG_EVENT_BUFFER_SIZE, ORG_EVENT_BUFFER_IDLE_MS, ORG_EVENT_DETAIL_MAX_BYTES, orgEventKind, orgEventSeverity, orgEvent, orgEventSubscribe, orgEventUnsubscribe, orgEventReplay, orgEventDropped, } from './realtime.js';
31
31
  export type { ClientAuth, AuthOk, AuthError, ClientInvoke, ClientCancel, ClientPublish, CommandResult, ErrorFrame, ClientSubscribe, ClientUnsubscribe, SubscribeError, DatapointEvent, ResourceHealthEvent, ResourceHealthCleared, LiveSessionEndReason, LiveSessionEvent, OrgEventKind, OrgEventSeverity, OrgEvent, OrgEventSubscribe, OrgEventUnsubscribe, OrgEventReplay, OrgEventDropped, } from './realtime.js';
32
- export { password, org, patchOrgResponse, sessionTokens, refreshRequest, signUpRequest, signUpResponse, waitlistRequest, developerLoginRequest, USER_DISPLAY_NAME_MAX, orgAdminTier, fleetlessUser, fleetlessUserListResponse, createTeamInviteRequest, teamInvite, pendingTeamInvite, pendingTeamInviteListResponse, acceptTeamInviteRequest, patchFleetlessUserRequest, tierChangeRequest, mailStatus, tierRequiredDetails, passwordChangeRequest, passwordResetRequest, passwordResetConfirm, idpIssuer, authMeResponse, patchOrgRequest, patchAuthMeRequest, } from './identity.js';
33
- export type { Org, PatchOrgResponse, SessionTokens, RefreshRequest, SignUpRequest, SignUpResponse, WaitlistRequest, DeveloperLoginRequest, OrgAdminTier, FleetlessUser, FleetlessUserListResponse, CreateTeamInviteRequest, TeamInvite, PendingTeamInvite, PendingTeamInviteListResponse, AcceptTeamInviteRequest, PatchFleetlessUserRequest, TierChangeRequest, MailStatus, TierRequiredDetails, PasswordChangeRequest, PasswordResetRequest, PasswordResetConfirm, IdpIssuer, AuthMeResponse, PatchOrgRequest, PatchAuthMeRequest, } from './identity.js';
34
- export { FEEDBACK_KINDS, FEEDBACK_MESSAGE_MAX, feedbackKind, feedbackRequest, feedbackResponse } from './feedback.js';
35
- export type { FeedbackKind, FeedbackRequest, FeedbackResponse } from './feedback.js';
36
- export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, roleRenameRequest, roleDeleteQuery, roleInUseDetails, } from './apps.js';
37
- export type { App, AppListResponse, AppDeletionSummary, CreateAppRequest, UpdateAppRequest, ServerKey, ServerKeyListResponse, CreateServerKeyResponse, Role, RoleListResponse, RolePermissions, RoleRenameRequest, RoleDeleteQuery, RoleInUseDetails, } from './apps.js';
38
- export { clientLoginRequest, clientRefreshRequest, clientLogoutRequest, clientRegisterRequest, clientVerifyEmailRequest, clientResendVerificationRequest, clientPasswordResetRequest, clientPasswordResetConfirmRequest, clientAcceptInvitationRequest, CLIENT_OIDC_CALLBACK_PATH, clientProviderListQuery, clientProviderListResponse, clientOidcStartQuery, clientOidcCallbackQuery, clientOidcExchangeRequest, clientOidcErrorCode, clientMcpInteraction, clientMcpInteractionDecisionResponse, mcpConsentGrant, mcpConsentGrantListResponse, clientIdentity, } from './client-auth.js';
39
- export type { ClientLoginRequest, ClientRefreshRequest, ClientLogoutRequest, ClientRegisterRequest, ClientVerifyEmailRequest, ClientResendVerificationRequest, ClientPasswordResetRequest, ClientPasswordResetConfirmRequest, ClientAcceptInvitationRequest, ClientProviderListQuery, ClientProviderListResponse, ClientOidcStartQuery, ClientOidcCallbackQuery, ClientOidcExchangeRequest, ClientOidcErrorCode, ClientMcpInteraction, ClientMcpInteractionDecisionResponse, McpConsentGrant, McpConsentGrantListResponse, ClientIdentity, } from './client-auth.js';
32
+ export { password, org, patchOrgResponse, sessionTokens, refreshRequest, waitlistRequest, USER_DISPLAY_NAME_MAX, orgAdminTier, fleetlessUser, fleetlessUserListResponse, createTeamInviteRequest, teamInvite, pendingTeamInvite, pendingTeamInviteListResponse, acceptTeamInviteRequest, patchFleetlessUserRequest, tierChangeRequest, mailStatus, tierRequiredDetails, passwordChangeRequest, idpIssuer, loginCode, totpCode, recoveryCode, recoveryCodesList, twoFactorSetupResponse, webauthnJson, webauthnOptionsResponse, developerPasskey, developerTwoFactor, createPasskeyRequest, createPasskeyResponse, renamePasskeyRequest, totpConfirmRequest, totpConfirmResponse, recoveryCodesResponse, authMeResponse, patchOrgRequest, patchAuthMeRequest, } from './identity.js';
33
+ export type { Org, PatchOrgResponse, SessionTokens, RefreshRequest, WaitlistRequest, OrgAdminTier, FleetlessUser, FleetlessUserListResponse, CreateTeamInviteRequest, TeamInvite, PendingTeamInvite, PendingTeamInviteListResponse, AcceptTeamInviteRequest, PatchFleetlessUserRequest, TierChangeRequest, MailStatus, TierRequiredDetails, PasswordChangeRequest, IdpIssuer, TwoFactorSetupResponse, WebauthnOptionsResponse, DeveloperPasskey, DeveloperTwoFactor, CreatePasskeyRequest, CreatePasskeyResponse, RenamePasskeyRequest, TotpConfirmRequest, TotpConfirmResponse, RecoveryCodesResponse, AuthMeResponse, PatchOrgRequest, PatchAuthMeRequest, } from './identity.js';
34
+ export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, } from './apps.js';
35
+ export type { App, AppListResponse, AppDeletionSummary, CreateAppRequest, UpdateAppRequest, ServerKey, ServerKeyListResponse, CreateServerKeyResponse, Role, RoleListResponse, RolePermissions, } from './apps.js';
36
+ export { clientLoginRequest, clientRefreshRequest, clientLogoutRequest, clientRegisterRequest, clientVerifyEmailRequest, clientResendVerificationRequest, clientPasswordResetRequest, clientPasswordResetConfirmRequest, clientAcceptInvitationRequest, CLIENT_OIDC_CALLBACK_PATH, clientProviderListQuery, clientProviderListResponse, clientOidcStartQuery, clientOidcCallbackQuery, clientOidcExchangeRequest, clientOidcErrorCode, clientMcpInteraction, clientMcpInteractionDecisionResponse, mcpConsentGrant, mcpConsentGrantListResponse, clientIdentity, clientLoginCodeRequest, clientLoginCodeVerifyRequest, twoFactorChallenge, clientSignInResult, clientTwoFactorVerifyRequest, clientTwoFactorSetupRequest, clientTwoFactorSetupConfirmRequest, clientTwoFactorSetupConfirmResponse, clientTwoFactorDisableRequest, } from './client-auth.js';
37
+ export type { ClientLoginRequest, ClientRefreshRequest, ClientLogoutRequest, ClientRegisterRequest, ClientVerifyEmailRequest, ClientResendVerificationRequest, ClientPasswordResetRequest, ClientPasswordResetConfirmRequest, ClientAcceptInvitationRequest, ClientProviderListQuery, ClientProviderListResponse, ClientOidcStartQuery, ClientOidcCallbackQuery, ClientOidcExchangeRequest, ClientOidcErrorCode, ClientMcpInteraction, ClientMcpInteractionDecisionResponse, McpConsentGrant, McpConsentGrantListResponse, ClientIdentity, ClientLoginCodeRequest, ClientLoginCodeVerifyRequest, TwoFactorChallenge, ClientSignInResult, ClientTwoFactorVerifyRequest, ClientTwoFactorSetupRequest, ClientTwoFactorSetupConfirmRequest, ClientTwoFactorSetupConfirmResponse, ClientTwoFactorDisableRequest, } from './client-auth.js';
40
38
  export { clientRobotListItem, clientRobotListResponse } from './client-robots.js';
41
39
  export type { ClientRobotListItem, ClientRobotListResponse } from './client-robots.js';
42
- export { APP_USER_DISPLAY_NAME_MAX, APP_URL_PLACEHOLDERS, MAIL_TEMPLATE_VARIABLES, DEFAULT_MAIL_TEMPLATES, providerSlug, appUserStatus, appUser, appUserListResponse, createAppUserRequest, patchAppUserRequest, createAppInvitationRequest, appInvitation, pendingAppInvitation, appInvitationListResponse, appOidcProvider, appOidcProviderListResponse, createAppOidcProviderRequest, patchAppOidcProviderRequest, appUrlTemplate, allowedOrigin, emailDomain, appAuthConfig, putAppAuthRegistrationRequest, putAppAuthUrlsRequest, putAppAuthMcpRequest, mailTemplateKind, appMailTemplate, appMailTemplateListResponse, putAppMailTemplateRequest, mailTemplatePreviewRequest, mailTemplatePreviewResponse, mailTemplateProblemDetails, mailOutcome, } from './app-users.js';
43
- export type { AppUserStatus, AppUser, AppUserListResponse, CreateAppUserRequest, PatchAppUserRequest, CreateAppInvitationRequest, AppInvitation, PendingAppInvitation, AppInvitationListResponse, AppOidcProvider, AppOidcProviderListResponse, CreateAppOidcProviderRequest, PatchAppOidcProviderRequest, AppAuthConfig, PutAppAuthRegistrationRequest, PutAppAuthUrlsRequest, PutAppAuthMcpRequest, MailTemplateKind, AppMailTemplate, AppMailTemplateListResponse, PutAppMailTemplateRequest, MailTemplatePreviewRequest, MailTemplatePreviewResponse, MailTemplateProblemDetails, MailOutcome, } from './app-users.js';
40
+ export { APP_USER_DISPLAY_NAME_MAX, APP_URL_PLACEHOLDERS, MAIL_TEMPLATE_VARIABLES, DEFAULT_MAIL_TEMPLATES, providerSlug, appUserStatus, appUser, appUserListResponse, createAppUserRequest, patchAppUserRequest, createAppInvitationRequest, appInvitation, pendingAppInvitation, appInvitationListResponse, appOidcProvider, appOidcProviderListResponse, createAppOidcProviderRequest, patchAppOidcProviderRequest, appUrlTemplate, allowedOrigin, emailDomain, appAuthConfig, appSignInMethods, appTwoFactorPolicy, appHomeUrl, hostedAccent, HOSTED_LOGO_MAX_BYTES, HOSTED_LOGO_TYPES, appHostedPages, putAppAuthRegistrationRequest, putAppAuthSignInRequest, putAppAuthUrlsRequest, putAppAuthMcpRequest, putAppAuthLookRequest, mailTemplateKind, appMailTemplate, appMailTemplateListResponse, putAppMailTemplateRequest, mailTemplatePreviewRequest, mailTemplatePreviewResponse, mailTemplateProblemDetails, mailOutcome, } from './app-users.js';
41
+ export type { AppUserStatus, AppUser, AppUserListResponse, CreateAppUserRequest, PatchAppUserRequest, CreateAppInvitationRequest, AppInvitation, PendingAppInvitation, AppInvitationListResponse, AppOidcProvider, AppOidcProviderListResponse, CreateAppOidcProviderRequest, PatchAppOidcProviderRequest, AppAuthConfig, AppSignInMethods, AppTwoFactorPolicy, AppHostedPages, PutAppAuthRegistrationRequest, PutAppAuthSignInRequest, PutAppAuthUrlsRequest, PutAppAuthMcpRequest, PutAppAuthLookRequest, MailTemplateKind, AppMailTemplate, AppMailTemplateListResponse, PutAppMailTemplateRequest, MailTemplatePreviewRequest, MailTemplatePreviewResponse, MailTemplateProblemDetails, MailOutcome, } from './app-users.js';
44
42
  export { assetKind, URDF_ASSET_NAME, asset, urdfCompleteness, assetListResponse, assetsClearResponse, missingAssetQuery, assetSyncRequest, assetSyncResponse, assetSyncState, assetSyncStatus, assetFailure, assetFailureKind, assetStoreRefusedDetails, assetSyncBusyDetails, ROBOT_ASSET_STORE_BYTES, } from './assets.js';
45
43
  export type { AssetKind, Asset, UrdfCompleteness, AssetListResponse, AssetsClearResponse, MissingAssetQuery, AssetSyncRequest, AssetSyncResponse, AssetSyncState, AssetSyncStatus, AssetFailure, AssetFailureKind, AssetStoreRefusedDetails, AssetSyncBusyDetails, } from './assets.js';
46
44
  export { auditActor, auditEvent, auditQuery, auditListResponse, AUDIT_CSV_COLUMNS, AUDIT_RETENTION_DAYS } from './audit.js';
47
45
  export type { AuditActor, AuditEvent, AuditQuery, AuditListResponse } from './audit.js';
48
46
  export { alertRowCondition, alertSeverity, alertState, datapointAlertRow, alertListResponse, orgFiringAlertsResponse, orgAlertsQuery, datapointDisplay, putDatapointDisplayRequest, } from './alerts.js';
49
47
  export type { AlertRowCondition, AlertSeverity, AlertState, DatapointAlertRow, AlertListResponse, OrgFiringAlertsResponse, OrgAlertsQuery, DatapointDisplay, PutDatapointDisplayRequest, } from './alerts.js';
50
- export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, ERROR_CODES } from './errors.js';
51
- export type { ApiError, ParameterViolation, ParameterInvalidDetails, CancelRejectedDetails, ErrorCode } from './errors.js';
48
+ export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, invalidCodeDetails, ERROR_CODES } from './errors.js';
49
+ export type { ApiError, ParameterViolation, ParameterInvalidDetails, CancelRejectedDetails, InvalidCodeDetails, ErrorCode } from './errors.js';
52
50
  export { oauthErrorCode, oauthError, oauthRedirectResponse, oauthCodeTokenRequest, oauthRefreshTokenRequest, oauthTokenRequest, oauthTokenResponse, redirectUri, codeChallengeMethod, oauthAuthorizeQuery, dynamicClientRegistrationRequest, MCP_DCR_MAX_REDIRECT_URIS, dynamicClientRegistrationResponse, authorizationServerMetadata, protectedResourceMetadata, } from './oauth.js';
53
51
  export type { OauthErrorCode, OauthError, OauthRedirectResponse, OauthCodeTokenRequest, OauthRefreshTokenRequest, OauthTokenRequest, OauthTokenResponse, RedirectUri, OauthAuthorizeQuery, DynamicClientRegistrationRequest, DynamicClientRegistrationResponse, AuthorizationServerMetadata, ProtectedResourceMetadata, } from './oauth.js';
54
- export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES } from './routes.js';
52
+ export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES, developerSignInRoutes } from './routes.js';
55
53
  export type { RouteEntry, RouteParam, RouteAudience, RouteAuth, RouteSection, RouteMethod, RouteTransport, } from './routes.js';
package/dist/index.js CHANGED
@@ -29,25 +29,27 @@ historyQuery, historySamplesResponse, historyBucketsResponse, historyResponse, o
29
29
  patchRobotRequest, renameSlugRequest, renameSlugResponse, slugUsageResponse, } from './rest.js';
30
30
  export { LATENCY_BUCKET_MS, BRIDGE_LATENCY_RETENTION_DAYS, MAX_LATENCY_BUCKETS_PER_RESPONSE, latencyBucket, robotLatencySeries, orgLatencyQuery, orgLatencyResponse, USAGE_WINDOW_MAX_DAYS, usageMetric, usageDay, orgUsageQuery, usageRow, orgUsageResponse, } from './rest.js';
31
31
  export { clientAuth, authOk, authError, clientInvoke, clientCancel, clientPublish, commandResult, errorFrame, clientSubscribe, clientUnsubscribe, subscribeError, datapointEvent, resourceHealthEvent, resourceHealthCleared, liveSessionEndReason, liveSessionEvent, ORG_EVENT_SAMPLE_INTERVAL_MS, ORG_EVENT_ORG_CEILING_PER_SECOND, ORG_EVENT_BUFFER_SIZE, ORG_EVENT_BUFFER_IDLE_MS, ORG_EVENT_DETAIL_MAX_BYTES, orgEventKind, orgEventSeverity, orgEvent, orgEventSubscribe, orgEventUnsubscribe, orgEventReplay, orgEventDropped, } from './realtime.js';
32
- export { password, org, patchOrgResponse, sessionTokens, refreshRequest, signUpRequest, signUpResponse,
32
+ export { password, org, patchOrgResponse, sessionTokens, refreshRequest,
33
33
  // 2026-09-04 — the public site (closed beta).
34
- waitlistRequest, developerLoginRequest,
34
+ waitlistRequest,
35
35
  // The two identity spaces.
36
36
  USER_DISPLAY_NAME_MAX, orgAdminTier, fleetlessUser, fleetlessUserListResponse, createTeamInviteRequest, teamInvite, pendingTeamInvite, pendingTeamInviteListResponse, acceptTeamInviteRequest, patchFleetlessUserRequest, tierChangeRequest,
37
37
  // Identity.
38
- mailStatus, tierRequiredDetails, passwordChangeRequest, passwordResetRequest, passwordResetConfirm, idpIssuer,
38
+ mailStatus, tierRequiredDetails, passwordChangeRequest, idpIssuer,
39
+ // Codes and second factors, shared by both identity spaces.
40
+ loginCode, totpCode, recoveryCode, recoveryCodesList, twoFactorSetupResponse,
41
+ // A developer's second factors.
42
+ webauthnJson, webauthnOptionsResponse, developerPasskey, developerTwoFactor, createPasskeyRequest, createPasskeyResponse, renamePasskeyRequest, totpConfirmRequest, totpConfirmResponse, recoveryCodesResponse,
39
43
  // auth/me, org and member patches.
40
44
  authMeResponse, patchOrgRequest, patchAuthMeRequest, } from './identity.js';
41
- // 2026-09-30 — the console's feedback modal.
42
- export { FEEDBACK_KINDS, FEEDBACK_MESSAGE_MAX, feedbackKind, feedbackRequest, feedbackResponse } from './feedback.js';
43
- export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, roleRenameRequest, roleDeleteQuery, roleInUseDetails, } from './apps.js';
44
- export { clientLoginRequest, clientRefreshRequest, clientLogoutRequest, clientRegisterRequest, clientVerifyEmailRequest, clientResendVerificationRequest, clientPasswordResetRequest, clientPasswordResetConfirmRequest, clientAcceptInvitationRequest, CLIENT_OIDC_CALLBACK_PATH, clientProviderListQuery, clientProviderListResponse, clientOidcStartQuery, clientOidcCallbackQuery, clientOidcExchangeRequest, clientOidcErrorCode, clientMcpInteraction, clientMcpInteractionDecisionResponse, mcpConsentGrant, mcpConsentGrantListResponse, clientIdentity, } from './client-auth.js';
45
+ export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, } from './apps.js';
46
+ export { clientLoginRequest, clientRefreshRequest, clientLogoutRequest, clientRegisterRequest, clientVerifyEmailRequest, clientResendVerificationRequest, clientPasswordResetRequest, clientPasswordResetConfirmRequest, clientAcceptInvitationRequest, CLIENT_OIDC_CALLBACK_PATH, clientProviderListQuery, clientProviderListResponse, clientOidcStartQuery, clientOidcCallbackQuery, clientOidcExchangeRequest, clientOidcErrorCode, clientMcpInteraction, clientMcpInteractionDecisionResponse, mcpConsentGrant, mcpConsentGrantListResponse, clientIdentity, clientLoginCodeRequest, clientLoginCodeVerifyRequest, twoFactorChallenge, clientSignInResult, clientTwoFactorVerifyRequest, clientTwoFactorSetupRequest, clientTwoFactorSetupConfirmRequest, clientTwoFactorSetupConfirmResponse, clientTwoFactorDisableRequest, } from './client-auth.js';
45
47
  export { clientRobotListItem, clientRobotListResponse } from './client-robots.js';
46
48
  // The per-app identity space.
47
- export { APP_USER_DISPLAY_NAME_MAX, APP_URL_PLACEHOLDERS, MAIL_TEMPLATE_VARIABLES, DEFAULT_MAIL_TEMPLATES, providerSlug, appUserStatus, appUser, appUserListResponse, createAppUserRequest, patchAppUserRequest, createAppInvitationRequest, appInvitation, pendingAppInvitation, appInvitationListResponse, appOidcProvider, appOidcProviderListResponse, createAppOidcProviderRequest, patchAppOidcProviderRequest, appUrlTemplate, allowedOrigin, emailDomain, appAuthConfig, putAppAuthRegistrationRequest, putAppAuthUrlsRequest, putAppAuthMcpRequest, mailTemplateKind, appMailTemplate, appMailTemplateListResponse, putAppMailTemplateRequest, mailTemplatePreviewRequest, mailTemplatePreviewResponse, mailTemplateProblemDetails, mailOutcome, } from './app-users.js';
49
+ export { APP_USER_DISPLAY_NAME_MAX, APP_URL_PLACEHOLDERS, MAIL_TEMPLATE_VARIABLES, DEFAULT_MAIL_TEMPLATES, providerSlug, appUserStatus, appUser, appUserListResponse, createAppUserRequest, patchAppUserRequest, createAppInvitationRequest, appInvitation, pendingAppInvitation, appInvitationListResponse, appOidcProvider, appOidcProviderListResponse, createAppOidcProviderRequest, patchAppOidcProviderRequest, appUrlTemplate, allowedOrigin, emailDomain, appAuthConfig, appSignInMethods, appTwoFactorPolicy, appHomeUrl, hostedAccent, HOSTED_LOGO_MAX_BYTES, HOSTED_LOGO_TYPES, appHostedPages, putAppAuthRegistrationRequest, putAppAuthSignInRequest, putAppAuthUrlsRequest, putAppAuthMcpRequest, putAppAuthLookRequest, mailTemplateKind, appMailTemplate, appMailTemplateListResponse, putAppMailTemplateRequest, mailTemplatePreviewRequest, mailTemplatePreviewResponse, mailTemplateProblemDetails, mailOutcome, } from './app-users.js';
48
50
  export { assetKind, URDF_ASSET_NAME, asset, urdfCompleteness, assetListResponse, assetsClearResponse, missingAssetQuery, assetSyncRequest, assetSyncResponse, assetSyncState, assetSyncStatus, assetFailure, assetFailureKind, assetStoreRefusedDetails, assetSyncBusyDetails, ROBOT_ASSET_STORE_BYTES, } from './assets.js';
49
51
  export { auditActor, auditEvent, auditQuery, auditListResponse, AUDIT_CSV_COLUMNS, AUDIT_RETENTION_DAYS } from './audit.js';
50
52
  export { alertRowCondition, alertSeverity, alertState, datapointAlertRow, alertListResponse, orgFiringAlertsResponse, orgAlertsQuery, datapointDisplay, putDatapointDisplayRequest, } from './alerts.js';
51
- export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, ERROR_CODES } from './errors.js';
53
+ export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, invalidCodeDetails, ERROR_CODES } from './errors.js';
52
54
  export { oauthErrorCode, oauthError, oauthRedirectResponse, oauthCodeTokenRequest, oauthRefreshTokenRequest, oauthTokenRequest, oauthTokenResponse, redirectUri, codeChallengeMethod, oauthAuthorizeQuery, dynamicClientRegistrationRequest, MCP_DCR_MAX_REDIRECT_URIS, dynamicClientRegistrationResponse, authorizationServerMetadata, protectedResourceMetadata, } from './oauth.js';
53
- export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES } from './routes.js';
55
+ export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES, developerSignInRoutes } from './routes.js';
package/dist/jobs.d.ts CHANGED
@@ -241,7 +241,6 @@ export declare const jobActor: z.ZodObject<{
241
241
  }>;
242
242
  id: z.ZodUUID;
243
243
  label: z.ZodString;
244
- name: z.ZodNullable<z.ZodString>;
245
244
  }, z.core.$strip>;
246
245
  export type JobActor = z.infer<typeof jobActor>;
247
246
  export declare const jobRunKind: z.ZodEnum<{
@@ -290,7 +289,6 @@ export declare const jobRun: z.ZodObject<{
290
289
  }>;
291
290
  id: z.ZodUUID;
292
291
  label: z.ZodString;
293
- name: z.ZodNullable<z.ZodString>;
294
292
  }, z.core.$strip>;
295
293
  seq: z.ZodNumber;
296
294
  progress: z.ZodNullable<z.ZodNumber>;
@@ -353,7 +351,6 @@ export declare const jobRunListResponse: z.ZodObject<{
353
351
  }>;
354
352
  id: z.ZodUUID;
355
353
  label: z.ZodString;
356
- name: z.ZodNullable<z.ZodString>;
357
354
  }, z.core.$strip>;
358
355
  seq: z.ZodNumber;
359
356
  progress: z.ZodNullable<z.ZodNumber>;
package/dist/jobs.js CHANGED
@@ -226,22 +226,6 @@ export const jobActor = z.object({
226
226
  label: z.string().min(1).max(200).meta({
227
227
  description: 'A display name taken at invoke time — the email for a Fleetless user or an app user, the key\'s own name for a server key. Storing it rather than joining is the point: renaming a key afterwards does not rewrite history.',
228
228
  }),
229
- /**
230
- * The person's display name, snapshotted beside `label` for the same
231
- * reason. **Required and nullable**, so a consumer never has to tell
232
- * "absent" from "null": every run a 5.3.0 cloud answers carries it, and
233
- * `null` means there is no name to show — a server key, a person without
234
- * one, or a run recorded before the field existed.
235
- *
236
- * `jobActor` stays a plain object, not `.strict()`: a consumer still on an
237
- * older contracts version then parses a newer cloud's answer by stripping
238
- * the key instead of refusing the whole run.
239
- */
240
- name: z.string().min(1).max(200).nullable().meta({
241
- description: 'The person\'s display name when the job started: the Fleetless user\'s `display_name` for a developer, the app user\'s ' +
242
- '`display_name` for an app user. `null` for a server key, when the person had no name set, and for runs recorded before ' +
243
- 'contracts 5.3.0. Show `label` when it is null.',
244
- }),
245
229
  });
246
230
  export const jobRunKind = z.enum(['action', 'service']);
247
231
  /**
@@ -559,9 +559,9 @@ export declare const cloudConfig: z.ZodObject<{
559
559
  }, z.core.$strict>>>;
560
560
  low_bandwidth: z.ZodOptional<z.ZodObject<{
561
561
  mode: z.ZodOptional<z.ZodEnum<{
562
+ off: "off";
562
563
  auto: "auto";
563
564
  on: "on";
564
- off: "off";
565
565
  }>>;
566
566
  enter_lag_ms: z.ZodOptional<z.ZodNumber>;
567
567
  enter_after_s: z.ZodOptional<z.ZodNumber>;
@@ -41,6 +41,7 @@ export declare const authOk: z.ZodObject<{
41
41
  app_id: z.ZodNullable<z.ZodUUID>;
42
42
  role_id: z.ZodNullable<z.ZodUUID>;
43
43
  email: z.ZodNullable<z.ZodEmail>;
44
+ two_factor_enabled: z.ZodNullable<z.ZodBoolean>;
44
45
  }, z.core.$strip>;
45
46
  }, z.core.$strip>;
46
47
  export type AuthOk = z.infer<typeof authOk>;
package/dist/rest.d.ts CHANGED
@@ -444,9 +444,9 @@ export declare const configDraftResponse: z.ZodObject<{
444
444
  }, z.core.$strict>>>;
445
445
  low_bandwidth: z.ZodOptional<z.ZodObject<{
446
446
  mode: z.ZodOptional<z.ZodEnum<{
447
+ off: "off";
447
448
  auto: "auto";
448
449
  on: "on";
449
- off: "off";
450
450
  }>>;
451
451
  enter_lag_ms: z.ZodOptional<z.ZodNumber>;
452
452
  enter_after_s: z.ZodOptional<z.ZodNumber>;
@@ -698,9 +698,9 @@ export declare const configVersionResponse: z.ZodObject<{
698
698
  }, z.core.$strict>>>;
699
699
  low_bandwidth: z.ZodOptional<z.ZodObject<{
700
700
  mode: z.ZodOptional<z.ZodEnum<{
701
+ off: "off";
701
702
  auto: "auto";
702
703
  on: "on";
703
- off: "off";
704
704
  }>>;
705
705
  enter_lag_ms: z.ZodOptional<z.ZodNumber>;
706
706
  enter_after_s: z.ZodOptional<z.ZodNumber>;