@fleetless/contracts 5.1.0 → 5.3.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 CHANGED
@@ -9,6 +9,57 @@ version.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ### Added
13
+
14
+ - **`feedbackRequest` and `feedbackResponse`** (`FeedbackRequest`,
15
+ `FeedbackResponse`) for the new `POST /api/feedback`: a developer's
16
+ message to the people who build Fleetless, `{ kind, message, page }` with
17
+ `kind` one of `FEEDBACK_KINDS` (`idea`, `problem`, `question`, `other`), a
18
+ trimmed message of at most `FEEDBACK_MESSAGE_MAX` (5000) characters and
19
+ the console path it was sent from. The route answers `202` with
20
+ `{ id, mail }`: the message is stored before any mail is tried, so `mail`
21
+ (`sent`, `failed`, `not_configured`) never means it was lost. Rate
22
+ limited to 10 per developer per hour. Published as the artifacts
23
+ `feedback-request` and `feedback-response`.
24
+ - **`jobActor.name`**: the person's display name when the job started,
25
+ required and nullable — `null` for a server key, a person without a name
26
+ and runs recorded before this version; show `label` then. `jobActor`
27
+ stays non-strict, so a consumer on 5.2.0 strips the new key rather than
28
+ refusing the run. Changes the artifacts `job-actor`, `job-run` and
29
+ `job-run-list-response`.
30
+ - **`roleRenameRequest`, `roleDeleteQuery` and `roleInUseDetails`**
31
+ (`RoleRenameRequest`, `RoleDeleteQuery`, `RoleInUseDetails`) for the new
32
+ `PATCH` and `DELETE /api/apps/:id/roles/:roleId`: rename a role
33
+ (`409 role_name_taken` on a clash), or delete it, moving its app users,
34
+ pending invitations and default-role status to `move_to`. Without
35
+ `move_to` a held role answers `409 role_in_use` with
36
+ `{ users, invitations, is_default }`; the app's only role answers
37
+ `409 last_role`. The three codes join `ERROR_CODES`. `role.builtin` no
38
+ longer says built-in roles cannot be renamed or deleted, and the create
39
+ route's note now states the 60-character limit `role.name` always had.
40
+ Published as the artifacts `role-rename-request`, `role-delete-query`
41
+ and `role-in-use-details`.
42
+ - **`auditQuery.target_id`**: only the events about one target — for a
43
+ robot also those that name it in `details.robot_id`, so a robot's log
44
+ includes what was started on it. A string, since target ids are not all
45
+ uuids. `GET /api/audit/export` takes it too. Changes the artifact
46
+ `audit-query`.
47
+
48
+ ## [5.2.0] — 2026-09-30
49
+
50
+ ### Added
51
+
52
+ - **A cancel can be limited to the bridge's own job.** `cancel`
53
+ (`cloudCancel`) gains an optional `own_only: boolean`; absent means
54
+ `false`, today's meaning. With `true` the bridge cancels the named job
55
+ only if it started it itself: a `job_id` it does not hold — typically an
56
+ `unknown` job — cancels nothing, where without the flag it cancels every
57
+ external goal on the action. The cloud sets it on the cancels it sends on
58
+ its own (a republish's reset and its resend at the next hello), so a
59
+ republish never stops a goal Fleetless did not start; a user's cancel
60
+ never sets it. `LATEST_BRIDGE_VERSION` is `6.1.0`, the first bridge that
61
+ honours it. The protocol stays 5.
62
+
12
63
  ## [5.1.0] — 2026-09-30
13
64
 
14
65
  ### Added
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "PROTOCOL_SUNSET_DAYS": 90,
12
- "LATEST_BRIDGE_VERSION": "6.0.0",
12
+ "LATEST_BRIDGE_VERSION": "6.1.0",
13
13
  "CLOSE_ROBOT_DELETED": 4004,
14
14
  "CLOSE_TOKEN_ROTATED": 4005,
15
15
  "JOB_HEARTBEAT_INTERVAL_MS": 1000,
@@ -525,6 +525,17 @@
525
525
  "maxLength": 40
526
526
  }
527
527
  },
