@fleetless/contracts 1.0.5 → 1.1.0

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 (96) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/CONTRIBUTING.md +100 -75
  3. package/README.md +69 -83
  4. package/SECURITY.md +24 -24
  5. package/artifacts/openapi.json +359 -65
  6. package/artifacts/routes.json +74 -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/client-robot-list-item.schema.json +70 -0
  27. package/artifacts/schema/client-robot-list-response.schema.json +83 -0
  28. package/artifacts/schema/cloud-config.schema.json +1 -1
  29. package/artifacts/schema/command-result.schema.json +3 -3
  30. package/artifacts/schema/config-draft-response.schema.json +1 -1
  31. package/artifacts/schema/config-version-response.schema.json +1 -1
  32. package/artifacts/schema/create-server-key-response.schema.json +1 -1
  33. package/artifacts/schema/datapoint-config.schema.json +1 -1
  34. package/artifacts/schema/datapoint-value.schema.json +2 -2
  35. package/artifacts/schema/dynamic-client-registration-request.schema.json +2 -2
  36. package/artifacts/schema/fleetless-user-list-response.schema.json +2 -2
  37. package/artifacts/schema/fleetless-user.schema.json +2 -2
  38. package/artifacts/schema/invoke-or-service-response.schema.json +4 -4
  39. package/artifacts/schema/invoke-response.schema.json +3 -3
  40. package/artifacts/schema/job-actor.schema.json +1 -1
  41. package/artifacts/schema/job-event.schema.json +3 -3
  42. package/artifacts/schema/job-response.schema.json +3 -3
  43. package/artifacts/schema/job-run-list-response.schema.json +2 -2
  44. package/artifacts/schema/job-run.schema.json +2 -2
  45. package/artifacts/schema/job.schema.json +3 -3
  46. package/artifacts/schema/mcp-consent-grant-list-response.schema.json +2 -2
  47. package/artifacts/schema/mcp-consent-grant.schema.json +2 -2
  48. package/artifacts/schema/oauth-authorize-query.schema.json +1 -1
  49. package/artifacts/schema/oauth-token-request.schema.json +1 -1
  50. package/artifacts/schema/patch-org-response.schema.json +1 -1
  51. package/artifacts/schema/patch-robot-response.schema.json +1 -1
  52. package/artifacts/schema/robot-config-doc.schema.json +1 -1
  53. package/artifacts/schema/robot-jobs-response.schema.json +3 -3
  54. package/artifacts/schema/role-list-response.schema.json +1 -1
  55. package/artifacts/schema/role.schema.json +1 -1
  56. package/artifacts/schema/server-key-list-response.schema.json +2 -2
  57. package/artifacts/schema/server-key.schema.json +1 -1
  58. package/artifacts/schema/service-call-response.schema.json +1 -1
  59. package/artifacts/schema/sign-up-response.schema.json +2 -2
  60. package/artifacts/schema/urdf-completeness.schema.json +2 -2
  61. package/artifacts/schema-outgoing/bridge-asset-progress.schema.json +1 -1
  62. package/dist/alerts.d.ts +15 -17
  63. package/dist/alerts.js +15 -17
  64. package/dist/app-users.d.ts +5 -6
  65. package/dist/app-users.js +9 -10
  66. package/dist/apps.d.ts +5 -6
  67. package/dist/apps.js +11 -12
  68. package/dist/assets.js +10 -13
  69. package/dist/audit.d.ts +10 -12
  70. package/dist/audit.js +14 -17
  71. package/dist/client-auth.d.ts +8 -9
  72. package/dist/client-auth.js +14 -15
  73. package/dist/client-robots.d.ts +37 -0
  74. package/dist/client-robots.js +30 -0
  75. package/dist/config-issues.d.ts +3 -3
  76. package/dist/config-issues.js +3 -3
  77. package/dist/config.d.ts +5 -6
  78. package/dist/config.js +7 -8
  79. package/dist/errors.d.ts +4 -4
  80. package/dist/errors.js +8 -9
  81. package/dist/identity.d.ts +4 -5
  82. package/dist/identity.js +7 -8
  83. package/dist/index.d.ts +3 -1
  84. package/dist/index.js +2 -1
  85. package/dist/jobs.js +5 -5
  86. package/dist/mcp.d.ts +11 -9
  87. package/dist/mcp.js +8 -3
  88. package/dist/oauth.d.ts +8 -10
  89. package/dist/oauth.js +13 -15
  90. package/dist/protocol.d.ts +7 -8
  91. package/dist/protocol.js +20 -22
  92. package/dist/realtime.d.ts +2 -2
  93. package/dist/realtime.js +4 -4
  94. package/dist/rest.js +4 -4
  95. package/dist/routes.js +40 -4
  96. package/package.json +1 -1
