@fleetless/contracts 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +11 -2
  2. package/CONTRIBUTING.md +100 -75
  3. package/README.md +69 -83
  4. package/SECURITY.md +24 -24
  5. package/artifacts/openapi.json +65 -65
  6. package/artifacts/routes.json +3 -3
  7. package/artifacts/schema/app-list-response.schema.json +2 -2
  8. package/artifacts/schema/app-oidc-provider-list-response.schema.json +1 -1
  9. package/artifacts/schema/app-oidc-provider.schema.json +1 -1
  10. package/artifacts/schema/app-user-list-response.schema.json +2 -2
  11. package/artifacts/schema/app-user.schema.json +2 -2
  12. package/artifacts/schema/app.schema.json +2 -2
  13. package/artifacts/schema/asset-list-response.schema.json +7 -7
  14. package/artifacts/schema/asset-sync-request.schema.json +1 -1
  15. package/artifacts/schema/asset-sync-status.schema.json +1 -1
  16. package/artifacts/schema/asset.schema.json +3 -3
  17. package/artifacts/schema/auth-me-response.schema.json +2 -2
  18. package/artifacts/schema/auth-ok.schema.json +1 -1
  19. package/artifacts/schema/authorization-server-metadata.schema.json +1 -1
  20. package/artifacts/schema/bridge-asset-progress.schema.json +1 -1
  21. package/artifacts/schema/busy-details.schema.json +3 -3
  22. package/artifacts/schema/client-identity.schema.json +1 -1
  23. package/artifacts/schema/client-login-request.schema.json +1 -1
  24. package/artifacts/schema/client-logout-request.schema.json +1 -1
  25. package/artifacts/schema/client-mcp-interaction.schema.json +1 -1
  26. package/artifacts/schema/cloud-config.schema.json +1 -1
  27. package/artifacts/schema/command-result.schema.json +3 -3
  28. package/artifacts/schema/config-draft-response.schema.json +1 -1
  29. package/artifacts/schema/config-version-response.schema.json +1 -1
  30. package/artifacts/schema/create-server-key-response.schema.json +1 -1
  31. package/artifacts/schema/datapoint-config.schema.json +1 -1
  32. package/artifacts/schema/datapoint-value.schema.json +2 -2
  33. package/artifacts/schema/dynamic-client-registration-request.schema.json +2 -2
  34. package/artifacts/schema/fleetless-user-list-response.schema.json +2 -2
  35. package/artifacts/schema/fleetless-user.schema.json +2 -2
  36. package/artifacts/schema/invoke-or-service-response.schema.json +4 -4
  37. package/artifacts/schema/invoke-response.schema.json +3 -3
  38. package/artifacts/schema/job-actor.schema.json +1 -1
  39. package/artifacts/schema/job-event.schema.json +3 -3
  40. package/artifacts/schema/job-response.schema.json +3 -3
  41. package/artifacts/schema/job-run-list-response.schema.json +2 -2
  42. package/artifacts/schema/job-run.schema.json +2 -2
  43. package/artifacts/schema/job.schema.json +3 -3
  44. package/artifacts/schema/mcp-consent-grant-list-response.schema.json +2 -2
  45. package/artifacts/schema/mcp-consent-grant.schema.json +2 -2
  46. package/artifacts/schema/oauth-authorize-query.schema.json +1 -1
  47. package/artifacts/schema/oauth-token-request.schema.json +1 -1
  48. package/artifacts/schema/patch-org-response.schema.json +1 -1
  49. package/artifacts/schema/patch-robot-response.schema.json +1 -1
  50. package/artifacts/schema/robot-config-doc.schema.json +1 -1
  51. package/artifacts/schema/robot-jobs-response.schema.json +3 -3
  52. package/artifacts/schema/role-list-response.schema.json +1 -1
  53. package/artifacts/schema/role.schema.json +1 -1
  54. package/artifacts/schema/server-key-list-response.schema.json +2 -2
  55. package/artifacts/schema/server-key.schema.json +1 -1
  56. package/artifacts/schema/service-call-response.schema.json +1 -1
  57. package/artifacts/schema/sign-up-response.schema.json +2 -2
  58. package/artifacts/schema/urdf-completeness.schema.json +2 -2
  59. package/artifacts/schema-outgoing/bridge-asset-progress.schema.json +1 -1
  60. package/dist/alerts.d.ts +15 -17
  61. package/dist/alerts.js +15 -17
  62. package/dist/app-users.d.ts +5 -6
  63. package/dist/app-users.js +9 -10
  64. package/dist/apps.d.ts +5 -6
  65. package/dist/apps.js +11 -12
  66. package/dist/assets.js +10 -13
  67. package/dist/audit.d.ts +10 -12
  68. package/dist/audit.js +14 -17
  69. package/dist/client-auth.d.ts +8 -9
  70. package/dist/client-auth.js +14 -15
  71. package/dist/config-issues.d.ts +3 -3
  72. package/dist/config-issues.js +3 -3
  73. package/dist/config.d.ts +5 -6
  74. package/dist/config.js +7 -8
  75. package/dist/errors.d.ts +4 -4
  76. package/dist/errors.js +8 -9
  77. package/dist/identity.d.ts +4 -5
  78. package/dist/identity.js +7 -8
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.js +1 -1
  81. package/dist/jobs.js +5 -5
  82. package/dist/mcp.d.ts +5 -8
  83. package/dist/mcp.js +2 -2
  84. package/dist/oauth.d.ts +8 -10
  85. package/dist/oauth.js +13 -15
  86. package/dist/protocol.d.ts +7 -8
  87. package/dist/protocol.js +20 -22
  88. package/dist/realtime.js +4 -4
  89. package/dist/rest.js +4 -4
  90. package/dist/routes.js +3 -3
  91. package/package.json +1 -1
