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.
- package/LICENSE +21 -21
- package/README.md +11 -21
- package/package.json +29 -23
- package/plugin.mjs +3847 -0
- package/.editorconfig +0 -12
- package/.github/workflows/ci.yml +0 -75
- package/.github/workflows/release.yml +0 -50
- package/.node-version +0 -1
- package/AGENTS.md +0 -23
- package/INSTALL.md +0 -104
- package/docs/checkpoint.md +0 -68
- package/docs/history/1-spec-review.md +0 -233
- package/docs/history/10-p0-launch-prerequisites-review.md +0 -186
- package/docs/history/11-p0-job-containment-review.md +0 -188
- package/docs/history/12-p0-api-client.md +0 -15
- package/docs/history/13-p0-status-review.md +0 -122
- package/docs/history/14-p0-containment-final-review.md +0 -84
- package/docs/history/15-config-source-implementation.md +0 -27
- package/docs/history/16-sanitizer-implementation.md +0 -65
- package/docs/history/17-store-policy-implementation.md +0 -36
- package/docs/history/18-pure-mvp-review.md +0 -182
- package/docs/history/19-pure-mvp-re-review.md +0 -142
- package/docs/history/2-p0-runtime-prerequisites.md +0 -163
- package/docs/history/20-pure-mvp-final-review.md +0 -116
- package/docs/history/21-pure-mvp-review-final.md +0 -109
- package/docs/history/22-pure-mvp-signoff-review.md +0 -113
- package/docs/history/23-pure-mvp-signoff-review.md +0 -75
- package/docs/history/24-owned-tools-implementation.md +0 -27
- package/docs/history/25-v2-plugin-integration.md +0 -53
- package/docs/history/26-owned-tools-review.md +0 -138
- package/docs/history/27-owned-tools-final-review.md +0 -93
- package/docs/history/28-owned-tools-signoff.md +0 -98
- package/docs/history/3-p0-harness-foundation.md +0 -105
- package/docs/history/4-p0-source-opening.md +0 -78
- package/docs/history/5-qualification-gate-review.md +0 -133
- package/docs/history/6-p0-infrastructure-review.md +0 -275
- package/docs/history/7-p0-job-containment.md +0 -29
- package/docs/history/8-p0-evidence-support.md +0 -52
- package/docs/history/9-p0-launch-plan.md +0 -88
- package/docs/spec/design.md +0 -111
- package/docs/spec/intent.md +0 -81
- package/docs/spec/plan.md +0 -78
- package/docs/testing.md +0 -157
- package/scripts/build-plugin.mjs +0 -84
- package/scripts/install-opencode-ci.ps1 +0 -39
- package/scripts/install-opencode-ci.sh +0 -27
- package/scripts/smoke.mjs +0 -105
- package/scripts/verify-package.mjs +0 -18
- package/src/README.md +0 -22
- package/src/budgets/index.ts +0 -49
- package/src/config/README.md +0 -4
- package/src/config/options.ts +0 -76
- package/src/diagnostics/README.md +0 -4
- package/src/opencode/v2/filter.ts +0 -350
- package/src/opencode/v2/index.ts +0 -86
- package/src/opencode/v2/runtime.ts +0 -207
- package/src/opencode/v2/transports/README.md +0 -5
- package/src/runtime/http-transport.ts +0 -20
- package/src/sanitize/README.md +0 -4
- package/src/sanitize/index.ts +0 -454
- package/src/sources/README.md +0 -5
- package/src/sources/dotenv.ts +0 -133
- package/src/sources/native/README.md +0 -5
- package/src/store/index.ts +0 -64
- package/tests/README.md +0 -26
- package/tests/contract/plugin-v2.test.ts +0 -29
- package/tests/fixtures/README.md +0 -9
- package/tests/fixtures/job-child.mjs +0 -18
- package/tests/fixtures/plugins/README.md +0 -8
- package/tests/fixtures/process-child.mjs +0 -20
- package/tests/fixtures/services/README.md +0 -10
- package/tests/integration/components.test.ts +0 -5
- package/tests/integration/transparent-runtime.test.ts +0 -97
- package/tests/integration/windows-job.test.ts +0 -71
- package/tests/p0-host/README.md +0 -24
- package/tests/p0-host/linux-job.sh +0 -61
- package/tests/p0-host/windows-job.ps1 +0 -51
- package/tests/p0-native/README.md +0 -33
- package/tests/p0-native/windows-handle-loader.tests.ps1 +0 -191
- package/tests/scaffold/repository.test.ts +0 -105
- package/tests/smoke/README.md +0 -37
- package/tests/smoke/cases.json +0 -17
- package/tests/smoke/qualification.json +0 -20
- package/tests/smoke/runtime-candidate.json +0 -111
- package/tests/support/README.md +0 -32
- package/tests/support/child-process.ts +0 -235
- package/tests/support/host-api.ts +0 -123
- package/tests/support/opencode-environment.ts +0 -239
- package/tests/support/qualification.ts +0 -154
- package/tests/support/recording-endpoint.ts +0 -242
- package/tests/support/run-directory.ts +0 -179
- package/tests/support/smoke-cases.ts +0 -289
- package/tests/unit/budgets.test.ts +0 -35
- package/tests/unit/config.test.ts +0 -40
- package/tests/unit/dotenv.test.ts +0 -72
- package/tests/unit/filter-size.test.ts +0 -132
- package/tests/unit/harness.test.ts +0 -228
- package/tests/unit/host-api.test.ts +0 -122
- package/tests/unit/opencode-environment.test.ts +0 -161
- package/tests/unit/qualification.test.ts +0 -128
- package/tests/unit/recording-endpoint.test.ts +0 -188
- package/tests/unit/sanitize.test.ts +0 -159
- package/tests/unit/smoke-cases.test.ts +0 -20
- 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`.
|