@fleetless/contracts 6.0.0-next.1 → 6.0.0-next.3
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 +53 -3
- package/artifacts/openapi.json +306 -29
- package/artifacts/routes.json +123 -22
- package/artifacts/schema/app-invitation.schema.json +4 -11
- package/artifacts/schema/audit-query.schema.json +6 -0
- package/artifacts/schema/feedback-request.schema.json +34 -0
- package/artifacts/schema/feedback-response.schema.json +27 -0
- package/artifacts/schema/job-actor.schema.json +15 -1
- package/artifacts/schema/job-run-list-response.schema.json +15 -1
- package/artifacts/schema/job-run.schema.json +15 -1
- package/artifacts/schema/role-delete-query.schema.json +13 -0
- package/artifacts/schema/role-in-use-details.schema.json +28 -0
- package/artifacts/schema/role-list-response.schema.json +1 -1
- package/artifacts/schema/role-rename-request.schema.json +16 -0
- package/artifacts/schema/role.schema.json +1 -1
- package/dist/app-users.d.ts +3 -4
- package/dist/app-users.js +4 -5
- package/dist/apps.d.ts +38 -2
- package/dist/apps.js +46 -3
- package/dist/audit.d.ts +1 -0
- package/dist/audit.js +13 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +36 -8
- package/dist/feedback.d.ts +42 -0
- package/dist/feedback.js +35 -0
- package/dist/identity.d.ts +3 -5
- package/dist/identity.js +3 -5
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/jobs.d.ts +3 -0
- package/dist/jobs.js +16 -0
- package/dist/routes.d.ts +10 -3
- package/dist/routes.js +79 -23
- package/package.json +1 -1
package/dist/apps.d.ts
CHANGED
|
@@ -151,8 +151,9 @@ export declare const createServerKeyResponse: z.ZodObject<{
|
|
|
151
151
|
export type CreateServerKeyResponse = z.infer<typeof createServerKeyResponse>;
|
|
152
152
|
/**
|
|
153
153
|
* Every app starts with `observe` and `operate`; custom roles are allowed
|
|
154
|
-
* too. `builtin` marks the two starting roles — editable
|
|
155
|
-
* the flag only tells the console where they came
|
|
154
|
+
* too. `builtin` marks the two starting roles — editable, renamable and
|
|
155
|
+
* deletable like any other; the flag only tells the console where they came
|
|
156
|
+
* from.
|
|
156
157
|
*/
|
|
157
158
|
export declare const role: z.ZodObject<{
|
|
158
159
|
id: z.ZodUUID;
|
|
@@ -171,6 +172,41 @@ export declare const roleListResponse: z.ZodObject<{
|
|
|
171
172
|
}, z.core.$strip>>;
|
|
172
173
|
}, z.core.$strip>;
|
|
173
174
|
export type RoleListResponse = z.infer<typeof roleListResponse>;
|
|
175
|
+
/**
|
|
176
|
+
* The body of `PATCH /api/apps/:id/roles/:roleId`: the role's new name.
|
|
177
|
+
*
|
|
178
|
+
* The same bounds as `role.name`, trimmed. Names are unique per app, compared
|
|
179
|
+
* exactly as stored after trimming; a clash answers `409 role_name_taken`.
|
|
180
|
+
*/
|
|
181
|
+
export declare const roleRenameRequest: z.ZodObject<{
|
|
182
|
+
name: z.ZodString;
|
|
183
|
+
}, z.core.$strict>;
|
|
184
|
+
export type RoleRenameRequest = z.infer<typeof roleRenameRequest>;
|
|
185
|
+
/**
|
|
186
|
+
* The query of `DELETE /api/apps/:id/roles/:roleId`.
|
|
187
|
+
*
|
|
188
|
+
* `move_to` is what makes a held role deletable: every app user and pending
|
|
189
|
+
* invitation holding the role moves to it, and so does the app's default when
|
|
190
|
+
* it pointed at the role, in the same transaction as the delete. Without it a
|
|
191
|
+
* held role answers `409 role_in_use` with `roleInUseDetails`, so a client
|
|
192
|
+
* can ask where they should go instead of guessing.
|
|
193
|
+
*/
|
|
194
|
+
export declare const roleDeleteQuery: z.ZodObject<{
|
|
195
|
+
move_to: z.ZodOptional<z.ZodUUID>;
|
|
196
|
+
}, z.core.$strict>;
|
|
197
|
+
export type RoleDeleteQuery = z.infer<typeof roleDeleteQuery>;
|
|
198
|
+
/**
|
|
199
|
+
* `details` of `409 role_in_use`: what still holds the role.
|
|
200
|
+
*
|
|
201
|
+
* All three are reported, zeros included, so a client renders one sentence
|
|
202
|
+
* from one shape rather than inferring a missing key.
|
|
203
|
+
*/
|
|
204
|
+
export declare const roleInUseDetails: z.ZodObject<{
|
|
205
|
+
users: z.ZodNumber;
|
|
206
|
+
invitations: z.ZodNumber;
|
|
207
|
+
is_default: z.ZodBoolean;
|
|
208
|
+
}, z.core.$strict>;
|
|
209
|
+
export type RoleInUseDetails = z.infer<typeof roleInUseDetails>;
|
|
174
210
|
/**
|
|
175
211
|
* The rights matrix of one role: which slugs of which robot it may use, plus
|
|
176
212
|
* the capabilities roles also govern. `capabilities`' own doc comment
|
package/dist/apps.js
CHANGED
|
@@ -206,8 +206,9 @@ export const createServerKeyResponse = z.object({
|
|
|
206
206
|
});
|
|
207
207
|
/**
|
|
208
208
|
* Every app starts with `observe` and `operate`; custom roles are allowed
|
|
209
|
-
* too. `builtin` marks the two starting roles — editable
|
|
210
|
-
* the flag only tells the console where they came
|
|
209
|
+
* too. `builtin` marks the two starting roles — editable, renamable and
|
|
210
|
+
* deletable like any other; the flag only tells the console where they came
|
|
211
|
+
* from.
|
|
211
212
|
*/
|
|
212
213
|
export const role = z.object({
|
|
213
214
|
id: z.uuid().meta({
|
|
@@ -220,7 +221,7 @@ export const role = z.object({
|
|
|
220
221
|
description: 'The role\'s name, shown wherever a user\'s access is chosen. The two roles every app starts with are named `observe` and `operate`.',
|
|
221
222
|
}),
|
|
222
223
|
builtin: z.boolean().meta({
|
|
223
|
-
description: '`true` for the two roles every app starts with. Their **rights may be re-scoped** exactly like a custom role\'s, through `PUT /api/apps/:id/roles/:roleId/permissions` — the flag exists so the console can explain where they came from, not to protect them.
|
|
224
|
+
description: '`true` for the two roles every app starts with. Their **rights may be re-scoped** exactly like a custom role\'s, through `PUT /api/apps/:id/roles/:roleId/permissions` — the flag exists so the console can explain where they came from, not to protect them. Built-in roles can be renamed and deleted like any other; the flag only records that the cloud seeded them.',
|
|
224
225
|
}),
|
|
225
226
|
});
|
|
226
227
|
/** What `GET /api/apps/:id/roles` answers: the app's roles, builtin and custom alike. */
|
|
@@ -229,6 +230,48 @@ export const roleListResponse = z.object({
|
|
|
229
230
|
description: 'The app\'s roles, built-in and custom alike, ordered by `created_at` and then by `name`. The tie-break is not cosmetic — the two built-in roles are inserted in one statement and share a creation time to the microsecond, so never read a role by position.',
|
|
230
231
|
}),
|
|
231
232
|
});
|
|
233
|
+
/**
|
|
234
|
+
* The body of `PATCH /api/apps/:id/roles/:roleId`: the role's new name.
|
|
235
|
+
*
|
|
236
|
+
* The same bounds as `role.name`, trimmed. Names are unique per app, compared
|
|
237
|
+
* exactly as stored after trimming; a clash answers `409 role_name_taken`.
|
|
238
|
+
*/
|
|
239
|
+
export const roleRenameRequest = z.object({
|
|
240
|
+
name: z.string().trim().min(1).max(60).meta({
|
|
241
|
+
description: 'The new name, trimmed, 1 to 60 characters. Unique per app: another role of this app with the same name answers `409 role_name_taken`. The role\'s users keep it under its new name.',
|
|
242
|
+
}),
|
|
243
|
+
}).strict();
|
|
244
|
+
/**
|
|
245
|
+
* The query of `DELETE /api/apps/:id/roles/:roleId`.
|
|
246
|
+
*
|
|
247
|
+
* `move_to` is what makes a held role deletable: every app user and pending
|
|
248
|
+
* invitation holding the role moves to it, and so does the app's default when
|
|
249
|
+
* it pointed at the role, in the same transaction as the delete. Without it a
|
|
250
|
+
* held role answers `409 role_in_use` with `roleInUseDetails`, so a client
|
|
251
|
+
* can ask where they should go instead of guessing.
|
|
252
|
+
*/
|
|
253
|
+
export const roleDeleteQuery = z.object({
|
|
254
|
+
move_to: z.uuid().optional().meta({
|
|
255
|
+
description: 'Another role of the same app that takes over the deleted role\'s app users, pending invitations and, when it applies, the app\'s default. The role itself or a role of another app answers `400 validation_error`.',
|
|
256
|
+
}),
|
|
257
|
+
}).strict();
|
|
258
|
+
/**
|
|
259
|
+
* `details` of `409 role_in_use`: what still holds the role.
|
|
260
|
+
*
|
|
261
|
+
* All three are reported, zeros included, so a client renders one sentence
|
|
262
|
+
* from one shape rather than inferring a missing key.
|
|
263
|
+
*/
|
|
264
|
+
export const roleInUseDetails = z.object({
|
|
265
|
+
users: z.number().int().nonnegative().meta({
|
|
266
|
+
description: 'App users whose role this is.',
|
|
267
|
+
}),
|
|
268
|
+
invitations: z.number().int().nonnegative().meta({
|
|
269
|
+
description: 'Pending invitations that would grant this role when accepted.',
|
|
270
|
+
}),
|
|
271
|
+
is_default: z.boolean().meta({
|
|
272
|
+
description: '`true` when this is the app\'s `default_role_id`; the default then moves with the users to `move_to`.',
|
|
273
|
+
}),
|
|
274
|
+
}).strict();
|
|
232
275
|
/**
|
|
233
276
|
* The rights matrix of one role: which slugs of which robot it may use, plus
|
|
234
277
|
* the capabilities roles also govern. `capabilities`' own doc comment
|
package/dist/audit.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export declare const auditQuery: z.ZodObject<{
|
|
|
72
72
|
action_prefix: z.ZodOptional<z.ZodString>;
|
|
73
73
|
actor_id: z.ZodOptional<z.ZodUUID>;
|
|
74
74
|
target_kind: z.ZodOptional<z.ZodString>;
|
|
75
|
+
target_id: z.ZodOptional<z.ZodString>;
|
|
75
76
|
from_ms: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>, z.ZodNumber>>;
|
|
76
77
|
to_ms: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>, z.ZodNumber>>;
|
|
77
78
|
}, z.core.$strict>;
|
package/dist/audit.js
CHANGED
|
@@ -155,6 +155,19 @@ export const auditQuery = z.object({
|
|
|
155
155
|
actor_id: z.uuid().optional(),
|
|
156
156
|
/** Only events about this kind of target, e.g. `robot`. */
|
|
157
157
|
target_kind: z.string().min(1).max(40).optional(),
|
|
158
|
+
/**
|
|
159
|
+
* Only events about this target — and, for a robot, also the events that
|
|
160
|
+
* name it in `details.robot_id`, so a robot's log includes what was
|
|
161
|
+
* started on it.
|
|
162
|
+
*
|
|
163
|
+
* **A string, not `z.uuid()`**, unlike `actor_id` above: `target.id` is a
|
|
164
|
+
* string in this contract and text in the cloud's table, so a uuid rule
|
|
165
|
+
* here would refuse ids the log can hold, and no value can fail a cast.
|
|
166
|
+
*/
|
|
167
|
+
target_id: z.string().min(1).max(200).optional().meta({
|
|
168
|
+
description: 'Events whose target is this id; for a robot also the events that name it in `details.robot_id` (`action.invoked`, ' +
|
|
169
|
+
'`service.called`, …), so a robot\'s events include what was started on it.',
|
|
170
|
+
}),
|
|
158
171
|
/**
|
|
159
172
|
* Absolute bounds in unix milliseconds, **half-open `[from, to)`** — the
|
|
160
173
|
* same rule the history shapes follow.
|
package/dist/errors.d.ts
CHANGED
|
@@ -77,5 +77,5 @@ export type InvalidCodeDetails = z.infer<typeof invalidCodeDetails>;
|
|
|
77
77
|
* list is the shared vocabulary, not a closed set, so a new refusal never
|
|
78
78
|
* needs a contracts release before it can be reported honestly.
|
|
79
79
|
*/
|
|
80
|
-
export declare const ERROR_CODES: readonly ["not_found", "validation_error", "bad_request", "unknown_datapoint", "invalid_token", "protocol_mismatch", "bridge_too_old", "invalid_frame", "duplicate_slug", "reserved_slug", "unknown_slug", "unknown_field_path", "unknown_type", "unknown_topic", "invalid_rate", "invalid_range", "config_conflict", "no_data", "robot_offline", "bridge_timeout", "unauthorized", "forbidden", "invalid_credentials", "token_expired", "token_revoked", "email_taken", "identifier_taken", "weak_password", "account_blocked", "busy", "parameter_invalid", "cancel_rejected", "job_lost", "job_unknown_to_bridge", "action_server_lost", "action_failed", "goal_rejected", "goal_send_failed", "result_failed", "goal_uncontrollable", "bridge_disconnected", "config_changed", "publisher_busy", "unknown_command", "not_subscribable", "camera_offline", "no_snapshot_yet", "live_unavailable", "wrong_kind", "not_recorded", "not_aggregatable", "quota_exceeded", "credential_in_use", "goal_timeout", "robot_in_use", "robot_deletion_partial", "job_queue_full", "invalid_uuid", "rate_limited", "tier_required", "token_spent", "service_timeout", "asset_missing", "dynamic_registration_disabled", "client_limit_reached", "idp_unavailable", "mcp_disabled", "tool_not_available", "capability_required", "last_owner", "target_state_conflict", "signup_closed", "draft_not_a_document", "internal_error", "not_cancellable", "unsupported_media_type", "wrong_browser", "invalid_yaml", "unstorable_yaml", "registration_closed", "domain_not_allowed", "email_unverified", "origin_not_allowed", "template_invalid", "provider_disabled", "provider_misconfigured", "invalid_redirect_uri", "interaction_expired", "invalid_code", "method_not_allowed"];
|
|
80
|
+
export declare const ERROR_CODES: readonly ["not_found", "validation_error", "bad_request", "unknown_datapoint", "invalid_token", "protocol_mismatch", "bridge_too_old", "invalid_frame", "duplicate_slug", "reserved_slug", "unknown_slug", "unknown_field_path", "unknown_type", "unknown_topic", "invalid_rate", "invalid_range", "config_conflict", "no_data", "robot_offline", "bridge_timeout", "unauthorized", "forbidden", "invalid_credentials", "token_expired", "token_revoked", "email_taken", "identifier_taken", "weak_password", "account_blocked", "busy", "parameter_invalid", "cancel_rejected", "job_lost", "job_unknown_to_bridge", "action_server_lost", "action_failed", "goal_rejected", "goal_send_failed", "result_failed", "goal_uncontrollable", "bridge_disconnected", "config_changed", "publisher_busy", "unknown_command", "not_subscribable", "camera_offline", "no_snapshot_yet", "live_unavailable", "wrong_kind", "not_recorded", "not_aggregatable", "quota_exceeded", "credential_in_use", "goal_timeout", "robot_in_use", "robot_deletion_partial", "job_queue_full", "invalid_uuid", "rate_limited", "tier_required", "token_spent", "service_timeout", "asset_missing", "dynamic_registration_disabled", "client_limit_reached", "idp_unavailable", "mcp_disabled", "tool_not_available", "capability_required", "last_owner", "role_name_taken", "role_in_use", "last_role", "target_state_conflict", "signup_closed", "draft_not_a_document", "internal_error", "not_cancellable", "unsupported_media_type", "wrong_browser", "invalid_yaml", "unstorable_yaml", "registration_closed", "domain_not_allowed", "email_unverified", "origin_not_allowed", "template_invalid", "provider_disabled", "provider_misconfigured", "invalid_redirect_uri", "interaction_expired", "invalid_code", "method_not_allowed"];
|
|
81
81
|
export type ErrorCode = (typeof ERROR_CODES)[number];
|
package/dist/errors.js
CHANGED
|
@@ -576,6 +576,35 @@ export const ERROR_CODES = [
|
|
|
576
576
|
* caller could infer from a silence about existence.
|
|
577
577
|
*/
|
|
578
578
|
'last_owner',
|
|
579
|
+
// App roles.
|
|
580
|
+
/**
|
|
581
|
+
* **Another role of this app already has that name.** 409, on
|
|
582
|
+
* `PATCH /api/apps/:id/roles/:roleId`. Names are unique per app, compared
|
|
583
|
+
* exactly as stored after trimming.
|
|
584
|
+
*
|
|
585
|
+
* Not `validation_error`: the name is well-formed, and the remedy — pick
|
|
586
|
+
* another — depends on the app's other roles, not on the body.
|
|
587
|
+
*/
|
|
588
|
+
'role_name_taken',
|
|
589
|
+
/**
|
|
590
|
+
* **The role is still held**, by app users, by pending invitations, or as
|
|
591
|
+
* the app's default role. 409, on `DELETE /api/apps/:id/roles/:roleId`
|
|
592
|
+
* without `move_to`. `details` is `roleInUseDetails`:
|
|
593
|
+
* `{ users, invitations, is_default }`.
|
|
594
|
+
*
|
|
595
|
+
* Not `conflict`: the details tell the console what to offer — a role to
|
|
596
|
+
* move them to — and a generic code would leave it guessing.
|
|
597
|
+
*/
|
|
598
|
+
'role_in_use',
|
|
599
|
+
/**
|
|
600
|
+
* **An app must keep at least one role.** 409, on
|
|
601
|
+
* `DELETE /api/apps/:id/roles/:roleId` for the app's only role: every app
|
|
602
|
+
* user holds exactly one role, so an app without roles could hold no users.
|
|
603
|
+
*
|
|
604
|
+
* The same shape of refusal as `last_owner`: the caller may delete roles;
|
|
605
|
+
* the app's remaining state is what refuses this one.
|
|
606
|
+
*/
|
|
607
|
+
'last_role',
|
|
579
608
|
// OIDC federation.
|
|
580
609
|
/**
|
|
581
610
|
* **The target is in a state that refuses the operation** — not the caller's
|
|
@@ -589,10 +618,9 @@ export const ERROR_CODES = [
|
|
|
589
618
|
* string on the validation envelope is not a code a consumer can switch on.
|
|
590
619
|
*
|
|
591
620
|
* Its producers in the two-space model are the ones about an app or an
|
|
592
|
-
* account rather than about a caller
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
* where the session is live and it is the target's state that refuses.
|
|
621
|
+
* account rather than about a caller — for example a password change on an
|
|
622
|
+
* app user who has no password at all, an OIDC-only account, where the
|
|
623
|
+
* session is live and it is the target's state that refuses.
|
|
596
624
|
*
|
|
597
625
|
* **A tier change aimed at somebody who is not a Fleetless user of this org
|
|
598
626
|
* was listed here and stopped being a producer at the cut.** That refusal
|
|
@@ -857,10 +885,10 @@ export const ERROR_CODES = [
|
|
|
857
885
|
*/
|
|
858
886
|
'invalid_code',
|
|
859
887
|
/**
|
|
860
|
-
* `403`: the app does not offer this sign-in method — a password login
|
|
861
|
-
*
|
|
862
|
-
*
|
|
863
|
-
* no enumeration oracle.
|
|
888
|
+
* `403`: the app does not offer this sign-in method — a password login, a
|
|
889
|
+
* password reset or a password change on a code-only app, or a code request
|
|
890
|
+
* on a password-only one. It names the app's policy, never a person, so it
|
|
891
|
+
* is no enumeration oracle.
|
|
864
892
|
*/
|
|
865
893
|
'method_not_allowed',
|
|
866
894
|
];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* **Feedback: a message from a developer to the people who build Fleetless.**
|
|
5
|
+
*
|
|
6
|
+
* The console's feedback modal sends it; the cloud stores it first and mails
|
|
7
|
+
* it afterwards, so a message is never lost to a mail failure. Who sent it and
|
|
8
|
+
* from which org is the caller's session, never the body: the body carries
|
|
9
|
+
* only what the developer chose to say and the page they said it on.
|
|
10
|
+
*/
|
|
11
|
+
/** The four kinds the console's modal offers. */
|
|
12
|
+
export declare const FEEDBACK_KINDS: readonly ["idea", "problem", "question", "other"];
|
|
13
|
+
export declare const feedbackKind: z.ZodEnum<{
|
|
14
|
+
idea: "idea";
|
|
15
|
+
problem: "problem";
|
|
16
|
+
question: "question";
|
|
17
|
+
other: "other";
|
|
18
|
+
}>;
|
|
19
|
+
/** Longest message the cloud stores; the console's counter starts at 4 500. */
|
|
20
|
+
export declare const FEEDBACK_MESSAGE_MAX = 5000;
|
|
21
|
+
export declare const feedbackRequest: z.ZodObject<{
|
|
22
|
+
kind: z.ZodEnum<{
|
|
23
|
+
idea: "idea";
|
|
24
|
+
problem: "problem";
|
|
25
|
+
question: "question";
|
|
26
|
+
other: "other";
|
|
27
|
+
}>;
|
|
28
|
+
message: z.ZodString;
|
|
29
|
+
page: z.ZodString;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
export declare const feedbackResponse: z.ZodObject<{
|
|
32
|
+
id: z.ZodUUID;
|
|
33
|
+
mail: z.ZodEnum<{
|
|
34
|
+
sent: "sent";
|
|
35
|
+
not_requested: "not_requested";
|
|
36
|
+
not_configured: "not_configured";
|
|
37
|
+
failed: "failed";
|
|
38
|
+
}>;
|
|
39
|
+
}, z.core.$strict>;
|
|
40
|
+
export type FeedbackKind = z.infer<typeof feedbackKind>;
|
|
41
|
+
export type FeedbackRequest = z.infer<typeof feedbackRequest>;
|
|
42
|
+
export type FeedbackResponse = z.infer<typeof feedbackResponse>;
|
package/dist/feedback.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { mailStatus } from './identity.js';
|
|
4
|
+
/**
|
|
5
|
+
* **Feedback: a message from a developer to the people who build Fleetless.**
|
|
6
|
+
*
|
|
7
|
+
* The console's feedback modal sends it; the cloud stores it first and mails
|
|
8
|
+
* it afterwards, so a message is never lost to a mail failure. Who sent it and
|
|
9
|
+
* from which org is the caller's session, never the body: the body carries
|
|
10
|
+
* only what the developer chose to say and the page they said it on.
|
|
11
|
+
*/
|
|
12
|
+
/** The four kinds the console's modal offers. */
|
|
13
|
+
export const FEEDBACK_KINDS = ['idea', 'problem', 'question', 'other'];
|
|
14
|
+
export const feedbackKind = z.enum(FEEDBACK_KINDS);
|
|
15
|
+
/** Longest message the cloud stores; the console's counter starts at 4 500. */
|
|
16
|
+
export const FEEDBACK_MESSAGE_MAX = 5000;
|
|
17
|
+
export const feedbackRequest = z.object({
|
|
18
|
+
kind: feedbackKind.meta({
|
|
19
|
+
description: 'What the message is: an `idea`, a `problem`, a `question` or `other`. It only sorts the inbox; it changes nothing about how the message is handled.',
|
|
20
|
+
}),
|
|
21
|
+
message: z.string().trim().min(1).max(FEEDBACK_MESSAGE_MAX).meta({
|
|
22
|
+
description: 'What the developer wrote, trimmed. At most 5000 characters; a message that is only whitespace is refused.',
|
|
23
|
+
}),
|
|
24
|
+
page: z.string().startsWith('/').max(512).meta({
|
|
25
|
+
description: 'The console path the message was sent from, e.g. `/robots/:id/jobs` with its real id. A path, never a full URL, so no host and no query string reach the inbox by accident.',
|
|
26
|
+
}),
|
|
27
|
+
}).strict();
|
|
28
|
+
export const feedbackResponse = z.object({
|
|
29
|
+
id: z.uuid().meta({
|
|
30
|
+
description: 'The stored message. It exists whatever `mail` says.',
|
|
31
|
+
}),
|
|
32
|
+
mail: mailStatus.meta({
|
|
33
|
+
description: 'What happened to the notification mail: `sent`, `failed`, or `not_configured` when this cloud has no feedback address. The message is stored in every case, so a client shows success for all three.',
|
|
34
|
+
}),
|
|
35
|
+
}).strict();
|
package/dist/identity.d.ts
CHANGED
|
@@ -220,11 +220,9 @@ export type WaitlistRequest = z.infer<typeof waitlistRequest>;
|
|
|
220
220
|
* no sender can promise that, and this value must never
|
|
221
221
|
* be rendered as if it could.
|
|
222
222
|
* - `not_requested` — no mail was attempted: the caller asked for none
|
|
223
|
-
* (`send_mail: false`)
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
* word rather than a reuse of `not_configured`**: the
|
|
227
|
-
* deployment's mailer is irrelevant in both cases, and a
|
|
223
|
+
* (`send_mail: false`). **A fourth word rather than a
|
|
224
|
+
* reuse of `not_configured`**: the deployment's mailer
|
|
225
|
+
* is irrelevant there, and a
|
|
228
226
|
* console reading "mail server not configured" beside an
|
|
229
227
|
* invitation whose mail checkbox was off would send a
|
|
230
228
|
* developer to fix something that is not broken.
|
package/dist/identity.js
CHANGED
|
@@ -225,11 +225,9 @@ export const waitlistRequest = z.object({ email: z.email().max(254) });
|
|
|
225
225
|
* no sender can promise that, and this value must never
|
|
226
226
|
* be rendered as if it could.
|
|
227
227
|
* - `not_requested` — no mail was attempted: the caller asked for none
|
|
228
|
-
* (`send_mail: false`)
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* word rather than a reuse of `not_configured`**: the
|
|
232
|
-
* 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
|
|
233
231
|
* console reading "mail server not configured" beside an
|
|
234
232
|
* invitation whose mail checkbox was off would send a
|
|
235
233
|
* developer to fix something that is not broken.
|
package/dist/index.d.ts
CHANGED
|
@@ -31,8 +31,10 @@ export { clientAuth, authOk, authError, clientInvoke, clientCancel, clientPublis
|
|
|
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
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
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 {
|
|
35
|
-
export type {
|
|
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';
|
|
36
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, clientLoginCodeRequest, clientLoginCodeVerifyRequest, twoFactorChallenge, clientSignInResult, clientTwoFactorVerifyRequest, clientTwoFactorSetupRequest, clientTwoFactorSetupConfirmRequest, clientTwoFactorSetupConfirmResponse, clientTwoFactorDisableRequest, } from './client-auth.js';
|
|
37
39
|
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
40
|
export { clientRobotListItem, clientRobotListResponse } from './client-robots.js';
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,9 @@ loginCode, totpCode, recoveryCode, recoveryCodesList, twoFactorSetupResponse,
|
|
|
42
42
|
webauthnJson, webauthnOptionsResponse, developerPasskey, developerTwoFactor, createPasskeyRequest, createPasskeyResponse, renamePasskeyRequest, totpConfirmRequest, totpConfirmResponse, recoveryCodesResponse,
|
|
43
43
|
// auth/me, org and member patches.
|
|
44
44
|
authMeResponse, patchOrgRequest, patchAuthMeRequest, } from './identity.js';
|
|
45
|
-
|
|
45
|
+
// 2026-09-30 — the console's feedback modal.
|
|
46
|
+
export { FEEDBACK_KINDS, FEEDBACK_MESSAGE_MAX, feedbackKind, feedbackRequest, feedbackResponse } from './feedback.js';
|
|
47
|
+
export { appIdentifier, app, appListResponse, appDeletionSummary, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, roleRenameRequest, roleDeleteQuery, roleInUseDetails, } from './apps.js';
|
|
46
48
|
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';
|
|
47
49
|
export { clientRobotListItem, clientRobotListResponse } from './client-robots.js';
|
|
48
50
|
// The per-app identity space.
|
package/dist/jobs.d.ts
CHANGED
|
@@ -241,6 +241,7 @@ export declare const jobActor: z.ZodObject<{
|
|
|
241
241
|
}>;
|
|
242
242
|
id: z.ZodUUID;
|
|
243
243
|
label: z.ZodString;
|
|
244
|
+
name: z.ZodNullable<z.ZodString>;
|
|
244
245
|
}, z.core.$strip>;
|
|
245
246
|
export type JobActor = z.infer<typeof jobActor>;
|
|
246
247
|
export declare const jobRunKind: z.ZodEnum<{
|
|
@@ -289,6 +290,7 @@ export declare const jobRun: z.ZodObject<{
|
|
|
289
290
|
}>;
|
|
290
291
|
id: z.ZodUUID;
|
|
291
292
|
label: z.ZodString;
|
|
293
|
+
name: z.ZodNullable<z.ZodString>;
|
|
292
294
|
}, z.core.$strip>;
|
|
293
295
|
seq: z.ZodNumber;
|
|
294
296
|
progress: z.ZodNullable<z.ZodNumber>;
|
|
@@ -351,6 +353,7 @@ export declare const jobRunListResponse: z.ZodObject<{
|
|
|
351
353
|
}>;
|
|
352
354
|
id: z.ZodUUID;
|
|
353
355
|
label: z.ZodString;
|
|
356
|
+
name: z.ZodNullable<z.ZodString>;
|
|
354
357
|
}, z.core.$strip>;
|
|
355
358
|
seq: z.ZodNumber;
|
|
356
359
|
progress: z.ZodNullable<z.ZodNumber>;
|
package/dist/jobs.js
CHANGED
|
@@ -226,6 +226,22 @@ 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
|
+
}),
|
|
229
245
|
});
|
|
230
246
|
export const jobRunKind = z.enum(['action', 'service']);
|
|
231
247
|
/**
|
package/dist/routes.d.ts
CHANGED
|
@@ -103,9 +103,16 @@ export declare const IN_HANDLER_ROUTES: readonly string[];
|
|
|
103
103
|
*
|
|
104
104
|
* Every step is a page the auth portal serves to itself: `audience:
|
|
105
105
|
* 'internal'`, no request schema — the handlers read form fields by hand — and
|
|
106
|
-
* HTML for a browser form post, JSON for a JSON caller.
|
|
107
|
-
*
|
|
108
|
-
*
|
|
106
|
+
* HTML for a browser form post, JSON for a JSON caller.
|
|
107
|
+
*
|
|
108
|
+
* **The browser-proof cookie binds the interaction to one browser**, and it
|
|
109
|
+
* is set by whichever of these comes first for the interaction: the email
|
|
110
|
+
* card (`GET <prefix>/interaction/:id`), `POST <prefix>/identify`, or `POST
|
|
111
|
+
* <prefix>/passkey/options`. The email card is what a browser normally opens
|
|
112
|
+
* first; the two steps set it for a caller that never loaded the page, so
|
|
113
|
+
* `Sign in with a passkey` works without an email step. Once the interaction
|
|
114
|
+
* is bound, every step — those three included — without the matching cookie
|
|
115
|
+
* renders the `wrong_browser` page. The interaction's ten
|
|
109
116
|
* minutes cover every step; only when the last one is done is anything
|
|
110
117
|
* minted. **For `/mcp/oauth`, "done" means the consent step**, as the
|
|
111
118
|
* password did before.
|