Skip to content

fix(deps): repair malformed expression-js lockfile, add Dependabot config + PR guard - #46

Merged
jdenquin merged 3 commits into
mainfrom
fix/expression-js-lockfile
Aug 18, 2026
Merged

jdenquin merged 3 commits into
mainfrom
fix/expression-js-lockfile

Conversation

@mikeh-lago

Copy link
Copy Markdown
Contributor

PR #45 hand-edited expression-js/package-lock.json instead of regenerating it, leaving an unterminated http-proxy-middleware/node_modules/debug entry and a duplicate http-proxy-middleware key. The file is not valid JSON, so npm ci fails with EUSAGE and Dependabot reports it cannot read the file — which is why /expression-js has had no dependency updates since 17 July.

Regenerated from the last valid lockfile with #45's webpack-dev-server ^6 bump preserved, plus a dependabot.yml (none existed) and a PR check that would have caught this. Full detail in the two commit messages.

Verified: lockfile parses, npm ci exits 0, npm audit 0 vulnerabilities, no duplicate keys.

mikeh-lago and others added 3 commits August 18, 2026 09:10
PR #45 ("chore(cve): Fix CVE 2026-41907") hand-edited
expression-js/package-lock.json instead of regenerating it. The diff
inserted a new `node_modules/http-proxy-middleware/node_modules/debug`
entry but kept the old `"node_modules/http-proxy-middleware": {` line as
untouched context, so on main:

  * the `debug` entry is never closed (978 `{` vs 977 `}`)
  * `node_modules/http-proxy-middleware` appears twice as a key, at
    lines 2620 and 2641
  * the second entry's metadata says http-proxy-middleware@2.0.10 while its
    body is debug@4.x (`ms` dependency, `supports-color` peer meta)

The file is therefore not valid JSON. Every npm/Dependabot consumer treats
it as a missing lockfile:

  $ npm ci
  npm error code EUSAGE
  npm error The `npm ci` command can only install with an existing
  npm error package-lock.json or npm-shrinkwrap.json ...

which is why Dependabot reports it cannot read the file and has stopped
opening updates for /expression-js.

Regenerated from the last valid lockfile (dda4c2c) with the
webpack-dev-server ^6.0.0 bump from #45 preserved, so churn stays minimal:
direct devDependencies are untouched apart from webpack-dev-server
5.2.5 -> 6.0.0. The transitive churn (express 4 -> 5,
http-proxy-middleware 2 -> 4, chokidar 3 -> 5, ...) is what that major
bump pulls in. Also picks up ajv 8.17.1 -> 8.20.0 (GHSA-2g4f-4pwh-qvx6)
and fast-uri 3.1.2 -> 3.1.5 (GHSA-v2hh-gcrm-f6hx, GHSA-7p8r-x3mc-p8w7,
GHSA-4c8g-83qw-93j6).

webpack.config.js has no `devServer` block, so the dev-server major bump
has no config surface to break.

Verified on node 24.11.1 / npm 11.6.2: lockfile parses, root
packages[""].devDependencies matches package.json exactly, every resolved
direct dep satisfies its declared range, no duplicate keys anywhere in the
document, `npm ci` exits 0 and `npm audit` reports 0 vulnerabilities.

Not verified: `wasm-pack`. `npm run build` exits 0 but the WasmPackPlugin
step fails silently -- root Cargo.lock pins wit-bindgen 0.51.0, which needs
cargo >= 1.85 (edition2024), while expression-js/rust-toolchain.toml pins
channel 1.81, so pkg/index.js is emitted at 1 byte. That is pre-existing on
main and unrelated to this change, but it means the release publish workflow
is currently shipping an empty wasm bundle. Tracking separately.

Drive-by: fix the repository URL typo (ago-expression -> lago-expression).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two reasons the broken lockfile in #45 went unnoticed for a month:

1. There is no .github/dependabot.yml in this repo at all, so there are no
   version-update PRs for any ecosystem here -- only org-level security
   updates, which silently produce nothing once a manifest stops parsing.
   Add entries for npm (/expression-js), cargo (/), bundler
   (/expression-ruby), gomod (/expression-go) and github-actions, staggered
   Mon-Fri so they don't all land at once.

   One cargo entry covers every Rust crate: expression-core, expression-js,
   expression-go and expression-ruby/ext/lago_expression are all members of
   the root workspace and resolve against the root Cargo.lock.
   expression-core/Cargo.lock is vestigial (31 packages vs the root's 109,
   still pinning lago-expression 0.1.0) -- cargo never reads it, so it gets
   no entry.

