Repository navigation
fix(opencode): admit patched Node 26.12.1 and release the patched engines - #25
Conversation
Node 18 (EOL 2025-04-30) and 20 (EOL 2026-04-30) will not receive the eMudhra intermediate SPKI blocklist (nodejs/node#66871), so advertising them as supported would point users at runtimes that can never be patched. 22, 24 and 26 are the lines the backport targets. Refs #23
Issue #23: Node releases before 22.23.4 and 24.22.1 accept chains through the revoked eMudhra intermediates. Pin the exact release in .nvmrc and floor engines.node at the fixed release of each supported line, excluding lines with no fix.
engines.node becomes ^22.23.4 || ^24.22.1, the first releases carrying the SPKI blocklist (nodejs/node#66871); Node 26 has no fixed release yet. .nvmrc pins 24.22.1 as the single exact version for development and CI. scripts/tls-probe.mjs is the acceptance check: it exits non-zero unless the eMudhra test endpoint fails with CERT_REVOKED and a trusted endpoint connects.
CI used the ubuntu-latest default Node, which is unpinned and may predate the eMudhra fix. Every setup-node step now reads plugins/opencode-last9/.nvmrc (action pinned by commit), the plugin's tests and typecheck run in CI, and the TLS probe proves the pinned release rejects the revoked chain. A test keeps workflows from setting node-version inline. Kept as the last commit since it edits workflows.
Node 26.12.1 (2026-10-21) carries the eMudhra SPKI blocklist (a2caddd20e, nodejs/node#66871), so Node 26 is now a patched line and belongs in the floors table that engines.node is derived from.
Node 26.12.1 is the first 26.x release with the eMudhra SPKI blocklist (a2caddd20e, nodejs/node#66871); before it, engines rejected every Node 26 install, patched or not. ^26.12.1 floors the line at the fix, matching 22 and 24. A fix commit also lets release-please cut a release, so the published package finally carries the patched engines range: #24 landed as a chore, which does not trigger one.
reviewer9io
left a comment
There was a problem hiding this comment.
The engine range, README and regression test agree on the first patched Node 26 release, while retaining the Node 22/24 floors. Completed the three-file assessment at c73410607467eae3e3a66974f9b9336a0f56c938; no actionable finding.
Fresh verification on checksum-verified Node 26.12.1: 14 tests, typecheck and 11 npm-semver boundary probes passed. Reverting the package’s Node 26 range makes the committed engine assertion fail. The upstream v26.12.1 changelog includes the blocklist backport. Current-head test/typecheck, guardrails, skill parity and TLS-probe CI are green.
The repository has no committed lockfile; installation followed its declared ranges, with the resolved versions recorded. npm reported an unapproved esbuild postinstall; the checks above passed without enabling it. No live TLS probe, Bun/OpenCode integration or npm publication was performed locally.
Advisory rollout: the fix commit enables the configured release flow, but existing npm consumers retain the old metadata until a release is published. Publishing remains a separate step.
Unverified assumptions
- The separate npm publication process will publish the generated release; it is outside this repository and was not verified.
Coverage
- Ran: Intent, Correctness and safety, Contract and rollout, Tests, Guidance compliance
- Skipped: Reliability (No async/error-handling behavior changed.), Cost and resource (No hot-path, I/O, loop or cache change.), Maintainability and design (Three-path engine metadata/test/docs adjustment; no structural change.), Prior discussion (No earlier reviews or threads.)
Second part of #23. #24 pinned Node 22 and 24, but two gaps remained.
What
9e3fdd2test(opencode): add Node 26 (26.12.1) toPATCHED_FLOORSintest/node-version.test.ts.engines.nodeis derived from that table.c734106fix(opencode):engines.nodeis now^22.23.4 || ^24.22.1 || ^26.12.1, and the README Development note is updated to match.(
0510d70is a no-op merge ofmaster, because #24 was squash-merged from this branch.)Why
security: truein nodejs.org/dist/index.json) is the first 26.x release withtls: reject chains containing blocked public keys(a2caddd20e, tls: reject chains containing blocked public keys nodejs/node#66871, CHANGELOG_V26). Before this change,enginesrejected every Node 26 install, including patched ones.chore:, and release-please doesn't release on chores. npmlatestis still@last9/opencode-plugin@0.3.0withengines.node: ">=18". Thisfix(opencode):commit lets release-please open a 0.3.1 release PR. After that release, the package needs to be published to npm (publishing isn't done in this repo).Node surfaces are unchanged from #24:
.nvmrc(24.22.1) is used for development and by everyactions/setup-nodestep inopencode-plugin.ymlandoss-guardrails.yml. The package'sengines.nodecovers the OpenCode/Bun runtime users. There is no Dockerfile or container image.Tests
engines.node admits only patched releases of supported linesfail on 9e3fdd2 (actual^22.23.4 || ^24.22.1, expected... || ^26.12.1). It passes on c734106.npm test(14/14) andnpm run typecheckpass.node --use-env-proxy scripts/tls-probe.mjs):TLS revocation probejob already passed on master (7ff760d).scripts/check-skill-pack.shneeds approval in my sandbox, so it is left to CI.Fixes #23
Agent usage
claude-opus-5-5· $2.97 · 162 input · 42,864 output · 3,669,519 cache-read · 172,028 cache-write-1hclaude-sonnet-5-5· $0.41 · 44 input · 8,625 output · 635,974 cache-read · 66,209 cache-write-1hOpened by coder9io. Review comments and CI results on this PR are picked up automatically.