528
+ {
529
+ "name": "target_id",
530
+ "in": "query",
531
+ "required": false,
532
+ "schema": {
533
+ "description": "Events whose target is this id; for a robot also the events that name it in `details.robot_id` (`action.invoked`, `service.called`, …), so a robot's events include what was started on it.",
534
+ "type": "string",
535
+ "minLength": 1,
536
+ "maxLength": 200
537
+ }
538
+ },
528
539
  {
529
540
  "name": "from_ms",
530
541
  "in": "query",
@@ -676,6 +687,17 @@
676
687
  "maxLength": 40
677
688
  }
678
689
  },
690
+ {
691
+ "name": "target_id",
692
+ "in": "query",
693
+ "required": false,
694
+ "schema": {
695
+ "description": "Events whose target is this id; for a robot also the events that name it in `details.robot_id` (`action.invoked`, `service.called`, …), so a robot's events include what was started on it.",
696
+ "type": "string",
697
+ "minLength": 1,
698
+ "maxLength": 200
699
+ }
700
+ },
679
701
  {
680
702
  "name": "from_ms",
681
703
  "in": "query",
@@ -1058,7 +1080,7 @@
1058
1080
  }
1059
1081
  }
1060
1082
  },
1061
- "description": "The body is `{ \"name\": string }` — non-empty, trimmed, at most 120 characters — and is deliberately not a contract shape: contracts define the `role` this answers with, not this one trivial request. **The answer is a bare `role`, not an envelope**, unlike the listing beside it."
1083
+ "description": "The body is `{ \"name\": string }` — non-empty, trimmed, at most 60 characters as on `role.name` — and is deliberately not a contract shape: contracts define the `role` this answers with, not this one trivial request. **The answer is a bare `role`, not an envelope**, unlike the listing beside it."
1062
1084
  },
1063
1085
  "get": {
1064
1086
  "operationId": "get_api_apps_id_roles",
@@ -1285,6 +1307,132 @@
1285
1307
  "description": "Built by the same builder the MCP server's own `robot_describe` uses, so the two cannot drift. It answers what the role *would* be offered and consults nothing about any user's actual MCP entitlement. A robot the role grants nothing on still appears, with an empty `exposures` — dropping it would read as \"not attached\", which is a different fact."
1286
1308
  }
1287
1309
  },
