@capybara-hq/kernel 0.1.0-rc.11 → 0.1.0-rc.13

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 (220) hide show
  1. package/dist/admin/admin.schemas.d.ts +13 -0
  2. package/dist/agents/agent-lookup.d.ts +5 -0
  3. package/dist/agents/agent-lookup.js +15 -0
  4. package/dist/agents/agents.schemas.d.ts +3 -0
  5. package/dist/agents/agents.service.js +11 -1
  6. package/dist/agents/definition.d.ts +1 -0
  7. package/dist/agents/definition.js +7 -3
  8. package/dist/agents/org-templates.js +4 -0
  9. package/dist/agents/pending-connectors.service.js +1 -1
  10. package/dist/background/background.module.js +2 -2
  11. package/dist/background/launch-lock.d.ts +1 -1
  12. package/dist/background/launch-lock.js +1 -1
  13. package/dist/background/poll.job.d.ts +2 -2
  14. package/dist/background/poll.job.js +10 -10
  15. package/dist/background/stop.d.ts +1 -1
  16. package/dist/background/stop.js +3 -3
  17. package/dist/background/store.d.ts +5 -5
  18. package/dist/background/store.js +5 -5
  19. package/dist/background/tasks.service.d.ts +6 -6
  20. package/dist/background/tasks.service.js +13 -13
  21. package/dist/catalog/component-scope.controller.d.ts +18 -6
  22. package/dist/catalog/component-scope.controller.js +36 -13
  23. package/dist/catalog/component-scope.service.d.ts +11 -0
  24. package/dist/catalog/component-scope.service.js +4 -0
  25. package/dist/catalog/component-state.d.ts +8 -0
  26. package/dist/catalog/component-state.js +19 -11
  27. package/dist/catalog/marketplaces.service.d.ts +1 -1
  28. package/dist/catalog/plugin-import.js +4 -1
  29. package/dist/channels/channels.module.js +2 -2
  30. package/dist/channels/inbound.d.ts +8 -8
  31. package/dist/channels/inbound.js +31 -31
  32. package/dist/channels/phrases.d.ts +27 -27
  33. package/dist/channels/phrases.js +27 -27
  34. package/dist/config/docs.js +1 -1
  35. package/dist/config/schema.d.ts +2 -2
  36. package/dist/config/schema.js +21 -21
  37. package/dist/conversations/conversations.controller.d.ts +11 -11
  38. package/dist/conversations/conversations.controller.js +15 -15
  39. package/dist/conversations/conversations.module.d.ts +1 -1
  40. package/dist/conversations/conversations.module.js +7 -7
  41. package/dist/conversations/conversations.schemas.js +1 -1
  42. package/dist/conversations/conversations.service.d.ts +23 -14
  43. package/dist/conversations/conversations.service.js +28 -21
  44. package/dist/conversations/{environment-status.d.ts → device-status.d.ts} +9 -9
  45. package/dist/conversations/{environment-status.js → device-status.js} +18 -18
  46. package/dist/conversations/event-log.d.ts +1 -1
  47. package/dist/conversations/event-log.js +1 -1
  48. package/dist/conversations/events.d.ts +2 -1
  49. package/dist/conversations/events.js +2 -2
  50. package/dist/ctx/create-ctx.d.ts +10 -1
  51. package/dist/ctx/create-ctx.js +86 -25
  52. package/dist/db/kernel-schema.d.ts +39 -23
  53. package/dist/{environments → devices}/access.d.ts +19 -19
  54. package/dist/{environments → devices}/access.js +28 -28
  55. package/dist/devices/conversation-devices.d.ts +75 -0
  56. package/dist/{environments/conversation-environments.js → devices/conversation-devices.js} +71 -72
  57. package/dist/devices/devices.controller.d.ts +36 -0
  58. package/dist/{environments/environments.controller.js → devices/devices.controller.js} +37 -37
  59. package/dist/devices/devices.module.d.ts +5 -13
  60. package/dist/devices/devices.module.js +16 -29
  61. package/dist/devices/devices.schemas.d.ts +3 -0
  62. package/dist/devices/devices.schemas.js +14 -0
  63. package/dist/{environments/environments.service.d.ts → devices/devices.service.d.ts} +70 -70
  64. package/dist/{environments/environments.service.js → devices/devices.service.js} +122 -122
  65. package/dist/devices/dto.d.ts +13 -54
  66. package/dist/devices/dto.js +7 -39
  67. package/dist/devices/label.d.ts +11 -0
  68. package/dist/{environments → devices}/label.js +7 -7
  69. package/dist/{environments → devices}/legacy-cleanup.job.d.ts +3 -3
  70. package/dist/{environments → devices}/legacy-cleanup.job.js +3 -3
  71. package/dist/errors.d.ts +27 -25
  72. package/dist/errors.js +27 -25
  73. package/dist/evals/recorded-tools.d.ts +2 -2
  74. package/dist/evals/recorded-tools.js +6 -6
  75. package/dist/extensions/admin-ops.js +1 -0
  76. package/dist/extensions/admin-view.js +2 -0
  77. package/dist/extensions/effective-config.d.ts +6 -0
  78. package/dist/extensions/effective-config.js +18 -7
  79. package/dist/extensions/host.d.ts +13 -2
  80. package/dist/extensions/host.js +24 -3
  81. package/dist/extensions/instance.d.ts +12 -1
  82. package/dist/extensions/instance.js +13 -0
  83. package/dist/extensions/permission-view.d.ts +10 -1
  84. package/dist/files/previewers.d.ts +1 -1
  85. package/dist/files/previewers.js +1 -1
  86. package/dist/http/api.module.js +10 -6
  87. package/dist/http/gateway-routes.d.ts +1 -1
  88. package/dist/http/gateway-routes.js +1 -1
  89. package/dist/identity/settings.d.ts +32 -0
  90. package/dist/identity/settings.js +26 -2
  91. package/dist/infra/config/kernel-config.service.js +4 -4
  92. package/dist/kernel.module.js +3 -3
  93. package/dist/{devices → local-devices}/device-auth.controller.d.ts +6 -6
  94. package/dist/{devices → local-devices}/device-auth.controller.js +5 -5
  95. package/dist/{devices → local-devices}/device-auth.d.ts +20 -20
  96. package/dist/{devices → local-devices}/device-auth.js +51 -53
  97. package/dist/local-devices/device-auth.module.d.ts +7 -0
  98. package/dist/{devices → local-devices}/device-auth.module.js +5 -5
  99. package/dist/{devices → local-devices}/device-routes.d.ts +3 -3
  100. package/dist/{devices → local-devices}/device-routes.js +2 -2
  101. package/dist/local-devices/dto.d.ts +66 -0
  102. package/dist/local-devices/dto.js +44 -0
  103. package/dist/{devices → local-devices}/keys.d.ts +11 -11
  104. package/dist/{devices → local-devices}/keys.js +11 -11
  105. package/dist/{devices/device-gateway.d.ts → local-devices/local-device-gateway.d.ts} +14 -14
  106. package/dist/{devices/device-gateway.js → local-devices/local-device-gateway.js} +44 -44
  107. package/dist/{devices/device-provider.d.ts → local-devices/local-device-provider.d.ts} +15 -15
  108. package/dist/{devices/device-provider.js → local-devices/local-device-provider.js} +23 -23
  109. package/dist/local-devices/local-devices.module.d.ts +16 -0
  110. package/dist/local-devices/local-devices.module.js +44 -0
  111. package/dist/{devices → local-devices}/machines.d.ts +26 -26
  112. package/dist/{devices → local-devices}/machines.js +71 -71
  113. package/dist/{devices → local-devices}/relay.d.ts +15 -15
  114. package/dist/{devices → local-devices}/relay.js +55 -55
  115. package/dist/{devices → local-devices}/targets.d.ts +8 -8
  116. package/dist/{devices → local-devices}/targets.js +14 -14
  117. package/dist/orgs/offboarding.d.ts +6 -6
  118. package/dist/orgs/offboarding.js +12 -12
  119. package/dist/orgs/settings.service.d.ts +28 -0
  120. package/dist/orgs/settings.service.js +20 -1
  121. package/dist/platform/exclusions.js +48 -3
  122. package/dist/platform/operation.js +6 -2
  123. package/dist/platform/ops/admin.ops.js +8 -2
  124. package/dist/platform/ops/agents.ops.js +19 -6
  125. package/dist/platform/ops/conversations.ops.d.ts +3 -3
  126. package/dist/platform/ops/conversations.ops.js +9 -9
  127. package/dist/platform/ops/devices.ops.d.ts +26 -0
  128. package/dist/platform/ops/devices.ops.js +311 -0
  129. package/dist/platform/ops/org-settings.ops.js +2 -2
  130. package/dist/platform/ops/orgs.ops.js +1 -0
  131. package/dist/platform/ops/ui.ops.d.ts +8 -0
  132. package/dist/platform/ops/ui.ops.js +41 -0
  133. package/dist/platform/platform-ops.module.d.ts +3 -2
  134. package/dist/platform/platform-ops.module.js +8 -5
  135. package/dist/platform/route-schemas.js +6 -3
  136. package/dist/roles/gateway-role.d.ts +3 -3
  137. package/dist/roles/gateway-role.js +4 -4
  138. package/dist/roles/gateway.module.d.ts +1 -1
  139. package/dist/roles/gateway.module.js +5 -5
  140. package/dist/roles/worker.module.js +1 -1
  141. package/dist/runtime/context/build.d.ts +1 -1
  142. package/dist/runtime/context/build.js +6 -6
  143. package/dist/runtime/context/compaction.js +1 -1
  144. package/dist/runtime/context/{environment-paths.d.ts → device-paths.d.ts} +11 -11
  145. package/dist/runtime/context/{environment-paths.js → device-paths.js} +13 -13
  146. package/dist/runtime/maintenance.d.ts +1 -1
  147. package/dist/runtime/subagents/definition.d.ts +3 -2
  148. package/dist/runtime/subagents/definition.js +2 -1
  149. package/dist/sandbox/jobs.d.ts +13 -13
  150. package/dist/sandbox/jobs.js +20 -20
  151. package/dist/sandbox/leases.d.ts +9 -9
  152. package/dist/sandbox/leases.js +14 -14
  153. package/dist/sandbox/providers.d.ts +8 -8
  154. package/dist/sandbox/providers.js +8 -8
  155. package/dist/sandbox/sandbox.module.d.ts +1 -1
  156. package/dist/sandbox/sandbox.module.js +1 -1
  157. package/dist/sandbox/sandbox.service.d.ts +76 -76
  158. package/dist/sandbox/sandbox.service.js +230 -230
  159. package/dist/tools/builtins/builtin-tools.d.ts +2 -2
  160. package/dist/tools/builtins/builtin-tools.js +5 -5
  161. package/dist/tools/builtins/platform.js +1 -1
  162. package/dist/tools/builtins/sandbox/bash.js +6 -6
  163. package/dist/tools/builtins/sandbox/common.d.ts +25 -25
  164. package/dist/tools/builtins/sandbox/common.js +51 -51
  165. package/dist/tools/builtins/sandbox/edit.js +2 -2
  166. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  167. package/dist/tools/builtins/sandbox/index.js +1 -1
  168. package/dist/tools/builtins/sandbox/task-output.d.ts +6 -6
  169. package/dist/tools/builtins/sandbox/task-output.js +10 -10
  170. package/dist/tools/builtins/sandbox/task-stop.js +2 -2
  171. package/dist/tools/builtins/sandbox/write.js +2 -2
  172. package/dist/tools/builtins/skill-load.d.ts +1 -1
  173. package/dist/tools/builtins/skill-load.js +2 -2
  174. package/dist/tools/connector-account-policies.d.ts +51 -0
  175. package/dist/tools/connector-account-policies.js +165 -0
  176. package/dist/tools/connectors.controller.d.ts +35 -4
  177. package/dist/tools/connectors.controller.js +66 -7
  178. package/dist/tools/connectors.schemas.d.ts +11 -0
  179. package/dist/tools/connectors.schemas.js +11 -0
  180. package/dist/tools/connectors.service.d.ts +2 -0
  181. package/dist/tools/connectors.service.js +1 -0
  182. package/dist/tools/pipeline.d.ts +1 -1
  183. package/dist/tools/pipeline.js +4 -3
  184. package/dist/tools/policy.d.ts +23 -1
  185. package/dist/tools/policy.js +99 -24
  186. package/dist/tools/registry.d.ts +2 -2
  187. package/dist/tools/tools.module.js +6 -3
  188. package/dist/ui/admin-ui.controller.d.ts +56 -0
  189. package/dist/ui/admin-ui.controller.js +192 -0
  190. package/dist/ui/arrangement.d.ts +74 -0
  191. package/dist/ui/arrangement.js +98 -0
  192. package/dist/ui/embed-token.d.ts +2 -2
  193. package/dist/ui/embed-token.js +30 -5
  194. package/dist/ui/registry.d.ts +29 -14
  195. package/dist/ui/registry.js +31 -10
  196. package/dist/ui/slots.controller.d.ts +11 -0
  197. package/dist/ui/slots.controller.js +25 -0
  198. package/dist/ui/ui-stream.d.ts +20 -3
  199. package/dist/ui/ui-stream.js +25 -7
  200. package/dist/ui/ui.schemas.d.ts +66 -0
  201. package/dist/ui/ui.schemas.js +65 -0
  202. package/dist/ui/views.controller.d.ts +35 -49
  203. package/dist/ui/views.controller.js +48 -70
  204. package/dist/ui/views.d.ts +84 -18
  205. package/dist/ui/views.js +201 -38
  206. package/package.json +3 -3
  207. package/src/migrations/0104_connector_tool_account_policies.sql +16 -0
  208. package/src/migrations/0105_devices_rename.sql +136 -0
  209. package/dist/devices/device-auth.module.d.ts +0 -7
  210. package/dist/environments/conversation-environments.d.ts +0 -75
  211. package/dist/environments/dto.d.ts +0 -25
  212. package/dist/environments/dto.js +0 -12
  213. package/dist/environments/environments.controller.d.ts +0 -36
  214. package/dist/environments/environments.module.d.ts +0 -8
  215. package/dist/environments/environments.module.js +0 -31
  216. package/dist/environments/environments.schemas.d.ts +0 -3
  217. package/dist/environments/environments.schemas.js +0 -14
  218. package/dist/environments/label.d.ts +0 -11
  219. package/dist/platform/ops/environments.ops.d.ts +0 -26
  220. package/dist/platform/ops/environments.ops.js +0 -311
