@secure-exec/core 0.2.0-rc.2 → 0.2.1-rc.1

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 (53) hide show
  1. package/dist/generated/isolate-runtime.d.ts +1 -1
  2. package/dist/generated/isolate-runtime.js +1 -1
  3. package/dist/index.d.ts +17 -4
  4. package/dist/index.js +10 -2
  5. package/dist/isolate-runtime/require-setup.js +145 -7
  6. package/dist/kernel/device-backend.d.ts +14 -0
  7. package/dist/kernel/device-backend.js +251 -0
  8. package/dist/kernel/device-layer.js +9 -0
  9. package/dist/kernel/index.d.ts +4 -4
  10. package/dist/kernel/index.js +3 -3
  11. package/dist/kernel/kernel.js +141 -119
  12. package/dist/kernel/mount-table.d.ts +75 -0
  13. package/dist/kernel/mount-table.js +353 -0
  14. package/dist/kernel/permissions.d.ts +9 -0
  15. package/dist/kernel/permissions.js +33 -1
  16. package/dist/kernel/proc-backend.d.ts +30 -0
  17. package/dist/kernel/proc-backend.js +428 -0
  18. package/dist/kernel/proc-layer.js +6 -0
  19. package/dist/kernel/process-table.d.ts +3 -1
  20. package/dist/kernel/process-table.js +23 -3
  21. package/dist/kernel/pty.d.ts +3 -2
  22. package/dist/kernel/pty.js +13 -2
  23. package/dist/kernel/types.d.ts +45 -4
  24. package/dist/kernel/types.js +9 -0
  25. package/dist/kernel/vfs.d.ts +30 -2
  26. package/dist/kernel/vfs.js +19 -2
  27. package/dist/shared/api-types.d.ts +6 -0
  28. package/dist/shared/console-formatter.js +8 -8
  29. package/dist/shared/in-memory-fs.d.ts +14 -62
  30. package/dist/shared/in-memory-fs.js +101 -636
  31. package/dist/shared/permissions.js +5 -0
  32. package/dist/test/block-store-conformance.d.ts +34 -0
  33. package/dist/test/block-store-conformance.js +251 -0
  34. package/dist/test/metadata-store-conformance.d.ts +37 -0
  35. package/dist/test/metadata-store-conformance.js +646 -0
  36. package/dist/test/vfs-conformance.d.ts +65 -0
  37. package/dist/test/vfs-conformance.js +842 -0
  38. package/dist/types.d.ts +1 -0
  39. package/dist/vfs/chunked-vfs.d.ts +66 -0
  40. package/dist/vfs/chunked-vfs.js +1290 -0
  41. package/dist/vfs/host-block-store.d.ts +19 -0
  42. package/dist/vfs/host-block-store.js +97 -0
  43. package/dist/vfs/memory-block-store.d.ts +16 -0
  44. package/dist/vfs/memory-block-store.js +45 -0
  45. package/dist/vfs/memory-metadata.d.ts +75 -0
  46. package/dist/vfs/memory-metadata.js +528 -0
  47. package/dist/vfs/sqlite-metadata.d.ts +91 -0
  48. package/dist/vfs/sqlite-metadata.js +582 -0
  49. package/dist/vfs/types.d.ts +210 -0
  50. package/dist/vfs/types.js +8 -0
  51. package/package.json +20 -1
  52. package/dist/kernel/inode-table.d.ts +0 -43
  53. package/dist/kernel/inode-table.js +0 -85
@@ -6,6 +6,27 @@
6
6
  */
7
7
  import type { WaitQueue } from "./wait.js";
8
8
  export type { VirtualFileSystem, VirtualDirEntry, VirtualStat, } from "./vfs.js";
