@isol8/core 0.13.0-alpha.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/README.md +39 -0
- package/dist/client/remote.d.ts +64 -0
- package/dist/client/remote.d.ts.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/docker/Dockerfile +42 -0
- package/dist/docker/proxy-handler.sh +180 -0
- package/dist/docker/proxy.sh +57 -0
- package/dist/docker/seccomp-profile.json +67 -0
- package/dist/engine/audit.d.ts +31 -0
- package/dist/engine/audit.d.ts.map +1 -0
- package/dist/engine/code-fetcher.d.ts +21 -0
- package/dist/engine/code-fetcher.d.ts.map +1 -0
- package/dist/engine/concurrency.d.ts +46 -0
- package/dist/engine/concurrency.d.ts.map +1 -0
- package/dist/engine/default-seccomp-profile.d.ts +8 -0
- package/dist/engine/default-seccomp-profile.d.ts.map +1 -0
- package/dist/engine/docker.d.ts +167 -0
- package/dist/engine/docker.d.ts.map +1 -0
- package/dist/engine/image-builder.d.ts +71 -0
- package/dist/engine/image-builder.d.ts.map +1 -0
- package/dist/engine/pool.d.ts +94 -0
- package/dist/engine/pool.d.ts.map +1 -0
- package/dist/engine/stats.d.ts +35 -0
- package/dist/engine/stats.d.ts.map +1 -0
- package/dist/engine/utils.d.ts +71 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2777 -0
- package/dist/index.js.map +30 -0
- package/dist/runtime/adapter.d.ts +63 -0
- package/dist/runtime/adapter.d.ts.map +1 -0
- package/dist/runtime/adapters/bash.d.ts +3 -0
- package/dist/runtime/adapters/bash.d.ts.map +1 -0
- package/dist/runtime/adapters/bun.d.ts +4 -0
- package/dist/runtime/adapters/bun.d.ts.map +1 -0
- package/dist/runtime/adapters/deno.d.ts +10 -0
- package/dist/runtime/adapters/deno.d.ts.map +1 -0
- package/dist/runtime/adapters/node.d.ts +4 -0
- package/dist/runtime/adapters/node.d.ts.map +1 -0
- package/dist/runtime/adapters/python.d.ts +4 -0
- package/dist/runtime/adapters/python.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +15 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/types.d.ts +532 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/docker/Dockerfile +42 -0
- package/docker/proxy-handler.sh +180 -0
- package/docker/proxy.sh +57 -0
- package/docker/seccomp-profile.json +67 -0
- package/package.json +48 -0
- package/schema/isol8.config.schema.json +315 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module engine/docker
|
|
3
|
+
*
|
|
4
|
+
* The Docker-backed isol8 engine. Creates and manages Docker containers
|
|
5
|
+
* for executing untrusted code with resource limits, network controls, and
|
|
6
|
+
* output sanitization.
|
|
7
|
+
*/
|
|
8
|
+
import Docker from "dockerode";
|
|
9
|
+
import type { ExecutionRequest, ExecutionResult, Isol8Engine, Isol8Options, StartOptions, StreamEvent } from "../types";
|
|
10
|
+
/** Options for constructing a {@link DockerIsol8} instance. Extends {@link Isol8Options} with Docker-specific settings. */
|
|
11
|
+
export interface DockerIsol8Options extends Isol8Options {
|
|
12
|
+
/** Custom dockerode instance. Defaults to connecting to the local Docker socket. */
|
|
13
|
+
docker?: Docker;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Docker-backed isol8 engine that executes code in isolated containers.
|
|
17
|
+
*
|
|
18
|
+
* Supports two modes:
|
|
19
|
+
* - **Ephemeral** — a new container is created and destroyed per `execute()` call.
|
|
20
|
+
* - **Persistent** — a long-lived container is reused across calls, preserving state.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const isol8 = new DockerIsol8({ network: "none", memoryLimit: "256m" });
|
|
25
|
+
* await isol8.start();
|
|
26
|
+
* const result = await isol8.execute({ code: "print(1+1)", runtime: "python" });
|
|
27
|
+
* await isol8.stop();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class DockerIsol8 implements Isol8Engine {
|
|
31
|
+
private readonly docker;
|
|
32
|
+
private readonly mode;
|
|
33
|
+
private readonly network;
|
|
34
|
+
private readonly networkFilter?;
|
|
35
|
+
private readonly cpuLimit;
|
|
36
|
+
private readonly memoryLimit;
|
|
37
|
+
private readonly pidsLimit;
|
|
38
|
+
private readonly readonlyRootFs;
|
|
39
|
+
private readonly maxOutputSize;
|
|
40
|
+
private readonly secrets;
|
|
41
|
+
private readonly defaultTimeoutMs;
|
|
42
|
+
private readonly overrideImage?;
|
|
43
|
+
private readonly semaphore;
|
|
44
|
+
private readonly sandboxSize;
|
|
45
|
+
private readonly tmpSize;
|
|
46
|
+
private readonly security;
|
|
47
|
+
private readonly persist;
|
|
48
|
+
private readonly logNetwork;
|
|
49
|
+
private readonly poolStrategy;
|
|
50
|
+
private readonly poolSize;
|
|
51
|
+
private readonly dependencies;
|
|
52
|
+
private readonly auditLogger?;
|
|
53
|
+
private readonly remoteCodePolicy;
|
|
54
|
+
private container;
|
|
55
|
+
private persistentRuntime;
|
|
56
|
+
private pool;
|
|
57
|
+
private readonly imageCache;
|
|
58
|
+
private resolveExecutionRequest;
|
|
59
|
+
/**
|
|
60
|
+
* @param options - Sandbox configuration options.
|
|
61
|
+
* @param maxConcurrent - Maximum number of concurrent executions (controls the internal semaphore).
|
|
62
|
+
*/
|
|
63
|
+
constructor(options?: DockerIsol8Options, maxConcurrent?: number);
|
|
64
|
+
/**
|
|
65
|
+
* Initialize isol8.
|
|
66
|
+
*
|
|
67
|
+
* In ephemeral mode this can optionally pre-warm the container pool.
|
|
68
|
+
* In persistent mode the container is created lazily on first execute.
|
|
69
|
+
*/
|
|
70
|
+
start(options?: StartOptions): Promise<void>;
|
|
71
|
+
/** Stop and remove the container (if one exists). Safe to call multiple times. */
|
|
72
|
+
stop(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Execute code in isol8. Acquires a semaphore permit to enforce
|
|
75
|
+
* the concurrency limit, then delegates to ephemeral or persistent execution.
|
|
76
|
+
*/
|
|
77
|
+
execute(req: ExecutionRequest): Promise<ExecutionResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Record an audit entry for the execution.
|
|
80
|
+
*/
|
|
81
|
+
private recordAudit;
|
|
82
|
+
/**
|
|
83
|
+
* Collect security events from the container (e.g., network filter blocks).
|
|
84
|
+
*/
|
|
85
|
+
private collectSecurityEvents;
|
|
86
|
+
/**
|
|
87
|
+
* Collect network logs from the container (requests made through the proxy).
|
|
88
|
+
*/
|
|
89
|
+
private collectNetworkLogs;
|
|
90
|
+
/**
|
|
91
|
+
* Upload a file into the running container via a tar archive.
|
|
92
|
+
* Only available in persistent mode after at least one `execute()` call.
|
|
93
|
+
*
|
|
94
|
+
* @param path - Absolute path inside the container.
|
|
95
|
+
* @param content - File contents.
|
|
96
|
+
* @throws {Error} If no container is active.
|
|
97
|
+
*/
|
|
98
|
+
putFile(path: string, content: Buffer | string): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Download a file from the running container.
|
|
101
|
+
*
|
|
102
|
+
* @param path - Absolute path inside the container.
|
|
103
|
+
* @returns File contents as a Buffer.
|
|
104
|
+
* @throws {Error} If no container is active.
|
|
105
|
+
*/
|
|
106
|
+
getFile(path: string): Promise<Buffer>;
|
|
107
|
+
/** The Docker container ID, or `null` if no container is active. Used by the server for session tracking. */
|
|
108
|
+
get containerId(): string | null;
|
|
109
|
+
/**
|
|
110
|
+
* Execute code and stream output chunks as they arrive.
|
|
111
|
+
* Yields {@link StreamEvent} objects for stdout, stderr, exit, and error events.
|
|
112
|
+
*/
|
|
113
|
+
executeStream(req: ExecutionRequest): AsyncIterable<StreamEvent>;
|
|
114
|
+
private resolveImage;
|
|
115
|
+
private ensurePool;
|
|
116
|
+
private executeEphemeral;
|
|
117
|
+
private executePersistent;
|
|
118
|
+
private retrieveFiles;
|
|
119
|
+
private getFileFromContainer;
|
|
120
|
+
private startPersistentContainer;
|
|
121
|
+
private getAdapter;
|
|
122
|
+
private buildHostConfig;
|
|
123
|
+
private buildSecurityOpts;
|
|
124
|
+
private loadDefaultSeccompProfile;
|
|
125
|
+
private buildEnv;
|
|
126
|
+
private streamExecOutput;
|
|
127
|
+
private collectExecOutput;
|
|
128
|
+
private postProcessOutput;
|
|
129
|
+
/**
|
|
130
|
+
* Remove all isol8 containers (both running and stopped).
|
|
131
|
+
*
|
|
132
|
+
* This static utility method finds and removes all containers created by isol8,
|
|
133
|
+
* identified by images starting with `isol8:`.
|
|
134
|
+
*
|
|
135
|
+
* @param docker - Optional Docker instance. If not provided, creates a new one.
|
|
136
|
+
* @returns Promise resolving to an object with counts of removed and failed containers.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* import { DockerIsol8 } from "isol8";
|
|
141
|
+
*
|
|
142
|
+
* // Remove all isol8 containers
|
|
143
|
+
* const result = await DockerIsol8.cleanup();
|
|
144
|
+
* console.log(`Removed ${result.removed} containers`);
|
|
145
|
+
* if (result.failed > 0) {
|
|
146
|
+
* console.log(`Failed to remove ${result.failed} containers`);
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
static cleanup(docker?: Docker): Promise<{
|
|
151
|
+
removed: number;
|
|
152
|
+
failed: number;
|
|
153
|
+
errors: string[];
|
|
154
|
+
}>;
|
|
155
|
+
/**
|
|
156
|
+
* Remove all isol8 Docker images.
|
|
157
|
+
*
|
|
158
|
+
* Images are identified by repo tags starting with `isol8:`
|
|
159
|
+
* (for example `isol8:python` or `isol8:python-custom-<hash>`).
|
|
160
|
+
*/
|
|
161
|
+
static cleanupImages(docker?: Docker): Promise<{
|
|
162
|
+
removed: number;
|
|
163
|
+
failed: number;
|
|
164
|
+
errors: string[];
|
|
165
|
+
}>;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=docker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/engine/docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module engine/image-builder
|
|
3
|
+
*
|
|
4
|
+
* Builds Docker images for each supported runtime. Base images are built from
|
|
5
|
+
* the multi-stage `docker/Dockerfile`. Custom images layer user-specified
|
|
6
|
+
* packages on top of the base images.
|
|
7
|
+
*/
|
|
8
|
+
import type Docker from "dockerode";
|
|
9
|
+
import type { Isol8Config } from "../types";
|
|
10
|
+
/**
|
|
11
|
+
* Normalize package lists for stable tags/cache hits.
|
|
12
|
+
* - trims whitespace
|
|
13
|
+
* - removes empty entries
|
|
14
|
+
* - de-duplicates
|
|
15
|
+
* - sorts lexicographically
|
|
16
|
+
*/
|
|
17
|
+
export declare function normalizePackages(packages: string[]): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Returns deterministic custom image tag for a runtime + package set.
|
|
20
|
+
* Uses a short deps hash suffix to avoid tag collisions across different
|
|
21
|
+
* dependency sets for the same runtime.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCustomImageTag(runtime: string, packages: string[]): string;
|
|
24
|
+
/** Progress update emitted during image builds. */
|
|
25
|
+
interface BuildProgress {
|
|
26
|
+
/** Runtime being built (e.g. `"python"`). */
|
|
27
|
+
runtime: string;
|
|
28
|
+
/** Current build status. */
|
|
29
|
+
status: "building" | "done" | "error";
|
|
30
|
+
/** Optional status message (error text, package list, etc). */
|
|
31
|
+
message?: string;
|
|
32
|
+
}
|
|
33
|
+
type ProgressCallback = (progress: BuildProgress) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Builds the base `isol8:<runtime>` images for all registered runtimes.
|
|
36
|
+
* Each image is built from the multi-stage Dockerfile in `docker/`.
|
|
37
|
+
*
|
|
38
|
+
* Uses smart build logic: computes a hash of the docker directory contents
|
|
39
|
+
* and skips builds if the image already exists with matching hash.
|
|
40
|
+
* Cleans up dangling images after rebuilding.
|
|
41
|
+
*
|
|
42
|
+
* @param docker - Dockerode instance.
|
|
43
|
+
* @param onProgress - Optional callback for build progress updates.
|
|
44
|
+
* @param force - If true, always rebuild even if image is up to date.
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildBaseImages(docker: Docker, onProgress?: ProgressCallback, force?: boolean, onlyRuntimes?: string[]): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Builds custom images with user-specified dependencies layered on top of
|
|
49
|
+
* the base images. Reads package lists from the config's `dependencies` field.
|
|
50
|
+
*
|
|
51
|
+
* Uses smart build logic: computes a hash of the dependency list and
|
|
52
|
+
* skips builds if the image already exists with matching hash.
|
|
53
|
+
* Cleans up dangling images after rebuilding.
|
|
54
|
+
*
|
|
55
|
+
* @param docker - Dockerode instance.
|
|
56
|
+
* @param config - Resolved isol8 configuration.
|
|
57
|
+
* @param onProgress - Optional callback for build progress updates.
|
|
58
|
+
* @param force - If true, always rebuild even if image is up to date.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildCustomImages(docker: Docker, config: Isol8Config, onProgress?: ProgressCallback, force?: boolean): Promise<void>;
|
|
61
|
+
export declare function buildCustomImage(docker: Docker, runtime: import("../types").Runtime | string, packages: string[], onProgress?: ProgressCallback, force?: boolean): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Checks if an image exists locally.
|
|
64
|
+
*/
|
|
65
|
+
export declare function imageExists(docker: Docker, imageName: string): Promise<boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Ensures all base images are built.
|
|
68
|
+
*/
|
|
69
|
+
export declare function ensureImages(docker: Docker, onProgress?: ProgressCallback): Promise<void>;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=image-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-builder.d.ts","sourceRoot":"","sources":["../../src/engine/image-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AA6F5C;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAK7E;AAkCD,mDAAmD;AACnD,UAAU,aAAa;IACrB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IACtC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,gBAAgB,GAAG,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,gBAAgB,EAC7B,KAAK,UAAQ,EACb,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,IAAI,CAAC,CAuEf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,UAAU,CAAC,EAAE,gBAAgB,EAC7B,KAAK,UAAQ,GACZ,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,UAAU,EAAE,OAAO,GAAG,MAAM,EAC5C,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,CAAC,EAAE,gBAAgB,EAC7B,KAAK,UAAQ,GACZ,OAAO,CAAC,IAAI,CAAC,CA2Ff;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/F"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module engine/pool
|
|
3
|
+
*
|
|
4
|
+
* Warm container pool for fast ephemeral execution. Pre-creates and
|
|
5
|
+
* starts containers so they're ready for immediate use, eliminating
|
|
6
|
+
* the create+start overhead (~100-200ms per execution).
|
|
7
|
+
*
|
|
8
|
+
* Supports two strategies:
|
|
9
|
+
* - "secure": Clean container before returning (slower but ensures clean state)
|
|
10
|
+
* - "fast": Dual-pool system - instant acquire from clean pool, background cleanup
|
|
11
|
+
*/
|
|
12
|
+
import type Docker from "dockerode";
|
|
13
|
+
/** Configuration for the container pool. */
|
|
14
|
+
export interface PoolOptions {
|
|
15
|
+
/** Docker client instance. */
|
|
16
|
+
docker: Docker;
|
|
17
|
+
/** Pool strategy: "secure" or "fast". @default "fast" */
|
|
18
|
+
poolStrategy?: "secure" | "fast";
|
|
19
|
+
/** Pool size configuration.
|
|
20
|
+
* For "secure" mode: number of containers to keep warm
|
|
21
|
+
* For "fast" mode: { clean: ready containers, dirty: being cleaned }
|
|
22
|
+
* @default 1 (for fast mode: { clean: 1, dirty: 1 })
|
|
23
|
+
*/
|
|
24
|
+
poolSize?: number | {
|
|
25
|
+
clean: number;
|
|
26
|
+
dirty: number;
|
|
27
|
+
};
|
|
28
|
+
/** Container creation options (HostConfig, Env, etc). */
|
|
29
|
+
createOptions: Omit<Docker.ContainerCreateOptions, "Image">;
|
|
30
|
+
/** Network mode to determine if iptables cleanup is needed. */
|
|
31
|
+
networkMode: "none" | "host" | "filtered";
|
|
32
|
+
/** Security mode - if strict, run process cleanup between executions */
|
|
33
|
+
securityMode: "strict" | "unconfined" | "custom";
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A per-image warm container pool. Maintains pre-started containers
|
|
37
|
+
* ready for immediate exec, recycling them after use.
|
|
38
|
+
*
|
|
39
|
+
* Supports two strategies:
|
|
40
|
+
* - "secure": Single pool, cleanup in acquire (current behavior)
|
|
41
|
+
* - "fast": Dual pools (clean/dirty), instant acquire, background cleanup
|
|
42
|
+
*/
|
|
43
|
+
export declare class ContainerPool {
|
|
44
|
+
private readonly docker;
|
|
45
|
+
private readonly poolStrategy;
|
|
46
|
+
private readonly cleanPoolSize;
|
|
47
|
+
private readonly dirtyPoolSize;
|
|
48
|
+
private readonly createOptions;
|
|
49
|
+
private readonly networkMode;
|
|
50
|
+
private readonly securityMode;
|
|
51
|
+
private readonly pools;
|
|
52
|
+
private readonly replenishing;
|
|
53
|
+
private readonly pendingReplenishments;
|
|
54
|
+
private cleaningInterval;
|
|
55
|
+
constructor(options: PoolOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Acquire a started container for the given image.
|
|
58
|
+
* - "secure" mode: Clean container before returning
|
|
59
|
+
* - "fast" mode: Instant return from clean pool, create new if empty
|
|
60
|
+
*/
|
|
61
|
+
acquire(image: string): Promise<Docker.Container>;
|
|
62
|
+
/**
|
|
63
|
+
* Return a container to the pool.
|
|
64
|
+
* - "secure" mode: Add to pool, cleanup happens on next acquire
|
|
65
|
+
* - "fast" mode: Add to dirty pool for background cleaning
|
|
66
|
+
*/
|
|
67
|
+
release(container: Docker.Container, image: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Start background cleaning for fast mode.
|
|
70
|
+
* Runs every 5 seconds to clean dirty containers.
|
|
71
|
+
*/
|
|
72
|
+
private startBackgroundCleaning;
|
|
73
|
+
/**
|
|
74
|
+
* Clean a dirty container immediately and add to clean pool.
|
|
75
|
+
*/
|
|
76
|
+
private cleanDirtyImmediate;
|
|
77
|
+
private cleanupContainer;
|
|
78
|
+
/**
|
|
79
|
+
* Pre-warm the pool for a specific image.
|
|
80
|
+
*/
|
|
81
|
+
warm(image: string): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Stop the pool and clean up resources.
|
|
84
|
+
* Alias for drain() - destroys all containers and stops background cleaning.
|
|
85
|
+
*/
|
|
86
|
+
stop(): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Destroy all pooled containers and clear the pool.
|
|
89
|
+
*/
|
|
90
|
+
drain(): Promise<void>;
|
|
91
|
+
private createContainer;
|
|
92
|
+
private replenish;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/engine/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAGpC,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,yDAAyD;IACzD,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;IAC5D,+DAA+D;IAC/D,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAC1C,wEAAwE;IACxE,YAAY,EAAE,QAAQ,GAAG,YAAY,GAAG,QAAQ,CAAC;CAClD;AAYD;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IACjD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA+C;IAC7E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqC;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA4B;IAClE,OAAO,CAAC,gBAAgB,CAA+C;gBAE3D,OAAO,EAAE,WAAW;IA0BhC;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;IAkDvD;;;;OAIG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCxE;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAoB/B;;OAEG;YACW,mBAAmB;YAenB,gBAAgB;IA4B9B;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCxC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAyBd,eAAe;IAW7B,OAAO,CAAC,SAAS;CAsDlB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module engine/stats
|
|
3
|
+
*
|
|
4
|
+
* Resource usage statistics collection from Docker containers.
|
|
5
|
+
* Uses dockerode's container.stats() API to get CPU, memory, and network metrics.
|
|
6
|
+
*/
|
|
7
|
+
import type Docker from "dockerode";
|
|
8
|
+
/**
|
|
9
|
+
* Resource usage metrics for a container execution.
|
|
10
|
+
*/
|
|
11
|
+
export interface ContainerResourceUsage {
|
|
12
|
+
/** CPU usage as percentage (0-100 * num_cores) */
|
|
13
|
+
cpuPercent: number;
|
|
14
|
+
/** Current memory usage in megabytes */
|
|
15
|
+
memoryMB: number;
|
|
16
|
+
/** Peak memory usage in megabytes (if tracked) */
|
|
17
|
+
peakMemoryMB?: number;
|
|
18
|
+
/** Bytes received during execution */
|
|
19
|
+
networkBytesIn: number;
|
|
20
|
+
/** Bytes sent during execution */
|
|
21
|
+
networkBytesOut: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get resource usage snapshot for a container.
|
|
25
|
+
*
|
|
26
|
+
* @param container - Docker container instance
|
|
27
|
+
* @returns Resource usage metrics
|
|
28
|
+
*/
|
|
29
|
+
export declare function getContainerStats(container: Docker.Container): Promise<ContainerResourceUsage>;
|
|
30
|
+
/**
|
|
31
|
+
* Calculate resource usage delta between two stat snapshots.
|
|
32
|
+
* Useful for getting per-execution metrics.
|
|
33
|
+
*/
|
|
34
|
+
export declare function calculateResourceDelta(before: ContainerResourceUsage, after: ContainerResourceUsage): ContainerResourceUsage;
|
|
35
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/engine/stats.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,eAAe,EAAE,MAAM,CAAC;CACzB;AA+ED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,CAAC,SAAS,GAC1B,OAAO,CAAC,sBAAsB,CAAC,CAgBjC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,sBAAsB,EAC9B,KAAK,EAAE,sBAAsB,GAC5B,sBAAsB,CAUxB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module engine/utils
|
|
3
|
+
*
|
|
4
|
+
* Low-level utility functions used by the Docker engine: memory parsing,
|
|
5
|
+
* output truncation, secret masking, and POSIX tar archive creation/extraction.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parses a human-readable memory limit string into bytes.
|
|
9
|
+
*
|
|
10
|
+
* @param limit - Memory string (e.g. `"512m"`, `"1g"`, `"256k"`, `"1024"`).
|
|
11
|
+
* @returns The limit in bytes.
|
|
12
|
+
* @throws {Error} If the format is invalid.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* parseMemoryLimit("512m"); // 536870912
|
|
17
|
+
* parseMemoryLimit("1g"); // 1073741824
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseMemoryLimit(limit: string): number;
|
|
21
|
+
/**
|
|
22
|
+
* Truncates output to a maximum byte length. If truncated, appends a
|
|
23
|
+
* summary line indicating the original and limit sizes.
|
|
24
|
+
*
|
|
25
|
+
* @param output - The full output string.
|
|
26
|
+
* @param maxBytes - Maximum allowed byte length.
|
|
27
|
+
* @returns Object with the (possibly truncated) text and a truncation flag.
|
|
28
|
+
*/
|
|
29
|
+
export declare function truncateOutput(output: string, maxBytes: number): {
|
|
30
|
+
text: string;
|
|
31
|
+
truncated: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Replaces all occurrences of secret values in a string with `***`.
|
|
35
|
+
* Empty secret values are skipped.
|
|
36
|
+
*
|
|
37
|
+
* @param text - The text to sanitize.
|
|
38
|
+
* @param secrets - Map of secret names to values.
|
|
39
|
+
* @returns The sanitized text.
|
|
40
|
+
*/
|
|
41
|
+
export declare function maskSecrets(text: string, secrets: Record<string, string>): string;
|
|
42
|
+
/**
|
|
43
|
+
* Creates a POSIX tar archive buffer containing a single file.
|
|
44
|
+
*
|
|
45
|
+
* Uses a minimal tar header (512-byte blocks) followed by data blocks
|
|
46
|
+
* and a 1024-byte end-of-archive marker.
|
|
47
|
+
*
|
|
48
|
+
* @param filePath - Path for the file inside the archive (leading `/` is stripped).
|
|
49
|
+
* @param content - File contents as a string or Buffer.
|
|
50
|
+
* @returns A Buffer containing the complete tar archive.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createTarBuffer(filePath: string, content: Buffer | string): Buffer;
|
|
53
|
+
/**
|
|
54
|
+
* Extracts a single file from a tar archive buffer.
|
|
55
|
+
*
|
|
56
|
+
* @param tarBuffer - The tar archive buffer.
|
|
57
|
+
* @param targetPath - Path of the file to extract (leading `/` is stripped for matching).
|
|
58
|
+
* @returns The extracted file contents as a Buffer.
|
|
59
|
+
* @throws {Error} If the file is not found in the archive.
|
|
60
|
+
*/
|
|
61
|
+
export declare function extractFromTar(tarBuffer: Buffer, targetPath: string): Buffer;
|
|
62
|
+
/**
|
|
63
|
+
* Validates a package name to prevent command injection.
|
|
64
|
+
* allow alphanumeric, dash, underscore, dot, @, / (for scoped packages), and = (for versions)
|
|
65
|
+
*
|
|
66
|
+
* @param name - The package name to validate.
|
|
67
|
+
* @returns The name if valid.
|
|
68
|
+
* @throws {Error} If the name contains invalid characters.
|
|
69
|
+
*/
|
|
70
|
+
export declare function validatePackageName(name: string): string;
|
|
71
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/engine/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAetC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAQjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CA8ClF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAoC5E;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQxD"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @isol8/core
|
|
3
|
+
*
|
|
4
|
+
* Public API for the isol8 secure code execution engine.
|
|
5
|
+
* Import from `"@isol8/core"` to access the engine, client, config, runtime registry.
|
|
6
|
+
*/
|
|
7
|
+
export type { RemoteIsol8Options } from "./client/remote";
|
|
8
|
+
export { RemoteIsol8 } from "./client/remote";
|
|
9
|
+
export { loadConfig } from "./config";
|
|
10
|
+
export { Semaphore } from "./engine/concurrency";
|
|
11
|
+
export type { DockerIsol8Options } from "./engine/docker";
|
|
12
|
+
export { DockerIsol8 } from "./engine/docker";
|
|
13
|
+
export { buildBaseImages, buildCustomImages } from "./engine/image-builder";
|
|
14
|
+
export { BunAdapter, bashAdapter, DenoAdapter, NodeAdapter, PythonAdapter, RuntimeRegistry, } from "./runtime";
|
|
15
|
+
export type { RuntimeAdapter } from "./runtime/adapter";
|
|
16
|
+
export type { ExecutionRequest, ExecutionResult, Isol8Config, Isol8Engine, Isol8Mode, Isol8Options, NetworkFilterConfig, NetworkMode, RemoteCodePolicy, Runtime, StreamEvent, } from "./types";
|
|
17
|
+
export { logger } from "./utils/logger";
|
|
18
|
+
export { VERSION } from "./version";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE5E,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,aAAa,EACb,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|