opencode-secrets-obfuscation 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +1 -31
- package/package.json +29 -23
- package/plugin.mjs +3841 -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,65 +0,0 @@
|
|
|
1
|
-
# 16 — Pure sanitizer implementation
|
|
2
|
-
|
|
3
|
-
Status: implemented pure MVP components; host qualification deferred. R19 residual sanitizer blockers remediated.
|
|
4
|
-
|
|
5
|
-
## Scope
|
|
6
|
-
|
|
7
|
-
`src/sanitize/index.ts` provides a dependency-free, internally derived representation inventory,
|
|
8
|
-
whole-snapshot admission predicate, finite UUID/reserved-output conflict checks,
|
|
9
|
-
transitive interval unions, one-pass replacement with final boundary validation,
|
|
10
|
-
canonical newline-joined text sinks, and bounded canonical projections of plain
|
|
11
|
-
structured data. Ambiguous unions use redaction-only output. Construction checks
|
|
12
|
-
finite default output, traversal depth, node, and match bounds and withholds rather
|
|
13
|
-
than returning partial data. Pattern count, text, representation, index, and
|
|
14
|
-
temporary construction limits are checked before expansion. Interval materialization
|
|
15
|
-
is capped before each hit is allocated; active object identities are rejected. Dotenv inventory uses the parser's
|
|
16
|
-
double/single quote, escape, and multiline lexical forms. Caller representation
|
|
17
|
-
metadata is not trusted.
|
|
18
|
-
|
|
19
|
-
All public pure boundaries validate plain data descriptors and catch foreign proxy,
|
|
20
|
-
accessor, malformed-pattern, budget, and serialization failures, returning only the
|
|
21
|
-
fixed admission denial or `null` (or an empty interval result). The implementation
|
|
22
|
-
does not claim universal encoding coverage, noninterference,
|
|
23
|
-
or protection against arbitrary host serializers. It rejects getters, non-plain
|
|
24
|
-
prototypes, arrays, binary data, and unqualified host projections; it does not invoke
|
|
25
|
-
`toJSON`.
|
|
26
|
-
|
|
27
|
-
## Test-first evidence
|
|
28
|
-
|
|
29
|
-
The initial `tests/unit/sanitize.test.ts` run was red because
|
|
30
|
-
`src/sanitize/index.ts` did not exist. After implementation:
|
|
31
|
-
|
|
32
|
-
```text
|
|
33
|
-
node --test tests/unit/sanitize.test.ts
|
|
34
|
-
12 passed, 0 failed
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
The focused suite covers transitive `abc`/`bcdef` overlap, ambiguous replacement
|
|
38
|
-
and idempotence, UUID/reserved admission (`e`, `true`, `!`), canonical cross-part
|
|
39
|
-
joining, scalar/key handling, and construction limits.
|
|
40
|
-
|
|
41
|
-
`npm run typecheck` remains blocked by the unrelated pre-existing malformed
|
|
42
|
-
`src/budgets/index.ts` placeholder. The repository-wide unit command also has
|
|
43
|
-
unrelated missing config/source/store modules and Windows private-directory
|
|
44
|
-
harness failures. No host or OpenCode process was launched.
|
|
45
|
-
|
|
46
|
-
Residual aggregate-work findings are closed: public transforms reserve shared finite
|
|
47
|
-
pattern, index, identity, and temporary-work capacity before construction and release
|
|
48
|
-
it on every return path.
|
|
49
|
-
|
|
50
|
-
## R21 budget ceiling remediation
|
|
51
|
-
|
|
52
|
-
The four caller-controlled operation budgets have fixed hard ceilings equal to their
|
|
53
|
-
defaults: 2 MiB output, depth 32, 50,000 nodes, and 50,000 matches. An explicit
|
|
54
|
-
nonnegative safe integer above any ceiling is rejected (not clamped), so no public
|
|
55
|
-
sanitizer path can opt into unbounded interval, traversal, or output work. Rejected
|
|
56
|
-
operations reserve no partial output and all successful reservations remain released
|
|
57
|
-
on every return path.
|
|
58
|
-
|
|
59
|
-
## R22 boundary and key-work remediation
|
|
60
|
-
|
|
61
|
-
Canonical text-sink inspection and reservation calculation are contained by one
|
|
62
|
-
fail-closed `try`/`finally`, including hostile array proxies. Plain projection collects
|
|
63
|
-
enumerable keys incrementally under the finite node/object-key ceiling before sorting;
|
|
64
|
-
it does not call an unbounded `Object.keys(...).sort()` operation. Denials return no
|
|
65
|
-
partial projection and reservations remain reusable.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# 17 — Pure store, policy, and budget implementation
|
|
2
|
-
|
|
3
|
-
Status: implemented as unit-tested pure components; host qualification remains deferred.
|
|
4
|
-
|
|
5
|
-
The MVP components are activation-local and memory-only. `ActivationStore` creates
|
|
6
|
-
cryptographically random `secret-<UUIDv4>` references, keeps redaction references distinct
|
|
7
|
-
from capability references, requires explicit session/agent enrollment, checks
|
|
8
|
-
generation and canonical Location on every use, and clears all state on teardown.
|
|
9
|
-
Raw values are only passed to a caller-owned callback after a successful policy
|
|
10
|
-
proof; they are not included in errors or public records.
|
|
11
|
-
|
|
12
|
-
`createPolicy` supports only explicit `plugin-preauthorized` authorization with
|
|
13
|
-
`hostPermissions: not-integrated`. It intersects session, agent, Location,
|
|
14
|
-
generation, capability, operation, and resource, and rejects malformed records
|
|
15
|
-
without echoing input. Host-mediated authorization is intentionally unavailable.
|
|
16
|
-
|
|
17
|
-
`BudgetLedger` performs atomic reservation-before-work accounting across source,
|
|
18
|
-
index, payload, traversal, session/handle/call, and working-memory dimensions.
|
|
19
|
-
Admission is denied at capacity and checked additions cannot exceed safe integers;
|
|
20
|
-
reservations are idempotently released only by
|
|
21
|
-
explicit disposal and no eviction or waiting queue exists. `ActivationStore` accepts
|
|
22
|
-
an injected ledger, reserves session/handle/secret/index/working capacity before
|
|
23
|
-
mutating its maps, bounds UUID collision retries, and disposes all reservations on
|
|
24
|
-
teardown. Session handle quotas apply to handles explicitly enrolled to that session.
|
|
25
|
-
Malformed budget records and requests are denied without propagating foreign errors.
|
|
26
|
-
The ledger is activation-local and does not establish the process-wide quota
|
|
27
|
-
arbiter required by the production profile.
|
|
28
|
-
|
|
29
|
-
Evidence: `tests/unit/store-policy.test.ts` and `tests/unit/budgets.test.ts` are
|
|
30
|
-
red before implementation and pass after implementation. These tests do not
|
|
31
|
-
qualify OpenCode host hooks, process-wide quota sharing, or movement epochs.
|
|
32
|
-
The Windows Job Object/real-host harness remains deferred per `docs/spec/plan.md`.
|
|
33
|
-
|
|
34
|
-
The store now always uses a validated bounded ledger, including safe defaults when no
|
|
35
|
-
ledger is supplied, and charges UTF-8 byte lengths for secret, index, and working
|
|
36
|
-
reservations.
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
# 18 — Adversarial review of pure MVP components
|
|
2
|
-
|
|
3
|
-
Status: review only. No source changes were made. The focused pure tests pass
|
|
4
|
-
(19/19), and `npm run typecheck` passes. The ACL/host harness was not run; this
|
|
5
|
-
review makes no host or OpenCode qualification claim.
|
|
6
|
-
|
|
7
|
-
## Findings
|
|
8
|
-
|
|
9
|
-
### High — Store references do not implement the specified handle language
|
|
10
|
-
|
|
11
|
-
`src/store/index.ts:7,50-57` accepts and generates arbitrary 64-hex strings.
|
|
12
|
-
The design requires independently generated `secret-<UUIDv4>` references
|
|
13
|
-
(`docs/spec/design.md:288-293, 316-322`). The current handles are therefore
|
|
14
|
-
not compatible with the public grammar or its admission oracle, and the
|
|
15
|
-
store's `isHandle` check admits values that are not valid MVP references.
|
|
16
|
-
|
|
17
|
-
**Required fix:** generate lowercase CSPRNG UUIDv4 handles with the exact
|
|
18
|
-
`secret-` prefix, validate that finite grammar (including version/variant), and
|
|
19
|
-
make redaction-only and capability handles use the same versioned public
|
|
20
|
-
language without deriving either from a secret.
|
|
21
|
-
|
|
22
|
-
### High — Raw-secret callback authorization is forgeable and operation-free
|
|
23
|
-
|
|
24
|
-
`src/store/index.ts:43-47` treats any structurally supplied
|
|
25
|
-
`{ok: true, capability: ref}` as a valid proof. `AuthorizationProof` is an
|
|
26
|
-
unbranded public interface (`src/policy/index.ts:7`), so a caller can forge it
|
|
27
|
-
without invoking `createPolicy`. The store also accepts no operation/resource
|
|
28
|
-
at the callback boundary; `_operation` is ignored after `grant`
|
|
29
|
-
(`src/store/index.ts:36-40`). This violates the private resolver boundary and
|
|
30
|
-
the requirement that policy, operation, resource, session, generation and
|
|
31
|
-
Location all be intersected immediately before resolution
|
|
32
|
-
(`docs/spec/design.md:162, 393`).
|
|
33
|
-
|
|
34
|
-
**Required fix:** use a non-forgeable/internal policy decision or have the
|
|
35
|
-
store perform the policy check itself with an issuer-owned opaque proof bound
|
|
36
|
-
to the complete request (including operation and resource). Do not expose a
|
|
37
|
-
plain object that is sufficient to release the raw value. Add tests that forge
|
|
38
|
-
every proof field and that change operation/resource after authorization.
|
|
39
|
-
|
|
40
|
-
### High — Sanitizer can recurse unboundedly on cyclic structured data
|
|
41
|
-
|
|
42
|
-
`src/sanitize/index.ts:183-214` has node/depth limits only when callers supply
|
|
43
|
-
them and has no visited-set. A cyclic plain object with the default budget
|
|
44
|
-
recurses until a `RangeError`; the error is neither a fixed omission nor a
|
|
45
|
-
bounded denial. This conflicts with the explicit cycle/inspectability and
|
|
46
|
-
bounded traversal requirements (`docs/spec/design.md:339-340`; `plan.md:126-129`).
|
|
47
|
-
|
|
48
|
-
**Required fix:** track object identity on the active traversal path (or reject
|
|
49
|
-
all repeated identities), enforce finite default limits before descending, and
|
|
50
|
-
convert all malformed/cyclic/foreign-object cases to `null` without exposing
|
|
51
|
-
the thrown error or retaining partial output.
|
|
52
|
-
|
|
53
|
-
### High — Dotenv lexical representation inventory misses actual parser spellings
|
|
54
|
-
|
|
55
|
-
`src/sanitize/index.ts:53-55` returns dotenv content without the surrounding
|
|
56
|
-
quotes, while `src/sources/dotenv.ts:17-23` records quoted lexical values with
|
|
57
|
-
those quotes. It also omits the `\\t` spelling even though
|
|
58
|
-
`src/sources/dotenv.ts:31-33` decodes it. Consequently a semantic value can
|
|
59
|
-
remain in a supported dotenv lexical representation while the matcher scans
|
|
60
|
-
only the semantic/content spelling. The stated requirement is to preserve and
|
|
61
|
-
protect relevant lexical representations (`docs/spec/design.md:251-253, 314`).
|
|
62
|
-
|
|
63
|
-
**Required fix:** define the grammar's exact lexical forms in one place and
|
|
64
|
-
generate every accepted form, including quote delimiters, escaped quote,
|
|
65
|
-
backslash, `n/r/t`, multiline spelling, and any accepted unquoted form. Add
|
|
66
|
-
accepted-snapshot tests that assert each lexical byte sequence is absent.
|
|
67
|
-
|
|
68
|
-
### High — Dotenv parser mishandles escaped quote grammar
|
|
69
|
-
|
|
70
|
-
`src/sources/dotenv.ts:19-22` finds the first quote with `indexOf`, without
|
|
71
|
-
recognizing escaped quotes. A valid value such as `KEY="a\\"b"` is closed at
|
|
72
|
-
the escaped quote and is rejected or misparsed. This contradicts the claimed
|
|
73
|
-
documented quoting support (`docs/spec/design.md:249-253`) and makes the
|
|
74
|
-
parser's lexical contract inconsistent with its decoder.
|
|
75
|
-
|
|
76
|
-
**Required fix:** scan quoted bodies with escape state, distinguish escaped
|
|
77
|
-
quotes from terminators, and test escaped quote/backslash/control spellings
|
|
78
|
-
under CRLF and multiline input. Reject unsupported escapes explicitly rather
|
|
79
|
-
than silently changing their bytes.
|
|
80
|
-
|
|
81
|
-
### Medium — Sanitizer construction is not fully bounded during allocation
|
|
82
|
-
|
|
83
|
-
`src/sanitize/index.ts:142-158` checks output only after `output +=` has already
|
|
84
|
-
constructed each fragment, and appends the final unsanitized suffix before the
|
|
85
|
-
final budget check (`145-156`). `collectIntervals` also materializes every
|
|
86
|
-
match without a node/match bound (`110-134`). This does not satisfy
|
|
87
|
-
`outputBytes`-while-constructing and bounded matching requirements
|
|
88
|
-
(`docs/spec/design.md:171-174, 329`).
|
|
89
|
-
|
|
90
|
-
**Required fix:** reserve/count input, match storage and each output fragment
|
|
91
|
-
before allocation; reject when a reservation would exceed the configured
|
|
92
|
-
limit. Bound pattern count, match count and interval-cache/identity storage,
|
|
93
|
-
and return only a complete validated result.
|
|
94
|
-
|
|
95
|
-
### Medium — Admission depends on caller-supplied, incomplete pattern metadata
|
|
96
|
-
|
|
97
|
-
`src/sanitize/index.ts:61-63,99-107` trusts `Pattern.representations` and does
|
|
98
|
-
not derive or verify the complete representation set. A caller can pass only
|
|
99
|
-
`text` and receive `ok: true` even when an omitted supported encoding is unsafe.
|
|
100
|
-
The source/parser integration may intend to call `representationsFor`, but the
|
|
101
|
-
pure admission API itself does not enforce the all-pattern contract.
|
|
102
|
-
|
|
103
|
-
**Required fix:** admit a canonical secret value/source entry and derive the
|
|
104
|
-
versioned representation set internally, or validate that supplied
|
|
105
|
-
representations exactly match the inventory. Reject malformed/accessor pattern
|
|
106
|
-
objects with fixed diagnostics.
|
|
107
|
-
|
|
108
|
-
### Medium — Policy malformed inputs can throw instead of fixed denial
|
|
109
|
-
|
|
110
|
-
`src/policy/index.ts:34-39` indexes `options.sessions[request.sessionId]` after
|
|
111
|
-
only shallow record checks. A request with a key such as `toString` or
|
|
112
|
-
`__proto__` can select an inherited non-array value and then throw when
|
|
113
|
-
`.includes` is called, rather than returning `denied()`. Proxy/accessor inputs
|
|
114
|
-
can likewise throw from `Object.getOwnPropertyDescriptors` or property access
|
|
115
|
-
(`18-21,27-38`). The contract requires malformed inputs to fail closed with
|
|
116
|
-
safe, fixed behavior.
|
|
117
|
-
|
|
118
|
-
**Required fix:** normalize sessions into null-prototype maps during validated
|
|
119
|
-
construction, validate request field types before lookup, use own-property
|
|
120
|
-
checks, and catch/reject uninspectable objects without propagating foreign
|
|
121
|
-
errors. Add prototype-key, proxy, accessor and cyclic tests.
|
|
122
|
-
|
|
123
|
-
### Medium — Config accepts unsafe/semantically invalid resource and path forms
|
|
124
|
-
|
|
125
|
-
`src/config/options.ts:67-70,80` rejects only slash traversal and a drive
|
|
126
|
-
prefix. A rooted Windows path beginning with `\\`, NUL-containing paths, and
|
|
127
|
-
`.`/`..` resource identifiers can pass. Resource identifiers also have no
|
|
128
|
-
explicit 100-byte limit, while the operation contract requires rejecting
|
|
129
|
-
`.`/`..`, ambiguous spellings and values over 100 bytes
|
|
130
|
-
(`docs/spec/design.md:377`). Capabilities are not checked against an actual
|
|
131
|
-
key in their source, so a typo can create an accepted but unusable grant.
|
|
132
|
-
|
|
133
|
-
**Required fix:** validate canonical relative path syntax including NUL and
|
|
134
|
-
Windows rooted/UNC forms, enforce the exact resource grammar and byte limits,
|
|
135
|
-
reject `.`/`..`, and require every capability source/key pair to exist in the
|
|
136
|
-
validated source schema or fail the whole configuration.
|
|
137
|
-
|
|
138
|
-
### Medium — Budget ledger can lose atomic accounting at safe-integer overflow
|
|
139
|
-
|
|
140
|
-
`src/budgets/index.ts:15-25` validates each reservation value but not
|
|
141
|
-
`used + value`. Repeated reservations near `Number.MAX_SAFE_INTEGER` can lose
|
|
142
|
-
precision, allowing counters to diverge from actual reservations. The ledger
|
|
143
|
-
also remains activation-local; it cannot establish the process-wide quota
|
|
144
|
-
required by `docs/spec/design.md:177`.
|
|
145
|
-
|
|
146
|
-
**Required fix:** reject additions that exceed `Number.MAX_SAFE_INTEGER` (or
|
|
147
|
-
use checked bigint accounting), and keep process-wide sharing/dedicated-service
|
|
148
|
-
restriction as an explicit integration gate rather than implying this ledger
|
|
149
|
-
proves aggregate quotas.
|
|
150
|
-
|
|
151
|
-
## Sound choices
|
|
152
|
-
|
|
153
|
-
- Configuration errors, source parse errors, policy denial, and budget denial
|
|
154
|
-
use fixed messages and do not intentionally echo input values
|
|
155
|
-
(`options.ts:19-23`, `dotenv.ts:3`, `policy.ts:16`, `budgets.ts:17`).
|
|
156
|
-
- `checked` rejects non-plain objects, accessors and cycles before ordinary
|
|
157
|
-
option traversal (`src/config/options.ts:35-45`), and options reject unknown
|
|
158
|
-
fields and raised limits (`53-84`). This remains useful after proxy/error
|
|
159
|
-
hardening.
|
|
160
|
-
- Dotenv parsing is non-executing, does not consult `process.env`, rejects
|
|
161
|
-
duplicate keys, and returns an immutable snapshot (`src/sources/dotenv.ts:9-29`).
|
|
162
|
-
- Sanitization correctly computes transitive overlap unions, performs one
|
|
163
|
-
replacement, scans the final output, joins text sink parts before matching,
|
|
164
|
-
and emits one text part (`src/sanitize/index.ts:110-159,163-174`).
|
|
165
|
-
- Plain projection rejects non-plain objects/accessors and independently
|
|
166
|
-
handles scalar JSON spellings rather than invoking `toJSON` or prototypes
|
|
167
|
-
(`src/sanitize/index.ts:176-214`). It still needs cycle and allocation fixes.
|
|
168
|
-
- Store teardown clears maps and checks active state, session/agent enrollment,
|
|
169
|
-
generation and Location before callback invocation (`src/store/index.ts:43-49`).
|
|
170
|
-
- Budget reservations are checked before commit and disposal is idempotent
|
|
171
|
-
(`src/budgets/index.ts:15-25`).
|
|
172
|
-
|
|
173
|
-
## MVP disposition
|
|
174
|
-
|
|
175
|
-
The pure tests are useful regression coverage but do not close the above
|
|
176
|
-
findings. The handle-language, callback-proof, cycle, lexical-representation,
|
|
177
|
-
and escaped-quote findings must be fixed before MVP-owned tools are built on
|
|
178
|
-
these APIs. The policy/config hardening and checked accounting are also needed
|
|
179
|
-
before treating malformed inputs or resource limits as fail-closed. These
|
|
180
|
-
results are limited to pure code; source-opening ACLs, host hooks, publication
|
|
181
|
-
ordering, aggregate quota ownership, and transport behavior remain unverified
|
|
182
|
-
per `docs/spec/plan.md`.
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# 19 — Fresh adversarial re-review of pure MVP after R18
|
|
2
|
-
|
|
3
|
-
Status: store/budget blockers remediated in the pure MVP; host qualification remains
|
|
4
|
-
deferred. The ACL/source-opening harness, OpenCode, real transport, and host
|
|
5
|
-
qualification were not run.
|
|
6
|
-
|
|
7
|
-
## Verdict
|
|
8
|
-
|
|
9
|
-
**Not ready for MVP-owned tools or an MVP qualification claim.** R18 resolves
|
|
10
|
-
the previously reported handle grammar, authorization-proof binding, cycle and
|
|
11
|
-
default traversal bounds, dotenv escaped-quote parsing, derived
|
|
12
|
-
representation inventory, malformed policy/config handling, and safe-integer
|
|
13
|
-
budget-overflow findings. The pure components remain useful, but the findings
|
|
14
|
-
below are residual blockers, and the host/source gates remain entirely open.
|
|
15
|
-
|
|
16
|
-
## R18 findings verified resolved
|
|
17
|
-
|
|
18
|
-
- Store-generated and accepted references use lowercase `secret-<UUIDv4>` with
|
|
19
|
-
version and variant validation.
|
|
20
|
-
- Policy proofs are issuer-held `WeakMap` capabilities and bind session,
|
|
21
|
-
agent, Location, generation, capability, operation, and resource. Forged
|
|
22
|
-
objects and changed operation/resource are rejected by the store boundary.
|
|
23
|
-
- Structured projection has finite default depth/node limits and rejects active
|
|
24
|
-
cycles.
|
|
25
|
-
- Dotenv quoted scanning is escape-aware; the focused tests cover escaped
|
|
26
|
-
quotes, backslashes, control escapes, CRLF, and multiline values.
|
|
27
|
-
- Admission derives the finite representation inventory instead of trusting
|
|
28
|
-
caller-supplied `Pattern.representations`; UUID-language and reserved-output
|
|
29
|
-
conflicts reject the whole set.
|
|
30
|
-
- Config checks relative paths, resource grammar/byte limits, declared source
|
|
31
|
-
keys, malformed proxy/cyclic/accessor inputs, and fixed safe errors.
|
|
32
|
-
- Budget reservation checks `current + value` against the safe-integer range.
|
|
33
|
-
|
|
34
|
-
## Residual findings
|
|
35
|
-
|
|
36
|
-
### High — Sanitizer malformed inputs can escape as foreign exceptions
|
|
37
|
-
|
|
38
|
-
`src/sanitize/index.ts` does not put all public pure entry points behind a
|
|
39
|
-
fail-closed exception boundary. `projectPlain` calls `Object.getPrototypeOf`,
|
|
40
|
-
`Object.keys`, and descriptors on untrusted objects; proxy traps can throw. The
|
|
41
|
-
pattern path similarly calls `patternRepresentations` and `representationsFor`
|
|
42
|
-
without validating/catching malformed patterns, accessors, or non-string
|
|
43
|
-
`text`. `admitPatterns`, `sanitizeText`, and `projectPlain` can therefore
|
|
44
|
-
propagate a caller-controlled error instead of returning the fixed denial/null
|
|
45
|
-
required for malformed or uninspectable data.
|
|
46
|
-
|
|
47
|
-
This was reproduced without source modification with proxies whose
|
|
48
|
-
`getPrototypeOf`, `ownKeys`, or pattern property access throws. The exception
|
|
49
|
-
message was observable (`x`).
|
|
50
|
-
|
|
51
|
-
**Required gate:** validate immutable, plain pattern records and budgets at the
|
|
52
|
-
boundary; catch all object/proxy/serialization failures and return the fixed
|
|
53
|
-
admission failure or `null`. Add tests for throwing traps on every sanitizer
|
|
54
|
-
entry point and ensure no error/cause is returned or logged.
|
|
55
|
-
|
|
56
|
-
### High — Pure sanitizer allocation accounting is still incomplete
|
|
57
|
-
|
|
58
|
-
`collectIntervalsBounded` bounds matches, but there is no bound on pattern count,
|
|
59
|
-
pattern text/representation size, derived representation construction, or
|
|
60
|
-
pattern metadata storage before those allocations occur. `admitPatterns` has no
|
|
61
|
-
budget at all. `sanitizeText` does preflight fragment byte counts, but still
|
|
62
|
-
constructs intermediate concatenations and repeatedly derives representations;
|
|
63
|
-
the pure API does not reserve the configured working/index memory required by
|
|
64
|
-
the design. A bounded input alone therefore does not establish bounded total
|
|
65
|
-
allocation for adversarial pattern arrays.
|
|
66
|
-
|
|
67
|
-
**Required gate:** impose explicit pattern/representation/index limits and
|
|
68
|
-
reserve before construction, including temporary copies and interval identity
|
|
69
|
-
storage; reject the complete operation before partial output. Test oversized
|
|
70
|
-
pattern arrays, oversized pattern values, and representation-expansion limits.
|
|
71
|
-
|
|
72
|
-
### Medium — Store handle/map growth and collision retry are unbounded
|
|
73
|
-
|
|
74
|
-
**Remediated:** `ActivationStore` now accepts an activation-local `BudgetLedger`,
|
|
75
|
-
reserves capacity before map mutation, enforces active-session and explicit
|
|
76
|
-
per-session handle quotas, bounds UUID collision attempts, and releases all
|
|
77
|
-
reservations on teardown. Deterministic collision exhaustion is fixed denial.
|
|
78
|
-
|
|
79
|
-
`src/store/index.ts` has no handle/session/map quota and `newHandle()` retries
|
|
80
|
-
forever on collisions. A supplied or failing deterministic random source can
|
|
81
|
-
make registration hang, and repeated registration/grant calls can grow the
|
|
82
|
-
activation maps without the configured `handlesPerSession`, `secretCount`, or
|
|
83
|
-
working/index reservations. The R18 UUID formatting fix does not close the
|
|
84
|
-
resource-accounting contract.
|
|
85
|
-
|
|
86
|
-
**Required gate:** inject the budget ledger and enforce admission before map or
|
|
87
|
-
handle allocation, with a finite collision-attempt bound and fixed denial.
|
|
88
|
-
Cover per-session and activation exhaustion, collision exhaustion, teardown,
|
|
89
|
-
and reservation release.
|
|
90
|
-
|
|
91
|
-
### Medium — Budget ledger malformed-object paths are not fail-closed
|
|
92
|
-
|
|
93
|
-
**Remediated:** limits and requests are descriptor-validated, symbol/unknown and
|
|
94
|
-
accessor/proxy/cyclic shapes are rejected, and request failures return `{ ok: false }`.
|
|
95
|
-
|
|
96
|
-
`src/budgets/index.ts` directly uses `Object.entries` and later property reads
|
|
97
|
-
on caller-supplied limits/requests. Throwing proxies or accessors can escape
|
|
98
|
-
from the constructor or `reserve` rather than producing the fixed invalid
|
|
99
|
-
constructor error or `{ ok: false }`. Checked arithmetic is fixed, but malformed
|
|
100
|
-
input handling is not equivalent to the hardened config/policy boundaries.
|
|
101
|
-
|
|
102
|
-
**Required gate:** normalize/validate own data descriptors or catch foreign
|
|
103
|
-
exceptions at both ledger boundaries; add proxy, accessor, symbol/unknown-field,
|
|
104
|
-
and cyclic request tests with safe denial and no diagnostic echo.
|
|
105
|
-
|
|
106
|
-
## Exact residual release gates
|
|
107
|
-
|
|
108
|
-
The following are still open and are not closed by the 29 pure tests:
|
|
109
|
-
|
|
110
|
-
1. **P0/R8 source gate:** opened-handle, canonical containment, symlink/reparse,
|
|
111
|
-
hard-link, ancestor replacement, filesystem identity, owner/ACL, and
|
|
112
|
-
tracked-file tests on each advertised OS/filesystem; no insecure fallback.
|
|
113
|
-
2. **P0 quota/deployment gate:** prove shared process-wide accounting or adopt
|
|
114
|
-
the explicitly restricted supervised single-instance/Location envelope;
|
|
115
|
-
measure actual RSS under the process memory ceiling.
|
|
116
|
-
3. **P1/P2 integration:** package/config loading through the pinned V2 runtime,
|
|
117
|
-
activation-closure ownership, source loading, immutable generations,
|
|
118
|
-
lifecycle cleanup, and source rotation semantics.
|
|
119
|
-
4. **P3 residual pure gate:** the sanitizer malformed-input and allocation
|
|
120
|
-
findings above, plus independent property tests for all declared sink
|
|
121
|
-
representations and final-boundary validation.
|
|
122
|
-
5. **P4/P5 host/tool gate:** native Effect entrypoint, enrollment and private
|
|
123
|
-
credential executor, fixed status-only HTTPS operation, DNS/address/peer
|
|
124
|
-
policy, cancellation/body withholding, and actual sink/network evidence.
|
|
125
|
-
6. **P0/P5 active-only limitations:** readiness/unload/fallback rollback,
|
|
126
|
-
captured executors, late overlays, queued/resumed work, A→B→A moves,
|
|
127
|
-
sessionless generation, provider-hosted tools, WebSocket/SDK routes,
|
|
128
|
-
shell/progress/spill paths, and host permission deny/ask remain unverified or
|
|
129
|
-
expected gaps exactly as the specification says.
|
|
130
|
-
7. **P6+ production gates:** independent mandatory readiness/revision control,
|
|
131
|
-
host-mediated authorization, final model-egress/publication gates, and
|
|
132
|
-
isolated broker/sandbox enforcement are absent; no enforced-profile claim is
|
|
133
|
-
permitted.
|
|
134
|
-
|
|
135
|
-
## Evidence
|
|
136
|
-
|
|
137
|
-
- `npm run typecheck` — pass.
|
|
138
|
-
- `node --test tests/unit/config.test.ts tests/unit/dotenv.test.ts
|
|
139
|
-
tests/unit/sanitize.test.ts tests/unit/store-policy.test.ts
|
|
140
|
-
tests/unit/budgets.test.ts` — **29 passed, 0 failed**.
|
|
141
|
-
- No source, ACL, OpenCode, smoke, integration, or host process was launched or
|
|
142
|
-
modified for this review.
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# P0-A: published runtime and startup-isolation research
|
|
2
|
-
|
|
3
|
-
Research date: 2026-10-13. This is source research only; no OpenCode executable
|
|
4
|
-
was run, and no shared service, user configuration, or credentials were accessed.
|
|
5
|
-
The separately identified source checkout was inspected read-only.
|
|
6
|
-
|
|
7
|
-
## Result
|
|
8
|
-
|
|
9
|
-
**The published artifact/source pin is now established; runtime qualification
|
|
10
|
-
remains unqualified.** The extracted Windows executables are real PE
|
|
11
|
-
byte PE executable, not a stub: it has `MZ`/`PE` headers and contains compiled
|
|
12
|
-
V2 CLI/server code, the `serve` command, `--standalone`, `OPENCODE_CONFIG_DIR`,
|
|
13
|
-
the embedded version `2.0.28`, and the compiled source path logic described
|
|
14
|
-
below. The npm package description is therefore not evidence that the binary
|
|
15
|
-
cannot run. Registry metadata has no `gitHead`, but that is not required here:
|
|
16
|
-
the official Git tag `v2.0.28` resolves through GitHub's ref API to commit
|
|
17
|
-
`026b106bc5d41b679ffc413264229c340871e4d3`, and the tag source has the exact
|
|
18
|
-
host/plugin/AI versions and Effect pin recorded below.
|
|
19
|
-
|
|
20
|
-
The source snapshot does materially improve isolation. It exposes enough
|
|
21
|
-
documented-by-source environment controls to construct a sterile launch, but
|
|
22
|
-
those controls still require a real-host proof before use. The exact source
|
|
23
|
-
commit and binary checksum remain recorded as candidate evidence, not as a
|
|
24
|
-
qualification claim.
|
|
25
|
-
|
|
26
|
-
## Published artifact evidence
|
|
27
|
-
|
|
28
|
-
Registry metadata was queried from `https://registry.npmjs.org/` and package
|
|
29
|
-
archives were downloaded only into an ACL-restricted directory under
|
|
30
|
-
`C:\Users\jfomh\AppData\Local\Temp\opencode\p0-runtime-20261013`. The
|
|
31
|
-
Windows archive was inspected, not executed.
|
|
32
|
-
|
|
33
|
-
| Role | Published version | Evidence / integrity |
|
|
34
|
-
|---|---:|---|
|
|
35
|
-
| Host bootstrap `@opencode/cli` | 2.0.28 | tarball `https://registry.npmjs.org/@opencode/cli/-/cli-2.0.28.tgz`; SHA-256 `088D38127C529232164381213718F91652450BAF3F65CFD380A4E84FD1A79245`; npm integrity `sha512-nKStJJVG6to58gSPv5AuzNQZhYtou6b1jfI5EIckshWT9w8teesSLgP3gH/iSA/madUhvkNqsFjUFuD3NRne9Q==` |
|
|
36
|
-
| Windows x64 host binary | 2.0.28 | `@opencode/cli-windows-x64`; tarball SHA-256 `A5A212125E497726A95D6F9C3CDCFE6F1FA35CA61F3F263E6575D557747FEAE2`; SHA-512 `D7FA7230C8BAD511EC44E3C96CB52C3BC53684850CC33350BD81FF5D4945E488315EF21577DA0D23C931999703EF6AED6B7B35EDDA0A00407E30A76C9E6785C5`; npm integrity `sha512-1/pyMMi61RHsROPJbLUsO8U2hIUMwzNQvY/XUlF5IgxXvIVd9oNI8kxmZcD72rta3s17doKAEB+MKdsnmeFxQ==` |
|
|
37
|
-
| Windows ARM64 host binary | 2.0.28 | `@opencode/cli-windows-arm64`; tarball SHA-256 `5DD7944A1EE879E7D9794263D945386B706F404F3EEE885CB599E81ABC5E59EF`; executable member SHA-256 `65F0E7ACCC7D5FD77CA7380FDE87E3289D0CF27687851E5240BBDE6CAA7BDB66`; npm integrity `sha512-9HXcqjQa2ghY6tgqjRqaVCZfBuP10b55ffo2QdgHESzsItTwL0yKWaorzj91q96dqmQJ6MOvpl31PdhJnhuJ4g==` |
|
|
38
|
-
| Plugin API | 2.0.28 | `@opencode/plugin`; npm shasum `2afadd0ef92eb7cbd7ecad515cadd9e39522d56b`; npm integrity `sha512-YqcpULwPXLX70ICm/EPeFacnWsYtBmaCwVgO67HCuyFDiBNnQtY8DMhHzBgUtAAI0djYLGPbwEHvHp0ZTyrnHw==` |
|
|
39
|
-
| Host Effect runtime dependency | 4.0.1 required by plugin | `@opencode/plugin@2.0.28` declares exact dependency `effect: 4.0.1`; registry latest independently is 4.0.4, which must **not** replace the host copy without qualification. |
|
|
40
|
-
| AI/provider runtime | 2.0.28 | `@opencode/ai@2.0.28`; plugin declares this exact host family. |
|
|
41
|
-
| Candidate provider | 2.0.28 | `@opencode/ai/providers/openai-compatible`; V2 provider docs identify this package and its OpenAI-compatible HTTP protocol. The exact model/endpoint is still a fixture decision, not a qualified provider. |
|
|
42
|
-
|
|
43
|
-
The platform archive contains `package/bin/opencode.exe` and its package JSON
|
|
44
|
-
points to the OpenCode repository. Static inspection of the executable found
|
|
45
|
-
the exact source-derived strings `nH="2.0.28"`, `ju="latest"`, the command
|
|
46
|
-
descriptions, and minified implementations of `Global.layerWith`, XDG roots,
|
|
47
|
-
`OPENCODE_CONFIG_DIR`, `OPENCODE_CONFIG_CONTENT`, and the standalone server.
|
|
48
|
-
This establishes that the “bootstrap” label is stale for this archive. It does
|
|
49
|
-
not establish a reproducible-build proof; the candidate relies on the official
|
|
50
|
-
same-version tag association rather than claiming byte-for-byte source
|
|
51
|
-
reproduction.
|
|
52
|
-
|
|
53
|
-
Read-only source comparison:
|
|
54
|
-
|
|
55
|
-
* The official Git ref `refs/tags/v2.0.28` resolves to
|
|
56
|
-
`026b106bc5d41b679ffc413264229c340871e4d3`. Tag source files report root,
|
|
57
|
-
`packages/cli`, `packages/plugin`, and `packages/ai` version `2.0.28`; the
|
|
58
|
-
root catalog pins `effect` and Effect platform packages to `4.0.1`.
|
|
59
|
-
* The local checkout is the separate research snapshot
|
|
60
|
-
`e9def88a7790efc6abace15b67f3625ff4d66237`; it was useful for initial
|
|
61
|
-
inspection only and is not the release source pin.
|
|
62
|
-
* The executable’s embedded version/channel strings and minified code match
|
|
63
|
-
those source files. This is a **candidate source mapping**, not a signed
|
|
64
|
-
build attestation. This source association meets the repository plan's
|
|
65
|
-
published-release/source-commit pin requirement. It does **not** claim a
|
|
66
|
-
reproducible-build equality between the tag and the npm archive; that is a
|
|
67
|
-
stronger supply-chain property and is outside this P0 pin gate.
|
|
68
|
-
|
|
69
|
-
The V2 docs do establish the intended native interfaces: `@opencode/plugin/effect`
|
|
70
|
-
with `Plugin.define({ id, effect })`, host-provided `@opencode/plugin` and
|
|
71
|
-
`effect`, and externalized public Effect subpaths. They explicitly require
|
|
72
|
-
testing against the installed package and compatible host release.
|
|
73
|
-
|
|
74
|
-
## Official distribution path
|
|
75
|
-
|
|
76
|
-
The official V2 landing page documents `npm install -g @opencode/cli` and
|
|
77
|
-
direct Windows downloads from the update service, including
|
|
78
|
-
`https://opencode.ai/update/api/latest/cli/opencode/opencode-windows-x64.zip`
|
|
79
|
-
and its baseline variant. It explicitly says Windows package managers are not
|
|
80
|
-
supported. The pinned source's updater constructs the same endpoint as
|
|
81
|
-
`https://opencode.ai/update/api/{channel}/{artifact}/{distribution}`; its
|
|
82
|
-
publish workflow builds platform binaries and signs Windows binaries. This
|
|
83
|
-
confirms that `@opencode/cli@2.0.28` and the update-service binary are official
|
|
84
|
-
V2 distribution paths, rather than an arbitrary guessed executable.
|
|
85
|
-
|
|
86
|
-
The update endpoint does not publish a reproducible-build attestation in the
|
|
87
|
-
metadata inspected. That does not defeat the source pin: the published npm
|
|
88
|
-
version, official same-version Git tag, exact archive integrity, and private
|
|
89
|
-
binary checksum are recorded as the candidate identity. Reproducibility is
|
|
90
|
-
not asserted.
|
|
91
|
-
|
|
92
|
-
## Verified isolation facts and implications
|
|
93
|
-
|
|
94
|
-
Evidence: [V2 CLI](https://opencode.ai/v2/docs/cli), [commands](https://opencode.ai/v2/docs/cli/commands),
|
|
95
|
-
[config](https://opencode.ai/v2/docs/config), and
|
|
96
|
-
[troubleshooting](https://opencode.ai/v2/docs/troubleshooting).
|
|
97
|
-
|
|
98
|
-
* The default client discovers/starts one per-user shared background service.
|
|
99
|
-
`--standalone` is the documented private-server mode; `--server URL` targets
|
|
100
|
-
an explicit server. `serve` starts a foreground API server.
|
|
101
|
-
* Config is loaded from Windows `%ProgramData%\opencode`, the global config
|
|
102
|
-
root, and current directory through filesystem ancestors. Plugin/config
|
|
103
|
-
entries accumulate by precedence; ancestor config is not excluded by
|
|
104
|
-
choosing a private working directory.
|
|
105
|
-
* Documented persistent locations include service registration
|
|
106
|
-
`~/.local/state/opencode/service.json`, service config
|
|
107
|
-
`~/.config/opencode/service.json`, database
|
|
108
|
-
`~/.local/share/opencode/opencode.db`, and logs
|
|
109
|
-
`~/.local/share/opencode/log/opencode.log`. `OPENCODE_DB` changes only the
|
|
110
|
-
database location.
|
|
111
|
-
* Source inspection adds these exact controls for a sterile process:
|
|
112
|
-
`XDG_DATA_HOME`, `XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, and `XDG_STATE_HOME`
|
|
113
|
-
root the four persistent OpenCode trees; `TEMP`/`TMP` control the native
|
|
114
|
-
temporary root; `ProgramData` controls Windows system-config discovery;
|
|
115
|
-
`OPENCODE_CONFIG_DIR` overrides the effective global config directory;
|
|
116
|
-
`OPENCODE_CONFIG_PROJECT_DISABLE=1` disables the ancestor/project walk;
|
|
117
|
-
`OPENCODE_CONFIG_CONTENT` supplies virtual config; and `OPENCODE_DB` or
|
|
118
|
-
`:memory:` selects the database. These names are source-verified in
|
|
119
|
-
`packages/util/src/global-roots.ts`, `packages/util/src/global.ts`,
|
|
120
|
-
`packages/core/src/config/discovery.ts`, `packages/cli/src/server-process.ts`,
|
|
121
|
-
and `packages/cli/src/database-path.ts` at the pinned commit. The harness
|
|
122
|
-
must set all of them in an allowlisted environment and use a fixture-owned
|
|
123
|
-
cwd; setting only `OPENCODE_CONFIG_DIR` is insufficient because system config
|
|
124
|
-
is otherwise still read.
|
|
125
|
-
* `service set disabled true` disables the shared service but edits the user's
|
|
126
|
-
service configuration and stops the shared service. It is not an acceptable
|
|
127
|
-
harness isolation mechanism.
|
|
128
|
-
* `snapshots: false` and `warming: false` are configuration controls, not
|
|
129
|
-
relocation or service-isolation controls.
|
|
130
|
-
|
|
131
|
-
`--standalone` source starts a child `serve --stdio --port 0` with a random
|
|
132
|
-
password and no service-registration path, so it is preferable to the shared
|
|
133
|
-
service. Its child inherits the parent environment (`extendEnv: true`), making
|
|
134
|
-
the allowlist mandatory. A foreground `serve` is also source-supported. The
|
|
135
|
-
remaining isolation work is executable proof: verify all filesystem reads and
|
|
136
|
-
network endpoints with synthetic markers, and verify no service discovery or
|
|
137
|
-
shared process connection. Do not run the user's installed CLI or use
|
|
138
|
-
`service` commands.
|
|
139
|
-
|
|
140
|
-
## Required next evidence
|
|
141
|
-
|
|
142
|
-
1. Treat the exact candidate pins in
|
|
143
|
-
[`../tests/smoke/runtime-candidate.json`](../../tests/smoke/runtime-candidate.json)
|
|
144
|
-
as the selected P0 artifact identity. Record additional platform archives
|
|
145
|
-
and exact protocol/model routes as they are selected; do not substitute an
|
|
146
|
-
unpinned channel artifact.
|
|
147
|
-
2. In a fresh ACL-protected fixture, set the source-verified XDG/ProgramData/
|
|
148
|
-
config/project/database/temp controls and prove startup isolation before any plugin
|
|
149
|
-
or synthetic provider runs: no shared service connection, no inherited API
|
|
150
|
-
keys, no user/system/ancestor config, and all DB/state/cache/log/temp files
|
|
151
|
-
under owned paths. Probe using only synthetic values and safe path markers.
|
|
152
|
-
3. Then run the repository's planned `P0-BOOT` identity check. Until those
|
|
153
|
-
proofs exist, `runtime-candidate.json` remains explicitly `unqualified` and
|
|
154
|
-
no host smoke/qualification result may be labeled passed.
|
|
155
|
-
|
|
156
|
-
## Parent verification correction
|
|
157
|
-
|
|
158
|
-
Direct `Get-FileHash -Algorithm SHA256` on the extracted `package/bin/opencode.exe`
|
|
159
|
-
returned `9C59FCD39AA9C611AEDA04711BAB9D668CE3145FA5CDE9868F69C31ADCCFD3E3`.
|
|
160
|
-
The original candidate accidentally used the **tarball** SHA-256 for the executable.
|
|
161
|
-
`runtime-candidate.json` now distinguishes both hashes and records the archive
|
|
162
|
-
member instead of a machine-specific executable path. A future runner must verify
|
|
163
|
-
the extracted binary hash, not compare it against the compressed archive hash.
|