2. javascript.yml only runs on `release` and `workflow_dispatch`, so no PR
   ever installed the JS package. Add javascript-ci.yml, which on any PR
   touching expression-js/package.json or package-lock.json:

     * JSON.parse's the lockfile -- npm ci's own error is "no lockfile
       found", which sends people looking in the wrong place
     * runs `npm ci`, which also catches a lockfile out of sync with
       package.json (the signature of a hand-edited lockfile)
     * runs `npm audit --audit-level=high` as advisory only
       (continue-on-error): expression-js has no runtime dependencies, and a
       hard failure here would block the Dependabot PRs that fix advisories

Confirmed the job fails on main's lockfile: parse step exit 1, `npm ci`
exit 1 (EUSAGE), and it also fails on a valid-but-out-of-sync lockfile.

Deliberately no build step: `wasm-pack` currently cannot build on the
toolchain expression-js pins (rust-toolchain.toml channel 1.81 vs
wit-bindgen 0.51.0 needing cargo >= 1.85), so a build step would land red.

Note for whoever merges: the ecosystem labels (javascript, rust, ruby, go,
ci) must already exist on the repo -- Dependabot only creates its own
default labels and silently drops unknown ones.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…m is real in CI

The wasm build has been silently broken on main since 2026-01-20 and no
release has shipped since. Two independent faults:

1. expression-js/rust-toolchain.toml pinned channel 1.81, but 0ff1b8d
   ("misc(ruby): Bump to 4.0.1 (#24)") regenerated the root Cargo.lock and
   pulled wasm-bindgen 0.2.95 -> 0.2.108, which brings wit-bindgen 0.51.0.
   That manifest needs the edition2024 cargo feature, stabilised in 1.85:

     failed to parse manifest at .../wit-bindgen-0.51.0/Cargo.toml
     feature `edition2024` is required ... not stabilized in this version of
     Cargo (1.81.0)

   Pinned to 1.90 rather than the 1.85 floor: building wasm-bindgen-cli
   0.2.108 from source needs 1.88 (icu_* and time require rustc 1.88), and a
   minimum-viable pin is what let 1.81 rot in the first place. Also declares
   the wasm32-unknown-unknown target so rustup provisions it from the repo.

2. Nothing caught it, because @wasm-tool/wasm-pack-plugin surfaces a failed
   wasm-pack run as a webpack error but webpack still exits 0. On main:

     $ npm run build          # exit 0, "compiled successfully"
     $ ls -l pkg/             # index.js, 0 bytes
     $ ls -l dist/            # index.js 5,278 B, no .module.wasm
     $ wasm-pack pack         # exit 1 -- where javascript.yml actually dies

   So `npm run build` is not a usable signal. The new `wasm` job asserts on
   the artifacts instead: a *_bg.wasm exists, is >50KB, starts with the
   0061736d magic number, webpack emitted a .module.wasm, and `wasm-pack
   pack` succeeds.

Verified both directions on this branch: with channel 1.81 the assertions
exit 1 while `npm run build` still exits 0; with 1.90 the crate compiles,
pkg/index_bg.wasm is 270,792 bytes of valid wasm, webpack emits the
.module.wasm and `wasm-pack pack` exits 0.

Good news on impact: nothing broken was published. The last npm release,
lago-expression@0.2.0 (2026-01-02), predates the breakage by 18 days and
contains a healthy 193,203-byte index_bg.wasm. The failure mode is a red
release, not a corrupt artifact -- javascript.yml dies at `wasm-pack pack`
before `wasm-pack publish` runs. But the next release would have failed,
and would have looked like a mystery.

Widened the workflow path filters to expression-js/**, expression-core/**,
Cargo.toml and Cargo.lock, since a cargo bump is what broke it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jdenquin
jdenquin merged commit efdabfa into main Aug 18, 2026
4 checks passed
@jdenquin
jdenquin deleted the fix/expression-js-lockfile branch August 18, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants