@fleetless/contracts 1.0.0 → 1.0.2

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 (48) hide show
  1. package/CHANGELOG.md +68 -2
  2. package/CODE_OF_CONDUCT.md +83 -0
  3. package/CONTRIBUTING.md +136 -0
  4. package/README.md +49 -13
  5. package/SECURITY.md +55 -0
  6. package/artifacts/openapi.json +1 -1
  7. package/artifacts/routes.json +1 -1
  8. package/dist/alerts.d.ts +19 -24
  9. package/dist/alerts.js +18 -24
  10. package/dist/app-users.d.ts +7 -6
  11. package/dist/app-users.js +6 -6
  12. package/dist/apps.d.ts +21 -25
  13. package/dist/apps.js +40 -51
  14. package/dist/assets.d.ts +70 -132
  15. package/dist/assets.js +130 -223
  16. package/dist/audit.d.ts +11 -11
  17. package/dist/audit.js +25 -51
  18. package/dist/client-auth.d.ts +4 -4
  19. package/dist/client-auth.js +3 -4
  20. package/dist/common.d.ts +27 -35
  21. package/dist/common.js +26 -35
  22. package/dist/config-issues.d.ts +4 -3
  23. package/dist/config-issues.js +7 -6
  24. package/dist/config.d.ts +31 -37
  25. package/dist/config.js +81 -110
  26. package/dist/errors.d.ts +4 -3
  27. package/dist/errors.js +61 -87
  28. package/dist/identity.d.ts +18 -21
  29. package/dist/identity.js +17 -21
  30. package/dist/index.d.ts +4 -4
  31. package/dist/index.js +12 -13
  32. package/dist/introspection.d.ts +7 -6
  33. package/dist/introspection.js +6 -6
  34. package/dist/jobs.d.ts +12 -12
  35. package/dist/jobs.js +20 -25
  36. package/dist/mcp.d.ts +11 -12
  37. package/dist/mcp.js +10 -12
  38. package/dist/oauth.d.ts +13 -18
  39. package/dist/oauth.js +13 -19
  40. package/dist/protocol.d.ts +51 -62
  41. package/dist/protocol.js +107 -139
  42. package/dist/realtime.d.ts +53 -68
  43. package/dist/realtime.js +77 -103
  44. package/dist/rest.d.ts +182 -243
  45. package/dist/rest.js +301 -395
  46. package/dist/routes.d.ts +4 -3
  47. package/dist/routes.js +3 -2
  48. package/package.json +12 -7
@@ -1,11 +1,11 @@
1
+ // SPDX-License-Identifier: Apache-2.0
1
2
  import { z } from 'zod';
2
3
  /**
3
4
  * Bridge <-> cloud protocol, version 2.
4
5
  *
5
6
  * The version is exchanged in the hello handshake; the cloud refuses an
6
- * incompatible bridge with a clear message (spec §5) — `ws/bridge.ts`'s
7
- * `protocol_mismatch`, which names both versions and lands on the robot
8
- * detail page as `last_hello_error`.
7
+ * incompatible bridge with a clear message: `protocol_mismatch`, which names
8
+ * both versions and reaches the robot's detail view as `last_hello_error`.
9
9
  *
10
10
  * **2 (2026-08-21):** `config_applied.errors` entries gained `kind` and `code`
11
11
  * beside `message`. The check is `!==`, not a floor, so a bridge that is not
@@ -14,7 +14,7 @@ import { z } from 'zod';
14
14
  */
15
15
  export declare const PROTOCOL_VERSION = 2;
16
16
  /**
17
- * The bridge socket close code for "this robot no longer exists" (W6a).
17
+ * The bridge socket close code for "this robot no longer exists".
18
18
  *
19
19
  * Deliberately distinct from the auth failures: a deleted robot must **stop**,
20
20
  * and a token that was valid a second ago is indistinguishable from one that
@@ -26,42 +26,37 @@ export declare const PROTOCOL_VERSION = 2;
26
26
  export declare const CLOSE_ROBOT_DELETED = 4004;
27
27
  /**
28
28
  * How long a command waits for its answer when the caller names no patience
29
- * of its own (W6b).
29
+ * of its own.
30
30
  *
31
- * 15 s, which is what both halves already used independently: the cloud's
32
- * `commandTimeoutMs` and the bridge's `GOAL_ACCEPT_TIMEOUT_S`. That they
33
- * agreed was a coincidence of two separate decisions, and neither side could
34
- * be told otherwise for a single call. Naming the number once, here, is what
35
- * makes it one number rather than two that happen to match.
31
+ * 15 s, stated once here rather than once in the cloud and once in the bridge.
32
+ * Two constants that happen to match are not one number: neither side can be
33
+ * told otherwise for a single call, and when they drift nobody can say whose
34
+ * deadline a caller hit.
36
35
  *
37
- * A caller who knows their robot's work takes longer says so per call. A
38
- * caller who says nothing gets exactly today's behaviour — which is the point
39
- * of picking today's number as the default rather than a nicer one.
36
+ * A caller who knows their robot's work takes longer says so per call.
40
37
  */