@@ -1822,7 +1822,7 @@
1822
1822
  "name": "clientId",
1823
1823
  "in": "path",
1824
1824
  "required": true,
1825
- "description": "The MCP client, as `GET /api/apps/:id/users/:userId/mcp-grants` reports its `client_id`. Not a uuid — it is the identifier the dynamic registration issued.",
1825
+ "description": "The MCP client, as `GET /api/apps/:id/users/:userId/mcp-grants` reports its `client_id`. Not a uuid — the identifier dynamic registration issued.",
1826
1826
  "schema": {
1827
1827
  "type": "string"
1828
1828
  }
@@ -3441,7 +3441,7 @@
3441
3441
  "schema": {
3442
3442
  "type": "string",
3443
3443
  "minLength": 1,
3444
- "description": "The PKCE challenge; the verifier is presented at the token endpoint. Only non-emptiness is checked here — length and alphabet are not — since the verifier is what actually has to match."
3444
+ "description": "The PKCE challenge; the verifier is presented at the token endpoint. Only non-emptiness is checked here — length and alphabet are not — since the verifier is what has to match."
3445
3445
  }
3446
3446
  },
3447
3447
  {
@@ -3882,7 +3882,7 @@
3882
3882
  "schema": {
3883
3883
  "type": "string",
3884
3884
  "minLength": 1,
3885
- "description": "The PKCE challenge; the verifier is presented at the token endpoint. Only non-emptiness is checked here — length and alphabet are not — since the verifier is what actually has to match."
3885
+ "description": "The PKCE challenge; the verifier is presented at the token endpoint. Only non-emptiness is checked here — length and alphabet are not — since the verifier is what has to match."
3886
3886
  }
3887
3887
  },
3888
3888
  {
@@ -4915,7 +4915,7 @@
4915
4915
  "name": "clientId",
4916
4916
  "in": "path",
4917
4917
  "required": true,
4918
- "description": "The MCP client, as `GET /api/client/mcp/grants` reports its `client_id`. Not a uuid — it is the identifier the dynamic registration issued.",
4918
+ "description": "The MCP client, as `GET /api/client/mcp/grants` reports its `client_id`. Not a uuid — the identifier dynamic registration issued.",
4919
4919
  "schema": {
4920
4920
  "type": "string"
4921
4921
  }
@@ -6441,7 +6441,7 @@
6441
6441
  "name": "slug",
6442
6442
  "in": "path",
6443
6443
  "required": true,
6444
- "description": "The action or service slug from the published configuration; the cloud already knows which kind it is.",
6444
+ "description": "The action or service slug from the published configuration — the cloud already knows which kind.",
6445
6445
  "schema": {
6446
6446
  "type": "string"
6447
6447
  }
@@ -8271,7 +8271,7 @@
8271
8271
  "minLength": 2,
8272
8272
  "maxLength": 63,
8273
8273
  "pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$",
8274
- "description": "The stable handle a client sends at login, lowercase and underscore-separated. **Globally unique, not per organisation** — `clientLoginRequest` carries no org context to disambiguate with, so a collision is refused with `identifier_taken`."
8274
+ "description": "The stable handle a client sends at login, lowercase and underscore-separated. **Globally unique, not per organisation** — `clientLoginRequest` carries no org context, so a collision is refused with `identifier_taken`."
8275
8275
  },
8276
8276
  "robot_ids": {
8277
8277
  "type": "array",
@@ -8293,7 +8293,7 @@
8293
8293
  "type": "null"
8294
8294
  }
8295
8295
  ],
8296
- "description": "The role an app user gets when they are created or invited without an explicit one. `null` means this app has not chosen a default, the normal state of an app created before its roles were configured — and then a create or invite that omits `role_id` is a `validation_error` rather than a user with no role. An invitation resolves the role when it is issued, so changing this never re-aims an outstanding one. The role must belong to this app, which `PATCH /api/apps/:id` checks and the schema cannot."
8296
+ "description": "The role an app user gets when created or invited without an explicit one. `null` means this app has not chosen a default, the normal state of an app created before its roles were configured — and then a create or invite that omits `role_id` gets `validation_error`, not a user with no role. An invitation resolves the role when issued, so changing this never re-aims an outstanding one. The role must belong to this app, which `PATCH /api/apps/:id` checks and the schema cannot."
8297
8297
  },
8298
8298
  "created_at": {
8299
8299
  "type": "string",
@@ -8573,7 +8573,7 @@
8573
8573
  "minLength": 2,
8574
8574
  "maxLength": 63,
8575
8575
  "pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$",
8576
- "description": "The stable handle a client sends at login, lowercase and underscore-separated. **Globally unique, not per organisation** — `clientLoginRequest` carries no org context to disambiguate with, so a collision is refused with `identifier_taken`."
8576
+ "description": "The stable handle a client sends at login, lowercase and underscore-separated. **Globally unique, not per organisation** — `clientLoginRequest` carries no org context, so a collision is refused with `identifier_taken`."
8577
8577
  },
8578
8578
  "robot_ids": {
8579
8579
  "type": "array",
@@ -8595,7 +8595,7 @@
8595
8595
  "type": "null"
8596
8596
  }
8597
8597
  ],
8598
- "description": "The role an app user gets when they are created or invited without an explicit one. `null` means this app has not chosen a default, the normal state of an app created before its roles were configured — and then a create or invite that omits `role_id` is a `validation_error` rather than a user with no role. An invitation resolves the role when it is issued, so changing this never re-aims an outstanding one. The role must belong to this app, which `PATCH /api/apps/:id` checks and the schema cannot."
8598
+ "description": "The role an app user gets when created or invited without an explicit one. `null` means this app has not chosen a default, the normal state of an app created before its roles were configured — and then a create or invite that omits `role_id` gets `validation_error`, not a user with no role. An invitation resolves the role when issued, so changing this never re-aims an outstanding one. The role must belong to this app, which `PATCH /api/apps/:id` checks and the schema cannot."
8599
8599
  },
