opencode-secrets-obfuscation 0.1.0 → 0.1.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 (104) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +11 -21
  3. package/package.json +29 -23
  4. package/plugin.mjs +3847 -0
  5. package/.editorconfig +0 -12
  6. package/.github/workflows/ci.yml +0 -75
  7. package/.github/workflows/release.yml +0 -50
  8. package/.node-version +0 -1
  9. package/AGENTS.md +0 -23
  10. package/INSTALL.md +0 -104
  11. package/docs/checkpoint.md +0 -68
  12. package/docs/history/1-spec-review.md +0 -233
  13. package/docs/history/10-p0-launch-prerequisites-review.md +0 -186
  14. package/docs/history/11-p0-job-containment-review.md +0 -188
  15. package/docs/history/12-p0-api-client.md +0 -15
  16. package/docs/history/13-p0-status-review.md +0 -122
  17. package/docs/history/14-p0-containment-final-review.md +0 -84
  18. package/docs/history/15-config-source-implementation.md +0 -27
  19. package/docs/history/16-sanitizer-implementation.md +0 -65
  20. package/docs/history/17-store-policy-implementation.md +0 -36
  21. package/docs/history/18-pure-mvp-review.md +0 -182
  22. package/docs/history/19-pure-mvp-re-review.md +0 -142
  23. package/docs/history/2-p0-runtime-prerequisites.md +0 -163
  24. package/docs/history/20-pure-mvp-final-review.md +0 -116
  25. package/docs/history/21-pure-mvp-review-final.md +0 -109
  26. package/docs/history/22-pure-mvp-signoff-review.md +0 -113
  27. package/docs/history/23-pure-mvp-signoff-review.md +0 -75
  28. package/docs/history/24-owned-tools-implementation.md +0 -27
  29. package/docs/history/25-v2-plugin-integration.md +0 -53
  30. package/docs/history/26-owned-tools-review.md +0 -138
  31. package/docs/history/27-owned-tools-final-review.md +0 -93
  32. package/docs/history/28-owned-tools-signoff.md +0 -98
  33. package/docs/history/3-p0-harness-foundation.md +0 -105
  34. package/docs/history/4-p0-source-opening.md +0 -78
  35. package/docs/history/5-qualification-gate-review.md +0 -133
  36. package/docs/history/6-p0-infrastructure-review.md +0 -275
  37. package/docs/history/7-p0-job-containment.md +0 -29
  38. package/docs/history/8-p0-evidence-support.md +0 -52
  39. package/docs/history/9-p0-launch-plan.md +0 -88
  40. package/docs/spec/design.md +0 -111
  41. package/docs/spec/intent.md +0 -81
  42. package/docs/spec/plan.md +0 -78
  43. package/docs/testing.md +0 -157
  44. package/scripts/build-plugin.mjs +0 -84
  45. package/scripts/install-opencode-ci.ps1 +0 -39
  46. package/scripts/install-opencode-ci.sh +0 -27
  47. package/scripts/smoke.mjs +0 -105
  48. package/scripts/verify-package.mjs +0 -18
  49. package/src/README.md +0 -22
  50. package/src/budgets/index.ts +0 -49
  51. package/src/config/README.md +0 -4
  52. package/src/config/options.ts +0 -76
  53. package/src/diagnostics/README.md +0 -4
  54. package/src/opencode/v2/filter.ts +0 -350
  55. package/src/opencode/v2/index.ts +0 -86
  56. package/src/opencode/v2/runtime.ts +0 -207
  57. package/src/opencode/v2/transports/README.md +0 -5
  58. package/src/runtime/http-transport.ts +0 -20
  59. package/src/sanitize/README.md +0 -4
  60. package/src/sanitize/index.ts +0 -454
  61. package/src/sources/README.md +0 -5
  62. package/src/sources/dotenv.ts +0 -133
  63. package/src/sources/native/README.md +0 -5
  64. package/src/store/index.ts +0 -64
  65. package/tests/README.md +0 -26
  66. package/tests/contract/plugin-v2.test.ts +0 -29
  67. package/tests/fixtures/README.md +0 -9
  68. package/tests/fixtures/job-child.mjs +0 -18
  69. package/tests/fixtures/plugins/README.md +0 -8
  70. package/tests/fixtures/process-child.mjs +0 -20
  71. package/tests/fixtures/services/README.md +0 -10
  72. package/tests/integration/components.test.ts +0 -5
  73. package/tests/integration/transparent-runtime.test.ts +0 -97
  74. package/tests/integration/windows-job.test.ts +0 -71
  75. package/tests/p0-host/README.md +0 -24
  76. package/tests/p0-host/linux-job.sh +0 -61
  77. package/tests/p0-host/windows-job.ps1 +0 -51
  78. package/tests/p0-native/README.md +0 -33
  79. package/tests/p0-native/windows-handle-loader.tests.ps1 +0 -191
  80. package/tests/scaffold/repository.test.ts +0 -105
  81. package/tests/smoke/README.md +0 -37
  82. package/tests/smoke/cases.json +0 -17
  83. package/tests/smoke/qualification.json +0 -20
  84. package/tests/smoke/runtime-candidate.json +0 -111
  85. package/tests/support/README.md +0 -32
  86. package/tests/support/child-process.ts +0 -235
  87. package/tests/support/host-api.ts +0 -123
  88. package/tests/support/opencode-environment.ts +0 -239
  89. package/tests/support/qualification.ts +0 -154
  90. package/tests/support/recording-endpoint.ts +0 -242
  91. package/tests/support/run-directory.ts +0 -179
  92. package/tests/support/smoke-cases.ts +0 -289
  93. package/tests/unit/budgets.test.ts +0 -35
  94. package/tests/unit/config.test.ts +0 -40
  95. package/tests/unit/dotenv.test.ts +0 -72
  96. package/tests/unit/filter-size.test.ts +0 -132
  97. package/tests/unit/harness.test.ts +0 -228
  98. package/tests/unit/host-api.test.ts +0 -122
  99. package/tests/unit/opencode-environment.test.ts +0 -161
  100. package/tests/unit/qualification.test.ts +0 -128
  101. package/tests/unit/recording-endpoint.test.ts +0 -188
  102. package/tests/unit/sanitize.test.ts +0 -159
  103. package/tests/unit/smoke-cases.test.ts +0 -20
  104. package/tsconfig.json +0 -20