41
38
  export declare const DEFAULT_PATIENCE_MS = 15000;
42
39
  /**
43
40
  * The longest patience a caller may ask for.
44
41
  *
45
- * A waiting REST request is a held-open connection, and there is **no rate
46
- * limiting** on this platform until W8 — so an unbounded `patience_ms` is an
47
- * unauthenticated way to pin the cloud's sockets open. Two minutes is long
48
- * enough for the robot work anybody has described (a planner, a docking
42
+ * A waiting REST request is a held-open connection, so an unbounded
43
+ * `patience_ms` is a way to pin the cloud's sockets open. Two minutes is long
44
+ * enough for the robot work this API is meant for (a planner, a docking
49
45
  * manoeuvre, an arm trajectory) and short enough that a thousand of them is
50
46
  * still a bounded amount of cloud.
51
47
  *
52
- * Raising it is a W8 conversation, after rate limiting exists — not a
53
- * one-line change here.
48
+ * Raising it is a conversation about rate limiting, not a one-line change
49
+ * here.
54
50
  */
55
51
  export declare const MAX_PATIENCE_MS = 120000;
56
52
  /**
57
53
  * The shortest patience a caller may ask for.
58
54
  *
59
- * A floor exists because **impatience reaches the robot**. Measured in W6b's
60
- * review: `patience_ms: 1` on an action makes the bridge report `goal_timeout`
61
- * and then issue a *corrective cancel* against a goal the action server
62
- * accepts a moment later — so a caller who asks for an unreachable deadline
63
- * does not merely get an error, they cause a cancellation on the machine.
64
- * Repeatable, and on a platform with no rate limiting until W8.
55
+ * A floor exists because **impatience reaches the robot**. A `patience_ms` of
56
+ * 1 on an action makes the bridge report `goal_timeout` and then issue a
57
+ * *corrective cancel* against a goal the action server accepts a moment later
58
+ * — so a caller who asks for an unreachable deadline does not merely get an
59
+ * error, they cause a cancellation on the machine.
65
60
  *
66
61
  * One second, because it has to be longer than a goal-acceptance round trip on
67
62
  * a healthy robot and shorter than any wait a human would call patient. It is
@@ -73,7 +68,7 @@ export declare const MIN_PATIENCE_MS = 1000;
73
68
  /** Re-exported so consumers keep importing wire names from one place. */
74
69
  export { slug } from './common.js';
75
70
  /**
76
- * One job the bridge still has, as reported in the handshake (W6b).
71
+ * One job the bridge still has, as reported in the handshake.
77
72
  *
78
73
  * It carries the **slug and the state**, not only the id, because the cloud's
79
74
  * reconciliation needs both and had neither. Reading `active_job_ids` as bare
@@ -134,7 +129,7 @@ export declare const cloudHelloError: z.ZodObject<{
134
129
  export type CloudHelloError = z.infer<typeof cloudHelloError>;
135
130
  /**
136
131
  * One datapoint sample. `timestamp_ms` is the capture time at the bridge —
137
- * never the receive time — so clients compute age themselves (spec §6.3).
132
+ * never the receive time — so clients compute age themselves.
138
133
  */