@@ -9,7 +9,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
9
9
  };
10
10
  import { randomBytes } from "node:crypto";
11
11
  import { Inject, Injectable } from "@nestjs/common";
12
- import { EnvironmentsService } from "../environments/environments.service.js";
12
+ import { DevicesService } from "../devices/devices.service.js";
13
13
  import { ApiError } from "../errors.js";
14
14
  import { audit } from "../identity/audit.js";
15
15
  import { sha256Hex } from "../identity/hash.js";
@@ -19,8 +19,8 @@ import { TransactionHost } from "../infra/database/transaction-host.js";
19
19
  import { Transactional } from "../infra/database/transactional.decorator.js";
20
20
  import { KERNEL_LOGGER, REDIS } from "../infra/tokens.js";
21
21
  import { authorizeOrgAction } from "../orgs/org.guard.js";
22
- import { DEVICE_PROVIDER } from "../sandbox/providers.js";
23
- import { environmentNotFound } from "../sandbox/sandbox.service.js";
22
+ import { LOCAL_PROVIDER } from "../sandbox/providers.js";
23
+ import { deviceNotFound } from "../sandbox/sandbox.service.js";
24
24
  import { MachinesService } from "./machines.js";
25
25
  /** The 20 consonants a user code is made of (no vowels: no words; no look-alike letters). */