package/dist/protocol.js CHANGED
@@ -10,8 +10,8 @@ import { rosTypeName } from './common.js';
10
10
  * Bridge <-> cloud protocol, version 2.
11
11
  *
12
12
  * The version is exchanged in the hello handshake; the cloud refuses an
13
- * incompatible bridge with a clear message: `protocol_mismatch`, which names
14
- * both versions and reaches the robot's detail view as `last_hello_error`.
13
+ * incompatible bridge: `protocol_mismatch`, which names both versions and
14
+ * reaches the robot's detail view as `last_hello_error`.
15
15
  *
16
16
  * **2 (2026-08-21):** `config_applied.errors` entries gained `kind` and `code`
17
17
  * beside `message`. The check is `!==`, not a floor, so a bridge that is not
@@ -78,12 +78,11 @@ export { slug } from './common.js';
78
78
  *
79
79
  * It carries the **slug and the state**, not only the id, because the cloud's
80
80
  * reconciliation needs both and had neither. Reading `active_job_ids` as bare
81
- * uuids, a restarted cloud could answer exactly one question — "is this job
82
- * still alive?" — for jobs it already knew about. It could not name what the
83
- * robot is doing, could not tell a job that is still `running` from one that
84
- * finished while the cloud was down, and had nothing at all to say about a
85
- * job it never recorded because it crashed between minting the id and writing
86
- * the row.
81
+ * uuids, a restarted cloud could only ask "is this job still alive?" for jobs
82
+ * it already knew about — not what the robot is doing, not whether a
83
+ * `running` job had actually finished while the cloud was down, and nothing
84
+ * at all about a job it never recorded because it crashed between minting the
85
+ * id and writing the row.
87
86
  *
88
87
  * `state` is the bridge's own current answer, not a history. A bridge that
89
88
  * has a terminal result still in hand reports it here and the cloud writes it
@@ -103,22 +102,21 @@ export const bridgeHello = z.object({
103
102
  /**
104
103
  * Every job this bridge still knows about, right now.
105
104
  *
106
- * A reconnect and a restart look **identical** on the wire otherwise: same
107
- * token, same version, same frame. But they must end differently — after a
108
- * dropped connection the running jobs are still running, after a restart
109
- * their results are gone forever. Asking the bridge to enumerate what it
110
- * still has settles it without either side guessing: the cloud marks every
111
- * job it believes is running on this robot and that is *not* named here as
112
- * `lost`.
105
+ * A reconnect and a restart look **identical** on the wire — same token,
106
+ * same version, same frame — but must end differently: after a dropped
107
+ * connection the running jobs are still running, after a restart their
108
+ * results are gone forever. Enumerating what the bridge still has settles
109
+ * it without either side guessing: the cloud marks every job it believed
110
+ * running that is *not* named here as `lost`.
113
111
  *
114
- * This deliberately needs no persistence at the bridge. A live process
115
- * lists its live jobs; a process that just started lists none, because it
116
- * has none — which is exactly the truth the cloud needs. A breadcrumb file
117
- * would only add a window in which the crash beat the write.
112
+ * Deliberately needs no persistence at the bridge: a live process lists its
113
+ * live jobs, a process that just started lists none — exactly the truth
114
+ * the cloud needs. A breadcrumb file would only add a window in which the
115
+ * crash beat the write.
118
116
  *
119
- * Defaulted, so a bridge that sends no such field still parses; a bridge
120
- * with no jobs and a bridge that does not report them both mean the cloud
121
- * has nothing to keep alive.
117
+ * Defaulted, so a bridge that sends no such field still parses; no jobs
118
+ * and no report both mean the same thing to the cloud: nothing to keep
119
+ * alive.
122
120
  */
123
121
  active_jobs: z.array(activeJob).max(500).default([]),
124
122
  });
@@ -254,8 +254,8 @@ export type DatapointEvent = z.infer<typeof datapointEvent>;
254
254
  */