8600
8600
  "created_at": {
8601
8601
  "type": "string",
@@ -8799,7 +8799,7 @@
8799
8799
  },
8800
8800
  "enabled": {
8801
8801
  "type": "boolean",
8802
- "description": "Whether this provider is offered at all. A disabled provider disappears from `GET /api/client/providers` and refuses a start with `provider_disabled`, without the row and its linked identities being deleted."
8802
+ "description": "Whether this provider is offered. A disabled provider disappears from `GET /api/client/providers` and refuses a start with `provider_disabled`, without the row and its linked identities being deleted."
8803
8803
  },
8804
8804
  "created_at": {
8805
8805
  "type": "string",
@@ -8883,7 +8883,7 @@
8883
8883
  },
8884
8884
  "enabled": {
8885
8885
  "type": "boolean",
8886
- "description": "Whether this provider is offered at all. A disabled provider disappears from `GET /api/client/providers` and refuses a start with `provider_disabled`, without the row and its linked identities being deleted."
8886
+ "description": "Whether this provider is offered. A disabled provider disappears from `GET /api/client/providers` and refuses a start with `provider_disabled`, without the row and its linked identities being deleted."
8887
8887
  },
8888
8888
  "created_at": {
8889
8889
  "type": "string",
@@ -8965,7 +8965,7 @@
8965
8965
  },
8966
8966
  "has_password": {
8967
8967
  "type": "boolean",
8968
- "description": "Whether this account has a Fleetless-held password at all. `false` is an identity-provider-only account, or an invitation not yet accepted — it does not mean blocked and it does not mean without access. No hash, no algorithm and no \"last changed\" travels here, and nothing on the wire can say whether a password is strong or already known to somebody else."
8968
+ "description": "Whether this account has a Fleetless-held password. `false` is an identity-provider-only account, or an invitation not yet accepted — it does not mean blocked and it does not mean without access. No hash, no algorithm and no \"last changed\" travels here, and nothing on the wire can say whether a password is strong or already known to somebody else."
8969
8969
  },
8970
8970
  "providers": {
8971
8971
  "maxItems": 20,
@@ -8975,7 +8975,7 @@
8975
8975
  "maxLength": 40,
8976
8976
  "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
8977
8977
  },
8978
- "description": "The slugs of the identity providers this account is linked to, empty for a password-only user. It is what lets a developer's user list say where an account came from without a second request."
8978
+ "description": "The slugs of the identity providers this account is linked to, empty for a password-only user. Lets a developer's user list say where an account came from without a second request."
8979
8979
  },
8980
8980
  "last_login_at": {
8981
8981
  "anyOf": [
@@ -9067,7 +9067,7 @@
9067
9067
  },
9068
9068
  "has_password": {
9069
9069
  "type": "boolean",
9070
- "description": "Whether this account has a Fleetless-held password at all. `false` is an identity-provider-only account, or an invitation not yet accepted — it does not mean blocked and it does not mean without access. No hash, no algorithm and no \"last changed\" travels here, and nothing on the wire can say whether a password is strong or already known to somebody else."
9070
+ "description": "Whether this account has a Fleetless-held password. `false` is an identity-provider-only account, or an invitation not yet accepted — it does not mean blocked and it does not mean without access. No hash, no algorithm and no \"last changed\" travels here, and nothing on the wire can say whether a password is strong or already known to somebody else."
9071
9071
  },
9072
9072
  "providers": {
9073
9073
  "maxItems": 20,
@@ -9077,7 +9077,7 @@
9077
9077
  "maxLength": 40,
9078
9078
  "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
9079
9079
  },
9080
- "description": "The slugs of the identity providers this account is linked to, empty for a password-only user. It is what lets a developer's user list say where an account came from without a second request."
9080
+ "description": "The slugs of the identity providers this account is linked to, empty for a password-only user. Lets a developer's user list say where an account came from without a second request."
9081
9081
  },
9082
9082
  "last_login_at": {
9083
9083
  "anyOf": [
@@ -9149,13 +9149,13 @@
9149
9149
  "texture",
9150
9150
  "other"
9151
9151
  ],
9152
- "description": "What the file is: the `urdf` itself, a `mesh` it references, a `texture` a mesh or the URDF paints with, or `other`. A renderer decides from this alone, before fetching anything, what it has to pre-fetch."
9152
+ "description": "What the file is: the `urdf` itself, a `mesh` it references, a `texture` a mesh or the URDF paints with, or `other`. A renderer decides from this alone, before fetching anything, what to pre-fetch."
9153
9153
  },
9154
9154
  "name": {
9155
9155
  "type": "string",
9156
9156
  "minLength": 1,
9157
9157
  "maxLength": 500,
9158
- "description": "What the robot called it — for a mesh, the `package://` URI the URDF references, verbatim, which is the only string a developer can match against their own workspace. A file the URDF never names (an image a `.dae` loads for itself) is named by joining the mesh's own directory with that internal reference."
9158
+ "description": "What the robot called it — for a mesh, the `package://` URI the URDF references, verbatim, the only string a developer can match against their own workspace. A file the URDF never names (an image a `.dae` loads for itself) is named by joining the mesh's own directory with that internal reference."
9159
9159
  },
