@fleetless/contracts 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +97 -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 +11 -11
  7. package/artifacts/routes.json +12 -12
  8. package/artifacts/schema/create-app-oidc-provider-request.schema.json +1 -1
  9. package/dist/alerts.d.ts +23 -28
  10. package/dist/alerts.js +23 -29
  11. package/dist/app-users.d.ts +18 -19
  12. package/dist/app-users.js +18 -20
  13. package/dist/apps.d.ts +21 -25
  14. package/dist/apps.js +42 -52
  15. package/dist/assets.d.ts +70 -132
  16. package/dist/assets.js +130 -223
  17. package/dist/audit.d.ts +14 -15
  18. package/dist/audit.js +28 -55
  19. package/dist/client-auth.d.ts +9 -9
  20. package/dist/client-auth.js +8 -9
  21. package/dist/common.d.ts +29 -37
  22. package/dist/common.js +28 -37
  23. package/dist/config-issues.d.ts +23 -25
  24. package/dist/config-issues.js +17 -17
  25. package/dist/config.d.ts +37 -44
  26. package/dist/config.js +145 -187
  27. package/dist/errors.d.ts +4 -3
  28. package/dist/errors.js +83 -116
  29. package/dist/identity.d.ts +24 -27
  30. package/dist/identity.js +23 -27
  31. package/dist/index.d.ts +4 -4
  32. package/dist/index.js +14 -15
  33. package/dist/introspection.d.ts +7 -6
  34. package/dist/introspection.js +6 -6
  35. package/dist/jobs.d.ts +16 -16
  36. package/dist/jobs.js +24 -29
  37. package/dist/mcp.d.ts +14 -15
  38. package/dist/mcp.js +12 -14
  39. package/dist/oauth.d.ts +21 -27
  40. package/dist/oauth.js +33 -43
  41. package/dist/protocol.d.ts +51 -62
  42. package/dist/protocol.js +107 -139
  43. package/dist/realtime.d.ts +53 -68
  44. package/dist/realtime.js +78 -104
  45. package/dist/rest.d.ts +183 -244
  46. package/dist/rest.js +305 -399
  47. package/dist/routes.d.ts +4 -3
  48. package/dist/routes.js +33 -32
  49. package/package.json +12 -7
@@ -1,7 +1,8 @@
1
+ // SPDX-License-Identifier: Apache-2.0
1
2
  import { z } from 'zod';
2
3
  /**
3
4
  * **Fleetless users: the org's team, and the only people who reach the
4
- * console** (spec `2026-09-05-app-user-auth`, D1).
5
+ * console.**
5
6
  *
6
7
  * There are two identity spaces now and **nothing joins them**:
7
8
  *
@@ -16,7 +17,7 @@ import { z } from 'zod';
16
17
  * A Fleetless user who wants to use an app registers or is invited like
17
18
  * anybody else; there is no path from one space to the other.
18
19
  *
19
- * **What that deleted, with no successor** (D1): groups and the Org Admins
20
+ * **What that deleted, with no successor**: groups and the Org Admins
20
21
  * group, app assignments, impersonation, the per-user MCP override and the
21
22
  * org-level federation policy. The 2026-08-29 model had put developers and end
22
23
  * users into one pool per org and connected them with all of the above; in use
@@ -48,7 +49,7 @@ export declare const password: z.ZodString;
48
49
  /** The bound on a Fleetless user's display name; `APP_USER_DISPLAY_NAME_MAX` matches it, so a rename cannot be legal in one space and refused in the other. */
49
50
  export declare const USER_DISPLAY_NAME_MAX = 120;
50
51
  /**
51
- * **The two tiers a Fleetless user can hold** (D1). Owner-exclusive: delete
52
+ * **The two tiers a Fleetless user can hold**. Owner-exclusive: delete
52
53
  * the org, edit org settings, promote to owner, and later billing. Everything
53
54
  * else a Fleetless user may do, a `developer` may do.
54
55
  *
@@ -96,7 +97,7 @@ export type PatchOrgResponse = z.infer<typeof patchOrgResponse>;
96
97
  * central endpoint), and `has_password`. The last is the interesting one — it
97
98
  * existed because a pool user might have been provisioned by an identity
98
99
  * provider and hold no Fleetless credential. A Fleetless user always holds
99
- * one: the console is password-only by design (D1), which removes the
100
+ * one: the console is password-only by design, which removes the
100
101
  * IdP-lockout class entirely, so a field reporting whether the credential
101
102
  * exists would have exactly one value forever.
102
103
  */
@@ -128,7 +129,7 @@ export declare const fleetlessUserListResponse: z.ZodObject<{
128
129
  }, z.core.$strip>;
129
130
  export type FleetlessUserListResponse = z.infer<typeof fleetlessUserListResponse>;
130
131
  /**
131
- * Access plus refresh (spec §3.4). The access token is short-lived; the
132
+ * Access plus refresh. The access token is short-lived; the
132
133
  * refresh token rotates on every use, so a stolen one is detectable when the
133
134
  * original is presented again.
134
135
  *
@@ -146,8 +147,8 @@ export declare const refreshRequest: z.ZodObject<{
146
147
  }, z.core.$strip>;
147
148
  export type RefreshRequest = z.infer<typeof refreshRequest>;
148
149
  /**
149
- * Registering an org creates the org and its first owner in one step
150
- * (André, 2026-08-10): whoever registers the organisation is the owner.
150
+ * Registering an org creates the org and its first owner in one step: whoever
151
+ * registers the organisation is the owner.
151
152
  */
