@fleetless/contracts 5.2.0 → 6.0.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/CHANGELOG.md +99 -0
- package/artifacts/openapi.json +1975 -415
- package/artifacts/routes.json +1697 -251
- package/artifacts/schema/accept-team-invite-request.schema.json +13 -7
- package/artifacts/schema/app-auth-config.schema.json +108 -4
- package/artifacts/schema/app-hosted-pages.schema.json +33 -0
- package/artifacts/schema/app-invitation.schema.json +2 -2
- package/artifacts/schema/app-mail-template-list-response.schema.json +4 -3
- package/artifacts/schema/app-mail-template.schema.json +3 -2
- package/artifacts/schema/app-sign-in-methods.schema.json +19 -0
- package/artifacts/schema/app-user-list-response.schema.json +36 -0
- package/artifacts/schema/app-user.schema.json +36 -0
- package/artifacts/schema/auth-me-response.schema.json +27 -0
- package/artifacts/schema/auth-ok.schema.json +13 -1
- package/artifacts/schema/client-accept-invitation-request.schema.json +3 -4
- package/artifacts/schema/client-identity.schema.json +13 -1
- package/artifacts/schema/client-login-code-request.schema.json +24 -0
- package/artifacts/schema/client-login-code-verify-request.schema.json +30 -0
- package/artifacts/schema/client-provider-list-response.schema.json +22 -2
- package/artifacts/schema/client-register-request.schema.json +3 -4
- package/artifacts/schema/client-sign-in-result.schema.json +55 -0
- package/artifacts/schema/client-two-factor-disable-request.schema.json +15 -0
- package/artifacts/schema/client-two-factor-setup-confirm-request.schema.json +20 -0
- package/artifacts/schema/client-two-factor-setup-confirm-response.schema.json +49 -0
- package/artifacts/schema/client-two-factor-setup-request.schema.json +12 -0
- package/artifacts/schema/client-two-factor-verify-request.schema.json +25 -0
- package/artifacts/schema/create-app-invitation-request.schema.json +1 -1
- package/artifacts/schema/create-passkey-request.schema.json +25 -0
- package/artifacts/schema/create-passkey-response.schema.json +84 -0
- package/artifacts/schema/developer-passkey.schema.json +56 -0
- package/artifacts/schema/developer-two-factor.schema.json +105 -0
- package/artifacts/schema/fleetless-user-list-response.schema.json +22 -0
- package/artifacts/schema/fleetless-user.schema.json +22 -0
- package/artifacts/schema/invalid-code-details.schema.json +16 -0
- package/artifacts/schema/org.schema.json +5 -0
- package/artifacts/schema/patch-org-request.schema.json +5 -3
- package/artifacts/schema/patch-org-response.schema.json +5 -0
- package/artifacts/schema/put-app-auth-look-request.schema.json +22 -0
- package/artifacts/schema/put-app-auth-mcp-request.schema.json +1 -14
- package/artifacts/schema/put-app-auth-sign-in-request.schema.json +39 -0
- package/artifacts/schema/put-app-auth-urls-request.schema.json +31 -4
- package/artifacts/schema/recovery-codes-response.schema.json +20 -0
- package/artifacts/schema/rename-passkey-request.schema.json +16 -0
- package/artifacts/schema/totp-confirm-request.schema.json +15 -0
- package/artifacts/schema/totp-confirm-response.schema.json +27 -0
- package/artifacts/schema/two-factor-challenge.schema.json +24 -0
- package/artifacts/schema/two-factor-setup-response.schema.json +21 -0
- package/artifacts/schema/webauthn-options-response.schema.json +18 -0
- package/dist/app-users.d.ts +154 -34
- package/dist/app-users.js +177 -45
- package/dist/client-auth.d.ts +133 -24
- package/dist/client-auth.js +139 -28
- package/dist/config.d.ts +2 -2
- package/dist/errors.d.ts +10 -1
- package/dist/errors.js +34 -5
- package/dist/identity.d.ts +172 -123
- package/dist/identity.js +189 -101
- package/dist/index.d.ts +9 -9
- package/dist/index.js +11 -7
- package/dist/protocol.d.ts +1 -1
- package/dist/realtime.d.ts +1 -0
- package/dist/rest.d.ts +2 -2
- package/dist/rest.js +17 -28
- package/dist/routes.d.ts +19 -0
- package/dist/routes.js +497 -183
- package/package.json +1 -1
- package/artifacts/schema/developer-login-request.schema.json +0 -19
- package/artifacts/schema/password-reset-confirm.schema.json +0 -19
- package/artifacts/schema/password-reset-request.schema.json +0 -14
- package/artifacts/schema/sign-up-request.schema.json +0 -26
- package/artifacts/schema/sign-up-response.schema.json +0 -127
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`,
|
|
11
|
-
*
|
|
12
|
-
* the
|
|
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
|
|
28
|
-
*
|
|
29
|
-
*
|
|
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.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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
|
-
*
|
|
44
|
-
*
|
|
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
|
|
85
|
-
*
|
|
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.
|
|
97
|
-
*
|
|
98
|
-
* IdP-lockout class
|
|
99
|
-
*
|
|
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
|
-
*
|
|
149
|
-
*
|
|
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
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
*
|
|
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
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
*
|
|
@@ -304,14 +319,18 @@ export const pendingTeamInviteListResponse = z.object({
|
|
|
304
319
|
description: 'Pending invitations only. An accepted invitation is history, not something to revoke.',
|
|
305
320
|
}),
|
|
306
321
|
});
|
|
307
|
-
/**
|
|
322
|
+
/**
|
|
323
|
+
* Accepting it: the token proves the invitation, and the mailed link proves
|
|
324
|
+
* the address, so accepting needs no code and takes **no password** — the
|
|
325
|
+
* new member signs in by emailed code from then on.
|
|
326
|
+
*/
|
|
308
327
|
export const acceptTeamInviteRequest = z
|
|
309
328
|
.object({
|
|
310
329
|
token: z.string().min(1).meta({
|
|
311
330
|
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
331
|
}),
|
|
313
|
-
|
|
314
|
-
description: '
|
|
332
|
+
display_name: z.string().min(1).max(USER_DISPLAY_NAME_MAX).nullable().optional().meta({
|
|
333
|
+
description: 'An optional name, overriding whatever the invitation pre-filled. Absent keeps it.',
|
|
315
334
|
}),
|
|
316
335
|
})
|
|
317
336
|
.strict();
|
|
@@ -366,17 +385,14 @@ export const tierRequiredDetails = z.object({
|
|
|
366
385
|
actual: orgAdminTier,
|
|
367
386
|
});
|
|
368
387
|
/**
|
|
369
|
-
*
|
|
388
|
+
* An app user changing their own password while signed in
|
|
389
|
+
* (`POST /api/client/password/change`). Fleetless users have no password.
|
|
370
390
|
*
|
|
371
391
|
* `current_password` is required even though the session already proves
|
|
372
392
|
* identity: it is what makes a stolen *session* insufficient to take the
|
|
373
393
|
* *account*. Every other session is revoked on success; the one that made the
|
|
374
394
|
* change survives, because logging someone out of the tab they just used is
|
|
375
395
|
* 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
396
|
*/
|
|
381
397
|
export const passwordChangeRequest = z.object({
|
|
382
398
|
current_password: z.string().min(1).meta({
|
|
@@ -386,39 +402,6 @@ export const passwordChangeRequest = z.object({
|
|
|
386
402
|
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
403
|
}),
|
|
388
404
|
});
|
|
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
405
|
/**
|
|
423
406
|
* An IdP issuer URL — **an attacker-supplied string that decides where the
|
|
424
407
|
* *server* connects.**
|
|
@@ -471,8 +454,8 @@ export const idpIssuer = z
|
|
|
471
454
|
* here.** `oidcCallbackErrorCode` and `oidcCallbackError` described the page
|
|
472
455
|
* `GET /mcp/oauth/idp-callback` rendered when a group's identity provider sent
|
|
473
456
|
* a browser back — `jit_disabled` and `email_collision` name provisioning steps
|
|
474
|
-
* only a group provider had. Fleetless users
|
|
475
|
-
* group providers, so the flow that produced these codes cannot start; the
|
|
457
|
+
* only a group provider had. Fleetless users sign in by emailed code or
|
|
458
|
+
* passkey, with no group providers, so the flow that produced these codes cannot start; the
|
|
476
459
|
* route is gone from this manifest and from the cloud.
|
|
477
460
|
*
|
|
478
461
|
* The per-app OIDC vocabulary is `clientOidcErrorCode` in `client-auth.ts`: a
|
|
@@ -492,7 +475,112 @@ export const idpIssuer = z
|
|
|
492
475
|
* field required on the shape itself.
|
|
493
476
|
*/
|
|
494
477
|
export const authMeResponse = z.object({ org, user: fleetlessUser });
|
|
495
|
-
/**
|
|
496
|
-
|
|
478
|
+
/**
|
|
479
|
+
* `PATCH /api/org` — rename the org, require two-factor for its members, or
|
|
480
|
+
* both. Owner only. At least one field: an empty patch is a refusal rather
|
|
481
|
+
* than a write that changed nothing.
|
|
482
|
+
*/
|
|
483
|
+
export const patchOrgRequest = z
|
|
484
|
+
.object({
|
|
485
|
+
name: z.string().min(1).max(120).optional().meta({
|
|
486
|
+
description: 'The organisation\'s new display name. Absent leaves it alone.',
|
|
487
|
+
}),
|
|
488
|
+
require_two_factor: z.boolean().optional().meta({
|
|
489
|
+
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.',
|
|
490
|
+
}),
|
|
491
|
+
})
|
|
492
|
+
.strict()
|
|
493
|
+
.refine((b) => b.name !== undefined || b.require_two_factor !== undefined, { message: 'Send name, require_two_factor, or both.' });
|
|
497
494
|
/** `PATCH /api/auth/me` — the caller updates their own display name (null clears it). */
|
|
498
495
|
export const patchAuthMeRequest = z.object({ display_name: z.string().min(1).max(USER_DISPLAY_NAME_MAX).nullable() }).strict();
|
|
496
|
+
/* ----------------------------------------- a developer's second factors --
|
|
497
|
+
* Settings › Profile › Security in the console. Several passkeys, at most one
|
|
498
|
+
* authenticator app, and ten recovery codes issued with the first factor.
|
|
499
|
+
* Passkeys are for Fleetless users only; app users have the authenticator.
|
|
500
|
+
*/
|
|
501
|
+
/**
|
|
502
|
+
* **A WebAuthn JSON document, opaque here.** The `PublicKeyCredential*JSON`
|
|
503
|
+
* shapes of the WebAuthn Level 3 specification — creation and request options
|
|
504
|
+
* going out, the browser's credential coming back. The browser API and the
|
|
505
|
+
* server library define them; a second, hand-written copy here would be one
|
|
506
|
+
* that drifts.
|
|
507
|
+
*/
|
|
508
|
+
export const webauthnJson = z.record(z.string(), z.unknown());
|
|
509
|
+
/**
|
|
510
|
+
* **Options for a WebAuthn ceremony**, to hand to the browser as they are.
|
|
511
|
+
* The relying party is `fleetless.dev`, so the auth portal and the console
|
|
512
|
+
* both accept the same passkey; user verification is required.
|
|
513
|
+
*/
|
|
514
|
+
export const webauthnOptionsResponse = z.object({
|
|
515
|
+
options: webauthnJson.meta({
|
|
516
|
+
description: 'The `PublicKeyCredentialCreationOptionsJSON` or `PublicKeyCredentialRequestOptionsJSON` to pass to the browser. Its challenge is single-use and short-lived.',
|
|
517
|
+
}),
|
|
518
|
+
});
|
|
519
|
+
/** **One registered passkey**, as Settings › Profile lists it. No key material travels here. */
|
|
520
|
+
export const developerPasskey = z.object({
|
|
521
|
+
id: z.uuid().meta({ description: 'The passkey in the API, as renamed and removed through `/api/auth/passkeys/:id`.' }),
|
|
522
|
+
name: z.string().min(1).max(80).meta({ description: 'What the person called it, such as the device it lives on.' }),
|
|
523
|
+
created_at: z.iso.datetime().meta({ description: 'When it was registered.' }),
|
|
524
|
+
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.' }),
|
|
525
|
+
synced: z.boolean().nullable().meta({
|
|
526
|
+
description: 'Whether the authenticator reported the passkey as syncable across the person\'s devices (the backup-eligible flag), or `null` when it said nothing.',
|
|
527
|
+
}),
|
|
528
|
+
});
|
|
529
|
+
/** **`GET /api/auth/two-factor`** — the caller's own second factors, in full. */
|
|
530
|
+
export const developerTwoFactor = z.object({
|
|
531
|
+
passkeys: z.array(developerPasskey).meta({ description: 'Every passkey the caller has registered, oldest first. Empty when none.' }),
|
|
532
|
+
authenticator: z
|
|
533
|
+
.object({ created_at: z.iso.datetime().meta({ description: 'When the authenticator was confirmed.' }) })
|
|
534
|
+
.nullable()
|
|
535
|
+
.meta({ description: 'The confirmed authenticator app, or `null` when there is none. At most one.' }),
|
|
536
|
+
recovery_codes_left: z.number().int().min(0).max(10).meta({
|
|
537
|
+
description: 'How many of the ten recovery codes are unspent. `0` while the caller has no second factor.',
|
|
538
|
+
}),
|
|
539
|
+
required_by_org: z.boolean().meta({
|
|
540
|
+
description: 'Whether the organisation requires a second factor. While it does, the last one cannot be removed.',
|
|
541
|
+
}),
|
|
542
|
+
});
|
|
543
|
+
/** **Registering a passkey**: the name, and the browser's answer to the creation options. */
|
|
544
|
+
export const createPasskeyRequest = z
|
|
545
|
+
.object({
|
|
546
|
+
name: z.string().min(1).max(80).meta({ description: 'What to call the passkey, such as the device it lives on.' }),
|
|
547
|
+
credential: webauthnJson.meta({ description: 'The browser\'s `RegistrationResponseJSON` for the options `POST /api/auth/passkeys/options` answered.' }),
|
|
548
|
+
})
|
|
549
|
+
.strict();
|
|
550
|
+
/**
|
|
551
|
+
* **The registered passkey**, and the ten recovery codes when it is the
|
|
552
|
+
* account's first second factor — `null` otherwise, since the existing codes
|
|
553
|
+
* stay valid.
|
|
554
|
+
*/
|
|
555
|
+
export const createPasskeyResponse = z.object({
|
|
556
|
+
passkey: developerPasskey.meta({ description: 'The passkey as it is now stored.' }),
|
|
557
|
+
recovery_codes: recoveryCodesList.nullable().meta({
|
|
558
|
+
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.',
|
|
559
|
+
}),
|
|
560
|
+
});
|
|
561
|
+
/** **Renaming a passkey.** The name is the only thing about one that can change. */
|
|
562
|
+
export const renamePasskeyRequest = z
|
|
563
|
+
.object({
|
|
564
|
+
name: z.string().min(1).max(80).meta({ description: 'The new name.' }),
|
|
565
|
+
})
|
|
566
|
+
.strict();
|
|
567
|
+
/** **Confirming a new authenticator** with a code it shows now. */
|
|
568
|
+
export const totpConfirmRequest = z
|
|
569
|
+
.object({
|
|
570
|
+
code: totpCode.meta({ description: 'A code the new authenticator shows now. It proves the secret was copied correctly before anything depends on it.' }),
|
|
571
|
+
})
|
|
572
|
+
.strict();
|
|
573
|
+
/**
|
|
574
|
+
* **The confirmed authenticator.** Ten recovery codes when it is the
|
|
575
|
+
* account's first second factor; `null` when it replaces an authenticator or
|
|
576
|
+
* joins passkeys, whose codes stay valid.
|
|
577
|
+
*/
|
|
578
|
+
export const totpConfirmResponse = z.object({
|
|
579
|
+
recovery_codes: recoveryCodesList.nullable().meta({
|
|
580
|
+
description: 'The ten recovery codes, shown once, when this is the account\'s first second factor; `null` otherwise.',
|
|
581
|
+
}),
|
|
582
|
+
});
|
|
583
|
+
/** **A fresh set of ten recovery codes**, shown once. The previous set stops working. */
|
|
584
|
+
export const recoveryCodesResponse = z.object({
|
|
585
|
+
recovery_codes: recoveryCodesList.meta({ description: 'The ten new recovery codes, lowercase, shown once. Every earlier code is void.' }),
|
|
586
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -29,25 +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,
|
|
33
|
-
export type { Org, PatchOrgResponse, SessionTokens, RefreshRequest,
|
|
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
34
|
export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, } from './apps.js';
|
|
35
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, } 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, } from './client-auth.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';
|
|
38
38
|
export { clientRobotListItem, clientRobotListResponse } from './client-robots.js';
|
|
39
39
|
export type { ClientRobotListItem, ClientRobotListResponse } from './client-robots.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, putAppAuthRegistrationRequest, putAppAuthUrlsRequest, putAppAuthMcpRequest, 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, 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';
|
|
42
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';
|
|
43
43
|
export type { AssetKind, Asset, UrdfCompleteness, AssetListResponse, AssetsClearResponse, MissingAssetQuery, AssetSyncRequest, AssetSyncResponse, AssetSyncState, AssetSyncStatus, AssetFailure, AssetFailureKind, AssetStoreRefusedDetails, AssetSyncBusyDetails, } from './assets.js';
|
|
44
44
|
export { auditActor, auditEvent, auditQuery, auditListResponse, AUDIT_CSV_COLUMNS, AUDIT_RETENTION_DAYS } from './audit.js';
|
|
45
45
|
export type { AuditActor, AuditEvent, AuditQuery, AuditListResponse } from './audit.js';
|
|
46
46
|
export { alertRowCondition, alertSeverity, alertState, datapointAlertRow, alertListResponse, orgFiringAlertsResponse, orgAlertsQuery, datapointDisplay, putDatapointDisplayRequest, } from './alerts.js';
|
|
47
47
|
export type { AlertRowCondition, AlertSeverity, AlertState, DatapointAlertRow, AlertListResponse, OrgFiringAlertsResponse, OrgAlertsQuery, DatapointDisplay, PutDatapointDisplayRequest, } from './alerts.js';
|
|
48
|
-
export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, ERROR_CODES } from './errors.js';
|
|
49
|
-
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';
|
|
50
50
|
export { oauthErrorCode, oauthError, oauthRedirectResponse, oauthCodeTokenRequest, oauthRefreshTokenRequest, oauthTokenRequest, oauthTokenResponse, redirectUri, codeChallengeMethod, oauthAuthorizeQuery, dynamicClientRegistrationRequest, MCP_DCR_MAX_REDIRECT_URIS, dynamicClientRegistrationResponse, authorizationServerMetadata, protectedResourceMetadata, } from './oauth.js';
|
|
51
51
|
export type { OauthErrorCode, OauthError, OauthRedirectResponse, OauthCodeTokenRequest, OauthRefreshTokenRequest, OauthTokenRequest, OauthTokenResponse, RedirectUri, OauthAuthorizeQuery, DynamicClientRegistrationRequest, DynamicClientRegistrationResponse, AuthorizationServerMetadata, ProtectedResourceMetadata, } from './oauth.js';
|
|
52
|
-
export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES } from './routes.js';
|
|
52
|
+
export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES, developerSignInRoutes } from './routes.js';
|
|
53
53
|
export type { RouteEntry, RouteParam, RouteAudience, RouteAuth, RouteSection, RouteMethod, RouteTransport, } from './routes.js';
|
package/dist/index.js
CHANGED
|
@@ -29,23 +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,
|
|
32
|
+
export { password, org, patchOrgResponse, sessionTokens, refreshRequest,
|
|
33
33
|
// 2026-09-04 — the public site (closed beta).
|
|
34
|
-
waitlistRequest,
|
|
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,
|
|
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
45
|
export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, } from './apps.js';
|
|
42
|
-
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';
|
|
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';
|
|
43
47
|
export { clientRobotListItem, clientRobotListResponse } from './client-robots.js';
|
|
44
48
|
// The per-app identity space.
|
|
45
|
-
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';
|
|
46
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';
|
|
47
51
|
export { auditActor, auditEvent, auditQuery, auditListResponse, AUDIT_CSV_COLUMNS, AUDIT_RETENTION_DAYS } from './audit.js';
|
|
48
52
|
export { alertRowCondition, alertSeverity, alertState, datapointAlertRow, alertListResponse, orgFiringAlertsResponse, orgAlertsQuery, datapointDisplay, putDatapointDisplayRequest, } from './alerts.js';
|
|
49
|
-
export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, ERROR_CODES } from './errors.js';
|
|
53
|
+
export { apiError, parameterViolation, parameterInvalidDetails, cancelRejectedDetails, invalidCodeDetails, ERROR_CODES } from './errors.js';
|
|
50
54
|
export { oauthErrorCode, oauthError, oauthRedirectResponse, oauthCodeTokenRequest, oauthRefreshTokenRequest, oauthTokenRequest, oauthTokenResponse, redirectUri, codeChallengeMethod, oauthAuthorizeQuery, dynamicClientRegistrationRequest, MCP_DCR_MAX_REDIRECT_URIS, dynamicClientRegistrationResponse, authorizationServerMetadata, protectedResourceMetadata, } from './oauth.js';
|
|
51
|
-
export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES } from './routes.js';
|
|
55
|
+
export { ROUTES, ROUTE_SECTIONS, IN_HANDLER_ROUTES, developerSignInRoutes } from './routes.js';
|
package/dist/protocol.d.ts
CHANGED
|
@@ -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>;
|
package/dist/realtime.d.ts
CHANGED
|
@@ -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>;
|
package/dist/rest.js
CHANGED
|
@@ -567,23 +567,17 @@ export const jobResponse = z.object({
|
|
|
567
567
|
* There are no compatibility aliases, because an alias here is how a deleted
|
|
568
568
|
* model survives in production while the contract says otherwise.
|
|
569
569
|
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
570
|
+
* **Every route that mails a code or a link answers the same for a known and
|
|
571
|
+
* an unknown address** — the portal's identify step, `POST
|
|
572
|
+
* /api/client/login/code`, `POST /api/client/password/reset`. Saying nothing
|
|
573
|
+
* about whether an account exists is not a preference there but the entire
|
|
574
|
+
* point: any status, body or timing difference between the two cases is an
|
|
574
575
|
* account-enumeration oracle. Note *timing* — a route that only sends mail for
|
|
575
|
-
* a real address must not become measurably faster for an unknown one.
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
* console user each need a way to change and to reset a password.
|
|
581
|
-
* `passwordChangeRequest` is shared because the operation is identical; the
|
|
582
|
-
* **prefix** is what says
|
|
583
|
-
* which session is being spent, exactly as it does for `login`. The two *reset*
|
|
584
|
-
* requests are separate shapes rather than one, because the surfaces identify a
|
|
585
|
-
* person differently: a Fleetless user by a globally unique address, an app
|
|
586
|
-
* user by app **and** address.
|
|
576
|
+
* a real address must not become measurably faster for an unknown one.
|
|
577
|
+
*
|
|
578
|
+
* **Only app users hold a password.** Fleetless users sign in by emailed code
|
|
579
|
+
* or passkey, so the password change and reset routes are the app user's
|
|
580
|
+
* alone, under `/api/client`.
|
|
587
581
|
*
|
|
588
582
|
* **A password change answers with fresh `sessionTokens`, not `204`.** The
|
|
589
583
|
* promise is that the session which made the change survives while every other
|
|
@@ -611,20 +605,15 @@ export const jobResponse = z.object({
|
|
|
611
605
|
*
|
|
612
606
|
* | purpose | URL |
|
|
613
607
|
* |---|---|
|
|
614
|
-
* | password reset, Fleetless user | `{portal}/reset-password/{token}` |
|
|
615
608
|
* | team invitation | `{portal}/accept-invite/{token}` |
|
|
616
609
|
*
|
|
617
|
-
* **An app user's links
|
|
618
|
-
*
|
|
619
|
-
*
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
623
|
-
*
|
|
624
|
-
*
|
|
625
|
-
* The paragraph this replaces said an app-user reset *"is a feature to design,
|
|
626
|
-
* not a row to restore"*. It was designed; the answer was that the row belongs
|
|
627
|
-
* to the developer and not to this table.
|
|
610
|
+
* **An app user's links point into the developer's own app** where it has
|
|
611
|
+
* configured one — the template in `appAuthConfig.invite_url`, `verify_url` or
|
|
612
|
+
* `reset_url`, with the token substituted for `{token}`. That is why those
|
|
613
|
+
* fields are validated as templates rather than as URLs. Where the app has
|
|
614
|
+
* configured none, the link points at the Fleetless-hosted page the cloud
|
|
615
|
+
* reports in `appAuthConfig.hosted_pages` (`{portal}/app/<identifier>/…`), so
|
|
616
|
+
* no mail is refused for a missing URL.
|
|
628
617
|
*
|
|
629
618
|
* The strings themselves live server-side, read by the
|
|
630
619
|
* route that serves each page AND by the builder that mails it — one constant,
|