@@ -1,186 +0,0 @@
1
- # P0 launch-prerequisites review: environment builder and runtime candidate
2
-
3
- Date: 2026-10-13
4
- Scope: `tests/support/opencode-environment.ts`,
5
- `tests/unit/opencode-environment.test.ts`,
6
- `tests/smoke/runtime-candidate.json`, and `docs/history/9-p0-launch-plan.md`,
7
- checked against `docs/history/2-p0-runtime-prerequisites.md`. The active Job
8
- Object/environment worker and all other helpers were excluded.
9
-
10
- ## Verdict
11
-
12
- **No-go for launch as currently composed.** The pure builder is a sound
13
- synthetic allowlist/config-construction primitive, and the candidate pin is
14
- accurately unqualified. Before use in P0-BOOT, the launch contract must resolve
15
- the authentication/database mismatch below and select one exact command
16
- contract. Once the physical run-root/process containment boundary is separately
17
- qualified, the builder and candidate are suitable inputs for a controlled
18
- launch on a Windows x64 worker; they do not themselves prove startup
19
- isolation.
20
-
21
- ## Verification
22
-
23
- - `node --test tests/unit/opencode-environment.test.ts`: **5 passed, 0 skipped**.
24
- - `npm.cmd exec -- tsc --noEmit --pretty false`: passed.
25
- - No OpenCode executable was launched. No user configuration, credentials,
26
- shared service, or ambient environment was read.
27
-
28
- ## What is correct
29
-
30
- ### Environment builder
31
-
32
- - `buildOpenCodeEnvironment` does not read `process.env`; it accepts explicit
33
- trusted OS values and copies only the fixed `ALLOWED_ENV` list
34
- (`opencode-environment.ts:42-60,135-153`). The targeted test verifies that a
35
- synthetic ambient marker and credential/proxy/plugin-like names are absent.
36
- - Derived data/cache/config/state/temp/database/cwd paths are rooted beneath
37
- the resolved run root (`:114-132`). The path containment check correctly
38
- handles the platform separator and rejects relative/escaping values.
39
- - Config is closed to the three intended values and rejects unknown, cyclic,
40
- accessor-backed, or mismatched content (`:91-99`); serialization is of the
41
- builder-owned frozen config, not caller content.
42
- - Runtime input validation uses own data descriptors and fixed fields
43
- (`:74-89,101-111`), so the repaired malformed/getter cases return only the
44
- fixed diagnostic. Returned environment, paths, and allowlist are frozen.
45
- - The names used here are supported by the pinned-source report: XDG roots,
46
- `TEMP`/`TMP`, `ProgramData`, `OPENCODE_CONFIG_DIR`,
47
- `OPENCODE_CONFIG_PROJECT_DISABLE`, `OPENCODE_CONFIG_CONTENT`, and
48
- `OPENCODE_DB`. No unsupported service-discovery, proxy, plugin-path, or
49
- credential-agent variable was invented in the builder.
50
-
51
- ### Candidate and launch plan
52
-
53
- - `runtime-candidate.json` is explicitly `unqualified`, uses tag
54
- `v2.0.28`/commit `026b106bc5d41b679ffc413264229c340871e4d3`, and records
55
- distinct platform archive (`A5A212...FEAE2`) and extracted executable
56
- (`9C59FC...FD3E3`) SHA-256 values. This agrees with the corrected source pin
57
- report and does not confuse archive and member identity.
58
- - The candidate explicitly limits itself to Windows x64 and says ARM64 is not
59
- qualified. It records source association without claiming reproducible-build
60
- equality, and lists P0-BOOT/startup isolation as blockers.
61
- - The launch plan correctly forbids installed executable lookup, shared-service
62
- discovery/control, user config, and ambient credentials. Its source-backed
63
- `serve`/stdio/readiness and `/api/info` claims are bounded to the pinned tag
64
- rather than presented as generic current-CLI behavior.
65
-
66
- ## Must fix before using the composition
67
-
68
- ### 1. Authentication contract is not representable by the builder
69
-
70
- The launch plan requires a synthetic `OPENCODE_PASSWORD` for the explicit
71
- foreground `serve` alternative (`docs/history/9-p0-launch-plan.md:22-27`), but
72
- `OPENCODE_PASSWORD` is absent from `ALLOWED_ENV` and the builder has no input
73
- for a per-run password (`opencode-environment.ts:42-60,135-153`). Passing that
74
- password by command-line, ambient inheritance, or an ad hoc environment merge
75
- would violate the stated launch contract.
76
-
77
- This is not a reason to add a general credential passthrough. Select exactly
78
- one supported mode: either use the source-verified standalone stdio contract
79
- whose child generates its own synthetic password, or extend the narrowly
80
- specified launch input/allowlist for a generated per-run password and ensure it
81
- never enters arguments, logs, public evidence, or the generic builder output.
82
- The readiness probe must authenticate using the corresponding private value.
83
-
84
- ### 2. Candidate metadata disagrees with the builder's database mode
85
-
86
- `runtime-candidate.json:43-60` lists `OPENCODE_DB=:memory:`, while the builder
87
- sets `OPENCODE_DB` to the run-rooted file path `paths.database`
88
- (`opencode-environment.ts:126,152`). The launch plan also promises inspection
89
- of DB/state/log/temp files under the run root (`9-p0-launch-plan.md:66-72`).
90
- Choose and record one contract: a run-rooted file database for filesystem
91
- evidence, or `:memory:` with the corresponding loss of on-disk DB evidence.
92
- The candidate, launch plan, and first probe must assert the same value; a stale
93
- metadata value is a qualification false-pass risk.
94
-
95
- ## Scoped limitations, not builder defects
96
-
97
- - The builder accepts a caller-supplied `root` and trusted OS values. It does
98
- not inspect physical paths, symlinks/junctions, ACLs, ownership, or whether
99
- the root is a private existing directory. That is correctly delegated to the
100
- run-directory/containment boundary; the pure builder must not be credited
101
- with proving it. The launch sequence must call it only after that boundary
102
- returns a qualified root.
103
- - `trustedOs.path`, `systemRoot`, `comspec`, and `pathext` are intentionally
104
- caller-supplied OS runtime values and are not required to be under the run
105
- root. Their provenance and executable trust belong to the containment/launch
106
- layer. The builder only validates type/length/no-control-character, not that
107
- a caller supplied a genuine system binary or safe PATH.
108
- - Rooted strings do not prove that OpenCode will make no other reads. P0-BOOT
109
- still must run the pinned executable and use synthetic marker files to verify
110
- no user/system/ancestor config, shared service, inherited key, or unexpected
111
- DB/cache/temp/log path is touched.
112
- - `OPENCODE_CONFIG_PROJECT_DISABLE=1` and the redirected `ProgramData` are
113
- source-verified controls, not a universal sandbox. A later host release or
114
- plugin/runtime path can change behavior; candidate identity and exact source
115
- version must be asserted at runtime.
116
- - `snapshots: false`, `warming: false`, and `update: "disable"` constrain
117
- behavior but do not establish service isolation or prevent every possible
118
- network operation. They must not be used as startup-isolation evidence.
119
- - The candidate is Windows x64 only. The reviewed ARM64 worker cannot qualify
120
- it merely by running under emulation or by passing the pure builder tests.
121
-
122
- ## Required P0-BOOT prerequisites
123
-
124
- 1. Resolve the password mode and database mode inconsistencies, update the
125
- candidate/launch contract, and add a test that rejects any unapproved
126
- environment merge.
127
- 2. Materialize exactly `package/bin/opencode.exe`, verify its regular-file,
128
- non-link, single-link identity and `9C59...FD3E3` hash after extraction, and
129
- launch only after the separately qualified physical containment boundary is
130
- active.
131
- 3. Use the fixed environment and exact command from the pinned tag; parse only
132
- bounded readiness output; authenticate `/api/info`; assert version `2.0.28`,
133
- PID, run-owned URL, and run-rooted temporary/database paths without printing
134
- passwords or raw responses.
135
- 4. Prove zero shared-service attachment and inspect synthetic-marker state,
136
- config, DB, cache, logs, and temp outputs. A successful API response alone is
137
- insufficient.
138
- 5. Stop only the contained owned process tree. Preserve raw evidence only in
139
- the private run root and publish safe identity/status fields.
140
- 6. Keep `runtime-candidate.json` status `unqualified` until those cases execute
141
- on a Windows x64 worker and satisfy the qualification evidence contract.
142
-
143
- ## Resolution review
144
-
145
- Date: 2026-10-13
146
-
147
- ### Verification
148
-
149
- - `node --test tests/unit/opencode-environment.test.ts`: **6 passed, 0 skipped**.
150
- - No OpenCode host was launched; no user settings, credentials, shared service,
151
- or ambient environment was read.
152
-
153
- ### Must-reconcile items: resolved
154
-
155
- 1. **Run-owned password:** `OpenCodeEnvironmentInput.password` is now required
156
- (`tests/support/opencode-environment.ts:15-20`). The builder accepts only
157
- exactly 64 lowercase hexadecimal characters (`:104-114`), includes
158
- `OPENCODE_PASSWORD` in the immutable allowlist and immutable environment
159
- (`:44-63,139-162`), and does not source it from `process.env`. The new test
160
- rejects missing, empty, short, wrong-case/non-hex, and newline-containing
161
- values (`tests/unit/opencode-environment.test.ts:92-101`). The launch plan
162
- now requires the future caller to generate 32 CSPRNG bytes per run and pass
163
- them through the private environment channel only
164
- (`docs/history/9-p0-launch-plan.md:48-53`). This resolves the prior
165
- composition mismatch without introducing a general credential passthrough.
166
-
167
- 2. **Database mode:** the builder sets `OPENCODE_DB` to
168
- `<private-root>/data/opencode.db` (`opencode-environment.ts:124-131,149-157`),
169
- and the candidate metadata now records the same rooted file contract plus a
170
- run-owned password placeholder (`tests/smoke/runtime-candidate.json:47-60`).
171
- The new test asserts the exact rooted database path alongside the password
172
- (`opencode-environment.test.ts:92-101`). The launch plan explicitly records
173
- that this is a file database selected for inspectable sink evidence
174
- (`docs/history/9-p0-launch-plan.md:48-53`). The prior metadata mismatch is
175
- resolved.
176
-
177
- ### Final verdict
178
-
179
- **The builder/candidate reconciliation is approved for the next launch-planning
180
- stage, conditional on the separately qualified containment boundary.** These
181
- changes establish a coherent private authentication/database input contract;
182
- they do not establish physical root safety, executable launch identity, process
183
- tree containment, filesystem/service isolation, or host qualification. The
184
- candidate remains `unqualified`, and actual P0-BOOT launch remains blocked
185
- until containment and runtime isolation evidence executes on a Windows x64
186
- worker. No claim is made from these six pure builder tests about a real host.
@@ -1,188 +0,0 @@
1
- # P0 Windows job-containment primitive review
2
-
3
- Date: 2026-10-13
4
- Scope: `tests/p0-host/windows-job.ps1`, its README, the six-case integration
5
- test, `tests/fixtures/job-child.mjs`, and `docs/history/7-p0-job-containment.md`.
6
- No OpenCode launch, code edit, commit, or Job Object worker work was included.
7
-
8
- ## Decision
9
-
10
- **Narrow GO:** the supervisor is adequate as a scoped synthetic test primitive
11
- for the six trusted, generated-fixture cases exercised here: suspended launch,
12
- pre-resume assignment failure, direct-child/descendant timeout cleanup,
13
- bounded output overflow, explicit native empty-environment execution, and
14
- post-assignment supervisor cancellation. The targeted suite passed **6/6**.
15
-
16
- **NO-GO for launching the source-pinned OpenCode 2.0.28 candidate on the
17
- current Windows ARM64 worker.** The candidate is Windows x64 and remains
18
- unqualified; these tests execute the local Node/native `cmd.exe` fixtures, not
19
- the candidate. In addition, several concrete supervisor boundaries below must
20
- be closed or explicitly supplied by a trusted outer layer before this is used
21
- for P0-BOOT.
22
-
23
- ## Verification
24
-
25
- Command run:
26
-
27
- ```text
28
- node --test tests/integration/windows-job.test.ts
29
- ```
30
-
31
- Result: **6 passed, 0 skipped**. No OpenCode executable, user configuration,
32
- credential, shared service, or live endpoint was accessed.
33
-
34
- ## Native implementation review
35
-
36
- The basic Win32 sequencing is sound for the tested path:
37
-
38
- - `CreateProcess` is called with `CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT`
39
- (`windows-job.ps1:25,30-31,35`), and the child is assigned before
40
- `ResumeThread` (`:35`). The forced assignment-failure case leaves the
41
- fixture's parent marker absent, so the child did not run.
42
- - The `JOBOBJECT_EXTENDED_LIMIT_INFORMATION` layout uses pointer-sized
43
- `UIntPtr` fields and 64-bit `long` fields, and its size is passed to
44
- `SetInformationJobObject` (`:29,35`). The job flags and limits correspond to
45
- kill-on-job-close, per-process memory, and job memory. No obvious
46
- x64/ARM64 pointer-width or field-order error was found in this static review.
47
- - The two pipe read handles are made non-inheritable, while the child receives
48
- the write handles through `STARTF_USESTDHANDLES`; output is drained on
49
- separate threads and capped at 262,144 bytes per stream (`:34-35`).
50
- - Normal and timeout paths close the job, wait for the direct process, join
51
- both drainers, and then close process/thread/pipe handles in `finally`.
52
- `SafeFileHandle(..., false)` does not double-close the explicit `CloseHandle`
53
- on the normal drain path.
54
-
55
- These observations support the narrow synthetic GO only; they are not an ABI
56
- qualification for arbitrary ARM64/x64 OpenCode binaries.
57
-
58
- ## Must-fix before source-pinned P0-BOOT
59
-
60
- ### 1. The supervisor does not verify the executable identity
61
-
62
- `windows-job.ps1:12-13` checks only absolute path, existence, leaf type, and
63
- `.exe` extension. The request has no expected SHA-256, archive-member identity,
64
- single-link check, or post-materialization identity binding. A request can
65
- therefore launch an arbitrary existing executable under the owned root or an
66
- explicit path outside it. The README's “explicit verified `.exe`” is a caller
67
- assertion, not an invariant enforced by this supervisor.
68
-
69
- For the source-pinned candidate, the trusted launch layer must either bind the
70
- verified extracted `package/bin/opencode.exe` identity into the request and
71
- revalidate it immediately before `CreateProcess`, or keep this supervisor
72
- behind an already-qualified launcher that makes replacement impossible. The
73
- request must not be able to substitute a different `.exe` while retaining a
74
- passing P0 result.
75
-
76
- ### 2. Arbitrary inheritable handles and supervisor stdin cross the boundary
77
-
78
- `CreateProcess(..., inherit=true, ...)` at `windows-job.ps1:30-35` allows all
79
- inheritable handles in the supervisor to enter the child. The code only clears
80
- inheritance on the two pipe read ends; it does not use an explicit handle list
81
- or otherwise disable unrelated inherited handles. `STARTUPINFO.input` is also
82
- set to `GetStdHandle(-10)`, so the child's stdin can be the supervisor's
83
- ambient stdin. This is especially significant for OpenCode's stdio mode and
84
- is not covered by the “explicit environment” tests.
85
-
86
- Use an explicit inherited-handle list (or an equivalent `bInheritHandles=false`
87
- construction with only controlled standard handles), and deliberately provide
88
- EOF/closed stdin unless the selected protocol requires a private controlled
89
- stdio channel. Add a test proving an ambient/inheritable sentinel handle is not
90
- visible to the child.
91
-
92
- ### 3. No active-job-count barrier exists before return
93
-
94
- After `CloseHandle(j)`, the supervisor waits only on `pi.process` for 2 seconds
95
- (`windows-job.ps1:35`). It never calls `QueryInformationJobObject` and never
96
- proves `ActiveProcesses == 0`. Closing a kill-on-close job initiates termination
97
- asynchronously; a direct parent wait and pipe joins do not establish that every
98
- descendant has exited. The integration PID checks occur after return and can
99
- pass by timing rather than by a supervisor-owned zero-active-count barrier.
100
-
101
- Before reporting timeout/cancellation/overflow completion, query the job until
102
- active count is zero under a bounded deadline, or return a fixed teardown
103
- failure. Keep the external PID oracle as an independent check, not as the
104
- supervisor's only tree proof.
105
-
106
- ### 4. Supervisor-death ownership has a pre-assignment orphan window
107
-
108
- `KILL_ON_JOB_CLOSE` correctly owns processes after `AssignProcessToJobObject`,
109
- but the child is created before assignment. Between `CreateProcess` and
110
- assignment (`windows-job.ps1:35`), a supervisor crash/kill leaves a suspended
111
- process that is not yet in the job. The cancellation test waits for the PID
112
- file and normally occurs after assignment, so it does not cover this race.
113
-
114
- For a hostile or crash-prone launch boundary, use atomic job-list process
115
- creation where supported, or add a trusted guardian/handshake that closes the
116
- pre-assignment orphan window and proves cleanup. At minimum, record this as an
117
- explicit unavailable failure rather than claiming parent-death containment
118
- for the entire launch interval.
119
-
120
- ### 5. Request parsing and environment/argument bounds are incomplete
121
-
122
- `Get-Content -Raw | ConvertFrom-Json` (`:10`) has no input-size limit. Argument
123
- count/length, environment count/name/value length, and path lengths are not
124
- bounded. `[string[]]$r.arguments` and `[string]$p.Value` coerce malformed JSON
125
- types instead of rejecting them (`:17-19`). A .NET case-sensitive dictionary
126
- also permits both `PATH` and `path`; Windows environment lookup is
127
- case-insensitive and the resulting block is ambiguous. Environment values are
128
- not rejected for embedded NUL, and the generated block is not checked for
129
- size.
130
-
131
- Add strict JSON shape/size/count/length validation, reject duplicate names
132
- case-insensitively and invalid/NUL values, and bound the final UTF-16
133
- environment block and command line before native launch. The current 256 KiB
134
- stdout/stderr cap and 16/4096 MiB numeric limits do not bound request parsing
135
- or supervisor-side memory.
136
-
137
- ### 6. Ownership and fixture paths are marker-presence, not ownership proof
138
-
139
- The supervisor checks only that `.owned-p0-job` exists
140
- (`windows-job.ps1:7-8`); it does not validate exact marker bytes, marker
141
- identity/link count, directory ACL/owner, or physical no-reparse containment.
142
- `Assert-OwnedPath` is lexical (`:9`) and permits a junction/reparse substitution
143
- after validation. The integration fixture itself creates `mkdtemp` below the
144
- ambient `TEMP` and writes a marker (`windows-job.test.ts:15-18`), but does not
145
- ACL-harden or independently verify that root.
146
-
147
- This is acceptable for the narrow generated test primitive when an outer
148
- run-directory boundary owns the root. It is not proof that request/stdout/
149
- stderr/PID files are private for a real host. Before P0-BOOT, pass a
150
- containment-qualified root and enforce exact marker/identity checks, or make
151
- the outer boundary's ownership contract explicit and independently tested.
152
-
153
- ## Additional cleanup and oracle findings
154
-
155
- - There is no cleanup traversal in the supervisor. The integration `finally`
156
- uses exact generated paths but invokes `cmd.exe /c rmdir /s /q`; this is
157
- acceptable only for that generated synthetic root, not a general ownership
158
- primitive. The supervisor should not be credited with safe recursive cleanup.
159
- - `Drain` closes its read handle only after successful stream construction and
160
- loop completion (`windows-job.ps1:34`). Exceptions from `FileStream`/file
161
- creation can bypass the explicit close because `SafeFileHandle` was created
162
- with `ownsHandle=false`; the thread exception is not converted to a safe
163
- supervisor result. Check all native return values, close on every exception,
164
- and surface a bounded `DRAIN_FAILED`/teardown failure.
165
- - `SetHandleInformation`, `TerminateProcess`, `CloseHandle`, and native wait
166
- return values are not consistently checked. In particular a `WAIT_FAILED`
167
- result is not distinguished from a non-timeout wait before the job is closed.
168
- Synthetic success does not prove those failure paths.
169
- - The PID oracle (`windows-job.test.ts:20-26`) proves only that the recorded
170
- numeric PIDs are absent from `tasklist` at one instant. It does not verify
171
- image identity, creation time, job membership, all descendants, or that an
172
- unknown descendant was not spawned. It is an independent smoke signal, not
173
- a proof that the supervisor waited for active count zero.
174
- - `job-child.mjs` creates the descendant with inherited process context and
175
- writes paths supplied through environment variables. This is appropriate as
176
- a synthetic tree fixture, but it does not test an OpenCode binary's actual
177
- handles, stdio protocol, memory behavior, or startup filesystem accesses.
178
-
179
- ## Final qualification boundary
180
-
181
- The six passing cases justify a **narrow GO for trusted synthetic test
182
- processes**, provided an already-owned private root is supplied and the caller
183
- accepts the documented direct primitive scope. They do not justify launching
184
- the source-pinned candidate on this ARM64 worker or claiming a private real
185
- host sandbox. The candidate remains unqualified. P0-BOOT remains blocked on
186
- Windows x64 artifact identity, controlled handle inheritance/stdin, active-job
187
- zero teardown, strict bounded request parsing, and the separate containment
188
- worker's physical root/process-death qualification.
@@ -1,15 +0,0 @@
1
- # P0 API identity client
2
-
3
- This test-only helper supports the future P0-BOOT probe; it does not launch or
4
- discover OpenCode. It accepts only an explicit `http://127.0.0.1:<port>` origin,
5
- caller-owned 64-character lowercase-hex authentication, an expected version, and
6
- a private temporary-root expectation. `expectedPID` is optional until supervisor
7
- identity is available; without it the helper cannot prove process ownership.
8
-
9
- The client performs one authenticated `GET /api/info` using Node's HTTP client,
10
- with no redirects, proxy handling, environment discovery, or alternate hosts. It
11
- limits headers, body, and deadline, destroys the request on failure, and exposes
12
- only `version`, `pid`, `urls`, and `paths.tmp`. Advertised URLs must remain on the
13
- explicit loopback origin and the temporary path must be contained by the expected
14
- private root. Failures use fixed safe codes and never include response, password,
15
- or transport details.
@@ -1,122 +0,0 @@
1
- # P0 status review — fresh-eyes assessment
2
-
3
- Date: 2026-10-13
4
-
5
- ## Verdict
6
-
7
- **NO-GO for P0-BOOT and MVP qualification.** The repository has useful,
8
- fail-closed helper tests and a source-selected Windows x64 candidate, but no
9
- real-host smoke harness has executed the candidate. `src/` remains placeholders
10
- only, and the P0 hook, abort, source, quota, and compatibility evidence gates
11
- remain open.
12
-
13
- The current ARM64 Windows machine cannot qualify the selected candidate. The
14
- candidate is the Windows x64 `@opencode/cli@2.0.28` artifact; emulation or a
15
- passing ARM64 helper/native feasibility test is not x64 runtime qualification.
16
- Qualification requires a Windows x64 worker, the exact extracted executable
17
- and hash, and the complete isolated launch evidence.
18
-
19
- ## Evidence inspected
20
-
21
- - `docs/spec/plan.md` still marks the P0 runtime selection as source-level only
22
- and leaves parser/runtime, hook, active abort, reload, permission, source
23
- opening, quota, matrix, and threat-model gates unchecked.
24
- - `tests/smoke/runtime-candidate.json` correctly remains `unqualified` and
25
- identifies only `win32/x64` as the candidate platform.
26
- - `tests/smoke/qualification.json` remains an intentionally empty,
27
- unqualified manifest. `tests/smoke/cases.json` keeps P0-BOOT/P0-HOOKS and
28
- related cases `planned`.
29
- - `src/README.md` confirms there is no plugin entrypoint or implementation.
30
- Contract and integration suites still contain named TODOs, including R1–R8
31
- and V2 lifecycle/hook behavior.
32
- - `docs/history/2-p0-runtime-prerequisites.md` establishes artifact/source
33
- identity only; startup isolation and runtime qualification are explicitly
34
- pending.
35
- - `docs/history/4-p0-source-opening.md` reports Windows ARM64/NTFS **partial**
36
- feasibility and Linux/ext4 entirely untested. It is not a loader or platform
37
- qualification.
38
- - `docs/history/10-p0-launch-prerequisites-review.md` resolves the password and
39
- database-contract mismatch, but explicitly leaves physical containment,
40
- executable launch identity, runtime isolation, and x64 host qualification
41
- blocked.
42
- - `docs/history/11-p0-job-containment-review.md` gives the supervisor only a
43
- narrow synthetic six-case GO. It lists executable identity binding, handle
44
- inheritance/stdin, active-job-zero teardown, pre-assignment orphaning,
45
- bounded request parsing, and physical root ownership as blockers for P0-BOOT.
46
- - `docs/history/12-p0-api-client.md` describes a bounded `/api/info` client,
47
- not proof that the responding PID is the owned process unless `expectedPID`
48
- is supplied.
49
-
50
- ## Safe checks run
51
-
52
- - `npm.cmd run typecheck`: passed.
53
- - `npm.cmd run test:unit`: 48 passed, 0 failed, 1 skipped (non-Windows), 11
54
- TODOs. These are helper/contract scaffolding results, not host or security
55
- qualification.
56
- - `npm.cmd run test:smoke:list`: listed all cases; no runtime was qualified.
57
- - `git diff --check`: no whitespace errors (only line-ending warnings from
58
- existing modified files).
59
-
60
- `npm run check` was not run: its configured `npm test` includes the Windows job
61
- integration test, and this review was explicitly prohibited from running the
62
- in-flux job supervisor. No OpenCode executable, shared service, user config, or
63
- credentials were accessed.
64
-
65
- ## Exact remaining blockers
66
-
67
- ### P0-BOOT
68
-
69
- 1. Implement the real pinned-host harness: explicit artifact materialization,
70
- hash/regular-file/non-link/single-link checks, qualified private root,
71
- controlled process tree, bounded readiness, authenticated `/api/info`, PID
72
- binding, and safe teardown.
73
- 2. Resolve the job-supervisor findings in history 11 or put it behind a
74
- separately qualified outer launcher. The current six synthetic cases do not
75
- prove host containment.
76
- 3. Execute startup-isolation probes with synthetic markers proving no shared
77
- service, user/system/ancestor config, inherited credential, or unexpected
78
- DB/cache/state/log/temp path is used.
79
- 4. Run the complete boot evidence on Windows x64. The current ARM64 host cannot
80
- qualify this candidate.
81
-
82
- ### P0-HOOKS / P0-ABORT and compatibility
83
-
84
- 1. Install/test the pinned V2 runtime and probe `Plugin.define`, options,
85
- typed failures, four request kinds, tool outcomes, defects/interruption,
86
- Code Mode/MCP/metadata, ordering, and persistence/compaction paths.
87
- 2. Prove active native HTTP abort-before-transmission for one exact route,
88
- including no raw diagnostic/fallback. Separately record unload/late-overlay
89
- behavior as an expected gap; it is not a pass.
90
- 3. Produce the compatibility matrix with `verified`, `blocked`, and
91
- `uncovered` states and record the active-only envelope.
92
-
93
- ### P0-C / P0-QUOTAS
94
-
95
- 1. Complete a reviewed Windows loader on the intended platform and a matching
96
- Linux/ext4 loader, or remove unsupported platforms from claims. The current
97
- ARM64 NTFS partial and absent Linux evidence do not satisfy R8.
98
- 2. Prove shared quota ownership across reactivation/package instances, or
99
- explicitly adopt and test the supervised single-Location/no-overlap MVP
100
- envelope. No implementation or proof currently exists.
101
-
102
- ## Incorrect or overstated gate claims
103
-
104
- No P0 qualification status is incorrectly marked as passed: the plan's
105
- source-level `[x]` candidate selection is explicitly limited, the candidate
106
- manifest is `unqualified`, and all smoke cases are `planned`.
107
-
108
- One supporting description is too broad for the evidence: `tests/p0-host/README.md`
109
- describes the supervisor as closing the job on supervisor death, while history
110
- 11 documents a pre-assignment orphan window. This must be read as
111
- post-assignment behavior only until a guardian/atomic launch solution proves
112
- the entire interval. Likewise, the synthetic integration result must not be
113
- reported as P0-BOOT or real-host containment qualification.
114
-
115
- ## Prioritized next action
116
-
117
- **First, qualify the launch boundary on a Windows x64 worker.** Reconcile the
118
- job supervisor's identity, handle, teardown, parsing, and physical-root gaps;
119
- then run P0-BOOT against the exact `2.0.28` x64 artifact and publish private
120
- evidence plus a safe manifest. Only after that should P0-HOOKS/P0-ABORT and the
121
- native loader/quota gates be evaluated. Do not change `runtime-candidate.json`
122
- to `qualified` based on the current ARM64 or helper-test results.
@@ -1,84 +0,0 @@
1
- # P0 containment final review
2
-
3
- Date: 2026-10-13
4
- Scope: `tests/p0-host/windows-job.ps1`, `tests/integration/windows-job.test.ts`,
5
- `tests/fixtures/job-child.mjs`, `docs/history/7-p0-job-containment.md`,
6
- `docs/history/11-p0-job-containment-review.md`, and
7
- `docs/history/13-p0-status-review.md`. No OpenCode launch, product edit, or
8
- commit was performed.
9
-
10
- ## Decision
11
-
12
- **NO-GO on this Windows ARM64 worker.** The candidate remains unqualified.
13
- The exact next action is: obtain a Windows x64 runner, rerun the targeted job
14
- test there, and only then assess the candidate launch boundary. ARM64 cannot
15
- qualify the Windows x64 candidate.
16
-
17
- ## Checks run
18
-
19
- - `npm.cmd run typecheck`: passed.
20
- - `node --test tests/integration/windows-job.test.ts`: 1 passed, 5 failed.
21
- The five failures all stop with `ATOMIC_JOB_LIST_UNSUPPORTED`; the one pass
22
- is the deliberate pre-launch denial case. This is the expected ARM64
23
- platform blocker, not evidence of successful containment.
24
-
25
- The test uses only the synthetic Node/native `cmd.exe` fixtures and generated
26
- private roots. It does not launch OpenCode or qualify a real host.
27
-
28
- ## Atomic job-list review
29
-
30
- The launcher creates the job and configures limits, then constructs a
31
- `STARTUPINFOEX` attribute list with both:
32
-
33
- - `PROC_THREAD_ATTRIBUTE_JOB_LIST` (`0x2000D`), containing the job handle; and
34
- - `PROC_THREAD_ATTRIBUTE_HANDLE_LIST` (`0x20002`), containing only private
35
- stdin/stdout/stderr handles.
36
-
37
- `CreateProcessW` is called suspended with the attribute list. If it returns
38
- Win32 error **87 (`ERROR_INVALID_PARAMETER`)**, the code throws the explicit
39
- `ATOMIC_JOB_LIST_UNSUPPORTED` result. This occurs before `made=true`, before a
40
- PID file is written, and before any child can resume. The `finally` path only
41
- closes the newly created job; it does not invoke a suspended-create/
42
- `AssignProcessToJobObject` fallback. The current ARM64 observation therefore
43
- proves the intended fail-closed behavior: no child creation and no fallback.
44
-
45
- The native layouts are sufficient for accepting this as a platform blocker in
46
- static review: `STARTUPINFOEX` embeds `STARTUPINFO` and a pointer-sized
47
- attribute-list pointer; attribute values and sizes use `IntPtr`/`UIntPtr`; and
48
- `JOBOBJECT_EXTENDED_LIMIT_INFORMATION` uses pointer-sized memory and affinity
49
- fields with explicit alignment padding. The accounting query also uses the
50
- expected pointer-independent 64-bit time and 32-bit process-count fields.
51
- This is not ABI qualification on ARM64 or x64; rerun on x64 is still required.
52
-
53
- One test naming limitation remains: `forceAssignmentFailure` deliberately
54
- throws before `CreateProcessW`, so that case proves no-resume/no-child for the
55
- requested denial but is not a native post-create assignment-failure test. That
56
- does not weaken the observed atomic attribute blocker.
57
-
58
- ## Documentation overclaims
59
-
60
- `tests/p0-host/README.md` line 6 says the supervisor “closes the job on
61
- supervisor death.” History 11 correctly identifies the pre-assignment orphan
62
- window, and the current atomic path is unsupported on this ARM64 host. The
63
- README statement must be read narrowly as post-atomic-assignment behavior; it
64
- must not claim protection over the entire launch interval or ARM64
65
- qualification.
66
-
67
- The README's “explicit verified `.exe`” wording is also broader than the
68
- supervisor invariant: history 11 notes that the current request validation
69
- checks an absolute existing `.exe`, while identity binding is a separate
70
- caller/outer-layer requirement. The README should not be used to claim
71
- source-pinned executable identity or P0-BOOT qualification.
72
-
73
- The repository root README and `docs/spec/plan.md` remain appropriately
74
- bounded: they state that the product and real-host smoke harness are not
75
- complete, and the candidate manifest remains `unqualified`. No status change
76
- is justified by this ARM64 run.
77
-
78
- ## Required next action
79
-
80
- Run the same targeted test on a **Windows x64 runner** supporting
81
- `PROC_THREAD_ATTRIBUTE_JOB_LIST`. Verify the exact atomic success path and
82
- then rerun the remaining P0-BOOT evidence against the pinned Windows x64
83
- artifact. Until that happens, ARM64 is blocked and cannot qualify the
84
- candidate.
@@ -1,27 +0,0 @@
1
- # Config and source implementation (MVP pure components)
2
-
3
- This milestone implements only pure configuration validation and dotenv parsing.
4
- `parseOptions` accepts the explicit-session, plugin-preauthorized MVP envelope,
5
- the fixed GitHub repository-access operation/resource shape, and bounded source
6
- descriptors. It rejects unknown fields, unsafe object graphs, substitutions,
7
- unsupported policies, invalid paths, and raised limits with fixed diagnostics.
8
-
9
- `parseDotenv` is non-executing and does not read `process.env`: it handles
10
- comments, `export`, quoted values, CRLF, and quoted multiline values while
11
- retaining semantic and lexical representations. Duplicate keys, malformed
12
- assignments, and size/count violations reject the complete snapshot.
13
-
14
- The native source opener is intentionally not implemented here. No filesystem
15
- is opened, and no regular-file, symlink/reparse, link-count, ownership, ACL,
16
- ancestor-replacement, or opened-object identity guarantee is made. Those checks
17
- remain the deferred P0 native qualification gate described in `docs/spec/plan.md`.
18
- Non-dotenv source formats and vault adapters are also unsupported and rejected.
19
-
20
- Evidence: the red-first unit tests in `tests/unit/config.test.ts` and
21
- `tests/unit/dotenv.test.ts` initially failed because the owned modules were
22
- absent; after implementation, the focused suite passes. `npm run typecheck`
23
- passes. This is not host or filesystem qualification.
24
-
25
- Options are normalized as plain data-only records inside the fixed parse-error boundary;
26
- unknown fields, accessors, proxy traps, and non-positive/non-finite/unsafe limits are
27
- rejected as `SOURCE_INVALID`.