9160
9160
  "media_type": {
9161
9161
  "type": "string",
@@ -9172,7 +9172,7 @@
9172
9172
  "sha256": {
9173
9173
  "type": "string",
9174
9174
  "pattern": "^[a-f0-9]{64}$",
9175
- "description": "The content hash, lowercase hex, and the reason two robots sharing a mesh cost one copy. It is exposed because it is the only way a client can tell \"this is the same mesh I already have\" across robots."
9175
+ "description": "The content hash, lowercase hex. Exposed because it is the only way a client can tell \"this is the same mesh I already have\" across robots — the reason two robots sharing a mesh cost one copy."
9176
9176
  },
9177
9177
  "created_at": {
9178
9178
  "type": "string",
@@ -9271,7 +9271,7 @@
9271
9271
  "type": "integer",
9272
9272
  "exclusiveMinimum": 0,
9273
9273
  "maximum": 9007199254740991,
9274
- "description": "How large the refused file actually is, in bytes. With `limit_bytes` beside it a developer can tell whether to shrink the mesh or raise the limit; \"too large\" alone answers neither."
9274
+ "description": "How large the refused file is, in bytes. With `limit_bytes` beside it a developer can tell whether to shrink the mesh or raise the limit; \"too large\" alone answers neither."
9275
9275
  }
9276
9276
  },
9277
9277
  "required": [
@@ -9360,7 +9360,7 @@
9360
9360
  "type": "string",
9361
9361
  "minLength": 1,
9362
9362
  "maxLength": 500,
9363
- "description": "The reference, verbatim, that no stored asset answers — a `package://` URI the workspace does not hold, or an absolute or bare relative path nothing will ever fetch. A developer whose URDF names one of the latter is entitled to be told so."
9363
+ "description": "The reference, verbatim, that no stored asset answers — a `package://` URI the workspace does not hold, or an absolute or bare relative path nothing will ever fetch."
9364
9364
  },
9365
9365
  "element": {
9366
9366
  "type": "string",
@@ -9377,7 +9377,7 @@
9377
9377
  ],
9378
9378
  "additionalProperties": false
9379
9379
  },
9380
- "description": "The references nothing in the store answers, each with the element that asked for it. A bare count is a dead end that sends a developer hunting through a workspace by hand; the references are what they can act on, so the references travel."
9380
+ "description": "The references nothing in the store answers, each with the element that asked for it. A bare count would send a developer hunting through the workspace by hand; the references are what they can act on."
9381
9381
  }
9382
9382
  },
9383
9383
  "required": [
@@ -9397,7 +9397,7 @@
9397
9397
  "type": "null"
9398
9398
  }
9399
9399
  ],
9400
- "description": "What the connected bridge says it *could* transfer, which is deliberately separate from what has been transferred. `null` when no bridge is connected — distinct from `false`, because \"no robot is online to ask\" and \"the robot has no URDF\" send a developer to two different places. After a publisher is killed rather than shut down this can read `true` for some seconds, on the underlying DDS liveliness timeout rather than on any check made here."
9400
+ "description": "What the connected bridge says it *could* transfer — deliberately separate from what has been transferred. `null` when no bridge is connected, distinct from `false`: \"no robot is online to ask\" and \"the robot has no URDF\" send a developer to different places. After a publisher is killed rather than shut down this can read `true` for some seconds, on the underlying DDS liveliness timeout rather than on any check made here."
9401
9401
  }
9402
9402
  },
9403
9403
  "required": [
@@ -9416,7 +9416,7 @@
9416
9416
  "enum": [
9417
9417
  "bridge"
9418
9418
  ],
9419
- "description": "Where the bytes come from. `bridge` is the only value today: the connected bridge reads them from the robot's own workspace. It is validated rather than ignored, so a caller naming a source that does not exist yet learns that instead of silently getting a bridge sync."
9419
+ "description": "Where the bytes come from. `bridge` is the only value today: the connected bridge reads them from the robot's own workspace. Validated rather than ignored, so a caller naming an unknown source is told so instead of silently getting a bridge sync."
9420
9420
  }
9421
9421
  },
9422
9422
  "required": [
@@ -9513,7 +9513,7 @@
9513
9513
  "type": "integer",
9514
9514
  "exclusiveMinimum": 0,
9515
9515
  "maximum": 9007199254740991,
9516
- "description": "How large the refused file actually is, in bytes. With `limit_bytes` beside it a developer can tell whether to shrink the mesh or raise the limit; \"too large\" alone answers neither."
9516
+ "description": "How large the refused file is, in bytes. With `limit_bytes` beside it a developer can tell whether to shrink the mesh or raise the limit; \"too large\" alone answers neither."
9517
9517
  }
9518
9518
  },
9519
9519
  "required": [
@@ -9762,7 +9762,7 @@
9762
9762
  "type": "string",
9763
9763
  "format": "uuid",
9764
9764
  "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)$",
9765
- "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at rather than being a filter it applies."
9765
+ "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at, not a filter it applies."
9766
9766
  },
9767
9767
  "email": {
9768
9768
  "type": "string",
@@ -9789,7 +9789,7 @@
9789
9789
  "owner",
9790
9790
  "developer"
9791
9791
  ],
9792
- "description": "The console powers this person holds. **Required** — every Fleetless user is a member of the team and has a tier; the optional version of this field existed only while the org also held people with no console powers to grade, and that pool is gone."
9792
+ "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."
9793
9793
  },
9794
9794
  "created_at": {
9795
9795
  "type": "string",
@@ -9826,7 +9826,7 @@
9826
9826
  "authorization_endpoint": {
9827
9827
  "type": "string",
9828
9828
  "format": "uri",
9829
- "description": "The URL a client sends the user to in order to authorize."
9829
+ "description": "Where a client sends the user to authorize."
9830
9830
  },
9831
9831
  "token_endpoint": {
9832
9832
  "type": "string",
@@ -10014,7 +10014,7 @@
10014
10014
  "app_user",
10015
10015
  "server_key"
10016
10016
  ],
10017
- "description": "Which of the three kinds of caller this is: a `developer` working through the console, an `app_user` holding a token from a client login, or a `server_key` used by server-side code. Stated outright rather than left to be inferred from which id happens to be set."
10017
+ "description": "Which of the three kinds of caller this is: a `developer` working through the console, an `app_user` holding a token from a client login, or a `server_key` used by server-side code. Stated outright, not inferred from which id is set."
10018
10018
  },
