@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,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { type EastType, type ValueTypeOf } from '@elaraai/east';
|
|
6
|
+
import { RackCompleteResponseType, RackHeartbeatResponseType, RackStorageResponseType, type RackLeaseGrant, type RackLeaseRef, type RackLogChunk, type RackStorageRequest } from '../protocol/rack-wire.js';
|
|
7
|
+
import type { RackLeaseResult } from '../protocol/task-envelope.js';
|
|
8
|
+
/** Configures deterministic failures of an in-process protocol peer. */
|
|
9
|
+
export interface TestRackAgentFaults {
|
|
10
|
+
/** Completes this many claims with an infrastructure failure, without an exit code. */
|
|
11
|
+
infraFailNext?: number;
|
|
12
|
+
/** Completes this many claims with exit code 1 without executing the task. */
|
|
13
|
+
taskFailNext?: number;
|
|
14
|
+
/** Holds this many claims silently until the agent stops. */
|
|
15
|
+
hangNext?: number;
|
|
16
|
+
/** Executes this many claims but never posts their completion. */
|
|
17
|
+
dropCompletionNext?: number;
|
|
18
|
+
/** Delays every claim request. */
|
|
19
|
+
claimDelayMs?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Configures a protocol peer backed by a real local runner repository. */
|
|
22
|
+
export interface TestRackAgentOptions {
|
|
23
|
+
/** Origin hosting /api/rack. */
|
|
24
|
+
apiUrl: string;
|
|
25
|
+
/** Transports control requests and object transfers. */
|
|
26
|
+
fetch?: typeof fetch;
|
|
27
|
+
/** Pins a TLS hub's certificate by its SHA-256, as a worker does; ignored when fetch is given. */
|
|
28
|
+
certificateSha256?: string;
|
|
29
|
+
/** Advertises supported runner tiers. */
|
|
30
|
+
tiers?: string[];
|
|
31
|
+
/** Limits concurrent executions. */
|
|
32
|
+
capacity?: number;
|
|
33
|
+
/** Labels the rack registration. */
|
|
34
|
+
label?: string;
|
|
35
|
+
/** Reports the agent and bundled e3 version. */
|
|
36
|
+
agentVersion?: string;
|
|
37
|
+
/** Holds the isolated scratch repository in its repo subdirectory. */
|
|
38
|
+
workDir: string;
|
|
39
|
+
/** Overrides heartbeat and lease-extension intervals. */
|
|
40
|
+
timings?: {
|
|
41
|
+
heartbeatMs?: number;
|
|
42
|
+
extendMs?: number;
|
|
43
|
+
};
|
|
44
|
+
/** Consumes counters in place, permitting faults to be armed during a test. */
|
|
45
|
+
faults?: TestRackAgentFaults;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Exercises the real rack HTTP protocol over an isolated local runner store.
|
|
49
|
+
* It runs e3-core task/unit execution instead of a microVM; it is not a
|
|
50
|
+
* security or isolation boundary, or a substitute for the pinned e3-cloud agent's VM/installer acceptance test.
|
|
51
|
+
* Every input travels through storage descriptors and every output through
|
|
52
|
+
* checksum-bound PUTs and per-object commits.
|
|
53
|
+
* @example
|
|
54
|
+
* const agent = await TestRackAgent.enroll(origin, token);
|
|
55
|
+
* await agent.runOne();
|
|
56
|
+
* await agent.close();
|
|
57
|
+
*/
|
|
58
|
+
export declare class TestRackAgent {
|
|
59
|
+
private readonly options;
|
|
60
|
+
/** Stable identity assigned by enrollment. */
|
|
61
|
+
rackId: string;
|
|
62
|
+
/** Boot identity reported in every poll and heartbeat. */
|
|
63
|
+
readonly bootId: `${string}-${string}-${string}-${string}-${string}`;
|
|
64
|
+
/** Runs against a separate repository, like the guest's staged store. */
|
|
65
|
+
readonly repo: string;
|
|
66
|
+
/** Consumes deterministic faults before executing each claim. */
|
|
67
|
+
readonly faults: TestRackAgentFaults;
|
|
68
|
+
private readonly storage;
|
|
69
|
+
private token;
|
|
70
|
+
private readonly abort;
|
|
71
|
+
private readonly transport;
|
|
72
|
+
private readonly tiers;
|
|
73
|
+
private readonly version;
|
|
74
|
+
private readonly capacity;
|
|
75
|
+
private readonly active;
|
|
76
|
+
private loop;
|
|
77
|
+
private loopError;
|
|
78
|
+
private temporaryHome;
|
|
79
|
+
/** Creates an unenrolled peer; enroll before starting its claim loop.
|
|
80
|
+
* @param options - Transport, scratch directory, capacity and deterministic faults.
|
|
81
|
+
*/
|
|
82
|
+
constructor(options: TestRackAgentOptions);
|
|
83
|
+
/** Enrolls one protocol peer with an automatically cleaned temporary store. */
|
|
84
|
+
static enroll(origin: string, enrollmentToken: string, options?: Omit<TestRackAgentOptions, 'apiUrl' | 'workDir' | 'agentVersion'> & {
|
|
85
|
+
version?: string;
|
|
86
|
+
}): Promise<TestRackAgent>;
|
|
87
|
+
/** Consumes a single-use token and publishes this boot's health.
|
|
88
|
+
* @param enrollmentToken - Token minted by the control plane.
|
|
89
|
+
*/
|
|
90
|
+
enroll(enrollmentToken: string): Promise<void>;
|
|
91
|
+
/** Starts long-polling while slots are free; stop drains all active runners. */
|
|
92
|
+
start(): void;
|
|
93
|
+
private poll;
|
|
94
|
+
/** Posts a typed agent request with a finite transport deadline. */
|
|
95
|
+
raw<T extends EastType>(path: string, type: T, value: ValueTypeOf<T>): Promise<Response>;
|
|
96
|
+
/** Decodes one standard response, raising its typed error. */
|
|
97
|
+
post<Req extends EastType, Res extends EastType>(path: string, type: Req, value: ValueTypeOf<Req>, responseType: Res): Promise<ValueTypeOf<Res>>;
|
|
98
|
+
/** Reports health and returns the leases the hub asks this agent to stop. */
|
|
99
|
+
heartbeat(runningLeases?: RackLeaseRef[]): Promise<ValueTypeOf<typeof RackHeartbeatResponseType>>;
|
|
100
|
+
/** Claims a lease, or answers null after an idle poll window. */
|
|
101
|
+
claim(): Promise<RackLeaseGrant | null>;
|
|
102
|
+
/** Resolves storage descriptors and write receipts for a held lease. */
|
|
103
|
+
storageRequest(lease: RackLeaseRef, request?: Partial<Omit<RackStorageRequest, 'repo' | 'leaseId'>>): Promise<ValueTypeOf<typeof RackStorageResponseType>>;
|
|
104
|
+
/** Streams an ordered log batch through the rack endpoint. */
|
|
105
|
+
logs(lease: RackLeaseRef, chunks: RackLogChunk[]): Promise<boolean>;
|
|
106
|
+
/** Posts an outcome without hiding accepted-and-discarded semantics. */
|
|
107
|
+
complete(lease: RackLeaseRef, result: RackLeaseResult): Promise<ValueTypeOf<typeof RackCompleteResponseType>>;
|
|
108
|
+
/** Fetches a closure through inline descriptors or capability URLs. */
|
|
109
|
+
private fetchObjects;
|
|
110
|
+
/** Executes one claimed task/unit with the production core over the fetched closure. */
|
|
111
|
+
execute(lease: RackLeaseGrant): Promise<RackLeaseResult>;
|
|
112
|
+
private consume;
|
|
113
|
+
private executeClaim;
|
|
114
|
+
/** Claims and executes the next task. */
|
|
115
|
+
runOne(): Promise<RackLeaseResult | null>;
|
|
116
|
+
/** Aborts requests and removes the isolated guest store. */
|
|
117
|
+
close(): Promise<void>;
|
|
118
|
+
/** Stops polling, aborts active executions and waits for runner cleanup. */
|
|
119
|
+
stop(): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=test-rack-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-rack-agent.d.ts","sourceRoot":"","sources":["../../../src/testing/test-rack-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
7
|
+
import { tmpdir } from 'node:os';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
10
|
+
import { BooleanType, decodeBeast2For, encodeBeast2For, none, printFor, variant } from '@elaraai/east';
|
|
11
|
+
import { BEAST2_CONTENT_TYPE, ErrorType, ResponseType } from '@elaraai/e3-types';
|
|
12
|
+
import { LocalStorage, gcObjectReaders, markReachable, repoInit, taskExecute, taskExecuteUnit } from '@elaraai/e3-core';
|
|
13
|
+
import { closureHashes } from '../lease/closure.js';
|
|
14
|
+
import { decodeRunnerEvent, splitUnitFromWire } from '../runner-event.js';
|
|
15
|
+
import { E3_RACK_VERSION } from '../version.js';
|
|
16
|
+
import { pinnedFetch } from '../tls/tls.js';
|
|
17
|
+
import { RackCompleteRequestType, RackCompleteResponseType, RackEnrollRequestType, RackEnrollResponseType, RackExtendRequestType, RackHeartbeatRequestType, RackHeartbeatResponseType, RackLeaseGrantType, RackLeaseRequestType, RackLogsRequestType, RackStorageRequestType, RackStorageResponseType } from '../protocol/rack-wire.js';
|
|
18
|
+
/**
|
|
19
|
+
* Exercises the real rack HTTP protocol over an isolated local runner store.
|
|
20
|
+
* It runs e3-core task/unit execution instead of a microVM; it is not a
|
|
21
|
+
* security or isolation boundary, or a substitute for the pinned e3-cloud agent's VM/installer acceptance test.
|
|
22
|
+
* Every input travels through storage descriptors and every output through
|
|
23
|
+
* checksum-bound PUTs and per-object commits.
|
|
24
|
+
* @example
|
|
25
|
+
* const agent = await TestRackAgent.enroll(origin, token);
|
|
26
|
+
* await agent.runOne();
|
|
27
|
+
* await agent.close();
|
|
28
|
+
*/
|
|
29
|
+
export class TestRackAgent {
|
|
30
|
+
options;
|
|
31
|
+
/** Stable identity assigned by enrollment. */
|
|
32
|
+
rackId = '';
|
|
33
|
+
/** Boot identity reported in every poll and heartbeat. */
|
|
34
|
+
bootId = randomUUID();
|
|
35
|
+
/** Runs against a separate repository, like the guest's staged store. */
|
|
36
|
+
repo;
|
|
37
|
+
/** Consumes deterministic faults before executing each claim. */
|
|
38
|
+
faults;
|
|
39
|
+
storage = new LocalStorage();
|
|
40
|
+
token = '';
|
|
41
|
+
abort = new AbortController();
|
|
42
|
+
transport;
|
|
43
|
+
tiers;
|
|
44
|
+
version;
|
|
45
|
+
capacity;
|
|
46
|
+
active = new Map();
|
|
47
|
+
loop;
|
|
48
|
+
loopError;
|
|
49
|
+
temporaryHome;
|
|
50
|
+
/** Creates an unenrolled peer; enroll before starting its claim loop.
|
|
51
|
+
* @param options - Transport, scratch directory, capacity and deterministic faults.
|
|
52
|
+
*/
|
|
53
|
+
constructor(options) {
|
|
54
|
+
this.options = options;
|
|
55
|
+
this.repo = join(options.workDir, 'repo');
|
|
56
|
+
this.transport = options.fetch ?? (options.certificateSha256 === undefined ? fetch : pinnedFetch(options.certificateSha256));
|
|
57
|
+
this.tiers = options.tiers ?? ['node'];
|
|
58
|
+
this.version = options.agentVersion ?? `0.5.0+e3.${E3_RACK_VERSION}`;
|
|
59
|
+
this.capacity = options.capacity ?? 1;
|
|
60
|
+
if (!Number.isSafeInteger(this.capacity) || this.capacity < 1)
|
|
61
|
+
throw new Error('Test rack capacity must be a positive integer');
|
|
62
|
+
for (const ms of [options.timings?.heartbeatMs ?? 15000, options.timings?.extendMs ?? 20000]) {
|
|
63
|
+
if (!Number.isFinite(ms) || ms <= 0)
|
|
64
|
+
throw new Error('Test rack intervals must be positive');
|
|
65
|
+
}
|
|
66
|
+
this.faults = options.faults ?? {};
|
|
67
|
+
}
|
|
68
|
+
/** Enrolls one protocol peer with an automatically cleaned temporary store. */
|
|
69
|
+
static async enroll(origin, enrollmentToken, options = {}) {
|
|
70
|
+
const home = await mkdtemp(join(tmpdir(), 'e3a-'));
|
|
71
|
+
const agent = new TestRackAgent({ ...options, apiUrl: origin, workDir: home, agentVersion: options.version });
|
|
72
|
+
agent.temporaryHome = home;
|
|
73
|
+
try {
|
|
74
|
+
await agent.enroll(enrollmentToken);
|
|
75
|
+
return agent;
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
await rm(home, { recursive: true, force: true });
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Consumes a single-use token and publishes this boot's health.
|
|
83
|
+
* @param enrollmentToken - Token minted by the control plane.
|
|
84
|
+
*/
|
|
85
|
+
async enroll(enrollmentToken) {
|
|
86
|
+
if (this.token)
|
|
87
|
+
throw new Error('Test rack is already enrolled');
|
|
88
|
+
if (!repoInit(this.repo).success)
|
|
89
|
+
throw new Error('Could not initialize test rack repository');
|
|
90
|
+
const enrolled = await this.post('enroll', RackEnrollRequestType, { enrollmentToken,
|
|
91
|
+
hostInfo: { label: this.options.label ?? 'test rack', tiers: this.tiers, capacity: BigInt(this.capacity), agentVersion: this.version } }, RackEnrollResponseType);
|
|
92
|
+
this.rackId = enrolled.rackId;
|
|
93
|
+
this.token = enrolled.rackToken;
|
|
94
|
+
await this.heartbeat();
|
|
95
|
+
}
|
|
96
|
+
/** Starts long-polling while slots are free; stop drains all active runners. */
|
|
97
|
+
start() {
|
|
98
|
+
if (!this.token || this.abort.signal.aborted)
|
|
99
|
+
throw new Error('Test rack must be enrolled and not stopped');
|
|
100
|
+
if (this.loop)
|
|
101
|
+
return;
|
|
102
|
+
this.loop = this.poll().catch((error) => { if (!this.abort.signal.aborted)
|
|
103
|
+
this.loopError = error; this.abort.abort(); });
|
|
104
|
+
}
|
|
105
|
+
async poll() {
|
|
106
|
+
const heartbeat = setInterval(() => { void this.heartbeat().catch(() => this.abort.abort()); }, this.options.timings?.heartbeatMs ?? 15000);
|
|
107
|
+
try {
|
|
108
|
+
while (!this.abort.signal.aborted) {
|
|
109
|
+
if (this.active.size >= this.capacity) {
|
|
110
|
+
await Promise.race([...this.active.values()].map((value) => value.done));
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const lease = await this.claim();
|
|
114
|
+
if (lease)
|
|
115
|
+
void this.execute(lease).catch((error) => {
|
|
116
|
+
if (!this.abort.signal.aborted)
|
|
117
|
+
this.loopError = error;
|
|
118
|
+
this.abort.abort();
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
clearInterval(heartbeat);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Posts a typed agent request with a finite transport deadline. */
|
|
127
|
+
async raw(path, type, value) {
|
|
128
|
+
return this.transport(`${this.options.apiUrl}/api/rack/${path}`, { method: 'POST',
|
|
129
|
+
headers: { 'content-type': BEAST2_CONTENT_TYPE, ...(this.token ? { authorization: `Bearer ${this.token}` } : {}) },
|
|
130
|
+
body: encodeBeast2For(type)(value), signal: AbortSignal.any([this.abort.signal, AbortSignal.timeout(25000)]) });
|
|
131
|
+
}
|
|
132
|
+
/** Decodes one standard response, raising its typed error. */
|
|
133
|
+
async post(path, type, value, responseType) {
|
|
134
|
+
const response = await this.raw(path, type, value);
|
|
135
|
+
if (response.status !== 200)
|
|
136
|
+
throw new Error(`Rack ${path}: HTTP ${response.status}`);
|
|
137
|
+
const envelope = decodeBeast2For(ResponseType(responseType))(new Uint8Array(await response.arrayBuffer()));
|
|
138
|
+
if (envelope.type === 'error')
|
|
139
|
+
throw new Error(printFor(ErrorType)(envelope.value));
|
|
140
|
+
return envelope.value;
|
|
141
|
+
}
|
|
142
|
+
/** Reports health and returns the leases the hub asks this agent to stop. */
|
|
143
|
+
async heartbeat(runningLeases = [...this.active.values()].filter((value) => !value.silent).map((value) => value.lease)) {
|
|
144
|
+
const response = await this.post('heartbeat', RackHeartbeatRequestType, { healthy: true, freeCapacity: BigInt(Math.max(0, this.capacity - Math.max(this.active.size, runningLeases.length))),
|
|
145
|
+
runningLeases, agentVersion: this.version, bootId: this.bootId, cacheBytes: 0n }, RackHeartbeatResponseType);
|
|
146
|
+
if (response.rotatedToken.type === 'some')
|
|
147
|
+
this.token = response.rotatedToken.value;
|
|
148
|
+
for (const lease of response.stop)
|
|
149
|
+
this.active.get(lease.leaseId)?.stop.abort();
|
|
150
|
+
return response;
|
|
151
|
+
}
|
|
152
|
+
/** Claims a lease, or answers null after an idle poll window. */
|
|
153
|
+
async claim() {
|
|
154
|
+
if (this.faults.claimDelayMs)
|
|
155
|
+
await delay(this.faults.claimDelayMs, undefined, { signal: this.abort.signal });
|
|
156
|
+
const response = await this.raw('lease', RackLeaseRequestType, { tiers: this.tiers, bootId: this.bootId });
|
|
157
|
+
if (response.status === 204)
|
|
158
|
+
return null;
|
|
159
|
+
if (response.status !== 200)
|
|
160
|
+
throw new Error(`Rack claim: HTTP ${response.status}`);
|
|
161
|
+
const envelope = decodeBeast2For(ResponseType(RackLeaseGrantType))(new Uint8Array(await response.arrayBuffer()));
|
|
162
|
+
if (envelope.type === 'error')
|
|
163
|
+
throw new Error(printFor(ErrorType)(envelope.value));
|
|
164
|
+
return envelope.value;
|
|
165
|
+
}
|
|
166
|
+
/** Resolves storage descriptors and write receipts for a held lease. */
|
|
167
|
+
storageRequest(lease, request = {}) {
|
|
168
|
+
return this.post('storage', RackStorageRequestType, { repo: lease.repo, leaseId: lease.leaseId,
|
|
169
|
+
need: [], output: none, envManifest: none, outputs: [], commits: [], ...request }, RackStorageResponseType);
|
|
170
|
+
}
|
|
171
|
+
/** Streams an ordered log batch through the rack endpoint. */
|
|
172
|
+
logs(lease, chunks) {
|
|
173
|
+
return this.post('logs', RackLogsRequestType, { repo: lease.repo, leaseId: lease.leaseId, chunks }, BooleanType);
|
|
174
|
+
}
|
|
175
|
+
/** Posts an outcome without hiding accepted-and-discarded semantics. */
|
|
176
|
+
complete(lease, result) {
|
|
177
|
+
return this.post('complete', RackCompleteRequestType, { repo: lease.repo, leaseId: lease.leaseId,
|
|
178
|
+
resultJson: JSON.stringify(result), inlineOutput: none, outputUploadId: none }, RackCompleteResponseType);
|
|
179
|
+
}
|
|
180
|
+
/** Fetches a closure through inline descriptors or capability URLs. */
|
|
181
|
+
async fetchObjects(lease, hashes) {
|
|
182
|
+
for (let from = 0; from < hashes.length; from += 256) {
|
|
183
|
+
const need = [];
|
|
184
|
+
for (const hash of hashes.slice(from, from + 256))
|
|
185
|
+
if (!await this.storage.objects.exists(this.repo, hash))
|
|
186
|
+
need.push(hash);
|
|
187
|
+
if (need.length === 0)
|
|
188
|
+
continue;
|
|
189
|
+
const response = await this.storageRequest(lease, { need });
|
|
190
|
+
for (const object of response.objects) {
|
|
191
|
+
const bytes = object.type === 'inline' ? object.value.data : await (async () => {
|
|
192
|
+
const response = await this.transport(object.value.url, { signal: AbortSignal.any([this.abort.signal, AbortSignal.timeout(30000)]) });
|
|
193
|
+
if (!response.ok)
|
|
194
|
+
throw new Error(`Rack input GET: HTTP ${response.status}`);
|
|
195
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
196
|
+
})();
|
|
197
|
+
if (await this.storage.objects.write(this.repo, bytes) !== object.value.hash)
|
|
198
|
+
throw new Error('Rack input checksum mismatch');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Executes one claimed task/unit with the production core over the fetched closure. */
|
|
203
|
+
execute(lease) {
|
|
204
|
+
if (this.active.has(lease.leaseId))
|
|
205
|
+
throw new Error('Test rack lease is already executing');
|
|
206
|
+
const stop = new AbortController();
|
|
207
|
+
const done = this.executeClaim(lease, stop).finally(() => { this.active.delete(lease.leaseId); });
|
|
208
|
+
this.active.set(lease.leaseId, { lease, stop, done, silent: false });
|
|
209
|
+
return done;
|
|
210
|
+
}
|
|
211
|
+
consume(fault) {
|
|
212
|
+
const count = this.faults[fault] ?? 0;
|
|
213
|
+
if (count <= 0)
|
|
214
|
+
return false;
|
|
215
|
+
this.faults[fault] = count - 1;
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
async executeClaim(lease, stop) {
|
|
219
|
+
// Let execute register the active slot before starting callbacks or faults.
|
|
220
|
+
await Promise.resolve();
|
|
221
|
+
const event = JSON.parse(lease.eventJson);
|
|
222
|
+
const signal = AbortSignal.any([stop.signal, this.abort.signal]);
|
|
223
|
+
if (this.consume('hangNext')) {
|
|
224
|
+
this.active.get(lease.leaseId).silent = true;
|
|
225
|
+
await delay(2147483647, undefined, { signal }).catch(() => { });
|
|
226
|
+
return { taskName: event.taskName, status: 'failed', state: 'error', cancelled: true, error: 'Test rack stopped a silent claim' };
|
|
227
|
+
}
|
|
228
|
+
const infra = this.consume('infraFailNext');
|
|
229
|
+
if (infra || this.consume('taskFailNext')) {
|
|
230
|
+
const result = { taskName: event.taskName, status: 'failed', state: infra ? 'error' : 'failed',
|
|
231
|
+
...(infra ? {} : { exitCode: 1 }), error: infra ? 'Injected infrastructure failure' : 'Injected task failure' };
|
|
232
|
+
await this.complete(lease, result);
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
const run = decodeRunnerEvent(event.runnerEvent);
|
|
236
|
+
if (run.mode !== 'task' && run.mode !== 'unit')
|
|
237
|
+
throw new Error('Test agent runs tasks and units');
|
|
238
|
+
const heartbeat = setInterval(() => {
|
|
239
|
+
void this.heartbeat().catch(() => stop.abort());
|
|
240
|
+
}, this.options.timings?.heartbeatMs ?? 15000);
|
|
241
|
+
const extend = setInterval(() => {
|
|
242
|
+
void this.post('lease/extend', RackExtendRequestType, { repo: lease.repo, leaseId: lease.leaseId }, BooleanType).then((held) => { if (!held)
|
|
243
|
+
stop.abort(); }).catch(() => stop.abort());
|
|
244
|
+
}, this.options.timings?.extendMs ?? 20000);
|
|
245
|
+
heartbeat.unref();
|
|
246
|
+
extend.unref();
|
|
247
|
+
const chunks = [];
|
|
248
|
+
try {
|
|
249
|
+
if ('object' in event.closure)
|
|
250
|
+
await this.fetchObjects(lease, [event.closure.object]);
|
|
251
|
+
await this.fetchObjects(lease, await closureHashes(event.closure, (hash) => this.storage.objects.read(this.repo, hash)));
|
|
252
|
+
const options = { force: true, signal, timeout: run.timeoutMs, verbose: run.verbose,
|
|
253
|
+
onStdout: (data) => { chunks.push({ stream: variant('stdout', null), data }); },
|
|
254
|
+
onStderr: (data) => { chunks.push({ stream: variant('stderr', null), data }); } };
|
|
255
|
+
const result = run.mode === 'task'
|
|
256
|
+
? await taskExecute(this.storage, this.repo, run.taskHash, [...run.inputHashes], options)
|
|
257
|
+
: await taskExecuteUnit(this.storage, this.repo, run.taskHash, splitUnitFromWire(run.unit), options);
|
|
258
|
+
if (chunks.length > 0)
|
|
259
|
+
await this.logs(lease, chunks);
|
|
260
|
+
if (result.state === 'success' && result.outputHash !== null) {
|
|
261
|
+
const readers = gcObjectReaders(this.storage, this.repo);
|
|
262
|
+
const hashes = [...await markReachable(readers.readObject, new Set([result.outputHash]), { readHead: readers.readHead })];
|
|
263
|
+
for (const hash of hashes) {
|
|
264
|
+
const bytes = await this.storage.objects.read(this.repo, hash);
|
|
265
|
+
const size = BigInt(bytes.length);
|
|
266
|
+
const targets = await this.storageRequest(lease, { outputs: [{ hash, size }] });
|
|
267
|
+
const target = targets.targets[0].target;
|
|
268
|
+
if (target.type === 'held')
|
|
269
|
+
continue;
|
|
270
|
+
const put = await this.transport(target.value.url, { method: 'PUT', headers: Object.fromEntries(target.value.headers), body: bytes,
|
|
271
|
+
signal: AbortSignal.any([signal, AbortSignal.timeout(30000)]) });
|
|
272
|
+
if (!put.ok)
|
|
273
|
+
throw new Error(`Rack output PUT: HTTP ${put.status}`);
|
|
274
|
+
const version = put.headers.get('x-amz-version-id');
|
|
275
|
+
await put.arrayBuffer();
|
|
276
|
+
if (version === null)
|
|
277
|
+
throw new Error('Rack upload has no receipt');
|
|
278
|
+
const commit = { hash, size, version };
|
|
279
|
+
if (!(await this.storageRequest(lease, { commits: [commit] })).committed[0]?.committed)
|
|
280
|
+
throw new Error('Rack output commit refused');
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const output = { taskName: event.taskName, status: result.state === 'success' ? 'success' : 'failed',
|
|
284
|
+
state: result.state, ...(result.outputHash === null ? {} : { outputHash: result.outputHash }),
|
|
285
|
+
...(result.exitCode == null ? {} : { exitCode: result.exitCode }), ...(result.error == null ? {} : { error: result.error }),
|
|
286
|
+
...(result.peakBytes === undefined ? {} : { peakBytes: result.peakBytes }), cancelled: signal.aborted };
|
|
287
|
+
if (!this.consume('dropCompletionNext') && !this.abort.signal.aborted)
|
|
288
|
+
await this.complete(lease, output);
|
|
289
|
+
return output;
|
|
290
|
+
}
|
|
291
|
+
finally {
|
|
292
|
+
clearInterval(heartbeat);
|
|
293
|
+
clearInterval(extend);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/** Claims and executes the next task. */
|
|
297
|
+
async runOne() { const lease = await this.claim(); return lease === null ? null : this.execute(lease); }
|
|
298
|
+
/** Aborts requests and removes the isolated guest store. */
|
|
299
|
+
async close() {
|
|
300
|
+
try {
|
|
301
|
+
await this.stop();
|
|
302
|
+
}
|
|
303
|
+
finally {
|
|
304
|
+
await rm(this.temporaryHome ?? this.repo, { recursive: true, force: true });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/** Stops polling, aborts active executions and waits for runner cleanup. */
|
|
308
|
+
async stop() {
|
|
309
|
+
this.abort.abort();
|
|
310
|
+
await this.loop;
|
|
311
|
+
await Promise.allSettled([...this.active.values()].map((value) => value.done));
|
|
312
|
+
if (this.loopError)
|
|
313
|
+
throw this.loopError;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=test-rack-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-rack-agent.js","sourceRoot":"","sources":["../../../src/testing/test-rack-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { Agent } from 'node:https';
|
|
6
|
+
/** A hub's self-signed certificate and its private key, both PEM. */
|
|
7
|
+
export interface HubCertificate {
|
|
8
|
+
/** The X.509 certificate a rack pins by its SHA-256 fingerprint. */
|
|
9
|
+
certificatePem: string;
|
|
10
|
+
/** The PKCS#8 private key; it never leaves the hub's private state. */
|
|
11
|
+
privateKeyPem: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a hub's self-signed ECDSA P-256 certificate, valid from an hour ago
|
|
15
|
+
* (a rack's clock may lag) for ten years, naming `e3-rack-hub` only.
|
|
16
|
+
* @param now - The issue time
|
|
17
|
+
* @returns The certificate and its private key
|
|
18
|
+
* @example
|
|
19
|
+
* const { certificatePem, privateKeyPem } = createHubCertificate();
|
|
20
|
+
*/
|
|
21
|
+
export declare function createHubCertificate(now?: Date): HubCertificate;
|
|
22
|
+
/**
|
|
23
|
+
* The SHA-256 fingerprint a rack pins: uppercase hex pairs joined by colons,
|
|
24
|
+
* as `openssl x509 -fingerprint -sha256` prints it.
|
|
25
|
+
* @param certificatePem - A PEM certificate
|
|
26
|
+
* @returns Its fingerprint
|
|
27
|
+
* @example
|
|
28
|
+
* console.log(certificateSha256(certificatePem)); // 'AB:CD:…'
|
|
29
|
+
*/
|
|
30
|
+
export declare function certificateSha256(certificatePem: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Reads a pinned fingerprint as an operator writes it: 64 hex digits, with or
|
|
33
|
+
* without colons, in either case.
|
|
34
|
+
* @param text - The fingerprint
|
|
35
|
+
* @returns It in {@link certificateSha256}'s form
|
|
36
|
+
* @throws {Error} When it is not a SHA-256 fingerprint
|
|
37
|
+
* @example
|
|
38
|
+
* parseCertificateSha256('abcd…'); // 'AB:CD:…'
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseCertificateSha256(text: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Makes an HTTPS agent that trusts exactly the certificate whose SHA-256 is
|
|
43
|
+
* pinned. A first handshake, which sends nothing, reads the certificate the
|
|
44
|
+
* origin presents; it is refused unless its fingerprint is the pin. Every
|
|
45
|
+
* request then verifies the server against that certificate alone, and its
|
|
46
|
+
* fingerprint again, so a different certificate is refused before any
|
|
47
|
+
* request or credential is written.
|
|
48
|
+
* @param origin - An https:// origin
|
|
49
|
+
* @param certificateSha256 - The pinned fingerprint
|
|
50
|
+
* @param timeoutMs - The first handshake's deadline
|
|
51
|
+
* @returns The agent
|
|
52
|
+
* @throws {Error} When the origin is not HTTPS or presents another certificate
|
|
53
|
+
* @example
|
|
54
|
+
* const agent = await pinnedHttpsAgent('https://10.0.0.2:7331', pin);
|
|
55
|
+
*/
|
|
56
|
+
export declare function pinnedHttpsAgent(origin: string, certificateSha256: string, timeoutMs?: number): Promise<Agent>;
|
|
57
|
+
/**
|
|
58
|
+
* A fetch that reaches HTTPS origins only through {@link pinnedHttpsAgent},
|
|
59
|
+
* one agent per origin; any other scheme is refused.
|
|
60
|
+
* @param certificateSha256 - The pinned fingerprint
|
|
61
|
+
* @returns A fetch-compatible function
|
|
62
|
+
* @throws {Error} When the fingerprint is malformed
|
|
63
|
+
* @example
|
|
64
|
+
* const response = await pinnedFetch(pin)('https://10.0.0.2:7331/api/rack/heartbeat', { method: 'POST', body });
|
|
65
|
+
*/
|
|
66
|
+
export declare function pinnedFetch(certificateSha256: string): typeof fetch;
|
|
67
|
+
//# sourceMappingURL=tls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tls.d.ts","sourceRoot":"","sources":["../../../src/tls/tls.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAW,MAAM,YAAY,CAAC;AAW5C,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;CACvB;AAqCD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,OAAa,GAAG,cAAc,CAiBrE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI3D;AAgBD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAUpH;AAMD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,KAAK,CAwCnE"}
|