152
153
  export declare const signUpRequest: z.ZodObject<{
153
154
  org_name: z.ZodString;
@@ -204,7 +205,7 @@ export declare const waitlistRequest: z.ZodObject<{
204
205
  export type WaitlistRequest = z.infer<typeof waitlistRequest>;
205
206
  /**
206
207
  * Console login. Fleetless users only, always the Fleetless password — the
207
- * console has no federated door at all (D1), which removes the IdP-lockout
208
+ * console has no federated door at all, which removes the IdP-lockout
208
209
  * class entirely.
209
210
  *
210
211
  * This resolves a person by address alone, and a Fleetless user's email is
@@ -222,7 +223,7 @@ export declare const developerLoginRequest: z.ZodObject<{
222
223
  }, z.core.$strip>;
223
224
  export type DeveloperLoginRequest = z.infer<typeof developerLoginRequest>;
224
225
  /**
225
- * What happened to the mail, in four words instead of one (W6c).
226
+ * What happened to the mail, in four words instead of one.
226
227
  *
227
228
  * `mail_sent: boolean` could not tell **"we have no SMTP configured"** from
228
229
  * **"we tried and the server refused"**, so the console had to pick a sentence
@@ -387,10 +388,10 @@ export declare const tierChangeRequest: z.ZodObject<{
387
388
  export type TierChangeRequest = z.infer<typeof tierChangeRequest>;
388
389
  /**
389
390
  * What a `forbidden` refusal carries when the reason is the caller's **tier**
390
- * rather than a missing grant (W6c).
391
+ * rather than a missing grant.
391
392
  *
392
- * §3.3 makes `forbidden` deliberately silent about *existence*, and that stays
393
- * true — this says nothing about what the target is. But "your role does not
393
+ * `forbidden` is deliberately silent about *existence*, and that stays true —
394
+ * this says nothing about what the target is. But "your role does not
394
395
  * permit this" and "there is no such thing" are the same answer today, and a
395
396
  * developer cannot tell *ask an owner* from *you have the wrong id*. Naming
396
397
  * the required tier reveals only what the caller could read off the docs.
@@ -429,8 +430,8 @@ export type PasswordChangeRequest = z.infer<typeof passwordChangeRequest>;
429
430
  *
430
431
  * **The response never says whether the address exists.** It is unauthenticated
431
432
  * and would otherwise be an account-enumeration oracle — the one place where
432
- * §3.3's "reveal nothing about what exists" is not a preference but the whole
433
- * point. So this answers the same way for a known and an unknown address, in
433
+ * revealing nothing about what exists is not a preference but the whole point.
434
+ * So this answers the same way for a known and an unknown address, in
434
435
  * status, body **and timing**, and any consumer that renders "no such account"
435
436
  * from it has reintroduced the oracle.
436
437
  *
@@ -463,24 +464,20 @@ export type PasswordResetConfirm = z.infer<typeof passwordResetConfirm>;
463
464
  * An IdP issuer URL — **an attacker-supplied string that decides where the
464
465
  * *server* connects.**
465
466
  *
466
- * `redirectUri` in `oauth.ts` got a parsed scheme check and an explicit
467
- * loopback allow-list, with the reasoning written down, because it decides
468
- * where a *credential* goes. This field got `z.url()` — in the same file, in
469
- * the same wave. Argus-W7b found it and stored `file:///etc/passwd`,
470
- * `http://169.254.169.254/latest/meta-data` and `http://infra-postgres-1:5432`
471
- * through the app's IdP route, then caught the outbound discovery fetch on a
472
- * listener he stood up. **That is this project's own question — which rules
473
- * have we already written down, and where else do they apply — answered badly,
474
- * one field over.**
467
+ * `redirectUri` in `oauth.ts` carries a parsed scheme check and an explicit
468
+ * loopback allow-list because it decides where a *credential* goes. A bare
469
+ * `z.url()` here would accept `file:///etc/passwd`, a cloud metadata address or
470
+ * an internal database host, and the server would then fetch it during issuer
471
+ * discovery. The same rule applies one field over.
475
472
  *
476
473
  * **What this shape can decide, it now decides:** http(s) only (so no `file:`,
477
474
  * `gopher:`, `data:`), no credentials in the URL, no fragment, no query. RFC
478
- * 8414 §3 builds the discovery URL from the issuer's path, so a query string
475
+ * 8414 builds the discovery URL from the issuer's path, so a query string
479
476
  * there is meaningless and a `@` is a redirect trick.
480
477
  *
481
478
  * **What it cannot decide, stated rather than implied:** it cannot tell
482
- * `http://localhost:8081/realms/fleetless-test` — the dev IdP this project
483
- * ships — from `http://127.0.0.1:5432`. Both are loopback http. So **this is
479
+ * a development identity provider on `http://localhost:8081` from a database
480
+ * on `http://127.0.0.1:5432`. Both are loopback http. So **this is
484
481
  * not the SSRF defence and must not be mistaken for one.** The defence belongs
485
482
  * at the fetch, in the cloud: refuse loopback, link-local and private ranges
486
483
  * unless something explicitly opts in for development, and it names DNS
@@ -498,7 +495,7 @@ export type IdpIssuer = z.infer<typeof idpIssuer>;
498
495
  * here.** `oidcCallbackErrorCode` and `oidcCallbackError` described the page
499
496
  * `GET /mcp/oauth/idp-callback` rendered when a group's identity provider sent
500
497
  * a browser back — `jit_disabled` and `email_collision` name provisioning steps
501
- * only a group provider had. D1 makes Fleetless users password-only and deletes
498
+ * only a group provider had. Fleetless users are password-only now, which deletes
502
499
  * group providers, so the flow that produced these codes cannot start; the
503
500
  * route is gone from this manifest and from the cloud.
504
501
  *
package/dist/identity.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { z } from 'zod';
3
3
  /**
4
4
  * **Fleetless users: the org's team, and the only people who reach the
5
- * console** (spec `2026-09-05-app-user-auth`, D1).
5
+ * console.**
6
6
  *
7
7
  * There are two identity spaces now and **nothing joins them**:
8
8
  *
@@ -17,7 +17,7 @@ import { z } from 'zod';
17
17
  * A Fleetless user who wants to use an app registers or is invited like
18
18
  * anybody else; there is no path from one space to the other.
19
19
  *
20
- * **What that deleted, with no successor** (D1): groups and the Org Admins
20
+ * **What that deleted, with no successor**: groups and the Org Admins
21
21
  * group, app assignments, impersonation, the per-user MCP override and the
22
22
  * org-level federation policy. The 2026-08-29 model had put developers and end
23
23
  * users into one pool per org and connected them with all of the above; in use
@@ -49,7 +49,7 @@ export const password = z.string().min(12).max(256);
49
49
  /** The bound on a Fleetless user's display name; `APP_USER_DISPLAY_NAME_MAX` matches it, so a rename cannot be legal in one space and refused in the other. */
50
50
  export const USER_DISPLAY_NAME_MAX = 120;
51
51
  /**
52
- * **The two tiers a Fleetless user can hold** (D1). Owner-exclusive: delete
52
+ * **The two tiers a Fleetless user can hold**. Owner-exclusive: delete
53
53
  * the org, edit org settings, promote to owner, and later billing. Everything
54
54
  * else a Fleetless user may do, a `developer` may do.
55
55
  *
@@ -95,7 +95,7 @@ export const patchOrgResponse = z.object({
95
95
  * central endpoint), and `has_password`. The last is the interesting one — it
96
96
  * existed because a pool user might have been provisioned by an identity
97
97
  * provider and hold no Fleetless credential. A Fleetless user always holds
98
- * one: the console is password-only by design (D1), which removes the
98
+ * one: the console is password-only by design, which removes the
99
99
  * IdP-lockout class entirely, so a field reporting whether the credential
100
100
  * exists would have exactly one value forever.
101
101
  */
@@ -126,7 +126,7 @@ export const fleetlessUserListResponse = z.object({
126
126
  }),
127
127
  });