255
255
  export declare const liveSessionEndReason: z.ZodEnum<{
256
256
  unknown: "unknown";
257
- robot_offline: "robot_offline";
258
257
  publish_failed: "publish_failed";
258
+ robot_offline: "robot_offline";
259
259
  released_by_peer: "released_by_peer";
260
260
  config_changed: "config_changed";
261
261
  revoked: "revoked";
@@ -285,8 +285,8 @@ export declare const liveSessionEvent: z.ZodObject<{
285
285
  state: z.ZodLiteral<"ended">;
286
286
  reason: z.ZodEnum<{
287
287
  unknown: "unknown";
288
- robot_offline: "robot_offline";
289
288
  publish_failed: "publish_failed";
289
+ robot_offline: "robot_offline";
290
290
  released_by_peer: "released_by_peer";
291
291
  config_changed: "config_changed";
292
292
  revoked: "revoked";
package/dist/realtime.js CHANGED
@@ -324,10 +324,10 @@ export const liveSessionEvent = z.object({
324
324
  /**
325
325
  * **Classified text the cloud produced, never text the robot sent.**
326
326
  *
327
- * It is **not** the robot's own words. Nothing sanitises
328
- * `bridgeCameraState.error.message`, and a camera password reaches a
329
- * developer surface through exactly that route — which is why the cloud maps
330
- * a robot's diagnosis to fixed strings rather than forwarding it.
327
+ * Nothing sanitises `bridgeCameraState.error.message`, and a camera
328
+ * password reaches a developer surface through exactly that route — which
329
+ * is why the cloud maps a robot's diagnosis to fixed strings rather than
330
+ * forwarding it.
331
331
  *
332
332
  * So: `null` unless the cloud itself has something classified to say. If a
333
333
  * developer needs the robot's own diagnosis later, it arrives as a mapped
package/dist/rest.js CHANGED
@@ -23,7 +23,7 @@ export const robot = z.object({
23
23
  /** What `PATCH /api/robots/:id` answers: the robot as it now stands. */
24
24
  export const patchRobotResponse = z.object({
25
25
  robot: robot.meta({
26
- description: 'The robot as it now stands, after the patch was applied. The whole resource comes back, not only the fields that changed.',
26
+ description: 'The robot as it now stands, after the patch. The whole resource comes back, not only the changed fields.',
27
27
  }),
28
28
  });
29
29
  export const createRobotRequest = z.object({
@@ -85,10 +85,10 @@ export const robotListResponse = z.object({
85
85
  export const datapointValue = z.object({
86
86
  slug: slug.meta({ description: 'The datapoint this value belongs to.' }),
87
87
  value: z.unknown().meta({
88
- 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.',
88
+ 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.',
89
89
  }),
90
90
  timestamp_ms: z.number().int().nonnegative().meta({
91
- 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.',
91
+ 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.',
92
92
  }),
93
93
  });
94
94
  /* ------------------------------------------------------------------------
@@ -396,7 +396,7 @@ export const invokeResponse = z.object({
396
396
  /** A service call answers with its result directly — no job to observe. */
397
397
  export const serviceCallResponse = z.object({
398
398
  result: z.unknown().meta({
399
- 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.',
399
+ 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.',
400
400
  }),
401
401
  });
402
402
  /**
package/dist/routes.js CHANGED
@@ -4,10 +4,11 @@ import { alertListResponse, orgAlertsQuery, orgFiringAlertsResponse } from './al
4
4
  import { asset, assetListResponse, assetSyncRequest, assetSyncResponse, assetSyncStatus, missingAssetQuery } from './assets.js';
5
5
  import { auditListResponse, auditQuery } from './audit.js';
6
6
  import { CLIENT_OIDC_CALLBACK_PATH, clientAcceptInvitationRequest, clientIdentity, clientLoginRequest, clientLogoutRequest, clientMcpInteraction, clientMcpInteractionDecisionResponse, clientOidcCallbackQuery, clientOidcExchangeRequest, clientOidcStartQuery, clientPasswordResetConfirmRequest, clientPasswordResetRequest, clientProviderListQuery, clientProviderListResponse, clientRefreshRequest, clientRegisterRequest, clientResendVerificationRequest, clientVerifyEmailRequest, mcpConsentGrantListResponse, } from './client-auth.js';
7
+ import { clientRobotListResponse } from './client-robots.js';
7
8
  import { appAuthConfig, appInvitation, appInvitationListResponse, appMailTemplate, appMailTemplateListResponse, appOidcProvider, appOidcProviderListResponse, appUser, appUserListResponse, createAppInvitationRequest, createAppOidcProviderRequest, createAppUserRequest, mailOutcome, mailTemplatePreviewRequest, mailTemplatePreviewResponse, patchAppOidcProviderRequest, patchAppUserRequest, putAppAuthConfigRequest, putAppMailTemplateRequest, } from './app-users.js';
8
9
  import { acceptTeamInviteRequest, authMeResponse, createTeamInviteRequest, fleetlessUser, fleetlessUserListResponse, passwordChangeRequest, passwordResetConfirm, passwordResetRequest, patchAuthMeRequest, patchFleetlessUserRequest, patchOrgRequest, patchOrgResponse, pendingTeamInviteListResponse, refreshRequest, sessionTokens, signUpRequest, signUpResponse, teamInvite, tierChangeRequest, waitlistRequest, } from './identity.js';
9
10
  import { jobRunListResponse, jobRunQuery, jobRunSummary, jobRunSummaryQuery } from './jobs.js';
10
- import { MCP_APP_PATHS, mcpRolePreviewResponse } from './mcp.js';
11
+ import { MCP_APP_PATHS, mcpRobotDatasheet, mcpRolePreviewResponse } from './mcp.js';
11
12
  import { authorizationServerMetadata, dynamicClientRegistrationRequest, dynamicClientRegistrationResponse, oauthAuthorizeQuery, oauthRedirectResponse, oauthTokenRequest, oauthTokenResponse, protectedResourceMetadata, } from './oauth.js';
12
13
  import { cameraListResponse, cancelRequest, configDraftResponse, configVersionResponse, configVersionsResponse, createRobotRequest, createRobotResponse, datapointListResponse, datapointValue, exposureListResponse, fetchTypesRequest, fetchTypesResponse, historyQuery, historyResponse, introspectionResponse, invokeOrServiceResponse, invokeRequest, jobResponse, liveSessionResponse, orgHealthQuery, orgLatencyQuery, orgLatencyResponse, orgQuotaUsage, orgUsageQuery, orgUsageResponse, patchRobotRequest, patchRobotResponse, publishConfigResponse, publishRequest, putConfigDraftRequest, putRobotDetailsRequest, putRobotDetailsResponse, releaseLiveQuery, renameSlugRequest, renameSlugResponse, robotDeleteQuery, resourceHealthListResponse, robotDeletionSummary, robotDetailResponse, robotJobsResponse, robotListResponse, slugUsageResponse, snapshotMetaResponse, typesResponse, } from './rest.js';
13
14
  export const ROUTE_SECTIONS = [
@@ -208,6 +209,14 @@ export const ROUTES = [
208
209
  'and splitting them here would tell a stranger which tokens ever existed. No rate limiter: the GET changes nothing, and the POST it ' +
209
210
  'leads to is limited per IP.',
210
211
  },
212
+ {
213
+ method: 'GET', path: '/favicon.svg', section: 'client-auth',
214
+ summary: 'Serves the Fleetless icon for the auth portal\'s and the MCP welcome page\'s browser tab.',
215
+ audience: 'internal', auth: 'none', rateLimited: false, ownerTier: false, status: 200,
216
+ params: [], query: null, request: null, response: null, errors: [], transport: 'http',
217
+ notes: 'An SVG, not JSON. Those pages carry a Content-Security-Policy that admits no `data:` image, so the icon is a file on their own ' +
218
+ 'origin — the one source `img-src \'self\'` names. Cached for a day: the bytes change when the brand does, not per deploy.',
219
+ },
211
220
  {
212
221
  method: 'POST', path: '/api/auth/password/reset/confirm', section: 'developer-auth',
213
222
  summary: 'Spends a reset token, sets the new password and ends every session of the account.',
@@ -509,7 +518,7 @@ export const ROUTES = [
509
518
  params: [
510
519
  { name: 'id', description: 'The app\'s uuid, as returned by `POST /api/apps` or listed by `GET /api/apps`.' },
511
520
  { name: 'userId', description: 'The app user\'s uuid, from `GET /api/apps/:id/users`; a user of another app answers `404`.' },
512
- { name: 'clientId', 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.' },
521
+ { name: 'clientId', 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.' },
513
522
  ],
514
523
  query: null, request: null, response: null,
515
524
  errors: [...DEVELOPER_GUARD, 'invalid_uuid', 'not_found'], transport: 'http',
@@ -1628,7 +1637,7 @@ export const ROUTES = [
1628
1637
  method: 'DELETE', path: '/api/client/mcp/grants/:clientId', section: 'client-auth',
1629
1638
  summary: 'Withdraws the signed-in app user\'s consent to one MCP client.',
1630
1639
  audience: 'client', auth: 'developer_or_client', rateLimited: false, ownerTier: false, status: 204,
1631
- params: [{ name: 'clientId', 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.' }],
1640
+ params: [{ name: 'clientId', description: 'The MCP client, as `GET /api/client/mcp/grants` reports its `client_id`. Not a uuid — the identifier dynamic registration issued.' }],
1632
1641
  query: null, request: null, response: null, errors: [...CLIENT_GUARD], transport: 'http',
1633
1642
  notes: 'The person\'s own door, beside the developer\'s `DELETE /api/apps/:id/users/:userId/mcp-grants/:clientId`. It acts on the bearer\'s ' +
1634
1643
  'own account and on no other — the path carries a client and never a subject — so there is no user for a caller to name and none to ' +
@@ -1750,6 +1759,33 @@ export const ROUTES = [
1750
1759
  '`404 unknown_datapoint` and a configured one with no sample yet is `404 no_data` — three facts a caller who is entitled to them needs ' +
1751
1760
  'told apart. The plane built-ins (`bridge_state`, `robot_details`) answer here too, without appearing in any document.',
1752
1761
  },
1762
+ /* ------------------------------------------ discovery: the REST twins of the two MCP tools a session starts from */
1763
+ {
1764
+ method: 'GET', path: '/api/client/robots', section: 'robots',
1765
+ summary: 'Lists the robots the caller reaches, with bridge state and the published configuration version.',
1766
+ audience: 'client', auth: 'developer_or_client', rateLimited: false, ownerTier: false, status: 200,
1767
+ params: [], query: null, request: null, response: clientRobotListResponse,
1768
+ errors: [...CLIENT_GUARD], transport: 'http',
1769
+ notes: '**The REST twin of the MCP tool `robots_list`**, and the one robot question no robot-scoped route can answer: which robots may I name ' +
1770
+ 'at all. An app user sees the robots their app attaches on which their role grants at least one slug or capability; a server key sees ' +
1771
+ 'every robot its app attaches; a developer bearer sees the organisation\'s robots. Name order, id as the tiebreak. A robot on which the ' +
1772
+ 'role grants nothing is absent rather than listed empty — the same answer `robots_list` gives, for the same reason: reach is a grant, ' +
1773
+ 'not an attachment. Under `/api/client/` because it names no robot; every robot-scoped read stays under `/api/robots/:id/…`.',
1774
+ },
1775
+ {
1776
+ method: 'GET', path: '/api/robots/:id/datasheet', section: 'robots',
1777
+ summary: 'Describes everything the caller\'s role lets them do on one robot, with parameter schemas.',
1778
+ audience: 'client', auth: 'developer_or_client', rateLimited: false, ownerTier: false, status: 200,
1779
+ params: [{ name: 'id', description: 'The robot\'s uuid, as `GET /api/client/robots` lists it.' }],
1780
+ query: null, request: null, response: mcpRobotDatasheet,
1781
+ errors: [...CLIENT_GUARD, 'invalid_uuid', 'not_found'], transport: 'http',
1782
+ notes: '**The REST twin of the MCP tool `robot_describe`**: one answer per robot — every datapoint, action, service, publisher and camera the ' +
1783
+ 'role grants, each with its `input_schema` where it takes parameters, plus the two capabilities that gate whole features, ' +
1784
+ '`action_history` and `assets`. A robot with nothing published answers an empty `exposures` list, never a refusal. A robot the caller ' +
1785
+ 'does not reach — not attached to their app, or attached with a role that grants nothing on it — answers `404` exactly as one that ' +
1786
+ 'does not exist. The app-user datapoint and camera listings under this prefix stay; this is the one read that also names actions, ' +
1787
+ 'services, publishers and capabilities, which is what an app needs before it can draw a screen.',
1788
+ },
1753
1789
  /* ------------------------------------------------- config (draft/publish) */
1754
1790
  {
1755
1791
  method: 'GET', path: '/api/robots/:id/config/draft', section: 'config',
@@ -1946,7 +1982,7 @@ export const ROUTES = [
1946
1982
  audience: 'client', auth: 'developer_or_client', rateLimited: false, ownerTier: false, status: 202,
1947
1983
  params: [
1948
1984
  { name: 'id', description: 'The robot\'s uuid; an end user reaches it through an app that attaches it.' },
1949
- { name: 'slug', description: 'The action or service slug from the published configuration; the cloud already knows which kind it is.' },
1985
+ { name: 'slug', description: 'The action or service slug from the published configuration — the cloud already knows which kind.' },
1950
1986
  ],
1951
1987
  query: null, request: invokeRequest, response: invokeOrServiceResponse,
1952
1988
  errors: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetless/contracts",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "Fleetless wire contracts: the bridge-cloud protocol, the REST API schemas and the error codes, as zod schemas with generated JSON Schema and OpenAPI artifacts.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Dehne Robotik GmbH",