10019
10019
  "developer_id": {
10020
10020
  "anyOf": [
@@ -10114,7 +10114,7 @@
10114
10114
  "minLength": 2,
10115
10115
  "maxLength": 63,
10116
10116
  "pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$",
10117
- "description": "The app being logged in to, as its globally unique identifier — the lowercase, underscore-separated string the developer chose when the app was created. There is no organisation context at login, so this is what decides which app the credentials are checked for."
10117
+ "description": "The app being logged in to: its globally unique, lowercase, underscore-separated identifier, chosen by the developer at creation. There is no organisation context at login, so this is what decides which app the credentials are checked for."
10118
10118
  },
10119
10119
  "email": {
10120
10120
  "type": "string",
@@ -10140,7 +10140,7 @@
10140
10140
  "refresh_token": {
10141
10141
  "type": "string",
10142
10142
  "minLength": 1,
10143
- "description": "Any refresh token of the session to end. The whole token family is revoked server-side, so a token stolen before this call stops working too — clearing a client-side store is a gesture, not a revocation. The answer is `204`: a token the server does not recognise gets it too, since the end state a caller asked for is the end state they get."
10143
+ "description": "Any refresh token of the session to end. The whole token family is revoked server-side, so a token stolen before this call stops working too — clearing a client-side store is a gesture, not a revocation. The answer is `204`: a token the server does not recognise gets it too, since that is the end state being asked for."
10144
10144
  }
10145
10145
  },
10146
10146
  "required": [
@@ -10174,7 +10174,7 @@
10174
10174
  "client_name_verified": {
10175
10175
  "type": "boolean",
10176
10176
  "const": false,
10177
- "description": "Always `false`. The client registered itself without authentication and chose this name about itself, so it must be rendered as a claim and never as an identity. There is no verified case, which is why this is a literal and not a boolean: a `true` branch would be dead code that looked like a safeguard."
10177
+ "description": "Always `false`. The client registered itself without authentication and named itself, so it must be rendered as a claim and never as an identity. There is no verified case, which is why this is a literal and not a boolean: a `true` branch would be dead code that looked like a safeguard."
10178
10178
  },
10179
10179
  "scopes": {
10180
10180
  "type": "array",
@@ -10486,7 +10486,7 @@
10486
10486
  ]
10487
10487
  },
10488
10488
  "description": {
10489
- "description": "Prose about what this value is, for whoever meets it in the console later. It changes nothing the robot does, so a publish that touches only it pushes no configuration at all — but it is carried verbatim into `robot_describe`, where a model that has never seen this robot reads it. The datapoint is offered whenever the role grants it; without one it is offered with `description: null` and the model has less to go on, as for actions, services, publishers and cameras. Omission is the only way to say nothing; an empty string is refused, here and on all five.",
10489
+ "description": "Prose about what this value is, for whoever meets it in the console. It changes nothing the robot does, so a publish that touches only it pushes no configuration at all — but it is carried verbatim into `robot_describe`, where a model that has never seen this robot reads it. The datapoint is offered whenever the role grants it; without one it is offered with `description: null` and the model has less to go on, as for actions, services, publishers and cameras. Omission is the only way to say nothing; an empty string is refused, here and on all five.",
10490
10490
  "examples": [
10491
10491
  "What this value is, for whoever meets it in the console."
10492
10492
  ],
@@ -11583,7 +11583,7 @@
11583
11583
  ]
11584
11584
  },
11585
11585
  "description": {
11586
- "description": "Prose about what this value is, for whoever meets it in the console later. It changes nothing the robot does, so a publish that touches only it pushes no configuration at all — but it is carried verbatim into `robot_describe`, where a model that has never seen this robot reads it. The datapoint is offered whenever the role grants it; without one it is offered with `description: null` and the model has less to go on, as for actions, services, publishers and cameras. Omission is the only way to say nothing; an empty string is refused, here and on all five.",
11586
+ "description": "Prose about what this value is, for whoever meets it in the console. It changes nothing the robot does, so a publish that touches only it pushes no configuration at all — but it is carried verbatim into `robot_describe`, where a model that has never seen this robot reads it. The datapoint is offered whenever the role grants it; without one it is offered with `description: null` and the model has less to go on, as for actions, services, publishers and cameras. Omission is the only way to say nothing; an empty string is refused, here and on all five.",
11587
11587
  "examples": [
11588
11588
  "What this value is, for whoever meets it in the console."
11589
11589
  ],
@@ -12809,7 +12809,7 @@
12809
12809
  "type": "string",
12810
12810
  "format": "uuid",
12811
12811
  "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)$",
12812
- "description": "The key row, and what the rotate and delete routes address. It is not the key: the secret itself is never carried by this shape."
12812
+ "description": "The key row, and what the rotate and delete routes address. It is not the key: this shape never carries the secret."
12813
12813
  },
12814
12814
  "app_id": {
12815
12815
  "type": "string",
@@ -12976,13 +12976,13 @@
12976
12976
  "description": "The datapoint this value belongs to."
12977
12977
  },
12978
12978
  "value": {
12979
- "description": "The value itself, shaped by the datapoint: a number, a boolean, a string, or the whole ROS message where the configuration names no field inside it. Any `scale` and `offset` the configuration declares have already been applied, at the robot."
12979
+ "description": "The value, shaped by the datapoint: a number, a boolean, a string, or the whole ROS message where the configuration names no field inside it. Any `scale` and `offset` the configuration declares have already been applied, at the robot."
12980
12980
  },
