@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.
- package/README.md +407 -2
- package/dist/src/client/client.spec.d.ts +6 -0
- package/dist/src/client/client.spec.d.ts.map +1 -0
- package/dist/src/client/client.spec.js +150 -0
- package/dist/src/client/client.spec.js.map +1 -0
- package/dist/src/client/connect.d.ts +52 -0
- package/dist/src/client/connect.d.ts.map +1 -0
- package/dist/src/client/connect.js +112 -0
- package/dist/src/client/connect.js.map +1 -0
- package/dist/src/client/hub-client.d.ts +57 -0
- package/dist/src/client/hub-client.d.ts.map +1 -0
- package/dist/src/client/hub-client.js +87 -0
- package/dist/src/client/hub-client.js.map +1 -0
- package/dist/src/client/local-http.d.ts +78 -0
- package/dist/src/client/local-http.d.ts.map +1 -0
- package/dist/src/client/local-http.js +149 -0
- package/dist/src/client/local-http.js.map +1 -0
- package/dist/src/client/session-attempts.d.ts +20 -0
- package/dist/src/client/session-attempts.d.ts.map +1 -0
- package/dist/src/client/session-attempts.js +88 -0
- package/dist/src/client/session-attempts.js.map +1 -0
- package/dist/src/client/session-data-server.d.ts +37 -0
- package/dist/src/client/session-data-server.d.ts.map +1 -0
- package/dist/src/client/session-data-server.js +280 -0
- package/dist/src/client/session-data-server.js.map +1 -0
- package/dist/src/client/session-data-server.spec.d.ts +6 -0
- package/dist/src/client/session-data-server.spec.d.ts.map +1 -0
- package/dist/src/client/session-data-server.spec.js +192 -0
- package/dist/src/client/session-data-server.spec.js.map +1 -0
- package/dist/src/client/session.d.ts +119 -0
- package/dist/src/client/session.d.ts.map +1 -0
- package/dist/src/client/session.js +290 -0
- package/dist/src/client/session.js.map +1 -0
- package/dist/src/hub/config.d.ts +74 -0
- package/dist/src/hub/config.d.ts.map +1 -0
- package/dist/src/hub/config.js +159 -0
- package/dist/src/hub/config.js.map +1 -0
- package/dist/src/hub/fair-lease-store.d.ts +36 -0
- package/dist/src/hub/fair-lease-store.d.ts.map +1 -0
- package/dist/src/hub/fair-lease-store.js +73 -0
- package/dist/src/hub/fair-lease-store.js.map +1 -0
- package/dist/src/hub/hub.d.ts +91 -0
- package/dist/src/hub/hub.d.ts.map +1 -0
- package/dist/src/hub/hub.js +641 -0
- package/dist/src/hub/hub.js.map +1 -0
- package/dist/src/hub/hub.spec.d.ts +6 -0
- package/dist/src/hub/hub.spec.d.ts.map +1 -0
- package/dist/src/hub/hub.spec.js +363 -0
- package/dist/src/hub/hub.spec.js.map +1 -0
- package/dist/src/hub/infrastructure.spec.d.ts +6 -0
- package/dist/src/hub/infrastructure.spec.d.ts.map +1 -0
- package/dist/src/hub/infrastructure.spec.js +211 -0
- package/dist/src/hub/infrastructure.spec.js.map +1 -0
- package/dist/src/hub/lock.d.ts +62 -0
- package/dist/src/hub/lock.d.ts.map +1 -0
- package/dist/src/hub/lock.js +165 -0
- package/dist/src/hub/lock.js.map +1 -0
- package/dist/src/hub/main.d.ts +16 -0
- package/dist/src/hub/main.d.ts.map +1 -0
- package/dist/src/hub/main.js +56 -0
- package/dist/src/hub/main.js.map +1 -0
- package/dist/src/hub/session-bridge.d.ts +116 -0
- package/dist/src/hub/session-bridge.d.ts.map +1 -0
- package/dist/src/hub/session-bridge.js +336 -0
- package/dist/src/hub/session-bridge.js.map +1 -0
- package/dist/src/identity/file-identity-store.d.ts +18 -0
- package/dist/src/identity/file-identity-store.d.ts.map +1 -0
- package/dist/src/identity/file-identity-store.js +34 -0
- package/dist/src/identity/file-identity-store.js.map +1 -0
- package/dist/src/identity/file-identity-store.spec.d.ts +6 -0
- package/dist/src/identity/file-identity-store.spec.d.ts.map +1 -0
- package/dist/src/identity/file-identity-store.spec.js +59 -0
- package/dist/src/identity/file-identity-store.spec.js.map +1 -0
- package/dist/src/identity/in-memory-identity-store.d.ts +48 -0
- package/dist/src/identity/in-memory-identity-store.d.ts.map +1 -0
- package/dist/src/identity/in-memory-identity-store.js +102 -0
- package/dist/src/identity/in-memory-identity-store.js.map +1 -0
- package/dist/src/identity/machine-identity.d.ts +134 -0
- package/dist/src/identity/machine-identity.d.ts.map +1 -0
- package/dist/src/identity/machine-identity.js +65 -0
- package/dist/src/identity/machine-identity.js.map +1 -0
- package/dist/src/index.d.ts +34 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +34 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lease/closure.d.ts +96 -0
- package/dist/src/lease/closure.d.ts.map +1 -0
- package/dist/src/lease/closure.js +192 -0
- package/dist/src/lease/closure.js.map +1 -0
- package/dist/src/lease/closure.spec.d.ts +6 -0
- package/dist/src/lease/closure.spec.d.ts.map +1 -0
- package/dist/src/lease/closure.spec.js +35 -0
- package/dist/src/lease/closure.spec.js.map +1 -0
- package/dist/src/lease/coordinator.d.ts +34 -0
- package/dist/src/lease/coordinator.d.ts.map +1 -0
- package/dist/src/lease/coordinator.js +42 -0
- package/dist/src/lease/coordinator.js.map +1 -0
- package/dist/src/lease/in-memory-lease-store.d.ts +58 -0
- package/dist/src/lease/in-memory-lease-store.d.ts.map +1 -0
- package/dist/src/lease/in-memory-lease-store.js +132 -0
- package/dist/src/lease/in-memory-lease-store.js.map +1 -0
- package/dist/src/lease/lease-store.d.ts +169 -0
- package/dist/src/lease/lease-store.d.ts.map +1 -0
- package/dist/src/lease/lease-store.js +94 -0
- package/dist/src/lease/lease-store.js.map +1 -0
- package/dist/src/lease/lease-store.spec.d.ts +6 -0
- package/dist/src/lease/lease-store.spec.d.ts.map +1 -0
- package/dist/src/lease/lease-store.spec.js +8 -0
- package/dist/src/lease/lease-store.spec.js.map +1 -0
- package/dist/src/lease/rack-dispatch.d.ts +105 -0
- package/dist/src/lease/rack-dispatch.d.ts.map +1 -0
- package/dist/src/lease/rack-dispatch.js +6 -0
- package/dist/src/lease/rack-dispatch.js.map +1 -0
- package/dist/src/mutation-queue.d.ts +13 -0
- package/dist/src/mutation-queue.d.ts.map +1 -0
- package/dist/src/mutation-queue.js +17 -0
- package/dist/src/mutation-queue.js.map +1 -0
- package/dist/src/paths.d.ts +56 -0
- package/dist/src/paths.d.ts.map +1 -0
- package/dist/src/paths.js +82 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/protocol/control.d.ts +295 -0
- package/dist/src/protocol/control.d.ts.map +1 -0
- package/dist/src/protocol/control.js +74 -0
- package/dist/src/protocol/control.js.map +1 -0
- package/dist/src/protocol/index.d.ts +9 -0
- package/dist/src/protocol/index.d.ts.map +1 -0
- package/dist/src/protocol/index.js +9 -0
- package/dist/src/protocol/index.js.map +1 -0
- package/dist/src/protocol/rack-wire.d.ts +357 -0
- package/dist/src/protocol/rack-wire.d.ts.map +1 -0
- package/dist/src/protocol/rack-wire.js +262 -0
- package/dist/src/protocol/rack-wire.js.map +1 -0
- package/dist/src/protocol/rack-wire.spec.d.ts +6 -0
- package/dist/src/protocol/rack-wire.spec.d.ts.map +1 -0
- package/dist/src/protocol/rack-wire.spec.js +14 -0
- package/dist/src/protocol/rack-wire.spec.js.map +1 -0
- package/dist/src/protocol/registration.d.ts +70 -0
- package/dist/src/protocol/registration.d.ts.map +1 -0
- package/dist/src/protocol/registration.js +67 -0
- package/dist/src/protocol/registration.js.map +1 -0
- package/dist/src/protocol/session-data.d.ts +69 -0
- package/dist/src/protocol/session-data.d.ts.map +1 -0
- package/dist/src/protocol/session-data.js +26 -0
- package/dist/src/protocol/session-data.js.map +1 -0
- package/dist/src/protocol/task-envelope.d.ts +198 -0
- package/dist/src/protocol/task-envelope.d.ts.map +1 -0
- package/dist/src/protocol/task-envelope.js +93 -0
- package/dist/src/protocol/task-envelope.js.map +1 -0
- package/dist/src/protocol/wire-golden.d.ts +8 -0
- package/dist/src/protocol/wire-golden.d.ts.map +1 -0
- package/dist/src/protocol/wire-golden.js +34 -0
- package/dist/src/protocol/wire-golden.js.map +1 -0
- package/dist/src/protocol/wire-samples.d.ts +11 -0
- package/dist/src/protocol/wire-samples.d.ts.map +1 -0
- package/dist/src/protocol/wire-samples.js +52 -0
- package/dist/src/protocol/wire-samples.js.map +1 -0
- package/dist/src/registry/file-rack-registry.d.ts +68 -0
- package/dist/src/registry/file-rack-registry.d.ts.map +1 -0
- package/dist/src/registry/file-rack-registry.js +138 -0
- package/dist/src/registry/file-rack-registry.js.map +1 -0
- package/dist/src/registry/file-rack-registry.spec.d.ts +6 -0
- package/dist/src/registry/file-rack-registry.spec.d.ts.map +1 -0
- package/dist/src/registry/file-rack-registry.spec.js +50 -0
- package/dist/src/registry/file-rack-registry.spec.js.map +1 -0
- package/dist/src/registry/rack-registry.d.ts +64 -0
- package/dist/src/registry/rack-registry.d.ts.map +1 -0
- package/dist/src/registry/rack-registry.js +65 -0
- package/dist/src/registry/rack-registry.js.map +1 -0
- package/dist/src/registry/rack-registry.spec.d.ts +6 -0
- package/dist/src/registry/rack-registry.spec.d.ts.map +1 -0
- package/dist/src/registry/rack-registry.spec.js +8 -0
- package/dist/src/registry/rack-registry.spec.js.map +1 -0
- package/dist/src/routing/eligibility.d.ts +38 -0
- package/dist/src/routing/eligibility.d.ts.map +1 -0
- package/dist/src/routing/eligibility.js +78 -0
- package/dist/src/routing/eligibility.js.map +1 -0
- package/dist/src/routing/host-coupling.d.ts +26 -0
- package/dist/src/routing/host-coupling.d.ts.map +1 -0
- package/dist/src/routing/host-coupling.js +62 -0
- package/dist/src/routing/host-coupling.js.map +1 -0
- package/dist/src/routing/policy.d.ts +188 -0
- package/dist/src/routing/policy.d.ts.map +1 -0
- package/dist/src/routing/policy.js +212 -0
- package/dist/src/routing/policy.js.map +1 -0
- package/dist/src/routing/routing.spec.d.ts +6 -0
- package/dist/src/routing/routing.spec.d.ts.map +1 -0
- package/dist/src/routing/routing.spec.js +100 -0
- package/dist/src/routing/routing.spec.js.map +1 -0
- package/dist/src/routing/tiers.d.ts +22 -0
- package/dist/src/routing/tiers.d.ts.map +1 -0
- package/dist/src/routing/tiers.js +26 -0
- package/dist/src/routing/tiers.js.map +1 -0
- package/dist/src/runner/api-server.d.ts +45 -0
- package/dist/src/runner/api-server.d.ts.map +1 -0
- package/dist/src/runner/api-server.js +21 -0
- package/dist/src/runner/api-server.js.map +1 -0
- package/dist/src/runner/capacity.d.ts +13 -0
- package/dist/src/runner/capacity.d.ts.map +1 -0
- package/dist/src/runner/capacity.js +18 -0
- package/dist/src/runner/capacity.js.map +1 -0
- package/dist/src/runner/rack-body.d.ts +43 -0
- package/dist/src/runner/rack-body.d.ts.map +1 -0
- package/dist/src/runner/rack-body.js +208 -0
- package/dist/src/runner/rack-body.js.map +1 -0
- package/dist/src/runner/rack-runner.d.ts +62 -0
- package/dist/src/runner/rack-runner.d.ts.map +1 -0
- package/dist/src/runner/rack-runner.js +75 -0
- package/dist/src/runner/rack-runner.js.map +1 -0
- package/dist/src/runner/rack-runner.spec.d.ts +6 -0
- package/dist/src/runner/rack-runner.spec.d.ts.map +1 -0
- package/dist/src/runner/rack-runner.spec.js +302 -0
- package/dist/src/runner/rack-runner.spec.js.map +1 -0
- package/dist/src/runner/split.spec.d.ts +6 -0
- package/dist/src/runner/split.spec.d.ts.map +1 -0
- package/dist/src/runner/split.spec.js +188 -0
- package/dist/src/runner/split.spec.js.map +1 -0
- package/dist/src/runner-event.d.ts +261 -0
- package/dist/src/runner-event.d.ts.map +1 -0
- package/dist/src/runner-event.js +332 -0
- package/dist/src/runner-event.js.map +1 -0
- package/dist/src/server/beast2.d.ts +19 -0
- package/dist/src/server/beast2.d.ts.map +1 -0
- package/dist/src/server/beast2.js +18 -0
- package/dist/src/server/beast2.js.map +1 -0
- package/dist/src/server/body-limit.d.ts +16 -0
- package/dist/src/server/body-limit.d.ts.map +1 -0
- package/dist/src/server/body-limit.js +53 -0
- package/dist/src/server/body-limit.js.map +1 -0
- package/dist/src/server/body-limit.spec.d.ts +2 -0
- package/dist/src/server/body-limit.spec.d.ts.map +1 -0
- package/dist/src/server/body-limit.spec.js +32 -0
- package/dist/src/server/body-limit.spec.js.map +1 -0
- package/dist/src/server/bounded.d.ts +16 -0
- package/dist/src/server/bounded.d.ts.map +1 -0
- package/dist/src/server/bounded.js +39 -0
- package/dist/src/server/bounded.js.map +1 -0
- package/dist/src/server/dispatch.d.ts +137 -0
- package/dist/src/server/dispatch.d.ts.map +1 -0
- package/dist/src/server/dispatch.js +267 -0
- package/dist/src/server/dispatch.js.map +1 -0
- package/dist/src/server/env-publication.d.ts +45 -0
- package/dist/src/server/env-publication.d.ts.map +1 -0
- package/dist/src/server/env-publication.js +10 -0
- package/dist/src/server/env-publication.js.map +1 -0
- package/dist/src/server/index.d.ts +16 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +17 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/protocol.spec.d.ts +6 -0
- package/dist/src/server/protocol.spec.d.ts.map +1 -0
- package/dist/src/server/protocol.spec.js +78 -0
- package/dist/src/server/protocol.spec.js.map +1 -0
- package/dist/src/server/rack-routes.d.ts +175 -0
- package/dist/src/server/rack-routes.d.ts.map +1 -0
- package/dist/src/server/rack-routes.js +755 -0
- package/dist/src/server/rack-routes.js.map +1 -0
- package/dist/src/server/rack-routes.spec.d.ts +6 -0
- package/dist/src/server/rack-routes.spec.d.ts.map +1 -0
- package/dist/src/server/rack-routes.spec.js +477 -0
- package/dist/src/server/rack-routes.spec.js.map +1 -0
- package/dist/src/server/storage-bridge.d.ts +140 -0
- package/dist/src/server/storage-bridge.d.ts.map +1 -0
- package/dist/src/server/storage-bridge.js +6 -0
- package/dist/src/server/storage-bridge.js.map +1 -0
- package/dist/src/state-file.d.ts +10 -0
- package/dist/src/state-file.d.ts.map +1 -0
- package/dist/src/state-file.js +38 -0
- package/dist/src/state-file.js.map +1 -0
- package/dist/src/testing/in-memory.d.ts +116 -0
- package/dist/src/testing/in-memory.d.ts.map +1 -0
- package/dist/src/testing/in-memory.js +193 -0
- package/dist/src/testing/in-memory.js.map +1 -0
- package/dist/src/testing/index.d.ts +14 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +14 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/lease-store-contract.d.ts +14 -0
- package/dist/src/testing/lease-store-contract.d.ts.map +1 -0
- package/dist/src/testing/lease-store-contract.js +78 -0
- package/dist/src/testing/lease-store-contract.js.map +1 -0
- package/dist/src/testing/protocol-suite.d.ts +38 -0
- package/dist/src/testing/protocol-suite.d.ts.map +1 -0
- package/dist/src/testing/protocol-suite.js +207 -0
- package/dist/src/testing/protocol-suite.js.map +1 -0
- package/dist/src/testing/rack-registry-contract.d.ts +15 -0
- package/dist/src/testing/rack-registry-contract.d.ts.map +1 -0
- package/dist/src/testing/rack-registry-contract.js +106 -0
- package/dist/src/testing/rack-registry-contract.js.map +1 -0
- package/dist/src/testing/test-rack-agent.d.ts +121 -0
- package/dist/src/testing/test-rack-agent.d.ts.map +1 -0
- package/dist/src/testing/test-rack-agent.js +316 -0
- package/dist/src/testing/test-rack-agent.js.map +1 -0
- package/dist/src/tls/tls.d.ts +67 -0
- package/dist/src/tls/tls.d.ts.map +1 -0
- package/dist/src/tls/tls.js +200 -0
- package/dist/src/tls/tls.js.map +1 -0
- package/dist/src/tls/tls.spec.d.ts +6 -0
- package/dist/src/tls/tls.spec.d.ts.map +1 -0
- package/dist/src/tls/tls.spec.js +101 -0
- package/dist/src/tls/tls.spec.js.map +1 -0
- package/dist/src/version.d.ts +9 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +10 -0
- package/dist/src/version.js.map +1 -0
- package/package.json +67 -7
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { RackLeaseStatus } from './rack-dispatch.js';
|
|
6
|
+
import type { RackLeaseAttempt, RackLeaseEvent, RackLeaseResult } from '../protocol/task-envelope.js';
|
|
7
|
+
/**
|
|
8
|
+
* The most object keys a lease may be issued write targets for (#214): its
|
|
9
|
+
* row records each, and a failed or expired lease deletes the uncatalogued
|
|
10
|
+
* versions of each. A unit that writes more new objects than this falls back
|
|
11
|
+
* to the cloud.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MAX_LEASE_TARGETS = 4096;
|
|
14
|
+
/** A stored lease — the persistent shape behind the RackDispatch seam. */
|
|
15
|
+
export interface RackLeaseRecord {
|
|
16
|
+
/** `{taskHash}#{inputsHash}#{uuidv7}` — see {@link makeLeaseId}. */
|
|
17
|
+
leaseId: string;
|
|
18
|
+
repo: string;
|
|
19
|
+
workspace: string;
|
|
20
|
+
taskHash: string;
|
|
21
|
+
inputsHash: string;
|
|
22
|
+
/** The rack tier the task needs (node | py | c | ...). */
|
|
23
|
+
tier: string;
|
|
24
|
+
/** The task's compute size tag — the agent's VM shape (default serverless). */
|
|
25
|
+
computeSize?: string;
|
|
26
|
+
status: RackLeaseStatus;
|
|
27
|
+
/** The rack that claimed it (set on claim and preserved after). */
|
|
28
|
+
claimedBy?: string;
|
|
29
|
+
/** Epoch ms of the (latest) claim — the rack-activity timeline (D12 UI). */
|
|
30
|
+
claimedAtMs?: number;
|
|
31
|
+
/** Epoch ms of completion. */
|
|
32
|
+
completedAtMs?: number;
|
|
33
|
+
/** Epoch ms; while `claimed`, past-deadline means reclaimable. */
|
|
34
|
+
visibilityDeadlineMs?: number;
|
|
35
|
+
/** The task envelope the agent executes. */
|
|
36
|
+
event: RackLeaseEvent;
|
|
37
|
+
/** The attempt the latest claim runs: minted by the claim, for a task or
|
|
38
|
+
* unit lease (#214) */
|
|
39
|
+
attempt?: RackLeaseAttempt;
|
|
40
|
+
/** The object hashes the lease was issued write targets for (#214): what
|
|
41
|
+
* its end deletes the uncatalogued versions of */
|
|
42
|
+
targets?: readonly string[];
|
|
43
|
+
/** Terminal result (set on `completed`). */
|
|
44
|
+
result?: RackLeaseResult;
|
|
45
|
+
createdAtMs: number;
|
|
46
|
+
}
|
|
47
|
+
/** Disposition of a completion attempt (accepted-and-discarded semantics). */
|
|
48
|
+
export type CompleteDisposition = 'recorded' | 'idempotent' | 'discarded';
|
|
49
|
+
/**
|
|
50
|
+
* Build a lease id embedding the re-attachment key.
|
|
51
|
+
*
|
|
52
|
+
* @param taskHash - The task's content hash
|
|
53
|
+
* @param inputsHash - Hash of the resolved input set
|
|
54
|
+
* @returns `{taskHash}#{inputsHash}#{uuidv7}`: a fresh id, which sorts after every earlier lease of the task
|
|
55
|
+
* @example
|
|
56
|
+
* const leaseId = makeLeaseId(taskHash, inputsHash);
|
|
57
|
+
*/
|
|
58
|
+
export declare function makeLeaseId(taskHash: string, inputsHash: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* The key prefix all leases for a task identity share.
|
|
61
|
+
*
|
|
62
|
+
* @param taskHash - The task's content hash
|
|
63
|
+
* @param inputsHash - Hash of the resolved input set
|
|
64
|
+
* @returns `{taskHash}#{inputsHash}#`
|
|
65
|
+
* @example
|
|
66
|
+
* const ofTask = ids.filter((id) => id.startsWith(leaseIdPrefix(taskHash, inputsHash)));
|
|
67
|
+
*/
|
|
68
|
+
export declare function leaseIdPrefix(taskHash: string, inputsHash: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Whether a lease can be claimed right now: pending, or claimed with an
|
|
71
|
+
* expired visibility deadline (the claimant went quiet).
|
|
72
|
+
*
|
|
73
|
+
* @param record - The stored lease
|
|
74
|
+
* @param nowMs - Current epoch ms
|
|
75
|
+
* @returns Whether a claim would take it
|
|
76
|
+
* @example
|
|
77
|
+
* const candidates = records.filter((record) => isClaimable(record, Date.now()));
|
|
78
|
+
*/
|
|
79
|
+
export declare function isClaimable(record: RackLeaseRecord, nowMs: number): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Whether a rack lease is still held: claimed within its visibility deadline,
|
|
82
|
+
* which the claimant's heartbeat extends, or pending a claim. A rack
|
|
83
|
+
* attempt's liveness (#206, `launchLiveness`): the attempt can still finish
|
|
84
|
+
* while its lease is held.
|
|
85
|
+
*
|
|
86
|
+
* @param leases - The lease store
|
|
87
|
+
* @param now - The time, in ms since the epoch (default `Date.now`)
|
|
88
|
+
* @returns Whether a repository's lease is held
|
|
89
|
+
*/
|
|
90
|
+
export declare function rackLeaseHeld(leases: Pick<RackLeaseStore, 'get'>, now?: () => number): (repo: string, leaseId: string) => Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Rack lease persistence seam. Implementations: `InMemoryRackLeaseStore`
|
|
93
|
+
* (testing) and `DynamoRackLeaseStore` (e3-aws; lease rows under
|
|
94
|
+
* `PK=RACKLEASE/{repo}` plus a small `PK=RACKQUEUE` discovery partition).
|
|
95
|
+
*/
|
|
96
|
+
export interface RackLeaseStore {
|
|
97
|
+
/** Persist a new pending lease (and its queue-discovery entry). */
|
|
98
|
+
put(record: RackLeaseRecord): Promise<void>;
|
|
99
|
+
/** Read one lease. */
|
|
100
|
+
get(repo: string, leaseId: string): Promise<RackLeaseRecord | null>;
|
|
101
|
+
/**
|
|
102
|
+
* Latest lease for a task identity that is not superseded/cancelled —
|
|
103
|
+
* the yield re-attachment lookup (prefix query on the lease id).
|
|
104
|
+
*/
|
|
105
|
+
findByTask(repo: string, taskHash: string, inputsHash: string): Promise<RackLeaseRecord | null>;
|
|
106
|
+
/**
|
|
107
|
+
* Leases an agent with the given tiers could claim right now (pending or
|
|
108
|
+
* visibility-expired), oldest first.
|
|
109
|
+
*
|
|
110
|
+
* @param tiers - The tiers the agent has rootfs for
|
|
111
|
+
* @param nowMs - Current epoch ms
|
|
112
|
+
* @param limit - Max candidates to return
|
|
113
|
+
*/
|
|
114
|
+
listClaimable(tiers: string[], nowMs: number, limit: number): Promise<RackLeaseRecord[]>;
|
|
115
|
+
/**
|
|
116
|
+
* Conditionally claim a lease: succeeds only while {@link isClaimable}.
|
|
117
|
+
* Exactly one racing claimant wins.
|
|
118
|
+
*
|
|
119
|
+
* @param attempt - The attempt the claim runs, for a task or unit lease
|
|
120
|
+
* (#214): it replaces the one an earlier claim ran
|
|
121
|
+
* @returns The claimed record, or null when the condition lost
|
|
122
|
+
*/
|
|
123
|
+
claim(repo: string, leaseId: string, rackId: string, visibilityDeadlineMs: number, attempt?: RackLeaseAttempt): Promise<RackLeaseRecord | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Record object hashes a lease was issued write targets for (#214), only
|
|
126
|
+
* by its claimant while it holds the lease. The lease keeps each once.
|
|
127
|
+
*
|
|
128
|
+
* @returns Whether they were recorded: false when the lease is not held by
|
|
129
|
+
* the rack
|
|
130
|
+
*/
|
|
131
|
+
recordTargets(repo: string, leaseId: string, rackId: string, hashes: readonly string[]): Promise<boolean>;
|
|
132
|
+
/**
|
|
133
|
+
* Recent leases claimed by a rack, newest first — the fleet-table
|
|
134
|
+
* activity view ("what has this rack done"). A lease reclaimed by
|
|
135
|
+
* ANOTHER rack after visibility expiry leaves this rack's list (the
|
|
136
|
+
* record tracks its latest claimant only).
|
|
137
|
+
*
|
|
138
|
+
* @param rackId - The rack whose activity is listed
|
|
139
|
+
* @param limit - Max records
|
|
140
|
+
*/
|
|
141
|
+
listRecentByRack(rackId: string, limit: number): Promise<RackLeaseRecord[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Extend a claimed lease's visibility — only by its claimant.
|
|
144
|
+
*
|
|
145
|
+
* @returns Whether the extension applied
|
|
146
|
+
*/
|
|
147
|
+
extend(repo: string, leaseId: string, rackId: string, visibilityDeadlineMs: number): Promise<boolean>;
|
|
148
|
+
/**
|
|
149
|
+
* Record a terminal result — only transitions `claimed → completed` by
|
|
150
|
+
* the claimant. Anything else is 'idempotent' (already completed) or
|
|
151
|
+
* 'discarded' (superseded/cancelled/expired-and-reclaimed/unknown).
|
|
152
|
+
*/
|
|
153
|
+
complete(repo: string, leaseId: string, rackId: string, result: RackLeaseResult): Promise<CompleteDisposition>;
|
|
154
|
+
/**
|
|
155
|
+
* CAS supersede (runner falling back to cloud): `pending|claimed →
|
|
156
|
+
* superseded`; a completed lease stays completed.
|
|
157
|
+
*
|
|
158
|
+
* @returns The lease's state after the attempt
|
|
159
|
+
*/
|
|
160
|
+
supersede(repo: string, leaseId: string): Promise<RackLeaseRecord | null>;
|
|
161
|
+
/**
|
|
162
|
+
* CAS cancel: `pending|claimed → cancelled`; a completed lease stays
|
|
163
|
+
* completed. Heartbeats deliver the signal to the running agent.
|
|
164
|
+
*
|
|
165
|
+
* @returns The lease's state after the attempt
|
|
166
|
+
*/
|
|
167
|
+
cancel(repo: string, leaseId: string): Promise<RackLeaseRecord | null>;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=lease-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease-store.d.ts","sourceRoot":"","sources":["../../../src/lease/lease-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Rack lease persistence (#73, epic #67 design §9.2–9.3) — the DynamoDB-
|
|
7
|
+
* layered pull queue behind {@link StoreRackDispatch} and the /rack
|
|
8
|
+
* dispatch routes.
|
|
9
|
+
*
|
|
10
|
+
* Lease state machine (review F3), every transition a conditional write:
|
|
11
|
+
*
|
|
12
|
+
* pending ──claim──▶ claimed ──complete──▶ completed
|
|
13
|
+
* │ │ ▲
|
|
14
|
+
* │ │ └─ extend (visibility)
|
|
15
|
+
* │ visibility expires (lazily observed: the lease becomes
|
|
16
|
+
* │ claimable again; a claim retakes it)
|
|
17
|
+
* ├──supersede──▶ superseded (runner fell back to cloud)
|
|
18
|
+
* └──cancel─────▶ cancelled (heartbeat delivers; agent kills the VM)
|
|
19
|
+
*
|
|
20
|
+
* `complete` against superseded/cancelled (or by a non-claimant) is
|
|
21
|
+
* **accepted-and-discarded** — never an error, the response just tells the
|
|
22
|
+
* agent to drop local state. `complete` on completed is idempotent-success.
|
|
23
|
+
* Supersede/cancel are CAS: an already-completed lease stays completed and
|
|
24
|
+
* the caller receives it (completed-wins).
|
|
25
|
+
*
|
|
26
|
+
* The lease id embeds the task identity (`{taskHash}#{inputsHash}#{uuid}`)
|
|
27
|
+
* so the store can find re-attachable leases with a key-prefix query — no
|
|
28
|
+
* scans, no extra index.
|
|
29
|
+
*/
|
|
30
|
+
import { uuidv7 } from '@elaraai/e3-core';
|
|
31
|
+
/**
|
|
32
|
+
* The most object keys a lease may be issued write targets for (#214): its
|
|
33
|
+
* row records each, and a failed or expired lease deletes the uncatalogued
|
|
34
|
+
* versions of each. A unit that writes more new objects than this falls back
|
|
35
|
+
* to the cloud.
|
|
36
|
+
*/
|
|
37
|
+
export const MAX_LEASE_TARGETS = 4096;
|
|
38
|
+
/**
|
|
39
|
+
* Build a lease id embedding the re-attachment key.
|
|
40
|
+
*
|
|
41
|
+
* @param taskHash - The task's content hash
|
|
42
|
+
* @param inputsHash - Hash of the resolved input set
|
|
43
|
+
* @returns `{taskHash}#{inputsHash}#{uuidv7}`: a fresh id, which sorts after every earlier lease of the task
|
|
44
|
+
* @example
|
|
45
|
+
* const leaseId = makeLeaseId(taskHash, inputsHash);
|
|
46
|
+
*/
|
|
47
|
+
export function makeLeaseId(taskHash, inputsHash) {
|
|
48
|
+
return `${taskHash}#${inputsHash}#${uuidv7()}`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The key prefix all leases for a task identity share.
|
|
52
|
+
*
|
|
53
|
+
* @param taskHash - The task's content hash
|
|
54
|
+
* @param inputsHash - Hash of the resolved input set
|
|
55
|
+
* @returns `{taskHash}#{inputsHash}#`
|
|
56
|
+
* @example
|
|
57
|
+
* const ofTask = ids.filter((id) => id.startsWith(leaseIdPrefix(taskHash, inputsHash)));
|
|
58
|
+
*/
|
|
59
|
+
export function leaseIdPrefix(taskHash, inputsHash) {
|
|
60
|
+
return `${taskHash}#${inputsHash}#`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether a lease can be claimed right now: pending, or claimed with an
|
|
64
|
+
* expired visibility deadline (the claimant went quiet).
|
|
65
|
+
*
|
|
66
|
+
* @param record - The stored lease
|
|
67
|
+
* @param nowMs - Current epoch ms
|
|
68
|
+
* @returns Whether a claim would take it
|
|
69
|
+
* @example
|
|
70
|
+
* const candidates = records.filter((record) => isClaimable(record, Date.now()));
|
|
71
|
+
*/
|
|
72
|
+
export function isClaimable(record, nowMs) {
|
|
73
|
+
return (record.status === 'pending' ||
|
|
74
|
+
(record.status === 'claimed' && (record.visibilityDeadlineMs ?? 0) < nowMs));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether a rack lease is still held: claimed within its visibility deadline,
|
|
78
|
+
* which the claimant's heartbeat extends, or pending a claim. A rack
|
|
79
|
+
* attempt's liveness (#206, `launchLiveness`): the attempt can still finish
|
|
80
|
+
* while its lease is held.
|
|
81
|
+
*
|
|
82
|
+
* @param leases - The lease store
|
|
83
|
+
* @param now - The time, in ms since the epoch (default `Date.now`)
|
|
84
|
+
* @returns Whether a repository's lease is held
|
|
85
|
+
*/
|
|
86
|
+
export function rackLeaseHeld(leases, now = Date.now) {
|
|
87
|
+
return async (repo, leaseId) => {
|
|
88
|
+
const record = await leases.get(repo, leaseId);
|
|
89
|
+
if (record === null)
|
|
90
|
+
return false;
|
|
91
|
+
return record.status === 'pending' || (record.status === 'claimed' && (record.visibilityDeadlineMs ?? 0) >= now());
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=lease-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease-store.js","sourceRoot":"","sources":["../../../src/lease/lease-store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAuCtC;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,UAAkB;IAC9D,OAAO,GAAG,QAAQ,IAAI,UAAU,IAAI,MAAM,EAAE,EAAE,CAAC;AACjD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,UAAkB;IAChE,OAAO,GAAG,QAAQ,IAAI,UAAU,GAAG,CAAC;AACtC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,MAAuB,EAAE,KAAa;IAChE,OAAO,CACL,MAAM,CAAC,MAAM,KAAK,SAAS;QAC3B,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAmC,EACnC,MAAoB,IAAI,CAAC,GAAG;IAE5B,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAClC,OAAO,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACrH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease-store.spec.d.ts","sourceRoot":"","sources":["../../../src/lease/lease-store.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { InMemoryRackLeaseStore } from './in-memory-lease-store.js';
|
|
6
|
+
import { leaseStoreContract } from '../testing/lease-store-contract.js';
|
|
7
|
+
leaseStoreContract('memory', () => new InMemoryRackLeaseStore());
|
|
8
|
+
//# sourceMappingURL=lease-store.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease-store.spec.js","sourceRoot":"","sources":["../../../src/lease/lease-store.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAExE,kBAAkB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The rack dispatch seam DelegatingTaskRunner drives (epic #67 design §7.3,
|
|
7
|
+
* §9.2 rev. 2026-07-11). #73 implements it over the RackLease store +
|
|
8
|
+
* registry; FakeRackDispatch (testing) lets #70 land and test independently.
|
|
9
|
+
*
|
|
10
|
+
* Lease lifecycle (every transition a conditional write):
|
|
11
|
+
* `pending → claimed → completed | superseded | cancelled`, with visibility
|
|
12
|
+
* expiry making a claimed lease reclaimable. A completion against a
|
|
13
|
+
* superseded/cancelled lease is accepted-and-discarded by the store. The
|
|
14
|
+
* cloud records a task or unit lease's attempt itself (#214): `running` when
|
|
15
|
+
* a rack claims it, its outcome when the rack completes it, and `interrupted`
|
|
16
|
+
* or `cancelled` when it is superseded or cancelled while claimed.
|
|
17
|
+
*/
|
|
18
|
+
import type { RackLeaseAttempt, RackLeaseEvent, RackLeaseResult } from '../protocol/task-envelope.js';
|
|
19
|
+
/** A lease's lifecycle state. */
|
|
20
|
+
export type RackLeaseStatus = 'pending' | 'claimed' | 'completed' | 'superseded' | 'cancelled';
|
|
21
|
+
/** One delegated task hand-off. */
|
|
22
|
+
export interface RackLease {
|
|
23
|
+
leaseId: string;
|
|
24
|
+
repo: string;
|
|
25
|
+
workspace: string;
|
|
26
|
+
/** Task identity — the re-attachment key across orchestrator yields. */
|
|
27
|
+
taskHash: string;
|
|
28
|
+
inputsHash: string;
|
|
29
|
+
/** The dataflow run this lease belongs to, a UUIDv7: re-attach is scoped
|
|
30
|
+
* to it (a lease from a prior run is never a cache; #67) */
|
|
31
|
+
runId?: string;
|
|
32
|
+
/** The rack tier it runs on */
|
|
33
|
+
tier: string;
|
|
34
|
+
/** The compute size tag its VM is shaped by */
|
|
35
|
+
computeSize: string;
|
|
36
|
+
status: RackLeaseStatus;
|
|
37
|
+
/** The rack that claimed it (set on `claimed` and beyond). */
|
|
38
|
+
claimedBy?: string;
|
|
39
|
+
/** The attempt its latest claim runs, for a task or unit lease (#214) */
|
|
40
|
+
attempt?: RackLeaseAttempt;
|
|
41
|
+
/** Terminal result (set on `completed`). */
|
|
42
|
+
result?: RackLeaseResult;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* What DelegatingTaskRunner needs from the rack control plane. Implemented
|
|
46
|
+
* over the lease store + rack registry (#73); faked in tests.
|
|
47
|
+
*/
|
|
48
|
+
export interface RackDispatch {
|
|
49
|
+
/**
|
|
50
|
+
* Whether any healthy enrolled rack advertises the tier and runs an agent
|
|
51
|
+
* that runs a v2 lease (0.5.0 and later, #214): the prefer-rack
|
|
52
|
+
* availability check. NOT per-rack targeting: the v1 lease pool is
|
|
53
|
+
* repo-global and any matching agent claims.
|
|
54
|
+
*
|
|
55
|
+
* @param tier - The work's rack tier (node | py | c | full | env base)
|
|
56
|
+
*/
|
|
57
|
+
anyHealthyRackWithTier(tier: string): Promise<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* The rack tier (base image) a PUBLISHED environment was built on, or
|
|
60
|
+
* null when the env is not published for rack execution (#94 Slice D).
|
|
61
|
+
* Also the delegability gate for env/custom tasks: null ⇒ cloud.
|
|
62
|
+
*
|
|
63
|
+
* @param envHash - The task's declared environment hash
|
|
64
|
+
*/
|
|
65
|
+
envBaseTier(envHash: string): Promise<string | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Find a live (pending/claimed) or completed lease for a task — the
|
|
68
|
+
* re-attachment path a resumed orchestrator cycle takes instead of
|
|
69
|
+
* creating a duplicate.
|
|
70
|
+
*/
|
|
71
|
+
findLease(repo: string, taskHash: string, inputsHash: string): Promise<RackLease | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Create a pending lease carrying the work's event.
|
|
74
|
+
*
|
|
75
|
+
* @param event - The v2 lease event the agent will run
|
|
76
|
+
* @param tier - The rack tier the work requires
|
|
77
|
+
* @param computeSize - The work's resolved compute size tag (VM shape)
|
|
78
|
+
*/
|
|
79
|
+
createLease(event: RackLeaseEvent, tier: string, computeSize?: string): Promise<RackLease>;
|
|
80
|
+
/** Re-read a lease's current state. */
|
|
81
|
+
getLease(repo: string, leaseId: string): Promise<RackLease | null>;
|
|
82
|
+
/**
|
|
83
|
+
* Terminally supersede a lease (runner falling back to cloud). A CAS —
|
|
84
|
+
* a lease already `completed` stays completed (the store returns the
|
|
85
|
+
* final state so the caller can still use a result that won the race).
|
|
86
|
+
* A claimed lease's attempt is recorded `interrupted` (#214).
|
|
87
|
+
*
|
|
88
|
+
* @returns The lease's state after the attempt
|
|
89
|
+
*/
|
|
90
|
+
supersede(repo: string, leaseId: string): Promise<RackLease | null>;
|
|
91
|
+
/**
|
|
92
|
+
* Terminally cancel a lease: its run was cancelled. A CAS, as
|
|
93
|
+
* {@link supersede}; the rack's next heartbeat stops it, and a claimed
|
|
94
|
+
* lease's attempt is recorded `cancelled` (#214).
|
|
95
|
+
*
|
|
96
|
+
* @returns The lease's state after the attempt
|
|
97
|
+
*/
|
|
98
|
+
cancel(repo: string, leaseId: string): Promise<RackLease | null>;
|
|
99
|
+
/**
|
|
100
|
+
* Whether a lease is still held: pending a claim, or claimed within its
|
|
101
|
+
* visibility deadline. A rack attempt's liveness (#206, #214).
|
|
102
|
+
*/
|
|
103
|
+
leaseHeld(repo: string, leaseId: string): Promise<boolean>;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=rack-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rack-dispatch.d.ts","sourceRoot":"","sources":["../../../src/lease/rack-dispatch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEtG,iCAAiC;AACjC,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,CAAC;AAE/F,mCAAmC;AACnC,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB;iEAC6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD;;;;;;OAMG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAErD;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEzF;;;;;;OAMG;IACH,WAAW,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAE3F,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEnE;;;;;;;OAOG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEpE;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEjE;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rack-dispatch.js","sourceRoot":"","sources":["../../../src/lease/rack-dispatch.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/** Serializes a store's mutations; failed mutations do not poison the queue. @internal */
|
|
6
|
+
export declare class MutationQueue {
|
|
7
|
+
private tail;
|
|
8
|
+
/** Runs the operation after every preceding operation has settled. */
|
|
9
|
+
run<T>(operation: () => Promise<T>): Promise<T>;
|
|
10
|
+
/** Waits for all operations already queued. */
|
|
11
|
+
idle(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=mutation-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-queue.d.ts","sourceRoot":"","sources":["../../src/mutation-queue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,0FAA0F;AAC1F,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAuC;IAEnD,sEAAsE;IACtE,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAM/C,+CAA+C;IACzC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAC5B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/** Serializes a store's mutations; failed mutations do not poison the queue. @internal */
|
|
6
|
+
export class MutationQueue {
|
|
7
|
+
tail = Promise.resolve();
|
|
8
|
+
/** Runs the operation after every preceding operation has settled. */
|
|
9
|
+
run(operation) {
|
|
10
|
+
const result = this.tail.then(operation);
|
|
11
|
+
this.tail = result.catch(() => undefined);
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
/** Waits for all operations already queued. */
|
|
15
|
+
async idle() { await this.tail; }
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=mutation-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-queue.js","sourceRoot":"","sources":["../../src/mutation-queue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,0FAA0F;AAC1F,MAAM,OAAO,aAAa;IAChB,IAAI,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEnD,sEAAsE;IACtE,GAAG,CAAI,SAA2B;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,IAAI,KAAoB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;CACjD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/** The hashed machine credentials, under the rack home. */
|
|
6
|
+
export declare const IDENTITY_FILE = "identity.beast2";
|
|
7
|
+
/** The enrolled machines and their security policy. */
|
|
8
|
+
export declare const RACKS_FILE = "racks.beast2";
|
|
9
|
+
/** The hub's listening address and advertised origin. */
|
|
10
|
+
export declare const HUB_CONFIG_FILE = "hub-config.beast2";
|
|
11
|
+
/** The hub's TLS certificate and private key, created when its listener first serves TLS. */
|
|
12
|
+
export declare const HUB_TLS_FILE = "hub-tls.beast2";
|
|
13
|
+
/** The single hub's ownership record. */
|
|
14
|
+
export declare const HUB_LOCK_FILE = "hub.lock";
|
|
15
|
+
/** The hub process's diagnostic log. */
|
|
16
|
+
export declare const HUB_LOG_FILE = "hub.log";
|
|
17
|
+
/**
|
|
18
|
+
* Resolves this user's rack home, respecting `E3_RACK_HOME`.
|
|
19
|
+
* @returns An absolute path
|
|
20
|
+
* @example
|
|
21
|
+
* const home = rackHome();
|
|
22
|
+
*/
|
|
23
|
+
export declare function rackHome(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Creates the private rack home, tightening its existing permissions too.
|
|
26
|
+
* @param home - The rack home (default: this user's)
|
|
27
|
+
* @returns Its path
|
|
28
|
+
* @example
|
|
29
|
+
* const home = ensureRackHome();
|
|
30
|
+
*/
|
|
31
|
+
export declare function ensureRackHome(home?: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Checks a socket path against the shortest supported Unix socket limit.
|
|
34
|
+
* @param path - The socket's path
|
|
35
|
+
* @throws {Error} When it exceeds 100 bytes on POSIX
|
|
36
|
+
* @example
|
|
37
|
+
* socketPathOk('/tmp/e3r/hub.sock');
|
|
38
|
+
*/
|
|
39
|
+
export declare function socketPathOk(path: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Names this rack home's hub socket or Windows named pipe.
|
|
42
|
+
* @param home - The rack home
|
|
43
|
+
* @returns Its socket path
|
|
44
|
+
* @example
|
|
45
|
+
* const socket = hubSocketPath(rackHome());
|
|
46
|
+
*/
|
|
47
|
+
export declare function hubSocketPath(home?: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Names a fresh session socket or Windows named pipe.
|
|
50
|
+
* @param home - The rack home
|
|
51
|
+
* @returns Its socket path
|
|
52
|
+
* @example
|
|
53
|
+
* const socket = sessionSocketPath(rackHome());
|
|
54
|
+
*/
|
|
55
|
+
export declare function sessionSocketPath(home?: string): string;
|
|
56
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,2DAA2D;AAC3D,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAC/C,uDAAuD;AACvD,eAAO,MAAM,UAAU,iBAAiB,CAAC;AACzC,yDAAyD;AACzD,eAAO,MAAM,eAAe,sBAAsB,CAAC;AACnD,6FAA6F;AAC7F,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAC7C,yCAAyC;AACzC,eAAO,MAAM,aAAa,aAAa,CAAC;AACxC,wCAAwC;AACxC,eAAO,MAAM,YAAY,YAAY,CAAC;AAEtC;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAa,GAAG,MAAM,CAIxD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,SAAa,GAAG,MAAM,CAMvD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,SAAa,GAAG,MAAM,CAK3D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
6
|
+
import { chmodSync, mkdirSync } from 'node:fs';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
import { join, resolve } from 'node:path';
|
|
9
|
+
/** The hashed machine credentials, under the rack home. */
|
|
10
|
+
export const IDENTITY_FILE = 'identity.beast2';
|
|
11
|
+
/** The enrolled machines and their security policy. */
|
|
12
|
+
export const RACKS_FILE = 'racks.beast2';
|
|
13
|
+
/** The hub's listening address and advertised origin. */
|
|
14
|
+
export const HUB_CONFIG_FILE = 'hub-config.beast2';
|
|
15
|
+
/** The hub's TLS certificate and private key, created when its listener first serves TLS. */
|
|
16
|
+
export const HUB_TLS_FILE = 'hub-tls.beast2';
|
|
17
|
+
/** The single hub's ownership record. */
|
|
18
|
+
export const HUB_LOCK_FILE = 'hub.lock';
|
|
19
|
+
/** The hub process's diagnostic log. */
|
|
20
|
+
export const HUB_LOG_FILE = 'hub.log';
|
|
21
|
+
/**
|
|
22
|
+
* Resolves this user's rack home, respecting `E3_RACK_HOME`.
|
|
23
|
+
* @returns An absolute path
|
|
24
|
+
* @example
|
|
25
|
+
* const home = rackHome();
|
|
26
|
+
*/
|
|
27
|
+
export function rackHome() {
|
|
28
|
+
return resolve(process.env.E3_RACK_HOME ?? join(homedir(), '.e3', 'rack'));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates the private rack home, tightening its existing permissions too.
|
|
32
|
+
* @param home - The rack home (default: this user's)
|
|
33
|
+
* @returns Its path
|
|
34
|
+
* @example
|
|
35
|
+
* const home = ensureRackHome();
|
|
36
|
+
*/
|
|
37
|
+
export function ensureRackHome(home = rackHome()) {
|
|
38
|
+
mkdirSync(home, { recursive: true, mode: 0o700 });
|
|
39
|
+
if (process.platform !== 'win32')
|
|
40
|
+
chmodSync(home, 0o700);
|
|
41
|
+
return home;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Checks a socket path against the shortest supported Unix socket limit.
|
|
45
|
+
* @param path - The socket's path
|
|
46
|
+
* @throws {Error} When it exceeds 100 bytes on POSIX
|
|
47
|
+
* @example
|
|
48
|
+
* socketPathOk('/tmp/e3r/hub.sock');
|
|
49
|
+
*/
|
|
50
|
+
export function socketPathOk(path) {
|
|
51
|
+
if (process.platform !== 'win32' && Buffer.byteLength(path) > 100) {
|
|
52
|
+
throw new Error('Rack socket path exceeds 100 bytes; set E3_RACK_HOME to a shorter path');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Names this rack home's hub socket or Windows named pipe.
|
|
57
|
+
* @param home - The rack home
|
|
58
|
+
* @returns Its socket path
|
|
59
|
+
* @example
|
|
60
|
+
* const socket = hubSocketPath(rackHome());
|
|
61
|
+
*/
|
|
62
|
+
export function hubSocketPath(home = rackHome()) {
|
|
63
|
+
const path = process.platform === 'win32'
|
|
64
|
+
? `\\\\.\\pipe\\e3-rack-hub-${createHash('sha256').update(resolve(home)).digest('hex').slice(0, 12)}`
|
|
65
|
+
: join(home, 'hub.sock');
|
|
66
|
+
socketPathOk(path);
|
|
67
|
+
return path;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Names a fresh session socket or Windows named pipe.
|
|
71
|
+
* @param home - The rack home
|
|
72
|
+
* @returns Its socket path
|
|
73
|
+
* @example
|
|
74
|
+
* const socket = sessionSocketPath(rackHome());
|
|
75
|
+
*/
|
|
76
|
+
export function sessionSocketPath(home = rackHome()) {
|
|
77
|
+
const id = randomBytes(6).toString('hex');
|
|
78
|
+
const path = process.platform === 'win32' ? `\\\\.\\pipe\\e3-rack-s-${id}` : join(home, `s-${id}.sock`);
|
|
79
|
+
socketPathOk(path);
|
|
80
|
+
return path;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,2DAA2D;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAC/C,uDAAuD;AACvD,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC;AACzC,yDAAyD;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC;AACnD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAC7C,yCAAyC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;AACxC,wCAAwC;AACxC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAI,GAAG,QAAQ,EAAE;IAC9C,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAI,GAAG,QAAQ,EAAE;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO;QACvC,CAAC,CAAC,4BAA4B,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;QACrG,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC3B,YAAY,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAI,GAAG,QAAQ,EAAE;IACjD,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACxG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC;AACd,CAAC"}
|