128
128
  /**
129
- * Access plus refresh (spec §3.4). The access token is short-lived; the
129
+ * Access plus refresh. The access token is short-lived; the
130
130
  * refresh token rotates on every use, so a stolen one is detectable when the
131
131
  * original is presented again.
132
132
  *
@@ -146,8 +146,8 @@ export const sessionTokens = z.object({
146
146
  });
147
147
  export const refreshRequest = z.object({ refresh_token: z.string().min(1) });
148
148
  /**
149
- * Registering an org creates the org and its first owner in one step
150
- * (André, 2026-08-10): whoever registers the organisation is the owner.
149
+ * Registering an org creates the org and its first owner in one step: whoever
150
+ * registers the organisation is the owner.
151
151
  */
152
152
  export const signUpRequest = z.object({
153
153
  org_name: z.string().min(1).max(120),
@@ -181,7 +181,7 @@ export const signUpResponse = z.object({
181
181
  export const waitlistRequest = z.object({ email: z.email().max(254) });
182
182
  /**
183
183
  * Console login. Fleetless users only, always the Fleetless password — the
184
- * console has no federated door at all (D1), which removes the IdP-lockout
184
+ * console has no federated door at all, which removes the IdP-lockout
185
185
  * class entirely.
186
186
  *
187
187
  * This resolves a person by address alone, and a Fleetless user's email is
@@ -198,7 +198,7 @@ export const developerLoginRequest = z.object({
198
198
  password: z.string().min(1),
199
199
  });
200
200
  /**
201
- * What happened to the mail, in four words instead of one (W6c).
201
+ * What happened to the mail, in four words instead of one.
202
202
  *
203
203
  * `mail_sent: boolean` could not tell **"we have no SMTP configured"** from
204
204
  * **"we tried and the server refused"**, so the console had to pick a sentence
@@ -353,10 +353,10 @@ export const patchFleetlessUserRequest = z
353
353
  export const tierChangeRequest = z.object({ tier: orgAdminTier }).strict();
354
354
  /**
355
355
  * What a `forbidden` refusal carries when the reason is the caller's **tier**
356
- * rather than a missing grant (W6c).
356
+ * rather than a missing grant.
357
357
  *
358
- * §3.3 makes `forbidden` deliberately silent about *existence*, and that stays
359
- * true — this says nothing about what the target is. But "your role does not
358
+ * `forbidden` is deliberately silent about *existence*, and that stays true —
359
+ * this says nothing about what the target is. But "your role does not
360
360
  * permit this" and "there is no such thing" are the same answer today, and a
361
361
  * developer cannot tell *ask an owner* from *you have the wrong id*. Naming
362
362
  * the required tier reveals only what the caller could read off the docs.
@@ -392,8 +392,8 @@ export const passwordChangeRequest = z.object({
392
392
  *
393
393
  * **The response never says whether the address exists.** It is unauthenticated
394
394
  * and would otherwise be an account-enumeration oracle — the one place where
395
- * §3.3's "reveal nothing about what exists" is not a preference but the whole
396
- * point. So this answers the same way for a known and an unknown address, in
395
+ * revealing nothing about what exists is not a preference but the whole point.
396
+ * So this answers the same way for a known and an unknown address, in
397
397
  * status, body **and timing**, and any consumer that renders "no such account"
398
398
  * from it has reintroduced the oracle.
399
399
  *
@@ -424,24 +424,20 @@ export const passwordResetConfirm = z.object({
424
424
  * An IdP issuer URL — **an attacker-supplied string that decides where the
425
425
  * *server* connects.**
426
426
  *
427
- * `redirectUri` in `oauth.ts` got a parsed scheme check and an explicit
428
- * loopback allow-list, with the reasoning written down, because it decides
429
- * where a *credential* goes. This field got `z.url()` — in the same file, in
430
- * the same wave. Argus-W7b found it and stored `file:///etc/passwd`,
431
- * `http://169.254.169.254/latest/meta-data` and `http://infra-postgres-1:5432`
432
- * through the app's IdP route, then caught the outbound discovery fetch on a
433
- * listener he stood up. **That is this project's own question — which rules
434
- * have we already written down, and where else do they apply — answered badly,
435
- * one field over.**
427
+ * `redirectUri` in `oauth.ts` carries a parsed scheme check and an explicit
428
+ * loopback allow-list because it decides where a *credential* goes. A bare
429
+ * `z.url()` here would accept `file:///etc/passwd`, a cloud metadata address or
430
+ * an internal database host, and the server would then fetch it during issuer
431
+ * discovery. The same rule applies one field over.
436
432
  *
437
433
  * **What this shape can decide, it now decides:** http(s) only (so no `file:`,
438
434
  * `gopher:`, `data:`), no credentials in the URL, no fragment, no query. RFC
439
- * 8414 §3 builds the discovery URL from the issuer's path, so a query string
435
+ * 8414 builds the discovery URL from the issuer's path, so a query string
440
436
  * there is meaningless and a `@` is a redirect trick.
441
437
  *
442
438
  * **What it cannot decide, stated rather than implied:** it cannot tell
443
- * `http://localhost:8081/realms/fleetless-test` — the dev IdP this project
444
- * ships — from `http://127.0.0.1:5432`. Both are loopback http. So **this is
439
+ * a development identity provider on `http://localhost:8081` from a database
440
+ * on `http://127.0.0.1:5432`. Both are loopback http. So **this is
445
441
  * not the SSRF defence and must not be mistaken for one.** The defence belongs
446
442
  * at the fetch, in the cloud: refuse loopback, link-local and private ranges
447
443
  * unless something explicitly opts in for development, and it names DNS
@@ -476,7 +472,7 @@ export const idpIssuer = z
476
472
  * here.** `oidcCallbackErrorCode` and `oidcCallbackError` described the page
477
473
  * `GET /mcp/oauth/idp-callback` rendered when a group's identity provider sent
478
474
  * a browser back — `jit_disabled` and `email_collision` name provisioning steps
479
- * only a group provider had. D1 makes Fleetless users password-only and deletes
475
+ * only a group provider had. Fleetless users are password-only now, which deletes
480
476
  * group providers, so the flow that produced these codes cannot start; the
481
477
  * route is gone from this manifest and from the cloud.
482
478
  *
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ // SPDX-License-Identifier: Apache-2.0
1
2
  export { SLUG_RULE, ROS_NAME_RULE, ROS_TYPE_NAME_RULE, FIELD_PATH_RULE, slug, rosName, rosTypeName, fieldPath, wireSeqCursor, wireTimestampMs, applyErrorKind, applyError, } from './common.js';
2
3
  export type { ApplyErrorKind, ApplyError } from './common.js';
3
4
  export { MCP_PROTOCOL_VERSION, MCP_ENDPOINT_PATH, mcpAppEndpointPath, MCP_APP_PATHS, MCP_TOOL_NAME_MAX, MCP_ASSET_LINK_PATH, MCP_ASSET_LINK_TTL_MS, mcpToolNamePattern, mcpToolKind, mcpExposure, mcpCapabilities, mcpRobotDatasheet, mcpRolePreviewResponse, } from './mcp.js';
@@ -12,10 +13,9 @@ export { FLEETLESS_FORMAT_VERSION, RESERVED_SLUGS, parameterType, parameterSpec,
12
13
  export type { CameraSource } from './config.js';
13
14
  export type { ParameterType, ParameterSpec, ActionConfig, ServiceConfig, PublisherConfig, CameraConfig, CameraCredentials, AlertCondition, DatapointAlert, DatapointNumeric, DatapointRetention, DatapointChart, DatapointConfig, RobotConfigDoc, ValidationIssue, ConfigState, } from './config.js';
14
15
  /**
15
- * FL-005 — the one account of what is wrong with a document, shared by the
16
- * cloud and the console. The cloud held a second copy for one wave; it was
17
- * deleted in wave 2 task 8 (cloud `a307e18`, 2026-09-03). See
18
- * `config-issues.ts`'s header for what that window cost.
16
+ * The one account of what is wrong with a configuration document, shared by
17
+ * every layer that reports on one. See `config-issues.ts`'s header for why a
18
+ * second copy of this vocabulary is a defect rather than a convenience.
19
19
  */
20
20
  export { DOCUMENT_ROOT_PATH, EXPOSURE_SECTIONS, schemaIssues, formatPath, splitFormatPath, configSchemaHash, } from './config-issues.js';
21
21
  export type { SchemaIssue, ExposureSection } from './config-issues.js';
package/dist/index.js CHANGED
@@ -2,46 +2,45 @@
2
2
  export { SLUG_RULE, ROS_NAME_RULE, ROS_TYPE_NAME_RULE, FIELD_PATH_RULE, slug, rosName, rosTypeName, fieldPath, wireSeqCursor, wireTimestampMs, applyErrorKind, applyError, } from './common.js';
3
3
  export { MCP_PROTOCOL_VERSION, MCP_ENDPOINT_PATH, mcpAppEndpointPath, MCP_APP_PATHS, MCP_TOOL_NAME_MAX, MCP_ASSET_LINK_PATH, MCP_ASSET_LINK_TTL_MS, mcpToolNamePattern, mcpToolKind, mcpExposure, mcpCapabilities, mcpRobotDatasheet, mcpRolePreviewResponse, } from './mcp.js';
4
4
  export { PROTOCOL_VERSION, bridgeHello, cloudHelloOk, cloudHelloError, cloudPing, bridgePong, datapointFrame, bridgeState, bridgePressure, PRESSURE_SLUG, cloudConfig, bridgeConfigApplied, cloudIntrospectRequest, bridgeIntrospect, cloudTypeRequest, bridgeTypeDefinitions, cloudInvoke, cloudCancel, cloudPublish, bridgeJobUpdate, bridgeJobLost, snapshotHeader, cloudCameraStart, cloudCameraStop, bridgeCameraState, SNAPSHOT_MAX_BYTES, CLOSE_ROBOT_DELETED,
5
- // W7 — assets.
5
+ // Assets.
6
6
  bridgeAssetsAvailable, cloudAssetRequest, bridgeAssetProgress,
7
- // W6b — addressing.
7
+ // Addressing.
8
8
  activeJob, DEFAULT_PATIENCE_MS, MAX_PATIENCE_MS, MIN_PATIENCE_MS, } from './protocol.js';
9
9
  export { jobState, job, jobEvent, busyDetails, publisherBusyDetails, jobQueueFullDetails } from './jobs.js';
10
10
  export { JOB_RUN_PAGE_MAX, JOB_RUN_RETENTION_DAYS, jobActor, jobRunKind, jobRun, jobRunQuery, jobRunListResponse, jobRunSummaryQuery, jobRunSummary, } from './jobs.js';
11
11
  export { FLEETLESS_FORMAT_VERSION, RESERVED_SLUGS, parameterType, parameterSpec, parameterMap, serviceDescription, parameterDescription, messageTemplate, messageRef, messageBody, messageMap, PLACEHOLDER_RE, placeholderNames, actionConfig, serviceConfig, publisherConfig, cameraConfig, alertCondition, datapointAlert, rateThrottleHz, datapointNumeric, datapointRetention, datapointChart, datapointConfig, robotConfigDoc, validationIssue, configState, snapshotIntervalSeconds,
12
- // FL-002 — the defaults the format names, so nobody invents them twice.
12
+ // The defaults the format names, so nobody invents them twice.
13
13
  ALERT_SEVERITY_DEFAULT, ALERT_ENABLED_DEFAULT, RETENTION_INTERVAL_SECONDS_DEFAULT, CHART_WINDOW_MINUTES_DEFAULT,
14
- // W6
14
+ // Retention, history and quotas.
15
15
  cameraSource, cameraCredentials, } from './config.js';
16
16
  /**
17
- * FL-005 — the one account of what is wrong with a document, shared by the
18
- * cloud and the console. The cloud held a second copy for one wave; it was
19
- * deleted in wave 2 task 8 (cloud `a307e18`, 2026-09-03). See
20
- * `config-issues.ts`'s header for what that window cost.
17
+ * The one account of what is wrong with a configuration document, shared by
18
+ * every layer that reports on one. See `config-issues.ts`'s header for why a
19
+ * second copy of this vocabulary is a defect rather than a convenience.
21
20
  */
22
21
  export { DOCUMENT_ROOT_PATH, EXPOSURE_SECTIONS, schemaIssues, formatPath, splitFormatPath, configSchemaHash, } from './config-issues.js';
23
22
  export { rosGraphEntry, rosGraph, typeField, typeDefinition, parameterFieldsOf } from './introspection.js';
24
23
  export { robot, patchRobotResponse, robotToken, createRobotRequest, createRobotResponse, exposureCounts, robotListItem, robotListResponse, datapointValue, robotDetailResponse, configDraftResponse, putConfigDraftRequest, publishConfigResponse, configVersionsResponse, configVersionResponse, introspectionResponse, typesResponse, fetchTypesRequest, fetchTypesResponse, datapointDescriptor, datapointListResponse, robotDetailsDoc, putRobotDetailsResponse, putRobotDetailsRequest, invokeRequest, invokeResponse,
25
- // W6b — addressing.
24
+ // Addressing.
26
25
  cancelRequest, releaseLiveQuery, serviceCallResponse, invokeOrServiceResponse, publishRequest, jobResponse, robotJobsResponse, rateLimitDetails, exposure, exposureListResponse, SNAPSHOT_HEADERS, ASSET_UPLOAD_HEADERS, cameraDescriptor, cameraListResponse, liveSessionResponse, snapshotMetaResponse,
27
- // W6 — retention, history, quotas.
26
+ // Retention, history, quotas.
28
27
  historyQuery, historySamplesResponse, historyBucketsResponse, historyResponse, orgQuotas, orgQuotaUsage, orgQuotaUsageCounts, robotDeletionSummary, RESOURCE_HEALTH_STATES, resourceHealthState, resourceHealthListResponse, orgHealthQuery, robotDeleteQuery,
29
- // W3a — robot rename, slug rename.
28
+ // Robot rename, slug rename.
30
29
  patchRobotRequest, renameSlugRequest, renameSlugResponse, slugUsageResponse, } from './rest.js';
31
30
  export { LATENCY_BUCKET_MS, BRIDGE_LATENCY_RETENTION_DAYS, MAX_LATENCY_BUCKETS_PER_RESPONSE, latencyBucket, robotLatencySeries, orgLatencyQuery, orgLatencyResponse, USAGE_WINDOW_MAX_DAYS, usageMetric, usageDay, orgUsageQuery, usageRow, orgUsageResponse, } from './rest.js';
32
31
  export { clientAuth, authOk, authError, clientInvoke, clientCancel, clientPublish, commandResult, errorFrame, clientSubscribe, clientUnsubscribe, subscribeError, datapointEvent, resourceHealthEvent, resourceHealthCleared, liveSessionEndReason, liveSessionEvent, ORG_EVENT_SAMPLE_INTERVAL_MS, ORG_EVENT_ORG_CEILING_PER_SECOND, ORG_EVENT_BUFFER_SIZE, ORG_EVENT_BUFFER_IDLE_MS, ORG_EVENT_DETAIL_MAX_BYTES, orgEventKind, orgEventSeverity, orgEvent, orgEventSubscribe, orgEventUnsubscribe, orgEventReplay, orgEventDropped, } from './realtime.js';
33
32
  export { password, org, patchOrgResponse, sessionTokens, refreshRequest, signUpRequest, signUpResponse,
34
33
  // 2026-09-04 — the public site (closed beta).
35
34
  waitlistRequest, developerLoginRequest,
36
- // 2026-09-05 — the two identity spaces (app-user-auth, D1).
35
+ // The two identity spaces.
37
36
  USER_DISPLAY_NAME_MAX, orgAdminTier, fleetlessUser, fleetlessUserListResponse, createTeamInviteRequest, teamInvite, pendingTeamInvite, pendingTeamInviteListResponse, acceptTeamInviteRequest, patchFleetlessUserRequest, tierChangeRequest,
38
- // W6c — identity.
37
+ // Identity.
39
38
  mailStatus, tierRequiredDetails, passwordChangeRequest, passwordResetRequest, passwordResetConfirm, idpIssuer,
40
- // W3a — auth/me, org and member patches.
39
+ // auth/me, org and member patches.
41
40
  authMeResponse, patchOrgRequest, patchAuthMeRequest, } from './identity.js';
42
41
  export { appIdentifier, app, appListResponse, createAppRequest, updateAppRequest, serverKeyToken, serverKey, serverKeyListResponse, createServerKeyResponse, role, roleListResponse, rolePermissions, } from './apps.js';
43
42
  export { clientLoginRequest, clientRefreshRequest, clientLogoutRequest, clientRegisterRequest, clientVerifyEmailRequest, clientResendVerificationRequest, clientPasswordResetRequest, clientPasswordResetConfirmRequest, clientAcceptInvitationRequest, CLIENT_OIDC_CALLBACK_PATH, clientProviderListQuery, clientProviderListResponse, clientOidcStartQuery, clientOidcCallbackQuery, clientOidcExchangeRequest, clientOidcErrorCode, clientMcpInteraction, clientMcpInteractionDecisionResponse, mcpConsentGrant, mcpConsentGrantListResponse, clientIdentity, } from './client-auth.js';
44
- // 2026-09-05 — the per-app identity space (app-user-auth, D1/D3/D4/D5).
43
+ // The per-app identity space.
45
44
  export { APP_USER_DISPLAY_NAME_MAX, APP_URL_PLACEHOLDERS, MAIL_TEMPLATE_VARIABLES, DEFAULT_MAIL_TEMPLATES, providerSlug, appUserStatus, appUser, appUserListResponse, createAppUserRequest, patchAppUserRequest, createAppInvitationRequest, appInvitation, pendingAppInvitation, appInvitationListResponse, appOidcProvider, appOidcProviderListResponse, createAppOidcProviderRequest, patchAppOidcProviderRequest, appUrlTemplate, allowedOrigin, emailDomain, appAuthConfig, putAppAuthConfigRequest, mailTemplateKind, appMailTemplate, appMailTemplateListResponse, putAppMailTemplateRequest, mailTemplatePreviewRequest, mailTemplatePreviewResponse, mailTemplateProblemDetails, mailOutcome, } from './app-users.js';
46
45
  export { assetKind, URDF_ASSET_NAME, asset, urdfCompleteness, assetListResponse, missingAssetQuery, assetSyncRequest, assetSyncResponse, assetSyncState, assetSyncStatus, assetFailure, assetFailureKind, assetTooLargeDetails, assetSyncBusyDetails, ASSET_UPLOAD_MAX_BYTES, } from './assets.js';
47
46
  export { auditActor, auditEvent, auditQuery, auditListResponse, AUDIT_CSV_COLUMNS, AUDIT_RETENTION_DAYS } from './audit.js';
@@ -1,6 +1,7 @@
1
+ // SPDX-License-Identifier: Apache-2.0
1
2
  import { z } from 'zod';
2
3
  /**
3
- * Introspection (spec §4.1, §4.5): what the connected bridge can tell the
4
+ * Introspection: what the connected bridge can tell the
4
5
  * cloud about the robot's ROS graph, so the console can offer a quick pick
5
6
  * instead of a blank text field.
6
7
  *
@@ -45,10 +46,10 @@ export interface TypeField {
45
46
  }
46
47
  export declare const typeField: z.ZodType<TypeField>;
47
48
  /**
48
- * A resolved type of one robot. Custom types are per robot (spec §4.5): two
49
- * robots may define `custom_msgs/msg/Speed` differently and both are right.
49
+ * A resolved type of one robot. Custom types are per robot: two robots may
50
+ * define `custom_msgs/msg/Speed` differently and both are right.
50
51
  *
51
- * W2 resolved messages only; W4 adds services and actions, because a
52
+ * Messages, services and actions all appear here, because a
52
53
  * `parameterSpec.name` has to resolve against *something*, and an action has
53
54
  * no flat field list — it has a goal, a result and a feedback tree.
54
55
  *
@@ -65,8 +66,8 @@ export declare const typeField: z.ZodType<TypeField>;
65
66
  * a result in. They are carried so the console can show what an action will
66
67
  * report back, and so a client knows the shape of `job.result` in advance.
67
68
  *
68
- * The `msg` member keeps W2's exact shape, so every type already stored stays
69
- * valid without migration.
69
+ * The `msg` member is the flat field list a message resolves to; the other
70
+ * two carry one tree per part.
70
71
  */
71
72
  export declare const typeDefinition: z.ZodDiscriminatedUnion<[z.ZodObject<{
72
73
  name: z.ZodString;
@@ -2,7 +2,7 @@
2
2
  import { z } from 'zod';
3
3
  import { rosName, rosTypeName } from './common.js';
4
4
  /**
5
- * Introspection (spec §4.1, §4.5): what the connected bridge can tell the
5
+ * Introspection: what the connected bridge can tell the
6
6
  * cloud about the robot's ROS graph, so the console can offer a quick pick
7
7
  * instead of a blank text field.
8
8
  *
@@ -31,10 +31,10 @@ export const typeField = z.lazy(() => z.object({
31
31
  fields: z.array(typeField).nullable(),
32
32
  }));
33
33
  /**
34
- * A resolved type of one robot. Custom types are per robot (spec §4.5): two
35
- * robots may define `custom_msgs/msg/Speed` differently and both are right.
34
+ * A resolved type of one robot. Custom types are per robot: two robots may
35
+ * define `custom_msgs/msg/Speed` differently and both are right.
36
36
  *
37
- * W2 resolved messages only; W4 adds services and actions, because a
37
+ * Messages, services and actions all appear here, because a
38
38
  * `parameterSpec.name` has to resolve against *something*, and an action has
39
39
  * no flat field list — it has a goal, a result and a feedback tree.
40
40
  *
@@ -51,8 +51,8 @@ export const typeField = z.lazy(() => z.object({
51
51
  * a result in. They are carried so the console can show what an action will
52
52
  * report back, and so a client knows the shape of `job.result` in advance.
53
53
  *
54
- * The `msg` member keeps W2's exact shape, so every type already stored stays
55
- * valid without migration.
54
+ * The `msg` member is the flat field list a message resolves to; the other
55
+ * two carry one tree per part.
56
56
  */
57
57
  export const typeDefinition = z.discriminatedUnion('kind', [
58
58
  z.object({
package/dist/jobs.d.ts CHANGED
@@ -1,15 +1,16 @@
1
+ // SPDX-License-Identifier: Apache-2.0
1
2
  import { z } from 'zod';
2
3
  /**
3
- * Jobs (spec §6.1, §11.3): one running unit of work on a robot — an action
4
+ * Jobs: one running unit of work on a robot — an action
4
5
  * goal or a service call — with an id both sides know, so bridge and cloud
5
6
  * stay in sync across a disconnect.
6
7
  *
7
8
  * Two rules shape everything here:
8
9
  *
9
- * 1. **State is observed by slug, not by id.** The id is informative (§11.3);
10
- * a client watches `robot × slug` and sees whatever job is running there,
11
- * which is also why every observer of a slug sees the same job.
12
- * 2. **`lost` is a real outcome and must be said out loud** (§6.1). Job state
10
+ * 1. **State is observed by slug, not by id.** The id is informative; a client
11
+ * watches `robot × slug` and sees whatever job is running there, which is
12
+ * also why every observer of a slug sees the same job.
13
+ * 2. **`lost` is a real outcome and must be said out loud.** Job state
13
14
  * lives only in the bridge's memory; if it restarts mid-job, the results
14
15
  * are gone. The cloud then marks the job `lost` — never leaves it reading
15
16
  * "running" because nobody contradicted it. A system that reports a
@@ -49,8 +50,8 @@ export type Job = z.infer<typeof job>;
49
50
  /**
50
51
  * One update about a job, pushed to subscribers of its slug.
51
52
  *
52
- * `timestamp_ms` is the bridge's capture time, exactly as for a datapoint
53
- * (§6.3 says action feedback carries it too) — so a client computes the age
53
+ * `timestamp_ms` is the bridge's capture time, exactly as for a datapoint —
54
+ * action feedback carries it too — so a client computes the age
54
55
  * of a progress report the same way it computes the age of a sensor value,
55
56
  * and a burst of late-delivered feedback after a reconnect is visibly late
56
57
  * rather than looking current.
@@ -86,9 +87,8 @@ export declare const jobEvent: z.ZodObject<{
86
87
  }, z.core.$strip>;
87
88
  export type JobEvent = z.infer<typeof jobEvent>;
88
89
  /**
89
- * What a busy refusal tells the caller (spec §11.3: "inkl. Information, was
90
- * läuft"). A refusal that only says "busy" forces the caller to guess whether
91
- * to wait or to give up.
90
+ * What a busy refusal tells the caller: what is already running. A refusal that
91
+ * only says "busy" forces the caller to guess whether to wait or to give up.
92
92
  */
93
93
  export declare const busyDetails: z.ZodObject<{
94
94
  running: z.ZodObject<{
@@ -115,7 +115,7 @@ export declare const busyDetails: z.ZodObject<{
115
115
  }, z.core.$strip>;
116
116
  export type BusyDetails = z.infer<typeof busyDetails>;
117
117
  /**
118
- * What a `publisher_busy` refusal tells the caller (spec §6.4).
118
+ * What a `publisher_busy` refusal tells the caller.
119
119
  *
120
120
  * "Another caller is publishing and has not been quiet long enough" names a
121
121
  * state and no action: the caller does not know how much longer, because
@@ -133,7 +133,7 @@ export declare const publisherBusyDetails: z.ZodObject<{
133
133
  }, z.core.$strip>;
134
134
  export type PublisherBusyDetails = z.infer<typeof publisherBusyDetails>;
135
135
  /**
136
- * What a `job_queue_full` refusal tells the caller (W6b).
136
+ * What a `job_queue_full` refusal tells the caller.
137
137
  *
138
138
  * Both numbers, not just the limit: `limit` alone says how big the queue is
139
139
  * and nothing about whether waiting will help, and `queued` alone cannot be
@@ -163,7 +163,7 @@ export declare const JOB_RUN_RETENTION_DAYS = 90;
163
163
  * invites every reader to handle it.
164
164
  *
165
165
  * **`app_user` is what a client-app caller writes now, and `end_user` stays**
166
- * (app-user auth, D1). The seam this comment used to describe — two names for
166
+ * identity spaces. The seam this comment used to describe — two names for
167
167
  * two ways into one merged pool — is settled: the two identity spaces are
168
168
  * separate tables again, and `app_user` is a row in `app_users`, belonging to
169
169
  * exactly one app. `end_user` is kept for the same reason `auditActor.kind`
@@ -188,10 +188,10 @@ export declare const jobRunKind: z.ZodEnum<{
188
188
  }>;
189
189
  export type JobRunKind = z.infer<typeof jobRunKind>;
190
190
  /**
191
- * One durable record of one invocation (spec `2026-08-20-timeseries-and-run-history`,
192
- * D2). One row per run, never one per event: the per-event timeline's write rate
191
+ * One durable record of one invocation. One row per run, never one per event:
192
+ * the per-event timeline's write rate
193
193
  * is set by the bridge, and a throttled log that cannot say it was throttled is
194
- * the instrument this codebase refuses everywhere else. The live timeline is
194
+ * an instrument that cannot say what it does not know. The live timeline is
195
195
  * delivered in full by realtime, for as long as somebody is watching.
196
196
  */
197
197
  export declare const jobRun: z.ZodObject<{