1310
+ "/api/apps/{id}/roles/{roleId}": {
1311
+ "patch": {
1312
+ "operationId": "patch_api_apps_id_roles_roleId",
1313
+ "summary": "Renames a role; its users keep it.",
1314
+ "tags": [
1315
+ "apps"
1316
+ ],
1317
+ "security": [
1318
+ {
1319
+ "developerSession": []
1320
+ }
1321
+ ],
1322
+ "parameters": [
1323
+ {
1324
+ "name": "id",
1325
+ "in": "path",
1326
+ "required": true,
1327
+ "description": "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`.",
1328
+ "schema": {
1329
+ "type": "string"
1330
+ }
1331
+ },
1332
+ {
1333
+ "name": "roleId",
1334
+ "in": "path",
1335
+ "required": true,
1336
+ "description": "The role's uuid, from `GET /api/apps/:id/roles`; a role of another app answers `404`.",
1337
+ "schema": {
1338
+ "type": "string"
1339
+ }
1340
+ }
1341
+ ],
1342
+ "responses": {
1343
+ "200": {
1344
+ "description": "Success.",
1345
+ "content": {
1346
+ "application/json": {
1347
+ "schema": {
1348
+ "$ref": "#/components/schemas/role"
1349
+ }
1350
+ }
1351
+ }
1352
+ },
1353
+ "default": {
1354
+ "description": "An error envelope. Codes this route is known to answer: `unauthorized`, `token_expired`, `token_revoked`, `invalid_uuid`, `not_found`, `validation_error`, `role_name_taken`.",
1355
+ "content": {
1356
+ "application/json": {
1357
+ "schema": {
1358
+ "$ref": "#/components/schemas/api-error"
1359
+ }
1360
+ }
1361
+ }
1362
+ }
1363
+ },
1364
+ "description": "Names are unique per app, compared exactly as stored after trimming. Built-in roles can be renamed.",
1365
+ "requestBody": {
1366
+ "required": true,
1367
+ "content": {
1368
+ "application/json": {
1369
+ "schema": {
1370
+ "$ref": "#/components/schemas/role-rename-request"
1371
+ }
1372
+ }
1373
+ }
1374
+ }
1375
+ },
1376
+ "delete": {
1377
+ "operationId": "delete_api_apps_id_roles_roleId",
1378
+ "summary": "Deletes a role, moving its users, pending invitations and default-role status to another role.",
1379
+ "tags": [
1380
+ "apps"
1381
+ ],
1382
+ "security": [
1383
+ {
1384
+ "developerSession": []
1385
+ }
1386
+ ],
1387
+ "parameters": [
1388
+ {
1389
+ "name": "id",
1390
+ "in": "path",
1391
+ "required": true,
1392
+ "description": "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`.",
1393
+ "schema": {
1394
+ "type": "string"
1395
+ }
1396
+ },
1397
+ {
1398
+ "name": "roleId",
1399
+ "in": "path",
1400
+ "required": true,
1401
+ "description": "The role's uuid, from `GET /api/apps/:id/roles`; a role of another app answers `404`.",
1402
+ "schema": {
1403
+ "type": "string"
1404
+ }
1405
+ },
1406
+ {
1407
+ "name": "move_to",
1408
+ "in": "query",
1409
+ "required": false,
1410
+ "schema": {
1411
+ "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`.",
1412
+ "type": "string",
1413
+ "format": "uuid",
1414
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
1415
+ }
1416
+ }
1417
+ ],
1418
+ "responses": {
1419
+ "204": {
1420
+ "description": "Success."
1421
+ },
1422
+ "default": {
1423
+ "description": "An error envelope. Codes this route is known to answer: `unauthorized`, `token_expired`, `token_revoked`, `invalid_uuid`, `not_found`, `validation_error`, `role_in_use`, `last_role`.",
1424
+ "content": {
1425
+ "application/json": {
1426
+ "schema": {
1427
+ "$ref": "#/components/schemas/api-error"
1428
+ }
1429
+ }
1430
+ }
1431
+ }
1432
+ },
1433
+ "description": "Without `move_to`, a role that app users or pending invitations hold, or that is the app's default, answers `409 role_in_use` with `{ users, invitations, is_default }`. With `move_to` — another role of the same app, else `400 validation_error` — one transaction moves `app_users.role_id`, pending invitations and `default_role_id`, then deletes the role and its permissions. The app's only role answers `409 last_role`. Built-in roles can be deleted like any other."
1434
+ }
1435
+ },
1288
1436
  "/api/apps/{id}/server-keys": {
1289
1437
  "post": {
1290
1438
  "operationId": "post_api_apps_id_server_keys",
@@ -8476,6 +8624,54 @@
8476
8624
  },
8477
8625
  "description": "A window longer than `USAGE_WINDOW_MAX_DAYS` is refused naming the field, not silently capped: a caller who asked for more than the platform will answer is owed a refusal, not a shorter answer they will mistake for the whole picture. `from_day <= to_day` is a cross-field rule no JSON Schema can express and is enforced here. The window is echoed back."
8478
8626
  }
8627
+ },
8628
+ "/api/feedback": {
8629
+ "post": {
8630
+ "operationId": "post_api_feedback",
8631
+ "summary": "Sends a message from a developer to the people who build Fleetless.",
8632
+ "tags": [
8633
+ "org"
8634
+ ],
8635
+ "security": [
8636
+ {
8637
+ "developerSession": []
8638
+ }
8639
+ ],
8640
+ "parameters": [],
8641
+ "responses": {
8642
+ "202": {
8643
+ "description": "Success.",
8644
+ "content": {
8645
+ "application/json": {
8646
+ "schema": {
8647
+ "$ref": "#/components/schemas/feedback-response"
8648
+ }
8649
+ }
8650
+ }
8651
+ },
8652
+ "default": {
8653
+ "description": "An error envelope. Codes this route is known to answer: `unauthorized`, `token_expired`, `token_revoked`, `validation_error`, `rate_limited`.",
8654
+ "content": {
8655
+ "application/json": {
8656
+ "schema": {
8657
+ "$ref": "#/components/schemas/api-error"
8658
+ }
8659
+ }
8660
+ }
8661
+ }
8662
+ },
8663
+ "description": "The message is stored before any mail is tried, so `202` means it is kept whatever `mail` says: `sent`, `failed`, or `not_configured` when this cloud has no feedback address. At most 10 messages per developer per hour; the 11th answers `429 rate_limited` with `retry_after_ms`. Replies come by mail, to the sender's address.",
8664
+ "requestBody": {
8665
+ "required": true,
8666
+ "content": {
8667
+ "application/json": {
8668
+ "schema": {
8669
+ "$ref": "#/components/schemas/feedback-request"
8670
+ }
8671
+ }
8672
+ }
8673
+ }
8674
+ }
8479
8675
  }
