@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
package/dist/index.d.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  export { createKernel } from "./kernel/kernel.js";
2
- export type { Kernel, KernelOptions, KernelInterface, ExecOptions as KernelExecOptions, ExecResult as KernelExecResult, SpawnOptions as KernelSpawnOptions, ManagedProcess, RuntimeDriver as KernelRuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, Permissions, } from "./kernel/types.js";
3
- export { KernelError, defaultTermios } from "./kernel/types.js";
4
- export type { VirtualFileSystem, VirtualDirEntry, VirtualStat, } from "./kernel/vfs.js";
2
+ export type { FsMount, Kernel, KernelOptions, KernelInterface, KernelLogger, ExecOptions as KernelExecOptions, ExecResult as KernelExecResult, SpawnOptions as KernelSpawnOptions, ManagedProcess, RuntimeDriver as KernelRuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, Permissions, } from "./kernel/types.js";
3
+ export { KernelError, defaultTermios, noopKernelLogger } from "./kernel/types.js";
4
+ export type { VirtualFileSystem, VirtualDirEntry, VirtualDirStatEntry, VirtualStat, } from "./kernel/vfs.js";
5
5
  export { FDTableManager, ProcessFDTable } from "./kernel/fd-table.js";
6
6
  export { ProcessTable } from "./kernel/process-table.js";
7
7
  export { TimerTable } from "./kernel/timer-table.js";
8
8
  export type { KernelTimer, TimerTableOptions } from "./kernel/timer-table.js";
9
+ export { createDeviceBackend } from "./kernel/device-backend.js";
9
10
  export { createDeviceLayer } from "./kernel/device-layer.js";
11
+ export { MountTable } from "./kernel/mount-table.js";
12
+ export type { MountEntry, MountOptions } from "./kernel/mount-table.js";
10
13
  export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./kernel/proc-layer.js";
14
+ export { createProcBackend } from "./kernel/proc-backend.js";
15
+ export type { ProcBackendOptions } from "./kernel/proc-backend.js";
11
16
  export { PipeManager } from "./kernel/pipe-manager.js";
12
17
  export { PtyManager } from "./kernel/pty.js";
13
18
  export type { LineDisciplineConfig } from "./kernel/pty.js";