12981
12981
  "timestamp_ms": {
12982
12982
  "type": "integer",
12983
12983
  "minimum": 0,
12984
12984
  "maximum": 9007199254740991,
12985
- "description": "When the value was captured, as a unix timestamp in milliseconds. This is the **bridge's capture time**, never the time the cloud received it — the one exception is the built-in `bridge_state`, which the cloud observes by construction."
12985
+ "description": "When the value was captured, as a unix timestamp in milliseconds. The **bridge's capture time**, never the time the cloud received it — the one exception is the built-in `bridge_state`, which the cloud observes by construction."
12986
12986
  }
12987
12987
  },
12988
12988
  "required": [
@@ -13004,10 +13004,10 @@
13004
13004
  "minLength": 1,
13005
13005
  "maxLength": 2000
13006
13006
  },
13007
- "description": "Where the authorization code may be returned, and the one field a registration cannot omit. Each must be an `https` URL, or `http` on an explicit loopback address for a native app that cannot hold a certificate, and none may carry a fragment. There must be between `1` and `5` of them; duplicates are collapsed rather than counted twice. Matched **exactly** at the authorize step against what was registered here."
13007
+ "description": "Where the authorization code may be returned, and the one field a registration cannot omit. Each must be an `https` URL, or `http` on an explicit loopback address for a native app that cannot hold a certificate, and none may carry a fragment. Between `1` and `5` of them; duplicates are collapsed rather than counted twice. Matched **exactly** at the authorize step against what was registered here."
13008
13008
  },
13009
13009
  "client_name": {
13010
- "description": "The name the client calls itself. Optional — a registration without one is recorded under a default name, per RFC 7591's making every metadata field optional. It is **not** vouched for by Fleetless and must never be rendered as if it were: a self-registered client chooses this string, and one has called itself *\"Fleetless Official Helper\"*.",
13010
+ "description": "The name the client calls itself. Optional: RFC 7591 makes every metadata field optional, so a registration without one is recorded under a default name. It is **not** vouched for by Fleetless and must never be rendered as if it were: a self-registered client chooses this string, and one has called itself *\"Fleetless Official Helper\"*.",
13011
13011
  "type": "string",
13012
13012
  "minLength": 1,
13013
13013
  "maxLength": 200
@@ -13351,7 +13351,7 @@
13351
13351
  "type": "string",
13352
13352
  "format": "uuid",
13353
13353
  "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)$",
13354
- "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at rather than being a filter it applies."
13354
+ "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at, not a filter it applies."
13355
13355
  },
13356
13356
  "email": {
13357
13357
  "type": "string",
@@ -13378,7 +13378,7 @@
13378
13378
  "owner",
13379
13379
  "developer"
13380
13380
  ],
13381
- "description": "The console powers this person holds. **Required** — every Fleetless user is a member of the team and has a tier; the optional version of this field existed only while the org also held people with no console powers to grade, and that pool is gone."
13381
+ "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."
13382
13382
  },
13383
13383
  "created_at": {
13384
13384
  "type": "string",
@@ -13415,7 +13415,7 @@
13415
13415
  "type": "string",
13416
13416
  "format": "uuid",
13417
13417
  "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)$",
13418
- "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at rather than being a filter it applies."
13418
+ "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at, not a filter it applies."
13419
13419
  },
13420
13420
  "email": {
13421
13421
  "type": "string",
@@ -13442,7 +13442,7 @@
13442
13442
  "owner",
13443
13443
  "developer"
13444
13444
  ],
13445
- "description": "The console powers this person holds. **Required** — every Fleetless user is a member of the team and has a tier; the optional version of this field existed only while the org also held people with no console powers to grade, and that pool is gone."
13445
+ "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."
13446
13446
  },
13447
13447
  "created_at": {
13448
13448
  "type": "string",
@@ -13747,7 +13747,7 @@
13747
13747
  "type": "string",
13748
13748
  "format": "uuid",
13749
13749
  "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)$",
13750
- "description": "The job's id, minted by the cloud when the invocation is accepted. Informative: state is observed by slug, and this id is what a cancel names when a caller wants to stop one specific job rather than whatever is running."
13750
+ "description": "The job's id, minted by the cloud when the invocation is accepted. Informative — state is observed by slug; a cancel names this id to stop one specific job rather than whatever is running."
13751
13751
  },
13752
13752
  "robot_id": {
13753
13753
  "type": "string",
@@ -13771,13 +13771,13 @@
13771
13771
  "cancelled",
13772
13772
  "lost"
13773
13773
  ],
13774
- "description": "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `lost` is a real outcome — the bridge restarted mid-job and the result is gone — and is said out loud rather than left reading `running` because nobody contradicted it."
13774
+ "description": "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `lost` is a real outcome — the bridge restarted mid-job and the result is gone — stated rather than left reading `running` by default."
13775
13775
  },
13776
13776
  "started_at": {
13777
13777
  "type": "string",
13778
13778
  "format": "date-time",
13779
13779
  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
13780
- "description": "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge it is **adoption time**, not the real start, because the cloud never minted it and has no honest alternative."
13780
+ "description": "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge, this is **adoption time**, not the real start — the cloud never minted it."
13781
13781
  },
