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.
Files changed (104) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1 -31
  3. package/package.json +29 -23
  4. package/plugin.mjs +3841 -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,93 +0,0 @@
1
- # 27 — Owned tools final review
2
-
3
- Date: 2026-10-13
4
-
5
- ## Scope and evidence
6
-
7
- Reviewed the current P4 implementation and integration boundary:
8
-
9
- - `src/tools/index.ts`
10
- - `src/opencode/v2/index.ts`
11
- - `tests/unit/tools.test.ts`
12
- - `tests/integration/tools.test.ts`
13
- - `tests/contract/plugin-v2.test.ts`
14
- - `package.json` and the installed dependency tree
15
- - histories [24](24-owned-tools-implementation.md), [25](25-v2-plugin-integration.md), and [26](26-owned-tools-review.md)
16
- - the V2 plugin documentation and `docs/spec/{design,plan}.md`
17
-
18
- No source or test files were changed. No OpenCode process, ACL/source-loader probe, or
19
- host qualification run was performed.
20
-
21
- Executed evidence:
22
-
23
- ```text
24
- npm run typecheck PASS
25
- node --test tests/unit/tools.test.ts \
26
- tests/integration/tools.test.ts \
27
- tests/contract/plugin-v2.test.ts 15 pass, 0 fail, 0 skip
28
- git diff --check PASS (line-ending warnings only)
29
- ```
30
-
31
- The focused suite is exactly 15 tests: 9 unit, 3 integration, and 3 V2 contract
32
- tests.
33
-
34
- ## Decision
35
-
36
- **Injected owned-tool boundary: conditional signoff-ready.** The pure P4 boundary
37
- now resolves the principal findings from history 26: source and catalog inputs must
38
- be frozen/admitted, source entries are capability/session filtered, output and working
39
- budgets are bounded, HTTP authorization precedes transport use, response bodies and
40
- headers are not projected, and non-cooperative requests terminate with a fixed error.
41
- The native V2 entrypoint typechecks and registers documented Effect hooks and
42
- `codemode: false` tools.
43
-
44
- This is not signoff for an installed plugin-only MVP, a protected deployment, or a
45
- production transport. The tests exercise injected objects and API shapes; they do
46
- not establish native host behavior, serialization ordering, captured-executor
47
- lifecycle, or real network/filesystem security.
48
-
49
- ## New must-fix findings
50
-
51
- ### 1. Source budget is not checked after adding source headers — medium
52
-
53
- `credentialsRead` checks `maxBytes` and `maxWorkingBytes` while enumerating entries,
54
- then adds per-source header costs at `src/tools/index.ts:166-169` without checking
55
- the updated totals. A caller can therefore receive a result exceeding a deliberately
56
- lower configured source budget when the entries fit but the headers do not. The
57
- canonical sink's separate ceiling does not enforce the caller's lower source budget.
58
- Check and fail after header accounting, before constructing `lines`.
59
-
60
- ### 2. Snapshot/catalog identity uniqueness is not enforced — medium
61
-
62
- The admission predicates validate individual records but do not reject duplicate
63
- source entries/bindings, duplicate source IDs across a published source snapshot, or
64
- duplicate capability identities/names in a catalog. This conflicts with the design's
65
- whole-snapshot duplicate rejection rule and makes catalog lookup (`find` in the HTTP
66
- executor) order-dependent. The native source/catalog adapters must reject ambiguous
67
- identities atomically before publication.
68
-
69
- These findings are implementation follow-ups, not reasons to reject the narrow
70
- injected-boundary conclusion; they block claiming the complete source-admission
71
- contract until fixed and tested.
72
-
73
- ## Explicit remaining limitations
74
-
75
- 1. **Default unavailable factory.** `makeEffect()` uses
76
- `unavailableRuntimeFactory` unless a qualified `CoreRuntimeFactory` is injected.
77
- The default tools fail with `CREDENTIAL_RUNTIME_UNAVAILABLE`; this is intentional,
78
- not a working source-backed runtime.
79
- 2. **Native source loader absent.** No opened-handle, filesystem/ACL, dotenv parser,
80
- source watcher, or source-to-admitted-snapshot adapter is integrated. The current
81
- boundary accepts only an already admitted immutable snapshot.
82
- 3. **Trusted HTTP transport absent.** `HttpTransport` is injected. DNS/address
83
- selection and pinning, TLS peer/hostname verification, proxy and redirect refusal,
84
- header/parser limits, connection policy, and real socket cancellation remain
85
- trusted transport responsibilities and are not qualified here.
86
- 4. **Host qualification absent.** No real V2 host was launched. Tool discovery,
87
- schema/serialization, hook ordering and abort behavior, progress/publication
88
- sinks, reload/unload, captured executors, and host readiness are unverified.
89
- The isolated real-host smoke/qualification gates remain open.
90
-
91
- Accordingly, the correct release wording is **injected, trusted-boundary component
92
- ready subject to the two fixes above**, not “MVP qualified,” “host protected,” or
93
- “production ready.”
@@ -1,98 +0,0 @@
1
- # 28 — P4 owned-tools sign-off
2
-
3
- Date: 2026-10-13
4
-
5
- ## Scope and evidence
6
-
7
- Reviewed the current owned-tool and native V2 boundary:
8
-
9
- - `src/tools/index.ts`
10
- - `src/opencode/v2/index.ts`
11
- - `src/store/index.ts` (`ActivationStore.isEnrolled`)
12
- - `package.json` and `package-lock.json`
13
- - tests and histories 24–27
14
-
15
- No source files, tests, or package files were changed. No OpenCode process was
16
- launched.
17
-
18
- Executed evidence:
19
-
20
- ```text
21
- npm run typecheck PASS
22
- node --test tests/contract/*.test.ts 3 pass, 9 TODO, 0 fail
23
- node --test tests/unit/tools.test.ts \
24
- tests/integration/tools.test.ts 15 pass, 0 fail
25
- git diff --check PASS (line-ending warnings only)
26
- ```
27
-
28
- The direct package pins are exact and agree between the manifest, lockfile, and
29
- installed tree: `@opencode/plugin` 2.0.28, `effect` 4.0.1, `typescript` 5.9.3,
30
- and `@types/node` 24.19.2.
31
-
32
- ## Findings
33
-
34
- The latest fixes address the owned-tool findings from history 27:
35
-
36
- - Source and catalog admission validates the complete frozen snapshot before
37
- publication. Duplicate source entries, bindings, and catalog identities are
38
- rejected atomically; duplicate source IDs are rejected before read output.
39
- - Source headers are included in byte and working-memory accounting before any
40
- output lines are constructed. Entry counts, UTF-8 sizes, fixed ceilings, and
41
- sink budgets are bounded.
42
- - Read visibility is bound through source/key/capability bindings and session
43
- membership. `ActivationStore.isEnrolled` checks active state, generation,
44
- location, session, and agent, and is used before both tools proceed.
45
- - Admitted snapshots and catalogs are immutable/frozen and generation-bound;
46
- callers cannot supply arbitrary mutable source objects to the read path.
47
- - HTTP authorization and store proof precede transport use. Timeout/abort and
48
- resolved-response cleanup require bounded cancellation completion, with a
49
- fixed operation error on failure. Response bodies and headers are not
50
- projected.
51
- - The native V2 adapter has typed tool executors and documented hook
52
- registration. Its default runtime remains explicitly unavailable.
53
-
54
- ## Decision
55
-
56
- **CONDITIONAL GO — injected owned-tool boundary only.** The pure executors are
57
- sign-off-ready as an injected component when supplied an already admitted
58
- immutable snapshot and a separately trusted/qualified transport. This is not a
59
- claim that the component protects an installed OpenCode deployment.
60
-
61
- **NO-GO — installed plugin.** The default plugin factory is
62
- `unavailableRuntimeFactory`; its credential tools intentionally fail with
63
- `CREDENTIAL_RUNTIME_UNAVAILABLE`. No source loader, activation assembly, or
64
- production core factory is installed.
65
-
66
- **NO-GO — default factory as a functional runtime.** `makeEffect()` without an
67
- injected factory is a safe unavailable fallback, not a working credential
68
- runtime and not a shipping/default-runtime claim.
69
-
70
- **NO-GO — host qualification.** No real OpenCode host was launched. Contract
71
- tests prove package/API shape only; they do not qualify discovery,
72
- serialization, hook ordering, abort behavior, reload/unload, or host readiness.
73
-
74
- ## Residual gates
75
-
76
- ### Source/admission
77
-
78
- Implement and qualify native source opening, ACL/location binding, dotenv
79
- parsing, handle allocation, reload/watch behavior, and the adapter that
80
- constructs and publishes complete admitted snapshots. Prove aggregate quotas,
81
- generation transitions, teardown ordering, and no stale snapshot/executor
82
- visibility under reload.
83
-
84
- ### Transport
85
-
86
- Provide a separately trusted transport and tests for DNS/address selection and
87
- pinning, TLS peer/hostname verification, proxy and redirect refusal, parser and
88
- header limits, connection reuse policy, secret-safe logging, and real socket
89
- cancellation. The current tests qualify only the injected transport contract.
90
-
91
- ### Host/plugin
92
-
93
- Supply a qualified `CoreRuntimeFactory`, then run the isolated real-host smoke
94
- and qualification gates for tool discovery, schema/result serialization,
95
- session/agent mapping, hook ordering, error publication, captured-executor
96
- lifecycle, teardown, reload, and abort behavior. Until those gates pass, do
97
- not describe this as an installed MVP, protected host, or production-ready
98
- plugin.
@@ -1,105 +0,0 @@
1
- # P0 harness foundation
2
-
3
- Status: implemented test infrastructure only; no product or OpenCode runtime was launched.
4
-
5
- ## Scope
6
-
7
- - `tests/support/run-directory.ts` creates a unique directory below an explicit
8
- absolute root, writes an exact ownership marker, and verifies private
9
- permissions. POSIX mode is verified as `0700`; Windows uses `icacls` with
10
- inheritance removed and verifies the resulting full-control ACL query. Any
11
- permission/verification uncertainty fails closed.
12
- - Cleanup first validates the directory, regular single-link marker, and exact
13
- marker bytes. It traverses with `lstat`, removes links as links, never follows
14
- them, and removes only that validated directory.
15
- - `tests/support/child-process.ts` requires an explicit executable, argument
16
- vector, absolute cwd, explicit allowlisted environment, and bounded startup,
17
- overall, and output limits. It never invokes a shell or inherits the parent
18
- environment. Failures expose fixed error codes only; captured output remains
19
- in the private result/error boundary.
20
- - `tests/fixtures/process-child.mjs` is a synthetic Node-only child fixture.
21
-
22
- ## Process-tree boundary
23
-
24
- The helper tracks and kills only the PID returned by its own `spawn` call. It
25
- does not discover, signal, or claim to terminate arbitrary descendants. A
26
- future real-service harness must add an OS-native process-group/job boundary
27
- and qualify its behavior per platform before making a process-tree cleanup
28
- claim. Timeouts and cancellation are therefore only a guarantee about the
29
- owned direct child within this helper's boundary.
30
-
31
- ## Evidence
32
-
33
- The unit suite covers marker ownership, exact cleanup, link-safe cleanup where
34
- the platform permits link creation, supplied environment/cwd, output limits,
35
- overall timeout, and pre-cancellation. It launches only `process.execPath`
36
- with the checked-in synthetic fixture and synthetic values.
37
-
38
- Initial red run (before the support modules existed): `npm.cmd run test:unit`
39
- failed with `ERR_MODULE_NOT_FOUND` for `tests/support/run-directory.ts`.
40
- Passing focused run after implementation: `node --test
41
- tests/unit/harness.test.ts` — 6 passed, 0 skipped.
42
-
43
- Repository `npm.cmd run check` remains blocked by a concurrent untracked
44
- `tests/unit/recording-endpoint.test.ts`, which imports the missing
45
- `tests/support/recording-endpoint.ts`; that file is outside this task's owned
46
- paths and was not modified. The owned files pass standalone TypeScript
47
- checking.
48
-
49
- ## Corrective evidence (review 6)
50
-
51
- The infrastructure review found lifecycle, cancellation, executable identity,
52
- ACL, and recursive-cleanup defects. The owned files were repaired without
53
- claiming a hostile real-host boundary:
54
-
55
- - Child failures now stop accepting output, signal the directly spawned PID,
56
- escalate to a forced signal after a grace period, and reject only after child
57
- and stdio close. If that cannot be proven within the bound they return the
58
- fixed `TEARDOWN_FAILED` code. Pre-cancel is checked before hashing/spawn and
59
- the fixture's marker test makes an accidental launch observable.
60
- - Options are runtime-validated, the explicit executable is an actual
61
- regular-file SHA-256 match supplied by the caller, and Windows environment
62
- names are case-insensitively de-duplicated. Hash-before-launch is an
63
- artifact identity check, not a hostile replacement/race-proof launch claim.
64
- - Existing roots are never chmod/ACL-modified. POSIX roots/ancestors are
65
- checked for ownership and unsafe write permissions. Windows uses the current
66
- SID and fixed System32 Windows PowerShell/.NET ACL introspection; new
67
- directories are assigned exactly one current-SID full-control ACE with
68
- container/object inheritance, and child ACL verification is tested.
69
- - Cleanup is intentionally narrowed: after exact marker validation it removes
70
- only an empty marker-only directory. Nested content, links, and races are
71
- refused as `RUN_DIRECTORY_CONTENT_UNSAFE`; tests remove their own known
72
- synthetic paths in `finally` blocks. This is not handle-relative,
73
- race-free recursive cleanup.
74
-
75
- Focused corrective run: `node --test tests/unit/harness.test.ts` — 11 passed,
76
- 1 platform skip. Standalone TypeScript checking of the three owned TypeScript files
77
- also passed. The current `npm.cmd run check` reaches the full suite but fails
78
- the concurrent agent's `tests/integration/windows-job.test.ts` (`P0-JOB`:
79
- five Windows job containment cases with native `CreateProcess failed: 87` or
80
- missing child PID); that integration test and host fixture are outside this
81
- task's owned paths and were not modified.
82
-
83
- Remaining blockers are unchanged for real-host use: no qualified POSIX
84
- process-group or Windows Job Object tree boundary, no hostile-race-proof
85
- opened-object executable launch, and no handle-relative private-tree cleanup.
86
- This direct-child helper is unavailable as an actual OpenCode host/service
87
- isolation boundary until those platform qualifications and the P0 native/host
88
- gates are complete.
89
-
90
- ## Follow-up correction
91
-
92
- The final staging review identified three test-infrastructure issues and an
93
- inaccurate cancellation comment. Ancestor validation now permits trusted
94
- root-owned Linux ancestors when their write/sticky permissions are safe, while
95
- new run directories must remain current-UID-owned and `0700`. Missing root
96
- hierarchy components are created one at a time with private permissions; no
97
- existing ancestor is chmodded or ACL-modified. Tests cover both a fresh nested
98
- root and a root-owned sticky ancestor.
99
-
100
- Child containment now rejects absolute cross-volume `relative()` results and
101
- proper `..` components before ACL inspection. The Windows-only cross-volume
102
- test is an explicit platform skip elsewhere, not a false pass. The child
103
- helper comment now distinguishes pre-spawn cancellation checks from the
104
- post-spawn cancellation listener; the post-spawn test confirms cancellation
105
- waits for teardown before cleanup.
@@ -1,78 +0,0 @@
1
- # P0-C — source-opening feasibility spike
2
-
3
- Date: 2026-10-13
4
- Status: **Windows partial feasibility; not a platform qualification (corrected 2026-10-13, infrastructure follow-up)**
5
-
6
- ## Environment inspected
7
-
8
- - Windows 11 Pro, build 26200, ARM64.
9
- - The fixture proved the opened handle is on `NTFS` using
10
- `GetVolumeInformationByHandleW`; the separate `fsutil` query was denied.
11
- - No `cl`, `clang`, `clang-cl`, `gcc`, CMake, or .NET SDK was installed.
12
- - PowerShell's legacy `Add-Type` C# compiler was available. No WSL/Linux tool
13
- environment was found or installed.
14
-
15
- ## Executed evidence
16
-
17
- `tests/p0-native/windows-handle-loader.tests.ps1` was added as a dependency-free
18
- native API fixture. It uses P/Invoke rather than ordinary `ReadAllText` or an
19
- `icacls` preflight. The test creates and ACL-hardens its private temporary
20
- directory before writing a synthetic source, then:
21
-
22
- 1. opens the directory and final file by component-relative `NtCreateFile` with
23
- both `OBJ_DONT_REPARSE` and `FILE_OPEN_REPARSE_POINT` active (the prior
24
- report incorrectly described this as untested because it overlooked the
25
- masked options defect);
26
- 2. obtains final-handle identity/link count and reads via that same handle;
27
- 3. attempts to create a symbolic link, reporting Win32 error `1314`
28
- (`ERROR_PRIVILEGE_NOT_HELD`) without treating setup failure as rejection;
29
- 4. creates a native hard link successfully and asserts the opened object's link
30
- count is two; and
31
- 5. attempts an ancestor directory junction through the native reparse ioctl
32
- (setup error `4392`, `ERROR_REPARSE_TAG_INVALID`), then uses the OS Junction
33
- primitive to create the same synthetic adversary and verifies the ancestor
34
- is rejected. The native creator error remains recorded; the fallback is not
35
- counted as native-creator qualification.
36
- 6. inspects owner/DACL through native `GetSecurityInfo` on opened handles. The
37
- policy accepts only the current service SID, SYSTEM, and built-in
38
- Administrators; rejects unknown/broad ACEs, deny ACEs, wrong owners, and
39
- missing current-SID read or ancestor replacement masks. A one-link source is
40
- accepted; a genuine native hard link is rejected by policy with link count
41
- two. A broad inherited `BUILTIN\Users` ancestor/file fixture is rejected.
42
- 7. renames the opened positive file, creates a replacement at the original
43
- name, then rewinds and reads through the original handle; identity remains
44
- unchanged before/after the swap and the original handle remains readable.
45
-
46
- The corrected fixture was executed on this host and returned the deliberate
47
- partial result
48
- `P0-C-WINDOWS: PARTIAL (NTFS/relative/identity/read/post-read/hardlink; gaps=reparse-create-1314,junction-native-create-4392)`.
49
- The core relative-open/identity/read/post-read checks and genuine native
50
- hard-link setup ran. Symlink setup was unavailable for the precise privilege
51
- error above; the OS Junction fallback allowed the actual ancestor rejection
52
- assertion to run. The `fsutil` denial does not establish hard-link support or
53
- filesystem type; the handle APIs establish those tested facts instead.
54
- No result is represented as a qualification pass.
55
-
56
- ## Result against R8
57
-
58
- The native API route is feasible without a product package dependency, but the
59
- P0 gate is **not met**. The fixture demonstrates a narrow handle-relative
60
- primitive candidate; it now proves the configured no-reparse flags on a real
61
- NTFS handle path, native owner/DACL inspection for the tested ACE shapes,
62
- single-link policy, ancestor replacement-mask policy, and post-swap identity
63
- stability for this run. It does not prove all effective-token combinations,
64
- service-SID resolution, every ACE/tag variant, final size consistency under
65
- mutation, concurrent ACL changes, or safe concurrency. Linux/ext4 is entirely
66
- untested. Alternate data streams, mount types, symbolic-link tag variants, and
67
- other reparse tags remain untested. Ordinary path reads and ACL preflights
68
- remain insufficient.
69
-
70
- ## Recommendation / blocker
71
-
72
- Do not select a JavaScript-only or path-based loader. Before architecture is
73
- committed, build or adopt one small audited Windows helper exposing only a
74
- bounded handle-relative open/read/identity operation, with native ACL effective
75
- rights and ancestor replacement checks, and a matching Linux `openat2`
76
- implementation. Pin and review its source/build artifact. If those tests cannot
77
- be completed, advertise no filesystem source platform rather than weakening R8;
78
- the fallback should be a dedicated supervised helper/service, not `readFile`.
@@ -1,133 +0,0 @@
1
- # Qualification gate review
2
-
3
- Scope: `tests/support/qualification.ts` and `tests/unit/qualification.test.ts` only.
4
- This is a review of the bookkeeping assessor, not evidence that any host, plugin,
5
- capture, or security property has been qualified.
6
-
7
- ## Verdict
8
-
9
- **Not a real qualification gate yet.** The selected-case bookkeeping logic is
10
- mostly fail-closed for well-typed, schema-validated inputs: it rejects empty or
11
- oversized selections, duplicate required IDs, missing/duplicate/unexpected
12
- evidence, stale run/build/profile/platform/expectation identity, non-passing
13
- statuses, and missing assertion/capture references. The tests cover those paths.
14
- That is useful bookkeeping, but it does not establish runtime evidence.
15
-
16
- ## Must fix before treating this API as a safety boundary
17
-
18
- 1. **Malformed runtime input can throw instead of returning a safe failure** —
19
- `tests/support/qualification.ts:56-64,72-74,92-94`. TypeScript types do not
20
- validate JSON. Values such as a non-string `runID`/case `id`, a null record,
21
- or a non-array/null `captureIDs` can make regex/string operations or
22
- `.length`/`.some` throw. If the caller guarantees schema validation, that
23
- validator must be a mandatory, explicit adapter at this boundary; otherwise
24
- validate all shapes here and return a safe `INVALID_*` result. Add unit tests
25
- proving malformed external objects cannot escape as exceptions and that
26
- diagnostics contain only safe codes/counts.
27
-
28
- ## Qualification blockers that belong to the future real harness
29
-
30
- 1. **No authoritative case binding or completeness** —
31
- `tests/support/qualification.ts:47-68` accepts any syntactically valid
32
- selected ID. It does not load/bind `tests/smoke/cases.json`, reject an ID
33
- absent from the inventory, require the profile/expectation declared by the
34
- inventory, or require the complete enforced-profile selection. A caller can
35
- therefore qualify an invented subset. The file's header at lines 2-5
36
- correctly disclaims this. The future runner must reject unknown IDs, empty
37
- selections, missing implementations, stale evidence, and incomplete
38
- enforced-profile selections, as required by `docs/testing.md:76-83`.
39
-
40
- 2. **Capture IDs are only nonempty opaque references** —
41
- `tests/support/qualification.ts:92-94` checks syntax/count, not that a
42
- capture exists, is owned by the run, has the expected sink/network artifact,
43
- or contains an independent oracle. It also does not validate capture
44
- identity uniqueness or artifact references. This is a future real-host
45
- harness/evidence-store requirement, not something these unit tests can
46
- prove. `docs/testing.md:99-116` and `docs/spec/plan.md:37` require actual
47
- restricted captures and oracles.
48
-
49
- 3. **Evidence truth is explicitly unverified** — the module header
50
- (`tests/support/qualification.ts:2-5`) correctly says it does not verify
51
- hashes, contents, assertions, or completeness. Consequently, passing
52
- `tests/unit/qualification.test.ts:19-23` demonstrates only bookkeeping with
53
- synthetic records; it must never be reported as capture-truth or artifact
54
- qualification. The real runner must inspect actual sink/network bytes and
55
- keep raw evidence out of diagnostics, per `docs/testing.md:99-104`.
56
-
57
- 4. **No actual smoke execution or implementation-status binding** —
58
- `tests/unit/qualification.test.ts:5-17` fabricates two records and never
59
- launches a pinned host/provider/plugin. The statuses tested at lines 31-40
60
- are correctly rejected, but there is no test that a case is bound to a real
61
- executable, host/build/checksum identity, or observed execution. This is a
62
- future runner requirement; TODO/skipped/scaffold passes cannot be security
63
- evidence (`AGENTS.md:17-20`, `docs/testing.md:26-30,73-78`).
64
-
65
- ## Positive coverage
66
-
67
- - Duplicate required IDs and unexpected evidence are rejected
68
- (`tests/unit/qualification.test.ts:95-99`).
69
- - Run/build/profile/platform/expectation mismatches and zero assertions or
70
- captures are rejected (`tests/unit/qualification.test.ts:51-63`).
71
- - `expected-gap` is isolated to active-only and requires `observed-gap`; it
72
- cannot satisfy enforced (`tests/unit/qualification.test.ts:65-83`,
73
- `tests/support/qualification.ts:66,90-91`).
74
- - Result diagnostics contain failure codes only; the invalid ID is not echoed
75
- (`tests/unit/qualification.test.ts:86-93`).
76
-
77
- ## Checks run
78
-
79
- - `node --test tests/unit/qualification.test.ts`: **pass**, 13/13.
80
- - `npm.cmd run typecheck`: **fails in unrelated existing scope** at
81
- `tests/unit/recording-endpoint.test.ts:3` because
82
- `../support/recording-endpoint.ts` is missing. No qualification-file type
83
- error was reported.
84
-
85
- ## Revision: 2026-10-13 — repaired helper re-review
86
-
87
- Scope expanded for this revision to the four files named by the review request:
88
- `tests/support/qualification.ts`, `tests/unit/qualification.test.ts`,
89
- `tests/support/recording-endpoint.ts`, and `tests/unit/recording-endpoint.test.ts`.
90
-
91
- ### Revised verdict
92
-
93
- **Usable as test helpers only; not source/host qualification.** The prior
94
- qualification malformed-input finding is resolved: `assessCases` now accepts
95
- unknown inputs, validates bounded plain-data descriptors and array elements,
96
- rejects accessors without invoking them, catches reflection failures, and
97
- returns the fixed `INVALID_INPUT` result (`qualification.ts:47-101`). The
98
- focused tests cover malformed values and accessor behavior
99
- (`qualification.test.ts:102-128`).
100
-
101
- The recording fixture is also suitable synthetic loopback infrastructure: it
102
- validates options with fixed errors (`recording-endpoint.ts:34-80`), bounds
103
- request/response data, tracks sockets and pending buffers, separates parsed
104
- request counts from malformed connections, and has idempotent bounded close
105
- cleanup (`:83-211`). The nine focused tests exercise those repaired behaviors,
106
- including malformed options, incomplete bodies, and active-socket close.
107
-
108
- ### Remaining concrete observations
109
-
110
- - **No new must-fix defect found in these four files.** The assessor still
111
- intentionally accepts a caller-selected, syntactically valid case set and
112
- opaque capture IDs (`qualification.ts:2-5,109-151`). The smoke runner must
113
- supply authoritative inventory binding, completeness, capture ownership and
114
- capture/oracle truth. This is a qualification limitation, not evidence that
115
- the helper validates artifact hashes or capture contents.
116
- - The recording fixture retains successful request bodies until `close()`;
117
- its configured maxima permit up to 64 requests × 1 MiB (plus copies made by
118
- `captures()`) (`recording-endpoint.ts:71-79,141-145,175-178`). This is bounded,
119
- and not a current correctness/security finding for a test-only helper, but a
120
- future harness should set an explicit aggregate capture budget if it runs
121
- adversarial workloads.
122
- - `counts().attempted` deliberately counts parsed HTTP requests, while
123
- malformed connections are reported only by `malformed`
124
- (`recording-endpoint.ts:28,87-90,157-178`). It is therefore not a total
125
- connection-attempt or zero-egress oracle; callers must not interpret it as
126
- one.
127
-
128
- ### Focused verification
129
-
130
- - `node --test tests/unit/qualification.test.ts tests/unit/recording-endpoint.test.ts`:
131
- **pass, 24/24** (15 qualification, 9 recording-endpoint).
132
- - No full typecheck was run in this revision because unrelated agents are
133
- editing adjacent support files; the focused result is the primary evidence.