forked from rivet-dev/secure-exec
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprd.json
More file actions
2831 lines (2831 loc) · 165 KB
/
prd.json
File metadata and controls
2831 lines (2831 loc) · 165 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
"project": "secure-exec",
"branchName": "ralph/kernel-hardening",
"description": "Kernel Hardening & Documentation \u2014 fix critical bugs, replace fake tests, add missing coverage, write docs, implement PTY/process groups/positional I/O, harden bridge host protections, and improve compatibility, and split secure-exec into core + runtime-specific packages",
"userStories": [
{
"id": "US-001",
"title": "Fix FD table memory leak on process exit",
"description": "As a developer, I need FD tables to be cleaned up when processes exit so the kernel doesn't leak memory indefinitely.",
"acceptanceCriteria": [
"In kernel's onExit handler, call fdTableManager.remove(pid) after processTable.markExited(pid, exitCode)",
"Test: spawn N processes, all exit, fdTableManager internal map size === 0 (excluding init process)",
"Test: pipe read/write FileDescriptions are freed after both endpoints' processes exit",
"Typecheck passes",
"Tests pass"
],
"priority": 1,
"passes": true,
"notes": "P0 \u2014 packages/kernel/src/process-table.ts, fd-table.ts. fdTableManager.remove(pid) exists at fd-table.ts:274 but is never called."
},
{
"id": "US-002",
"title": "Return EIO for SharedArrayBuffer 1MB overflow in WasmVM",
"description": "As a developer, I need large file reads to fail with a clear error instead of silently truncating data.",
"acceptanceCriteria": [
"When kernel fdRead returns >1MB, WasmVM worker returns EIO (errno 76) instead of truncated data",
"Test: write 2MB file to VFS, attempt fdRead from WasmVM, verify error (not truncated data)",
"Typecheck passes",
"Tests pass"
],
"priority": 2,
"passes": true,
"notes": "P0 \u2014 packages/runtime/wasmvm/src/syscall-rpc.ts. 1MB SharedArrayBuffer for all response data."
},
{
"id": "US-003",
"title": "Replace fake Node driver security test with real boundary tests",
"description": "As a developer, I need security tests that actually prove host filesystem access is blocked, not just that the VFS is empty.",
"acceptanceCriteria": [
"Old negative assertion ('not.toContain root:x:0:0') removed",
"New test: fs.readFileSync('/etc/passwd') \u2192 error.code === 'ENOENT'",
"New test: symlink /tmp/escape \u2192 /etc/passwd, read /tmp/escape \u2192 ENOENT",
"New test: fs.readFileSync('../../etc/passwd') from cwd /app \u2192 ENOENT",
"All assertions unconditional",
"Typecheck passes",
"Tests pass"
],
"priority": 3,
"passes": true,
"notes": "P1 \u2014 packages/runtime/node/test/driver.test.ts \u2014 'cannot access host filesystem directly'"
},
{
"id": "US-004",
"title": "Replace fake child_process routing test with spy driver",
"description": "As a developer, I need the child_process routing test to prove routing actually happened, not just that a mock returned canned output.",
"acceptanceCriteria": [
"Spy driver records: { command: 'echo', args: ['hello'], callerPid: <node-pid> }",
"Assert spy.calls.length === 1",
"Assert spy.calls[0].command === 'echo'",
"Assert output contains mock response",
"Typecheck passes",
"Tests pass"
],
"priority": 4,
"passes": true,
"notes": "P1 \u2014 packages/runtime/node/test/driver.test.ts \u2014 'child_process.spawn routes through kernel'"
},
{
"id": "US-005",
"title": "Replace placeholder fork bomb test with honest concurrent spawn test",
"description": "As a developer, I need the process spawning test to honestly reflect what it tests and verify PID uniqueness.",
"acceptanceCriteria": [
"Test renamed to 'concurrent child process spawning' (or similar honest name)",
"Test spawns 10+ child processes, verifies each gets unique PID from kernel process table",
"All assertions unconditional",
"Typecheck passes",
"Tests pass"
],
"priority": 5,
"passes": true,
"notes": "P1 \u2014 packages/runtime/node/test/driver.test.ts \u2014 'cannot spawn unlimited processes'"
},
{
"id": "US-006",
"title": "Fix stdin tests to verify full stdin\u2192process\u2192stdout pipeline",
"description": "As a developer, I need stdin tests that prove the full pipeline works, not just kernel\u2192driver delivery.",
"acceptanceCriteria": [
"MockRuntimeDriver supports echoStdin config \u2014 writeStdin data immediately emitted as stdout",
"Test: writeStdin + closeStdin \u2192 stdout contains written data",
"Test: multiple writeStdin calls \u2192 stdout contains all chunks concatenated",
"Typecheck passes",
"Tests pass"
],
"priority": 6,
"passes": true,
"notes": "P1 \u2014 packages/kernel/test/kernel-integration.test.ts \u2014 stdin streaming tests"
},
{
"id": "US-007",
"title": "Add fdSeek test coverage for all seek modes",
"description": "As a developer, I need fdSeek tested for SEEK_SET, SEEK_CUR, SEEK_END, and pipe rejection.",
"acceptanceCriteria": [
"Test: write 'hello world', open, fdSeek(0, SEEK_SET), read returns 'hello world'",
"Test: read 5 bytes, fdSeek(0, SEEK_SET), read 5 bytes \u2192 both return 'hello'",
"Test: fdSeek(0, SEEK_END), read \u2192 returns empty (EOF)",
"Test: fdSeek on pipe FD \u2192 throws ESPIPE or similar error",
"Typecheck passes",
"Tests pass"
],
"priority": 7,
"passes": true,
"notes": "P2 \u2014 packages/kernel/src/types.ts:167-172 (KernelInterface.fdSeek). Zero test coverage."
},
{
"id": "US-008",
"title": "Add permission wrapper deny scenario tests",
"description": "As a developer, I need tests proving the permission system blocks operations when configured restrictively.",
"acceptanceCriteria": [
"Test: createKernel with permissions: { fs: false }, attempt writeFile \u2192 throws EACCES",
"Test: createKernel with permissions: { fs: (req) => req.path.startsWith('/tmp') }, write /tmp \u2192 succeeds, write /etc \u2192 EACCES",
"Test: createKernel with permissions: { childProcess: false }, attempt spawn \u2192 throws or blocked",
"Test: verify env filtering works (filterEnv with restricted keys)",
"Typecheck passes",
"Tests pass"
],
"priority": 8,
"passes": true,
"notes": "P2 \u2014 packages/kernel/src/permissions.ts. Zero test coverage for deny scenarios."
},
{
"id": "US-009",
"title": "Add stdio FD override wiring tests",
"description": "As a developer, I need tests verifying that stdinFd/stdoutFd/stderrFd overrides during spawn correctly wire the FD table.",
"acceptanceCriteria": [
"Test: spawn with stdinFd: pipeReadEnd \u2192 child's FD 0 points to pipe read description",
"Test: spawn with stdoutFd: pipeWriteEnd \u2192 child's FD 1 points to pipe write description",
"Test: spawn with all three overrides \u2192 FD table has correct descriptions for 0, 1, 2",
"Test: parent FD table unchanged after child spawn with overrides",
"Typecheck passes",
"Tests pass"
],
"priority": 9,
"passes": true,
"notes": "P2 \u2014 packages/kernel/src/kernel.ts:432-476. Complex wiring, completely untested in isolation."
},
{
"id": "US-010",
"title": "Add concurrent PID stress test (100 processes)",
"description": "As a developer, I need stress tests to verify PID uniqueness and exit code capture under high concurrency.",
"acceptanceCriteria": [
"Test: spawn 100 processes concurrently, collect all PIDs, verify all unique",
"Test: spawn 100 processes, wait all, verify all exit codes captured correctly",
"Typecheck passes",
"Tests pass"
],
"priority": 10,
"passes": true,
"notes": "P2 \u2014 packages/kernel/test/kernel-integration.test.ts. Current test only spawns 10."
},
{
"id": "US-011",
"title": "Add pipe refcount edge case tests (multi-writer EOF)",
"description": "As a developer, I need tests verifying pipe EOF only triggers when ALL write-end holders close.",
"acceptanceCriteria": [
"Test: create pipe, dup write end (two references), close one \u2192 reader still blocks (not EOF)",
"Test: close second write end \u2192 reader gets EOF",
"Test: write through both references \u2192 reader receives both writes",
"Typecheck passes",
"Tests pass"
],
"priority": 11,
"passes": true,
"notes": "P2 \u2014 packages/kernel/src/pipe-manager.ts"
},
{
"id": "US-012",
"title": "Add process exit FD cleanup chain verification tests",
"description": "As a developer, I need tests proving the full cleanup chain: process exits \u2192 FD table removed \u2192 refcounts decremented \u2192 pipe ends freed.",
"acceptanceCriteria": [
"Test: spawn process with open FD to pipe write end, process exits \u2192 pipe read end gets EOF",
"Test: spawn process, open 10 FDs, process exits \u2192 FDTableManager has no entry for that PID",
"Typecheck passes",
"Tests pass"
],
"priority": 12,
"passes": true,
"notes": "P2 \u2014 depends on US-001 FD leak fix being in place"
},
{
"id": "US-013",
"title": "Clear zombie cleanup timers on kernel dispose",
"description": "As a developer, I need zombie cleanup timers cleared when the kernel is disposed to avoid post-dispose timer firings.",
"acceptanceCriteria": [
"Store timer IDs during zombie scheduling, clear them in terminateAll() or new dispose() method",
"Test: spawn process, let it exit (becomes zombie), immediately dispose kernel \u2192 no timer warnings",
"Typecheck passes",
"Tests pass"
],
"priority": 13,
"passes": true,
"notes": "P2 \u2014 packages/kernel/src/process-table.ts:78-79. 60s setTimeout may fire after dispose."
},
{
"id": "US-014",
"title": "Ensure WASM binary availability in CI",
"description": "As a developer, I need CI to fail if the WASM binary is missing so critical WasmVM tests don't silently skip.",
"acceptanceCriteria": [
"CI pipeline builds wasmvm/target/wasm32-wasip1/release/multicall.wasm before test runs, OR add CI-only test asserting hasWasmBinary === true",
"Document in CLAUDE.md how to build the WASM binary locally",
"Typecheck passes",
"Tests pass"
],
"priority": 14,
"passes": true,
"notes": "P2 \u2014 tests gated behind skipIf(!hasWasmBinary) silently skip in CI"
},
{
"id": "US-015",
"title": "Replace WasmVM error string matching with structured error codes",
"description": "As a developer, I need kernel errors to include a structured code field so WasmVM errno mapping doesn't rely on brittle string matching.",
"acceptanceCriteria": [
"Kernel errors include structured code field (e.g., { code: 'EBADF', message: '...' })",
"WasmVM kernel-worker maps error.code \u2192 WASI errno instead of string matching",
"Fallback to string matching only if code field is missing",
"Test: throw error with code 'ENOENT' \u2192 worker maps to errno 44",
"Typecheck passes",
"Tests pass"
],
"priority": 15,
"passes": true,
"notes": "P2 \u2014 packages/runtime/wasmvm/src/kernel-worker.ts. mapErrorToErrno() uses msg.includes('EBADF')."
},
{
"id": "US-016",
"title": "Write kernel quickstart guide",
"description": "As a user, I need a quickstart guide to get started with the kernel (install, create kernel, mount drivers, exec, spawn, VFS, cleanup).",
"acceptanceCriteria": [
"File docs/kernel/quickstart.mdx created",
"Covers: install packages, create kernel with VFS, mount WasmVM and Node drivers, kernel.exec(), kernel.spawn() with streaming, cross-runtime example, VFS file read/write, kernel.dispose()",
"Follows Mintlify MDX style (50-70% code, short prose, working examples)",
"Typecheck passes"
],
"priority": 16,
"passes": true,
"notes": "P3 \u2014 code-heavy style matching sandbox-agent/docs"
},
{
"id": "US-017",
"title": "Write kernel API reference",
"description": "As a user, I need a complete API reference for all kernel types, methods, and interfaces.",
"acceptanceCriteria": [
"File docs/kernel/api-reference.mdx created",
"Covers: createKernel(options), Kernel methods, ExecOptions/ExecResult, SpawnOptions/ManagedProcess, RuntimeDriver/DriverProcess, KernelInterface syscalls, ProcessContext, Permission types",
"Follows Mintlify MDX style",
"Typecheck passes"
],
"priority": 17,
"passes": true,
"notes": "P3 \u2014 full type reference for kernel package"
},
{
"id": "US-018",
"title": "Write cross-runtime integration guide",
"description": "As a user, I need a guide explaining how to use multiple runtimes together through the kernel.",
"acceptanceCriteria": [
"File docs/kernel/cross-runtime.mdx created",
"Covers: mount order and command resolution table, child_process routing, cross-runtime pipes, VFS sharing, npm run scripts round-trip, error/exit code propagation, stdin streaming",
"Follows Mintlify MDX style",
"Typecheck passes"
],
"priority": 18,
"passes": true,
"notes": "P3"
},
{
"id": "US-019",
"title": "Write custom RuntimeDriver guide",
"description": "As a user, I need a guide for implementing a custom RuntimeDriver with the kernel.",
"acceptanceCriteria": [
"File docs/kernel/custom-runtime.mdx created",
"Covers: RuntimeDriver interface contract, minimal echo driver example, KernelInterface syscalls, ProcessContext/DriverProcess lifecycle, stdio routing, command registration, testing patterns",
"Follows Mintlify MDX style",
"Typecheck passes"
],
"priority": 19,
"passes": true,
"notes": "P3"
},
{
"id": "US-020",
"title": "Add kernel group to docs.json navigation",
"description": "As a user, I need the kernel docs visible in the sidebar navigation.",
"acceptanceCriteria": [
"docs.json has new 'Kernel' group between 'Features' and 'Reference'",
"Group includes quickstart, api-reference, cross-runtime, custom-runtime pages",
"Typecheck passes"
],
"priority": 20,
"passes": true,
"notes": "P3 \u2014 update existing docs/docs.json"
},
{
"id": "US-021",
"title": "Add process group and session ID tracking to kernel",
"description": "As a developer, I need pgid/sid tracking and setpgid/setsid/getpgid/getsid syscalls for job control support.",
"acceptanceCriteria": [
"ProcessEntry has pgid and sid fields, defaulting to parent's values",
"setpgid(pid, pgid) works: process can create new group or join existing group",
"setsid(pid) creates new session: sid=pid, pgid=pid",
"kill(-pgid, signal) delivers signal to all processes in group",
"getpgid(pid) and getsid(pid) return correct values",
"Child inherits parent's pgid and sid by default",
"Test: create process group, spawn 3 children in it, kill(-pgid, SIGTERM) \u2192 all 3 receive signal",
"Test: setsid creates new session, process becomes session leader",
"Test: setpgid with invalid pgid \u2192 EPERM",
"Typecheck passes",
"Tests pass"
],
"priority": 21,
"passes": true,
"notes": "P4 \u2014 packages/kernel/src/process-table.ts. Prerequisite for PTY/interactive shell."
},
{
"id": "US-022",
"title": "Create PTY device layer \u2014 master/slave pair and bidirectional I/O",
"description": "As a developer, I need a PtyManager that allocates PTY master/slave FD pairs with bidirectional data flow.",
"acceptanceCriteria": [
"openpty(pid) returns master FD, slave FD, and /dev/pts/N path",
"Writing to master \u2192 readable from slave (input direction)",
"Writing to slave \u2192 readable from master (output direction)",
"isatty(slaveFd) returns true, isatty(pipeFd) returns false",
"Multiple PTY pairs can coexist (separate /dev/pts/0, /dev/pts/1, etc.)",
"Master close \u2192 slave reads get EIO (terminal hangup)",
"Slave close \u2192 master reads get EIO",
"Test: open PTY, write 'hello\\n' to master, read from slave \u2192 'hello\\n'",
"Test: open PTY, write 'hello\\n' to slave, read from master \u2192 'hello\\n'",
"Test: isatty on slave FD returns true",
"Typecheck passes",
"Tests pass"
],
"priority": 22,
"passes": true,
"notes": "P4 \u2014 new packages/kernel/src/pty.ts. Core infrastructure; line discipline in next story."
},
{
"id": "US-023",
"title": "Add PTY line discipline \u2014 canonical mode, raw mode, echo, and signal generation",
"description": "As a developer, I need the PTY to support canonical/raw modes, echo, and signal character handling.",
"acceptanceCriteria": [
"Canonical mode: input buffered until newline, backspace erases last char",
"Raw mode: bytes pass through immediately with no buffering",
"Echo mode: input bytes echoed back through master for display",
"^C in canonical mode \u2192 SIGINT delivered to foreground process group",
"^Z \u2192 SIGTSTP, ^\\ \u2192 SIGQUIT, ^D at start of line \u2192 EOF",
"Test: raw mode \u2014 write single byte to master, immediately readable from slave",
"Test: canonical mode \u2014 write 'ab\\x7fc\\n' \u2192 slave reads 'ac\\n'",
"Test: ^C on master \u2192 SIGINT to foreground pgid",
"Typecheck passes",
"Tests pass"
],
"priority": 23,
"passes": true,
"notes": "P4 \u2014 extends pty.ts from US-022. Depends on US-021 for process group signal delivery."
},
{
"id": "US-024",
"title": "Add termios support (terminal attributes)",
"description": "As a developer, I need tcgetattr/tcsetattr/tcsetpgrp/tcgetpgrp syscalls so processes can configure terminal behavior.",
"acceptanceCriteria": [
"Default termios: canonical mode on, echo on, isig on, standard control characters",
"tcsetattr with icanon: false switches to raw mode \u2014 immediate byte delivery",
"tcsetattr with echo: false disables echo",
"tcsetpgrp sets foreground process group \u2014 ^C delivers SIGINT to that group only",
"Programs can read current termios via tcgetattr",
"Test: spawn on PTY in canonical mode, verify line buffering",
"Test: switch to raw mode via tcsetattr, verify immediate byte delivery",
"Test: disable echo, verify master doesn't receive echo bytes",
"Test: tcsetpgrp changes which group receives ^C",
"Typecheck passes",
"Tests pass"
],
"priority": 24,
"passes": true,
"notes": "P4 \u2014 new packages/kernel/src/termios.ts. Wire into KernelInterface and WasmVM host imports. Depends on US-022/023."
},
{
"id": "US-025",
"title": "Add kernel.openShell() interactive shell integration",
"description": "As a developer, I need a convenience method that wires PTY + process groups + termios for interactive shell use.",
"acceptanceCriteria": [
"kernel.openShell() returns handle with write/onData/resize/kill/wait",
"Shell process sees isatty(0) === true",
"Writing 'echo hello\\n' to handle \u2192 onData receives 'hello\\n' (plus prompt/echo)",
"Writing ^C \u2192 shell receives SIGINT (doesn't exit, just cancels current line)",
"Writing ^D on empty line \u2192 shell exits (EOF)",
"resize() \u2192 SIGWINCH delivered to foreground process group",
"Test: open shell, write 'echo hello\\n', verify output contains 'hello'",
"Test: open shell, write ^C, verify shell still running",
"Test: open shell, write ^D, verify shell exits",
"Test: resize, verify SIGWINCH delivered",
"Typecheck passes",
"Tests pass"
],
"priority": 25,
"passes": true,
"notes": "P4 \u2014 packages/kernel/src/kernel.ts. Depends on US-021 (process groups), US-022/023 (PTY), US-024 (termios)."
},
{
"id": "US-026",
"title": "Create kernel.connectTerminal() and CLI interactive shell",
"description": "As a developer, I need a reusable connectTerminal() method and a CLI entry point so I can get an interactive shell inside the kernel from any Node program or from the command line.",
"acceptanceCriteria": [
"kernel.connectTerminal(options?) exported \u2014 wires openShell() to process.stdin/stdout/resize, returns Promise<number> (exit code)",
"connectTerminal sets raw mode, forwards stdin, forwards stdout, handles resize, restores terminal on exit",
"connectTerminal accepts same options as openShell (command, args, env, cols, rows) plus onData override",
"Script at scripts/shell.ts uses kernel.connectTerminal() as a one-liner CLI entry point",
"Running the script drops into an interactive shell inside the kernel",
"process.stdin set to raw mode \u2014 arrow keys, tab, backspace pass through correctly",
"^C sends SIGINT (cancels command, does not exit shell)",
"^D on empty line exits the shell",
"Window resize triggers shell.resize() with current terminal dimensions",
"node -e \"console.log(42)\" works interactively (cross-runtime via kernel)",
"Shell exit restores terminal to normal mode and exits with shell exit code",
"Accepts --wasm-path and --no-node flags",
"Typecheck passes",
"Tests pass"
],
"priority": 26,
"passes": true,
"notes": "P4 \u2014 depends on US-025 (kernel.openShell). kernel.connectTerminal() is the reusable API; scripts/shell.ts is the CLI wrapper that calls it."
},
{
"id": "US-027",
"title": "Implement /dev/fd pseudo-directory",
"description": "As a developer, I need /dev/fd/N paths to work so bash process substitution and heredoc patterns function correctly.",
"acceptanceCriteria": [
"readFile('/dev/fd/0') reads from the process's stdin FD",
"readFile('/dev/fd/N') where N is an open file FD \u2192 returns file content at current cursor",
"stat('/dev/fd/N') returns stat for the underlying file",
"readDir('/dev/fd') lists open FD numbers as directory entries",
"open('/dev/fd/N') equivalent to dup(N)",
"Reading /dev/fd/N where N is not open \u2192 EBADF",
"Test: open file as FD 5, read via /dev/fd/5 \u2192 same content",
"Test: create pipe, write to write end, read via /dev/fd/<readEnd> \u2192 pipe data",
"Test: readDir('/dev/fd') lists 0, 1, 2 at minimum",
"Typecheck passes",
"Tests pass"
],
"priority": 27,
"passes": true,
"notes": "P4 \u2014 packages/kernel/src/device-layer.ts. Requires PID context in device layer operations."
},
{
"id": "US-028",
"title": "Implement fdPread and fdPwrite (positional I/O)",
"description": "As a developer, I need positional read/write that operates at a given offset without moving the FD cursor.",
"acceptanceCriteria": [
"fdPread(pid, fd, length, offset) reads at offset without changing FD cursor",
"fdPwrite(pid, fd, data, offset) writes at offset without changing FD cursor",
"After pread/pwrite, subsequent fdRead/fdWrite continues from original cursor position",
"fdPread on pipe \u2192 ESPIPE",
"fdPwrite on pipe \u2192 ESPIPE",
"Test: write 'hello world', fdPread(0, 5) \u2192 'hello', then fdRead \u2192 'hello world' (cursor at 0)",
"Test: fdPread(6, 5) \u2192 'world', cursor unchanged",
"Test: fdPwrite at offset 6, fdRead from 0 \u2192 written bytes visible at offset 6",
"Test: fdPread on pipe FD \u2192 ESPIPE",
"Typecheck passes",
"Tests pass"
],
"priority": 28,
"passes": true,
"notes": "P4 \u2014 packages/kernel/src/fd-table.ts, kernel.ts, wasmvm kernel-worker. Wire into existing WasmVM stubs."
},
{
"id": "US-029",
"title": "Write PTY and interactive shell documentation",
"description": "As a user, I need docs for PTY support, openShell(), terminal configuration, and process group job control.",
"acceptanceCriteria": [
"File docs/kernel/interactive-shell.mdx created",
"Covers: what PTY enables, kernel.openShell() quickstart, wiring to terminal UI, process groups/job control, termios config, resize/SIGWINCH, full Node.js CLI example",
"Follows Mintlify MDX style",
"Typecheck passes"
],
"priority": 29,
"passes": true,
"notes": "P5 \u2014 depends on US-025 (openShell implementation)"
},
{
"id": "US-030",
"title": "Update kernel API reference for new P4 syscalls",
"description": "As a user, I need the API reference updated with openpty, termios, process group, and positional I/O syscalls.",
"acceptanceCriteria": [
"docs/kernel/api-reference.mdx updated with: kernel.openShell(), openpty(pid), tcgetattr/tcsetattr/tcsetpgrp/tcgetpgrp, setpgid/setsid/getpgid/getsid, fdPread/fdPwrite",
"Device layer notes for /dev/fd, /dev/ptmx, /dev/pts/*",
"Termios type reference added",
"Typecheck passes"
],
"priority": 30,
"passes": true,
"notes": "P5 \u2014 update existing docs/kernel/api-reference.mdx. Depends on US-017 and P4 stories."
},
{
"id": "US-031",
"title": "Add global host resource budgets to bridge path",
"description": "As a developer, I need configurable caps on output bytes, bridge calls, timers, and child processes to prevent host resource exhaustion.",
"acceptanceCriteria": [
"ResourceBudget config added to NodeRuntimeOptions: maxOutputBytes, maxBridgeCalls, maxTimers, maxChildProcesses",
"Exceeding maxOutputBytes \u2192 subsequent writes silently dropped or error returned",
"Exceeding maxChildProcesses \u2192 child_process.spawn() returns error",
"Exceeding maxTimers \u2192 setInterval/setTimeout throws, existing timers continue",
"Exceeding maxBridgeCalls \u2192 bridge returns error, isolate can catch",
"Kernel: maxProcesses option added to KernelOptions",
"Test: set maxOutputBytes=100, write 200 bytes \u2192 only first 100 captured",
"Test: set maxChildProcesses=3, spawn 5 \u2192 first 3 succeed, last 2 error",
"Test: set maxTimers=5, create 10 intervals \u2192 first 5 succeed, rest throw",
"Test: kernel maxProcesses=10, spawn 15 \u2192 first 10 succeed, rest throw EAGAIN",
"Typecheck passes",
"Tests pass"
],
"priority": 31,
"passes": true,
"notes": "P6 \u2014 packages/secure-exec/src/node/execution-driver.ts, bridge/process.ts, shared/permissions.ts"
},
{
"id": "US-032",
"title": "Enforce maxBuffer on child-process output buffering",
"description": "As a developer, I need execSync/spawnSync to enforce maxBuffer to prevent host memory exhaustion from unbounded output.",
"acceptanceCriteria": [
"execSync with default maxBuffer (1MB): output >1MB \u2192 throws ERR_CHILD_PROCESS_STDIO_MAXBUFFER",
"execSync with maxBuffer: 100 \u2014 output >100 bytes \u2192 throws",
"spawnSync respects maxBuffer on stdout and stderr independently",
"Async exec(cmd, cb) enforces maxBuffer, kills child on exceed",
"Test: execSync producing 2MB output with maxBuffer=1MB \u2192 throws correct error code",
"Test: spawnSync with small maxBuffer \u2192 truncated with correct error",
"Typecheck passes",
"Tests pass"
],
"priority": 32,
"passes": true,
"notes": "P6 \u2014 packages/secure-exec/src/bridge/child-process.ts (710 lines, @ts-nocheck). Lines ~348-357."
},
{
"id": "US-033",
"title": "Add missing fs APIs: cp, mkdtemp, opendir",
"description": "As a developer, I need cp (recursive copy), mkdtemp (temp directory), and opendir (async Dir iterator) in the bridge for Node.js compatibility.",
"acceptanceCriteria": [
"fs.cp/cpSync recursively copies directories with { recursive: true }",
"fs.mkdtemp/mkdtempSync('/tmp/prefix-') creates unique directory with random suffix",
"fs.opendir returns async iterable of Dirent objects",
"All APIs match Node.js signatures",
"Available on fs, fs/promises, and callback forms where applicable",
"Typecheck passes",
"Tests pass"
],
"priority": 33,
"passes": true,
"notes": "P6 \u2014 packages/secure-exec/src/bridge/fs.ts. First batch of 8 missing fs APIs."
},
{
"id": "US-034",
"title": "Add missing fs APIs: glob, statfs, readv, fdatasync, fsync",
"description": "As a developer, I need glob, statfs, readv, fdatasync, and fsync in the bridge for Node.js compatibility.",
"acceptanceCriteria": [
"fs.glob/globSync('**/*.js') returns matching file paths",
"fs.statfs/statfsSync returns object with bsize, blocks, bfree, bavail, type fields",
"fs.readv/readvSync reads into multiple buffers sequentially",
"fs.fdatasync/fdatasyncSync and fs.fsync/fsyncSync resolve without error (no-op for in-memory VFS)",
"All APIs match Node.js signatures",
"Available on fs, fs/promises, and callback forms where applicable",
"Typecheck passes",
"Tests pass"
],
"priority": 34,
"passes": true,
"notes": "P6 \u2014 packages/secure-exec/src/bridge/fs.ts. Second batch of missing fs APIs."
},
{
"id": "US-035",
"title": "Wire deferred fs APIs (chmod, chown, link, symlink, readlink, truncate, utimes) through bridge",
"description": "As a developer, I need the fs APIs that currently throw 'not supported' to delegate to the VFS instead.",
"acceptanceCriteria": [
"fs.chmodSync('/tmp/f', 0o755) succeeds (delegates to VFS)",
"fs.symlinkSync creates symlink, fs.readlinkSync returns target",
"fs.linkSync creates hard link",
"fs.truncateSync truncates file",
"fs.utimesSync updates timestamps",
"fs.chownSync updates ownership",
"fs.watch still throws with clear message ('not supported \u2014 use polling')",
"All available in sync, async callback, and promises forms",
"Permissions checks applied (denied when permissions.fs blocks)",
"Typecheck passes",
"Tests pass"
],
"priority": 35,
"passes": true,
"notes": "P6 \u2014 packages/secure-exec/src/bridge/fs.ts. Remove 'not supported' throws, wire to VFS."
},
{
"id": "US-036",
"title": "Add Express project-matrix fixture",
"description": "As a developer, I need an Express fixture to catch compatibility regressions for the most common Node.js framework.",
"acceptanceCriteria": [
"packages/secure-exec/tests/projects/express-pass/ created with package.json and index.js",
"Express app with 2-3 routes, makes requests, verifies responses, prints deterministic stdout, exits 0",
"Fixture passes in host Node (node index.js \u2192 exit 0, expected stdout)",
"Fixture passes through kernel project-matrix (e2e-project-matrix.test.ts)",
"Fixture passes through secure-exec project-matrix (project-matrix.test.ts)",
"Stdout parity between host and sandbox",
"No sandbox-aware branches in fixture code",
"Typecheck passes",
"Tests pass"
],
"priority": 36,
"passes": true,
"notes": "P6 \u2014 packages/secure-exec/tests/projects/. Must be sandbox-blind."
},
{
"id": "US-037",
"title": "Add Fastify project-matrix fixture",
"description": "As a developer, I need a Fastify fixture to catch compatibility issues in async middleware, schema validation, and structured logging.",
"acceptanceCriteria": [
"packages/secure-exec/tests/projects/fastify-pass/ created with package.json and index.js",
"Fastify app with routes, async handlers, makes requests, verifies responses, exits 0",
"Fixture passes host parity, sandbox-blind, passes both project matrices",
"Typecheck passes",
"Tests pass"
],
"priority": 37,
"passes": true,
"notes": "P6 \u2014 same pattern as Express fixture (US-035)"
},
{
"id": "US-038",
"title": "Add pnpm and bun package manager layout fixtures",
"description": "As a developer, I need fixtures testing pnpm symlink-based and bun hardlink-based node_modules layouts.",
"acceptanceCriteria": [
"packages/secure-exec/tests/projects/pnpm-layout-pass/ \u2014 require('left-pad') resolves through symlinked .pnpm/ structure",
"packages/secure-exec/tests/projects/bun-layout-pass/ \u2014 require('left-pad') resolves through bun's layout",
"Both pass host parity comparison",
"Both pass through kernel and secure-exec project matrices",
"Typecheck passes",
"Tests pass"
],
"priority": 38,
"passes": true,
"notes": "P6 \u2014 Yarn PnP out of scope (needs .pnp.cjs loader hook support)"
},
{
"id": "US-039",
"title": "Remove @ts-nocheck from polyfills.ts and os.ts",
"description": "As a developer, I need type safety restored on these security-critical bridge files.",
"acceptanceCriteria": [
"@ts-nocheck removed from packages/secure-exec/src/bridge/polyfills.ts",
"@ts-nocheck removed from packages/secure-exec/src/bridge/os.ts",
"Zero type errors from tsc --noEmit",
"No runtime behavior changes \u2014 existing tests still pass",
"Typecheck passes",
"Tests pass"
],
"priority": 39,
"passes": true,
"notes": "P6 \u2014 only add type annotations and casts, do NOT change runtime behavior"
},
{
"id": "US-040",
"title": "Remove @ts-nocheck from child-process.ts",
"description": "As a developer, I need type safety restored on the 710-line child-process bridge file.",
"acceptanceCriteria": [
"@ts-nocheck removed from packages/secure-exec/src/bridge/child-process.ts",
"Zero type errors from tsc --noEmit",
"No runtime behavior changes \u2014 existing tests still pass",
"Typecheck passes",
"Tests pass"
],
"priority": 40,
"passes": true,
"notes": "P6 \u2014 largest bridge file (710 lines). Only type annotations/casts, no behavior changes."
},
{
"id": "US-041",
"title": "Remove @ts-nocheck from process.ts and network.ts",
"description": "As a developer, I need type safety restored on the remaining bridge files.",
"acceptanceCriteria": [
"@ts-nocheck removed from packages/secure-exec/src/bridge/process.ts",
"@ts-nocheck removed from packages/secure-exec/src/bridge/network.ts",
"Zero type errors from tsc --noEmit",
"No runtime behavior changes \u2014 existing tests still pass",
"Typecheck passes",
"Tests pass"
],
"priority": 41,
"passes": true,
"notes": "P6 \u2014 final two @ts-nocheck files"
},
{
"id": "US-042",
"title": "Fix v8.serialize/deserialize to use structured clone semantics",
"description": "As a developer, I need v8.serialize to handle Map, Set, RegExp, Date, circular refs, BigInt, etc. instead of using JSON.",
"acceptanceCriteria": [
"v8.serialize(new Map([['a', 1]])) \u2192 roundtrips to Map { 'a' => 1 }",
"v8.serialize(new Set([1, 2])) \u2192 roundtrips to Set { 1, 2 }",
"v8.serialize(/foo/gi) \u2192 roundtrips to /foo/gi",
"v8.serialize(new Date(0)) \u2192 roundtrips to Date(0)",
"Circular references survive roundtrip",
"undefined, NaN, Infinity, -Infinity, BigInt preserved",
"ArrayBuffer and typed arrays preserved",
"Test: roundtrip each type above",
"Typecheck passes",
"Tests pass"
],
"priority": 42,
"passes": true,
"notes": "P7 \u2014 packages/secure-exec/isolate-runtime/src/inject/bridge-initial-globals.ts. Currently uses JSON.stringify/parse."
},
{
"id": "US-043",
"title": "Implement HTTP Agent pooling, upgrade, and trailer APIs",
"description": "As a developer, I need http.Agent connection pooling, HTTP upgrade (WebSocket), trailer headers, and socket events for compatibility with ws, got, axios.",
"acceptanceCriteria": [
"new http.Agent({ keepAlive: true, maxSockets: 5 }) limits concurrent connections",
"Request with Connection: upgrade and 101 response \u2192 upgrade event fires",
"Response with trailer headers \u2192 response.trailers populated",
"request.on('socket', cb) fires with socket-like object",
"Test: Agent with maxSockets=1, two concurrent requests \u2192 second waits for first",
"Test: upgrade request \u2192 upgrade event fires with response and socket",
"Typecheck passes",
"Tests pass"
],
"priority": 43,
"passes": true,
"notes": "P7 \u2014 packages/secure-exec/src/bridge/network.ts"
},
{
"id": "US-044",
"title": "Create codemod example project",
"description": "As a user, I need an example showing how to use secure-exec for safe code transformations.",
"acceptanceCriteria": [
"examples/codemod/ created with package.json and src/index.ts",
"Example reads source file, writes to sandbox VFS, executes codemod, reads result, prints diff",
"pnpm --filter codemod-example start runs successfully",
"Sandbox prevents codemod from accessing host filesystem",
"Typecheck passes"
],
"priority": 44,
"passes": true,
"notes": "P7 \u2014 demonstrates primary use case: running untrusted/generated code safely"
},
{
"id": "US-045",
"title": "Split NodeExecutionDriver into focused modules",
"description": "As a developer, I need the 1756-line monolith broken into isolate-bootstrap, module-resolver, esm-compiler, bridge-setup, and execution-lifecycle modules.",
"acceptanceCriteria": [
"execution-driver.ts reduced to <300 lines (facade + wiring)",
"Extracted modules: isolate-bootstrap.ts, module-resolver.ts, esm-compiler.ts, bridge-setup.ts, execution-lifecycle.ts",
"Each module has a clear single responsibility",
"All existing tests pass without modification",
"No runtime behavior changes \u2014 pure extraction refactor",
"Typecheck passes",
"Tests pass"
],
"priority": 45,
"passes": true,
"notes": "P8 \u2014 packages/secure-exec/src/node/execution-driver.ts. Pure extraction, no behavior changes."
},
{
"id": "US-046",
"title": "Add O(1) ESM module reverse lookup",
"description": "As a developer, I need reverse lookup to use a Map instead of scanning, to avoid quadratic behavior on large import graphs.",
"acceptanceCriteria": [
"Reverse lookup uses Map.get() not Array.find() or iteration",
"Performance: 1000-module import graph resolves in <10ms",
"All existing ESM tests pass",
"Typecheck passes",
"Tests pass"
],
"priority": 46,
"passes": true,
"notes": "P8 \u2014 packages/secure-exec/src/node/execution-driver.ts (or extracted module-resolver.ts after US-044)"
},
{
"id": "US-047",
"title": "Add resolver memoization (negative/positive caches)",
"description": "As a developer, I need require/import resolution to cache results and avoid repeated miss probes.",
"acceptanceCriteria": [
"Same require('nonexistent') called twice \u2192 only one VFS probe",
"Same require('express') called twice \u2192 only one resolution walk",
"package.json in same directory read once, reused for subsequent resolves",
"Caches are per-execution (cleared on dispose)",
"All existing module resolution tests pass",
"Typecheck passes",
"Tests pass"
],
"priority": 47,
"passes": true,
"notes": "P8 \u2014 packages/secure-exec/src/package-bundler.ts, shared/require-setup.ts, node/execution-driver.ts"
},
{
"id": "US-048",
"title": "Fix zombie timer cleanup tests to actually verify timer clearing",
"description": "As a developer, I need the zombie timer cleanup tests to verify timers are actually cleared, not just that dispose() doesn't throw.",
"acceptanceCriteria": [
"ProcessTable exposes zombieTimerCount getter (or equivalent) for test observability",
"Test: spawn process, let it exit \u2192 zombieTimerCount > 0 (timer was scheduled)",
"Test: call kernel.dispose() \u2192 zombieTimerCount === 0 (timer was cleared)",
"Test: with vi.useFakeTimers(), advance 60s after dispose \u2192 no callbacks fire, no errors",
"Tests would FAIL if timers are not actually cleared during dispose",
"Typecheck passes",
"Tests pass"
],
"priority": 48,
"passes": true,
"notes": "P9 \u2014 US-013 implementation was pass-vacuous. Tests only checked dispose() didn't throw. packages/kernel/test/kernel-integration.test.ts and packages/kernel/src/process-table.ts"
},
{
"id": "US-049",
"title": "Fix pnpm layout fixture with real pnpm symlink structure",
"description": "As a developer, I need the pnpm fixture to have a real pnpm-installed node_modules layout so it actually tests symlink-based module resolution.",
"acceptanceCriteria": [
"pnpm-lock.yaml exists in packages/secure-exec/tests/projects/pnpm-layout-pass/",
"node_modules/.pnpm/ directory exists with real symlink structure",
"node_modules/left-pad is a symlink (not a regular directory)",
"fixture.json specifies packageManager: pnpm",
"require(\"left-pad\") resolves through the symlink chain in index.js",
"Fixture passes host parity comparison (node index.js \u2192 exit 0)",
"Fixture passes through kernel and secure-exec project matrices",
"Typecheck passes",
"Tests pass"
],
"priority": 49,
"passes": true,
"notes": "P9 \u2014 US-038 pnpm fixture was a stub with no .pnpm/ structure or pnpm-lock.yaml. packages/secure-exec/tests/projects/pnpm-layout-pass/"
},
{
"id": "US-050",
"title": "Fix bun layout fixture with real bun-installed structure",
"description": "As a developer, I need the bun fixture to have a real bun-installed node_modules layout and correct fixture.json metadata.",
"acceptanceCriteria": [
"bun.lockb exists in packages/secure-exec/tests/projects/bun-layout-pass/",
"fixture.json specifies packageManager: bun (was incorrectly set to npm)",
"node_modules/left-pad installed via bun layout",
"require(\"left-pad\") resolves correctly in index.js",
"Fixture passes host parity comparison (node index.js \u2192 exit 0)",
"Fixture passes through kernel and secure-exec project matrices",
"Typecheck passes",
"Tests pass"
],
"priority": 50,
"passes": true,
"notes": "P9 \u2014 US-038 bun fixture was misnamed. fixture.json said npm, no bun.lockb. packages/secure-exec/tests/projects/bun-layout-pass/"
},
{
"id": "US-051",
"title": "Express and Fastify fixtures should use real HTTP servers",
"description": "As a developer, I need the framework fixtures to start real HTTP servers and make real requests so the network stack is exercised.",
"acceptanceCriteria": [
"Express fixture starts server on port 0 (auto-assign), makes real http.get requests, verifies response status and body",
"Fastify fixture starts server on port 0, makes real http.get requests, verifies response status and body",
"Both fixtures close server and exit cleanly after tests",
"Both still sandbox-blind (no sandbox-specific code)",
"Both still pass host parity comparison",
"Both pass through kernel and secure-exec project matrices",
"Typecheck passes",
"Tests pass"
],
"priority": 51,
"passes": true,
"notes": "P9 \u2014 US-036/037 used EventEmitter mock dispatchers instead of real HTTP. packages/secure-exec/tests/projects/express-pass/ and fastify-pass/"
},
{
"id": "US-052",
"title": "Create @secure-exec/core package and move shared types + utilities",
"description": "As a developer, I need a core package that owns the shared types, constants, and utilities so runtime-specific packages can depend on it without pulling in each other.",
"acceptanceCriteria": [
"Create packages/secure-exec-core/ with package.json (name: @secure-exec/core, deps: buffer, sucrase, text-encoding-utf-8, whatwg-url)",
"Create tsconfig.json extending root tsconfig",
"Extract TIMEOUT_ERROR_MESSAGE and TIMEOUT_EXIT_CODE from isolate.ts into core src/shared/constants.ts",
"Move types.ts and runtime-driver.ts to core/src/",
"Move all shared/* files (api-types, bridge-contract, permissions, in-memory-fs, console-formatter, esm-utils, errors, global-exposure, require-setup) to core/src/shared/",
"Add @secure-exec/core workspace dependency to secure-exec package.json",
"Add @secure-exec/core to turbo.json pipeline (core builds before secure-exec)",
"Update secure-exec barrel (src/index.ts) to re-export moved types/utilities from @secure-exec/core",
"Typecheck passes",
"Tests pass"
],
"priority": 52,
"passes": true,
"notes": "Phase 1a of package-split spec (docs-internal/specs/package-split.md). Shared files have zero isolated-vm imports. Leave bridge/, generated/, isolate-runtime/, facades, and module resolution for subsequent stories."
},
{
"id": "US-053",
"title": "Move bridge guest code, generated artifacts, and build scripts to core",
"description": "As a developer, I need the bridge guest polyfills and generated build artifacts in core so both Node and Browser runtimes can consume them.",
"acceptanceCriteria": [
"Move bridge/ directory (all guest-side polyfill files, zero ivm imports) to core/src/bridge/",
"Move generated/ directory (isolate-runtime.ts, polyfills.ts) to core/src/generated/",
"Move isolate-runtime/ source TypeScript directory to core/src/isolate-runtime/",
"Move scripts/build-polyfills.mjs and scripts/build-isolate-runtime.mjs to core/scripts/",
"Update core build pipeline to run build:polyfills and build:isolate-runtime before tsc",
"Remove these build steps from secure-exec build pipeline",
"Update secure-exec barrel to re-export any generated code exports from core",
"Typecheck passes",
"Tests pass"
],
"priority": 53,
"passes": true,
"notes": "Phase 1b. Bridge guest code has zero ivm imports \u2014 Node injects via context.eval(), Browser imports directly. Generated code is used by both Node and Browser."
},
{
"id": "US-054",
"title": "Move runtime facades and module resolution to core",
"description": "As a developer, I need the NodeRuntime facade and module resolution logic in core since they are runtime-agnostic.",
"acceptanceCriteria": [
"Move runtime.ts (NodeRuntime facade) to core \u2014 export both Runtime and NodeRuntime",
"Move python-runtime.ts to core",
"Move fs-helpers.ts to core",
"Move esm-compiler.ts (the ivm-free top-level one, NOT node/esm-compiler.ts) to core",
"Move module-resolver.ts to core",
"Move package-bundler.ts to core",
"Move bridge-setup.ts (the generated code loader at src/bridge-setup.ts, NOT node/bridge-setup.ts) to core",
"Update cross-references within moved files to use core-local paths",
"Update secure-exec barrel re-exports",
"Typecheck passes",
"Tests pass"
],
"priority": 54,
"passes": true,
"notes": "Phase 1c. runtime.ts has zero ivm imports \u2014 it accepts any NodeRuntimeDriverFactory and delegates. Both Node (createNodeRuntimeDriverFactory) and Browser (createBrowserRuntimeDriverFactory) plug into it."
},
{
"id": "US-055",
"title": "Configure @secure-exec/core subpath exports for internal modules",
"description": "As a developer, I need core to expose internal modules via subpath exports so runtime packages can import them without making them public API.",
"acceptanceCriteria": [
"Add exports map to core package.json with internal/* subpaths (e.g. @secure-exec/core/internal/bridge-loader, @secure-exec/core/internal/generated/isolate-runtime, @secure-exec/core/internal/package-bundler, @secure-exec/core/internal/shared/*)",
"Verify all existing imports from \"secure-exec\" continue to work unchanged",
"Verify tests that import from ../../src/shared/ or similar internal paths still resolve (update to @secure-exec/core subpaths if needed)",
"Typecheck passes",
"All tests pass"
],
"priority": 55,
"passes": true,
"notes": "Phase 1d \u2014 final core story. The internal/ prefix signals these are not stable public API. Runtime packages use them but external consumers should not."
},
{
"id": "US-056",
"title": "Create @secure-exec/node package and move V8 execution engine",
"description": "As a developer, I need V8-specific execution code in its own package so consumers who do not use Node/V8 do not pull in isolated-vm.",
"acceptanceCriteria": [
"Create packages/secure-exec-node/ with package.json (name: @secure-exec/node, deps: @secure-exec/core, isolated-vm, esbuild, node-stdlib-browser)",
"Create tsconfig.json extending root config",
"Move execution.ts (V8 execution loop with ExecutionRuntime) to node package",
"Move isolate.ts (createIsolate, deadline/timeout utilities) to node package",
"Move bridge-loader.ts (esbuild bridge compilation) to node package",
"Move polyfills.ts (esbuild stdlib bundling) to node package",
"Update imports to use @secure-exec/core for shared types/utilities",
"Add @secure-exec/node to turbo.json pipeline (depends on core)",
"Typecheck passes",
"Tests pass"
],
"priority": 56,
"passes": true,
"notes": "Phase 2a. execution.ts ExecutionRuntime interface uses ivm.Isolate, ivm.Context, ivm.Module, ivm.Reference throughout \u2014 fully V8-specific."
},
{
"id": "US-057",
"title": "Move node/ directory and bridge compilation to @secure-exec/node",
"description": "As a developer, I need all node/-scoped files (execution-driver, bridge-setup, esm-compiler, driver, etc.) in the node package.",
"acceptanceCriteria": [
"Move node/execution-driver.ts, node/bridge-setup.ts, node/esm-compiler.ts, node/driver.ts, node/execution-lifecycle.ts, node/isolate-bootstrap.ts, node/module-access.ts, node/module-resolver.ts to @secure-exec/node",
"Set up build:bridge step in node package that compiles core bridge source into IIFE",
"Update internal cross-references to use @secure-exec/core subpath imports where needed",
"Update secure-exec barrel to re-export NodeExecutionDriver, createNodeDriver, createNodeRuntimeDriverFactory, NodeFileSystem, createDefaultNetworkAdapter from @secure-exec/node",
"Typecheck passes",
"Tests pass"
],
"priority": 57,
"passes": true,
"notes": "Phase 2b. The build:bridge step should use option 3 from spec: core exports getRawBridgeCode() and node imports it. node/bridge-setup.ts is the ivm.Reference wiring file (~780 lines)."
},
{
"id": "US-058",
"title": "Update kernel adapter to depend on @secure-exec/node",
"description": "As a developer, I need the kernel adapter to import from the split packages to avoid pulling in pyodide/browser code.",
"acceptanceCriteria": [
"Update packages/runtime/node/package.json: replace secure-exec dependency with @secure-exec/node + @secure-exec/core",
"Update imports in packages/runtime/node/src/driver.ts: NodeExecutionDriver, createNodeDriver from @secure-exec/node; types and permissions from @secure-exec/core",
"Verify packages/runtime/node/ no longer transitively depends on pyodide or browser code",
"Typecheck passes",
"All Node tests pass"
],
"priority": 58,
"passes": true,
"notes": "Phase 2c. This is the primary motivating consumer \u2014 the kernel adapter should not need to pull in the full secure-exec bundle."
},
{
"id": "US-059",
"title": "Create @secure-exec/browser package and move browser code",
"description": "As a developer, I need browser Web Worker code in its own package so Node consumers do not pull it in.",
"acceptanceCriteria": [
"Create packages/secure-exec-browser/ with package.json (name: @secure-exec/browser, deps: @secure-exec/core)",