8480
8676
  },
8481
8677
  "components": {
@@ -14004,6 +14200,65 @@
14004
14200
  ],
14005
14201
  "additionalProperties": false
14006
14202
  },
14203
+ "feedback-request": {
14204
+ "type": "object",
14205
+ "properties": {
14206
+ "kind": {
14207
+ "type": "string",
14208
+ "enum": [
14209
+ "idea",
14210
+ "problem",
14211
+ "question",
14212
+ "other"
14213
+ ],
14214
+ "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."
14215
+ },
14216
+ "message": {
14217
+ "type": "string",
14218
+ "minLength": 1,
14219
+ "maxLength": 5000,
14220
+ "description": "What the developer wrote, trimmed. At most 5000 characters; a message that is only whitespace is refused."
14221
+ },
14222
+ "page": {
14223
+ "type": "string",
14224
+ "maxLength": 512,
14225
+ "pattern": "^\\/.*",
14226
+ "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."
14227
+ }
14228
+ },
14229
+ "required": [
14230
+ "kind",
14231
+ "message",
14232
+ "page"
14233
+ ],
14234
+ "additionalProperties": false
14235
+ },
14236
+ "feedback-response": {
14237
+ "type": "object",
14238
+ "properties": {
14239
+ "id": {
14240
+ "type": "string",
14241
+ "format": "uuid",
14242
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
14243
+ "description": "The stored message. It exists whatever `mail` says."
14244
+ },
14245
+ "mail": {
14246
+ "type": "string",
14247
+ "enum": [
14248
+ "sent",
14249
+ "not_requested",
14250
+ "not_configured",
14251
+ "failed"
14252
+ ],
14253
+ "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."
14254
+ }
14255
+ },
14256
+ "required": [
14257
+ "id",
14258
+ "mail"
14259
+ ],
14260
+ "additionalProperties": false
14261
+ },
14007
14262
  "fetch-types-request": {
14008
14263
  "type": "object",
14009
14264
  "properties": {
@@ -15026,12 +15281,26 @@
15026
15281
  "minLength": 1,
15027
15282
  "maxLength": 200,
15028
15283
  "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."
15284
+ },
15285
+ "name": {
15286
+ "anyOf": [
15287
+ {
15288
+ "type": "string",
15289
+ "minLength": 1,
15290
+ "maxLength": 200
15291
+ },
15292
+ {
15293
+ "type": "null"
15294
+ }
15295
+ ],
15296
+ "description": "The person's display name when the job started: the Fleetless user's `display_name` for a developer, the app user's `display_name` for an app user. `null` for a server key, when the person had no name set, and for runs recorded before contracts 5.3.0. Show `label` when it is null."
15029
15297
  }
15030
15298
  },
15031
15299
  "required": [
15032
15300
  "kind",
15033
15301
  "id",
15034
- "label"
15302
+ "label",
15303
+ "name"
15035
15304
  ],
15036
15305
  "additionalProperties": false,
15037
15306
  "description": "Who invoked the run, and what they were acting as at the time."
@@ -17637,7 +17906,7 @@
17637
17906
  },
17638
17907
  "builtin": {
17639
17908
  "type": "boolean",
17640
- "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. It does not make them renamable or deletable — no route does that for any role."
17909
+ "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."
17641
17910
  }
17642
17911
  },
17643
17912
  "required": [
@@ -17676,7 +17945,7 @@
17676
17945
  },
17677
17946
  "builtin": {
17678
17947
  "type": "boolean",
17679
- "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. It does not make them renamable or deletable — no route does that for any role."
17948
+ "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."
17680
17949
  }
17681
17950
  },
17682
17951
  "required": [
@@ -17755,6 +18024,21 @@
17755
18024
  "capabilities"
17756
18025
  ]
17757
18026
  },
18027
+ "role-rename-request": {
18028
+ "type": "object",
18029
+ "properties": {
18030
+ "name": {
18031
+ "type": "string",
18032
+ "minLength": 1,
18033
+ "maxLength": 60,
18034
+ "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."
18035
+ }
18036
+ },
18037
+ "required": [
18038
+ "name"
18039
+ ],
18040
+ "additionalProperties": false
18041
+ },
17758
18042
  "server-key-list-response": {
17759
18043
  "type": "object",
17760
18044
  "properties": {
@@ -574,7 +574,7 @@
574
574
  "validation_error"
575
575
  ],
576
576
  "transport": "http",
577
- "notes": "The body is `{ \"name\": string }` — non-empty, trimmed, at most 120 characters — and is deliberately not a contract shape: contracts define the `role` this answers with, not this one trivial request. **The answer is a bare `role`, not an envelope**, unlike the listing beside it."
577
+ "notes": "The body is `{ \"name\": string }` — non-empty, trimmed, at most 60 characters as on `role.name` — and is deliberately not a contract shape: contracts define the `role` this answers with, not this one trivial request. **The answer is a bare `role`, not an envelope**, unlike the listing beside it."
578
578
  },
579
579
  {
580
580
  "method": "GET",
@@ -704,6 +704,77 @@
704
704
  "transport": "http",
705
705
  "notes": "Built by the same builder the MCP server's own `robot_describe` uses, so the two cannot drift. It answers what the role *would* be offered and consults nothing about any user's actual MCP entitlement. A robot the role grants nothing on still appears, with an empty `exposures` — dropping it would read as \"not attached\", which is a different fact."
706
706
  },
707
+ {
708
+ "method": "PATCH",
709
+ "path": "/api/apps/:id/roles/:roleId",
710
+ "section": "apps",
711
+ "summary": "Renames a role; its users keep it.",
712
+ "audience": "developer",
713
+ "auth": "developer",
714
+ "rateLimited": false,
715
+ "ownerTier": false,
716
+ "status": 200,
717
+ "params": [
718
+ {
719
+ "name": "id",
720
+ "description": "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`."
721
+ },
722
+ {
723
+ "name": "roleId",
724
+ "description": "The role's uuid, from `GET /api/apps/:id/roles`; a role of another app answers `404`."
725
+ }
726
+ ],
727
+ "query": null,
728
+ "request": "role-rename-request",
729
+ "response": "role",
730
+ "errors": [
731
+ "unauthorized",
732
+ "token_expired",
733
+ "token_revoked",
734
+ "invalid_uuid",
735
+ "not_found",
736
+ "validation_error",
737
+ "role_name_taken"
738
+ ],
739
+ "transport": "http",
740
+ "notes": "Names are unique per app, compared exactly as stored after trimming. Built-in roles can be renamed."
741
+ },
742
+ {
743
+ "method": "DELETE",
744
+ "path": "/api/apps/:id/roles/:roleId",
745
+ "section": "apps",
746
+ "summary": "Deletes a role, moving its users, pending invitations and default-role status to another role.",
747
+ "audience": "developer",
748
+ "auth": "developer",
749
+ "rateLimited": false,
750
+ "ownerTier": false,
751
+ "status": 204,
752
+ "params": [
753
+ {
754
+ "name": "id",
755
+ "description": "The app's uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`."
756
+ },
757
+ {
758
+ "name": "roleId",
759
+ "description": "The role's uuid, from `GET /api/apps/:id/roles`; a role of another app answers `404`."
760
+ }
761
+ ],
762
+ "query": "role-delete-query",
763
+ "request": null,
764
+ "response": null,
765
+ "errors": [
766
+ "unauthorized",
767
+ "token_expired",
768
+ "token_revoked",
769
+ "invalid_uuid",
770
+ "not_found",
771
+ "validation_error",
772
+ "role_in_use",
773
+ "last_role"
774
+ ],
775
+ "transport": "http",
776
+ "notes": "Without `move_to`, a role that app users or pending invitations hold, or that is the app's default, answers `409 role_in_use` with `{ users, invitations, is_default }`. With `move_to` — another role of the same app, else `400 validation_error` — one transaction moves `app_users.role_id`, pending invitations and `default_role_id`, then deletes the role and its permissions. The app's only role answers `409 last_role`. Built-in roles can be deleted like any other."
777
+ },
707
778
  {
708
779
  "method": "POST",
709
780
  "path": "/api/apps/:id/server-keys",
@@ -4821,6 +4892,30 @@
4821
4892
  "transport": "http",
4822
4893
  "notes": "A window longer than `USAGE_WINDOW_MAX_DAYS` is refused naming the field, not silently capped: a caller who asked for more than the platform will answer is owed a refusal, not a shorter answer they will mistake for the whole picture. `from_day <= to_day` is a cross-field rule no JSON Schema can express and is enforced here. The window is echoed back."
4823
4894
  },