139
134
  export declare const datapointFrame: z.ZodObject<{
140
135
  type: z.ZodLiteral<"datapoint">;
@@ -160,9 +155,9 @@ export declare const bridgePong: z.ZodObject<{
160
155
  }, z.core.$strip>;
161
156
  export type BridgePong = z.infer<typeof bridgePong>;
162
157
  /**
163
- * The published configuration, cloud → bridge (spec §4.1: the bridge applies
164
- * the published version). Sent right after `hello_ok` and again on every
165
- * publish, so a bridge never has to ask.
158
+ * The published configuration, cloud → bridge — the bridge applies the
159
+ * published version. Sent right after `hello_ok` and again on every publish,
160
+ * so a bridge never has to ask.
166
161
  *
167
162
  * `version: 0` with an empty document means *nothing published yet* — a fresh
168
163
  * robot, not an error.
@@ -391,7 +386,7 @@ export declare const bridgeConfigApplied: z.ZodObject<{
391
386
  }, z.core.$strip>;
392
387
  export type BridgeConfigApplied = z.infer<typeof bridgeConfigApplied>;
393
388
  /**
394
- * Commands, cloud → bridge (spec §6.1, §11.3). The **cloud** mints the
389
+ * Commands, cloud → bridge. The **cloud** mints the
395
390
  * `job_id` before the bridge is asked to do anything, so a job exists —
396
391
  * and can be reported `lost` — even if the answer never comes back.
397
392
  */
@@ -404,13 +399,13 @@ export declare const cloudInvoke: z.ZodObject<{
404
399
  }, z.core.$strip>;
405
400
  export type CloudInvoke = z.infer<typeof cloudInvoke>;
406
401
  /**
407
- * Cancel — the bridge must issue a real ROS goal cancel (§11.3).
402
+ * Cancel — the bridge must issue a real ROS goal cancel.
408
403
  *
409
404
  * `slug` stays, and stays required: it is how the bridge finds the tracker,
410
405
  * and it is what a cancel with no id means.
411
406
  *
412
- * `job_id` is what W6b adds, and what makes a cancel say *which* job. Without
413
- * it a cancel arriving a moment after one job ended and another began on the
407
+ * `job_id` is what makes a cancel say *which* job. Without it a cancel
408
+ * arriving a moment after one job ended and another began on the
414
409
  * same slug stops the **new** one — the caller asked to stop something that
415
410
  * had already finished and stopped a machine that had just started moving.
416
411
  * That is not a race anybody had to lose: the caller knew the id, and the
@@ -437,7 +432,7 @@ export declare const cloudPublish: z.ZodObject<{
437
432
  export type CloudPublish = z.infer<typeof cloudPublish>;
438
433
  /**
439
434
  * Progress on a job, bridge → cloud. `timestamp_ms` is capture time, so a
440
- * burst delivered late after a reconnect is visibly late (§6.3).
435
+ * burst delivered late after a reconnect is visibly late.
441
436
  */
442
437
  export declare const bridgeJobUpdate: z.ZodObject<{
443
438
  type: z.ZodLiteral<"job_update">;
@@ -462,7 +457,7 @@ export declare const bridgeJobUpdate: z.ZodObject<{
462
457
  }, z.core.$strip>;
463
458
  export type BridgeJobUpdate = z.infer<typeof bridgeJobUpdate>;
464
459
  /**
465
- * Jobs the bridge can no longer account for **while connected** (§6.1) — a
460
+ * Jobs the bridge can no longer account for **while connected** — a
466
461
  * tracker dropped, an action server that vanished mid-goal, anything where
467
462
  * the honest answer is "I lost this" rather than a state.
468
463
  *
@@ -542,8 +537,8 @@ export declare const bridgeTypeDefinitions: z.ZodObject<{
542
537
  }, z.core.$strip>;
543
538
  export type BridgeTypeDefinitions = z.infer<typeof bridgeTypeDefinitions>;
544
539
  /**
545
- * The built-in `bridge_state` datapoint every robot has (spec §4.3):
546
- * connection status plus latency, the basis for offline-aware client UIs.
540
+ * The built-in `bridge_state` datapoint every robot has: connection status
541
+ * plus latency, the basis for offline-aware client UIs.
547
542
  */
548
543
  export declare const bridgeState: z.ZodObject<{
549
544
  online: z.ZodBoolean;
@@ -551,8 +546,7 @@ export declare const bridgeState: z.ZodObject<{
551
546
  }, z.core.$strip>;
552
547
  export type BridgeState = z.infer<typeof bridgeState>;
553
548
  /**
554
- * The built-in `bridge_pressure` datapoint (spec §4.3, the pressure-telemetry
555
- * design's "The decision that shapes everything"): the bridge's own
549
+ * The built-in `bridge_pressure` datapoint: the bridge's own
556
550
  * bandwidth-shaping state, sent on the same reserved-slug path as
557
551
  * `bridge_state` so history, realtime, REST and MCP exposure fall out of the
558
552
  * ordinary datapoint machinery for free.
@@ -621,13 +615,11 @@ export declare const PRESSURE_SLUG: "bridge_pressure";
621
615
  * Binary rather than base64 in a text frame, because base64 costs a third of
622
616
  * the robot's upstream for nothing. Self-contained rather than a JSON frame
623
617
  * followed by a binary one, because that pairing would depend on frame
624
- * ordering — and W4 established, at some cost, that ordering across a socket
625
- * is not something to lean on.
618
+ * ordering, and ordering across a socket is not something to lean on.
626
619
  *
627
- * `timestamp_ms` is the bridge's **capture** time (§6.3), which is what lets
628
- * every consumer state a snapshot's true age. A picture that lies about when
629
- * it was taken is this wave's version of a job that reads "running" when
630
- * nobody knows.
620
+ * `timestamp_ms` is the bridge's **capture** time, which is what lets every
621
+ * consumer state a snapshot's true age. A picture that lies about when it was
622
+ * taken is as bad as a job that reads "running" when nobody knows.
631
623
  */
632
624
  /**
633
625
  * The largest a snapshot frame — header and image bytes together — may be on
@@ -643,15 +635,13 @@ export declare const PRESSURE_SLUG: "bridge_pressure";
643
635
  * connection with 1009 — taking datapoints, jobs, commands and configuration
644
636
  * down with it. The bridge would then reconnect, receive the same
645
637
  * configuration, capture the same frame and be closed again: a robot that
646
- * will not stay online, from a configuration the platform accepted. Measured
647
- * during the W5 review, a 4K JPEG of real camera content lands around
648
- * 2.2 MiB and 1080p on a noisy scene within 40% of this number, so the margin
649
- * is thinner than it looks.
638
+ * will not stay online, from a configuration the platform accepted. The margin
639
+ * is thinner than it looks — a 4K JPEG of real camera content lands around
640
+ * 2.2 MiB, and 1080p on a noisy scene comes within half of this number.
650
641
  *
651
- * **The bridge must degrade rather than exceed it** — lower JPEG quality,
652
- * then downscale, and if it still does not fit, skip the frame and say so.
653
- * A missing snapshot is a gap, and this wave already established that a gap
654
- * is an honest answer; a closed socket is not.
642
+ * **The bridge must degrade rather than exceed it** — lower JPEG quality, then
643
+ * downscale, and if it still does not fit, skip the frame and say so. A missing
644
+ * snapshot is a gap, and a gap is an honest answer; a closed socket is not.
655
645
  */
656
646
  export declare const SNAPSHOT_MAX_BYTES = 1572864;
657
647
  export declare const snapshotHeader: z.ZodObject<{
@@ -667,7 +657,7 @@ export type SnapshotHeader = z.infer<typeof snapshotHeader>;
667
657
  * Cloud → bridge: start publishing this camera live.
668
658
  *
669
659
  * The **cloud** mints the room and the publisher token, for the same reason
670
- * it mints a `job_id` before asking anything (§6.1): the side that owns the
660
+ * it mints a `job_id` before asking anything: the side that owns the
671
661
  * refcount must own the identity of the stream, or a robot could end up
672
662
  * publishing into a room nobody is watching.
673
663
  */
@@ -680,14 +670,13 @@ export declare const cloudCameraStart: z.ZodObject<{
680
670
  request_id: z.ZodString;
681
671
  }, z.core.$strip>;
682
672
  export type CloudCameraStart = z.infer<typeof cloudCameraStart>;
683
- /** Cloud → bridge: the last viewer left; stop publishing (§10 refcount). */
673
+ /** Cloud → bridge: the last viewer left; stop publishing. */
684
674
  /**
685
- * Assets (spec §4.6, W7): the bridge **reports availability and transfers
686
- * nothing** until asked.
675
+ * Assets: the bridge **reports availability and transfers nothing** until
676
+ * asked.
687
677
  *
688
- * **The bytes never travel on this socket.** `server.ts` caps a frame at
689
- * 2 MiB, a single mesh exceeds that routinely, and raising the cap is already
690
- * tied to W8's rate limiting in the deferral register because it amplifies an
678
+ * **The bytes never travel on this socket.** A frame is capped at 2 MiB and a
679
+ * single mesh exceeds that routinely; raising the cap amplifies an
691
680
  * unauthenticated path. So the socket carries the *conversation* — what exists,
692
681
  * transfer this, here is how far I got — and the bytes go over HTTP with the
693
682
  * robot's own credential.
@@ -703,7 +692,7 @@ export declare const bridgeAssetsAvailable: z.ZodObject<{
703
692
  }, z.core.$strip>;
704
693
  export type BridgeAssetsAvailable = z.infer<typeof bridgeAssetsAvailable>;
705
694
  /**
706
- * The explicit request §4.6 requires — nothing moves without it.
695
+ * The explicit request that starts a transfer — nothing moves without it.
707
696
  *
708
697
  * The upload credential is minted per sync and travels here rather than being
709
698
  * derived from the robot token: it is scoped to one robot's assets and one