Skip to content

chore(deps,middleware): bump better-sqlite3 to 13.0.3 (N-API) - #615

Merged
Weegy merged 2 commits into
mainfrom
chore/better-sqlite3-13
Aug 11, 2026
Merged

chore(deps,middleware): bump better-sqlite3 to 13.0.3 (N-API)#615
Weegy merged 2 commits into
mainfrom
chore/better-sqlite3-13

Conversation

@Weegy

@Weegy Weegy commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Closes the last open Dependabot PR from the 2026-08-03 batch. Supersedes #596, which proposed 13.0.2 and failed CI on middleware (build, no push).

What this is

better-sqlite3 v13 is the N-API rewrite. The addon no longer targets a specific Node ABI, and prebuilt binaries now ship inside the package for linux-x64/arm64, linuxmusl-x64/arm64, darwin-x64/arm64 and win32-x64/arm64 — the deprecated prebuild-install dependency is gone.

Taking 13.0.3 rather than the proposed 13.0.2; it adds the arm64 prebuild CI fix.

That has two nice consequences beyond the version bump:

  • The ABI-mismatch saga is structurally over. No more NODE_MODULE_VERSION 137 ... requires 127 after an install under the wrong Node major.
  • The dependency tree shrinks: bindings and prebuild-install disappear entirely (−246 lockfile lines).

Why #596 failed — and why this doesn't

Not a version-compatibility problem. npm ci runs node-gyp rebuild on better-sqlite3 even though the package declares gypfile: false and ships a matching prebuild. npm install honors the field; npm ci does not.

Reduced to a 5-line reproduction in node:22.23.2-slim:

npm init -y
npm install --package-lock-only better-sqlite3@13.0.3
npm ci            # -> node-gyp rebuild -> gyp ERR! find Python
npm npm install npm ci
10.9.8 (image default) clean compiles
11.19.0 clean compiles
12.0.2 clean compiles

So upgrading npm is not a fix. The slim image has no Python, and the build dies at gyp ERR! find Python.

The fix

Both npm ci calls in the root Dockerfile now pass --ignore-scripts, which lets the bundled prebuild be used, followed by an explicit rebuild of the packages that genuinely need their install script:

npm ci --ignore-scripts --no-audit --no-fund
npm rebuild argon2 esbuild          # builder stage
npm ci --omit=dev --ignore-scripts --no-audit --no-fund
npm rebuild argon2                  # runtime stage; esbuild is dev-only

--ignore-scripts here is load-bearing, not hardening theatre — and it is not a blind sweep. The lockfile lists exactly 4 packages with install scripts:

Package Handling
argon2@0.45.1 explicitly rebuilt (native, fetches a prebuilt binary)
esbuild@0.28.1 explicitly rebuilt in the builder stage (dev-only)
omadia-middleware (this package) its preinstall is the Node-version guard; the docker base image is Node 22
fsevents@2.3.3 optional, macOS-only, never installed in the linux image

Neither rebuild needs a compiler — both pull prebuilt binaries.

Trade-off worth stating: a future dependency that needs an install script will not get it silently. That is the cost of this approach. The alternative — installing python3/make/g++ into both stages — trades that footgun for a permanently larger image and a source build on every CI run, to work around a bug that will presumably be fixed upstream. I went with the smaller runtime surface; happy to flip it if you'd rather have the toolchain.

ensure-native-abi.mjs had to be rewritten

This was a hard blocker, not cosmetics. The script probed a hardcoded path:

node_modules/better-sqlite3/build/Release/better_sqlite3.node

v13 never produces that file — the binary lives in prebuilds/<platform>-<arch>.node. So on a correct v13 install the script ran a pointless npm rebuild, then exited 1, which breaks npm run dev (the dev script is node scripts/ensure-native-abi.mjs && ...).

The ABI-mismatch class of bug it guarded cannot happen under N-API, so the rebuild path is gone — forcing --build-from-source would now only demand a toolchain nobody needs. What remains is a genuine end-to-end probe: load the module, open an in-memory DB, run a query. That still catches a corrupt install, a partially extracted node_modules, or a platform with no prebuild — and it catches them at npm run dev instead of at first DB access.

Verified in both directions: exit 0 healthy, exit 1 with an actionable message when prebuilds/ is removed.

check-node-version.mjs keeps its behavior unchanged; only its comment is corrected, because it justified itself with the now-impossible ABI clobber. The Node pin still stands on its own — engines declares a single supported major.

Verification

Check Result
docker build --platform linux/amd64 succeeds, zero gyp/Python output (was: exit 1)
better-sqlite3 in the built runtime image v13.0.3, opens DB, insert + select, pragma journal_mode=WAL
argon2 in the built runtime image hashes and verifies, $argon2id$
sharp in the built runtime image encodes a 96-byte PNG
middleware build / lint / typecheck clean, 0 errors
middleware tests 6094 pass / 0 fail (4 skipped)
npm audit --audit-level=high exits 0
both guard scripts exit 0; native-abi guard also verified to fail correctly

