@rlemaigre/sbx 0.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.
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/api.d.ts +91 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +216 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/deploy.d.ts +6 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +49 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +21 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/run.d.ts +9 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +49 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/undeploy.d.ts +6 -0
- package/dist/commands/undeploy.d.ts.map +1 -0
- package/dist/commands/undeploy.js +28 -0
- package/dist/commands/undeploy.js.map +1 -0
- package/dist/config.d.ts +99 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +165 -0
- package/dist/config.js.map +1 -0
- package/dist/lib/config.d.ts +51 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +47 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/network.d.ts +18 -0
- package/dist/lib/network.d.ts.map +1 -0
- package/dist/lib/network.js +31 -0
- package/dist/lib/network.js.map +1 -0
- package/dist/lib/paths.d.ts +12 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +21 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/vfs.d.ts +15 -0
- package/dist/lib/vfs.d.ts.map +1 -0
- package/dist/lib/vfs.js +44 -0
- package/dist/lib/vfs.js.map +1 -0
- package/dist/templates/config.template.yaml +47 -0
- package/dist/templates/shim.template.cmd +2 -0
- package/dist/templates/shim.template.sh +2 -0
- package/package.json +43 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Init command — copy template config to user config directory.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.initCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const paths_1 = require("../lib/paths");
|
|
11
|
+
exports.initCommand = new commander_1.Command("init")
|
|
12
|
+
.description("Generate a config file at ~/.config/sbx/<name>.yaml")
|
|
13
|
+
.argument("<name>", "shim name (e.g. pi)")
|
|
14
|
+
.action((name) => {
|
|
15
|
+
const target = (0, node_path_1.join)(paths_1.CONFIG_DIR, `${name}.yaml`);
|
|
16
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(target), { recursive: true });
|
|
17
|
+
(0, node_fs_1.copyFileSync)((0, node_path_1.resolve)(__dirname, "../template.yaml"), target);
|
|
18
|
+
console.log(`Created ${target}`);
|
|
19
|
+
console.log(`Edit it, then run: sbx deploy ${name}`);
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,yCAAoC;AACpC,qCAAkD;AAClD,yCAAmD;AACnD,wCAA0C;AAE7B,QAAA,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,qDAAqD,CAAC;KAClE,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;KACzC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;IACvB,MAAM,MAAM,GAAG,IAAA,gBAAI,EAAC,kBAAU,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IAChD,IAAA,mBAAS,EAAC,IAAA,mBAAO,EAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,IAAA,sBAAY,EAAC,IAAA,mBAAO,EAAC,SAAS,EAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run command — execute agent inside sandboxed VM.
|
|
3
|
+
*
|
|
4
|
+
* Invoked by shim scripts. Delegates to the API:
|
|
5
|
+
* loadConfig → createSandbox → exec + TTY forwarding → shutdown
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
export declare const runCommand: Command;
|
|
9
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,UAAU,SAiCnB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Run command — execute agent inside sandboxed VM.
|
|
4
|
+
*
|
|
5
|
+
* Invoked by shim scripts. Delegates to the API:
|
|
6
|
+
* loadConfig → createSandbox → exec + TTY forwarding → shutdown
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.runCommand = void 0;
|
|
13
|
+
const commander_1 = require("commander");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
const paths_1 = require("../lib/paths");
|
|
16
|
+
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
|
|
17
|
+
const config_1 = require("../lib/config");
|
|
18
|
+
const api_1 = require("../api");
|
|
19
|
+
exports.runCommand = new commander_1.Command("run")
|
|
20
|
+
.description("Execute agent inside sandboxed VM (internal — invoked by shims)")
|
|
21
|
+
.argument("[args...]", "arguments to pass to the agent command")
|
|
22
|
+
.option("--shim-name <name>", "shim name (resolves config)")
|
|
23
|
+
.allowUnknownOption(true)
|
|
24
|
+
.action(async (args, opts) => {
|
|
25
|
+
const shimName = opts.shimName;
|
|
26
|
+
(0, tiny_invariant_1.default)(shimName, "Missing --shim-name");
|
|
27
|
+
const config = (0, config_1.loadConfig)((0, node_path_1.join)(paths_1.CONFIG_DIR, `${shimName}.yaml`));
|
|
28
|
+
(0, tiny_invariant_1.default)(config.cmd, `Config for ${shimName} must specify cmd`);
|
|
29
|
+
const sandbox = await (0, api_1.createSandbox)({
|
|
30
|
+
config,
|
|
31
|
+
cacheDir: (0, node_path_1.join)(paths_1.CACHE_DIR, shimName),
|
|
32
|
+
});
|
|
33
|
+
const cmd = args.length > 0 ? `${config.cmd} ${args.join(" ")}` : config.cmd;
|
|
34
|
+
try {
|
|
35
|
+
const proc = await sandbox.exec(cmd, {
|
|
36
|
+
pty: true,
|
|
37
|
+
stdin: true,
|
|
38
|
+
stdout: "pipe",
|
|
39
|
+
stderr: "pipe",
|
|
40
|
+
});
|
|
41
|
+
proc.attach(process.stdin, process.stdout, process.stderr);
|
|
42
|
+
const result = await proc.exit;
|
|
43
|
+
process.exit(result.exitCode);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
await sandbox.shutdown();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;AAEH,yCAAoC;AACpC,yCAAiC;AACjC,wCAAqD;AACrD,oEAAuC;AAEvC,0CAA2C;AAC3C,gCAAuC;AAE1B,QAAA,UAAU,GAAG,IAAI,mBAAO,CAAC,KAAK,CAAC;KACzC,WAAW,CAAC,iEAAiE,CAAC;KAC9E,QAAQ,CAAC,WAAW,EAAE,wCAAwC,CAAC;KAC/D,MAAM,CAAC,oBAAoB,EAAE,6BAA6B,CAAC;KAC3D,kBAAkB,CAAC,IAAI,CAAC;KACxB,MAAM,CAAC,KAAK,EAAE,IAAc,EAAE,IAAI,EAAE,EAAE;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAkB,CAAC;IACzC,IAAA,wBAAS,EAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,IAAA,gBAAI,EAAC,kBAAU,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC;IAChE,IAAA,wBAAS,EAAC,MAAM,CAAC,GAAG,EAAE,cAAc,QAAQ,mBAAmB,CAAC,CAAC;IAEjE,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAa,EAAC;QAClC,MAAM;QACN,QAAQ,EAAE,IAAA,gBAAI,EAAC,iBAAS,EAAE,QAAQ,CAAC;KACpC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAE7E,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;YACnC,GAAG,EAAE,IAAI;YACT,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undeploy.d.ts","sourceRoot":"","sources":["../../src/commands/undeploy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,eAAe,SAiBxB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Undeploy command — remove shim scripts.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.undeployCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const paths_1 = require("../lib/paths");
|
|
11
|
+
exports.undeployCommand = new commander_1.Command("undeploy")
|
|
12
|
+
.description("Remove shim scripts")
|
|
13
|
+
.argument("<names...>", "shim names to remove")
|
|
14
|
+
.action((names) => {
|
|
15
|
+
for (const name of names) {
|
|
16
|
+
const shimPath = process.platform === "win32"
|
|
17
|
+
? (0, node_path_1.join)(paths_1.SHIM_DIR, `${name}.cmd`)
|
|
18
|
+
: (0, node_path_1.join)(paths_1.SHIM_DIR, name);
|
|
19
|
+
if ((0, node_fs_1.existsSync)(shimPath)) {
|
|
20
|
+
(0, node_fs_1.unlinkSync)(shimPath);
|
|
21
|
+
console.log(`Removed ${shimPath}`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.error(`Shim not found: ${shimPath}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=undeploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undeploy.js","sourceRoot":"","sources":["../../src/commands/undeploy.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,yCAAoC;AACpC,qCAAiD;AACjD,yCAAiC;AACjC,wCAAwC;AAE3B,QAAA,eAAe,GAAG,IAAI,mBAAO,CAAC,UAAU,CAAC;KACnD,WAAW,CAAC,qBAAqB,CAAC;KAClC,QAAQ,CAAC,YAAY,EAAE,sBAAsB,CAAC;KAC9C,MAAM,CAAC,CAAC,KAAe,EAAE,EAAE;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GACZ,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC1B,CAAC,CAAC,IAAA,gBAAI,EAAC,gBAAQ,EAAE,GAAG,IAAI,MAAM,CAAC;YAC/B,CAAC,CAAC,IAAA,gBAAI,EAAC,gBAAQ,EAAE,IAAI,CAAC,CAAC;QAE3B,IAAI,IAAA,oBAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAA,oBAAU,EAAC,QAAQ,CAAC,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration interfaces, loading, and builder methods.
|
|
3
|
+
*
|
|
4
|
+
* `SandboxConfig` wraps the YAML config datastructure (SPECS §3.1)
|
|
5
|
+
* and provides methods to build Gondolin VFS mounts and HTTP hooks.
|
|
6
|
+
*/
|
|
7
|
+
import type { HttpHooks, VirtualProvider } from "@earendil-works/gondolin";
|
|
8
|
+
/**
|
|
9
|
+
* Outbound network policy.
|
|
10
|
+
*/
|
|
11
|
+
export interface INetworkPolicy {
|
|
12
|
+
allowedHosts?: string[];
|
|
13
|
+
allowedInternalHosts?: string[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Host filesystem mount.
|
|
17
|
+
*/
|
|
18
|
+
export interface IMount {
|
|
19
|
+
hostPath: string;
|
|
20
|
+
guestPath: string;
|
|
21
|
+
readOnly?: boolean;
|
|
22
|
+
shadow?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Secret injection configuration.
|
|
26
|
+
*/
|
|
27
|
+
export interface ISecretConfig {
|
|
28
|
+
hosts: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sandbox configuration — wraps the YAML config datastructure (SPECS §3.1)
|
|
32
|
+
* and provides methods to build Gondolin VFS mounts and HTTP hooks.
|
|
33
|
+
*/
|
|
34
|
+
export declare class SandboxConfig {
|
|
35
|
+
readonly cmd?: string;
|
|
36
|
+
readonly setup?: string[];
|
|
37
|
+
readonly network?: INetworkPolicy;
|
|
38
|
+
readonly mounts?: IMount[];
|
|
39
|
+
readonly shadow?: string[];
|
|
40
|
+
readonly env?: Record<string, string>;
|
|
41
|
+
readonly secrets?: Record<string, ISecretConfig>;
|
|
42
|
+
/**
|
|
43
|
+
* Create a SandboxConfig from a plain object.
|
|
44
|
+
*/
|
|
45
|
+
static from(data: Record<string, unknown>): SandboxConfig;
|
|
46
|
+
/**
|
|
47
|
+
* Load a sandbox configuration from a YAML file.
|
|
48
|
+
*/
|
|
49
|
+
static load(path: string): SandboxConfig;
|
|
50
|
+
private constructor();
|
|
51
|
+
/**
|
|
52
|
+
* Build VFS providers from config mounts and shadow rules.
|
|
53
|
+
* Mount chain: RealFS → Readonly (if readOnly) → Shadow (if shadow paths).
|
|
54
|
+
*/
|
|
55
|
+
buildVFSProviders(): Record<string, VirtualProvider>;
|
|
56
|
+
/**
|
|
57
|
+
* Build HTTP hooks and secret env vars from config.
|
|
58
|
+
* Secrets are read from the host environment at runtime.
|
|
59
|
+
*/
|
|
60
|
+
buildHttpHooks(): {
|
|
61
|
+
httpHooks: HttpHooks;
|
|
62
|
+
env: Record<string, string>;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Build VFS providers from a plain config object.
|
|
66
|
+
* @deprecated Use instance `config.buildVFSProviders()` instead.
|
|
67
|
+
*/
|
|
68
|
+
static buildVFSProviders(config: Record<string, unknown>): Record<string, VirtualProvider>;
|
|
69
|
+
/**
|
|
70
|
+
* Build HTTP hooks from a plain config object.
|
|
71
|
+
* @deprecated Use instance `config.buildHttpHooks()` instead.
|
|
72
|
+
*/
|
|
73
|
+
static buildHttpHooks(config: Record<string, unknown>): {
|
|
74
|
+
httpHooks: HttpHooks;
|
|
75
|
+
env: Record<string, string>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Assert that each mount has required hostPath and guestPath.
|
|
79
|
+
*/
|
|
80
|
+
private static validateMounts;
|
|
81
|
+
/**
|
|
82
|
+
* Check if a guest path matches any shadow pattern (glob or prefix).
|
|
83
|
+
*/
|
|
84
|
+
private static matchesShadow;
|
|
85
|
+
/**
|
|
86
|
+
* Build the RealFS → Readonly → Shadow provider chain for a single mount.
|
|
87
|
+
*/
|
|
88
|
+
private static buildMountChain;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Expand ~ prefix to HOME directory path.
|
|
92
|
+
*/
|
|
93
|
+
export declare function expandTilde(path: string): string;
|
|
94
|
+
/**
|
|
95
|
+
* Load a sandbox configuration from a YAML file.
|
|
96
|
+
* @deprecated Use `SandboxConfig.load(path)` instead.
|
|
97
|
+
*/
|
|
98
|
+
export declare function loadConfig(path: string): SandboxConfig;
|
|
99
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAO3E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAID;;;GAGG;AACH,qBAAa,aAAa;IACxB,SAAgB,GAAG,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAgB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,SAAgB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzC,SAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,SAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,SAAgB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAExD;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa;IAIzD;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IASxC,OAAO;IAUP;;;OAGG;IACH,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAWpD;;;OAGG;IACH,cAAc,IAAI;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;IAoBvE;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;IAI1F;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE;IAM7G;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAO7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAU5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;CAqB/B;AAID;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAEtD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration interfaces, loading, and builder methods.
|
|
4
|
+
*
|
|
5
|
+
* `SandboxConfig` wraps the YAML config datastructure (SPECS §3.1)
|
|
6
|
+
* and provides methods to build Gondolin VFS mounts and HTTP hooks.
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SandboxConfig = void 0;
|
|
13
|
+
exports.expandTilde = expandTilde;
|
|
14
|
+
exports.loadConfig = loadConfig;
|
|
15
|
+
const node_fs_1 = require("node:fs");
|
|
16
|
+
const node_path_1 = require("node:path");
|
|
17
|
+
const js_yaml_1 = require("js-yaml");
|
|
18
|
+
const minimatch_1 = require("minimatch");
|
|
19
|
+
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
|
|
20
|
+
const gondolin_1 = require("@earendil-works/gondolin");
|
|
21
|
+
const gondolin_2 = require("@earendil-works/gondolin");
|
|
22
|
+
// ─── SandboxConfig class ─────────────────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Sandbox configuration — wraps the YAML config datastructure (SPECS §3.1)
|
|
25
|
+
* and provides methods to build Gondolin VFS mounts and HTTP hooks.
|
|
26
|
+
*/
|
|
27
|
+
class SandboxConfig {
|
|
28
|
+
cmd;
|
|
29
|
+
setup;
|
|
30
|
+
network;
|
|
31
|
+
mounts;
|
|
32
|
+
shadow;
|
|
33
|
+
env;
|
|
34
|
+
secrets;
|
|
35
|
+
/**
|
|
36
|
+
* Create a SandboxConfig from a plain object.
|
|
37
|
+
*/
|
|
38
|
+
static from(data) {
|
|
39
|
+
return new SandboxConfig(data);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Load a sandbox configuration from a YAML file.
|
|
43
|
+
*/
|
|
44
|
+
static load(path) {
|
|
45
|
+
const resolved = expandTilde(path);
|
|
46
|
+
const raw = (0, js_yaml_1.load)((0, node_fs_1.readFileSync)(resolved, "utf-8"));
|
|
47
|
+
(0, tiny_invariant_1.default)(typeof raw === "object" && raw !== null, "Config must be a YAML mapping");
|
|
48
|
+
const config = new SandboxConfig(raw);
|
|
49
|
+
SandboxConfig.validateMounts(config.mounts);
|
|
50
|
+
return config;
|
|
51
|
+
}
|
|
52
|
+
constructor(data) {
|
|
53
|
+
this.cmd = data.cmd;
|
|
54
|
+
this.setup = data.setup;
|
|
55
|
+
this.network = data.network;
|
|
56
|
+
this.mounts = data.mounts;
|
|
57
|
+
this.shadow = data.shadow;
|
|
58
|
+
this.env = data.env;
|
|
59
|
+
this.secrets = data.secrets;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Build VFS providers from config mounts and shadow rules.
|
|
63
|
+
* Mount chain: RealFS → Readonly (if readOnly) → Shadow (if shadow paths).
|
|
64
|
+
*/
|
|
65
|
+
buildVFSProviders() {
|
|
66
|
+
const mounts = {};
|
|
67
|
+
const globalShadow = this.shadow ?? [];
|
|
68
|
+
for (const mount of this.mounts ?? []) {
|
|
69
|
+
mounts[mount.guestPath] = SandboxConfig.buildMountChain(mount, globalShadow);
|
|
70
|
+
}
|
|
71
|
+
return mounts;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Build HTTP hooks and secret env vars from config.
|
|
75
|
+
* Secrets are read from the host environment at runtime.
|
|
76
|
+
*/
|
|
77
|
+
buildHttpHooks() {
|
|
78
|
+
const secrets = {};
|
|
79
|
+
for (const [name, secret] of Object.entries(this.secrets ?? {})) {
|
|
80
|
+
secrets[name] = {
|
|
81
|
+
hosts: secret.hosts,
|
|
82
|
+
value: process.env[name] ?? "",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return (0, gondolin_1.createHttpHooks)({
|
|
86
|
+
allowedHosts: this.network?.allowedHosts ?? [],
|
|
87
|
+
allowedInternalHosts: this.network?.allowedInternalHosts ?? [],
|
|
88
|
+
blockInternalRanges: true,
|
|
89
|
+
secrets,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// ─── Static methods (backward compatibility) ───────────────────────────────
|
|
93
|
+
/**
|
|
94
|
+
* Build VFS providers from a plain config object.
|
|
95
|
+
* @deprecated Use instance `config.buildVFSProviders()` instead.
|
|
96
|
+
*/
|
|
97
|
+
static buildVFSProviders(config) {
|
|
98
|
+
return new SandboxConfig(config).buildVFSProviders();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build HTTP hooks from a plain config object.
|
|
102
|
+
* @deprecated Use instance `config.buildHttpHooks()` instead.
|
|
103
|
+
*/
|
|
104
|
+
static buildHttpHooks(config) {
|
|
105
|
+
return new SandboxConfig(config).buildHttpHooks();
|
|
106
|
+
}
|
|
107
|
+
// ─── Private static helpers ────────────────────────────────────────────────
|
|
108
|
+
/**
|
|
109
|
+
* Assert that each mount has required hostPath and guestPath.
|
|
110
|
+
*/
|
|
111
|
+
static validateMounts(mounts = []) {
|
|
112
|
+
for (const mount of mounts) {
|
|
113
|
+
(0, tiny_invariant_1.default)(mount.hostPath, "Mount must have hostPath");
|
|
114
|
+
(0, tiny_invariant_1.default)(mount.guestPath, "Mount must have guestPath");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Check if a guest path matches any shadow pattern (glob or prefix).
|
|
119
|
+
*/
|
|
120
|
+
static matchesShadow(shadowPaths, path) {
|
|
121
|
+
return shadowPaths.some((p) => {
|
|
122
|
+
if (p.endsWith("/")) {
|
|
123
|
+
const dir = `/${p.slice(0, -1)}`;
|
|
124
|
+
return path === dir || path.startsWith(`${dir}/`);
|
|
125
|
+
}
|
|
126
|
+
return (0, minimatch_1.minimatch)(path, `/${p}`, { dot: true });
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Build the RealFS → Readonly → Shadow provider chain for a single mount.
|
|
131
|
+
*/
|
|
132
|
+
static buildMountChain(mount, globalShadow) {
|
|
133
|
+
let provider = new gondolin_2.RealFSProvider(expandTilde(mount.hostPath));
|
|
134
|
+
if (mount.readOnly) {
|
|
135
|
+
provider = new gondolin_2.ReadonlyProvider(provider);
|
|
136
|
+
}
|
|
137
|
+
const shadowPaths = [...globalShadow, ...(mount.shadow ?? [])];
|
|
138
|
+
if (shadowPaths.length > 0) {
|
|
139
|
+
provider = new gondolin_2.ShadowProvider(provider, {
|
|
140
|
+
shouldShadow: (info) => SandboxConfig.matchesShadow(shadowPaths, info.path),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return provider;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
exports.SandboxConfig = SandboxConfig;
|
|
147
|
+
// ─── Standalone helpers ──────────────────────────────────────────────────────
|
|
148
|
+
/**
|
|
149
|
+
* Expand ~ prefix to HOME directory path.
|
|
150
|
+
*/
|
|
151
|
+
function expandTilde(path) {
|
|
152
|
+
if (!path.startsWith("~"))
|
|
153
|
+
return path;
|
|
154
|
+
const home = process.env.HOME;
|
|
155
|
+
(0, tiny_invariant_1.default)(home, "HOME environment variable not set");
|
|
156
|
+
return (0, node_path_1.resolve)(home, path.slice(2));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Load a sandbox configuration from a YAML file.
|
|
160
|
+
* @deprecated Use `SandboxConfig.load(path)` instead.
|
|
161
|
+
*/
|
|
162
|
+
function loadConfig(path) {
|
|
163
|
+
return SandboxConfig.load(path);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration interfaces and YAML loading/saving.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the YAML config keys (SPECS §3.1).
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Outbound network policy.
|
|
8
|
+
*/
|
|
9
|
+
export interface INetworkPolicy {
|
|
10
|
+
allowedHosts?: string[];
|
|
11
|
+
allowedInternalHosts?: string[];
|
|
12
|
+
blockInternalRanges?: boolean;
|
|
13
|
+
dnsMode?: "synthetic" | "trusted" | "open";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Host filesystem mount.
|
|
17
|
+
*/
|
|
18
|
+
export interface IMount {
|
|
19
|
+
hostPath: string;
|
|
20
|
+
guestPath: string;
|
|
21
|
+
readOnly?: boolean;
|
|
22
|
+
shadow?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Secret injection configuration.
|
|
26
|
+
*/
|
|
27
|
+
export interface ISecretConfig {
|
|
28
|
+
hosts: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sandbox configuration — mirrors the YAML config keys (SPECS §3.1).
|
|
32
|
+
*/
|
|
33
|
+
export interface ISandboxConfig {
|
|
34
|
+
cmd?: string;
|
|
35
|
+
packages?: string[];
|
|
36
|
+
network?: INetworkPolicy;
|
|
37
|
+
mounts?: IMount[];
|
|
38
|
+
shadow?: string[];
|
|
39
|
+
env?: Record<string, string>;
|
|
40
|
+
secrets?: Record<string, ISecretConfig>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Load a sandbox configuration from a YAML file.
|
|
44
|
+
* Same syntax as the Coding Assistants config files.
|
|
45
|
+
*/
|
|
46
|
+
export declare function loadConfig(path: string): ISandboxConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Save a sandbox configuration to a YAML file.
|
|
49
|
+
*/
|
|
50
|
+
export declare function saveConfig(path: string, config: ISandboxConfig): void;
|
|
51
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACzC;AAYD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAOvD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAGrE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration interfaces and YAML loading/saving.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the YAML config keys (SPECS §3.1).
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.loadConfig = loadConfig;
|
|
12
|
+
exports.saveConfig = saveConfig;
|
|
13
|
+
const node_fs_1 = require("node:fs");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
16
|
+
const js_yaml_1 = require("js-yaml");
|
|
17
|
+
const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
|
|
18
|
+
const config_json_1 = __importDefault(require("../../schema/config.json"));
|
|
19
|
+
const ajv = new ajv_1.default({ strict: false });
|
|
20
|
+
const validate = ajv.compile(config_json_1.default);
|
|
21
|
+
function expandTilde(path) {
|
|
22
|
+
if (!path.startsWith("~"))
|
|
23
|
+
return path;
|
|
24
|
+
const home = process.env.HOME;
|
|
25
|
+
(0, tiny_invariant_1.default)(home, "HOME environment variable not set");
|
|
26
|
+
return (0, node_path_1.resolve)(home, path.slice(1));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Load a sandbox configuration from a YAML file.
|
|
30
|
+
* Same syntax as the Coding Assistants config files.
|
|
31
|
+
*/
|
|
32
|
+
function loadConfig(path) {
|
|
33
|
+
const resolved = expandTilde(path);
|
|
34
|
+
const raw = (0, js_yaml_1.load)((0, node_fs_1.readFileSync)(resolved, "utf-8"));
|
|
35
|
+
if (!validate(raw)) {
|
|
36
|
+
throw new Error(`Config validation failed: ${JSON.stringify(validate.errors)}`);
|
|
37
|
+
}
|
|
38
|
+
return raw;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Save a sandbox configuration to a YAML file.
|
|
42
|
+
*/
|
|
43
|
+
function saveConfig(path, config) {
|
|
44
|
+
const resolved = expandTilde(path);
|
|
45
|
+
(0, node_fs_1.writeFileSync)(resolved, (0, js_yaml_1.dump)(config, { lineWidth: -1 }));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;AAgEH,gCAOC;AAKD,gCAGC;AA7ED,qCAAsD;AACtD,yCAA0C;AAC1C,8CAAsB;AACtB,qCAAqC;AACrC,oEAAuC;AAEvC,2EAA8C;AA0C9C,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAM,CAAC,CAAC;AAErC,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC9B,IAAA,wBAAS,EAAC,IAAI,EAAE,mCAAmC,CAAC,CAAC;IACrD,OAAO,IAAA,mBAAO,EAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU,CAAC,IAAY;IACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,IAAA,cAAI,EAAC,IAAA,sBAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAY,CAAC;IAC7D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,GAAqB,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAC,IAAY,EAAE,MAAsB;IAC7D,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,IAAA,uBAAa,EAAC,QAAQ,EAAE,IAAA,cAAI,EAAC,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP hooks building from config network policy and secrets.
|
|
3
|
+
*
|
|
4
|
+
* Maps YAML network + secrets to Gondolin's createHttpHooks.
|
|
5
|
+
*/
|
|
6
|
+
import type { HttpHooks } from "@earendil-works/gondolin";
|
|
7
|
+
import { ISandboxConfig } from "./config";
|
|
8
|
+
/**
|
|
9
|
+
* Build HTTP hooks and secret env vars from config.
|
|
10
|
+
*
|
|
11
|
+
* Secrets are read from the host environment at runtime.
|
|
12
|
+
* Returns { httpHooks, env } — the env maps secret names to placeholder values.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildHttpHooks(config: ISandboxConfig): {
|
|
15
|
+
httpHooks: HttpHooks;
|
|
16
|
+
env: Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/lib/network.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG;IACtD,SAAS,EAAE,SAAS,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B,CAmBA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP hooks building from config network policy and secrets.
|
|
4
|
+
*
|
|
5
|
+
* Maps YAML network + secrets to Gondolin's createHttpHooks.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.buildHttpHooks = buildHttpHooks;
|
|
9
|
+
const gondolin_1 = require("@earendil-works/gondolin");
|
|
10
|
+
/**
|
|
11
|
+
* Build HTTP hooks and secret env vars from config.
|
|
12
|
+
*
|
|
13
|
+
* Secrets are read from the host environment at runtime.
|
|
14
|
+
* Returns { httpHooks, env } — the env maps secret names to placeholder values.
|
|
15
|
+
*/
|
|
16
|
+
function buildHttpHooks(config) {
|
|
17
|
+
const secrets = {};
|
|
18
|
+
for (const [name, secret] of Object.entries(config.secrets ?? {})) {
|
|
19
|
+
secrets[name] = {
|
|
20
|
+
hosts: secret.hosts,
|
|
21
|
+
value: process.env[name] ?? "",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return (0, gondolin_1.createHttpHooks)({
|
|
25
|
+
allowedHosts: config.network?.allowedHosts ?? [],
|
|
26
|
+
allowedInternalHosts: config.network?.allowedInternalHosts ?? [],
|
|
27
|
+
blockInternalRanges: config.network?.blockInternalRanges ?? true,
|
|
28
|
+
secrets,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/lib/network.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAaH,wCAsBC;AAjCD,uDAA2D;AAK3D;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,MAAsB;IAInD,MAAM,OAAO,GAGT,EAAE,CAAC;IAEP,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,GAAG;YACd,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;SAC/B,CAAC;IACJ,CAAC;IAED,OAAO,IAAA,0BAAe,EAAC;QACrB,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE;QAChD,oBAAoB,EAAE,MAAM,CAAC,OAAO,EAAE,oBAAoB,IAAI,EAAE;QAChE,mBAAmB,EAAE,MAAM,CAAC,OAAO,EAAE,mBAAmB,IAAI,IAAI;QAChE,OAAO;KACR,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-aware path constants.
|
|
3
|
+
*
|
|
4
|
+
* Resolves config, shim, and cache directories per SPECS §3.2.
|
|
5
|
+
*/
|
|
6
|
+
/** Config directory: ~/.config/sbx/ */
|
|
7
|
+
export declare const CONFIG_DIR: string;
|
|
8
|
+
/** Shim directory: ~/.local/bin/ (Linux) or mapped WSL path (Windows) */
|
|
9
|
+
export declare const SHIM_DIR: string;
|
|
10
|
+
/** Cache directory: ~/.cache/sbx/ */
|
|
11
|
+
export declare const CACHE_DIR: string;
|
|
12
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,uCAAuC;AACvC,eAAO,MAAM,UAAU,QAAwC,CAAC;AAEhE,yEAAyE;AACzE,eAAO,MAAM,QAAQ,QAGqB,CAAC;AAE3C,qCAAqC;AACrC,eAAO,MAAM,SAAS,QAAuC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Platform-aware path constants.
|
|
4
|
+
*
|
|
5
|
+
* Resolves config, shim, and cache directories per SPECS §3.2.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.CACHE_DIR = exports.SHIM_DIR = exports.CONFIG_DIR = void 0;
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
const home = process.env.HOME;
|
|
11
|
+
if (!home)
|
|
12
|
+
throw new Error("HOME environment variable not set");
|
|
13
|
+
/** Config directory: ~/.config/sbx/ */
|
|
14
|
+
exports.CONFIG_DIR = (0, node_path_1.resolve)((0, node_path_1.join)(home, ".config", "sbx"));
|
|
15
|
+
/** Shim directory: ~/.local/bin/ (Linux) or mapped WSL path (Windows) */
|
|
16
|
+
exports.SHIM_DIR = process.platform === "win32"
|
|
17
|
+
? (0, node_path_1.resolve)((0, node_path_1.join)(home, "AppData", "Roaming", "bin"))
|
|
18
|
+
: (0, node_path_1.resolve)((0, node_path_1.join)(home, ".local", "bin"));
|
|
19
|
+
/** Cache directory: ~/.cache/sbx/ */
|
|
20
|
+
exports.CACHE_DIR = (0, node_path_1.resolve)((0, node_path_1.join)(home, ".cache", "sbx"));
|
|
21
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,yCAA0C;AAE1C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AAC9B,IAAI,CAAC,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;AAEhE,uCAAuC;AAC1B,QAAA,UAAU,GAAG,IAAA,mBAAO,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;AAEhE,yEAAyE;AAC5D,QAAA,QAAQ,GACnB,OAAO,CAAC,QAAQ,KAAK,OAAO;IAC1B,CAAC,CAAC,IAAA,mBAAO,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,IAAA,mBAAO,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3C,qCAAqC;AACxB,QAAA,SAAS,GAAG,IAAA,mBAAO,EAAC,IAAA,gBAAI,EAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VFS provider building from config mounts and shadow rules.
|
|
3
|
+
*
|
|
4
|
+
* Builds the RealFS → Readonly → Shadow mount chain per SPECS §2.1.
|
|
5
|
+
*/
|
|
6
|
+
import type { VirtualProvider } from "@earendil-works/gondolin";
|
|
7
|
+
import { ISandboxConfig } from "./config";
|
|
8
|
+
/**
|
|
9
|
+
* Build VFS providers from config mounts and shadow rules.
|
|
10
|
+
*
|
|
11
|
+
* Mount chain: RealFS → Readonly (if readOnly) → Shadow (if shadow paths).
|
|
12
|
+
* Global shadow is merged with per-mount shadow.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildVFSProviders(config: ISandboxConfig): Record<string, VirtualProvider>;
|
|
15
|
+
//# sourceMappingURL=vfs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vfs.d.ts","sourceRoot":"","sources":["../../src/lib/vfs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAS1C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,GACrB,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CA2BjC"}
|