@@ -25,7 +30,7 @@ export type { CommandExecutor, NetworkAdapter, NetworkServerAddress, NetworkServ
25
30
  export type { DriverRuntimeConfig, NodeRuntimeDriver, NodeRuntimeDriverFactory, PythonRuntimeDriver, PythonRuntimeDriverFactory, ResourceBudgets, RuntimeDriver, RuntimeDriverFactory, RuntimeDriverOptions, SharedRuntimeDriver, SystemDriver, } from "./runtime-driver.js";
26
31
  export type { ExecOptions, ExecResult, ExecutionStatus, OSConfig, ProcessConfig, PythonRunOptions, PythonRunResult, RunResult, StdioChannel, StdioEvent, StdioHook, TimingMitigation, } from "./shared/api-types.js";
27
32
  export { TIMEOUT_EXIT_CODE, TIMEOUT_ERROR_MESSAGE, } from "./shared/constants.js";
28
- export { createInMemoryFileSystem, InMemoryFileSystem, } from "./shared/in-memory-fs.js";
33
+ export { createInMemoryFileSystem } from "./shared/in-memory-fs.js";
29
34
  export { allowAll, allowAllChildProcess, allowAllEnv, allowAllFs, allowAllNetwork, createCommandExecutorStub, createFsStub, createNetworkStub, envAccessAllowed, filterEnv, wrapCommandExecutor, wrapFileSystem, wrapNetworkAdapter, } from "./shared/permissions.js";
30
35
  export type { SystemError } from "./shared/errors.js";
31
36
  export { createEaccesError, createEnosysError, createSystemError, } from "./shared/errors.js";
@@ -40,6 +45,14 @@ export { exposeCustomGlobal, exposeGlobalBinding, exposeMutableRuntimeStateGloba
40
45
  export type { IsolateRuntimeSourceId } from "./generated/isolate-runtime.js";
41
46
  export { getIsolateRuntimeSource, ISOLATE_RUNTIME_SOURCES, } from "./generated/isolate-runtime.js";
42
47
  export { POLYFILL_CODE_MAP } from "./generated/polyfills.js";
48
+ export type { InodeType, CreateInodeAttrs, InodeMeta, DentryInfo, DentryStatInfo, FsMetadataStore, FsBlockStore, FsMetadataStoreVersioning, VersionMeta, VersionInfo, RetentionPolicy, } from "./vfs/types.js";
49
+ export { InMemoryMetadataStore } from "./vfs/memory-metadata.js";
50
+ export { InMemoryBlockStore } from "./vfs/memory-block-store.js";
51
+ export { SqliteMetadataStore } from "./vfs/sqlite-metadata.js";
52
+ export type { SqliteMetadataStoreOptions } from "./vfs/sqlite-metadata.js";
53
+ export { createChunkedVfs } from "./vfs/chunked-vfs.js";
54
+ export type { ChunkedVfsOptions, ChunkedVfsVersioning } from "./vfs/chunked-vfs.js";
55
+ export { HostBlockStore } from "./vfs/host-block-store.js";
43
56
  export type { DirEntry, StatInfo } from "./fs-helpers.js";
44
57
  export { exists, stat, rename, readDirWithTypes, mkdir } from "./fs-helpers.js";
45
58
  export { BUILTIN_NAMED_EXPORTS, normalizeBuiltinSpecifier, getPathDir, } from "./module-resolver.js";
package/dist/index.js CHANGED
@@ -1,12 +1,15 @@
1
1
  // Kernel — VFS, process table, FD table, device layer, pipes, PTY, command registry, permissions.
2
2
  export { createKernel } from "./kernel/kernel.js";
3
- export { KernelError, defaultTermios } from "./kernel/types.js";
3
+ export { KernelError, defaultTermios, noopKernelLogger } from "./kernel/types.js";
4
4
  // Kernel components.
5
5
  export { FDTableManager, ProcessFDTable } from "./kernel/fd-table.js";
6
6
  export { ProcessTable } from "./kernel/process-table.js";
7
7
  export { TimerTable } from "./kernel/timer-table.js";
8
+ export { createDeviceBackend } from "./kernel/device-backend.js";
8
9
  export { createDeviceLayer } from "./kernel/device-layer.js";
10
+ export { MountTable } from "./kernel/mount-table.js";
9
11
  export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./kernel/proc-layer.js";
12
+ export { createProcBackend } from "./kernel/proc-backend.js";
10
13
  export { PipeManager } from "./kernel/pipe-manager.js";
11
14
  export { PtyManager } from "./kernel/pty.js";
12
15
  export { CommandRegistry } from "./kernel/command-registry.js";
@@ -24,7 +27,7 @@ export { encodeExitStatus, encodeSignalStatus, WIFEXITED, WEXITSTATUS, WIFSIGNAL
24
27
  // Shared constants.
25
28
  export { TIMEOUT_EXIT_CODE, TIMEOUT_ERROR_MESSAGE, } from "./shared/constants.js";
26
29
  // Shared utilities.
27
- export { createInMemoryFileSystem, InMemoryFileSystem, } from "./shared/in-memory-fs.js";
30
+ export { createInMemoryFileSystem } from "./shared/in-memory-fs.js";
28
31
  export { allowAll, allowAllChildProcess, allowAllEnv, allowAllFs, allowAllNetwork, createCommandExecutorStub, createFsStub, createNetworkStub, envAccessAllowed, filterEnv, wrapCommandExecutor, wrapFileSystem, wrapNetworkAdapter, } from "./shared/permissions.js";
29
32
  export { createEaccesError, createEnosysError, createSystemError, } from "./shared/errors.js";
30
33
  export { extractCjsNamedExports, extractDynamicImportSpecifiers, isESM, transformDynamicImport, wrapCJSForESM, wrapCJSForESMWithModulePath, } from "./shared/esm-utils.js";
@@ -35,6 +38,11 @@ export { exposeCustomGlobal, exposeGlobalBinding, exposeMutableRuntimeStateGloba
35
38
  export { getIsolateRuntimeSource, ISOLATE_RUNTIME_SOURCES, } from "./generated/isolate-runtime.js";
36
39
  // Generated polyfills.
37
40
  export { POLYFILL_CODE_MAP } from "./generated/polyfills.js";
41
+ export { InMemoryMetadataStore } from "./vfs/memory-metadata.js";
42
+ export { InMemoryBlockStore } from "./vfs/memory-block-store.js";
43
+ export { SqliteMetadataStore } from "./vfs/sqlite-metadata.js";
44
+ export { createChunkedVfs } from "./vfs/chunked-vfs.js";
45
+ export { HostBlockStore } from "./vfs/host-block-store.js";
38
46
  export { exists, stat, rename, readDirWithTypes, mkdir } from "./fs-helpers.js";
39
47
  // Module resolution.
40
48
  export { BUILTIN_NAMED_EXPORTS, normalizeBuiltinSpecifier, getPathDir, } from "./module-resolver.js";
@@ -525,7 +525,7 @@
525
525
  return "utf-8";
526
526
  }
527
527
  });
528
- function TextDecoder(label, options) {
528
+ function TextDecoder2(label, options) {
529
529
  var normalizedOptions = options == null ? {} : Object(options);
530
530
  this._encoding = _normalizeEncodingLabel(label);
531
531
  this._fatal = Boolean(normalizedOptions.fatal);
@@ -533,22 +533,22 @@
533
533
  this._pendingBytes = [];
534
534
  this._bomSeen = false;
535
535
  }
536
- Object.defineProperty(TextDecoder.prototype, "encoding", {
536
+ Object.defineProperty(TextDecoder2.prototype, "encoding", {
537
537
  get: function() {
538
538
  return this._encoding;
539
539
  }
540
540
  });
541
- Object.defineProperty(TextDecoder.prototype, "fatal", {
541
+ Object.defineProperty(TextDecoder2.prototype, "fatal", {
542
542
  get: function() {
543
543
  return this._fatal;
544
544
  }
545
545
  });
546
- Object.defineProperty(TextDecoder.prototype, "ignoreBOM", {
546
+ Object.defineProperty(TextDecoder2.prototype, "ignoreBOM", {
547
547
  get: function() {
548
548
  return this._ignoreBOM;
549
549
  }
550
550
  });
551
- TextDecoder.prototype.decode = function decode(input, options) {
551
+ TextDecoder2.prototype.decode = function decode(input, options) {
552
552
  var normalizedOptions = options == null ? {} : Object(options);
553
553
  var stream = Boolean(normalizedOptions.stream);
554
554
  var incoming = _toUint8Array(input);
@@ -743,7 +743,7 @@
743
743
  return !event.defaultPrevented;
744
744
  };
745
745
  globalThis.TextEncoder = TextEncoder;
746
- globalThis.TextDecoder = TextDecoder;
746
+ globalThis.TextDecoder = TextDecoder2;
747
747
  globalThis.Event = Event;
748
748
  globalThis.CustomEvent = CustomEvent;
749
749
  globalThis.EventTarget = EventTarget;
@@ -3437,9 +3437,137 @@
3437
3437
  MessageChannel: globalThis.MessageChannel,
3438
3438
  MessageEvent: globalThis.MessageEvent
3439
3439
  };
3440
+ const readlineCompat = {
3441
+ createInterface: function createInterface(opts) {
3442
+ const input = opts && opts.input ? opts.input : typeof process !== "undefined" ? process.stdin : null;
3443
+ const output = opts && opts.output ? opts.output : typeof process !== "undefined" ? process.stdout : null;
3444
+ const listeners = {};
3445
+ const rl = {
3446
+ input,
3447
+ output,
3448
+ terminal: false,
3449
+ closed: false,
3450
+ on: function(event, handler) {
3451
+ (listeners[event] = listeners[event] || []).push(handler);
3452
+ return rl;
3453
+ },
3454
+ once: function(event, handler) {
3455
+ const wrapper = function() {
3456
+ rl.off(event, wrapper);
3457
+ handler.apply(this, arguments);
3458
+ };
3459
+ return rl.on(event, wrapper);
3460
+ },
3461
+ off: function(event, handler) {
3462
+ if (listeners[event]) listeners[event] = listeners[event].filter(function(h) {
3463
+ return h !== handler;
3464
+ });
3465
+ return rl;
3466
+ },
3467
+ removeListener: function(event, handler) {
3468
+ return rl.off(event, handler);
3469
+ },
3470
+ emit: function(event) {
3471
+ const args = Array.prototype.slice.call(arguments, 1);
3472
+ (listeners[event] || []).forEach(function(h) {
3473
+ h.apply(null, args);
3474
+ });
3475
+ return rl;
3476
+ },
3477
+ close: function() {
3478
+ if (!rl.closed) {
3479
+ rl.closed = true;
3480
+ rl.emit("close");
3481
+ }
3482
+ },
3483
+ question: function(query, cb) {
3484
+ if (output && output.write) output.write(query);
3485
+ if (input && input.once) {
3486
+ var buf = "";
3487
+ var onData = function(chunk) {
3488
+ buf += typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
3489
+ var idx = buf.indexOf("\n");
3490
+ if (idx !== -1) {
3491
+ input.removeListener("data", onData);
3492
+ cb(buf.slice(0, idx));
3493
+ }
3494
+ };
3495
+ input.on("data", onData);
3496
+ } else {
3497
+ cb("");
3498
+ }
3499
+ },
3500
+ prompt: function() {
3501
+ if (output && output.write) output.write("> ");
3502
+ },
3503
+ setPrompt: function() {
3504
+ },
3505
+ pause: function() {
3506
+ return rl;
3507
+ },
3508
+ resume: function() {
3509
+ return rl;
3510
+ },
3511
+ write: function() {
3512
+ },
3513
+ [Symbol.asyncIterator]: function() {
3514
+ return rl._iterState;
3515
+ }
3516
+ };
3517
+ var _lineBuf = "";
3518
+ var _iterLines = [];
3519
+ var _iterResolve = null;
3520
+ var _iterDone = false;
3521
+ rl._iterState = {
3522
+ next: function() {
3523
+ if (_iterLines.length > 0) return Promise.resolve({ value: _iterLines.shift(), done: false });
3524
+ if (_iterDone) return Promise.resolve({ value: void 0, done: true });
3525
+ return new Promise(function(r) {
3526
+ _iterResolve = r;
3527
+ }).then(function() {
3528
+ if (_iterLines.length > 0) return { value: _iterLines.shift(), done: false };
3529
+ return { value: void 0, done: true };
3530
+ });
3531
+ }
3532
+ };
3533
+ if (input && input.on) {
3534
+ input.on("data", function(chunk) {
3535
+ _lineBuf += typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
3536
+ var idx;
3537
+ while ((idx = _lineBuf.indexOf("\n")) !== -1) {
3538
+ var line = _lineBuf.slice(0, idx);
3539
+ _lineBuf = _lineBuf.slice(idx + 1);
3540
+ rl.emit("line", line);
3541
+ _iterLines.push(line);
3542
+ if (_iterResolve) {
3543
+ _iterResolve();
3544
+ _iterResolve = null;
3545
+ }
3546
+ }
3547
+ });
3548
+ input.on("end", function() {
3549
+ rl.emit("close");
3550
+ _iterDone = true;
3551
+ if (_iterResolve) {
3552
+ _iterResolve();
3553
+ _iterResolve = null;
3554
+ }
3555
+ });
3556
+ if (input.resume) input.resume();
3557
+ }
3558
+ return rl;
3559
+ },
3560
+ promises: {
3561
+ createInterface: function createInterface(opts) {
3562
+ return readlineCompat.createInterface(opts);
3563
+ }
3564
+ }
3565
+ };
3440
3566
  const moduleCompat = {
3441
3567
  worker_threads: workerThreadsCompat,
3442
- "node:worker_threads": workerThreadsCompat
3568
+ "node:worker_threads": workerThreadsCompat,
3569
+ readline: readlineCompat,
3570
+ "node:readline": readlineCompat
3443
3571
  };
3444
3572
  let stub = null;
3445
3573
  stub = new Proxy({}, {
@@ -3861,6 +3989,16 @@
3861
3989
  _debugRequire("loaded", name, "diagnostics-channel-special");
3862
3990
  return dcModule;
3863
3991
  }
3992
+ if (name === "path/win32") {
3993
+ var pathMod = _requireFrom("path", fromDir);
3994
+ __internalModuleCache[name] = pathMod.win32 || pathMod;
3995
+ return __internalModuleCache[name];
3996
+ }
3997
+ if (name === "path/posix") {
3998
+ var pathMod2 = _requireFrom("path", fromDir);
3999
+ __internalModuleCache[name] = pathMod2.posix || pathMod2;
4000
+ return __internalModuleCache[name];
4001
+ }
3864
4002
  if (_deferredCoreModules.has(name)) {
3865
4003
  if (__internalModuleCache[name]) return __internalModuleCache[name];
3866
4004
  const deferredStub = _createDeferredModuleStub(name);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Device backend.
3
+ *
4
+ * Standalone VirtualFileSystem that handles device nodes.
5
+ * Receives relative paths (e.g. "null" not "/dev/null").
6
+ * Designed to be mounted at /dev via MountTable.
7
+ */
8
+ import type { VirtualFileSystem } from "./vfs.js";
9
+ /**
10
+ * Create a standalone device backend VFS.
11
+ * All paths are relative to /dev (e.g. "null", "zero", "pts/0").
12
+ * Mount at /dev via MountTable.
13
+ */
14
+ export declare function createDeviceBackend(): VirtualFileSystem;
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Device backend.
3
+ *
4
+ * Standalone VirtualFileSystem that handles device nodes.
5
+ * Receives relative paths (e.g. "null" not "/dev/null").
6
+ * Designed to be mounted at /dev via MountTable.
7
+ */
8
+ import { KernelError } from "./types.js";
9
+ const DEVICE_NAMES = new Set([
10
+ "null",
11
+ "zero",
12
+ "stdin",
13
+ "stdout",
14
+ "stderr",
15
+ "urandom",
16
+ "random",
17
+ "tty",
18
+ "console",
19
+ "full",
20
+ "ptmx",
21
+ ]);
22
+ const DEVICE_INO = {
23
+ null: 0xffff_0001,
24
+ zero: 0xffff_0002,
25
+ stdin: 0xffff_0003,
26
+ stdout: 0xffff_0004,
27
+ stderr: 0xffff_0005,
28
+ urandom: 0xffff_0006,
29
+ random: 0xffff_0007,
30
+ tty: 0xffff_0008,
31
+ console: 0xffff_0009,
32
+ full: 0xffff_000a,
33
+ ptmx: 0xffff_000b,
34
+ };
35
+ /** Device pseudo-directories that contain dynamic entries. */
36
+ const DEVICE_DIRS = new Set(["fd", "pts", "shm"]);
37
+ function isDeviceName(path) {
38
+ return (DEVICE_NAMES.has(path) || path.startsWith("fd/") || path.startsWith("pts/"));
39
+ }
40
+ function isDeviceDir(path) {
41
+ return path === "" || DEVICE_DIRS.has(path);
42
+ }
43
+ function deviceStat(path) {
44
+ const now = Date.now();
45
+ return {
46
+ mode: 0o666,
47
+ size: 0,
48
+ isDirectory: false,
49
+ isSymbolicLink: false,
50
+ atimeMs: now,
51
+ mtimeMs: now,
52
+ ctimeMs: now,
53
+ birthtimeMs: now,
54
+ ino: DEVICE_INO[path] ?? 0xffff_0000,
55
+ nlink: 1,
56
+ uid: 0,
57
+ gid: 0,
58
+ };
59
+ }
60
+ function dirStat(path) {
61
+ const now = Date.now();
62
+ return {
63
+ mode: 0o755,
64
+ size: 0,
65
+ isDirectory: true,
66
+ isSymbolicLink: false,
67
+ atimeMs: now,
68
+ mtimeMs: now,
69
+ ctimeMs: now,
70
+ birthtimeMs: now,
71
+ ino: DEVICE_INO[path] ?? 0xffff_0000,
72
+ nlink: 2,
73
+ uid: 0,
74
+ gid: 0,
75
+ };
76
+ }
77
+ const DEV_DIR_ENTRIES = [
78
+ { name: "null", isDirectory: false },
79
+ { name: "zero", isDirectory: false },
80
+ { name: "stdin", isDirectory: false },
81
+ { name: "stdout", isDirectory: false },
82
+ { name: "stderr", isDirectory: false },
83
+ { name: "urandom", isDirectory: false },
84
+ { name: "random", isDirectory: false },
85
+ { name: "tty", isDirectory: false },
86
+ { name: "console", isDirectory: false },
87
+ { name: "full", isDirectory: false },
88
+ { name: "ptmx", isDirectory: false },
89
+ { name: "fd", isDirectory: true },
90
+ { name: "pts", isDirectory: true },
91
+ { name: "shm", isDirectory: true },
92
+ ];
93
+ function randomBytes(length) {
94
+ const buf = new Uint8Array(length);
95
+ if (typeof globalThis.crypto?.getRandomValues === "function") {
96
+ globalThis.crypto.getRandomValues(buf);
97
+ }
98
+ else {
99
+ for (let i = 0; i < buf.length; i++) {
100
+ buf[i] = (Math.random() * 256) | 0;
101
+ }
102
+ }
103
+ return buf;
104
+ }
105
+ function notFound(path) {
106
+ throw new KernelError("ENOENT", `no such device: ${path}`);
107
+ }
108
+ /**
109
+ * Create a standalone device backend VFS.
110
+ * All paths are relative to /dev (e.g. "null", "zero", "pts/0").
111
+ * Mount at /dev via MountTable.
112
+ */
113
+ export function createDeviceBackend() {
114
+ const backend = {
115
+ async readFile(path) {
116
+ if (path === "null" || path === "full")
117
+ return new Uint8Array(0);
118
+ if (path === "zero")
119
+ return new Uint8Array(4096);
120
+ if (path === "urandom" || path === "random")
121
+ return randomBytes(4096);
122
+ if (path === "tty" || path === "console" || path === "ptmx")
123
+ return new Uint8Array(0);
124
+ if (path === "stdin" || path === "stdout" || path === "stderr")
125
+ return new Uint8Array(0);
126
+ notFound(path);
127
+ },
128
+ async pread(path, _offset, length) {
129
+ if (path === "null" || path === "full")
130
+ return new Uint8Array(0);
131
+ if (path === "zero")
132
+ return new Uint8Array(length);
133
+ if (path === "urandom" || path === "random")
134
+ return randomBytes(length);
135
+ if (path === "tty" || path === "console" || path === "ptmx")
136
+ return new Uint8Array(0);
137
+ if (path === "stdin" || path === "stdout" || path === "stderr")
138
+ return new Uint8Array(0);
139
+ notFound(path);
140
+ },
141
+ async readTextFile(path) {
142
+ const bytes = await this.readFile(path);
143
+ return new TextDecoder().decode(bytes);
144
+ },
145
+ async readDir(path) {
146
+ if (path === "")
147
+ return DEV_DIR_ENTRIES.map((e) => e.name);
148
+ if (DEVICE_DIRS.has(path))
149
+ return [];
150
+ notFound(path);
151
+ },
152
+ async readDirWithTypes(path) {
153
+ if (path === "")
154
+ return DEV_DIR_ENTRIES;
155
+ if (DEVICE_DIRS.has(path))
156
+ return [];
157
+ notFound(path);
158
+ },
159
+ async writeFile(path, _content) {
160
+ if (path === "full")
161
+ throw new KernelError("ENOSPC", "No space left on device");
162
+ if (DEVICE_NAMES.has(path) ||
163
+ path.startsWith("fd/") ||
164
+ path.startsWith("pts/")) {
165
+ return;
166
+ }
167
+ notFound(path);
168
+ },
169
+ async pwrite(path, _offset, _data) {
170
+ if (path === "full")
171
+ throw new KernelError("ENOSPC", "No space left on device");
172
+ if (DEVICE_NAMES.has(path) ||
173
+ path.startsWith("fd/") ||
174
+ path.startsWith("pts/")) {
175
+ return;
176
+ }
177
+ notFound(path);
178
+ },
179
+ async createDir(path) {
180
+ if (isDeviceDir(path))
181
+ return;
182
+ throw new KernelError("EPERM", "cannot create directory in /dev");
183
+ },
184
+ async mkdir(path, _options) {
185
+ if (isDeviceDir(path))
186
+ return;
187
+ throw new KernelError("EPERM", "cannot create directory in /dev");
188
+ },
189
+ async exists(path) {
190
+ return isDeviceName(path) || isDeviceDir(path);
191
+ },
192
+ async stat(path) {
193
+ if (isDeviceName(path))
194
+ return deviceStat(path);
195
+ if (isDeviceDir(path))
196
+ return dirStat(path);
197
+ notFound(path);
198
+ },
199
+ async removeFile(path) {
200
+ if (isDeviceName(path))
201
+ throw new KernelError("EPERM", "cannot remove device");
202
+ notFound(path);
203
+ },
204
+ async removeDir(path) {
205
+ if (isDeviceDir(path))
206
+ throw new KernelError("EPERM", "cannot remove device directory");
207
+ notFound(path);
208
+ },
209
+ async rename(_oldPath, _newPath) {
210
+ throw new KernelError("EPERM", "cannot rename device");
211
+ },
212
+ async realpath(path) {
213
+ if (isDeviceName(path) || isDeviceDir(path))
214
+ return path;
215
+ notFound(path);
216
+ },
217
+ async symlink(_target, _linkPath) {
218
+ throw new KernelError("EPERM", "cannot create symlink in /dev");
219
+ },
220
+ async readlink(path) {
221
+ notFound(path);
222
+ },
223
+ async lstat(path) {
224
+ return this.stat(path);
225
+ },
226
+ async link(_oldPath, _newPath) {
227
+ throw new KernelError("EPERM", "cannot link device");
228
+ },
229
+ async chmod(path, _mode) {
230
+ if (isDeviceName(path) || isDeviceDir(path))
231
+ return;
232
+ notFound(path);
233
+ },
234
+ async chown(path, _uid, _gid) {
235
+ if (isDeviceName(path) || isDeviceDir(path))
236
+ return;
237
+ notFound(path);
238
+ },
239
+ async utimes(path, _atime, _mtime) {
240
+ if (isDeviceName(path) || isDeviceDir(path))
241
+ return;
242
+ notFound(path);
243
+ },
244
+ async truncate(path, _length) {
245
+ if (isDeviceName(path) || isDeviceDir(path))
246
+ return;
247
+ notFound(path);
248
+ },
249
+ };
250
+ return backend;
251
+ }
@@ -160,6 +160,15 @@ export function createDeviceLayer(vfs) {
160
160
  return;
161
161
  return vfs.writeFile(path, content);
162
162
  },
163
+ async pwrite(path, offset, data) {
164
+ if (path === "/dev/full")
165
+ throw new KernelError("ENOSPC", "No space left on device");
166
+ if (path === "/dev/null" || path === "/dev/zero" || path === "/dev/urandom"
167
+ || path === "/dev/random" || path === "/dev/tty" || path === "/dev/console"
168
+ || path === "/dev/ptmx")
169
+ return;
170
+ return vfs.pwrite(path, offset, data);
171
+ },
163
172
  async createDir(path) {
164
173
  if (isDeviceDir(path))
165
174
  return;
@@ -6,21 +6,21 @@
6
6
  * same kernel instance.
7
7
  */
8
8
  export { createKernel } from "./kernel.js";
9
- export type { Kernel, KernelOptions, KernelInterface, ExecOptions, ExecResult, SpawnOptions, ManagedProcess, RuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, Permissions, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, SignalDisposition, SignalHandler, ProcessSignalState, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, } from "./types.js";
10
- export { KernelError, defaultTermios } from "./types.js";
9
+ export type { FsMount, Kernel, KernelOptions, KernelInterface, KernelLogger, ExecOptions, ExecResult, SpawnOptions, ManagedProcess, RuntimeDriver, ProcessContext, DriverProcess, ProcessEntry, ProcessInfo, FDStat, FileDescription, FDEntry, Pipe, Permissions, PermissionDecision, PermissionCheck, FsAccessRequest, NetworkAccessRequest, ChildProcessAccessRequest, EnvAccessRequest, KernelErrorCode, SignalDisposition, SignalHandler, ProcessSignalState, Termios, TermiosCC, OpenShellOptions, ShellHandle, ConnectTerminalOptions, } from "./types.js";
10
+ export { KernelError, defaultTermios, noopKernelLogger } from "./types.js";
11
11
  export type { VirtualFileSystem, VirtualDirEntry, VirtualStat, } from "./vfs.js";
12
12
  export { FDTableManager, ProcessFDTable } from "./fd-table.js";
13
13
  export { ProcessTable } from "./process-table.js";
14
14
  export { createDeviceLayer } from "./device-layer.js";
15
15
  export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./proc-layer.js";
16
+ export { createProcBackend } from "./proc-backend.js";
17
+ export type { ProcBackendOptions } from "./proc-backend.js";
16
18
  export { PipeManager } from "./pipe-manager.js";
17
19
  export { PtyManager } from "./pty.js";
18
20
  export type { LineDisciplineConfig } from "./pty.js";
19
21
  export { CommandRegistry } from "./command-registry.js";
20
22
  export { FileLockManager, LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB } from "./file-lock.js";
21
23
  export { WaitHandle, WaitQueue } from "./wait.js";
22
- export { InodeTable } from "./inode-table.js";
23
- export type { Inode } from "./inode-table.js";
24
24
  export { TimerTable } from "./timer-table.js";
25
25
  export type { KernelTimer, TimerTableOptions } from "./timer-table.js";
26
26
  export { DnsCache } from "./dns-cache.js";
@@ -7,19 +7,19 @@
7
7
  */
8
8
  // Kernel factory
9
9
  export { createKernel } from "./kernel.js";
10
- // Structured kernel error and termios defaults
11
- export { KernelError, defaultTermios } from "./types.js";
10
+ // Structured kernel error, termios defaults, and no-op logger
11
+ export { KernelError, defaultTermios, noopKernelLogger } from "./types.js";
12
12
  // Kernel components (for direct use / testing)
13
13
  export { FDTableManager, ProcessFDTable } from "./fd-table.js";
14
14
  export { ProcessTable } from "./process-table.js";
15
15
  export { createDeviceLayer } from "./device-layer.js";
16
16
  export { createProcLayer, createProcessScopedFileSystem, resolveProcSelfPath, } from "./proc-layer.js";
17
+ export { createProcBackend } from "./proc-backend.js";
17
18
  export { PipeManager } from "./pipe-manager.js";
18
19
  export { PtyManager } from "./pty.js";
19
20
  export { CommandRegistry } from "./command-registry.js";
20
21
  export { FileLockManager, LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB } from "./file-lock.js";
21
22
  export { WaitHandle, WaitQueue } from "./wait.js";
22
- export { InodeTable } from "./inode-table.js";
23
23
  export { TimerTable } from "./timer-table.js";
24
24
  export { DnsCache } from "./dns-cache.js";
25
25
  export { UserManager } from "./user.js";