@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,48 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { DateTimeType, DictType, NullType, OptionType, StringType, StructType, VariantType, type ValueTypeOf } from '@elaraai/east';
6
+ import { MutationQueue } from '../mutation-queue.js';
7
+ import type { MachineIdentityStore, RackTokenRecord } from './machine-identity.js';
8
+ /** The hub's credentials, hashed at rest. */
9
+ export declare const IdentityFileType: StructType<{
10
+ readonly enrollmentTokens: DictType<StringType, DateTimeType>;
11
+ readonly rackTokens: DictType<StringType, StructType<{
12
+ readonly rackId: StringType;
13
+ readonly status: VariantType<{
14
+ readonly current: NullType;
15
+ readonly pending: NullType;
16
+ readonly grace: NullType;
17
+ }>;
18
+ readonly issuedAt: DateTimeType;
19
+ readonly graceUntil: OptionType<DateTimeType>;
20
+ }>>;
21
+ }>;
22
+ /** The credentials' persisted value. */
23
+ export type IdentityFile = ValueTypeOf<typeof IdentityFileType>;
24
+ /**
25
+ * Keeps machine identities in memory, with atomic single-use enrollment.
26
+ * @example
27
+ * const store = new InMemoryMachineIdentityStore();
28
+ * await store.putEnrollmentToken(hashToken(token), expiresAt);
29
+ */
30
+ export declare class InMemoryMachineIdentityStore implements MachineIdentityStore {
31
+ protected state: IdentityFile;
32
+ protected readonly mutations: MutationQueue;
33
+ protected ready: Promise<void>;
34
+ /** Persists a candidate state before it becomes visible. @internal */
35
+ protected persist(_state: IdentityFile): Promise<void>;
36
+ private change;
37
+ putEnrollmentToken(hash: string, expiresAt: Date): Promise<void>;
38
+ consumeEnrollmentToken(hash: string, now: Date): Promise<boolean>;
39
+ putRackToken(hash: string, rackId: string, issuedAt: Date, status: 'current' | 'pending'): Promise<void>;
40
+ getRackToken(hash: string): Promise<RackTokenRecord | null>;
41
+ listRackTokens(rackId: string): Promise<Array<RackTokenRecord & {
42
+ tokenHash: string;
43
+ }>>;
44
+ promoteRackToken(rackId: string, hash: string, graceUntil: Date): Promise<void>;
45
+ deleteRackToken(hash: string): Promise<void>;
46
+ deleteRackTokens(rackId: string): Promise<void>;
47
+ }
48
+ //# sourceMappingURL=in-memory-identity-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-identity-store.d.ts","sourceRoot":"","sources":["../../../src/identity/in-memory-identity-store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAqE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACvM,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEnF,6CAA6C;AAC7C,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAQ3B,CAAC;AACH,wCAAwC;AACxC,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAKhE;;;;;GAKG;AACH,qBAAa,4BAA6B,YAAW,oBAAoB;IACvE,SAAS,CAAC,KAAK,EAAE,YAAY,CAA0D;IACvF,SAAS,CAAC,QAAQ,CAAC,SAAS,gBAAuB;IACnD,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;IAEnD,sEAAsE;IACtE,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtD,OAAO,CAAC,MAAM;IAgBd,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjE,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAU3D,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAS7F,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAKhD"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { DateTimeType, DictType, NullType, OptionType, StringType, StructType, VariantType, compareFor, decodeBeast2For, encodeBeast2For, none, some, variant } from '@elaraai/east';
6
+ import { MutationQueue } from '../mutation-queue.js';
7
+ /** The hub's credentials, hashed at rest. */
8
+ export const IdentityFileType = StructType({
9
+ enrollmentTokens: DictType(StringType, DateTimeType),
10
+ rackTokens: DictType(StringType, StructType({
11
+ rackId: StringType,
12
+ status: VariantType({ current: NullType, pending: NullType, grace: NullType }),
13
+ issuedAt: DateTimeType,
14
+ graceUntil: OptionType(DateTimeType),
15
+ })),
16
+ });
17
+ const encode = encodeBeast2For(IdentityFileType);
18
+ const decode = decodeBeast2For(IdentityFileType);
19
+ const compareTime = compareFor(DateTimeType);
20
+ /**
21
+ * Keeps machine identities in memory, with atomic single-use enrollment.
22
+ * @example
23
+ * const store = new InMemoryMachineIdentityStore();
24
+ * await store.putEnrollmentToken(hashToken(token), expiresAt);
25
+ */
26
+ export class InMemoryMachineIdentityStore {
27
+ state = { enrollmentTokens: new Map(), rackTokens: new Map() };
28
+ mutations = new MutationQueue();
29
+ ready = Promise.resolve();
30
+ /** Persists a candidate state before it becomes visible. @internal */
31
+ persist(_state) { return Promise.resolve(); }
32
+ change(edit, now = new Date()) {
33
+ return this.mutations.run(async () => {
34
+ await this.ready;
35
+ const next = decode(encode(this.state));
36
+ const prune = () => {
37
+ for (const [hash, expires] of next.enrollmentTokens)
38
+ if (compareTime(expires, now) <= 0)
39
+ next.enrollmentTokens.delete(hash);
40
+ };
41
+ prune();
42
+ const result = edit(next);
43
+ prune();
44
+ await this.persist(next);
45
+ this.state = decode(encode(next));
46
+ return result;
47
+ });
48
+ }
49
+ putEnrollmentToken(hash, expiresAt) {
50
+ return this.change((state) => { state.enrollmentTokens.set(hash, expiresAt); });
51
+ }
52
+ consumeEnrollmentToken(hash, now) {
53
+ return this.change((state) => state.enrollmentTokens.delete(hash), now);
54
+ }
55
+ putRackToken(hash, rackId, issuedAt, status) {
56
+ return this.change((state) => {
57
+ state.rackTokens.set(hash, { rackId, issuedAt, status: variant(status, null), graceUntil: none });
58
+ });
59
+ }
60
+ async getRackToken(hash) {
61
+ await this.ready;
62
+ await this.mutations.idle();
63
+ const record = this.state.rackTokens.get(hash);
64
+ return record === undefined ? null : {
65
+ rackId: record.rackId, status: record.status.type, issuedAt: new Date(record.issuedAt),
66
+ ...(record.graceUntil.type === 'some' && { graceUntil: new Date(record.graceUntil.value) }),
67
+ };
68
+ }
69
+ async listRackTokens(rackId) {
70
+ await this.ready;
71
+ await this.mutations.idle();
72
+ return [...this.state.rackTokens].flatMap(([tokenHash, record]) => record.rackId !== rackId ? [] : [{
73
+ tokenHash, rackId, status: record.status.type, issuedAt: new Date(record.issuedAt),
74
+ ...(record.graceUntil.type === 'some' && { graceUntil: new Date(record.graceUntil.value) }),
75
+ }]);
76
+ }
77
+ promoteRackToken(rackId, hash, graceUntil) {
78
+ return this.change((state) => {
79
+ if (state.rackTokens.get(hash)?.rackId !== rackId)
80
+ throw new Error('Cannot promote an unknown rack token');
81
+ for (const [key, record] of state.rackTokens) {
82
+ if (record.rackId !== rackId)
83
+ continue;
84
+ if (key === hash)
85
+ state.rackTokens.set(key, { ...record, status: variant('current', null), graceUntil: none });
86
+ else if (record.status.type !== 'grace')
87
+ state.rackTokens.set(key, { ...record, status: variant('grace', null), graceUntil: some(graceUntil) });
88
+ }
89
+ });
90
+ }
91
+ deleteRackToken(hash) {
92
+ return this.change((state) => { state.rackTokens.delete(hash); });
93
+ }
94
+ deleteRackTokens(rackId) {
95
+ return this.change((state) => {
96
+ for (const [hash, record] of state.rackTokens)
97
+ if (record.rackId === rackId)
98
+ state.rackTokens.delete(hash);
99
+ });
100
+ }
101
+ }
102
+ //# sourceMappingURL=in-memory-identity-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-identity-store.js","sourceRoot":"","sources":["../../../src/identity/in-memory-identity-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /** Prefix distinguishing rack machine tokens from human JWTs at a glance. */
6
+ export declare const RACK_TOKEN_PREFIX = "e3rk_";
7
+ /** Prefix for single-use enrollment tokens. */
8
+ export declare const ENROLLMENT_TOKEN_PREFIX = "e3rk_enroll_";
9
+ /** Default enrollment-token lifetime: long enough to paste one command. */
10
+ export declare const DEFAULT_ENROLLMENT_TTL_MS: number;
11
+ /**
12
+ * Token rotation (D12, #90). A current token older than ROTATION_AGE has a
13
+ * successor minted and offered via the heartbeat response. The offer is
14
+ * repeated (with a fresh successor) at most every ROTATION_REOFFER until
15
+ * the agent demonstrably switches — the successor's FIRST authenticated use
16
+ * promotes it and starts the old token's ROTATION_GRACE fuse. Activation-
17
+ * based expiry means a lost heartbeat response can never strand an agent:
18
+ * until the successor is seen, the old token remains fully valid.
19
+ */
20
+ export declare const ROTATION_AGE_MS: number;
21
+ export declare const ROTATION_REOFFER_MS: number;
22
+ export declare const ROTATION_GRACE_MS: number;
23
+ /**
24
+ * One rack token's lifecycle state:
25
+ * - `current` — the rack's working credential
26
+ * - `pending` — a minted successor the agent has not used yet
27
+ * - `grace` — superseded; valid only until `graceUntil`
28
+ */
29
+ export interface RackTokenRecord {
30
+ rackId: string;
31
+ status: 'current' | 'pending' | 'grace';
32
+ issuedAt: Date;
33
+ /** Hard cutoff for `grace` tokens; absent otherwise. */
34
+ graceUntil?: Date;
35
+ }
36
+ /**
37
+ * Persistence for machine credentials, hashed at rest. Implementations:
38
+ * `InMemoryMachineIdentityStore` (testing) and `DynamoMachineIdentityStore`
39
+ * (e3-aws; `PK=ENROLLTOKEN|RACKTOKEN`, `SK={tokenHash}`).
40
+ */
41
+ export interface MachineIdentityStore {
42
+ /**
43
+ * Record a freshly minted enrollment token.
44
+ *
45
+ * @param tokenHash - SHA-256 hex of the plaintext token
46
+ * @param expiresAt - When the token stops being exchangeable
47
+ */
48
+ putEnrollmentToken(tokenHash: string, expiresAt: Date): Promise<void>;
49
+ /**
50
+ * Atomically consume an enrollment token: exactly one caller ever
51
+ * receives `true` for a given token, and only before its expiry.
52
+ *
53
+ * @param tokenHash - SHA-256 hex of the presented token
54
+ * @param now - Current time (injected for testability)
55
+ * @returns Whether the token was valid, unexpired, and not yet used
56
+ */
57
+ consumeEnrollmentToken(tokenHash: string, now: Date): Promise<boolean>;
58
+ /**
59
+ * Bind a rack token (hashed) to a rack identity.
60
+ *
61
+ * @param tokenHash - SHA-256 hex of the plaintext rack token
62
+ * @param rackId - The rack the token authenticates
63
+ * @param issuedAt - Mint time (the rotation clock)
64
+ * @param status - `current` at enrollment, `pending` for a rotation offer
65
+ */
66
+ putRackToken(tokenHash: string, rackId: string, issuedAt: Date, status: 'current' | 'pending'): Promise<void>;
67
+ /**
68
+ * Resolve a presented rack token. Validity (grace expiry) is the
69
+ * caller's judgement — this returns the raw record.
70
+ *
71
+ * @param tokenHash - SHA-256 hex of the presented token
72
+ * @returns The token record, or null when unknown
73
+ */
74
+ getRackToken(tokenHash: string): Promise<RackTokenRecord | null>;
75
+ /**
76
+ * All tokens bound to a rack (a handful: current + at most one pending
77
+ * + expiring grace rows).
78
+ *
79
+ * @param rackId - The rack whose tokens are listed
80
+ */
81
+ listRackTokens(rackId: string): Promise<Array<RackTokenRecord & {
82
+ tokenHash: string;
83
+ }>>;
84
+ /**
85
+ * Activate a successor: `tokenHash` becomes `current`; every OTHER
86
+ * `current`/`pending` token of the rack drops to `grace` with the given
87
+ * cutoff. Tokens already in grace keep their earlier cutoff.
88
+ *
89
+ * @param rackId - The rack rotating
90
+ * @param tokenHash - The successor's hash (first use just observed)
91
+ * @param graceUntil - When the superseded token(s) die
92
+ */
93
+ promoteRackToken(rackId: string, tokenHash: string, graceUntil: Date): Promise<void>;
94
+ /**
95
+ * Remove one token row (a stale pending offer being replaced).
96
+ *
97
+ * @param tokenHash - SHA-256 hex of the token to remove
98
+ */
99
+ deleteRackToken(tokenHash: string): Promise<void>;
100
+ /**
101
+ * Remove every token bound to a rack — deregistration hygiene. Security
102
+ * does not depend on this (the middleware checks the registration), but
103
+ * it keeps the credential table honest.
104
+ *
105
+ * @param rackId - The rack whose tokens are purged
106
+ */
107
+ deleteRackTokens(rackId: string): Promise<void>;
108
+ }
109
+ /**
110
+ * Hash a token for at-rest storage and lookups.
111
+ *
112
+ * @param token - The plaintext token
113
+ * @returns SHA-256 hex digest
114
+ */
115
+ export declare function hashToken(token: string): string;
116
+ /**
117
+ * Generate a single-use enrollment token (256 bits of entropy).
118
+ *
119
+ * @returns The plaintext token and its at-rest hash
120
+ */
121
+ export declare function generateEnrollmentToken(): {
122
+ token: string;
123
+ tokenHash: string;
124
+ };
125
+ /**
126
+ * Generate a long-lived rack token (256 bits of entropy).
127
+ *
128
+ * @returns The plaintext token and its at-rest hash
129
+ */
130
+ export declare function generateRackToken(): {
131
+ token: string;
132
+ tokenHash: string;
133
+ };
134
+ //# sourceMappingURL=machine-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-identity.d.ts","sourceRoot":"","sources":["../../../src/identity/machine-identity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,UAAU,CAAC;AACzC,+CAA+C;AAC/C,eAAO,MAAM,uBAAuB,iBAAiB,CAAC;AAEtD,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,QAAc,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,QAAmB,CAAC;AAChD,eAAO,MAAM,mBAAmB,QAAc,CAAC;AAC/C,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACxC,QAAQ,EAAE,IAAI,CAAC;IACf,wDAAwD;IACxD,UAAU,CAAC,EAAE,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtE;;;;;;;OAOG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvE;;;;;;;OAOG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9G;;;;;;OAMG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAEjE;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAExF;;;;;;;;OAQG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErF;;;;OAIG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;;;;;OAMG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAG9E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAGxE"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Rack machine identity (#72, epic #67 design §9.1) — the minimal
7
+ * machine-credential scheme beside the human Cognito JWTs:
8
+ *
9
+ * - An admin mints a **single-use, short-TTL enrollment token** (Phase-1
10
+ * mint endpoint; `StoreEnrollmentTokenMinter` is its real implementation).
11
+ * - The agent exchanges it once (`POST /rack/enroll`) for a **long-lived,
12
+ * revocable rack token** bound to a generated rackId.
13
+ * - Both tokens are stored **hashed at rest** (SHA-256); the plaintext
14
+ * exists only in the mint/exchange responses.
15
+ * - Revocation = deregister (delete the `RackRegistration`): the auth
16
+ * middleware re-resolves the registration on every request, so a token
17
+ * whose rack is gone is dead even if its hash row lingers.
18
+ */
19
+ import { createHash, randomBytes } from 'node:crypto';
20
+ /** Prefix distinguishing rack machine tokens from human JWTs at a glance. */
21
+ export const RACK_TOKEN_PREFIX = 'e3rk_';
22
+ /** Prefix for single-use enrollment tokens. */
23
+ export const ENROLLMENT_TOKEN_PREFIX = 'e3rk_enroll_';
24
+ /** Default enrollment-token lifetime: long enough to paste one command. */
25
+ export const DEFAULT_ENROLLMENT_TTL_MS = 15 * 60_000;
26
+ /**
27
+ * Token rotation (D12, #90). A current token older than ROTATION_AGE has a
28
+ * successor minted and offered via the heartbeat response. The offer is
29
+ * repeated (with a fresh successor) at most every ROTATION_REOFFER until
30
+ * the agent demonstrably switches — the successor's FIRST authenticated use
31
+ * promotes it and starts the old token's ROTATION_GRACE fuse. Activation-
32
+ * based expiry means a lost heartbeat response can never strand an agent:
33
+ * until the successor is seen, the old token remains fully valid.
34
+ */
35
+ export const ROTATION_AGE_MS = 24 * 60 * 60_000;
36
+ export const ROTATION_REOFFER_MS = 60 * 60_000;
37
+ export const ROTATION_GRACE_MS = 15 * 60_000;
38
+ /**
39
+ * Hash a token for at-rest storage and lookups.
40
+ *
41
+ * @param token - The plaintext token
42
+ * @returns SHA-256 hex digest
43
+ */
44
+ export function hashToken(token) {
45
+ return createHash('sha256').update(token, 'utf8').digest('hex');
46
+ }
47
+ /**
48
+ * Generate a single-use enrollment token (256 bits of entropy).
49
+ *
50
+ * @returns The plaintext token and its at-rest hash
51
+ */
52
+ export function generateEnrollmentToken() {
53
+ const token = `${ENROLLMENT_TOKEN_PREFIX}${randomBytes(32).toString('hex')}`;
54
+ return { token, tokenHash: hashToken(token) };
55
+ }
56
+ /**
57
+ * Generate a long-lived rack token (256 bits of entropy).
58
+ *
59
+ * @returns The plaintext token and its at-rest hash
60
+ */
61
+ export function generateRackToken() {
62
+ const token = `${RACK_TOKEN_PREFIX}${randomBytes(32).toString('hex')}`;
63
+ return { token, tokenHash: hashToken(token) };
64
+ }
65
+ //# sourceMappingURL=machine-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-identity.js","sourceRoot":"","sources":["../../../src/identity/machine-identity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGtD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AACzC,+CAA+C;AAC/C,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAEtD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,MAAM,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,MAAM,CAAC;AAC/C,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,MAAM,CAAC;AA+F7C;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,KAAK,GAAG,GAAG,uBAAuB,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7E,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAG,GAAG,iBAAiB,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;IACvE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ export * from './protocol/index.js';
6
+ export * from './tls/tls.js';
7
+ export * from './lease/lease-store.js';
8
+ export * from './lease/rack-dispatch.js';
9
+ export * from './identity/machine-identity.js';
10
+ export * from './identity/in-memory-identity-store.js';
11
+ export * from './identity/file-identity-store.js';
12
+ export * from './lease/in-memory-lease-store.js';
13
+ export * from './registry/rack-registry.js';
14
+ export * from './registry/file-rack-registry.js';
15
+ export * from './paths.js';
16
+ export * from './version.js';
17
+ export * from './routing/policy.js';
18
+ export * from './routing/eligibility.js';
19
+ export * from './routing/tiers.js';
20
+ export * from './client/connect.js';
21
+ export * from './client/hub-client.js';
22
+ export * from './client/session.js';
23
+ export * from './hub/hub.js';
24
+ export * from './hub/config.js';
25
+ export { readHubLock } from './hub/lock.js';
26
+ export * from './server/dispatch.js';
27
+ export * from './server/rack-routes.js';
28
+ export * from './server/storage-bridge.js';
29
+ export * from './server/env-publication.js';
30
+ export * from './lease/coordinator.js';
31
+ export * from './runner/rack-body.js';
32
+ export * from './runner/rack-runner.js';
33
+ export * from './runner/api-server.js';
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AACvD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ export * from './protocol/index.js';
6
+ export * from './tls/tls.js';
7
+ export * from './lease/lease-store.js';
8
+ export * from './lease/rack-dispatch.js';
9
+ export * from './identity/machine-identity.js';
10
+ export * from './identity/in-memory-identity-store.js';
11
+ export * from './identity/file-identity-store.js';
12
+ export * from './lease/in-memory-lease-store.js';
13
+ export * from './registry/rack-registry.js';
14
+ export * from './registry/file-rack-registry.js';
15
+ export * from './paths.js';
16
+ export * from './version.js';
17
+ export * from './routing/policy.js';
18
+ export * from './routing/eligibility.js';
19
+ export * from './routing/tiers.js';
20
+ export * from './client/connect.js';
21
+ export * from './client/hub-client.js';
22
+ export * from './client/session.js';
23
+ export * from './hub/hub.js';
24
+ export * from './hub/config.js';
25
+ export { readHubLock } from './hub/lock.js';
26
+ export * from './server/dispatch.js';
27
+ export * from './server/rack-routes.js';
28
+ export * from './server/storage-bridge.js';
29
+ export * from './server/env-publication.js';
30
+ export * from './lease/coordinator.js';
31
+ export * from './runner/rack-body.js';
32
+ export * from './runner/rack-runner.js';
33
+ export * from './runner/api-server.js';
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wCAAwC,CAAC;AACvD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Licensed under BSL 1.1. See LICENSE for details.
4
+ */
5
+ import { type DetachedArg, type SplitUnit, type StorageBackend } from '@elaraai/e3-core';
6
+ import { type TaskObject } from '@elaraai/e3-types';
7
+ import type { RackLeaseClosure } from '../protocol/task-envelope.js';
8
+ /** The most hashes a lease's event carries inline: past it, the closure is an object. */
9
+ export declare const INLINE_CLOSURE_MAX = 512;
10
+ /**
11
+ * A closure object's bytes.
12
+ *
13
+ * @param hashes - The closure's hashes
14
+ * @returns The object's bytes
15
+ */
16
+ export declare function encodeClosure(hashes: readonly string[]): Uint8Array;
17
+ /**
18
+ * The hashes a closure object lists.
19
+ *
20
+ * @param bytes - The object's bytes
21
+ * @returns The hashes
22
+ * @throws {Error} When the bytes are not a closure object
23
+ */
24
+ export declare function decodeClosure(bytes: Uint8Array): string[];
25
+ /**
26
+ * What a unit's execution stages: a piece's inputs, or a merge's key range
27
+ * and its parts (e3-core's `taskExecuteBody`).
28
+ *
29
+ * @param inputs - The unit's inputs, as its record names them
30
+ * @param merge - What a merge unit merges, or null for a piece
31
+ * @returns The staged objects' hashes
32
+ */
33
+ export declare function stagedObjects(inputs: readonly string[], merge: SplitUnit['merge']): string[];
34
+ /**
35
+ * The closure of a task's or a unit's execution.
36
+ *
37
+ * @param storage - The repository's storage
38
+ * @param repo - Repository identifier
39
+ * @param taskHash - The task object's hash
40
+ * @param task - The task object
41
+ * @param staged - What the execution stages ({@link stagedObjects})
42
+ * @param parts - Collects the closure's collection parts (each staged
43
+ * manifest's entries): what a unit fetches only as it reads them
44
+ * @returns The objects it reads, sorted
45
+ * @throws {Error} When an object it names cannot be read
46
+ */
47
+ export declare function taskClosure(storage: StorageBackend, repo: string, taskHash: string, task: TaskObject, staged: readonly string[], parts?: Set<string>): Promise<string[]>;
48
+ /**
49
+ * The closure of a function call's execution.
50
+ *
51
+ * @param storage - The repository's storage
52
+ * @param repo - Repository identifier
53
+ * @param program - The program's object hash
54
+ * @param args - The call's arguments: a stored dataset's objects are staged
55
+ * @param environment - The environment the call declares
56
+ * @returns The objects it reads, sorted
57
+ * @throws {Error} When an object it names cannot be read
58
+ */
59
+ export declare function detachedClosure(storage: StorageBackend, repo: string, program: string, args: readonly DetachedArg[], environment?: string): Promise<string[]>;
60
+ /**
61
+ * The closure of a function call whose program travels with it, not as an
62
+ * object: its environment, and each stored dataset argument (#225, a
63
+ * sandbox's call).
64
+ *
65
+ * @param storage - The repository's storage
66
+ * @param repo - Repository identifier
67
+ * @param args - The call's arguments: a stored dataset's objects are staged
68
+ * @param environment - The environment the call declares
69
+ * @param parts - Collects the closure's collection parts, as {@link taskClosure}'s
70
+ * @returns The objects it reads, sorted
71
+ * @throws {Error} When an object it names cannot be read
72
+ */
73
+ export declare function callClosure(storage: StorageBackend, repo: string, args: readonly DetachedArg[], environment?: string, parts?: Set<string>): Promise<string[]>;
74
+ /**
75
+ * Records a closure on a lease: its hashes inline, or, when there are more
76
+ * than {@link INLINE_CLOSURE_MAX}, an object in the repository's store that
77
+ * lists them.
78
+ *
79
+ * @param storage - The repository's storage
80
+ * @param repo - Repository identifier
81
+ * @param hashes - The closure
82
+ * @returns What the lease's event carries
83
+ */
84
+ export declare function recordClosure(storage: StorageBackend, repo: string, hashes: readonly string[]): Promise<RackLeaseClosure>;
85
+ /**
86
+ * Every object a lease may read, as its closure names them: the hashes, and,
87
+ * for a closure recorded as an object, that object too.
88
+ *
89
+ * @param closure - The lease's closure
90
+ * @param read - Reads the closure object, for one recorded as an object
91
+ * @returns The hashes
92
+ * @throws {Error} When the closure object cannot be read, or lists another
93
+ * number of hashes than the lease says
94
+ */
95
+ export declare function closureHashes(closure: RackLeaseClosure, read: (hash: string) => Promise<Uint8Array>): Promise<string[]>;
96
+ //# sourceMappingURL=closure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closure.d.ts","sourceRoot":"","sources":["../../../src/lease/closure.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC5G,OAAO,EAAoD,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACtG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,yFAAyF;AACzF,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAQtC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAEnE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,EAAE,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE,CAE5F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CAYnB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,WAAW,CAAC,EAAE,MAAM,EACpB,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CAOnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAI/H;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO7H"}