13782
13782
  "updated_at": {
13783
13783
  "type": "string",
@@ -13865,7 +13865,7 @@
13865
13865
  "type": "object",
13866
13866
  "properties": {
13867
13867
  "result": {
13868
- "description": "What the service returned, shaped by the ROS service itself. A service call is awaited to completion, so there is no job to observe afterwards and no id to hold on to."
13868
+ "description": "What the service returned, shaped by the ROS service. A service call is awaited to completion, so there is no job to observe afterwards and no id to hold on to."
13869
13869
  }
13870
13870
  },
13871
13871
  "required": [
@@ -13909,7 +13909,7 @@
13909
13909
  "type": "string",
13910
13910
  "format": "uuid",
13911
13911
  "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)$",
13912
- "description": "The job's id, minted by the cloud when the invocation is accepted. Informative: state is observed by slug, and this id is what a cancel names when a caller wants to stop one specific job rather than whatever is running."
13912
+ "description": "The job's id, minted by the cloud when the invocation is accepted. Informative — state is observed by slug; a cancel names this id to stop one specific job rather than whatever is running."
13913
13913
  },
13914
13914
  "robot_id": {
13915
13915
  "type": "string",
@@ -13933,13 +13933,13 @@
13933
13933
  "cancelled",
13934
13934
  "lost"
13935
13935
  ],
13936
- "description": "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `lost` is a real outcome — the bridge restarted mid-job and the result is gone — and is said out loud rather than left reading `running` because nobody contradicted it."
13936
+ "description": "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `lost` is a real outcome — the bridge restarted mid-job and the result is gone — stated rather than left reading `running` by default."
13937
13937
  },
13938
13938
  "started_at": {
13939
13939
  "type": "string",
13940
13940
  "format": "date-time",
13941
13941
  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
13942
- "description": "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge it is **adoption time**, not the real start, because the cloud never minted it and has no honest alternative."
13942
+ "description": "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge, this is **adoption time**, not the real start — the cloud never minted it."
13943
13943
  },
13944
13944
  "updated_at": {
13945
13945
  "type": "string",
@@ -14031,7 +14031,7 @@
14031
14031
  "type": "string",
14032
14032
  "format": "uuid",
14033
14033
  "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)$",
14034
- "description": "The run's id, which is the same id the invocation was answered with — so a caller that kept a job id can find its durable record here later."
14034
+ "description": "The run's id — the same id the invocation was answered with, so a caller that kept a job id can find its durable record here later."
14035
14035
  },
14036
14036
  "robot_id": {
14037
14037
  "type": "string",
@@ -14148,7 +14148,7 @@
14148
14148
  "app_user",
14149
14149
  "server_key"
14150
14150
  ],
14151
- "description": "What the caller was acting as: a `developer` in the console, an `app_user` of one app, or a `server_key` used by server-side code. A bridge invokes nothing, so it is deliberately not a case here. `end_user` appears only on runs recorded before app users replaced the organisation-wide user pool — it is kept so a history page can still render them, and nothing writes it any more."
14151
+ "description": "What the caller was acting as: a `developer` in the console, an `app_user` of one app, or a `server_key` used by server-side code. A bridge invokes nothing, so it is deliberately not a case here. `end_user` appears only on runs recorded before app users replaced the organisation-wide user pool — kept so old runs still render; nothing writes it now."
14152
14152
  },
14153
14153
  "id": {
14154
14154
  "type": "string",
@@ -14416,12 +14416,12 @@
14416
14416
  "type": "null"
14417
14417
  }
14418
14418
  ],
14419
- "description": "What the client calls itself, or `null` when its registration is gone and there is no longer anything to have named. **Unverified** — see `client_name_verified`."
14419
+ "description": "What the client calls itself, or `null` once its registration is gone. **Unverified** — see `client_name_verified`."
14420
14420
  },
14421
14421
  "client_name_verified": {
14422
14422
  "type": "boolean",
14423
14423
  "const": false,
14424
- "description": "Always `false`. The client registered itself without authentication and chose this name about itself, so it must be rendered as a claim and never as an identity. There is no verified case, which is why this is a literal and not a boolean: a `true` branch would be dead code that looked like a safeguard."
14424
+ "description": "Always `false`. The client registered itself without authentication and named itself, so it must be rendered as a claim and never as an identity. There is no verified case, which is why this is a literal and not a boolean: a `true` branch would be dead code that looked like a safeguard."
14425
14425
  },
14426
14426
  "granted_at": {
14427
14427
  "type": "string",
@@ -14611,7 +14611,7 @@
14611
14611
  "description": "The PKCE verifier whose `S256` hash was sent as the challenge at the authorize step. Between `43` and `128` unreserved characters, per RFC 7636 §4.1 — it is compared rather than parsed, so a length nobody checks is a length an attacker chooses. PKCE is mandatory for every client under OAuth 2.1."
14612
14612
  },
14613
14613
  "resource": {
14614
- "description": "The resource the token is being requested for, per RFC 8707. It must match the audience the code was authorized for, or the answer is `invalid_target`; omitted, the code's own audience stands. It becomes the token's `aud`, and a resource refuses a token whose audience names something else — which is what keeps a token minted for one app out of another app's endpoint.",
14614
+ "description": "The resource the token is requested for, per RFC 8707. It must match the audience the code was authorized for, or the answer is `invalid_target`; omitted, the code's own audience stands. It becomes the token's `aud`, and a resource refuses a token whose audience names something else — which is what keeps a token minted for one app out of another app's endpoint.",
14615
14615
  "type": "string",
14616
14616
  "format": "uri"
14617
14617
  }
@@ -15357,7 +15357,7 @@
15357
15357
  "created_at"
15358
15358
  ],
15359
15359
  "additionalProperties": false,
15360
- "description": "The organisation as it now stands, after the patch was applied. The whole resource comes back, not only the fields that changed."
15360
+ "description": "The organisation as it now stands, after the patch. The whole resource comes back, not only the changed fields."
15361
15361
  }
15362
15362
  },
15363
15363
  "required": [
@@ -15410,7 +15410,7 @@
15410
15410
  "created_at"
15411
15411
  ],
15412
15412
  "additionalProperties": false,