26
26
  export const USER_CODE_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ";
@@ -31,8 +31,8 @@ const DEVICE_CODE_RE = /^cap_dvc_[A-Za-z0-9_-]{43}$/;
31
31
  export const SLOW_DOWN_STEP_SECONDS = 5;
32
32
  /** Polls this much earlier than the interval are still on time (network jitter). */
33
33
  const POLL_JITTER_MS = 500;
34
- /** The web page that confirms a code: `<http.publicUrl>/device`. */
35
- export const DEVICE_PAGE_PATH = "/device";
34
+ /** The web page that confirms a code: `<http.publicUrl>/devices/link`. */
35
+ export const DEVICE_PAGE_PATH = "/devices/link";
36
36
  /** The machine's WebSocket route: `ws(s)://<http.publicUrl host>/device/connect`. */
37
37
  export const DEVICE_CONNECT_PATH = "/device/connect";
38
38
  /** The sign-in state of one device code: `capk:device-auth:<sha256(deviceCode)>` (a hash). */
@@ -78,7 +78,7 @@ redis.call('HSET', KEYS[1], 'status', ARGV[2])
78
78
  if ARGV[3] then redis.call('HSET', KEYS[1], ARGV[3], ARGV[4]) end
79
79
  return 1
80
80
  `;
81
- const codeInvalid = () => new ApiError("device.code_invalid", "This code is unknown or has expired; check the code shown by capybara-device, or run capybara-device login again");
81
+ const codeInvalid = () => new ApiError("device_sign_in.code_invalid", "This code is unknown or has expired; check the code shown by capybara-device, or run capybara-device login again");
82
82
  /** A user code as typed → `XXXX-XXXX`, or null when it cannot be one. */
83
83
  export function normalizeUserCode(input) {
84
84
  const s = input.toUpperCase().replace(/[\s-]/g, "");
@@ -107,7 +107,7 @@ function newUserCode() {
107
107
  * for a code pair (`authorize`), the signed-in person confirms the user code on the web page
108
108
  * `/device` (`pending`, `confirm` or `deny`), and the program polls `token` until it gets the
109
109
  * machine credential, once. State lives only in Redis, both keys with the code's TTL
110
- * (`environments.device.authCodeTtlSeconds`): `capk:device-auth:<sha256(deviceCode)>` (a hash:
110
+ * (`devices.local.authCodeTtlSeconds`): `capk:device-auth:<sha256(deviceCode)>` (a hash:
111
111
  * `info` JSON, `status`, `interval`, `lastPollAt`, the parked `grant`) and
112
112
  * `capk:device-user:<userCode>` → the device code's hash. The device code itself is never stored.
113
113
  */
@@ -116,22 +116,22 @@ let DeviceAuthService = class DeviceAuthService {
116
116
  txHost;
117
117
  redis;
118
118
  config;
119
- environments;
119
+ devices;
120
120
  machines;
121
121
  log;
122
- constructor(db, txHost, redis, config, environments, machines, log) {
122
+ constructor(db, txHost, redis, config, devices, machines, log) {
123
123
  this.db = db;
124
124
  this.txHost = txHost;
125
125
  this.redis = redis;
126
126
  this.config = config;
127
- this.environments = environments;
127
+ this.devices = devices;
128
128
  this.machines = machines;
129
129
  this.log = log;
130
130
  }
131
131
  /** A new code pair for a machine. Needs `http.publicUrl` (the page and the connection URL). */
132
132
  async authorize(machine) {
133
133
  const web = this.publicUrl();
134
- const { authCodeTtlSeconds: ttl, pollIntervalSeconds: interval } = this.config.get().environments.device;
134
+ const { authCodeTtlSeconds: ttl, pollIntervalSeconds: interval } = this.config.get().devices.local;
135
135
  const deviceCode = DEVICE_CODE_PREFIX + randomBytes(32).toString("base64url");
136
136
  const hash = sha256Hex(deviceCode);
137
137
  for (let attempt = 0;; attempt++) {
@@ -169,8 +169,8 @@ let DeviceAuthService = class DeviceAuthService {
169
169
  }
170
170
  /**
171
171
  * The program's poll: the grant once the person confirmed (the code is consumed), else
172
- * `device.authorization_pending`, `device.slow_down` (details `[{ interval }]`, the grown
173
- * interval), `device.denied` or `device.expired` (also for an unknown code).
172
+ * `device_sign_in.authorization_pending`, `device_sign_in.slow_down` (details `[{ interval }]`, the grown
173
+ * interval), `device_sign_in.denied` or `device_sign_in.expired` (also for an unknown code).
174
174
  */
175
175
  async token(deviceCode) {
176
176
  const connectUrl = this.connectUrl();
@@ -180,21 +180,21 @@ let DeviceAuthService = class DeviceAuthService {
180
180
  switch (r[0]) {
181
181
  case "approved": {
182
182
  const grant = JSON.parse(r[1]);
183
- const device = this.config.get().environments.device;
183
+ const local = this.config.get().devices.local;
184
184
  return {
185
185
  ...grant,
186
186
  connectUrl,
187
- reconnectGraceSeconds: device.reconnectGraceSeconds,
188
- maxFrameBytes: device.maxFrameBytes,
187
+ reconnectGraceSeconds: local.reconnectGraceSeconds,
188
+ maxFrameBytes: local.maxFrameBytes,
189
189
  };
190
190
  }
191
191
  case "slow_down":
192
- throw new ApiError("device.slow_down", `Polling too fast; wait ${r[1]} seconds between polls`, [{ interval: Number(r[1]) }]);
192
+ throw new ApiError("device_sign_in.slow_down", `Polling too fast; wait ${r[1]} seconds between polls`, [{ interval: Number(r[1]) }]);
193
193
  case "denied":
194
- throw new ApiError("device.denied", "The sign-in was denied in the browser");
194
+ throw new ApiError("device_sign_in.denied", "The sign-in was denied in the browser");
195
195
  case "pending":
196
196
  case "claimed":
197
- throw new ApiError("device.authorization_pending", "Waiting for the code to be confirmed in the browser");
197
+ throw new ApiError("device_sign_in.authorization_pending", "Waiting for the code to be confirmed in the browser");
198
198
  default:
199
199
  throw expired();
200
200
  }
@@ -206,10 +206,10 @@ let DeviceAuthService = class DeviceAuthService {
206
206
  }
207
207
  /**
208
208
  * The person confirms a user code: in an org where they may use agents (`agents.use`), into
209
- * one of their own live device environments or a new one named `name` (` 2`, ` 3`, … appended
210
- * while the name is taken). One transaction creates the environment if needed, issues the
211
- * machine (revoking the environment's previous one) and audits
212
- * `environment.machine_connected` (retried once when a concurrent confirmation took the new
209
+ * one of their own live local devices or a new one named `name` (` 2`, ` 3`, … appended
210
+ * while the name is taken). One transaction creates the device if needed, issues the
211
+ * machine (revoking the device's previous one) and audits
212
+ * `device.machine_connected` (retried once when a concurrent confirmation took the new
213
213
  * name); after the commit the credential is parked for the poll ({@link park}). The code is
214
214
  * claimed first, so two confirmations of one code cannot both issue a machine; a confirmation
215
215
  * that fails before the commit leaves it pending.
@@ -223,9 +223,7 @@ let DeviceAuthService = class DeviceAuthService {
223
223
  try {
224
224
  issued = await this.confirmIn(principal.account.id, input, info).catch((e) => {
225
225
  // a concurrent confirmation took the same new name between our read and our insert
226
- if (input.name !== undefined &&
227
- e instanceof ApiError &&
228
- e.code === "environment.name_taken") {
226
+ if (input.name !== undefined && e instanceof ApiError && e.code === "device.name_taken") {
229
227
  return this.confirmIn(principal.account.id, input, info);
230
228
  }
231
229
  throw e;
@@ -236,12 +234,12 @@ let DeviceAuthService = class DeviceAuthService {
236
234
  throw e;
237
235
  }
238
236
  await this.park(hash, info, issued);
239
- return { environmentId: issued.environmentId };
237
+ return { deviceId: issued.deviceId };
240
238
  }
241
239
  /**
242
240
  * Parks the committed machine's credential for the poll. When that fails (the code expired
243
241
  * meanwhile, or Redis failed) the machine is revoked again, so no credential nobody holds stays
244
- * valid, and the person is told to start over: `device.expired` / `device.unavailable`.
242
+ * valid, and the person is told to start over: `device_sign_in.expired` / `device_sign_in.unavailable`.
245
243
  */
246
244
  async park(hash, info, issued) {
247
245
  let parked;
@@ -260,16 +258,16 @@ let DeviceAuthService = class DeviceAuthService {
260
258
  return;
261
259
  }
262
260
  this.log.warn("device credential could not be parked; the machine is revoked", {
263
- environmentId: issued.environmentId,
261
+ deviceId: issued.deviceId,
264
262
  machineId: issued.machineId,
265
263
  err: failure,
266
264
  });
267
265
  await this.abandon(issued);
268
- // the program's next poll then ends with device.expired instead of waiting out the TTL
266
+ // the program's next poll then ends with device_sign_in.expired instead of waiting out the TTL
269
267
  await this.redis.del(authKeyOf(hash), deviceUserKey(info.userCode)).catch(() => undefined);
270
268
  if (failure === undefined)
271
269
  throw expired();
272
- throw new ApiError("device.unavailable", "The machine could not be connected; run capybara-device login again");
270
+ throw new ApiError("device_sign_in.unavailable", "The machine could not be connected; run capybara-device login again");
273
271
  }
274
272
  /** Revokes a machine whose credential never reached the program (see {@link park}). */
275
273
  async abandon(issued) {
@@ -279,12 +277,12 @@ let DeviceAuthService = class DeviceAuthService {
279
277
  await audit(this.db.db, {
280
278
  actorAccountId: issued.accountId,
281
279
  orgId: grant.orgId,
282
- action: "environment.machine_revoked",
283
- target: grant.environmentId,
280
+ action: "device.machine_revoked",
281
+ target: grant.deviceId,
284
282
  detail: { machineId, reason: "sign_in_incomplete" },
285
283
  });
286
284
  }
287
- /** The person refuses a user code: the program's next poll gets `device.denied`. */
285
+ /** The person refuses a user code: the program's next poll gets `device_sign_in.denied`. */
288
286
  async deny(userCode) {
289
287
  const { info, hash } = await this.lookup(userCode, "pending");
290
288
  if (!(await this.transition(hash, "pending", "denied")))
@@ -293,53 +291,53 @@ let DeviceAuthService = class DeviceAuthService {
293
291
  }
294
292
  async confirmIn(accountId, input, info) {
295
293
  const { orgId } = input;
296
- let environmentId;
294
+ let deviceId;
297
295
  if (input.name !== undefined) {
298
296
  const name = await this.freeName(orgId, accountId, input.name);
299
- environmentId = (await this.environments.createDevice(orgId, accountId, name)).id;
297
+ deviceId = (await this.devices.createLocal(orgId, accountId, name)).id;
300
298
  }
301
299
  else {
302
300
  const env = await this.db
303
- .selectFrom("environments")
301
+ .selectFrom("devices")
304
302
  .select("id")
305
- .where("id", "=", input.environmentId)
303
+ .where("id", "=", input.deviceId)
306
304
  .where("org_id", "=", orgId)
307
305
  .where("owner_kind", "=", "personal")
308
306
  .where("owner_account_id", "=", accountId)
309
- .where("source", "=", "device")
310
- .where("provider", "=", DEVICE_PROVIDER)
307
+ .where("source", "=", "local")
308
+ .where("provider", "=", LOCAL_PROVIDER)
311
309
  .where("deleted_at", "is", null)
312
310
  .forNoKeyUpdate()
313
311
  .executeTakeFirst();
314
312
  if (!env)
315
- throw environmentNotFound();
316
- environmentId = env.id;
313
+ throw deviceNotFound();
314
+ deviceId = env.id;
317
315
  }
318
316
  const { machine } = info;
319
317
  const { machineId, credential } = await this.machines.issue({
320
318
  orgId,
321
- environmentId,
319
+ deviceId,
322
320
  accountId,
323
321
  ...machine,
324
322
  });
325
323
  await audit(this.db.db, {
326
324
  actorAccountId: accountId,
327
325
  orgId,
328
- action: "environment.machine_connected",
329
- target: environmentId,
326
+ action: "device.machine_connected",
327
+ target: deviceId,
330
328
  detail: { machineId, ...machine },
331
329
  });
332
330
  return {
333
- environmentId,
331
+ deviceId,
334
332
  machineId,
335
333
  accountId,
336
- grant: { credential, orgId, environmentId },
334
+ grant: { credential, orgId, deviceId },
337
335
  };
338
336
  }
339
337
  /** `name`, or `name 2`, `name 3`, … : the first that is none of the person's live names. */
340
338
  async freeName(orgId, accountId, name) {
341
339
  const taken = new Set((await this.db
342
- .selectFrom("environments")
340
+ .selectFrom("devices")
343
341
  .select("name")
344
342
  .where("org_id", "=", orgId)
345
343
  .where("owner_account_id", "=", accountId)
@@ -353,7 +351,7 @@ let DeviceAuthService = class DeviceAuthService {
353
351
  }
354
352
  return candidate;
355
353
  }
356
- /** The code behind a user code with status `status`, else `device.code_invalid`. */
354
+ /** The code behind a user code with status `status`, else `device_sign_in.code_invalid`. */
357
355
  async lookup(userCode, status) {
358
356
  const code = normalizeUserCode(userCode);
359
357
  if (code === null)
@@ -370,11 +368,11 @@ let DeviceAuthService = class DeviceAuthService {
370
368
  const args = grant === undefined ? [from, to] : [from, to, "grant", grant];
371
369
  return (await this.redis.eval(TRANSITION, 1, authKeyOf(hash), ...args)) === 1;
372
370
  }
373
- /** `http.publicUrl` without trailing slashes; unset → `environment.unavailable`. */
371
+ /** `http.publicUrl` without trailing slashes; unset → `device.unavailable`. */
374
372
  publicUrl() {
375
373
  const url = this.config.get().http.publicUrl;
376
374
  if (!url) {
377
- throw new ApiError("environment.unavailable", "Connecting machines needs http.publicUrl to be configured; ask the super admin");
375
+ throw new ApiError("device.unavailable", "Connecting machines needs http.publicUrl to be configured; ask the super admin");
378
376
  }
379
377
  return url.replace(/\/+$/, "");
380
378
  }
@@ -395,9 +393,9 @@ DeviceAuthService = __decorate([
395
393
  __param(1, Inject(TransactionHost)),
396
394
  __param(2, Inject(REDIS)),
397
395
  __param(3, Inject(KernelConfigService)),
398
- __param(4, Inject(EnvironmentsService)),
396
+ __param(4, Inject(DevicesService)),
399
397
  __param(5, Inject(MachinesService)),
400
398
  __param(6, Inject(KERNEL_LOGGER))
401
399
  ], DeviceAuthService);
402
400
  export { DeviceAuthService };
403
- const expired = () => new ApiError("device.expired", "This sign-in code has expired or was already used; run capybara-device login again");
401
+ const expired = () => new ApiError("device_sign_in.expired", "This sign-in code has expired or was already used; run capybara-device login again");
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Device sign-in (environments spec §13.3): {@link DeviceAuthService} behind
3
+ * `DeviceAuthController`. Kept apart from {@link LocalDevicesModule}, which `DevicesModule`
4
+ * imports (deleting a device revokes its machine), while sign-in needs both.
5
+ */
6
+ export declare class DeviceAuthModule {
7
+ }
@@ -5,19 +5,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { Module } from "@nestjs/common";
8
- import { EnvironmentsModule } from "../environments/environments.module.js";
8
+ import { DevicesModule } from "../devices/devices.module.js";
9
9
  import { DeviceAuthService } from "./device-auth.js";
10
- import { DevicesModule } from "./devices.module.js";
10
+ import { LocalDevicesModule } from "./local-devices.module.js";
11
11
  /**
12
12
  * Device sign-in (environments spec §13.3): {@link DeviceAuthService} behind
13
- * `DeviceAuthController`. Kept apart from {@link DevicesModule}, which `EnvironmentsModule`
14
- * imports (deleting an environment revokes its machine), while sign-in needs both.
13
+ * `DeviceAuthController`. Kept apart from {@link LocalDevicesModule}, which `DevicesModule`
14
+ * imports (deleting a device revokes its machine), while sign-in needs both.
15
15
  */
16
16
  let DeviceAuthModule = class DeviceAuthModule {
17
17
  };
18
18
  DeviceAuthModule = __decorate([
19
19
  Module({
20
- imports: [DevicesModule, EnvironmentsModule],
20
+ imports: [LocalDevicesModule, DevicesModule],
21
21
  providers: [DeviceAuthService],
22
22
  exports: [DeviceAuthService],
23
23
  })
@@ -5,14 +5,14 @@ import type { MachineIdentity } from "./machines.js";
5
5
  export declare const DEVICE_CONNECT_ROUTE = "/device/connect";
6
6
  /** The header carrying the program's protocol version. */
7
7
  export declare const DEVICE_PROTOCOL_HEADER = "x-capybara-device-protocol";
8
- /** What the route needs from the gateway (`DeviceGateway`). */
8
+ /** What the route needs from the gateway (`LocalDeviceGateway`). */
9
9
  export interface DeviceRoutesGateway {
10
10
  authenticate(credential: string): Promise<MachineIdentity | null>;
11
11
  accept(socket: WebSocket, identity: MachineIdentity, credential: string): void;
12
12
  }
13
13
  export interface DeviceRoutesOptions {
14
14
  gateway: DeviceRoutesGateway;
15
- /** `environments.device.maxFrameBytes`: a larger incoming frame closes the socket (1009). */
15
+ /** `devices.local.maxFrameBytes`: a larger incoming frame closes the socket (1009). */
16
16
  maxFrameBytes: number;
17
17
  }
18
18
  /**
@@ -24,7 +24,7 @@ export declare function isWebSocketUpgrade(req: FastifyRequest): boolean;
24
24
  * Registers `GET /device/connect` (the gateway role only) in its own encapsulated scope with
25
25
  * `@fastify/websocket`: a raw Fastify route outside Nest, so neither the API's `AuthGuard` nor its
26
26
  * CSRF check applies; the route checks the machine credential itself, before the upgrade (401
27
- * `device.credential_invalid`), then the protocol header (426 `environment.program_outdated`).
27
+ * `device.credential_invalid`), then the protocol header (426 `device.program_outdated`).
28
28
  * Must be called before Nest `app.init()`, on the root instance.
29
29
  *
30
30
  * `@fastify/websocket` sends every upgrade request of the server through the Fastify router; the
@@ -36,7 +36,7 @@ function bearer(req) {
36
36
  * Registers `GET /device/connect` (the gateway role only) in its own encapsulated scope with
37
37
  * `@fastify/websocket`: a raw Fastify route outside Nest, so neither the API's `AuthGuard` nor its
38
38
  * CSRF check applies; the route checks the machine credential itself, before the upgrade (401
39
- * `device.credential_invalid`), then the protocol header (426 `environment.program_outdated`).
39
+ * `device.credential_invalid`), then the protocol header (426 `device.program_outdated`).
40
40
  * Must be called before Nest `app.init()`, on the root instance.
41
41
  *
42
42
  * `@fastify/websocket` sends every upgrade request of the server through the Fastify router; the
@@ -73,7 +73,7 @@ export async function registerDeviceConnectRoute(fastify, opts) {
73
73
  if (req.headers[DEVICE_PROTOCOL_HEADER] !== String(DEVICE_PROTOCOL_VERSION)) {
74
74
  return reply
75
75
  .code(426)
76
- .send(errorBody("environment.program_outdated", `This kernel speaks device protocol ${DEVICE_PROTOCOL_VERSION}. ` +
76
+ .send(errorBody("device.program_outdated", `This kernel speaks device protocol ${DEVICE_PROTOCOL_VERSION}. ` +
77
77
  "Update capybara-device."));
78
78
  }
79
79
  identities.set(req, { identity, cred });
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ /** `POST /api/v1/device/authorize`: the machine as the program describes it. */
3
+ export declare const DeviceAuthorizeBody: z.ZodObject<{
4
+ name: z.ZodString;
5
+ os: z.ZodEnum<{
6
+ darwin: "darwin";
7
+ linux: "linux";
8
+ }>;
9
+ arch: z.ZodString;
10
+ programVersion: z.ZodString;
11
+ }, z.core.$strict>;
12
+ /** `POST /api/v1/device/token`: the secret device code from `authorize`. */
13
+ export declare const DeviceTokenBody: z.ZodObject<{
14
+ deviceCode: z.ZodString;
15
+ }, z.core.$strict>;
16
+ export declare const DeviceUserCodeParams: z.ZodObject<{
17
+ userCode: z.ZodString;
18
+ }, z.core.$strip>;
19
+ export declare const DeviceUserCodeBody: z.ZodObject<{
20
+ userCode: z.ZodString;
21
+ }, z.core.$strict>;
22
+ /**
23
+ * `POST /api/v1/device/confirm`: the org and exactly one of an existing local device of the
24
+ * person's (`deviceId`) or the name of a new one (`name`).
25
+ */
26
+ export declare const DeviceConfirmBody: z.ZodObject<{
27
+ userCode: z.ZodString;
28
+ orgId: z.ZodString;
29
+ deviceId: z.ZodOptional<z.ZodUUID>;
30
+ name: z.ZodOptional<z.ZodString>;
31
+ }, z.core.$strict>;
32
+ declare const DeviceAuthorizeBodyDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
33
+ name: z.ZodString;
34
+ os: z.ZodEnum<{
35
+ darwin: "darwin";
36
+ linux: "linux";
37
+ }>;
38
+ arch: z.ZodString;
39
+ programVersion: z.ZodString;
40
+ }, z.core.$strict>>;
41
+ export declare class DeviceAuthorizeBodyDto extends DeviceAuthorizeBodyDto_base {
42
+ }
43
+ declare const DeviceTokenBodyDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
44
+ deviceCode: z.ZodString;
45
+ }, z.core.$strict>>;
46
+ export declare class DeviceTokenBodyDto extends DeviceTokenBodyDto_base {
47
+ }
48
+ declare const DeviceUserCodeParamsDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
49
+ userCode: z.ZodString;
50
+ }, z.core.$strip>>;
51
+ export declare class DeviceUserCodeParamsDto extends DeviceUserCodeParamsDto_base {
52
+ }
53
+ declare const DeviceUserCodeBodyDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
54
+ userCode: z.ZodString;
55
+ }, z.core.$strict>>;
56
+ export declare class DeviceUserCodeBodyDto extends DeviceUserCodeBodyDto_base {
57
+ }
58
+ declare const DeviceConfirmBodyDto_base: import("../infra/validation/create-zod-dto.js").ZodDtoClass<z.ZodObject<{
59
+ userCode: z.ZodString;
60
+ orgId: z.ZodString;
61
+ deviceId: z.ZodOptional<z.ZodUUID>;
62
+ name: z.ZodOptional<z.ZodString>;
63
+ }, z.core.$strict>>;
64
+ export declare class DeviceConfirmBodyDto extends DeviceConfirmBodyDto_base {
65
+ }
66
+ export {};
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ import { DeviceName } from "../devices/dto.js";
3
+ import { createZodDto } from "../infra/validation/create-zod-dto.js";
4
+ /** `POST /api/v1/device/authorize`: the machine as the program describes it. */
5
+ export const DeviceAuthorizeBody = z
6
+ .object({
7
+ name: z.string().trim().min(1).max(64),
8
+ os: z.enum(["darwin", "linux"]),
9
+ arch: z.string().trim().min(1).max(32),
10
+ programVersion: z.string().trim().min(1).max(64),
11
+ })
12
+ .strict();
13
+ /** `POST /api/v1/device/token`: the secret device code from `authorize`. */
14
+ export const DeviceTokenBody = z.object({ deviceCode: z.string().min(1).max(200) }).strict();
15
+ /** A user code as typed (`XXXX-XXXX`; case, spaces and the dash are forgiven). */
16
+ const UserCode = z.string().min(1).max(32);
17
+ export const DeviceUserCodeParams = z.object({ userCode: UserCode });
18
+ export const DeviceUserCodeBody = z.object({ userCode: UserCode }).strict();
19
+ /**
20
+ * `POST /api/v1/device/confirm`: the org and exactly one of an existing local device of the
21
+ * person's (`deviceId`) or the name of a new one (`name`).
22
+ */
23
+ export const DeviceConfirmBody = z
24
+ .object({
25
+ userCode: UserCode,
26
+ orgId: z.string().min(1).max(100),
27
+ deviceId: z.uuid().optional(),
28
+ name: DeviceName.optional(),
29
+ })
30
+ .strict()
31
+ .refine((b) => (b.deviceId === undefined) !== (b.name === undefined), {
32
+ message: "Give exactly one of deviceId and name",
33
+ path: ["deviceId"],
34
+ });
35
+ export class DeviceAuthorizeBodyDto extends createZodDto(DeviceAuthorizeBody, "DeviceAuthorizeBody") {
36
+ }
37
+ export class DeviceTokenBodyDto extends createZodDto(DeviceTokenBody, "DeviceTokenBody") {
38
+ }
39
+ export class DeviceUserCodeParamsDto extends createZodDto(DeviceUserCodeParams, "DeviceUserCodeParams") {
40
+ }
41
+ export class DeviceUserCodeBodyDto extends createZodDto(DeviceUserCodeBody, "DeviceUserCodeBody") {
42
+ }
43
+ export class DeviceConfirmBodyDto extends createZodDto(DeviceConfirmBody, "DeviceConfirmBody") {
44
+ }
@@ -1,25 +1,25 @@
1
1
  /**
2
2
  * Redis keys and bus topics of the connected-machine relay (environments spec §6, §13). Every key
3
- * is per environment (or per request); writers set a TTL on each.
3
+ * is per device (or per request); writers set a TTL on each.
4
4
  */
5
- /** The lease of the replica holding the machine's connection: `capk:device-lease:<environmentId>`. */
6
- export declare const deviceLeaseKey: (environmentId: string) => string;
7
- /** The list of requests waiting for the machine: `capk:device-req:<environmentId>`. */
8
- export declare const deviceReqKey: (environmentId: string) => string;
5
+ /** The lease of the replica holding the machine's connection: `capk:device-lease:<deviceId>`. */
6
+ export declare const deviceLeaseKey: (deviceId: string) => string;
7
+ /** The list of requests waiting for the machine: `capk:device-req:<deviceId>`. */
8
+ export declare const deviceReqKey: (deviceId: string) => string;
9
9
  /** The result of one request: `capk:device-res:<requestId>`. */
10
10
  export declare const deviceResKey: (requestId: string) => string;
11
11
  /** The prefix of {@link deviceTakenKey} (the holder's Lua script builds the key from it). */
12
12
  export declare const DEVICE_TAKEN_PREFIX = "capk:device-taken:";
13
13
  /**
14
- * A request the holder forwarded to a machine: `capk:device-taken:<requestId>` → the environment
15
- * id. Only a result for a taken request of the socket's own environment is accepted.
14
+ * A request the holder forwarded to a machine: `capk:device-taken:<requestId>` → the device
15
+ * id. Only a result for a taken request of the socket's own device is accepted.
16
16
  */
17
17
  export declare const deviceTakenKey: (requestId: string) => string;
18
- /** A new request for the machine of the environment. */
19
- export declare const deviceReqTopic: (environmentId: string) => string;
18
+ /** A new request for the machine of the device. */
19
+ export declare const deviceReqTopic: (deviceId: string) => string;
20
20
  /** The result of one request is ready. */
21
21
  export declare const deviceResTopic: (requestId: string) => string;
22
22
  /** Another replica took the machine's connection over. */
23
- export declare const deviceTakeoverTopic: (environmentId: string) => string;
23
+ export declare const deviceTakeoverTopic: (deviceId: string) => string;
24
24
  /** The machine's credential was revoked: its connection is closed. */
25
- export declare const deviceRevokedTopic: (environmentId: string) => string;
25
+ export declare const deviceRevokedTopic: (deviceId: string) => string;
@@ -1,25 +1,25 @@
1
1
  /**
2
2
  * Redis keys and bus topics of the connected-machine relay (environments spec §6, §13). Every key
3
- * is per environment (or per request); writers set a TTL on each.
3
+ * is per device (or per request); writers set a TTL on each.
4
4
  */
5
- /** The lease of the replica holding the machine's connection: `capk:device-lease:<environmentId>`. */
6
- export const deviceLeaseKey = (environmentId) => `capk:device-lease:${environmentId}`;
7
- /** The list of requests waiting for the machine: `capk:device-req:<environmentId>`. */
8
- export const deviceReqKey = (environmentId) => `capk:device-req:${environmentId}`;
5
+ /** The lease of the replica holding the machine's connection: `capk:device-lease:<deviceId>`. */
6
+ export const deviceLeaseKey = (deviceId) => `capk:device-lease:${deviceId}`;
7
+ /** The list of requests waiting for the machine: `capk:device-req:<deviceId>`. */
8
+ export const deviceReqKey = (deviceId) => `capk:device-req:${deviceId}`;
9
9
  /** The result of one request: `capk:device-res:<requestId>`. */
10
10
  export const deviceResKey = (requestId) => `capk:device-res:${requestId}`;
11
11
  /** The prefix of {@link deviceTakenKey} (the holder's Lua script builds the key from it). */
12
12
  export const DEVICE_TAKEN_PREFIX = "capk:device-taken:";
13
13
  /**
14
- * A request the holder forwarded to a machine: `capk:device-taken:<requestId>` → the environment
15
- * id. Only a result for a taken request of the socket's own environment is accepted.
14
+ * A request the holder forwarded to a machine: `capk:device-taken:<requestId>` → the device
15
+ * id. Only a result for a taken request of the socket's own device is accepted.
16
16
  */
17
17
  export const deviceTakenKey = (requestId) => `${DEVICE_TAKEN_PREFIX}${requestId}`;
18
- /** A new request for the machine of the environment. */
19
- export const deviceReqTopic = (environmentId) => `device.req.${environmentId}`;
18
+ /** A new request for the machine of the device. */
19
+ export const deviceReqTopic = (deviceId) => `device.req.${deviceId}`;
20
20
  /** The result of one request is ready. */
21
21
  export const deviceResTopic = (requestId) => `device.res.${requestId}`;
22
22
  /** Another replica took the machine's connection over. */
23
- export const deviceTakeoverTopic = (environmentId) => `device.takeover.${environmentId}`;
23
+ export const deviceTakeoverTopic = (deviceId) => `device.takeover.${deviceId}`;
24
24
  /** The machine's credential was revoked: its connection is closed. */
25
- export const deviceRevokedTopic = (environmentId) => `device.revoked.${environmentId}`;
25
+ export const deviceRevokedTopic = (deviceId) => `device.revoked.${deviceId}`;
@@ -9,13 +9,13 @@ import { type MachineIdentity, MachinesService } from "./machines.js";
9
9
  export declare const DEVICE_CLOSE: {
10
10
  /** The kernel is shutting down: reconnect (another gateway replica takes over). */
11
11
  readonly shutdown: 1001;
12
- /** A frame larger than `environments.device.maxFrameBytes` (sent by `ws` itself). */
12
+ /** A frame larger than `devices.local.maxFrameBytes` (sent by `ws` itself). */
13
13
  readonly tooBig: 1009;
14
14
  /** The kernel failed (e.g. the database): reconnect. */
15
15
  readonly internal: 1011;
16
16
  /** The lease was lost (renewal kept failing or the key was taken): reconnect. */
17
17
  readonly leaseLost: 4001;
18
- /** A newer connection of the environment took over: the program exits. */
18
+ /** A newer connection of the device took over: the program exits. */
19
19
  readonly replaced: 4002;
20
20
  /** The machine's credential was revoked: the program exits. */
21
21
  readonly revoked: 4003;
@@ -55,17 +55,17 @@ declare class DeviceConnection {
55
55
  private chain;
56
56
  /** Resolves once the lease is handed back (or was never held). */
57
57
  private released;
58
- constructor(gw: DeviceGateway, socket: WebSocket, identity: MachineIdentity, credential: string);
59
- get environmentId(): string;
58
+ constructor(gw: LocalDeviceGateway, socket: WebSocket, identity: MachineIdentity, credential: string);
59
+ get deviceId(): string;
60
60
  start(): void;
61
61
  private onFrame;
62
62
  /**
63
63
  * Stores one result and announces it (the relay's wire, relay.ts), only for a request taken for
64
- * this environment (ruling R20); anything else is dropped.
64
+ * this device (ruling R20); anything else is dropped.
65
65
  */
66
66
  private store;
67
67
  /**
68
- * Claims the environment's lease; true when this connection holds it. The newest connection
68
+ * Claims the device's lease; true when this connection holds it. The newest connection
69
69
  * wins (ruling R21): when another connection holds the lease, a takeover is published (the
70
70
  * holder yields to any takeover) and the lease retried every {@link CLAIM_RETRY_MS} for
71
71
  * {@link CLAIM_TIMEOUT_MS}, then 4409 (the program reconnects). A claimer never yields.
@@ -79,7 +79,7 @@ declare class DeviceConnection {
79
79
  /** The next ping (a chain of timeouts; the lease renewal is LockService's, not this timer's). */
80
80
  private schedulePing;
81
81
  private ping;
82
- /** The credential still stands (membership, org and environment are read live). */
82
+ /** The credential still stands (membership, org and device are read live). */
83
83
  private reauthenticate;
84
84
  private traffic;
85
85
  /** Closes the socket with `code` and hands the lease back; idempotent. */
@@ -90,17 +90,17 @@ declare class DeviceConnection {
90
90
  /**
91
91
  * The gateway role's half of the device relay (environments spec §13.4): holds the WebSocket
92
92
  * connections of connected machines (`GET /device/connect`, device-routes.ts). One connection per
93
- * environment across replicas, under the lease `capk:device-lease:<environmentId>` (the newest
94
- * connection wins: it publishes `device.takeover.<environmentId>` and the holder lets go). The
95
- * holder drains `capk:device-req:<environmentId>` on every `device.req.<environmentId>` nudge,
96
- * once after claiming and on every ping, marking each forwarded request taken for its environment
93
+ * device across replicas, under the lease `capk:device-lease:<deviceId>` (the newest
94
+ * connection wins: it publishes `device.takeover.<deviceId>` and the holder lets go). The
95
+ * holder drains `capk:device-req:<deviceId>` on every `device.req.<deviceId>` nudge,
96
+ * once after claiming and on every ping, marking each forwarded request taken for its device
97
97
  * (`capk:device-taken:<id>`, TTL the reconnect grace plus the request's deadline plus a margin).
98
- * A `res` is accepted only for a request taken for the socket's environment: it is stored under
98
+ * A `res` is accepted only for a request taken for the socket's device: it is stored under
99
99
  * `capk:device-res:<id>` for the rest of that TTL and published on `device.res.<id>`.
100
- * `device.revoked.<environmentId>` closes the connection of that machine only (ruling R16). The
100
+ * `device.revoked.<deviceId>` closes the connection of that machine only (ruling R16). The
101
101
  * sockets are this process's own; everything other replicas need is in Redis.
102
102
  */
103
- export declare class DeviceGateway {
103
+ export declare class LocalDeviceGateway {
104
104
  readonly machines: Pick<MachinesService, "authenticate" | "recordHello" | "touch">;
105
105
  readonly locks: Pick<LockService, "hold">;
106
106
  readonly bus: ExtensionContext["bus"];