@elaraai/e3-rack 0.0.0-bootstrap.0 → 1.0.94

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 (306) hide show
  1. package/README.md +407 -2
  2. package/dist/src/client/client.spec.d.ts +6 -0
  3. package/dist/src/client/client.spec.d.ts.map +1 -0
  4. package/dist/src/client/client.spec.js +150 -0
  5. package/dist/src/client/client.spec.js.map +1 -0
  6. package/dist/src/client/connect.d.ts +52 -0
  7. package/dist/src/client/connect.d.ts.map +1 -0
  8. package/dist/src/client/connect.js +112 -0
  9. package/dist/src/client/connect.js.map +1 -0
  10. package/dist/src/client/hub-client.d.ts +57 -0
  11. package/dist/src/client/hub-client.d.ts.map +1 -0
  12. package/dist/src/client/hub-client.js +87 -0
  13. package/dist/src/client/hub-client.js.map +1 -0
  14. package/dist/src/client/local-http.d.ts +78 -0
  15. package/dist/src/client/local-http.d.ts.map +1 -0
  16. package/dist/src/client/local-http.js +149 -0
  17. package/dist/src/client/local-http.js.map +1 -0
  18. package/dist/src/client/session-attempts.d.ts +20 -0
  19. package/dist/src/client/session-attempts.d.ts.map +1 -0
  20. package/dist/src/client/session-attempts.js +88 -0
  21. package/dist/src/client/session-attempts.js.map +1 -0
  22. package/dist/src/client/session-data-server.d.ts +37 -0
  23. package/dist/src/client/session-data-server.d.ts.map +1 -0
  24. package/dist/src/client/session-data-server.js +280 -0
  25. package/dist/src/client/session-data-server.js.map +1 -0
  26. package/dist/src/client/session-data-server.spec.d.ts +6 -0
  27. package/dist/src/client/session-data-server.spec.d.ts.map +1 -0
  28. package/dist/src/client/session-data-server.spec.js +192 -0
  29. package/dist/src/client/session-data-server.spec.js.map +1 -0
  30. package/dist/src/client/session.d.ts +119 -0
  31. package/dist/src/client/session.d.ts.map +1 -0
  32. package/dist/src/client/session.js +290 -0
  33. package/dist/src/client/session.js.map +1 -0
  34. package/dist/src/hub/config.d.ts +74 -0
  35. package/dist/src/hub/config.d.ts.map +1 -0
  36. package/dist/src/hub/config.js +159 -0
  37. package/dist/src/hub/config.js.map +1 -0
  38. package/dist/src/hub/fair-lease-store.d.ts +36 -0
  39. package/dist/src/hub/fair-lease-store.d.ts.map +1 -0
  40. package/dist/src/hub/fair-lease-store.js +73 -0
  41. package/dist/src/hub/fair-lease-store.js.map +1 -0
  42. package/dist/src/hub/hub.d.ts +91 -0
  43. package/dist/src/hub/hub.d.ts.map +1 -0
  44. package/dist/src/hub/hub.js +641 -0
  45. package/dist/src/hub/hub.js.map +1 -0
  46. package/dist/src/hub/hub.spec.d.ts +6 -0
  47. package/dist/src/hub/hub.spec.d.ts.map +1 -0
  48. package/dist/src/hub/hub.spec.js +363 -0
  49. package/dist/src/hub/hub.spec.js.map +1 -0
  50. package/dist/src/hub/infrastructure.spec.d.ts +6 -0
  51. package/dist/src/hub/infrastructure.spec.d.ts.map +1 -0
  52. package/dist/src/hub/infrastructure.spec.js +211 -0
  53. package/dist/src/hub/infrastructure.spec.js.map +1 -0
  54. package/dist/src/hub/lock.d.ts +62 -0
  55. package/dist/src/hub/lock.d.ts.map +1 -0
  56. package/dist/src/hub/lock.js +165 -0
  57. package/dist/src/hub/lock.js.map +1 -0
  58. package/dist/src/hub/main.d.ts +16 -0
  59. package/dist/src/hub/main.d.ts.map +1 -0
  60. package/dist/src/hub/main.js +56 -0
  61. package/dist/src/hub/main.js.map +1 -0
  62. package/dist/src/hub/session-bridge.d.ts +116 -0
  63. package/dist/src/hub/session-bridge.d.ts.map +1 -0
  64. package/dist/src/hub/session-bridge.js +336 -0
  65. package/dist/src/hub/session-bridge.js.map +1 -0
  66. package/dist/src/identity/file-identity-store.d.ts +18 -0
  67. package/dist/src/identity/file-identity-store.d.ts.map +1 -0
  68. package/dist/src/identity/file-identity-store.js +34 -0
  69. package/dist/src/identity/file-identity-store.js.map +1 -0
  70. package/dist/src/identity/file-identity-store.spec.d.ts +6 -0
  71. package/dist/src/identity/file-identity-store.spec.d.ts.map +1 -0
  72. package/dist/src/identity/file-identity-store.spec.js +59 -0
  73. package/dist/src/identity/file-identity-store.spec.js.map +1 -0
  74. package/dist/src/identity/in-memory-identity-store.d.ts +48 -0
  75. package/dist/src/identity/in-memory-identity-store.d.ts.map +1 -0
  76. package/dist/src/identity/in-memory-identity-store.js +102 -0
  77. package/dist/src/identity/in-memory-identity-store.js.map +1 -0
  78. package/dist/src/identity/machine-identity.d.ts +134 -0
  79. package/dist/src/identity/machine-identity.d.ts.map +1 -0
  80. package/dist/src/identity/machine-identity.js +65 -0
  81. package/dist/src/identity/machine-identity.js.map +1 -0
  82. package/dist/src/index.d.ts +34 -0
  83. package/dist/src/index.d.ts.map +1 -0
  84. package/dist/src/index.js +34 -0
  85. package/dist/src/index.js.map +1 -0
  86. package/dist/src/lease/closure.d.ts +96 -0
  87. package/dist/src/lease/closure.d.ts.map +1 -0
  88. package/dist/src/lease/closure.js +192 -0
  89. package/dist/src/lease/closure.js.map +1 -0
  90. package/dist/src/lease/closure.spec.d.ts +6 -0
  91. package/dist/src/lease/closure.spec.d.ts.map +1 -0
  92. package/dist/src/lease/closure.spec.js +35 -0
  93. package/dist/src/lease/closure.spec.js.map +1 -0
  94. package/dist/src/lease/coordinator.d.ts +34 -0
  95. package/dist/src/lease/coordinator.d.ts.map +1 -0
  96. package/dist/src/lease/coordinator.js +42 -0
  97. package/dist/src/lease/coordinator.js.map +1 -0
  98. package/dist/src/lease/in-memory-lease-store.d.ts +58 -0
  99. package/dist/src/lease/in-memory-lease-store.d.ts.map +1 -0
  100. package/dist/src/lease/in-memory-lease-store.js +132 -0
  101. package/dist/src/lease/in-memory-lease-store.js.map +1 -0
  102. package/dist/src/lease/lease-store.d.ts +169 -0
  103. package/dist/src/lease/lease-store.d.ts.map +1 -0
  104. package/dist/src/lease/lease-store.js +94 -0
  105. package/dist/src/lease/lease-store.js.map +1 -0
  106. package/dist/src/lease/lease-store.spec.d.ts +6 -0
  107. package/dist/src/lease/lease-store.spec.d.ts.map +1 -0
  108. package/dist/src/lease/lease-store.spec.js +8 -0
  109. package/dist/src/lease/lease-store.spec.js.map +1 -0
  110. package/dist/src/lease/rack-dispatch.d.ts +105 -0
  111. package/dist/src/lease/rack-dispatch.d.ts.map +1 -0
  112. package/dist/src/lease/rack-dispatch.js +6 -0
  113. package/dist/src/lease/rack-dispatch.js.map +1 -0
  114. package/dist/src/mutation-queue.d.ts +13 -0
  115. package/dist/src/mutation-queue.d.ts.map +1 -0
  116. package/dist/src/mutation-queue.js +17 -0
  117. package/dist/src/mutation-queue.js.map +1 -0
  118. package/dist/src/paths.d.ts +56 -0
  119. package/dist/src/paths.d.ts.map +1 -0
  120. package/dist/src/paths.js +82 -0
  121. package/dist/src/paths.js.map +1 -0
  122. package/dist/src/protocol/control.d.ts +295 -0
  123. package/dist/src/protocol/control.d.ts.map +1 -0
  124. package/dist/src/protocol/control.js +74 -0
  125. package/dist/src/protocol/control.js.map +1 -0
  126. package/dist/src/protocol/index.d.ts +9 -0
  127. package/dist/src/protocol/index.d.ts.map +1 -0
  128. package/dist/src/protocol/index.js +9 -0
  129. package/dist/src/protocol/index.js.map +1 -0
  130. package/dist/src/protocol/rack-wire.d.ts +357 -0
  131. package/dist/src/protocol/rack-wire.d.ts.map +1 -0
  132. package/dist/src/protocol/rack-wire.js +262 -0
  133. package/dist/src/protocol/rack-wire.js.map +1 -0
  134. package/dist/src/protocol/rack-wire.spec.d.ts +6 -0
  135. package/dist/src/protocol/rack-wire.spec.d.ts.map +1 -0
  136. package/dist/src/protocol/rack-wire.spec.js +14 -0
  137. package/dist/src/protocol/rack-wire.spec.js.map +1 -0
  138. package/dist/src/protocol/registration.d.ts +70 -0
  139. package/dist/src/protocol/registration.d.ts.map +1 -0
  140. package/dist/src/protocol/registration.js +67 -0
  141. package/dist/src/protocol/registration.js.map +1 -0
  142. package/dist/src/protocol/session-data.d.ts +69 -0
  143. package/dist/src/protocol/session-data.d.ts.map +1 -0
  144. package/dist/src/protocol/session-data.js +26 -0
  145. package/dist/src/protocol/session-data.js.map +1 -0
  146. package/dist/src/protocol/task-envelope.d.ts +198 -0
  147. package/dist/src/protocol/task-envelope.d.ts.map +1 -0
  148. package/dist/src/protocol/task-envelope.js +93 -0
  149. package/dist/src/protocol/task-envelope.js.map +1 -0
  150. package/dist/src/protocol/wire-golden.d.ts +8 -0
  151. package/dist/src/protocol/wire-golden.d.ts.map +1 -0
  152. package/dist/src/protocol/wire-golden.js +34 -0
  153. package/dist/src/protocol/wire-golden.js.map +1 -0
  154. package/dist/src/protocol/wire-samples.d.ts +11 -0
  155. package/dist/src/protocol/wire-samples.d.ts.map +1 -0
  156. package/dist/src/protocol/wire-samples.js +52 -0
  157. package/dist/src/protocol/wire-samples.js.map +1 -0
  158. package/dist/src/registry/file-rack-registry.d.ts +68 -0
  159. package/dist/src/registry/file-rack-registry.d.ts.map +1 -0
  160. package/dist/src/registry/file-rack-registry.js +138 -0
  161. package/dist/src/registry/file-rack-registry.js.map +1 -0
  162. package/dist/src/registry/file-rack-registry.spec.d.ts +6 -0
  163. package/dist/src/registry/file-rack-registry.spec.d.ts.map +1 -0
  164. package/dist/src/registry/file-rack-registry.spec.js +50 -0
  165. package/dist/src/registry/file-rack-registry.spec.js.map +1 -0
  166. package/dist/src/registry/rack-registry.d.ts +64 -0
  167. package/dist/src/registry/rack-registry.d.ts.map +1 -0
  168. package/dist/src/registry/rack-registry.js +65 -0
  169. package/dist/src/registry/rack-registry.js.map +1 -0
  170. package/dist/src/registry/rack-registry.spec.d.ts +6 -0
  171. package/dist/src/registry/rack-registry.spec.d.ts.map +1 -0
  172. package/dist/src/registry/rack-registry.spec.js +8 -0
  173. package/dist/src/registry/rack-registry.spec.js.map +1 -0
  174. package/dist/src/routing/eligibility.d.ts +38 -0
  175. package/dist/src/routing/eligibility.d.ts.map +1 -0
  176. package/dist/src/routing/eligibility.js +78 -0
  177. package/dist/src/routing/eligibility.js.map +1 -0
  178. package/dist/src/routing/host-coupling.d.ts +26 -0
  179. package/dist/src/routing/host-coupling.d.ts.map +1 -0
  180. package/dist/src/routing/host-coupling.js +62 -0
  181. package/dist/src/routing/host-coupling.js.map +1 -0
  182. package/dist/src/routing/policy.d.ts +188 -0
  183. package/dist/src/routing/policy.d.ts.map +1 -0
  184. package/dist/src/routing/policy.js +212 -0
  185. package/dist/src/routing/policy.js.map +1 -0
  186. package/dist/src/routing/routing.spec.d.ts +6 -0
  187. package/dist/src/routing/routing.spec.d.ts.map +1 -0
  188. package/dist/src/routing/routing.spec.js +100 -0
  189. package/dist/src/routing/routing.spec.js.map +1 -0
  190. package/dist/src/routing/tiers.d.ts +22 -0
  191. package/dist/src/routing/tiers.d.ts.map +1 -0
  192. package/dist/src/routing/tiers.js +26 -0
  193. package/dist/src/routing/tiers.js.map +1 -0
  194. package/dist/src/runner/api-server.d.ts +45 -0
  195. package/dist/src/runner/api-server.d.ts.map +1 -0
  196. package/dist/src/runner/api-server.js +21 -0
  197. package/dist/src/runner/api-server.js.map +1 -0
  198. package/dist/src/runner/capacity.d.ts +13 -0
  199. package/dist/src/runner/capacity.d.ts.map +1 -0
  200. package/dist/src/runner/capacity.js +18 -0
  201. package/dist/src/runner/capacity.js.map +1 -0
  202. package/dist/src/runner/rack-body.d.ts +43 -0
  203. package/dist/src/runner/rack-body.d.ts.map +1 -0
  204. package/dist/src/runner/rack-body.js +208 -0
  205. package/dist/src/runner/rack-body.js.map +1 -0
  206. package/dist/src/runner/rack-runner.d.ts +62 -0
  207. package/dist/src/runner/rack-runner.d.ts.map +1 -0
  208. package/dist/src/runner/rack-runner.js +75 -0
  209. package/dist/src/runner/rack-runner.js.map +1 -0
  210. package/dist/src/runner/rack-runner.spec.d.ts +6 -0
  211. package/dist/src/runner/rack-runner.spec.d.ts.map +1 -0
  212. package/dist/src/runner/rack-runner.spec.js +302 -0
  213. package/dist/src/runner/rack-runner.spec.js.map +1 -0
  214. package/dist/src/runner/split.spec.d.ts +6 -0
  215. package/dist/src/runner/split.spec.d.ts.map +1 -0
  216. package/dist/src/runner/split.spec.js +188 -0
  217. package/dist/src/runner/split.spec.js.map +1 -0
  218. package/dist/src/runner-event.d.ts +261 -0
  219. package/dist/src/runner-event.d.ts.map +1 -0
  220. package/dist/src/runner-event.js +332 -0
  221. package/dist/src/runner-event.js.map +1 -0
  222. package/dist/src/server/beast2.d.ts +19 -0
  223. package/dist/src/server/beast2.d.ts.map +1 -0
  224. package/dist/src/server/beast2.js +18 -0
  225. package/dist/src/server/beast2.js.map +1 -0
  226. package/dist/src/server/body-limit.d.ts +16 -0
  227. package/dist/src/server/body-limit.d.ts.map +1 -0
  228. package/dist/src/server/body-limit.js +53 -0
  229. package/dist/src/server/body-limit.js.map +1 -0
  230. package/dist/src/server/body-limit.spec.d.ts +2 -0
  231. package/dist/src/server/body-limit.spec.d.ts.map +1 -0
  232. package/dist/src/server/body-limit.spec.js +32 -0
  233. package/dist/src/server/body-limit.spec.js.map +1 -0
  234. package/dist/src/server/bounded.d.ts +16 -0
  235. package/dist/src/server/bounded.d.ts.map +1 -0
  236. package/dist/src/server/bounded.js +39 -0
  237. package/dist/src/server/bounded.js.map +1 -0
  238. package/dist/src/server/dispatch.d.ts +137 -0
  239. package/dist/src/server/dispatch.d.ts.map +1 -0
  240. package/dist/src/server/dispatch.js +267 -0
  241. package/dist/src/server/dispatch.js.map +1 -0
  242. package/dist/src/server/env-publication.d.ts +45 -0
  243. package/dist/src/server/env-publication.d.ts.map +1 -0
  244. package/dist/src/server/env-publication.js +10 -0
  245. package/dist/src/server/env-publication.js.map +1 -0
  246. package/dist/src/server/index.d.ts +16 -0
  247. package/dist/src/server/index.d.ts.map +1 -0
  248. package/dist/src/server/index.js +17 -0
  249. package/dist/src/server/index.js.map +1 -0
  250. package/dist/src/server/protocol.spec.d.ts +6 -0
  251. package/dist/src/server/protocol.spec.d.ts.map +1 -0
  252. package/dist/src/server/protocol.spec.js +78 -0
  253. package/dist/src/server/protocol.spec.js.map +1 -0
  254. package/dist/src/server/rack-routes.d.ts +175 -0
  255. package/dist/src/server/rack-routes.d.ts.map +1 -0
  256. package/dist/src/server/rack-routes.js +755 -0
  257. package/dist/src/server/rack-routes.js.map +1 -0
  258. package/dist/src/server/rack-routes.spec.d.ts +6 -0
  259. package/dist/src/server/rack-routes.spec.d.ts.map +1 -0
  260. package/dist/src/server/rack-routes.spec.js +477 -0
  261. package/dist/src/server/rack-routes.spec.js.map +1 -0
  262. package/dist/src/server/storage-bridge.d.ts +140 -0
  263. package/dist/src/server/storage-bridge.d.ts.map +1 -0
  264. package/dist/src/server/storage-bridge.js +6 -0
  265. package/dist/src/server/storage-bridge.js.map +1 -0
  266. package/dist/src/state-file.d.ts +10 -0
  267. package/dist/src/state-file.d.ts.map +1 -0
  268. package/dist/src/state-file.js +38 -0
  269. package/dist/src/state-file.js.map +1 -0
  270. package/dist/src/testing/in-memory.d.ts +116 -0
  271. package/dist/src/testing/in-memory.d.ts.map +1 -0
  272. package/dist/src/testing/in-memory.js +193 -0
  273. package/dist/src/testing/in-memory.js.map +1 -0
  274. package/dist/src/testing/index.d.ts +14 -0
  275. package/dist/src/testing/index.d.ts.map +1 -0
  276. package/dist/src/testing/index.js +14 -0
  277. package/dist/src/testing/index.js.map +1 -0
  278. package/dist/src/testing/lease-store-contract.d.ts +14 -0
  279. package/dist/src/testing/lease-store-contract.d.ts.map +1 -0
  280. package/dist/src/testing/lease-store-contract.js +78 -0
  281. package/dist/src/testing/lease-store-contract.js.map +1 -0
  282. package/dist/src/testing/protocol-suite.d.ts +38 -0
  283. package/dist/src/testing/protocol-suite.d.ts.map +1 -0
  284. package/dist/src/testing/protocol-suite.js +207 -0
  285. package/dist/src/testing/protocol-suite.js.map +1 -0
  286. package/dist/src/testing/rack-registry-contract.d.ts +15 -0
  287. package/dist/src/testing/rack-registry-contract.d.ts.map +1 -0
  288. package/dist/src/testing/rack-registry-contract.js +106 -0
  289. package/dist/src/testing/rack-registry-contract.js.map +1 -0
  290. package/dist/src/testing/test-rack-agent.d.ts +121 -0
  291. package/dist/src/testing/test-rack-agent.d.ts.map +1 -0
  292. package/dist/src/testing/test-rack-agent.js +316 -0
  293. package/dist/src/testing/test-rack-agent.js.map +1 -0
  294. package/dist/src/tls/tls.d.ts +67 -0
  295. package/dist/src/tls/tls.d.ts.map +1 -0
  296. package/dist/src/tls/tls.js +200 -0
  297. package/dist/src/tls/tls.js.map +1 -0
  298. package/dist/src/tls/tls.spec.d.ts +6 -0
  299. package/dist/src/tls/tls.spec.d.ts.map +1 -0
  300. package/dist/src/tls/tls.spec.js +101 -0
  301. package/dist/src/tls/tls.spec.js.map +1 -0
  302. package/dist/src/version.d.ts +9 -0
  303. package/dist/src/version.d.ts.map +1 -0
  304. package/dist/src/version.js +10 -0
  305. package/dist/src/version.js.map +1 -0
  306. package/package.json +67 -7
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * The rack data-plane seam (#74, epic #67 design §10) — how the /rack
7
+ * storage routes hand object bytes to a credential-free agent:
8
+ *
9
+ * - objects travel by **presigned URL** — the API mints URLs, the agent
10
+ * transfers directly against the store, the API is never a byte proxy. A
11
+ * bridge that holds an object's bytes at hand may send them **inline** in
12
+ * the response body instead; the AWS bridge does not, as every object's
13
+ * bytes are in S3 (elaraai/e3-cloud#201);
14
+ * - each object a lease's guest wrote is **PUT at its content address**
15
+ * through a target bound to its SHA-256 and to the lease (#214), so the
16
+ * store refuses any other bytes; its commit checks the version the agent
17
+ * made (size, checksum, lease) and registers it, and never reads its body;
18
+ * - a lease that ends without committing what it wrote has those versions
19
+ * **discarded**: no uncatalogued version is left at a content address.
20
+ *
21
+ * Implemented by `S3DynamoRackStorageBridge` (e3-aws, over S3 and the object
22
+ * catalogue) and `InMemoryRackStorageBridge` (testing).
23
+ */
24
+ /** How the agent should obtain one object. */
25
+ export type RackObjectRead = {
26
+ kind: 'inline';
27
+ data: Uint8Array;
28
+ } | {
29
+ kind: 'url';
30
+ url: string;
31
+ };
32
+ /** A PUT target for one object at its content address (#214). */
33
+ export interface RackPutTarget {
34
+ /** The presigned URL */
35
+ readonly url: string;
36
+ /** The headers the PUT must send, as given: they are signed into its URL
37
+ * (the SHA-256 the store checks, and the lease's tag) */
38
+ readonly headers: Readonly<Record<string, string>>;
39
+ }
40
+ /** Supplies scoped object transfers and environment layers to rack routes. */
41
+ export interface RackStorageBridge {
42
+ /**
43
+ * Descriptor for an object the agent lacks: a presigned GET URL, or the
44
+ * bytes inline when the bridge holds them at hand.
45
+ *
46
+ * @param repo - The lease's repo
47
+ * @param hash - The object hash (already scope-validated by the route)
48
+ */
49
+ readDescriptor(repo: string, hash: string): Promise<RackObjectRead>;
50
+ /**
51
+ * A PUT target for an object a lease's guest wrote, at its content address,
52
+ * bound to its SHA-256 (the store refuses other bytes) and tagged with the
53
+ * lease (what {@link discardWrites} deletes). When the store holds the
54
+ * object already, it is re-referenced instead, as a write of it would be,
55
+ * and nothing is to be sent.
56
+ *
57
+ * @param repo - The lease's repo
58
+ * @param leaseId - The lease
59
+ * @param hash - The object's hash, as the agent declares it
60
+ * @param size - Its size in bytes
61
+ * @returns The target, or null when the store holds the object
62
+ */
63
+ writeTarget(repo: string, leaseId: string, hash: string, size: number): Promise<RackPutTarget | null>;
64
+ /**
65
+ * Takes in an object the agent PUT through a {@link writeTarget}: the
66
+ * version it made is checked (its size, its SHA-256 as the store computed
67
+ * it, and the lease's tag) and registered in the object catalogue, in one
68
+ * write with the condition that the rack holds the lease. So a commit that
69
+ * races its lease's end registers nothing, and the end's
70
+ * {@link discardWrites} never deletes a version the catalogue pins. Never a
71
+ * body read. An object another writer registered first is re-referenced,
72
+ * and this version deleted; a commit sent again is answered as the first.
73
+ *
74
+ * @param repo - The lease's repo
75
+ * @param leaseId - The lease
76
+ * @param rackId - The rack that holds it
77
+ * @param hash - The object's hash
78
+ * @param size - Its size in bytes
79
+ * @param version - The version the agent's PUT made, as the store answered it
80
+ * @returns false when the version is not the lease's, not these bytes, or
81
+ * the lease is not the rack's
82
+ */
83
+ commitWrite(repo: string, leaseId: string, rackId: string, hash: string, size: number, version: string): Promise<boolean>;
84
+ /**
85
+ * Deletes what a lease wrote that no catalogue row pins: every version at
86
+ * the keys it was issued targets for that carries its tag. A version the
87
+ * catalogue pins, and another lease's, are kept. Called only once the lease
88
+ * has ended.
89
+ *
90
+ * @param repo - The lease's repo
91
+ * @param leaseId - The lease
92
+ * @param hashes - The keys it was issued targets for
93
+ * @returns How many versions it deleted
94
+ */
95
+ discardWrites(repo: string, leaseId: string, hashes: readonly string[]): Promise<number>;
96
+ /**
97
+ * A presigned PUT target to a staging key for a whole output (#74, #210):
98
+ * nothing is trusted until {@link commitStaged} takes it in.
99
+ *
100
+ * @param repo - The lease's repo
101
+ * @param workspace - The lease's workspace (recorded on the transfer)
102
+ * @param hash - The agent-declared output hash
103
+ * @param size - The agent-declared output size in bytes
104
+ */
105
+ stagedTarget(repo: string, workspace: string, hash: string, size: bigint): Promise<{
106
+ url: string;
107
+ uploadId: string;
108
+ }>;
109
+ /**
110
+ * Takes a staged output in once the store's server-side copy of it hashes
111
+ * to the declared hash (#210): the large-output commit of an output sent
112
+ * whole.
113
+ *
114
+ * @returns false when verification fails (tampered/wrong upload) — the
115
+ * caller must then reject the completion
116
+ */
117
+ commitStaged(repo: string, hash: string, uploadId: string): Promise<boolean>;
118
+ /**
119
+ * Write an inline (small) output through the normal object-store write —
120
+ * the server computes the hash itself.
121
+ *
122
+ * @returns The server-computed content hash
123
+ */
124
+ writeInline(repo: string, data: Uint8Array): Promise<string>;
125
+ /**
126
+ * Read a published env-layer manifest (#94 Slice B) from the data
127
+ * bucket. Deployment-global (not repo-scoped) — the route has already
128
+ * scope-checked the env hash against the lease.
129
+ *
130
+ * @returns The manifest JSON, or null when unpublished
131
+ */
132
+ readEnvManifest(manifestKey: string): Promise<string | null>;
133
+ /**
134
+ * Mint a presigned GET for one published env-layer blob (#94 Slice B).
135
+ *
136
+ * @param blobKey - The content-addressed data-bucket key
137
+ */
138
+ presignEnvLayer(blobKey: string): Promise<string>;
139
+ }
140
+ //# sourceMappingURL=storage-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-bridge.d.ts","sourceRoot":"","sources":["../../../src/server/storage-bridge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8CAA8C;AAC9C,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;8DAC0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACpD;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEpE;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAEtG;;;;;;;;;;;;;;;;;;OAkBG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE1H;;;;;;;;;;OAUG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzF;;;;;;;;OAQG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEtH;;;;;;;OAOG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE7E;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7D;;;;;;OAMG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE7D;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACnD"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=storage-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-bridge.js","sourceRoot":"","sources":["../../../src/server/storage-bridge.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ export { MutationQueue } from './mutation-queue.js';
6
+ /** Reads a hub state payload, refusing an unknown format. @internal */
7
+ export declare function readStateFile(file: string): Promise<Uint8Array | null>;
8
+ /** Atomically replaces a hub state value inside its private home. @internal */
9
+ export declare function writeStateFile(file: string, value: Uint8Array): Promise<void>;
10
+ //# sourceMappingURL=state-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-file.d.ts","sourceRoot":"","sources":["../../src/state-file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,uEAAuE;AACvE,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAS5E;AAED,+EAA+E;AAC/E,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { chmod, readFile } from 'node:fs/promises';
6
+ import { BlobType, IntegerType, StringType, StructType, decodeBeast2For, encodeBeast2For, equalFor, printFor } from '@elaraai/east';
7
+ import { atomicWriteFile } from '@elaraai/e3-core';
8
+ import { E3_RACK_VERSION } from './version.js';
9
+ // Hub state is outside a repository and has its own explicit format. Its
10
+ // envelope remains readable before decoding the inner value, so a future
11
+ // release can refuse or migrate a form without guessing from corrupt bytes.
12
+ const Envelope = StructType({ release: StringType, format: IntegerType, value: BlobType });
13
+ const encode = encodeBeast2For(Envelope);
14
+ const decode = decodeBeast2For(Envelope);
15
+ export { MutationQueue } from './mutation-queue.js';
16
+ /** Reads a hub state payload, refusing an unknown format. @internal */
17
+ export async function readStateFile(file) {
18
+ let bytes;
19
+ try {
20
+ bytes = await readFile(file);
21
+ }
22
+ catch (err) {
23
+ if (err.code === 'ENOENT')
24
+ return null;
25
+ throw err;
26
+ }
27
+ const envelope = decode(bytes);
28
+ if (!equalFor(IntegerType)(envelope.format, 1n))
29
+ throw new Error(`${file} uses rack state format ${printFor(IntegerType)(envelope.format)}, written by e3 ${envelope.release}; update e3`);
30
+ return envelope.value;
31
+ }
32
+ /** Atomically replaces a hub state value inside its private home. @internal */
33
+ export async function writeStateFile(file, value) {
34
+ await atomicWriteFile(file, encode({ release: E3_RACK_VERSION, format: 1n, value }));
35
+ if (process.platform !== 'win32')
36
+ await chmod(file, 0o600);
37
+ }
38
+ //# sourceMappingURL=state-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-file.js","sourceRoot":"","sources":["../../src/state-file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpI,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,MAAM,QAAQ,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC3F,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;AACzC,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,KAAiB,CAAC;IACtB,IAAI,CAAC;QAAC,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACjD,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAClE,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,2BAA2B,QAAQ,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,mBAAmB,QAAQ,CAAC,OAAO,aAAa,CAAC,CAAC;IAC3L,OAAO,QAAQ,CAAC,KAAK,CAAC;AACxB,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,KAAiB;IAClE,MAAM,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACrF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import type { StorageBackend } from '@elaraai/e3-core';
6
+ import type { RackLeaseStore } from '../lease/lease-store.js';
7
+ import type { RackObjectRead, RackPutTarget, RackStorageBridge } from '../server/storage-bridge.js';
8
+ /**
9
+ * Models versioned rack uploads in memory over an explicit repository backend.
10
+ * Ported from pinned e3-cloud testing; this is not an isolation boundary.
11
+ * @example
12
+ * const bridge = new InMemoryRackStorageBridge(storage, leases);
13
+ */
14
+ export declare class InMemoryRackStorageBridge implements RackStorageBridge {
15
+ private readonly leases?;
16
+ /** Serves objects up to this size inline. */
17
+ inlineThreshold: number;
18
+ /** The store objects are read from, and committed to */
19
+ readonly storage: StorageBackend;
20
+ /** `${repo} ${hash}` → the versions PUTs made at the address, oldest first */
21
+ readonly versions: Map<string, {
22
+ version: string;
23
+ bytes: Uint8Array;
24
+ lease: string;
25
+ pinned: boolean;
26
+ }[]>;
27
+ /** uploadId → declared staged output (#210). */
28
+ readonly targets: Map<string, {
29
+ repo: string;
30
+ hash: string;
31
+ size: bigint;
32
+ }>;
33
+ /** uploadId → bytes the fake agent staged (#210). */
34
+ readonly staged: Map<string, Uint8Array<ArrayBufferLike>>;
35
+ /** manifestKey → published manifest JSON (#94 Slice B test seam). */
36
+ readonly envManifests: Map<string, string>;
37
+ private seq;
38
+ /**
39
+ * @param storage - The store objects are read from and committed to
40
+ * (required: tests use a real temporary repository)
41
+ * @param leases - The leases a commit is held to (default: none, and every
42
+ * commit is taken as held)
43
+ */
44
+ constructor(storage: StorageBackend, leases?: Pick<RackLeaseStore, "get"> | undefined);
45
+ private key;
46
+ /** Test hook: seed a committed object, returning its hash. */
47
+ seedObject(repo: string, data: Uint8Array): Promise<string>;
48
+ /** Test hook: simulate the agent's staged PUT of a whole output (#210). */
49
+ stageUpload(uploadId: string, data: Uint8Array): void;
50
+ /**
51
+ * Test hook: a presigned GET of `mem://{repo}/{hash}`, as the agent sends it.
52
+ *
53
+ * @returns The object's bytes, or null when the store holds none
54
+ */
55
+ fetch(url: string): Promise<Uint8Array | null>;
56
+ /**
57
+ * Test hook: a PUT through a write target, as S3 serves it: refused unless
58
+ * its bytes hash to the address and it sends the headers signed into its
59
+ * URL; otherwise a new version at the address.
60
+ *
61
+ * @returns The version the PUT made, or why it was refused
62
+ */
63
+ put(url: string, bytes: Uint8Array, headers: Readonly<Record<string, string>>): {
64
+ version: string;
65
+ } | {
66
+ refused: string;
67
+ };
68
+ /** Serves small objects inline and larger objects through the test transport. */
69
+ readDescriptor(repo: string, hash: string): Promise<RackObjectRead>;
70
+ /** Allocates a checksum-bound versioned upload unless the object is already held. */
71
+ writeTarget(repo: string, leaseId: string, hash: string, _size: number): Promise<RackPutTarget | null>;
72
+ /** Verifies a version and its claimant before committing the object. */
73
+ commitWrite(repo: string, leaseId: string, rackId: string, hash: string, size: number, version: string): Promise<boolean>;
74
+ /** Discards uncommitted versions belonging to the lease. */
75
+ discardWrites(repo: string, leaseId: string, hashes: readonly string[]): Promise<number>;
76
+ /** The versions at an address that nothing pinned: what a discard leaves none of. */
77
+ unpinned(repo: string, hash: string): number;
78
+ /** Allocates a legacy whole-output staging target. */
79
+ stagedTarget(repo: string, _workspace: string, hash: string, size: bigint): Promise<{
80
+ url: string;
81
+ uploadId: string;
82
+ }>;
83
+ /** Verifies and commits a legacy whole-output upload. */
84
+ commitStaged(repo: string, hash: string, uploadId: string): Promise<boolean>;
85
+ /** Reads an environment manifest seeded by a test. */
86
+ readEnvManifest(manifestKey: string): Promise<string | null>;
87
+ /** Names an environment layer in the test transport. */
88
+ presignEnvLayer(blobKey: string): Promise<string>;
89
+ /** Stores inline bytes and returns their computed hash. */
90
+ writeInline(repo: string, data: Uint8Array): Promise<string>;
91
+ }
92
+ /**
93
+ * Recording LogStore fake for route tests: its appends, and its flushes, each
94
+ * after the appends before it.
95
+ */
96
+ export declare class RecordingLogStore {
97
+ /** Appends received in transport order. */
98
+ readonly entries: Array<{
99
+ repo: string;
100
+ taskHash: string;
101
+ inputsHash: string;
102
+ executionId: string;
103
+ stream: 'stdout' | 'stderr';
104
+ data: string;
105
+ }>;
106
+ /** Each flush, with how many appends came before it: an attempt's, or every log's (none named) */
107
+ readonly flushes: Array<{
108
+ executionId?: string;
109
+ after: number;
110
+ }>;
111
+ /** Records an ordered log append. */
112
+ append(repo: string, taskHash: string, inputsHash: string, executionId: string, stream: 'stdout' | 'stderr', data: string): Promise<void>;
113
+ /** An attempt's flush (east-workspace#1051), or, named none, every log's. */
114
+ flush(_repo?: string, _taskHash?: string, _inputsHash?: string, executionId?: string): Promise<void>;
115
+ }
116
+ //# sourceMappingURL=in-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory.d.ts","sourceRoot":"","sources":["../../../src/testing/in-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { createHash } from 'node:crypto';
6
+ /**
7
+ * Models versioned rack uploads in memory over an explicit repository backend.
8
+ * Ported from pinned e3-cloud testing; this is not an isolation boundary.
9
+ * @example
10
+ * const bridge = new InMemoryRackStorageBridge(storage, leases);
11
+ */
12
+ export class InMemoryRackStorageBridge {
13
+ leases;
14
+ /** Serves objects up to this size inline. */
15
+ inlineThreshold = 4096;
16
+ /** The store objects are read from, and committed to */
17
+ storage;
18
+ /** `${repo} ${hash}` → the versions PUTs made at the address, oldest first */
19
+ versions = new Map();
20
+ /** uploadId → declared staged output (#210). */
21
+ targets = new Map();
22
+ /** uploadId → bytes the fake agent staged (#210). */
23
+ staged = new Map();
24
+ /** manifestKey → published manifest JSON (#94 Slice B test seam). */
25
+ envManifests = new Map();
26
+ seq = 0;
27
+ /**
28
+ * @param storage - The store objects are read from and committed to
29
+ * (required: tests use a real temporary repository)
30
+ * @param leases - The leases a commit is held to (default: none, and every
31
+ * commit is taken as held)
32
+ */
33
+ constructor(storage, leases) {
34
+ this.leases = leases;
35
+ this.storage = storage;
36
+ }
37
+ key(repo, hash) {
38
+ return `${repo} ${hash}`;
39
+ }
40
+ /** Test hook: seed a committed object, returning its hash. */
41
+ async seedObject(repo, data) {
42
+ return this.storage.objects.write(repo, data);
43
+ }
44
+ /** Test hook: simulate the agent's staged PUT of a whole output (#210). */
45
+ stageUpload(uploadId, data) {
46
+ this.staged.set(uploadId, data);
47
+ }
48
+ /**
49
+ * Test hook: a presigned GET of `mem://{repo}/{hash}`, as the agent sends it.
50
+ *
51
+ * @returns The object's bytes, or null when the store holds none
52
+ */
53
+ async fetch(url) {
54
+ const [repo, hash] = url.slice('mem://'.length).split('/');
55
+ try {
56
+ return await this.storage.objects.read(decodeURIComponent(repo), hash);
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ /**
63
+ * Test hook: a PUT through a write target, as S3 serves it: refused unless
64
+ * its bytes hash to the address and it sends the headers signed into its
65
+ * URL; otherwise a new version at the address.
66
+ *
67
+ * @returns The version the PUT made, or why it was refused
68
+ */
69
+ put(url, bytes, headers) {
70
+ const match = /^mem:\/\/put\/([^/]+)\/([0-9a-f]{64})\?lease=(.+)$/.exec(url);
71
+ if (match === null)
72
+ return { refused: `not a write target: ${url}` };
73
+ const [, repo, hash, lease] = match;
74
+ const checksum = Buffer.from(hash, 'hex').toString('base64');
75
+ if (headers['x-amz-checksum-sha256'] !== checksum || headers['x-amz-meta-e3-lease'] !== decodeURIComponent(lease)) {
76
+ return { refused: 'SignatureDoesNotMatch: the PUT sent other headers than its URL signs' };
77
+ }
78
+ if (createHash('sha256').update(bytes).digest('base64') !== checksum) {
79
+ return { refused: 'BadDigest: the SHA256 you specified did not match the calculated checksum' };
80
+ }
81
+ const version = `v${++this.seq}`;
82
+ const key = this.key(decodeURIComponent(repo), hash);
83
+ this.versions.set(key, [...(this.versions.get(key) ?? []), { version, bytes: new Uint8Array(bytes), lease: decodeURIComponent(lease), pinned: false }]);
84
+ return { version };
85
+ }
86
+ /** Serves small objects inline and larger objects through the test transport. */
87
+ async readDescriptor(repo, hash) {
88
+ const data = await this.storage.objects.read(repo, hash);
89
+ if (data.length <= this.inlineThreshold) {
90
+ return { kind: 'inline', data };
91
+ }
92
+ return { kind: 'url', url: `mem://${encodeURIComponent(repo)}/${hash}` };
93
+ }
94
+ /** Allocates a checksum-bound versioned upload unless the object is already held. */
95
+ async writeTarget(repo, leaseId, hash, _size) {
96
+ const [held] = await this.storage.objects.touch(repo, [hash]);
97
+ if (held === true)
98
+ return null;
99
+ return {
100
+ url: `mem://put/${encodeURIComponent(repo)}/${hash}?lease=${encodeURIComponent(leaseId)}`,
101
+ headers: { 'x-amz-checksum-sha256': Buffer.from(hash, 'hex').toString('base64'), 'x-amz-meta-e3-lease': leaseId },
102
+ };
103
+ }
104
+ /** Verifies a version and its claimant before committing the object. */
105
+ async commitWrite(repo, leaseId, rackId, hash, size, version) {
106
+ const put = this.versions.get(this.key(repo, hash))?.find((candidate) => candidate.version === version);
107
+ if (put === undefined || put.lease !== leaseId || put.bytes.length !== size)
108
+ return false;
109
+ if (createHash('sha256').update(put.bytes).digest('hex') !== hash)
110
+ return false;
111
+ if (this.leases !== undefined) {
112
+ // Held to the lease, as the catalogue's conditional write holds it
113
+ const lease = await this.leases.get(repo, leaseId);
114
+ if (lease?.status !== 'claimed' || lease.claimedBy !== rackId)
115
+ return false;
116
+ }
117
+ const [held] = await this.storage.objects.touch(repo, [hash]);
118
+ if (held !== true && (await this.storage.objects.write(repo, put.bytes)) !== hash)
119
+ return false;
120
+ put.pinned = true;
121
+ return true;
122
+ }
123
+ /** Discards uncommitted versions belonging to the lease. */
124
+ discardWrites(repo, leaseId, hashes) {
125
+ let deleted = 0;
126
+ for (const hash of hashes) {
127
+ const key = this.key(repo, hash);
128
+ const versions = this.versions.get(key) ?? [];
129
+ const kept = versions.filter((candidate) => candidate.pinned || candidate.lease !== leaseId);
130
+ deleted += versions.length - kept.length;
131
+ this.versions.set(key, kept);
132
+ }
133
+ return Promise.resolve(deleted);
134
+ }
135
+ /** The versions at an address that nothing pinned: what a discard leaves none of. */
136
+ unpinned(repo, hash) {
137
+ return (this.versions.get(this.key(repo, hash)) ?? []).filter((candidate) => !candidate.pinned).length;
138
+ }
139
+ /** Allocates a legacy whole-output staging target. */
140
+ stagedTarget(repo, _workspace, hash, size) {
141
+ const uploadId = `up-${++this.seq}`;
142
+ this.targets.set(uploadId, { repo, hash, size });
143
+ return Promise.resolve({ url: `mem://stage/${encodeURIComponent(repo)}/${hash}`, uploadId });
144
+ }
145
+ /** Verifies and commits a legacy whole-output upload. */
146
+ async commitStaged(repo, hash, uploadId) {
147
+ const target = this.targets.get(uploadId);
148
+ const data = this.staged.get(uploadId);
149
+ if (!target || !data || target.repo !== repo || target.hash !== hash)
150
+ return false;
151
+ if (BigInt(data.length) !== target.size)
152
+ return false;
153
+ if (createHash('sha256').update(data).digest('hex') !== hash)
154
+ return false;
155
+ await this.storage.objects.write(repo, data);
156
+ this.targets.delete(uploadId);
157
+ this.staged.delete(uploadId);
158
+ return true;
159
+ }
160
+ /** Reads an environment manifest seeded by a test. */
161
+ readEnvManifest(manifestKey) {
162
+ return Promise.resolve(this.envManifests.get(manifestKey) ?? null);
163
+ }
164
+ /** Names an environment layer in the test transport. */
165
+ presignEnvLayer(blobKey) {
166
+ return Promise.resolve(`mem://env/${blobKey}`);
167
+ }
168
+ /** Stores inline bytes and returns their computed hash. */
169
+ async writeInline(repo, data) {
170
+ return this.storage.objects.write(repo, data);
171
+ }
172
+ }
173
+ /**
174
+ * Recording LogStore fake for route tests: its appends, and its flushes, each
175
+ * after the appends before it.
176
+ */
177
+ export class RecordingLogStore {
178
+ /** Appends received in transport order. */
179
+ entries = [];
180
+ /** Each flush, with how many appends came before it: an attempt's, or every log's (none named) */
181
+ flushes = [];
182
+ /** Records an ordered log append. */
183
+ append(repo, taskHash, inputsHash, executionId, stream, data) {
184
+ this.entries.push({ repo, taskHash, inputsHash, executionId, stream, data });
185
+ return Promise.resolve();
186
+ }
187
+ /** An attempt's flush (east-workspace#1051), or, named none, every log's. */
188
+ flush(_repo, _taskHash, _inputsHash, executionId) {
189
+ this.flushes.push({ ...(executionId !== undefined && { executionId }), after: this.entries.length });
190
+ return Promise.resolve();
191
+ }
192
+ }
193
+ //# sourceMappingURL=in-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory.js","sourceRoot":"","sources":["../../../src/testing/in-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ export { InMemoryRackLeaseStore } from '../lease/in-memory-lease-store.js';
6
+ export { InMemoryMachineIdentityStore } from '../identity/in-memory-identity-store.js';
7
+ export { InMemoryRackRegistry } from '../registry/rack-registry.js';
8
+ export { rackRegistryContract } from './rack-registry-contract.js';
9
+ export { leaseStoreContract } from './lease-store-contract.js';
10
+ export { wireSamples } from '../protocol/wire-samples.js';
11
+ export { TestRackAgent, type TestRackAgentOptions, type TestRackAgentFaults } from './test-rack-agent.js';
12
+ export { InMemoryRackStorageBridge, RecordingLogStore } from './in-memory.js';
13
+ export { rackProtocolSuite, type RackProtocolFixture } from './protocol-suite.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC1G,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ export { InMemoryRackLeaseStore } from '../lease/in-memory-lease-store.js';
6
+ export { InMemoryMachineIdentityStore } from '../identity/in-memory-identity-store.js';
7
+ export { InMemoryRackRegistry } from '../registry/rack-registry.js';
8
+ export { rackRegistryContract } from './rack-registry-contract.js';
9
+ export { leaseStoreContract } from './lease-store-contract.js';
10
+ export { wireSamples } from '../protocol/wire-samples.js';
11
+ export { TestRackAgent } from './test-rack-agent.js';
12
+ export { InMemoryRackStorageBridge, RecordingLogStore } from './in-memory.js';
13
+ export { rackProtocolSuite } from './protocol-suite.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAuD,MAAM,sBAAsB,CAAC;AAC1G,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAA4B,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { type RackLeaseStore } from '../lease/lease-store.js';
6
+ /**
7
+ * Tests the conditional lease transitions every backend implements.
8
+ * @param label - The backend's name
9
+ * @param makeStore - Creates an empty store for each case
10
+ * @example
11
+ * leaseStoreContract('memory', () => new InMemoryRackLeaseStore());
12
+ */
13
+ export declare function leaseStoreContract(label: string, makeStore: () => RackLeaseStore | Promise<RackLeaseStore>): void;
14
+ //# sourceMappingURL=lease-store-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-store-contract.d.ts","sourceRoot":"","sources":["../../../src/testing/lease-store-contract.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAqC,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEjG;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CA8DjH"}