15413
- "description": "The robot as it now stands, after the patch was applied. The whole resource comes back, not only the fields that changed."
15413
+ "description": "The robot as it now stands, after the patch. The whole resource comes back, not only the changed fields."
15414
15414
  }
15415
15415
  },
15416
15416
  "required": [
@@ -16236,7 +16236,7 @@
16236
16236
  "type": "string",
16237
16237
  "format": "uuid",
16238
16238
  "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)$",
16239
- "description": "The job's id, minted by the cloud when the invocation is accepted. Informative: state is observed by slug, and this id is what a cancel names when a caller wants to stop one specific job rather than whatever is running."
16239
+ "description": "The job's id, minted by the cloud when the invocation is accepted. Informative — state is observed by slug; a cancel names this id to stop one specific job rather than whatever is running."
16240
16240
  },
16241
16241
  "robot_id": {
16242
16242
  "type": "string",
@@ -16260,13 +16260,13 @@
16260
16260
  "cancelled",
16261
16261
  "lost"
16262
16262
  ],
16263
- "description": "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `lost` is a real outcome — the bridge restarted mid-job and the result is gone — and is said out loud rather than left reading `running` because nobody contradicted it."
16263
+ "description": "Where the job stands: `running`, `succeeded`, `failed`, `cancelled` or `lost`. `lost` is a real outcome — the bridge restarted mid-job and the result is gone — stated rather than left reading `running` by default."
16264
16264
  },
16265
16265
  "started_at": {
16266
16266
  "type": "string",
16267
16267
  "format": "date-time",
16268
16268
  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
16269
- "description": "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge it is **adoption time**, not the real start, because the cloud never minted it and has no honest alternative."
16269
+ "description": "When the cloud minted this job, as an ISO 8601 timestamp. For a job adopted from a reconnecting bridge, this is **adoption time**, not the real start — the cloud never minted it."
16270
16270
  },
16271
16271
  "updated_at": {
16272
16272
  "type": "string",
@@ -16470,7 +16470,7 @@
16470
16470
  },
16471
16471
  "builtin": {
16472
16472
  "type": "boolean",
16473
- "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, because no route renames or deletes any role."
16473
+ "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."
16474
16474
  }
16475
16475
  },
16476
16476
  "required": [
@@ -16509,7 +16509,7 @@
16509
16509
  },
16510
16510
  "builtin": {
16511
16511
  "type": "boolean",
16512
- "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, because no route renames or deletes any role."
16512
+ "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."
16513
16513
  }
16514
16514
  },
16515
16515
  "required": [
@@ -16600,7 +16600,7 @@
16600
16600
  "type": "string",
16601
16601
  "format": "uuid",
16602
16602
  "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)$",
16603
- "description": "The key row, and what the rotate and delete routes address. It is not the key: the secret itself is never carried by this shape."
16603
+ "description": "The key row, and what the rotate and delete routes address. It is not the key: this shape never carries the secret."
16604
16604
  },
16605
16605
  "app_id": {
16606
16606
  "type": "string",
@@ -16643,7 +16643,7 @@
16643
16643
  ],
16644
16644
  "additionalProperties": false
16645
16645
  },
16646
- "description": "The app's server keys as metadata, oldest first by `created_at`. The raw secret is not here and never will be: it exists once, in the answer to the request that created or rotated the key."
16646
+ "description": "The app's server keys as metadata, oldest first by `created_at`. The raw secret is not here and never will be: it exists once, in the response that created or rotated the key."
16647
16647
  }
16648
16648
  },
16649
16649
  "required": [
@@ -16748,7 +16748,7 @@
16748
16748
  "type": "string",
16749
16749
  "format": "uuid",
16750
16750
  "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)$",
16751
- "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at rather than being a filter it applies."
16751
+ "description": "The organisation this person belongs to. Every developer route is already scoped to the caller's org, so this confirms what a client is looking at, not a filter it applies."
16752
16752
  },
16753
16753
  "email": {
16754
16754
  "type": "string",
@@ -16775,7 +16775,7 @@
16775
16775
  "owner",
16776
16776
  "developer"
16777
16777
  ],
16778
- "description": "The console powers this person holds. **Required** — every Fleetless user is a member of the team and has a tier; the optional version of this field existed only while the org also held people with no console powers to grade, and that pool is gone."
16778
+ "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."
16779
16779
  },
16780
16780
  "created_at": {
16781
16781
  "type": "string",
@@ -1006,7 +1006,7 @@
1006
1006
  },
1007
1007
  {
1008
1008
  "name": "clientId",
1009
- "description": "The MCP client, as `GET /api/apps/:id/users/:userId/mcp-grants` reports its `client_id`. Not a uuid — it is the identifier the dynamic registration issued."
1009
+ "description": "The MCP client, as `GET /api/apps/:id/users/:userId/mcp-grants` reports its `client_id`. Not a uuid — the identifier dynamic registration issued."
1010
1010
  }
1011
1011
  ],
1012
1012
  "query": null,
@@ -2995,7 +2995,7 @@
2995
2995
  "params": [
2996
2996
  {
2997
2997
  "name": "clientId",
2998
- "description": "The MCP client, as `GET /api/client/mcp/grants` reports its `client_id`. Not a uuid — it is the identifier the dynamic registration issued."
2998
+ "description": "The MCP client, as `GET /api/client/mcp/grants` reports its `client_id`. Not a uuid — the identifier dynamic registration issued."
2999
2999
  }
3000
3000
  ],
3001
3001
  "query": null,
@@ -3807,7 +3807,7 @@
3807
3807
  },
3808
3808
  {
3809
3809
  "name": "slug",
3810
- "description": "The action or service slug from the published configuration; the cloud already knows which kind it is."
3810
+ "description": "The action or service slug from the published configuration — the cloud already knows which kind."
3811
3811
  }
3812
3812
  ],
3813
3813
  "query": null,