4895
+ {
4896
+ "method": "POST",
4897
+ "path": "/api/feedback",
4898
+ "section": "org",
4899
+ "summary": "Sends a message from a developer to the people who build Fleetless.",
4900
+ "audience": "developer",
4901
+ "auth": "developer",
4902
+ "rateLimited": true,
4903
+ "ownerTier": false,
4904
+ "status": 202,
4905
+ "params": [],
4906
+ "query": null,
4907
+ "request": "feedback-request",
4908
+ "response": "feedback-response",
4909
+ "errors": [
4910
+ "unauthorized",
4911
+ "token_expired",
4912
+ "token_revoked",
4913
+ "validation_error",
4914
+ "rate_limited"
4915
+ ],
4916
+ "transport": "http",
4917
+ "notes": "The message is stored before any mail is tried, so `202` means it is kept whatever `mail` says: `sent`, `failed`, or `not_configured` when this cloud has no feedback address. At most 10 messages per developer per hour; the 11th answers `429 rate_limited` with `retry_after_ms`. Replies come by mail, to the sender's address."
4918
+ },
4824
4919
  {
4825
4920
  "method": "POST",
4826
4921
  "path": "/api/bridge/assets",
@@ -48,6 +48,12 @@
48
48
  "minLength": 1,
49
49
  "maxLength": 40
50
50
  },
51
+ "target_id": {
52
+ "description": "Events whose target is this id; for a robot also the events that name it in `details.robot_id` (`action.invoked`, `service.called`, …), so a robot's events include what was started on it.",
53
+ "type": "string",
54
+ "minLength": 1,
55
+ "maxLength": 200
56
+ },
51
57
  "from_ms": {
52
58
  "anyOf": [
53
59
  {
@@ -28,6 +28,9 @@
28
28
  "type": "null"
29
29
  }
30
30
  ]
31
+ },
32
+ "own_only": {
33
+ "type": "boolean"
31
34
  }
32
35
  },
33
36
  "required": [
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "kind": {
6
+ "type": "string",
7
+ "enum": [
8
+ "idea",
9
+ "problem",
10
+ "question",
11
+ "other"
12
+ ],
13
+ "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."
14
+ },
15
+ "message": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "maxLength": 5000,
19
+ "description": "What the developer wrote, trimmed. At most 5000 characters; a message that is only whitespace is refused."
20
+ },
21
+ "page": {
22
+ "type": "string",
23
+ "maxLength": 512,
24
+ "pattern": "^\\/.*",
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
+ },
28
+ "required": [
29
+ "kind",
30
+ "message",
31
+ "page"
32
+ ],
33
+ "additionalProperties": false
34
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "id": {
6
+ "type": "string",
7
+ "format": "uuid",
8
+ "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
9
+ "description": "The stored message. It exists whatever `mail` says."
10
+ },
11
+ "mail": {
12
+ "type": "string",
13
+ "enum": [
14
+ "sent",
15
+ "not_requested",
16
+ "not_configured",
17
+ "failed"
18
+ ],
19
+ "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."
20
+ }
21
+ },
22
+ "required": [
23
+ "id",
24
+ "mail"
25
+ ],
26
+ "additionalProperties": false
27
+ }
@@ -23,12 +23,26 @@
23
23
  "minLength": 1,
24
24
  "maxLength": 200,
25
25
  "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."
26
+ },
27
+ "name": {
28
+ "anyOf": [
29
+ {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "maxLength": 200
33
+ },
34
+ {
35
+ "type": "null"
36
+ }
37
+ ],
38
+ "description": "The person's display name when the job started: the Fleetless user's `display_name` for a developer, the app user's `display_name` for an app user. `null` for a server key, when the person had no name set, and for runs recorded before contracts 5.3.0. Show `label` when it is null."
26
39
  }
27
40
  },
28
41
  "required": [
29
42
  "kind",
30
43
  "id",
31
- "label"
44
+ "label",
45
+ "name"
32
46
  ],
33
47
  "additionalProperties": false
34
48
  }