@namzu/sandbox 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +474 -0
  2. package/LICENSE.md +110 -0
  3. package/README.md +148 -0
  4. package/dist/backends/aci-standby-pool/index.d.ts +104 -0
  5. package/dist/backends/aci-standby-pool/index.d.ts.map +1 -0
  6. package/dist/backends/aci-standby-pool/index.js +425 -0
  7. package/dist/backends/aci-standby-pool/index.js.map +1 -0
  8. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts +40 -0
  9. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.d.ts.map +1 -0
  10. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js +157 -0
  11. package/dist/backends/docker/__tests__/leaf-permissions.smoke.test.js.map +1 -0
  12. package/dist/backends/docker/index.d.ts +118 -0
  13. package/dist/backends/docker/index.d.ts.map +1 -0
  14. package/dist/backends/docker/index.js +645 -0
  15. package/dist/backends/docker/index.js.map +1 -0
  16. package/dist/backends/firecracker/__tests__/backend.test.d.ts +13 -0
  17. package/dist/backends/firecracker/__tests__/backend.test.d.ts.map +1 -0
  18. package/dist/backends/firecracker/__tests__/backend.test.js +353 -0
  19. package/dist/backends/firecracker/__tests__/backend.test.js.map +1 -0
  20. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts +19 -0
  21. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.d.ts.map +1 -0
  22. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js +201 -0
  23. package/dist/backends/firecracker/__tests__/control-plane-mtls.test.js.map +1 -0
  24. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts +39 -0
  25. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.d.ts.map +1 -0
  26. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js +149 -0
  27. package/dist/backends/firecracker/__tests__/fixtures/mtls-pki.js.map +1 -0
  28. package/dist/backends/firecracker/__tests__/protocol.test.d.ts +6 -0
  29. package/dist/backends/firecracker/__tests__/protocol.test.d.ts.map +1 -0
  30. package/dist/backends/firecracker/__tests__/protocol.test.js +77 -0
  31. package/dist/backends/firecracker/__tests__/protocol.test.js.map +1 -0
  32. package/dist/backends/firecracker/__tests__/transport.test.d.ts +20 -0
  33. package/dist/backends/firecracker/__tests__/transport.test.d.ts.map +1 -0
  34. package/dist/backends/firecracker/__tests__/transport.test.js +449 -0
  35. package/dist/backends/firecracker/__tests__/transport.test.js.map +1 -0
  36. package/dist/backends/firecracker/index.d.ts +124 -0
  37. package/dist/backends/firecracker/index.d.ts.map +1 -0
  38. package/dist/backends/firecracker/index.js +334 -0
  39. package/dist/backends/firecracker/index.js.map +1 -0
  40. package/dist/backends/firecracker/protocol.d.ts +132 -0
  41. package/dist/backends/firecracker/protocol.d.ts.map +1 -0
  42. package/dist/backends/firecracker/protocol.js +112 -0
  43. package/dist/backends/firecracker/protocol.js.map +1 -0
  44. package/dist/backends/firecracker/transport.d.ts +251 -0
  45. package/dist/backends/firecracker/transport.d.ts.map +1 -0
  46. package/dist/backends/firecracker/transport.js +524 -0
  47. package/dist/backends/firecracker/transport.js.map +1 -0
  48. package/dist/index.d.ts +611 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +376 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/index.test.d.ts +28 -0
  53. package/dist/index.test.d.ts.map +1 -0
  54. package/dist/index.test.js +670 -0
  55. package/dist/index.test.js.map +1 -0
  56. package/package.json +54 -0
  57. package/src/backends/aci-standby-pool/index.ts +602 -0
  58. package/src/backends/docker/__tests__/leaf-permissions.smoke.test.ts +169 -0
  59. package/src/backends/docker/index.ts +826 -0
  60. package/src/backends/firecracker/__tests__/backend.test.ts +418 -0
  61. package/src/backends/firecracker/__tests__/control-plane-mtls.test.ts +253 -0
  62. package/src/backends/firecracker/__tests__/fixtures/mtls-pki.ts +166 -0
  63. package/src/backends/firecracker/__tests__/protocol.test.ts +90 -0
  64. package/src/backends/firecracker/__tests__/transport.test.ts +526 -0
  65. package/src/backends/firecracker/index.ts +528 -0
  66. package/src/backends/firecracker/protocol.ts +191 -0
  67. package/src/backends/firecracker/transport.ts +667 -0
  68. package/src/index.test.ts +731 -0
  69. package/src/index.ts +930 -0
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Control-plane mTLS dial for the Firecracker backend (additive
3
+ * `config.controlPlaneMtls`).
4
+ *
5
+ * A loopback `https.createServer` with `requestCert + rejectUnauthorized`
6
+ * (pinned to the test CA) stands in for the orchestrator over the public hop.
7
+ * It serves the real `POST /sandboxes` + `:delete` routes; the create response
8
+ * points the agent handle at a unix-socket loopback running the REAL
9
+ * `agent/agent.cjs`, so the FULL create flow (control-plane POST over mTLS →
10
+ * vsock readiness fence → exec) runs end to end.
11
+ *
12
+ * Proves:
13
+ * - with `controlPlaneMtls` injected, the create POST succeeds over mTLS and
14
+ * the sandbox round-trips an exec.
15
+ * - WITHOUT the client cert (no `controlPlaneMtls`, so the backend uses plain
16
+ * `fetch` against the https listener), create is rejected at the TLS layer.
17
+ */
18
+ import { mkdtempSync, rmSync } from 'node:fs';
19
+ import { createServer as createHttpsServer, request as httpsRequest, } from 'node:https';
20
+ import { createRequire } from 'node:module';
21
+ import { createServer } from 'node:net';
22
+ import { tmpdir } from 'node:os';
23
+ import { join } from 'node:path';
24
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
25
+ import { buildFirecrackerBackend } from '../index.js';
26
+ import { CA_CRT, CLIENT_CRT, CLIENT_KEY, ROGUE_CLIENT_CRT, ROGUE_CLIENT_KEY, SERVER_CRT, SERVER_KEY, } from './fixtures/mtls-pki.js';
27
+ const require_ = createRequire(import.meta.url);
28
+ let workDir;
29
+ let sockPath;
30
+ let agentServer;
31
+ let orchestrator;
32
+ let agent;
33
+ beforeEach(() => {
34
+ workDir = mkdtempSync(join(tmpdir(), 'fc-cp-mtls-'));
35
+ sockPath = join(workDir, 'agent.sock');
36
+ process.env.NAMZU_SANDBOX_WORKSPACE = workDir;
37
+ delete require_.cache[require_.resolve('../../../../agent/agent.cjs')];
38
+ agent = require_('../../../../agent/agent.cjs');
39
+ });
40
+ afterEach(async () => {
41
+ if (orchestrator) {
42
+ await new Promise((r) => orchestrator?.close(() => r()));
43
+ orchestrator = undefined;
44
+ }
45
+ if (agentServer) {
46
+ await new Promise((r) => agentServer?.close(() => r()));
47
+ agentServer = undefined;
48
+ }
49
+ rmSync(workDir, { recursive: true, force: true });
50
+ });
51
+ function startAgent() {
52
+ return new Promise((resolve, reject) => {
53
+ const s = createServer(agent.handleConnection);
54
+ s.on('error', reject);
55
+ s.listen(sockPath, () => resolve(s));
56
+ });
57
+ }
58
+ /**
59
+ * A loopback mTLS orchestrator. Requires + verifies a client cert chaining to
60
+ * the test CA, then serves the control-plane routes: `POST /sandboxes` returns
61
+ * a unix agent handle, `:delete` returns 204. Records calls so the test can
62
+ * assert the create round-trip.
63
+ */
64
+ function startMtlsOrchestrator(handlePath) {
65
+ const calls = [];
66
+ return new Promise((resolve, reject) => {
67
+ const server = createHttpsServer({
68
+ cert: SERVER_CRT,
69
+ key: SERVER_KEY,
70
+ ca: CA_CRT,
71
+ requestCert: true,
72
+ rejectUnauthorized: true,
73
+ minVersion: 'TLSv1.3',
74
+ }, (req, res) => {
75
+ const method = req.method ?? 'GET';
76
+ const url = req.url ?? '/';
77
+ calls.push({ method, url });
78
+ // Drain the body, then respond per route.
79
+ req.on('data', () => { });
80
+ req.on('end', () => {
81
+ if (method === 'POST' && url.endsWith('/sandboxes')) {
82
+ res.statusCode = 200;
83
+ res.setHeader('content-type', 'application/json');
84
+ res.end(JSON.stringify({
85
+ sandboxId: 'sbx_cp_mtls',
86
+ agent: { kind: 'unix', path: handlePath },
87
+ rootDir: workDir,
88
+ }));
89
+ return;
90
+ }
91
+ if (method === 'DELETE' && url.includes(':delete')) {
92
+ res.statusCode = 204;
93
+ res.end();
94
+ return;
95
+ }
96
+ res.statusCode = 500;
97
+ res.end('unexpected');
98
+ });
99
+ });
100
+ server.on('error', reject);
101
+ server.listen(0, '127.0.0.1', () => {
102
+ const addr = server.address();
103
+ if (addr === null || typeof addr === 'string') {
104
+ reject(new Error('orchestrator: no TCP port'));
105
+ return;
106
+ }
107
+ resolve({ server, port: addr.port, calls });
108
+ });
109
+ });
110
+ }
111
+ describe('buildFirecrackerBackend (control-plane mTLS dial)', () => {
112
+ it('create POST succeeds over mTLS and round-trips an exec', async () => {
113
+ agentServer = await startAgent();
114
+ const orch = await startMtlsOrchestrator(sockPath);
115
+ orchestrator = orch.server;
116
+ const backend = buildFirecrackerBackend({
117
+ // An https:// endpoint over the (loopback stand-in for the) public hop.
118
+ orchestratorEndpoint: `https://127.0.0.1:${orch.port}/`,
119
+ getToken: async () => 'tok',
120
+ readyTimeoutMs: 5_000,
121
+ readyPollIntervalMs: 50,
122
+ // CONTROL-plane client material — injected by the consumer, never
123
+ // shipped by the orchestrator. Drives the node:https mTLS dial.
124
+ controlPlaneMtls: {
125
+ ca: CA_CRT,
126
+ cert: CLIENT_CRT,
127
+ key: CLIENT_KEY,
128
+ servername: 'sandbox.fc.internal',
129
+ },
130
+ });
131
+ const sandbox = await backend.create({ workingDirectory: workDir });
132
+ expect(sandbox.id).toBe('sbx_cp_mtls');
133
+ expect(sandbox.status).toBe('ready');
134
+ // The control-plane POST reached the mTLS orchestrator.
135
+ expect(orch.calls.some((c) => c.method === 'POST' && c.url.endsWith('/sandboxes'))).toBe(true);
136
+ // Exec over the vsock tunnel (the data plane), proving the whole flow.
137
+ const r = await sandbox.exec('/bin/sh', ['-c', 'echo hello-cp-mtls']);
138
+ expect(r.stdout).toContain('hello-cp-mtls');
139
+ // destroy DELETE also rides the mTLS control plane.
140
+ await sandbox.destroy();
141
+ expect(orch.calls.some((c) => c.method === 'DELETE' && c.url.includes(':delete'))).toBe(true);
142
+ });
143
+ it('the backend without controlPlaneMtls cannot reach the mTLS orchestrator (plain fetch fails the handshake)', async () => {
144
+ agentServer = await startAgent();
145
+ const orch = await startMtlsOrchestrator(sockPath);
146
+ orchestrator = orch.server;
147
+ // No `controlPlaneMtls` → the backend uses plain `fetch`, which neither
148
+ // presents a client cert nor trusts the test CA, so the TLS handshake
149
+ // fails and create rejects BEFORE any route runs.
150
+ const backend = buildFirecrackerBackend({
151
+ orchestratorEndpoint: `https://127.0.0.1:${orch.port}/`,
152
+ getToken: async () => 'tok',
153
+ readyTimeoutMs: 2_000,
154
+ readyPollIntervalMs: 50,
155
+ });
156
+ await expect(backend.create({ workingDirectory: workDir })).rejects.toThrow(/failed to create microVM sandbox/);
157
+ expect(orch.calls.some((c) => c.method === 'POST' && c.url.endsWith('/sandboxes'))).toBe(false);
158
+ });
159
+ it("the orchestrator's requestCert rejects a client presenting NO cert (server-side proof)", async () => {
160
+ // Isolate the SERVER's requestCert+rejectUnauthorized from any client-side
161
+ // CA distrust: dial directly with node:https TRUSTING the server CA but
162
+ // presenting NO client cert. The handshake must be rejected by the server.
163
+ const orch = await startMtlsOrchestrator(sockPath);
164
+ orchestrator = orch.server;
165
+ const err = await new Promise((resolve) => {
166
+ const req = httpsRequest({
167
+ host: '127.0.0.1',
168
+ port: orch.port,
169
+ method: 'POST',
170
+ path: '/sandboxes',
171
+ ca: CA_CRT,
172
+ servername: 'sandbox.fc.internal',
173
+ }, () => resolve(undefined));
174
+ req.on('error', (e) => resolve(e));
175
+ req.end();
176
+ });
177
+ expect(err).toBeInstanceOf(Error);
178
+ expect(orch.calls.some((c) => c.method === 'POST')).toBe(false);
179
+ });
180
+ it("the orchestrator's requestCert rejects a client cert from a DIFFERENT CA", async () => {
181
+ const orch = await startMtlsOrchestrator(sockPath);
182
+ orchestrator = orch.server;
183
+ const err = await new Promise((resolve) => {
184
+ const req = httpsRequest({
185
+ host: '127.0.0.1',
186
+ port: orch.port,
187
+ method: 'POST',
188
+ path: '/sandboxes',
189
+ ca: CA_CRT,
190
+ cert: ROGUE_CLIENT_CRT,
191
+ key: ROGUE_CLIENT_KEY,
192
+ servername: 'sandbox.fc.internal',
193
+ }, () => resolve(undefined));
194
+ req.on('error', (e) => resolve(e));
195
+ req.end();
196
+ });
197
+ expect(err).toBeInstanceOf(Error);
198
+ expect(orch.calls.some((c) => c.method === 'POST')).toBe(false);
199
+ });
200
+ });
201
+ //# sourceMappingURL=control-plane-mtls.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-plane-mtls.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/control-plane-mtls.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Shared Ring-0 mTLS test PKI + a loopback relay stand-in.
3
+ *
4
+ * A throwaway P-256 test PKI (CA + server leaf + client leaf + an unrelated
5
+ * rogue client) baked in as PEM constants — no openssl/forge at test time, so
6
+ * the package stays dependency-light. Minted offline:
7
+ * openssl ec/x509 self-signed CA + leaves
8
+ * (server SAN = DNS:sandbox.fc.internal, IP:127.0.0.1), far-future expiry.
9
+ * `ROGUE_*` chains to a DIFFERENT CA to prove `rejectUnauthorized` blocks it.
10
+ *
11
+ * Used by both transport.test.ts (the raw `kind:'mtls'` dialer arm) and
12
+ * backend.test.ts (the cert-INJECTION seam through `buildFirecrackerBackend`),
13
+ * so the PKI + relay harness lives in one place instead of per-test copies.
14
+ */
15
+ import { type Server as TlsServer } from 'node:tls';
16
+ export declare const CA_CRT = "-----BEGIN CERTIFICATE-----\nMIIBjjCCATWgAwIBAgIUGXUtG14KQr4spNGW7rpfjZGoBIIwCgYIKoZIzj0EAwIw\nHDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP\nMjEyNjA1MjMwODMyNTJaMBwxGjAYBgNVBAMMEXZhbmRhbC1mYy10ZXN0LWNhMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5l+vjhjm/PX02D55n56EwelgvM1jrqQM\nZ+ezzvMmrZEBGWInvBND3z3kc6nv7snu6fHT2HHOyhwUNoLqmrIg/qNTMFEwHQYD\nVR0OBBYEFP0M8/KZY1ovxyGDci5iuoYXcmZgMB8GA1UdIwQYMBaAFP0M8/KZY1ov\nxyGDci5iuoYXcmZgMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIg\nC0xtFDASnwsOYT0GiZwzYWTOBfgmjDWK7ANXQQFNTh4CICVLQwq5eLy3424drEHk\n5Ol/FNKVZcGRjE96rB0mRUOp\n-----END CERTIFICATE-----\n";
17
+ export declare const SERVER_CRT = "-----BEGIN CERTIFICATE-----\nMIIBsDCCAVWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1MwCgYIKoZIzj0EAwIw\nHDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP\nMjEyNjA1MjMwODMyNTJaMBIxEDAOBgNVBAMMB2ZjLWhvc3QwWTATBgcqhkjOPQIB\nBggqhkjOPQMBBwNCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMBfmonVb7dUhM0ZWpo\nePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6o30wezAkBgNVHREEHTAbghNz\nYW5kYm94LmZjLmludGVybmFshwR/AAABMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0G\nA1UdDgQWBBRXHU1vlX7WvqzcbaNxRxV4f3gfDDAfBgNVHSMEGDAWgBT9DPPymWNa\nL8chg3IuYrqGF3JmYDAKBggqhkjOPQQDAgNJADBGAiEAlqzKqgBf5hxJqd26QwcY\nn3cvEKi4f2BSLe1Rfzr5oSoCIQD0izUOJXLNvmac9cMgV0HvkftBerDKFOcGeGTN\ng3Eunw==\n-----END CERTIFICATE-----\n";
18
+ export declare const SERVER_KEY = "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/ROnYXIkMKnipbLt\nJnFEwXAifgeOv9TGLcK2RojE7jmhRANCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMB\nfmonVb7dUhM0ZWpoePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6\n-----END PRIVATE KEY-----\n";
19
+ export declare const CLIENT_CRT = "-----BEGIN CERTIFICATE-----\nMIIBjjCCATWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1QwCgYIKoZIzj0EAwIw\nHDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP\nMjEyNjA1MjMwODMyNTJaMBgxFjAUBgNVBAMMDWNhLXZhbmRhbC1hcHAwWTATBgcq\nhkjOPQIBBggqhkjOPQMBBwNCAASlCMCwjtrQUicWcWsO29R5S7fzjMbbxXvDh8/K\nw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXko1cwVTATBgNVHSUE\nDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU2cxDCNrlVkk4ODs6ZPrkC6GzHjkwHwYD\nVR0jBBgwFoAU/Qzz8pljWi/HIYNyLmK6hhdyZmAwCgYIKoZIzj0EAwIDRwAwRAIg\nRghqArNm3bXnWnRi+jkEEJa8mRb2z0Wj4G7SIhtMurUCIBQSllVtICgZB9hvcM0D\nd24fcW4nlfvaZJMJ6dRC1Wle\n-----END CERTIFICATE-----\n";
20
+ export declare const CLIENT_KEY = "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaamj/ycrEuPqpiC2\nIhAYx/M5iN4t4P+B17V4GO54Nb2hRANCAASlCMCwjtrQUicWcWsO29R5S7fzjMbb\nxXvDh8/Kw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXk\n-----END PRIVATE KEY-----\n";
21
+ export declare const ROGUE_CLIENT_CRT = "-----BEGIN CERTIFICATE-----\nMIIBhjCCASugAwIBAgIUbAYOlW4PQGyXjjRsjCPy62EHUmIwCgYIKoZIzj0EAwIw\nEzERMA8GA1UEAwwIcm9ndWUtY2EwIBcNMjYwNjE2MDgzMjUyWhgPMjEyNjA1MjMw\nODMyNTJaMBcxFTATBgNVBAMMDHJvZ3VlLWNsaWVudDBZMBMGByqGSM49AgEGCCqG\nSM49AwEHA0IABOPSzdzQTQz3M5CDHLVPguvHd10ncaDV9t4zKUy/PCE+U7GTJwN2\nTtypGnmYEahbcl45j94hwu495P5VbR5ohb6jVzBVMBMGA1UdJQQMMAoGCCsGAQUF\nBwMCMB0GA1UdDgQWBBTf0woauniche3/ps77+Kd0dsbbSDAfBgNVHSMEGDAWgBSX\nYu0IJlPxi79Gyi5hR1IfS/sqyzAKBggqhkjOPQQDAgNJADBGAiEAxD4N4XWtaHPJ\nyaCOzQP0e5RRyNst3QrhH0NSMyPw89wCIQC+bezLX97TuV1sId53Bo1l9j1TSOMa\nEZotN/Wsq6L+qw==\n-----END CERTIFICATE-----\n";
22
+ export declare const ROGUE_CLIENT_KEY = "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR6fGq27O9eT/hi0Q\nc+L5+lSm5fbDEghVJCo6k7HrG62hRANCAATj0s3c0E0M9zOQgxy1T4Lrx3ddJ3Gg\n1fbeMylMvzwhPlOxkycDdk7cqRp5mBGoW3JeOY/eIcLuPeT+VW0eaIW+\n-----END PRIVATE KEY-----\n";
23
+ export interface RelayHandle {
24
+ readonly server: TlsServer;
25
+ readonly port: number;
26
+ /** sandboxId from the first connection's `SANDBOX <id>` preamble. */
27
+ preamble(): Promise<string>;
28
+ }
29
+ /**
30
+ * A loopback stand-in for the per-FC-host mTLS relay.
31
+ *
32
+ * Terminates mTLS (requestCert + rejectUnauthorized + CA pin), reads the
33
+ * `SANDBOX <id>\n` routing preamble line, then bridges the rest of the TLS
34
+ * stream verbatim to a FRESH `net.connect` to `agentSockPath` (the
35
+ * unix-socket-backed real agent) — exactly the dumb byte-pump the production
36
+ * relay is. It does NOT speak framing itself and does NOT send an ack line.
37
+ */
38
+ export declare function startMtlsRelay(agentSockPath: string, listenPort?: number): Promise<RelayHandle>;
39
+ //# sourceMappingURL=mtls-pki.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mtls-pki.d.ts","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/mtls-pki.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAkB,KAAK,MAAM,IAAI,SAAS,EAAmC,MAAM,UAAU,CAAA;AAEpG,eAAO,MAAM,MAAM,umBAWlB,CAAA;AAED,eAAO,MAAM,UAAU,ypBAYtB,CAAA;AAED,eAAO,MAAM,UAAU,2PAKtB,CAAA;AAED,eAAO,MAAM,UAAU,umBAWtB,CAAA;AAED,eAAO,MAAM,UAAU,2PAKtB,CAAA;AAED,eAAO,MAAM,gBAAgB,+lBAW5B,CAAA;AAED,eAAO,MAAM,gBAAgB,2PAK5B,CAAA;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,SAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAyD1F"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Shared Ring-0 mTLS test PKI + a loopback relay stand-in.
3
+ *
4
+ * A throwaway P-256 test PKI (CA + server leaf + client leaf + an unrelated
5
+ * rogue client) baked in as PEM constants — no openssl/forge at test time, so
6
+ * the package stays dependency-light. Minted offline:
7
+ * openssl ec/x509 self-signed CA + leaves
8
+ * (server SAN = DNS:sandbox.fc.internal, IP:127.0.0.1), far-future expiry.
9
+ * `ROGUE_*` chains to a DIFFERENT CA to prove `rejectUnauthorized` blocks it.
10
+ *
11
+ * Used by both transport.test.ts (the raw `kind:'mtls'` dialer arm) and
12
+ * backend.test.ts (the cert-INJECTION seam through `buildFirecrackerBackend`),
13
+ * so the PKI + relay harness lives in one place instead of per-test copies.
14
+ */
15
+ import { connect as netConnect } from 'node:net';
16
+ import { createServer as createTlsServer } from 'node:tls';
17
+ export const CA_CRT = `-----BEGIN CERTIFICATE-----
18
+ MIIBjjCCATWgAwIBAgIUGXUtG14KQr4spNGW7rpfjZGoBIIwCgYIKoZIzj0EAwIw
19
+ HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
20
+ MjEyNjA1MjMwODMyNTJaMBwxGjAYBgNVBAMMEXZhbmRhbC1mYy10ZXN0LWNhMFkw
21
+ EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5l+vjhjm/PX02D55n56EwelgvM1jrqQM
22
+ Z+ezzvMmrZEBGWInvBND3z3kc6nv7snu6fHT2HHOyhwUNoLqmrIg/qNTMFEwHQYD
23
+ VR0OBBYEFP0M8/KZY1ovxyGDci5iuoYXcmZgMB8GA1UdIwQYMBaAFP0M8/KZY1ov
24
+ xyGDci5iuoYXcmZgMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIg
25
+ C0xtFDASnwsOYT0GiZwzYWTOBfgmjDWK7ANXQQFNTh4CICVLQwq5eLy3424drEHk
26
+ 5Ol/FNKVZcGRjE96rB0mRUOp
27
+ -----END CERTIFICATE-----
28
+ `;
29
+ export const SERVER_CRT = `-----BEGIN CERTIFICATE-----
30
+ MIIBsDCCAVWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1MwCgYIKoZIzj0EAwIw
31
+ HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
32
+ MjEyNjA1MjMwODMyNTJaMBIxEDAOBgNVBAMMB2ZjLWhvc3QwWTATBgcqhkjOPQIB
33
+ BggqhkjOPQMBBwNCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMBfmonVb7dUhM0ZWpo
34
+ ePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6o30wezAkBgNVHREEHTAbghNz
35
+ YW5kYm94LmZjLmludGVybmFshwR/AAABMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0G
36
+ A1UdDgQWBBRXHU1vlX7WvqzcbaNxRxV4f3gfDDAfBgNVHSMEGDAWgBT9DPPymWNa
37
+ L8chg3IuYrqGF3JmYDAKBggqhkjOPQQDAgNJADBGAiEAlqzKqgBf5hxJqd26QwcY
38
+ n3cvEKi4f2BSLe1Rfzr5oSoCIQD0izUOJXLNvmac9cMgV0HvkftBerDKFOcGeGTN
39
+ g3Eunw==
40
+ -----END CERTIFICATE-----
41
+ `;
42
+ export const SERVER_KEY = `-----BEGIN PRIVATE KEY-----
43
+ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/ROnYXIkMKnipbLt
44
+ JnFEwXAifgeOv9TGLcK2RojE7jmhRANCAAQodCSHY8Sz5Lh/4K6+SzekkrRCeKMB
45
+ fmonVb7dUhM0ZWpoePCcRrMcJp5aNxLxEgkl2EMMMMwE3LlLSOX5LZz6
46
+ -----END PRIVATE KEY-----
47
+ `;
48
+ export const CLIENT_CRT = `-----BEGIN CERTIFICATE-----
49
+ MIIBjjCCATWgAwIBAgIUYkXroqlz9blXW8llis6e2OxOc1QwCgYIKoZIzj0EAwIw
50
+ HDEaMBgGA1UEAwwRdmFuZGFsLWZjLXRlc3QtY2EwIBcNMjYwNjE2MDgzMjUyWhgP
51
+ MjEyNjA1MjMwODMyNTJaMBgxFjAUBgNVBAMMDWNhLXZhbmRhbC1hcHAwWTATBgcq
52
+ hkjOPQIBBggqhkjOPQMBBwNCAASlCMCwjtrQUicWcWsO29R5S7fzjMbbxXvDh8/K
53
+ w57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXko1cwVTATBgNVHSUE
54
+ DDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU2cxDCNrlVkk4ODs6ZPrkC6GzHjkwHwYD
55
+ VR0jBBgwFoAU/Qzz8pljWi/HIYNyLmK6hhdyZmAwCgYIKoZIzj0EAwIDRwAwRAIg
56
+ RghqArNm3bXnWnRi+jkEEJa8mRb2z0Wj4G7SIhtMurUCIBQSllVtICgZB9hvcM0D
57
+ d24fcW4nlfvaZJMJ6dRC1Wle
58
+ -----END CERTIFICATE-----
59
+ `;
60
+ export const CLIENT_KEY = `-----BEGIN PRIVATE KEY-----
61
+ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaamj/ycrEuPqpiC2
62
+ IhAYx/M5iN4t4P+B17V4GO54Nb2hRANCAASlCMCwjtrQUicWcWsO29R5S7fzjMbb
63
+ xXvDh8/Kw57x/PN/uQwLHWCz1Tsyk0FnbrwGP+nPtwrUPIxrLN//euXk
64
+ -----END PRIVATE KEY-----
65
+ `;
66
+ export const ROGUE_CLIENT_CRT = `-----BEGIN CERTIFICATE-----
67
+ MIIBhjCCASugAwIBAgIUbAYOlW4PQGyXjjRsjCPy62EHUmIwCgYIKoZIzj0EAwIw
68
+ EzERMA8GA1UEAwwIcm9ndWUtY2EwIBcNMjYwNjE2MDgzMjUyWhgPMjEyNjA1MjMw
69
+ ODMyNTJaMBcxFTATBgNVBAMMDHJvZ3VlLWNsaWVudDBZMBMGByqGSM49AgEGCCqG
70
+ SM49AwEHA0IABOPSzdzQTQz3M5CDHLVPguvHd10ncaDV9t4zKUy/PCE+U7GTJwN2
71
+ TtypGnmYEahbcl45j94hwu495P5VbR5ohb6jVzBVMBMGA1UdJQQMMAoGCCsGAQUF
72
+ BwMCMB0GA1UdDgQWBBTf0woauniche3/ps77+Kd0dsbbSDAfBgNVHSMEGDAWgBSX
73
+ Yu0IJlPxi79Gyi5hR1IfS/sqyzAKBggqhkjOPQQDAgNJADBGAiEAxD4N4XWtaHPJ
74
+ yaCOzQP0e5RRyNst3QrhH0NSMyPw89wCIQC+bezLX97TuV1sId53Bo1l9j1TSOMa
75
+ EZotN/Wsq6L+qw==
76
+ -----END CERTIFICATE-----
77
+ `;
78
+ export const ROGUE_CLIENT_KEY = `-----BEGIN PRIVATE KEY-----
79
+ MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgR6fGq27O9eT/hi0Q
80
+ c+L5+lSm5fbDEghVJCo6k7HrG62hRANCAATj0s3c0E0M9zOQgxy1T4Lrx3ddJ3Gg
81
+ 1fbeMylMvzwhPlOxkycDdk7cqRp5mBGoW3JeOY/eIcLuPeT+VW0eaIW+
82
+ -----END PRIVATE KEY-----
83
+ `;
84
+ /**
85
+ * A loopback stand-in for the per-FC-host mTLS relay.
86
+ *
87
+ * Terminates mTLS (requestCert + rejectUnauthorized + CA pin), reads the
88
+ * `SANDBOX <id>\n` routing preamble line, then bridges the rest of the TLS
89
+ * stream verbatim to a FRESH `net.connect` to `agentSockPath` (the
90
+ * unix-socket-backed real agent) — exactly the dumb byte-pump the production
91
+ * relay is. It does NOT speak framing itself and does NOT send an ack line.
92
+ */
93
+ export function startMtlsRelay(agentSockPath, listenPort = 0) {
94
+ let resolvePreamble;
95
+ const preamble = new Promise((r) => {
96
+ resolvePreamble = r;
97
+ });
98
+ return new Promise((resolve, reject) => {
99
+ const server = createTlsServer({
100
+ requestCert: true,
101
+ rejectUnauthorized: true,
102
+ ca: CA_CRT,
103
+ cert: SERVER_CRT,
104
+ key: SERVER_KEY,
105
+ minVersion: 'TLSv1.3',
106
+ }, (tlsSock) => {
107
+ let pre = Buffer.alloc(0);
108
+ const onPreambleData = (chunk) => {
109
+ pre = Buffer.concat([pre, chunk]);
110
+ const nl = pre.indexOf(0x0a);
111
+ if (nl < 0)
112
+ return;
113
+ tlsSock.removeListener('data', onPreambleData);
114
+ tlsSock.pause();
115
+ const line = pre.subarray(0, nl).toString('utf8');
116
+ const rest = pre.subarray(nl + 1);
117
+ if (rest.length > 0)
118
+ tlsSock.unshift(rest);
119
+ const m = /^SANDBOX (.+)$/.exec(line);
120
+ const id = m?.[1];
121
+ if (id === undefined) {
122
+ tlsSock.destroy();
123
+ return;
124
+ }
125
+ resolvePreamble(id);
126
+ // 1 inbound mTLS conn -> 1 FRESH local agent connect (the
127
+ // resume-survival invariant the relay must preserve).
128
+ const upstream = netConnect({ path: agentSockPath });
129
+ upstream.on('error', () => tlsSock.destroy());
130
+ tlsSock.on('error', () => upstream.destroy());
131
+ upstream.once('connect', () => {
132
+ tlsSock.pipe(upstream);
133
+ upstream.pipe(tlsSock);
134
+ });
135
+ };
136
+ tlsSock.on('data', onPreambleData);
137
+ });
138
+ server.on('error', reject);
139
+ server.listen(listenPort, '127.0.0.1', () => {
140
+ const addr = server.address();
141
+ if (addr === null || typeof addr === 'string') {
142
+ reject(new Error('relay: no TCP port'));
143
+ return;
144
+ }
145
+ resolve({ server, port: addr.port, preamble: () => preamble });
146
+ });
147
+ });
148
+ }
149
+ //# sourceMappingURL=mtls-pki.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mtls-pki.js","sourceRoot":"","sources":["../../../../../src/backends/firecracker/__tests__/fixtures/mtls-pki.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Unit-pins the shared NDJSON codec the vsock + HTTP transports both
3
+ * speak, and the `pickBackend` routing for `microvm:self-hosted`.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=protocol.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.test.d.ts","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/protocol.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Unit-pins the shared NDJSON codec the vsock + HTTP transports both
3
+ * speak, and the `pickBackend` routing for `microvm:self-hosted`.
4
+ */
5
+ import { describe, expect, it } from 'vitest';
6
+ import { SandboxBackendNotImplementedError, createSandboxProvider } from '../../../index.js';
7
+ import { ExecResultAccumulator, parseExecLine } from '../protocol.js';
8
+ describe('ExecResultAccumulator', () => {
9
+ it('accumulates stdout/stderr deltas and captures the terminal result', () => {
10
+ const acc = new ExecResultAccumulator(0);
11
+ expect(acc.push({ type: 'stdout_delta', data: 'a' })).toBe(false);
12
+ expect(acc.push({ type: 'stdout_delta', data: 'b' })).toBe(false);
13
+ expect(acc.push({ type: 'stderr_delta', data: 'E' })).toBe(false);
14
+ expect(acc.done).toBe(false);
15
+ expect(acc.push({ type: 'result', exitCode: 0, timedOut: false })).toBe(true);
16
+ expect(acc.done).toBe(true);
17
+ const r = acc.finish();
18
+ expect(r.stdout).toBe('ab');
19
+ expect(r.stderr).toBe('E');
20
+ expect(r.exitCode).toBe(0);
21
+ expect(r.timedOut).toBe(false);
22
+ });
23
+ it('throws on an error event (docker loop parity)', () => {
24
+ const acc = new ExecResultAccumulator(0);
25
+ expect(() => acc.push({ type: 'error', error: 'boom' })).toThrow('boom');
26
+ });
27
+ });
28
+ describe('parseExecLine', () => {
29
+ it('parses a valid NDJSON line', () => {
30
+ expect(parseExecLine('{"type":"stdout_delta","data":"x"}')).toEqual({
31
+ type: 'stdout_delta',
32
+ data: 'x',
33
+ });
34
+ });
35
+ it('returns undefined for blank or malformed lines (SyntaxError swallow)', () => {
36
+ expect(parseExecLine('')).toBeUndefined();
37
+ expect(parseExecLine(' ')).toBeUndefined();
38
+ expect(parseExecLine('{not json')).toBeUndefined();
39
+ });
40
+ });
41
+ describe('pickBackend — microvm:self-hosted', () => {
42
+ it('builds the firecracker backend when orchestratorEndpoint + getToken are present', () => {
43
+ const provider = createSandboxProvider({
44
+ backend: {
45
+ tier: 'microvm',
46
+ service: 'self-hosted',
47
+ firecrackerBinary: '/usr/bin/firecracker',
48
+ kernelImage: '/golden/vmlinux',
49
+ rootfsImage: '/golden/rootfs.ext4',
50
+ orchestratorEndpoint: 'https://orchestrator.test',
51
+ getToken: async () => 'tok',
52
+ template: 'golden-rev-1',
53
+ },
54
+ });
55
+ expect(provider.id).toContain('microvm');
56
+ expect(provider.id).toContain('firecracker');
57
+ expect(provider.name).toContain('microvm:self-hosted');
58
+ });
59
+ it('still throws for the legacy local-containerd self-hosted shape (no orchestrator)', () => {
60
+ expect(() => createSandboxProvider({
61
+ backend: {
62
+ tier: 'microvm',
63
+ service: 'self-hosted',
64
+ firecrackerBinary: '/usr/bin/firecracker',
65
+ kernelImage: '/k',
66
+ rootfsImage: '/r',
67
+ },
68
+ })).toThrow(SandboxBackendNotImplementedError);
69
+ });
70
+ it('still throws for microvm:e2b and microvm:fly-machines', () => {
71
+ expect(() => createSandboxProvider({ backend: { tier: 'microvm', service: 'e2b', apiKey: 'k' } })).toThrow(SandboxBackendNotImplementedError);
72
+ expect(() => createSandboxProvider({
73
+ backend: { tier: 'microvm', service: 'fly-machines', apiToken: 't', app: 'a', image: 'i' },
74
+ })).toThrow(SandboxBackendNotImplementedError);
75
+ });
76
+ });
77
+ //# sourceMappingURL=protocol.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.test.js","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/protocol.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,iCAAiC,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAC5F,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAErE,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC5E,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAA;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAA;QACtB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC1B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACxD,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAA;QACxC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,aAAa,CAAC,oCAAoC,CAAC,CAAC,CAAC,OAAO,CAAC;YACnE,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,GAAG;SACT,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC/E,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;QACzC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;QAC5C,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;IACnD,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QAC1F,MAAM,QAAQ,GAAG,qBAAqB,CAAC;YACtC,OAAO,EAAE;gBACR,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,aAAa;gBACtB,iBAAiB,EAAE,sBAAsB;gBACzC,WAAW,EAAE,iBAAiB;gBAC9B,WAAW,EAAE,qBAAqB;gBAClC,oBAAoB,EAAE,2BAA2B;gBACjD,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,KAAK;gBAC3B,QAAQ,EAAE,cAAc;aACxB;SACD,CAAC,CAAA;QACF,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QACxC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;QAC5C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC3F,MAAM,CAAC,GAAG,EAAE,CACX,qBAAqB,CAAC;YACrB,OAAO,EAAE;gBACR,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,aAAa;gBACtB,iBAAiB,EAAE,sBAAsB;gBACzC,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,IAAI;aACjB;SACD,CAAC,CACF,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,GAAG,EAAE,CACX,qBAAqB,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CACpF,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAA;QAC5C,MAAM,CAAC,GAAG,EAAE,CACX,qBAAqB,CAAC;YACrB,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;SAC1F,CAAC,CACF,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Loopback transport round-trip tests for the Firecracker vsock path.
3
+ *
4
+ * These prove the NEW transport (host dialer ↔ in-VM agent) over a
5
+ * **unix-socket stand-in** — the faithful local peer for AF_VSOCK,
6
+ * because the production vsock path also terminates on a host
7
+ * unix socket (see `transport.ts` docblock). The peer is the REAL
8
+ * `agent/agent.cjs` connection handler (its spawn/jail + NDJSON shapes
9
+ * verbatim), driven in-process over a temp unix socket; the client is
10
+ * the REAL {@link VsockAgentTransport}. So one test exercises:
11
+ * - exec → streamed stdout/stderr/result NDJSON, accumulated;
12
+ * - writeFile / readFile → base64 round-trip through the jail;
13
+ * - a simulated resume (server torn down + re-listened) survived by
14
+ * the dialer's connect-retry budget — the FC #4713 invariant.
15
+ *
16
+ * No docker, no Azure, no AF_VSOCK kernel support required: pure
17
+ * loopback, safe in CI.
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=transport.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.test.d.ts","sourceRoot":"","sources":["../../../../src/backends/firecracker/__tests__/transport.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}