The four builder-plugin modules backed by better-sqlite3 (draftStore, workaroundStateStore, builderTriageLog, githubIssueCache) are covered by the suite.

Not affected: web-ui/Dockerfile (no better-sqlite3) and middleware/sidecars/dev-runner/Dockerfile (installs only the shim's three devDeps, via npm install, not npm ci).

Test plan

Merge prep (2026-08-10)

origin/main merged into the branch (14 commits, incl. the consolidated
Dependabot batch #638 which also touches middleware/package.json +
package-lock.json). Branch protection is strict: true, so this was required.

  • No conflicts. package.json kept both sides: main's @modelcontextprotocol/sdk
    • --test-timeout and this PR's better-sqlite3 ^13.0.3.
  • Lockfile re-derived, zero drift. npm install --package-lock-only after the
    merge changes nothing, so the auto-merged lockfile is genuinely self-consistent.
  • The --ignore-scripts allowlist re-verified against the merged tree — still
    exactly 4 install-script packages (root, argon2, esbuild, fsevents);
    better-sqlite3 has dropped out, bindings and prebuild-install are absent.
    Nothing main added since needs an install script.

Re-verified on the merged tree: npm ci exit 0 with no gyp invocation, build /
lint / typecheck clean, 6094 tests pass / 0 fail, both audit gates exit 0, and the
linux/amd64 image builds with zero gyp/Python output.

Follow-up (not in this PR)

.github/dependabot.yml justifies the Node major-ignore with "the middleware ABI guard hard-pins NODE_MODULE_VERSION 127 for better-sqlite3, so a major Node bump silently breaks the native binary". After this PR that reason no longer holds. The ignore itself should stay — engines pins the major — but the comment deserves the same correction applied to check-node-version.mjs.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Closes the last open Dependabot PR (#596), which proposed 13.0.2 and failed
CI on `middleware (build, no push)`.

better-sqlite3 v13 is the N-API rewrite: the addon no longer targets a
specific Node ABI and ships prebuilt binaries for linux/darwin/win32 (glibc
and musl) inside the package. Taking 13.0.3 rather than the proposed 13.0.2
— it adds the arm64 prebuild CI fix.

Why #596 failed, and why this does not:

`npm ci` runs `node-gyp rebuild` on better-sqlite3 even though the package
declares `gypfile: false` and ships a matching prebuild. `npm install` honors
the field; `npm ci` does not. Verified as a 5-line reproduction on npm 10.9.8,
11.19.0 and 12.0.2 in node:22.23.2-slim, so upgrading npm is not a fix. The
slim image has no Python, so the gyp build dies at `find Python`.

Both `npm ci` invocations in the root Dockerfile therefore pass
`--ignore-scripts`, which lets the bundled prebuild be used, and then rebuild
the packages that genuinely need their install script: argon2 and esbuild in
the builder stage, argon2 alone in the runtime stage (esbuild is dev-only).
Both fetch prebuilt binaries, so no compiler is needed there either. Those are
the only two — the lockfile lists exactly 4 install scripts, the other two
being this package itself and optional fsevents.

`ensure-native-abi.mjs` had to be rewritten: it probed a hardcoded
`build/Release/better_sqlite3.node`, which v13 never produces, so it failed
outright (exit 1) and broke `npm run dev` — after first running a pointless
rebuild. The ABI-mismatch class of bug it guarded is structurally gone under
N-API, so the rebuild path is removed; what remains is an end-to-end probe
that opens an in-memory DB and runs a query, which also catches a corrupt
install or a platform without a prebuild. Verified in both directions.

check-node-version.mjs keeps its behavior; only its rationale is corrected,
since it cited the now-impossible ABI clobber.

Verified:
- docker build --platform linux/amd64 succeeds, zero gyp/Python output
- in the built runtime image: better-sqlite3 13.0.3 opens a DB and queries,
  argon2 hashes and verifies (argon2id), sharp encodes a PNG
- middleware build, lint, typecheck clean; 5502 tests pass / 0 fail
- npm audit --audit-level=high exits 0
- lockfile drops `bindings` and `prebuild-install` entirely (-246 lines)
@Weegy Weegy added deps Dependency updates (Dependabot) docker Docker base images and build files middleware middleware/ workspace labels Aug 5, 2026
Weegy added a commit that referenced this pull request Aug 10, 2026
Consolidates the 2026-08-10 Dependabot run into one verified change,
superseding #628, #629, #630, #631, #632, #633, #634, #635 and #636.

middleware: @azure/msal-node 5.5.0, typescript-eslint 8.66.0, ws 8.21.3,
@types/pg 8.21.0 (dev), tsx 4.23.12 (dev), csv-parse 7.0.2.
web-ui: next 16.3.0, next-intl 4.13.5, framer-motion 13.0.0,
lucide-react 1.31.0, eslint-config-next 16.3.0 (dev),
@testing-library/user-event 14.6.3 (dev).

ws, @types/pg, tsx and lucide-react take the current resolution rather
than the bot's, which had already gone stale.

framer-motion 13's only breaking change is the removal of automatic
@emotion/is-prop-valid loading; that package is absent from the tree and
MotionConfig/isValidProp appear nowhere in the repo, so the bump is inert.

Also mirrors the typescript major-version ignore from the /web-ui
dependabot block into /middleware, which lacked it and therefore
re-raised a TypeScript 7 bump every Monday (see #595).

Excludes #637 (better-sqlite3 13): v13 dropped its install hook and needs
a Docker builder toolchain, which #615 already carries.

Verified on Node 22.22.3 in CI job order: middleware 6094 pass / 0 fail,
web-ui 657 pass / 0 fail, both lint 0 errors, typecheck clean, web-ui
build and i18n:check pass, and npm audit reports 0 high / 0 critical in
both workspaces.
@Weegy
Weegy merged commit a42b1d5 into main Aug 11, 2026
10 checks passed
Weegy added a commit that referenced this pull request Aug 11, 2026
Consolidates the Dependabot PRs raised against main after #638 and #615
merged, superseding #651, #653, #654 and #655. All five PRs in this run
target /middleware only; web-ui is untouched.

openai 6.46.0 -> 7.4.0, @types/node 26.1.1 -> 26.2.0 (dev),
@aws-sdk/client-s3 3.1075.0 -> 3.1107.0, undici 8.5.0 -> 8.10.0.

@types/node is also raised from ^25.9.3 to ^26.2.0 in packages/canvas-core,
packages/conductor-core and packages/dev-runner-shim, and @aws-sdk/client-s3
is mirrored in packages/harness-diagrams, so the workspace manifests stop
skewing from the root. @types/node and @aws-sdk/client-s3 take the current
resolution rather than the bot's, which had already gone stale.

openai 7.0.0's only breaking change is that it requires Node.js 22 — there
are no API changes. That is already satisfied: engines is ">=22.13.0 <23",
.nvmrc is 22.22.3, every CI job pins node 22, and all Dockerfiles are on
node:22.23.2. The import surface is three source locations plus two tests,
deliberately funnelled through llm-adapter-openai's openaiClient.ts.

Excludes #652 (cookie 0.7.2 -> 2.0.1): v2 removed the deprecated `parse`
export in favour of `parseCookie` and went ESM-only, and we import exactly
that removed symbol in src/auth/operatorAuthAccessor.ts. It also sits in the
session-verification path, so it is handled as its own reviewable PR.

Verified on Node 22.22.3 in CI job order: build, lint (0 errors), typecheck
and 6094 pass / 0 fail / 4 skipped, with npm audit reporting 0 high /
0 critical.
Weegy added a commit that referenced this pull request Aug 13, 2026
The Windows desktop leg has failed on every release since v0.64.0
(2026-08-11), so no `.exe` installer has shipped since v0.63.0. macOS,
Linux, the release job and the image publish were all unaffected, which
is why this stayed quiet: only the Windows matrix entry went red.

Root cause: `better-sqlite3` was bumped 12 -> 13 in a42b1d5 (#615). v13
is N-API and ships prebuilt binaries for all platforms inside its own
tarball, so it declares `gypfile: false` to tell npm not to build it.
npm ignores that field and synthesises `install: node-gyp rebuild`
anyway, purely because a `binding.gyp` is present in the package.
macOS/Linux just waste time on the pointless compile; windows-latest has
no Visual Studio node-gyp can find, so `npm ci` dies outright:

    gyp ERR! find VS could not find a version of Visual Studio 2017 or newer

The same defect was already diagnosed and fixed for the container build
in #615 — the root Dockerfile carries `npm ci --ignore-scripts` plus an
explicit `npm rebuild argon2 esbuild`. The desktop workflow was simply
missed. Apply the identical treatment here.

Also drop the now-doubly-dead `GYP_MSVS_VERSION: '2022'` job env. It
never had any effect (node-gyp reads `npm_config_msvs_version`, and the
failing run logs "msvs_version not set from command line or npm config"),
and its value is wrong regardless: the runner image now ships Visual
Studio 18, which node-gyp 11.5.0 rejects as `unknown version "undefined"`.

And replace the "Provision better-sqlite3 for Electron" step with the
verification it already carried. That step could only ever fail or no-op:
upstream publishes no GitHub release assets for v13, so `prebuild-install`
always missed and fell through to a source rebuild — and even when that
rebuild succeeded, its artefact was never loaded, because v13's loader in
`lib/binding.js` resolves `prebuilds/` FIRST and only falls back to
`build/Release/`. The Electron ABI check is kept as the real gate.

Verified locally: `npm ci --ignore-scripts` on better-sqlite3 13.0.3
produces no `build/` directory, runs no node-gyp, and the module loads
and executes SQL from the bundled prebuild.
@Weegy
Weegy deleted the chore/better-sqlite3-13 branch August 14, 2026 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deps Dependency updates (Dependabot) docker Docker base images and build files middleware middleware/ workspace

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant