@secure-exec/core 0.2.1 → 0.3.0-rc.2

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 (248) hide show
  1. package/README.md +5 -5
  2. package/dist/binary.d.ts +4 -0
  3. package/dist/binary.js +25 -0
  4. package/dist/bytes.d.ts +2 -0
  5. package/dist/bytes.js +6 -0
  6. package/dist/callbacks.d.ts +41 -0
  7. package/dist/callbacks.js +94 -0
  8. package/dist/cargo.d.ts +2 -0
  9. package/dist/cargo.js +142 -0
  10. package/dist/correlation.d.ts +10 -0
  11. package/dist/correlation.js +49 -0
  12. package/dist/descriptors.d.ts +34 -0
  13. package/dist/descriptors.js +37 -0
  14. package/dist/event-buffer.d.ts +90 -0
  15. package/dist/event-buffer.js +313 -0
  16. package/dist/ext.d.ts +7 -0
  17. package/dist/ext.js +13 -0
  18. package/dist/filesystem.d.ts +41 -0
  19. package/dist/filesystem.js +70 -0
  20. package/dist/frame-payload-codec.d.ts +8 -0
  21. package/dist/frame-payload-codec.js +14 -0
  22. package/dist/frame-rpc.d.ts +38 -0
  23. package/dist/frame-rpc.js +73 -0
  24. package/dist/frame-stream.d.ts +27 -0
  25. package/dist/frame-stream.js +99 -0
  26. package/dist/framing.d.ts +7 -0
  27. package/dist/framing.js +22 -0
  28. package/dist/generated/AcpLimitsConfig.d.ts +4 -0
  29. package/dist/generated/AcpLimitsConfig.js +2 -0
  30. package/dist/generated/CreateVmConfig.d.ts +19 -0
  31. package/dist/generated/FsPermissionRule.d.ts +6 -0
  32. package/dist/generated/FsPermissionRuleSet.d.ts +6 -0
  33. package/dist/generated/FsPermissionRuleSet.js +1 -0
  34. package/dist/generated/FsPermissionScope.d.ts +3 -0
  35. package/dist/generated/FsPermissionScope.js +1 -0
  36. package/dist/generated/HttpLimitsConfig.d.ts +3 -0
  37. package/dist/generated/HttpLimitsConfig.js +2 -0
  38. package/dist/generated/JsModuleResolution.d.ts +1 -0
  39. package/dist/generated/JsModuleResolution.js +2 -0
  40. package/dist/generated/JsRuntimeConfig.d.ts +26 -0
  41. package/dist/generated/JsRuntimeConfig.js +1 -0
  42. package/dist/generated/JsRuntimeLimitsConfig.d.ts +7 -0
  43. package/dist/generated/JsRuntimeLimitsConfig.js +2 -0
  44. package/dist/generated/JsRuntimePlatform.d.ts +1 -0
  45. package/dist/generated/JsRuntimePlatform.js +2 -0
  46. package/dist/generated/MountPluginDescriptor.d.ts +4 -0
  47. package/dist/generated/MountPluginDescriptor.js +2 -0
  48. package/dist/generated/NativeRootFilesystemConfig.d.ts +5 -0
  49. package/dist/generated/NativeRootFilesystemConfig.js +1 -0
  50. package/dist/generated/PatternPermissionRule.d.ts +6 -0
  51. package/dist/generated/PatternPermissionRule.js +1 -0
  52. package/dist/generated/PatternPermissionRuleSet.d.ts +6 -0
  53. package/dist/generated/PatternPermissionRuleSet.js +1 -0
  54. package/dist/generated/PatternPermissionScope.d.ts +3 -0
  55. package/dist/generated/PatternPermissionScope.js +1 -0
  56. package/dist/generated/PermissionMode.d.ts +1 -0
  57. package/dist/generated/PermissionMode.js +2 -0
  58. package/dist/generated/PermissionsPolicy.d.ts +10 -0
  59. package/dist/generated/PermissionsPolicy.js +1 -0
  60. package/dist/generated/PluginLimitsConfig.d.ts +4 -0
  61. package/dist/generated/PluginLimitsConfig.js +2 -0
  62. package/dist/generated/PythonLimitsConfig.d.ts +5 -0
  63. package/dist/generated/PythonLimitsConfig.js +2 -0
  64. package/dist/generated/ResourceLimitsConfig.d.ts +22 -0
  65. package/dist/generated/ResourceLimitsConfig.js +2 -0
  66. package/dist/generated/RootFilesystemConfig.d.ts +9 -0
  67. package/dist/generated/RootFilesystemConfig.js +1 -0
  68. package/dist/generated/RootFilesystemEntry.d.ts +13 -0
  69. package/dist/generated/RootFilesystemEntry.js +1 -0
  70. package/dist/generated/RootFilesystemEntryEncoding.d.ts +1 -0
  71. package/dist/generated/RootFilesystemEntryEncoding.js +2 -0
  72. package/dist/generated/RootFilesystemEntryKind.d.ts +1 -0
  73. package/dist/generated/RootFilesystemEntryKind.js +2 -0
  74. package/dist/generated/RootFilesystemLowerDescriptor.d.ts +7 -0
  75. package/dist/generated/RootFilesystemLowerDescriptor.js +1 -0
  76. package/dist/generated/RootFilesystemMode.d.ts +1 -0
  77. package/dist/generated/RootFilesystemMode.js +2 -0
  78. package/dist/generated/ToolLimitsConfig.d.ts +10 -0
  79. package/dist/generated/ToolLimitsConfig.js +2 -0
  80. package/dist/generated/VmDnsConfig.d.ts +6 -0
  81. package/dist/generated/VmDnsConfig.js +2 -0
  82. package/dist/generated/VmLimitsConfig.d.ts +18 -0
  83. package/dist/generated/VmLimitsConfig.js +1 -0
  84. package/dist/generated/VmListenPolicyConfig.d.ts +5 -0
  85. package/dist/generated/VmListenPolicyConfig.js +2 -0
  86. package/dist/generated/WasmLimitsConfig.d.ts +5 -0
  87. package/dist/generated/WasmLimitsConfig.js +2 -0
  88. package/dist/generated-protocol.d.ts +1037 -0
  89. package/dist/generated-protocol.js +2887 -0
  90. package/dist/index.d.ts +24 -62
  91. package/dist/index.js +24 -53
  92. package/dist/json.d.ts +2 -0
  93. package/dist/json.js +20 -0
  94. package/dist/kernel-proxy.d.ts +149 -0
  95. package/dist/kernel-proxy.js +1733 -0
  96. package/dist/native-client.d.ts +41 -0
  97. package/dist/native-client.js +124 -0
  98. package/dist/node-runtime.d.ts +490 -0
  99. package/dist/node-runtime.js +585 -0
  100. package/dist/numbers.d.ts +1 -0
  101. package/dist/numbers.js +8 -0
  102. package/dist/ownership.d.ts +18 -0
  103. package/dist/ownership.js +77 -0
  104. package/dist/permissions.d.ts +29 -0
  105. package/dist/permissions.js +68 -0
  106. package/dist/process.d.ts +35 -0
  107. package/dist/process.js +125 -0
  108. package/dist/protocol-client.d.ts +46 -0
  109. package/dist/protocol-client.js +180 -0
  110. package/dist/protocol-frames.d.ts +68 -0
  111. package/dist/protocol-frames.js +139 -0
  112. package/dist/protocol-maps.d.ts +28 -0
  113. package/dist/protocol-maps.js +217 -0
  114. package/dist/protocol-schema.d.ts +10 -0
  115. package/dist/protocol-schema.js +11 -0
  116. package/dist/request-payloads.d.ts +137 -0
  117. package/dist/request-payloads.js +210 -0
  118. package/dist/response-payloads.d.ts +107 -0
  119. package/dist/response-payloads.js +161 -0
  120. package/dist/sidecar-client.d.ts +242 -0
  121. package/dist/sidecar-client.js +797 -0
  122. package/dist/state.d.ts +40 -0
  123. package/dist/state.js +44 -0
  124. package/dist/test-runtime.d.ts +526 -0
  125. package/dist/test-runtime.js +2119 -0
  126. package/dist/vm-config.d.ts +31 -0
  127. package/dist/vm-config.js +1 -0
  128. package/fixtures/alpine-defaults.json +520 -0
  129. package/fixtures/base-filesystem.json +528 -0
  130. package/package.json +193 -115
  131. package/LICENSE +0 -191
  132. package/dist/bridge-setup.d.ts +0 -6
  133. package/dist/bridge-setup.js +0 -9
  134. package/dist/esm-compiler.d.ts +0 -18
  135. package/dist/esm-compiler.js +0 -72
  136. package/dist/fs-helpers.d.ts +0 -23
  137. package/dist/fs-helpers.js +0 -41
  138. package/dist/generated/isolate-runtime.d.ts +0 -19
  139. package/dist/generated/isolate-runtime.js +0 -21
  140. package/dist/generated/polyfills.d.ts +0 -82
  141. package/dist/generated/polyfills.js +0 -82
  142. package/dist/isolate-runtime/apply-custom-global-policy.js +0 -53
  143. package/dist/isolate-runtime/apply-timing-mitigation-freeze.js +0 -130
  144. package/dist/isolate-runtime/apply-timing-mitigation-off.js +0 -14
  145. package/dist/isolate-runtime/bridge-attach.js +0 -29
  146. package/dist/isolate-runtime/bridge-initial-globals.js +0 -385
  147. package/dist/isolate-runtime/eval-script-result.js +0 -8
  148. package/dist/isolate-runtime/global-exposure-helpers.js +0 -36
  149. package/dist/isolate-runtime/init-commonjs-module-globals.js +0 -28
  150. package/dist/isolate-runtime/override-process-cwd.js +0 -8
  151. package/dist/isolate-runtime/override-process-env.js +0 -8
  152. package/dist/isolate-runtime/require-setup.js +0 -4153
  153. package/dist/isolate-runtime/set-commonjs-file-globals.js +0 -36
  154. package/dist/isolate-runtime/set-stdin-data.js +0 -10
  155. package/dist/isolate-runtime/setup-dynamic-import.js +0 -123
  156. package/dist/isolate-runtime/setup-fs-facade.js +0 -87
  157. package/dist/kernel/command-registry.d.ts +0 -44
  158. package/dist/kernel/command-registry.js +0 -114
  159. package/dist/kernel/device-backend.d.ts +0 -14
  160. package/dist/kernel/device-backend.js +0 -251
  161. package/dist/kernel/device-layer.d.ts +0 -12
  162. package/dist/kernel/device-layer.js +0 -271
  163. package/dist/kernel/dns-cache.d.ts +0 -29
  164. package/dist/kernel/dns-cache.js +0 -52
  165. package/dist/kernel/fd-table.d.ts +0 -84
  166. package/dist/kernel/fd-table.js +0 -278
  167. package/dist/kernel/file-lock.d.ts +0 -34
  168. package/dist/kernel/file-lock.js +0 -122
  169. package/dist/kernel/host-adapter.d.ts +0 -50
  170. package/dist/kernel/host-adapter.js +0 -8
  171. package/dist/kernel/index.d.ts +0 -36
  172. package/dist/kernel/index.js +0 -34
  173. package/dist/kernel/kernel.d.ts +0 -9
  174. package/dist/kernel/kernel.js +0 -1415
  175. package/dist/kernel/mount-table.d.ts +0 -75
  176. package/dist/kernel/mount-table.js +0 -353
  177. package/dist/kernel/permissions.d.ts +0 -36
  178. package/dist/kernel/permissions.js +0 -150
  179. package/dist/kernel/pipe-manager.d.ts +0 -64
  180. package/dist/kernel/pipe-manager.js +0 -267
  181. package/dist/kernel/proc-backend.d.ts +0 -30
  182. package/dist/kernel/proc-backend.js +0 -428
  183. package/dist/kernel/proc-layer.d.ts +0 -11
  184. package/dist/kernel/proc-layer.js +0 -507
  185. package/dist/kernel/process-table.d.ts +0 -126
  186. package/dist/kernel/process-table.js +0 -651
  187. package/dist/kernel/pty.d.ts +0 -109
  188. package/dist/kernel/pty.js +0 -552
  189. package/dist/kernel/socket-table.d.ts +0 -312
  190. package/dist/kernel/socket-table.js +0 -1188
  191. package/dist/kernel/timer-table.d.ts +0 -54
  192. package/dist/kernel/timer-table.js +0 -108
  193. package/dist/kernel/types.d.ts +0 -541
  194. package/dist/kernel/types.js +0 -98
  195. package/dist/kernel/user.d.ts +0 -29
  196. package/dist/kernel/user.js +0 -35
  197. package/dist/kernel/vfs.d.ts +0 -82
  198. package/dist/kernel/vfs.js +0 -25
  199. package/dist/kernel/wait.d.ts +0 -45
  200. package/dist/kernel/wait.js +0 -112
  201. package/dist/kernel/wstatus.d.ts +0 -21
  202. package/dist/kernel/wstatus.js +0 -33
  203. package/dist/module-resolver.d.ts +0 -29
  204. package/dist/module-resolver.js +0 -314
  205. package/dist/package-bundler.d.ts +0 -41
  206. package/dist/package-bundler.js +0 -497
  207. package/dist/runtime-driver.d.ts +0 -66
  208. package/dist/shared/api-types.d.ts +0 -83
  209. package/dist/shared/bridge-contract.d.ts +0 -772
  210. package/dist/shared/bridge-contract.js +0 -169
  211. package/dist/shared/console-formatter.d.ts +0 -22
  212. package/dist/shared/console-formatter.js +0 -161
  213. package/dist/shared/constants.d.ts +0 -3
  214. package/dist/shared/constants.js +0 -3
  215. package/dist/shared/errors.d.ts +0 -16
  216. package/dist/shared/errors.js +0 -21
  217. package/dist/shared/esm-utils.d.ts +0 -28
  218. package/dist/shared/esm-utils.js +0 -97
  219. package/dist/shared/global-exposure.d.ts +0 -38
  220. package/dist/shared/global-exposure.js +0 -876
  221. package/dist/shared/in-memory-fs.d.ts +0 -16
  222. package/dist/shared/in-memory-fs.js +0 -115
  223. package/dist/shared/permissions.d.ts +0 -36
  224. package/dist/shared/permissions.js +0 -314
  225. package/dist/shared/require-setup.d.ts +0 -6
  226. package/dist/shared/require-setup.js +0 -9
  227. package/dist/test/block-store-conformance.d.ts +0 -34
  228. package/dist/test/block-store-conformance.js +0 -251
  229. package/dist/test/metadata-store-conformance.d.ts +0 -37
  230. package/dist/test/metadata-store-conformance.js +0 -646
  231. package/dist/test/vfs-conformance.d.ts +0 -65
  232. package/dist/test/vfs-conformance.js +0 -842
  233. package/dist/types.d.ts +0 -98
  234. package/dist/types.js +0 -6
  235. package/dist/vfs/chunked-vfs.d.ts +0 -66
  236. package/dist/vfs/chunked-vfs.js +0 -1290
  237. package/dist/vfs/host-block-store.d.ts +0 -19
  238. package/dist/vfs/host-block-store.js +0 -97
  239. package/dist/vfs/memory-block-store.d.ts +0 -16
  240. package/dist/vfs/memory-block-store.js +0 -45
  241. package/dist/vfs/memory-metadata.d.ts +0 -75
  242. package/dist/vfs/memory-metadata.js +0 -528
  243. package/dist/vfs/sqlite-metadata.d.ts +0 -91
  244. package/dist/vfs/sqlite-metadata.js +0 -582
  245. package/dist/vfs/types.d.ts +0 -210
  246. package/dist/vfs/types.js +0 -8
  247. /package/dist/{runtime-driver.js → generated/CreateVmConfig.js} +0 -0
  248. /package/dist/{shared/api-types.js → generated/FsPermissionRule.js} +0 -0
@@ -1,75 +0,0 @@
1
- /**
2
- * Mount Table.
3
- *
4
- * Linux-style VFS mount table that routes paths to mounted filesystem backends
5
- * by longest-prefix matching. Replaces the hardcoded layer composition
6
- * (DeviceLayer wraps ProcLayer wraps base FS) with a unified routing table.
7
- */
8
- import type { VirtualDirEntry, VirtualDirStatEntry, VirtualFileSystem, VirtualStat } from "./vfs.js";
9
- export interface MountOptions {
10
- readOnly?: boolean;
11
- }
12
- export interface MountEntry {
13
- path: string;
14
- readOnly: boolean;
15
- }
16
- export declare class MountTable implements VirtualFileSystem {
17
- /**
18
- * Mounts sorted by path length descending so longest-prefix match is first hit.
19
- */
20
- private mounts;
21
- constructor(rootFs: VirtualFileSystem);
22
- /**
23
- * Mount a filesystem at the given path.
24
- * Auto-creates the mount point directory in the parent filesystem if needed.
25
- */
26
- mount(path: string, fs: VirtualFileSystem, options?: MountOptions): void;
27
- /**
28
- * Unmount the filesystem at the given path.
29
- */
30
- unmount(path: string): void;
31
- /**
32
- * List all current mounts.
33
- */
34
- getMounts(): ReadonlyArray<MountEntry>;
35
- private resolve;
36
- private assertWritable;
37
- readFile(path: string): Promise<Uint8Array>;
38
- readTextFile(path: string): Promise<string>;
39
- readDir(path: string): Promise<string[]>;
40
- readDirWithTypes(path: string): Promise<VirtualDirEntry[]>;
41
- exists(path: string): Promise<boolean>;
42
- stat(path: string): Promise<VirtualStat>;
43
- lstat(path: string): Promise<VirtualStat>;
44
- realpath(path: string): Promise<string>;
45
- readlink(path: string): Promise<string>;
46
- pread(path: string, offset: number, length: number): Promise<Uint8Array>;
47
- pwrite(path: string, offset: number, data: Uint8Array): Promise<void>;
48
- writeFile(path: string, content: string | Uint8Array): Promise<void>;
49
- createDir(path: string): Promise<void>;
50
- mkdir(path: string, options?: {
51
- recursive?: boolean;
52
- }): Promise<void>;
53
- removeFile(path: string): Promise<void>;
54
- removeDir(path: string): Promise<void>;
55
- symlink(target: string, linkPath: string): Promise<void>;
56
- link(oldPath: string, newPath: string): Promise<void>;
57
- rename(oldPath: string, newPath: string): Promise<void>;
58
- chmod(path: string, mode: number): Promise<void>;
59
- chown(path: string, uid: number, gid: number): Promise<void>;
60
- utimes(path: string, atime: number, mtime: number): Promise<void>;
61
- truncate(path: string, length: number): Promise<void>;
62
- fsync(path: string): Promise<void>;
63
- copy(srcPath: string, dstPath: string): Promise<void>;
64
- readDirStat(path: string): Promise<VirtualDirStatEntry[]>;
65
- /**
66
- * Get basenames of child mount points under a directory.
67
- * For example, if mounts exist at /dev and /proc, calling with "/" returns ["dev", "proc"].
68
- */
69
- private getChildMountBasenames;
70
- /**
71
- * Synchronous open preparation (O_CREAT, O_EXCL, O_TRUNC).
72
- * Delegates to the underlying backend's prepareOpenSync if it exists.
73
- */
74
- prepareOpenSync(path: string, flags: number): boolean;
75
- }
@@ -1,353 +0,0 @@
1
- /**
2
- * Mount Table.
3
- *
4
- * Linux-style VFS mount table that routes paths to mounted filesystem backends
5
- * by longest-prefix matching. Replaces the hardcoded layer composition
6
- * (DeviceLayer wraps ProcLayer wraps base FS) with a unified routing table.
7
- */
8
- import { KernelError } from "./types.js";
9
- /**
10
- * Normalize a path: collapse //, ., .., strip trailing /.
11
- */
12
- function normalizePath(path) {
13
- if (!path || path === "/")
14
- return "/";
15
- const parts = path.split("/");
16
- const stack = [];
17
- for (const part of parts) {
18
- if (part === "" || part === ".")
19
- continue;
20
- if (part === "..") {
21
- stack.pop();
22
- }
23
- else {
24
- stack.push(part);
25
- }
26
- }
27
- return `/${stack.join("/")}`;
28
- }
29
- /**
30
- * Get parent directory path.
31
- */
32
- function parentPath(p) {
33
- if (p === "/")
34
- return "/";
35
- const idx = p.lastIndexOf("/");
36
- if (idx <= 0)
37
- return "/";
38
- return p.slice(0, idx);
39
- }
40
- /**
41
- * Get basename of a path.
42
- */
43
- function basename(p) {
44
- const idx = p.lastIndexOf("/");
45
- return p.slice(idx + 1);
46
- }
47
- export class MountTable {
48
- /**
49
- * Mounts sorted by path length descending so longest-prefix match is first hit.
50
- */
51
- mounts;
52
- constructor(rootFs) {
53
- this.mounts = [{ path: "/", fs: rootFs, readOnly: false }];
54
- }
55
- /**
56
- * Mount a filesystem at the given path.
57
- * Auto-creates the mount point directory in the parent filesystem if needed.
58
- */
59
- mount(path, fs, options) {
60
- const normalized = normalizePath(path);
61
- if (normalized === "/") {
62
- throw new KernelError("EINVAL", "cannot mount over root");
63
- }
64
- // Check if already mounted
65
- if (this.mounts.some((m) => m.path === normalized)) {
66
- throw new KernelError("EEXIST", `already mounted at ${normalized}`);
67
- }
68
- // Auto-create mount point directory in the parent filesystem.
69
- // Resolve *before* inserting the new mount so the path goes to the current owner.
70
- const { mount: parentMount, relativePath } = this.resolve(normalized);
71
- void parentMount.fs
72
- .mkdir(relativePath || "/", { recursive: true })
73
- .catch(() => {
74
- /* directory may already exist */
75
- });
76
- const entry = {
77
- path: normalized,
78
- fs,
79
- readOnly: options?.readOnly ?? false,
80
- };
81
- this.mounts.push(entry);
82
- // Sort by path length descending for longest-prefix-first matching
83
- this.mounts.sort((a, b) => b.path.length - a.path.length);
84
- }
85
- /**
86
- * Unmount the filesystem at the given path.
87
- */
88
- unmount(path) {
89
- const normalized = normalizePath(path);
90
- if (normalized === "/") {
91
- throw new KernelError("EINVAL", "cannot unmount root");
92
- }
93
- const idx = this.mounts.findIndex((m) => m.path === normalized);
94
- if (idx === -1) {
95
- throw new KernelError("EINVAL", `not a mount point: ${normalized}`);
96
- }
97
- this.mounts.splice(idx, 1);
98
- }
99
- /**
100
- * List all current mounts.
101
- */
102
- getMounts() {
103
- return this.mounts.map((m) => ({
104
- path: m.path,
105
- readOnly: m.readOnly,
106
- }));
107
- }
108
- // -----------------------------------------------------------------------
109
- // Path resolution
110
- // -----------------------------------------------------------------------
111
- resolve(fullPath) {
112
- const normalized = normalizePath(fullPath);
113
- for (const mount of this.mounts) {
114
- if (mount.path === "/") {
115
- // Root mount: forward path as-is
116
- return { mount, relativePath: normalized };
117
- }
118
- if (normalized === mount.path ||
119
- normalized.startsWith(`${mount.path}/`)) {
120
- const rel = normalized === mount.path
121
- ? ""
122
- : normalized.slice(mount.path.length + 1);
123
- return { mount, relativePath: rel };
124
- }
125
- }
126
- // Should never happen since root mount always matches
127
- throw new KernelError("ENOENT", `no mount for path: ${fullPath}`);
128
- }
129
- assertWritable(mount, path) {
130
- if (mount.readOnly) {
131
- throw new KernelError("EROFS", `read-only filesystem: ${path}`);
132
- }
133
- }
134
- // -----------------------------------------------------------------------
135
- // Read operations
136
- // -----------------------------------------------------------------------
137
- async readFile(path) {
138
- const { mount, relativePath } = this.resolve(path);
139
- return mount.fs.readFile(relativePath);
140
- }
141
- async readTextFile(path) {
142
- const { mount, relativePath } = this.resolve(path);
143
- return mount.fs.readTextFile(relativePath);
144
- }
145
- async readDir(path) {
146
- const { mount, relativePath } = this.resolve(path);
147
- const entries = await mount.fs.readDir(relativePath);
148
- // Merge mount point basenames for child mounts
149
- const normalized = normalizePath(path);
150
- const mountBasenames = this.getChildMountBasenames(normalized);
151
- if (mountBasenames.length === 0)
152
- return entries;
153
- const entrySet = new Set(entries);
154
- for (const name of mountBasenames) {
155
- entrySet.add(name);
156
- }
157
- return [...entrySet];
158
- }
159
- async readDirWithTypes(path) {
160
- const { mount, relativePath } = this.resolve(path);
161
- const entries = await mount.fs.readDirWithTypes(relativePath);
162
- // Merge mount point basenames as directory entries
163
- const normalized = normalizePath(path);
164
- const mountBasenames = this.getChildMountBasenames(normalized);
165
- if (mountBasenames.length === 0)
166
- return entries;
167
- const nameSet = new Set(entries.map((e) => e.name));
168
- for (const name of mountBasenames) {
169
- if (!nameSet.has(name)) {
170
- entries.push({
171
- name,
172
- isDirectory: true,
173
- isSymbolicLink: false,
174
- });
175
- }
176
- }
177
- return entries;
178
- }
179
- async exists(path) {
180
- const { mount, relativePath } = this.resolve(path);
181
- return mount.fs.exists(relativePath);
182
- }
183
- async stat(path) {
184
- const { mount, relativePath } = this.resolve(path);
185
- return mount.fs.stat(relativePath);
186
- }
187
- async lstat(path) {
188
- const { mount, relativePath } = this.resolve(path);
189
- return mount.fs.lstat(relativePath);
190
- }
191
- async realpath(path) {
192
- const { mount, relativePath } = this.resolve(path);
193
- const resolved = await mount.fs.realpath(relativePath);
194
- if (mount.path === "/")
195
- return resolved;
196
- // Re-prefix the mount path for non-root mounts
197
- return `${mount.path}/${resolved}`;
198
- }
199
- async readlink(path) {
200
- const { mount, relativePath } = this.resolve(path);
201
- return mount.fs.readlink(relativePath);
202
- }
203
- async pread(path, offset, length) {
204
- const { mount, relativePath } = this.resolve(path);
205
- return mount.fs.pread(relativePath, offset, length);
206
- }
207
- async pwrite(path, offset, data) {
208
- const { mount, relativePath } = this.resolve(path);
209
- this.assertWritable(mount, path);
210
- return mount.fs.pwrite(relativePath, offset, data);
211
- }
212
- // -----------------------------------------------------------------------
213
- // Write operations (check readOnly before forwarding)
214
- // -----------------------------------------------------------------------
215
- async writeFile(path, content) {
216
- const { mount, relativePath } = this.resolve(path);
217
- this.assertWritable(mount, path);
218
- return mount.fs.writeFile(relativePath, content);
219
- }
220
- async createDir(path) {
221
- const { mount, relativePath } = this.resolve(path);
222
- this.assertWritable(mount, path);
223
- return mount.fs.createDir(relativePath);
224
- }
225
- async mkdir(path, options) {
226
- const { mount, relativePath } = this.resolve(path);
227
- this.assertWritable(mount, path);
228
- return mount.fs.mkdir(relativePath, options);
229
- }
230
- async removeFile(path) {
231
- const { mount, relativePath } = this.resolve(path);
232
- this.assertWritable(mount, path);
233
- return mount.fs.removeFile(relativePath);
234
- }
235
- async removeDir(path) {
236
- const { mount, relativePath } = this.resolve(path);
237
- this.assertWritable(mount, path);
238
- return mount.fs.removeDir(relativePath);
239
- }
240
- async symlink(target, linkPath) {
241
- const { mount, relativePath } = this.resolve(linkPath);
242
- this.assertWritable(mount, linkPath);
243
- return mount.fs.symlink(target, relativePath);
244
- }
245
- async link(oldPath, newPath) {
246
- const oldResolved = this.resolve(oldPath);
247
- const newResolved = this.resolve(newPath);
248
- if (oldResolved.mount !== newResolved.mount) {
249
- throw new KernelError("EXDEV", `link across mounts: ${oldPath} -> ${newPath}`);
250
- }
251
- this.assertWritable(oldResolved.mount, oldPath);
252
- return oldResolved.mount.fs.link(oldResolved.relativePath, newResolved.relativePath);
253
- }
254
- async rename(oldPath, newPath) {
255
- const oldResolved = this.resolve(oldPath);
256
- const newResolved = this.resolve(newPath);
257
- if (oldResolved.mount !== newResolved.mount) {
258
- throw new KernelError("EXDEV", `rename across mounts: ${oldPath} -> ${newPath}`);
259
- }
260
- this.assertWritable(oldResolved.mount, oldPath);
261
- return oldResolved.mount.fs.rename(oldResolved.relativePath, newResolved.relativePath);
262
- }
263
- async chmod(path, mode) {
264
- const { mount, relativePath } = this.resolve(path);
265
- this.assertWritable(mount, path);
266
- return mount.fs.chmod(relativePath, mode);
267
- }
268
- async chown(path, uid, gid) {
269
- const { mount, relativePath } = this.resolve(path);
270
- this.assertWritable(mount, path);
271
- return mount.fs.chown(relativePath, uid, gid);
272
- }
273
- async utimes(path, atime, mtime) {
274
- const { mount, relativePath } = this.resolve(path);
275
- this.assertWritable(mount, path);
276
- return mount.fs.utimes(relativePath, atime, mtime);
277
- }
278
- async truncate(path, length) {
279
- const { mount, relativePath } = this.resolve(path);
280
- this.assertWritable(mount, path);
281
- return mount.fs.truncate(relativePath, length);
282
- }
283
- async fsync(path) {
284
- const { mount, relativePath } = this.resolve(path);
285
- await mount.fs.fsync?.(relativePath);
286
- }
287
- async copy(srcPath, dstPath) {
288
- const srcResolved = this.resolve(srcPath);
289
- const dstResolved = this.resolve(dstPath);
290
- if (srcResolved.mount !== dstResolved.mount) {
291
- throw new KernelError("EXDEV", `copy across mounts: ${srcPath} -> ${dstPath}`);
292
- }
293
- this.assertWritable(srcResolved.mount, dstPath);
294
- if (srcResolved.mount.fs.copy) {
295
- return srcResolved.mount.fs.copy(srcResolved.relativePath, dstResolved.relativePath);
296
- }
297
- // Fallback: readFile + writeFile.
298
- const content = await srcResolved.mount.fs.readFile(srcResolved.relativePath);
299
- await srcResolved.mount.fs.writeFile(dstResolved.relativePath, content);
300
- }
301
- async readDirStat(path) {
302
- const { mount, relativePath } = this.resolve(path);
303
- if (mount.fs.readDirStat) {
304
- return mount.fs.readDirStat(relativePath);
305
- }
306
- // Fallback: readDirWithTypes + stat for each entry.
307
- const entries = await mount.fs.readDirWithTypes(relativePath);
308
- const normalized = normalizePath(path);
309
- const results = [];
310
- for (const entry of entries) {
311
- const entryPath = normalized === "/" ? `/${entry.name}` : `${normalized}/${entry.name}`;
312
- const stat = await mount.fs.stat(entryPath);
313
- results.push({ ...entry, stat });
314
- }
315
- return results;
316
- }
317
- // -----------------------------------------------------------------------
318
- // Helpers
319
- // -----------------------------------------------------------------------
320
- /**
321
- * Get basenames of child mount points under a directory.
322
- * For example, if mounts exist at /dev and /proc, calling with "/" returns ["dev", "proc"].
323
- */
324
- getChildMountBasenames(dirPath) {
325
- const names = [];
326
- for (const mount of this.mounts) {
327
- if (mount.path === "/")
328
- continue;
329
- const mountParent = parentPath(mount.path);
330
- if (mountParent === dirPath) {
331
- names.push(basename(mount.path));
332
- }
333
- }
334
- return names;
335
- }
336
- /**
337
- * Synchronous open preparation (O_CREAT, O_EXCL, O_TRUNC).
338
- * Delegates to the underlying backend's prepareOpenSync if it exists.
339
- */
340
- prepareOpenSync(path, flags) {
341
- const { mount, relativePath } = this.resolve(path);
342
- if (flags & ~0 && mount.readOnly) {
343
- // Check for write flags (O_CREAT=0o100, O_TRUNC=0o1000)
344
- const O_CREAT = 0o100;
345
- const O_TRUNC = 0o1000;
346
- if ((flags & O_CREAT) || (flags & O_TRUNC)) {
347
- this.assertWritable(mount, path);
348
- }
349
- }
350
- const backend = mount.fs;
351
- return backend.prepareOpenSync?.(relativePath, flags) ?? false;
352
- }
353
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Permission enforcement layer.
3
- *
4
- * Deny-by-default access control. Wraps VFS and other kernel operations
5
- * with permission checks that throw on denial.
6
- */
7
- import type { Permissions } from "./types.js";
8
- import type { VirtualFileSystem } from "./vfs.js";
9
- /**
10
- * Normalize a filesystem path for permission checks.
11
- *
12
- * Resolves `.` and `..` components and collapses repeated slashes so that
13
- * permission callbacks always see the canonical path. Without this,
14
- * `/home/user/project/../../../etc/passwd` would pass a naive
15
- * `startsWith('/home/user/project')` check.
16
- */
17
- export declare function normalizeFsPath(p: string): string;
18
- /**
19
- * Wrap a VFS with permission checks on every operation.
20
- */
21
- export declare function wrapFileSystem(fs: VirtualFileSystem, permissions?: Permissions): VirtualFileSystem;
22
- /**
23
- * Filter an env record through the env permission check.
24
- * Returns only allowed key-value pairs.
25
- */
26
- export declare function filterEnv(env: Record<string, string> | undefined, permissions?: Permissions): Record<string, string>;
27
- /**
28
- * Check childProcess permission before spawning.
29
- * No-op when no permissions or no childProcess check is configured.
30
- */
31
- export declare function checkChildProcess(permissions: Permissions | undefined, command: string, args: string[], cwd?: string): void;
32
- export declare const allowAllFs: Pick<Permissions, "fs">;
33
- export declare const allowAllNetwork: Pick<Permissions, "network">;
34
- export declare const allowAllChildProcess: Pick<Permissions, "childProcess">;
35
- export declare const allowAllEnv: Pick<Permissions, "env">;
36
- export declare const allowAll: Permissions;
@@ -1,150 +0,0 @@
1
- /**
2
- * Permission enforcement layer.
3
- *
4
- * Deny-by-default access control. Wraps VFS and other kernel operations
5
- * with permission checks that throw on denial.
6
- */
7
- import { KernelError } from "./types.js";
8
- function checkPermission(check, request, errorFactory) {
9
- if (!check)
10
- throw errorFactory(request);
11
- const decision = check(request);
12
- if (!decision?.allow)
13
- throw errorFactory(request, decision?.reason);
14
- }
15
- function fsError(op, path, reason) {
16
- const msg = reason
17
- ? `permission denied, ${op} '${path ?? ""}': ${reason}`
18
- : `permission denied, ${op} '${path ?? ""}'`;
19
- return new KernelError("EACCES", msg);
20
- }
21
- /**
22
- * Normalize a filesystem path for permission checks.
23
- *
24
- * Resolves `.` and `..` components and collapses repeated slashes so that
25
- * permission callbacks always see the canonical path. Without this,
26
- * `/home/user/project/../../../etc/passwd` would pass a naive
27
- * `startsWith('/home/user/project')` check.
28
- */
29
- export function normalizeFsPath(p) {
30
- // Collapse repeated slashes
31
- let cleaned = p.replace(/\/+/g, "/");
32
- if (cleaned.length > 1 && cleaned.endsWith("/")) {
33
- cleaned = cleaned.slice(0, -1);
34
- }
35
- const isAbsolute = cleaned.startsWith("/");
36
- const parts = cleaned.split("/");
37
- const resolved = [];
38
- for (const seg of parts) {
39
- if (seg === "" || seg === ".")
40
- continue;
41
- if (seg === "..") {
42
- if (resolved.length > 0)
43
- resolved.pop();
44
- }
45
- else {
46
- resolved.push(seg);
47
- }
48
- }
49
- const result = (isAbsolute ? "/" : "") + resolved.join("/");
50
- return result || (isAbsolute ? "/" : ".");
51
- }
52
- /**
53
- * Wrap a VFS with permission checks on every operation.
54
- */
55
- export function wrapFileSystem(fs, permissions) {
56
- const check = (op, path) => {
57
- checkPermission(permissions?.fs, { op, path: normalizeFsPath(path) }, (req, reason) => fsError(op, req.path, reason));
58
- };
59
- const wrapped = {
60
- prepareOpenSync: (path, flags) => {
61
- if ((flags & 0o100) !== 0 || (flags & 0o1000) !== 0) {
62
- check("write", path);
63
- }
64
- const syncFs = fs;
65
- return syncFs.prepareOpenSync?.(path, flags) ?? false;
66
- },
67
- readFile: async (path) => { check("read", path); return fs.readFile(path); },
68
- readTextFile: async (path) => { check("read", path); return fs.readTextFile(path); },
69
- readDir: async (path) => { check("readdir", path); return fs.readDir(path); },
70
- readDirWithTypes: async (path) => { check("readdir", path); return fs.readDirWithTypes(path); },
71
- writeFile: async (path, content) => { check("write", path); return fs.writeFile(path, content); },
72
- createDir: async (path) => { check("createDir", path); return fs.createDir(path); },
73
- mkdir: async (path, options) => { check("mkdir", path); return fs.mkdir(path, options); },
74
- exists: async (path) => { check("exists", path); return fs.exists(path); },
75
- stat: async (path) => { check("stat", path); return fs.stat(path); },
76
- removeFile: async (path) => { check("rm", path); return fs.removeFile(path); },
77
- removeDir: async (path) => { check("rm", path); return fs.removeDir(path); },
78
- rename: async (oldPath, newPath) => {
79
- check("rename", oldPath);
80
- check("rename", newPath);
81
- return fs.rename(oldPath, newPath);
82
- },
83
- realpath: async (path) => { check("read", path); return fs.realpath(path); },
84
- symlink: async (target, linkPath) => { check("symlink", linkPath); return fs.symlink(target, linkPath); },
85
- readlink: async (path) => { check("readlink", path); return fs.readlink(path); },
86
- lstat: async (path) => { check("stat", path); return fs.lstat(path); },
87
- link: async (oldPath, newPath) => { check("link", newPath); return fs.link(oldPath, newPath); },
88
- chmod: async (path, mode) => { check("chmod", path); return fs.chmod(path, mode); },
89
- chown: async (path, uid, gid) => { check("chown", path); return fs.chown(path, uid, gid); },
90
- utimes: async (path, atime, mtime) => { check("utimes", path); return fs.utimes(path, atime, mtime); },
91
- truncate: async (path, length) => { check("truncate", path); return fs.truncate(path, length); },
92
- pread: async (path, offset, length) => { check("read", path); return fs.pread(path, offset, length); },
93
- pwrite: async (path, offset, data) => { check("write", path); return fs.pwrite(path, offset, data); },
94
- };
95
- return wrapped;
96
- }
97
- /**
98
- * Filter an env record through the env permission check.
99
- * Returns only allowed key-value pairs.
100
- */
101
- export function filterEnv(env, permissions) {
102
- if (!env)
103
- return {};
104
- if (!permissions?.env)
105
- return {};
106
- const result = {};
107
- for (const [key, value] of Object.entries(env)) {
108
- const request = { op: "read", key, value };
109
- const decision = permissions.env(request);
110
- if (decision?.allow) {
111
- result[key] = value;
112
- }
113
- }
114
- return result;
115
- }
116
- /**
117
- * Check childProcess permission before spawning.
118
- * No-op when no permissions or no childProcess check is configured.
119
- */
120
- export function checkChildProcess(permissions, command, args, cwd) {
121
- if (!permissions?.childProcess)
122
- return;
123
- const request = { command, args, cwd };
124
- const decision = permissions.childProcess(request);
125
- if (!decision?.allow) {
126
- const msg = decision?.reason
127
- ? `permission denied, spawn '${command}': ${decision.reason}`
128
- : `permission denied, spawn '${command}'`;
129
- throw new KernelError("EACCES", msg);
130
- }
131
- }
132
- // Permission presets
133
- export const allowAllFs = {
134
- fs: () => ({ allow: true }),
135
- };
136
- export const allowAllNetwork = {
137
- network: () => ({ allow: true }),
138
- };
139
- export const allowAllChildProcess = {
140
- childProcess: () => ({ allow: true }),
141
- };
142
- export const allowAllEnv = {
143
- env: () => ({ allow: true }),
144
- };
145
- export const allowAll = {
146
- ...allowAllFs,
147
- ...allowAllNetwork,
148
- ...allowAllChildProcess,
149
- ...allowAllEnv,
150
- };
@@ -1,64 +0,0 @@
1
- /**
2
- * Pipe manager.
3
- *
4
- * Creates and manages pipes for inter-process communication.
5
- * Supports cross-runtime pipes: data flows through kernel-managed buffers.
6
- * SharedArrayBuffer ring buffers are deferred — this uses buffered pipes.
7
- */
8
- import type { FileDescription } from "./types.js";
9
- import { FILETYPE_PIPE } from "./types.js";
10
- import type { ProcessFDTable } from "./fd-table.js";
11
- export interface PipeEnd {
12
- description: FileDescription;
13
- filetype: typeof FILETYPE_PIPE;
14
- }
15
- /** Maximum buffered bytes per pipe before writers block or O_NONBLOCK returns EAGAIN. */
16
- export declare const MAX_PIPE_BUFFER_BYTES = 65536;
17
- export declare class PipeManager {
18
- private pipes;
19
- /** Map description ID → pipe ID for routing reads/writes */
20
- private descToPipe;
21
- private nextPipeId;
22
- private nextDescId;
23
- /** Called before EPIPE when a write hits a closed read end. Receives writer PID. */
24
- onBrokenPipe: ((pid: number) => void) | null;
25
- /**
26
- * Create a pipe. Returns two FileDescriptions:
27
- * one for reading and one for writing.
28
- */
29
- createPipe(): {
30
- read: PipeEnd;
31
- write: PipeEnd;
32
- };
33
- /** Write data to a pipe's write end. Delivers SIGPIPE via onBrokenPipe when read end is closed. */
34
- write(descriptionId: number, data: Uint8Array, writerPid?: number): number | Promise<number>;
35
- /** Read data from a pipe's read end. Returns null on EOF. */
36
- read(descriptionId: number, length: number): Promise<Uint8Array | null>;
37
- /** Close one end of a pipe. */
38
- close(descriptionId: number): void;
39
- /** Check if a description ID belongs to a pipe */
40
- isPipe(descriptionId: number): boolean;
41
- /** Query poll state for a pipe end (used by poll/select syscalls). */
42
- pollState(descriptionId: number): {
43
- readable: boolean;
44
- writable: boolean;
45
- hangup: boolean;
46
- } | null;
47
- /** Get the pipe ID for a description, or undefined if not a pipe */
48
- pipeIdFor(descriptionId: number): number | undefined;
49
- /** Wait for a pipe poll state change (data, capacity, or hangup). */
50
- waitForPoll(descriptionId: number, timeoutMs?: number): Promise<void>;
51
- /**
52
- * Create pipe FDs in the given FD table.
53
- * Returns the FD numbers for {read, write}.
54
- */
55
- createPipeFDs(fdTable: ProcessFDTable): {
56
- readFd: number;
57
- writeFd: number;
58
- };
59
- private bufferSize;
60
- private drainBuffer;
61
- private writeBlocking;
62
- private writeAvailable;
63
- private assertWriteOpen;
64
- }