9
+ /**
10
+ * Minimal structured logger interface for kernel diagnostics.
11
+ * Compatible with pino and any logger that supports child loggers.
12
+ * The kernel never depends on pino directly — embedders pass their own logger.
13
+ */
14
+ export interface KernelLogger {
15
+ trace(obj: Record<string, unknown>, msg?: string): void;
16
+ debug(obj: Record<string, unknown>, msg?: string): void;
17
+ info(obj: Record<string, unknown>, msg?: string): void;
18
+ warn(obj: Record<string, unknown>, msg?: string): void;
19
+ error(obj: Record<string, unknown>, msg?: string): void;
20
+ child(bindings: Record<string, unknown>): KernelLogger;
21
+ }
22
+ /** No-op logger that discards all records. */
23
+ export declare const noopKernelLogger: KernelLogger;
24
+ /** A filesystem to mount at a specific path inside the kernel VFS. */
25
+ export interface FsMount {
26
+ path: string;
27
+ fs: import("./vfs.js").VirtualFileSystem;
28
+ readOnly?: boolean;
29
+ }
9
30
  export interface KernelOptions {
10
31
  filesystem: import("./vfs.js").VirtualFileSystem;
11
32
  permissions?: Permissions;
@@ -15,6 +36,10 @@ export interface KernelOptions {
15
36
  maxProcesses?: number;
16
37
  /** Host network adapter for external socket routing (TCP, UDP, DNS). */
17
38
  hostNetworkAdapter?: import("./host-adapter.js").HostNetworkAdapter;
39
+ /** Structured debug logger for kernel diagnostics. Defaults to silent no-op. */
40
+ logger?: KernelLogger;
41
+ /** Additional filesystems to mount at boot (after /dev and /proc). */
42
+ mounts?: FsMount[];
18
43
  }
19
44
  export interface Kernel {
20
45
  /** Mount a runtime driver. Calls driver.init() and registers its commands. */
@@ -49,15 +74,23 @@ export interface Kernel {
49
74
  * Returns the shell exit code.
50
75
  */
51
76
  connectTerminal(options?: ConnectTerminalOptions): Promise<number>;
77
+ /** Mount a filesystem at the given path. */
78
+ mountFs(path: string, fs: import("./vfs.js").VirtualFileSystem, options?: {
79
+ readOnly?: boolean;
80
+ }): void;
81
+ /** Unmount the filesystem at the given path. */
82
+ unmountFs(path: string): void;
52
83
  readFile(path: string): Promise<Uint8Array>;
53
84
  writeFile(path: string, content: string | Uint8Array): Promise<void>;
54
85
  mkdir(path: string): Promise<void>;
55
86
  readdir(path: string): Promise<string[]>;
56
87
  stat(path: string): Promise<import("./vfs.js").VirtualStat>;
57
88
  exists(path: string): Promise<boolean>;
89
+ removeFile(path: string): Promise<void>;
90
+ removeDir(path: string): Promise<void>;
91
+ rename(oldPath: string, newPath: string): Promise<void>;
58
92
  readonly socketTable: import("./socket-table.js").SocketTable;
59
93
  readonly timerTable: import("./timer-table.js").TimerTable;
60
- readonly inodeTable: import("./inode-table.js").InodeTable;
61
94
  readonly commands: ReadonlyMap<string, string>;
62
95
  readonly processes: ReadonlyMap<number, ProcessInfo>;
63
96
  /** Number of pending zombie cleanup timers (test observability). */
@@ -84,6 +117,8 @@ export interface SpawnOptions extends ExecOptions {
84
117
  stdoutFd?: number;
85
118
  /** FD in caller's table to wire as child's stderr (pipe write end). */
86
119
  stderrFd?: number;
120
+ /** Enable streaming stdin: writeStdin() delivers data immediately instead of buffering until closeStdin(). */
121
+ streamStdin?: boolean;
87
122
  }
88
123
  export interface ManagedProcess {
89
124
  pid: number;
@@ -172,6 +207,8 @@ export interface ProcessContext {
172
207
  stdinIsTTY?: boolean;
173
208
  stdoutIsTTY?: boolean;
174
209
  stderrIsTTY?: boolean;
210
+ /** Enable streaming stdin delivery (writeStdin data arrives immediately). */
211
+ streamStdin?: boolean;
175
212
  /** Kernel-provided callback for stdout data emitted during spawn. */
176
213
  onStdout?: (data: Uint8Array) => void;
177
214
  /** Kernel-provided callback for stderr data emitted during spawn. */
@@ -292,8 +329,6 @@ export interface FDStat {
292
329
  export interface FileDescription {
293
330
  id: number;
294
331
  path: string;
295
- /** Stable inode identity for FD I/O after the pathname is unlinked. */
296
- inode?: number;
297
332
  cursor: bigint;
298
333
  flags: number;
299
334
  refCount: number;
@@ -348,6 +383,8 @@ export interface ProcessEntry {
348
383
  exitReason: "normal" | "signal" | null;
349
384
  /** Signal that killed the process (0 = normal exit). */
350
385
  termSignal: number;
386
+ /** Epoch ms when the process was registered. */
387
+ startTime: number;
351
388
  exitTime: number | null;
352
389
  env: Record<string, string>;
353
390
  cwd: string;
@@ -368,11 +405,15 @@ export interface ProcessInfo {
368
405
  sid: number;
369
406
  driver: string;
370
407
  command: string;
408
+ args: string[];
409
+ cwd: string;
371
410
  status: "running" | "stopped" | "exited";
372
411
  exitCode: number | null;
412
+ startTime: number;
413
+ exitTime: number | null;
373
414
  }
374
415
  /** POSIX error codes used by the kernel. */
375
- export type KernelErrorCode = "EACCES" | "EADDRINUSE" | "EAGAIN" | "EBADF" | "ECONNREFUSED" | "EINPROGRESS" | "EINTR" | "EEXIST" | "EINVAL" | "EIO" | "EISDIR" | "EMFILE" | "EMSGSIZE" | "ENOENT" | "ENOSPC" | "ENOSYS" | "ENOTCONN" | "ENOTEMPTY" | "ENOTDIR" | "EPERM" | "EPIPE" | "ESPIPE" | "ESRCH" | "ETIMEDOUT";
416
+ export type KernelErrorCode = "EACCES" | "EADDRINUSE" | "EAGAIN" | "EBADF" | "ECONNREFUSED" | "EINPROGRESS" | "EINTR" | "EEXIST" | "EINVAL" | "ELOOP" | "EIO" | "EISDIR" | "EMFILE" | "EMSGSIZE" | "ENOENT" | "ENOSPC" | "ENOSYS" | "ENOTCONN" | "ENOTEMPTY" | "ENOTDIR" | "EPERM" | "EPIPE" | "EROFS" | "ESPIPE" | "ESRCH" | "ETIMEDOUT" | "EXDEV";
376
417
  /**
377
418
  * Structured error for kernel operations.
378
419
  * Carries a machine-readable `code` so callers can map to errno without
@@ -4,6 +4,15 @@
4
4
  * The kernel is the shared OS layer. All runtimes make "syscalls" to the
5
5
  * kernel for filesystem, process, pipe, and FD operations.
6
6
  */
7
+ /** No-op logger that discards all records. */
8
+ export const noopKernelLogger = {
9
+ trace() { },
10
+ debug() { },
11
+ info() { },
12
+ warn() { },
13
+ error() { },
14
+ child() { return noopKernelLogger; },
15
+ };
7
16
  // FD open flags
8
17
  export const O_RDONLY = 0;
9
18
  export const O_WRONLY = 1;
@@ -2,8 +2,25 @@
2
2
  * Virtual Filesystem interface.
3
3
  *
4
4
  * POSIX-complete interface that all filesystem backends must implement.
5
- * Extends the original secure-exec VirtualFileSystem with symlinks,
6
- * links, permissions, and metadata operations needed by WasmVM's WASI polyfill.
5
+ * The primary implementation is ChunkedVFS, which composes an FsMetadataStore
6
+ * (directory tree, inodes, chunk mapping) with an FsBlockStore (key-value blob
7
+ * store) to provide tiered storage with optional write buffering and versioning.
8
+ *
9
+ * Error behavior (KernelError codes):
10
+ * - ENOENT: path does not exist (readFile, stat, pread, pwrite, truncate, readlink, etc.)
11
+ * - EISDIR: operation targets a directory when a file is expected (readFile, pread, pwrite)
12
+ * - ENOTDIR: intermediate path component is not a directory
13
+ * - EEXIST: target already exists (createDir without recursive, link to existing)
14
+ * - ELOOP: symlink resolution exceeds 40 levels
15
+ * - ENOTEMPTY: removeDir on non-empty directory
16
+ * - EPERM: link to directory
17
+ * - EXDEV: cross-mount copy (raised by MountTable, not VFS directly)
18
+ *
19
+ * Optional methods (fsync, copy, readDirStat) may be absent. The kernel and
20
+ * MountTable use optional chaining and provide fallbacks where needed.
21
+ *
22
+ * Usage: create via `createChunkedVfs()` from `./vfs/chunked-vfs.ts`, or use
23
+ * `createInMemoryFileSystem()` from the package root for the default in-memory VFS.
7
24
  */
8
25
  export interface VirtualDirEntry {
9
26
  name: string;
@@ -11,6 +28,9 @@ export interface VirtualDirEntry {
11
28
  isSymbolicLink?: boolean;
12
29
  ino?: number;
13
30
  }
31
+ export interface VirtualDirStatEntry extends VirtualDirEntry {
32
+ stat: VirtualStat;
33
+ }
14
34
  export interface VirtualStat {
15
35
  mode: number;
16
36
  size: number;
@@ -51,4 +71,12 @@ export interface VirtualFileSystem {
51
71
  truncate(path: string, length: number): Promise<void>;
52
72
  /** Read a range from a file without loading the entire file into memory. */
53
73
  pread(path: string, offset: number, length: number): Promise<Uint8Array>;
74
+ /** Write data at a specific offset without replacing the entire file. */
75
+ pwrite(path: string, offset: number, data: Uint8Array): Promise<void>;
76
+ /** Flush buffered writes for the given path to durable storage. */
77
+ fsync?(path: string): Promise<void>;
78
+ /** Copy a file within the same filesystem. */
79
+ copy?(srcPath: string, dstPath: string): Promise<void>;
80
+ /** Combined readdir + stat. Avoids N+1 queries for directory listings. */
81
+ readDirStat?(path: string): Promise<VirtualDirStatEntry[]>;
54
82
  }
@@ -2,7 +2,24 @@
2
2
  * Virtual Filesystem interface.
3
3
  *
4
4
  * POSIX-complete interface that all filesystem backends must implement.
5
- * Extends the original secure-exec VirtualFileSystem with symlinks,
6
- * links, permissions, and metadata operations needed by WasmVM's WASI polyfill.
5
+ * The primary implementation is ChunkedVFS, which composes an FsMetadataStore
6
+ * (directory tree, inodes, chunk mapping) with an FsBlockStore (key-value blob
7
+ * store) to provide tiered storage with optional write buffering and versioning.
8
+ *
9
+ * Error behavior (KernelError codes):
10
+ * - ENOENT: path does not exist (readFile, stat, pread, pwrite, truncate, readlink, etc.)
11
+ * - EISDIR: operation targets a directory when a file is expected (readFile, pread, pwrite)
12
+ * - ENOTDIR: intermediate path component is not a directory
13
+ * - EEXIST: target already exists (createDir without recursive, link to existing)
14
+ * - ELOOP: symlink resolution exceeds 40 levels
15
+ * - ENOTEMPTY: removeDir on non-empty directory
16
+ * - EPERM: link to directory
17
+ * - EXDEV: cross-mount copy (raised by MountTable, not VFS directly)
18
+ *
19
+ * Optional methods (fsync, copy, readDirStat) may be absent. The kernel and
20
+ * MountTable use optional chaining and provide fallbacks where needed.
21
+ *
22
+ * Usage: create via `createChunkedVfs()` from `./vfs/chunked-vfs.ts`, or use
23
+ * `createInMemoryFileSystem()` from the package root for the default in-memory VFS.
7
24
  */
8
25
  export {};
@@ -29,6 +29,10 @@ export interface ProcessConfig {
29
29
  stdoutIsTTY?: boolean;
30
30
  /** Whether stderr is a TTY (PTY slave attached) */
31
31
  stderrIsTTY?: boolean;
32
+ /** Terminal columns (from PTY dimensions). */
33
+ cols?: number;
34
+ /** Terminal rows (from PTY dimensions). */
35
+ rows?: number;
32
36
  }
33
37
  export interface OSConfig {
34
38
  platform?: string;
@@ -72,6 +76,8 @@ export interface ExecOptions {
72
76
  timingMitigation?: TimingMitigation;
73
77
  /** Optional streaming hook for console output events */
74
78
  onStdio?: StdioHook;
79
+ /** Override execution mode. 'run' mode processes async operations (timers, network). */
80
+ mode?: "exec" | "run";
75
81
  }
76
82
  export interface ExecResult extends ExecutionStatus {
77
83
  }
@@ -148,14 +148,14 @@ export function getConsoleSetupCode(budget = DEFAULT_CONSOLE_SERIALIZATION_BUDGE
148
148
  const formatConsoleArgs = ${formatConsoleArgs.toString()};
149
149
 
150
150
  globalThis.console = {
151
- log: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
152
- error: (...args) => _error(formatConsoleArgs(args, __consoleBudget)),
153
- warn: (...args) => _error(formatConsoleArgs(args, __consoleBudget)),
154
- info: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
155
- debug: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
156
- trace: (...args) => _error(formatConsoleArgs(args, __consoleBudget)),
157
- dir: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
158
- table: (...args) => _log(formatConsoleArgs(args, __consoleBudget)),
151
+ log: (...args) => _log(formatConsoleArgs(args, __consoleBudget) + "\\n"),
152
+ error: (...args) => _error(formatConsoleArgs(args, __consoleBudget) + "\\n"),
153
+ warn: (...args) => _error(formatConsoleArgs(args, __consoleBudget) + "\\n"),
154
+ info: (...args) => _log(formatConsoleArgs(args, __consoleBudget) + "\\n"),
155
+ debug: (...args) => _log(formatConsoleArgs(args, __consoleBudget) + "\\n"),
156
+ trace: (...args) => _error(formatConsoleArgs(args, __consoleBudget) + "\\n"),
157
+ dir: (...args) => _log(formatConsoleArgs(args, __consoleBudget) + "\\n"),
158
+ table: (...args) => _log(formatConsoleArgs(args, __consoleBudget) + "\\n"),
159
159
  };
160
160
  `;
161
161
  }
@@ -1,64 +1,16 @@
1
- import { InodeTable } from "../kernel/inode-table.js";
2
- import type { VirtualDirEntry, VirtualFileSystem, VirtualStat } from "../kernel/vfs.js";
3
1
  /**
4
- * A fully in-memory VirtualFileSystem backed by inode-aware Maps.
5
- * Used as the default filesystem for the browser sandbox and for tests.
6
- * Paths are always POSIX-style (forward slashes, rooted at "/").
2
+ * Factory for creating an in-memory VirtualFileSystem backed by ChunkedVFS.
3
+ *
4
+ * Replaces the old monolithic InMemoryFileSystem with
5
+ * ChunkedVFS(InMemoryMetadataStore + InMemoryBlockStore).
7
6
  */
8
- export declare class InMemoryFileSystem implements VirtualFileSystem {
9
- private inodeTable;
10
- private files;
11
- private fileContents;
12
- private dirs;
13
- private symlinks;
14
- constructor(inodeTable?: InodeTable);
15
- setInodeTable(inodeTable: InodeTable): void;
16
- getInodeForPath(path: string): number | null;
17
- readFileByInode(ino: number): Uint8Array;
18
- writeFileByInode(ino: number, content: Uint8Array): void;
19
- preadByInode(ino: number, offset: number, length: number): Uint8Array;
20
- statByInode(ino: number): VirtualStat;
21
- deleteInodeData(ino: number): void;
22
- private listDirEntries;
23
- readFile(path: string): Promise<Uint8Array>;
24
- readTextFile(path: string): Promise<string>;
25
- readDir(path: string): Promise<string[]>;
26
- readDirWithTypes(path: string): Promise<VirtualDirEntry[]>;
27
- writeFile(path: string, content: string | Uint8Array): Promise<void>;
28
- prepareOpenSync(path: string, flags: number): boolean;
29
- createDir(path: string): Promise<void>;
30
- mkdir(path: string, _options?: {
31
- recursive?: boolean;
32
- }): Promise<void>;
33
- private resolveIfSymlink;
34
- private resolveSymlink;
35
- private statForInode;
36
- private statEntry;
37
- exists(path: string): Promise<boolean>;
38
- stat(path: string): Promise<VirtualStat>;
39
- removeFile(path: string): Promise<void>;
40
- removeDir(path: string): Promise<void>;
41
- rename(oldPath: string, newPath: string): Promise<void>;
42
- symlink(target: string, linkPath: string): Promise<void>;
43
- readlink(path: string): Promise<string>;
44
- lstat(path: string): Promise<VirtualStat>;
45
- link(oldPath: string, newPath: string): Promise<void>;
46
- chmod(path: string, mode: number): Promise<void>;
47
- chown(path: string, uid: number, gid: number): Promise<void>;
48
- utimes(path: string, atime: number, mtime: number): Promise<void>;
49
- realpath(path: string): Promise<string>;
50
- pread(path: string, offset: number, length: number): Promise<Uint8Array>;
51
- truncate(path: string, length: number): Promise<void>;
52
- private reindexInodes;
53
- private cloneInode;
54
- private allocateFileInode;
55
- private allocateDirectoryInode;
56
- private allocateSymlinkInode;
57
- private updateFileMetadata;
58
- private requirePathInode;
59
- private requireFileInode;
60
- private requireInode;
61
- private ensureDirectory;
62
- private adjustParentDirectoryLinkCount;
63
- }
64
- export declare function createInMemoryFileSystem(): InMemoryFileSystem;
7
+ import type { VirtualFileSystem } from "../kernel/vfs.js";
8
+ /**
9
+ * Create an in-memory VirtualFileSystem using the chunked storage architecture.
10
+ *
11
+ * The returned VFS stores all data in memory via InMemoryMetadataStore and
12
+ * InMemoryBlockStore, composed through ChunkedVFS. It also includes a
13
+ * synchronous `prepareOpenSync` method used by the kernel for O_CREAT/O_EXCL/O_TRUNC
14
+ * handling during fdOpen.
15
+ */
16
+ export declare function createInMemoryFileSystem(): VirtualFileSystem;