Skip to content

fix(deps): take the fix for next GHSA-vcvr-r3jv-pc5j (critical) and dompurify GHSA-p98j-92pf-mc4p - #21083

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-21055-osv-next-dompurify
Oct 1, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-21055-osv-next-dompurify

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #21055

Clause-②: no

Summary

Validate Package Dependencies runs OSV-Scanner against pnpm-lock.yaml. On main it flags two rows, so the scheduled scan is red, and so is every PR that touches a package.json:

Advisory CVSS Package Locked on main Fixed in
GHSA-vcvr-r3jv-pc5j 9.5 next 16.3.3 16.3.6
GHSA-p98j-92pf-mc4p 2.3 dompurify 3.4.13 3.4.16

Both advisories name a fixed version, so this PR takes the fix. osv-scanner.toml is untouched and still holds zero exemptions.

Change

  • apps/docs/package.json: the direct next pin moves from 16.3.3 to 16.3.6. The pin stays exact, as it was. 16.3.6 is the advisory's fixed version and the same target as Dependabot's grouped chore(deps)(deps): bump the production-dependencies group with 27 updates #21029, so after this lands, that PR's next line is already satisfied rather than in conflict. The newer patches (16.3.7, 16.3.8) are left to the Dependabot group. No workspace manifest declares eslint-config-next or any @next/* package. The nine @next/* packages in the lockfile are next's own dependencies and move with it.
  • pnpm-workspace.yaml: the existing dompurify override's target goes from ^3.4.13 to ^3.4.16. Its selector is unchanged, still bounded at the 4.0.0 major. The OSV comment above it is extended in place, in the style of its neighbours. This PR adds no second override and does not touch the root package.json.
  • pnpm-lock.yaml: regenerated, not hand-edited (see below).

Correction to the issue body. The issue says the root pnpm.overrides has no floor for dompurify. On main, the workspace's overrides live in pnpm-workspace.yaml, because pnpm 10 ignores pnpm.overrides in package.json. A dompurify entry was already there at ^3.4.13, added for an earlier advisory (#6407). The new advisory's range is introduced 3.4.13, fixed 3.4.16, so the old floor was itself the first affected version. The existing comment had predicted this: it explains that the selector is bounded at the major so that a target-only lift is all a case like this needs. mermaid@11.16.1 declares dompurify ^3.3.3, which admits 3.4.16, so this is a dedupe onto the patched line and does not force an upgrade past what mermaid supports.

Reach. apps/docs/app/og/docs/[...slug]/route.tsx imports ImageResponse from next/og. That is the surface GHSA-vcvr-r3jv-pc5j names ("Remote Code Execution in next/og ImageResponse").

Lockfile

Regenerated with pnpm install --lockfile-only under pnpm 10.31.0, the packageManager version.

  • Size: 69 lines changed on each side, 138 in total.
  • Locked package set: 11 entries removed and 11 added, and the count stays at 1369. The entries are next, @next/env, the eight @next/swc-* binaries, and dompurify.
  • Everything else: the other changed lines are peer-suffixed snapshot keys that embed the next version. They belong to better-auth, its three @better-auth/* plugins, and fumadocs-core / fumadocs-mdx / fumadocs-ui. None of those packages changes version.
  • Frozen install: pnpm install --frozen-lockfile passes on the result.

OSV-Scanner, before and after

I ran OSV-Scanner v2.3.8, the version the workflow's action pins. The binary's SHA-256 (bc98e153…) matches the release's checksum file. The command was scan --offline-vulnerabilities --lockfile=pnpm-lock.yaml. The container's egress proxy refuses api.osv.dev, so the scan reads the offline npm database the scanner downloads, the same method as #20774.

Tree Exit Result
main at 5dbeb7d7b7 1 exactly the two rows above (1 Critical, 1 Low)
this branch at 68c26aa189 0 No issues found (1369 packages)

Changeset decision

No changeset; this PR should carry the skip-changeset label. Nothing it touches is published:

  • apps/docs is "private": true.
  • pnpm-workspace.yaml overrides and pnpm-lock.yaml are in no package's files[], and no published manifest changes.

check:override-consistency still reports its 9 published-manifest declarations covered, and check:published-files is green.

What I ran

The final head is 68c26aa189: my commit, then a merge of main at 0c5a71b094. Every row below was measured on that head. The build and the docs checks were also green on 3714ec8cef, before the merge.

Check Result
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands 41 commands
All 41, run on 68c26aa189 after a rebuild, codes recorded with the --ran idiom 41 exit 0
dispatch-gates --ran 41 derived, 41 run, 0 NOT-MEASURED, 0 UNRUN
pnpm build under the shared verify lock, --concurrency=2 72/72, both at 3714ec8cef and at 68c26aa189
pnpm --filter @objectstack/docs typecheck (fumadocs-mdx && next typegen && tsc --noEmit) exit 0
Docs production build command (apps/docs/vercel.json): pnpm turbo run build --filter=@objectstack/docs exit 0, Next.js 16.3.6, .next/BUILD_ID written, and the docs task was a cache miss, so it really executed
check:override-consistency, check:vendor-export-contract-resolve, check-osv-exemptions, check:nul-bytes, check:workspace-manifest-cycles all exit 0 (within the 41)

One deliberate difference from CI: the docs build ran without CI's TURBO_FORCE, which would also re-execute the spec build. The docs task itself missed the cache and ran. No package test suite applies, because no package source changes. CI's shard, dogfood and workspace type-check lanes are left to CI.

Acceptance notes


Generated by Claude Code

claude added 2 commits October 1, 2026 04:35
…SA-p98j-92pf-mc4p

OSV-Scanner on main's lockfile flags two rows: next 16.3.3 (CVSS 9.5,
fixed 16.3.6) and dompurify 3.4.13 (CVSS 2.3, fixed 3.4.16).

- apps/docs/package.json: the direct next pin moves 16.3.3 -> 16.3.6.
- pnpm-workspace.yaml: the existing dompurify override's target lifts
  ^3.4.13 -> ^3.4.16, selector unchanged at the 4.0.0 boundary; its
  advisory-history comment is extended in place.
- pnpm-lock.yaml: regenerated with pnpm 10.31.0 --lockfile-only. Only
  next, its nine @next/* packages and dompurify change version; the
  locked package count stays 1369.

No osv-scanner.toml exemption.

Claude-Session: https://claude.ai/code/session_01JAhu8u8QfBvRjVZDox7CP9
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 68c26aa189b4bef26e832045e8bd27ae1459abc3
Local-runs: none

Inputs: card #21055 (body, triage 5924465236, claim 5924776234, os-dev-report 5925128805, ACCEPT 5925147796), PR #21083 (body, file list, no comments or reviews), the net diff origin/main (2821e9f15b) ... 68c26aa189 (merge-base 0c5a71b094), the head's check-runs, AGENTS.md, .claude/skills/pm-dispatch/references/contract-review.md, pnpm-workspace.yaml, osv-scanner.toml, .github/workflows/validate-deps.yml, .github/workflows/ci.yml (Build Docs, Type Check lanes), .github/workflows/pr-automation.yml (Check Changeset), .changeset/config.json, apps/docs/package.json, apps/docs/vercel.json, apps/docs/next.config.mjs, apps/docs/app/og/docs/[...slug]/route.tsx, scripts/check-override-consistency.mjs, and npm view on next, dompurify, mermaid@11.16.1. Not read: the dispatch order, the dispatching seat's conclusions. Not reachable from this session: api.osv.dev and the GitHub advisory endpoint (both refused), so the two advisories' ranges are judged from the card's scanner table, the dev's offline-database read and the head's green scanner, as stated below.

① Derived judgments

Diff: 3 files, +80 −71 — apps/docs/package.json +1 −1, pnpm-workspace.yaml +10 −1, pnpm-lock.yaml +69 −69. Two commits: the fix 3714ec8cef and a merge of main at 0c5a71b094.

  1. next 16.3.3 → 16.3.6, exact pin kept (apps/docs/package.json:21) — RIGHT. 16.3.6 is the release both the card's scanner table ("Fixed in 16.3.6") and the dev's offline OSV-database read name as GHSA-vcvr-r3jv-pc5j's fixed version, and Validate Package Dependencies on this head is success (its OSV step pins the same scanner, v2.3.8, and matched nothing). Registry: 16.3.6 published 2026-09-22; latest is 16.3.8 (16.3.7 on 09-29, 16.3.8 on 09-30). The triage direction is "≥ 16.3.6", satisfied. next is declared by apps/docs and by no other workspace manifest (no eslint-config-next, no @next/* declared anywhere; measured with a grep over every package.json at the head).
  2. The docs app's use of next stays inside the 16.3.x patch promise — RIGHT. next@16.3.6's manifest against 16.3.3: dependencies identical except the self-versioned @next/env; optionalDependencies identical except the eight self-versioned @next/swc-* and sharp ^0.35.3 → ^0.35.4 (the lockfile already held sharp 0.35.4, an unchanged context line); peerDependencies, postcss 8.5.23, styled-jsx 5.1.6 and engines node ≥ 20.9.0 unchanged. The app's own surfaces are untouched by the diff: App Router pages, apps/docs/app/og/docs/[...slug]/route.tsx importing ImageResponse from next/og (the surface the advisory names, so the fix reaches the one caller), next.config.mjs (agentRules: false, experimental.cpus, turbopackSourceMaps, the turbopack alias, headers / rewrites / redirects). CI's Build Docs evaluates apps/docs/vercel.json's buildCommand verbatim under TURBO_FORCE and is success. What ships to docs-site users changes by the two library patches and nothing else.
  3. dompurify override target ^3.4.13 → ^3.4.16, selector unchanged (the existing dompurify@ entry with its exclusive bound at the 4.0.0 major) — RIGHT, and consistent with the overrides header. The header's SELECTOR SHAPE rule: an OSV pin is a floor, the selector covers the whole major, the target floats inside it, and "ONLY the target moves from now on"; dompurify is not a surface this repo compiles against, so the caret target (not the better-auth-style exact) is the correct arm. This is precisely the target-only lift the Validate Package Dependencies 在所有 PR 上红:dompurify@3.4.12 新公告 GHSA-55q2-fjhq-7xh7(已有 fix 3.4.13,经 mermaid 传递引入) #6407 note pre-announced. The floor binds this workspace alone: no workspace manifest declares dompurify (its only consumer in the lockfile is mermaid@11.16.1, declared by apps/docs only, which is private: true); pnpm-workspace.yaml is named in no package's files[]; no published manifest changes; check:override-consistency ran inside the green Validate Package Dependencies. Registry: dompurify@3.4.16 exists (2026-09-23, latest, no dependencies); mermaid@11.16.1 declares dompurify ^3.3.3, which admits 3.4.16 — a dedupe inside mermaid's own range. The root package.json pnpm field holds only ignoredBuiltDependencies, so the issue body's "root pnpm.overrides has no floor" was wrong about where the override lives; the PR's correction is right and matches the workspace file's own header ("pnpm v10 reads overrides from THIS file").
  4. Lockfile moves only next, its @next/* closure and dompurify — RIGHT. Census of all 138 changed lines: the overrides echo (2 lines); 11 package entries out and 11 in — next, @next/env, the eight @next/swc-*, dompurify — each as a resolution/integrity pair plus its snapshot stub, with the apps/docs importer's specifier/version lines; every remaining changed line is a peer-suffixed snapshot key or dependency line that embeds next@16.3.3 → 16.3.6 (fumadocs-core, fumadocs-mdx, fumadocs-ui, better-auth, @better-auth/oauth-provider, @better-auth/scim, @better-auth/sso) or mermaid's dompurify: 3.4.13 → 3.4.16 dependency line. No other package changes version; the lockfile header and settings are unchanged. Shape is a regeneration, not a hand edit.
  5. No exemption, no changeset file — RIGHT. osv-scanner.toml is byte-identical between origin/main and the head (zero exemptions, as its header requires); nothing under .changeset/ is in the diff.
  6. The new pnpm-workspace.yaml comment — RIGHT, with one provenance note. Date 2026-10-01 and card #21055: correct. GHSA-p98j-92pf-mc4p (2.3 low): the id and 2.3 are the card's scanner table, and 2.3 is CVSS Low. fixed: 3.4.16: the scanner table. introduced: 3.4.13 and the hook description ("IN_PLACE node-removing afterSanitize hook leaves the detached subtree's event handlers armed"): the dev's reading of the offline OSV database, which the comment itself attributes; it is consistent with the Validate Package Dependencies 在所有 PR 上红:dompurify@3.4.12 新公告 GHSA-55q2-fjhq-7xh7(已有 fix 3.4.13,经 mermaid 传递引入) #6407 note above it (3.4.13 was the previous advisory's fix on the same IN_PLACE-hook class) and with the old floor ^3.4.13 being the one version the scanner flagged, and it is not independently re-fetched from here. mermaid@11.16.1's ^3.3.3 admits 3.4.16: registry-confirmed. "The floor binds this workspace's resolution only; overrides do not reach downstream installs": the same sentence validate-deps.yml and check-override-consistency.mjs carry. Style matches its neighbours (dated OSV note, card number, no new claim about the gate's output).
  7. Check-runs on 68c26aa189, 41 runs, read 2026-10-01T05:13:58Z. success: Validate Package Dependencies, Build Docs, Build Core, Check Changeset, Governed Surface Queue Guard, Dogfood Regression Gate (and shards 1/3, 2/3, 3/3), Dogfood Verify CLI, Temporal Conformance (live PG + MySQL), Test Core 2/6 and 4/6, Type Check · source gates, Type Check · consumer gates, Type Check · debt ledger, Check PR Size, Auto Label, Check Documentation Links, Stable release watch for prerelease pins, The card this PR closes must claim this branch, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, filter. Still in_progress at read: Lint & Repo Gates, Type Check · workspace (it runs turbo run typecheck over ./apps/*, so it carries the docs typecheck), Test Core 1/6, 3/6, 5/6, 6/6. skipped: label-event re-runs of Auto Label, Check PR Size, Check Changeset, Packed-tarball smoke (opt-in), Console Pin Gate. No run has failed. "Every check green" before landing is the dispatching seat's re-read, not this record's claim.

② Semver level

Nothing published moves. next is declared only by @objectstack/docs (private: true, no files[], absent from .changeset/config.json's fixed group); dompurify is declared by no workspace manifest; pnpm-workspace.yaml overrides and pnpm-lock.yaml are in no package's files[] and ship in no tarball; no published package's dependency range changes. AGENTS.md Post-Task Checklist step 3's skip-changeset arm — "a diff that publishes nothing from any released package" — therefore holds; the label is on the PR and Check Changeset is success. origin/main precedent agrees in both directions: #20774 (override floors plus lockfile only) landed with no changeset, while #20719 carried one because it moved packages/metadata's declared range. @objectstack/docs's own CHANGELOG (versioned through privatePackages.version: true) records content fixes to the shipped pages; a dependency patch that changes no page is not owed one. Clause-②: no on line 3 of the PR body is correct — no accept-set or public-surface change, no arm. Level: none (skip-changeset), matching the diff.

③ Boundary flags

os-dev-report 5925128805: open_questions is empty. Its three deviations and one out_of_scope_findings entry:

  1. next 16.3.6 rather than the newest 16.3.8 — ANSWERED, accepted. The triage direction is "≥ 16.3.6"; osv-scanner.toml's header rule is "when an advisory HAS a fixed version, you take the fix"; the scanner on this head matches nothing at 16.3.6; and 16.3.6 is Dependabot chore(deps)(deps): bump the production-dependencies group with 27 updates #21029's target, so the grouped PR's next line is satisfied rather than in conflict. 16.3.7 and 16.3.8 stay in Dependabot's lane. No input names an advisory on 16.3.6.
  2. Local docs build ran without CI's TURBO_FORCE — ANSWERED, superseded. CI's Build Docs ran vercel.json's command under TURBO_FORCE on this head and is success.
  3. main moved 4 commits after the merged 0c5a71b094 — ANSWERED, verified. git log 0c5a71b094..origin/main -- pnpm-lock.yaml pnpm-workspace.yaml apps/docs/package.json package.json is empty (the four commits are feat(cli)!: os validate and os build refuse a picklistExtensions entry whose extend names no declared picklist #21049, feat(objectql,metadata-protocol): validate and insertMany answer which row lost which field #21041, fix(core,driver-sql,service-analytics): the analytics native-SQL path answers measures declared number as numbers (#20889) #21040, fix(objectql)!: engine aggregate asks the field-type table for every row — min / max / avg over a refused type answer INVALID_FIELD / 400 on every driver #21037); the PR is mergeable: true. No second merge was owed.
  4. Out of scope: the pre-existing Validate Package Dependencies 在所有 PR 上红:dompurify@3.4.12 新公告 GHSA-55q2-fjhq-7xh7(已有 fix 3.4.13,经 mermaid 传递引入) #6407 note says check-override-consistency.mjs "will list this as an override it cannot cross-check" — ANSWERED, confirmed stale, no carrier needed. The script (identical on main and the head) prints only its Consumer census and Self-expiring selectors reports; the sentence predates this diff, and the diff's new lines do not repeat it. Under Prime Directive chore: version packages #10 a stale comment is an acceptance note, not a card; it is recorded in the report and in the card's ACCEPT comment. The PR body's Acceptance notes do not carry it — a note, not a defect; no escalation.

No flag is left open. The PR is a draft on an apps/docs/** face carrying needs:contract-review; removing that label on a PASS is the writing seat's act, not this record's.

Implemented-by: claude/issue-21055-osv-next-dompurify
Reviewed-by: session_01JAhu8u8QfBvRjVZDox7CP9

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 1, 2026 05:39
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 1, 2026 05:39
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit b10f6e4 Oct 1, 2026
48 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-21055-osv-next-dompurify branch October 1, 2026 06:27
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
… better-auth family (objectstack-ai#21094) (objectstack-ai#21162)

Fixes objectstack-ai#21094

Clause-②: no

Takes the 2026-10 production-dependency group that Dependabot opened as
objectstack-ai#21029 (closed in favour of this card), without the better-auth family
and without `next`. Maintainer ruling, verbatim:

> 按你的推荐:关掉21029立卡,better-auth先放着,21024授权你落地

## What lands

- **43 manifests, 64 range moves.** The 63 range moves objectstack-ai#21029 made
(diffed from its merge base `9b0de7de73` to its head `c0b7dd923e`) were
re-applied one line at a time onto current `main`. The 64th is the `tsx`
devDependency objectstack-ai#21160 added to
`packages/drivers/driver-turso/package.json`, lifted from `^4.23.12` to
`^4.23.15` after objectstack-ai#21160 was merged in. Each move matched the exact old
spelling or the script refused. Excluded: `apps/docs/package.json`
(`next` belongs to objectstack-ai#21055 / objectstack-ai#21083) and the five better-auth family
lines in `packages/plugins/plugin-auth/package.json`, which stay at
`1.7.3`. `pnpm-workspace.yaml` is not touched. Check, taken before the
objectstack-ai#21160 merge: the sorted `-`/`+` lines of this branch's manifest diff
equal objectstack-ai#21029's lines minus those exclusions (`diff` exit 0, 126 lines).
- **`pnpm-lock.yaml`**, regenerated with the tooling in three steps
(pnpm 10.31.0, the `packageManager` pin), never by hand:
  1. `pnpm install --lockfile-only`, starting from main's lockfile.
2. `pnpm --filter @objectstack/plugin-hono-server --filter
@objectstack/plugin-auth --filter @objectstack/hono update
--lockfile-only --no-save hono`. Step 1 left `hono` at 4.13.7, below the
`^4.13.9` that `plugin-hono-server` now publishes. The workspace
override for `hono` (selector below 5.0.0) rewrites every declaration to
`^4.13.5`, which 4.13.7 still satisfies, so lockfile inertia kept the
old version. CI would have certified 4.13.7 while a downstream install
gets 4.13.12. That is the declared-versus-tested split the card names
for better-auth. Step 2 moves the single `hono` copy to 4.13.12 without
editing the override or any manifest. An unfiltered `pnpm update -r` was
tried and discarded: it also dropped `knex`'s `mysql2` / `pg` /
`tedious` peer links in two importers.
3. After objectstack-ai#21160 landed: merge `main` (`e35c40a52`), lift driver-turso's
new `tsx` line, and run `pnpm install --lockfile-only` again.
- The result is a fixed point: a second `pnpm install --lockfile-only`
leaves it byte-identical, and `pnpm install --frozen-lockfile` passes.
Lockfile blob `30ba2147`. The resolved set is unchanged from the set the
OSV scan below covered: 0 names differ.
- **`packages/drivers/driver-turso/src/**`**: the item-4 restamp, 21
lines in 7 files (below).
- **`packages/spec/src/data/driver/common.zod.ts` and
`driver-credential-refusal.test.ts`**: the `@libsql/core` version label
is restamped from 0.17.4 to 0.18.0. The TSDoc of
`CREDENTIAL_URL_QUERY_PARAMS` says it was measured "in the versions
pinned by this tree", so leaving 0.17.4 would have made it false. The
behaviour was re-measured identical on the installed 0.18.0:
`?authToken=` overrides the config token, `auth%54oken` is decoded,
`AuthToken` and `token` give `URL_PARAM_NOT_SUPPORTED`, and the control
without a query keeps the config token.
- **`.changeset/21094-prod-deps-group.md`**: `patch` for the 19
published packages whose `dependencies` range moves. The list was
re-derived from this diff and matches the PM correction on the card,
`plugin-auth` included (`@noble/hashes`, `jose`).

## Resolved versions against the merge base

Every changed `name@version` pair in the `packages:` section, compared
with `main` at `e35c40a52`: 25 names change. **DOWN: 0.**

| package | merge base | this branch |
|:--|:--|:--|
| `@libsql/client` / `@libsql/core` | 0.17.4 | 0.18.0 |
| `zod` | 4.6.1 | 4.6.5 (4.6.1 kept by `apps/docs` only) |
| `@modelcontextprotocol/sdk` | 1.30.0 | 1.31.0 |
| `hono` | 4.13.7 | 4.13.12 |
| `mongodb` | 7.5.0 | 7.7.0 (7.5.0 kept by `mongodb-memory-server-core`
only) |
| `jose` | 6.2.7, 6.2.8 | 6.2.12 |
| `@noble/hashes` | 2.3.0 | 2.4.0 |
| `@noble/ciphers` | 2.3.0 | 2.4.0 (2.3.0 kept by better-auth 1.7.3
only) |
| `react` / `react-dom` / `@types/react` / `@types/react-dom` | 19.2.x |
19.3.0 (19.2.x kept by `apps/docs` only) |
| `tsx` | 4.23.12 | 4.23.15 |
| `yaml` | 2.9.0 | 2.9.1 (2.9.0 kept by the `apps/docs` fumadocs tree
only) |
| `chalk` | 6.0.0 | 6.0.1 |
| `sql.js` | 1.14.1 | 1.14.2 |
| `pinyin-pro` | 3.29.1 | 3.29.4 |
| deduped onto a newer copy already present | `@hono/node-server`
2.0.12, `ws` 8.21.1, `@types/ws` 8.18.1, `eventsource-parser` 3.1.0 |
removed (2.1.1, 8.22.0, 8.18.2, 3.1.1 stay) |
| new transitive copies beside the old ones | none | `bson` 7.3.3 and
`@mongodb-js/saslprep` 1.5.5 (with `mongodb` 7.7.0), `scheduler` 0.28.0
(with `react-dom` 19.3.0) |

`nodemailer` stays at **10.0.13**, main's version and at least the
required 10.0.12. Dependabot's regeneration had moved it down to
10.0.11.

## Item 4: `@libsql/client` lifted to `^0.18.0`, because the premise
holds

The premise was measured before any driver edit, three ways.

1. **Package diff.** `npm pack` of both releases. `@libsql/core` 0.17.4
and 0.18.0 differ only in `package.json` (the version). `@libsql/client`
differs only in `lib-esm/sqlite3.js`, `lib-cjs/sqlite3.js`,
`lib-esm/sqlite3.d.ts` and `package.json`. The change is a connection
pool for the local `file:` client. `http.js`, `ws.js` and `node.js` are
byte-identical. Installed side by side, `@libsql/hrana-client` 0.10.0
and native `libsql` 0.5.29 (with `@libsql/linux-x64-gnu`) are
byte-identical too.
2. **Executed probe, same script against both installs.** Output is
identical except for the version strings and one count: `syncUrl`
occurrences in `sqlite3.js` go from 3 to 4 (the new pool-size line).
3. **The driver's own suite.** At base with 0.17.4: 81 files, 2210
passed, 33 skipped. With 0.18.0, before the restamp: 2209 passed, 1
failed, 33 skipped. Per-test outcomes are identical except the version
pin (`expected '0.18.0' to be '0.17.4'`). After the restamp: 2210
passed, 33 skipped. At `0f87e8488`, with objectstack-ai#21160's tests merged in: 2218
passed, 33 skipped, 0 failed.

| site (at base) | claim | 0.18.0 reading | verdict |
|:--|:--|:--|:--|
| `turso-authtoken-url-channel.test.ts:17-18` | client / core / native
versions, range | client 0.18.0, core 0.18.0, native `libsql` 0.5.29;
range now `^0.18.0`. Answers 1-4 (live wire, child-process replica
endpoint) pass, 7/7 non-pin cases, as 8/8 did on 0.17.4 | held,
restamped |
| `turso-authtoken-url-channel.test.ts:281` | version pin | `0.18.0` |
pin moved |
| `turso-driver-remote-url-replica-refusal.test.ts:28`,
`turso-driver.ts:1288`, `:1384` (message) | no embedded replica for a
remote url | `syncUrl` lines: `http.js` 0, `ws.js` 0, control
`authToken` lines 6 / 6. `https` and `ws` clients' `sync()` reject
`SYNC_NOT_SUPPORTED`. `:memory:` + `syncUrl` throws `URL_INVALID`
("Embedded replica must use file for local db"). File 27/27 on both
versions | held |
| `turso-driver-timeout.test.ts:9`, `turso-driver.ts:152` | HTTP arm
rides `Config.fetch`; replica `sync()` is native | `http.js` (one
`config.fetch` site) and hrana-client byte-identical. Timeout file 5/5,
supplied-client refusal file 13/13 on both | held |
| `turso-driver.ts:871` | `Config.timeout` is the busy timeout; "remote
clients ignore it" | core `api.d.ts` docblock byte-identical | held |
| `turso-driver-unrecognised-url-refusal.test.ts:26`,
`turso-driver.ts:1313`, `:1417` (message) | refusals of urls the client
rejects | `URL_INVALID` for `./data/app.db`, `data/app.db`,
`/abs/app.db`, `:MEMORY:`, empty, `libsql:host` (bare paths "not in a
valid format"). `URL_SCHEME_NOT_SUPPORTED` for `sqlite:`, `memory://`,
`C:\data\app.db`. File 42/42 on both | held |
| `turso-driver-uppercase-ws-scheme-timeout-refusal.test.ts:15`, `:26`,
`turso-driver.ts:932` | `expandConfig` lowercases the scheme before the
switch | `WSS://…` gives `wss`, `Ws://…` gives `ws`, control
`LIBSQL://…` gives `https`. `_createClient(expandConfig(config, true))`
present (1 hit). File 20/20 on both | held |
| `turso-driver-ws-timeout-refusal.test.ts:10`, `turso-driver.ts:963`,
`:1001` (message) | the WS client takes no `fetch` and no timeout |
`ws.js`: `fetch` 0, `timeout` 0. hrana `ws/*.js` + `index.js` `timeout`
0, control `fetch` over `http/*.js` 15. File 11/11 on both | held |
| `turso-driver.ts:1061` (message) | a built client's transport cannot
be re-seamed | `config.fetch` is read once, inside `_createClient` in
`http.js` (byte-identical) | held |
| `turso-driver.ts:1212` | the client folds scheme case and opens each
spelling | `FILE:./x.db` gives `file`, `Wss://` gives `wss`, `LIBSQL://`
gives `https`. `createClient` opens each (`http` / `ws` / `file`) | held
|
| `turso-driver.ts:1244` | `:memory:` expands to `file::memory:`;
`isInMemoryConfig` | `file::memory:`. `true` for `file::memory:` and
`file::memory:?cache=shared`, control `false` for `file:./x.db` | held |

After the edit, `git grep -n -E "0\.17\.[0-9]" --
packages/drivers/driver-turso/src` returns 0 lines (exit 1). The control
is the 23 `0.18.0` occurrences in the same 7 files.

## What objectstack-ai#21029 never measured

- **Test Core shard 4's eight unreached packages**, measured at
`cf1d700b`, before the `main` merge: `rest` 250 files, 4728 passed / 248
skipped. `driver-sql` 205 files, 3303 passed / 188 skipped.
`plugin-email` 31 files, 510 passed. `plugin-approvals` 52 files, 804
passed. `plugin-webhooks` 13 files, 160 passed. `trigger-schedule` 8
files, 170 passed. `connector-mcp` 3 files, 23 passed. `client-react` 3
files, 34 passed. Turbo ran 45 of 45 tasks, exit 0.
- **`Lint & Repo Gates` from `check:vendor-export-contract` on**: `pnpm
check:vendor-export-contract` reads `VERDICT: PASS — vendor export
contract (installed workspace), 1 edge(s) verified` (better-auth 1.7.3),
and the `-resolve` variant passes on the registry. The 72 later steps of
that job were not run here. They belong to CI's run on this PR. The
families this diff derives are below.
- **OSV.** `osv-scanner` v2.3.8, built from the Go module proxy because
this container's egress refuses `api.osv.dev`. It ran on the offline npm
database over lockfile blob `70547c67` (its resolved set is identical to
the current `30ba2147`), with the repo's `osv-scanner.toml` loaded: 1388
packages, `No issues found`, exit 0. Positive control: the same lockfile
with `hono` rewritten to 4.12.32 gives exit 1 and 8 advisories on
`hono`, among them GHSA-8j4g-w8fx-2239. CI's online step is the
authoritative reading.
- **`zod` 4.6.5 and `z.properties()`**: `git grep -n -E
"z\.properties\(" -- packages/` returns 0 lines; control `z.object(`,
1825 lines.
- **`mongodb` live suites**: NOT MEASURED. They need a `mongod` download
from `fastdl.mongodb.org`, which this container's egress refuses
(CONNECT 403). The default `driver-mongodb` suite passes: 30 files, 675
passed, 172 skipped (the five opt-in live files).

## Gates and tests

Gate families derived by `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` (no paths, change set from git)
at HEAD **`0f87e8488`** (54 paths against merge base `e35c40a52`): 117
commands. All 117 exit 0, and so does `pnpm
check:vendor-export-contract`. Exit codes were captured before any pipe.
`--ran` reconciliation: `117 derived, 117 run, 0 NOT-MEASURED, 0 UNRUN`,
a derived zero with an exit code on every line.

Package suites, all exit 0:

- At `cf1d700b`: `driver-mongodb`, `mcp` 32/344, `plugin-hono-server`
27/324, `plugin-auth` 115/2472, `service-settings` 33/584,
`plugin-pinyin-search` 2/21, `driver-sqlite-wasm` 36/675,
`driver-memory` 69/1613, `service-analytics` 155/3526 (10 skipped),
`create-objectstack` 16/247, `@objectstack/hono` 5/122. Also
`@objectstack/cli` `--project unit` 242/3432 and `@objectstack/spec`
`--project local` 591 files / 17368 passed.
- `typecheck`: the 19 moving packages plus `client-react`,
`@objectstack/hono` and `lint`. Turbo ran 80 of 80 tasks.
- At `0f87e8488`, after the objectstack-ai#21160 merge and a full rebuild: the
`driver-turso` suite (82 files) gives 2218 passed / 33 skipped / 0
failed. That includes objectstack-ai#21160's new tests, run on 0.18.0; its two-process
concurrency test overlapped, with 400 writes and 400 distinct numbers.
`typecheck` passes, and `pnpm install --frozen-lockfile` passes.

## Acceptance notes

- **Duplicate copies left by the exclusions**: `zod` 4.6.1, `react`
19.2.8 and `yaml` 2.9.0 are kept only by the excluded `apps/docs` tree.
`@noble/ciphers` 2.3.0 is kept only by the excluded better-auth 1.7.3.
`mongodb` 7.5.0 is kept only by the test harness
`mongodb-memory-server-core` 11.3.0.
- **libsql 0.18.0's one behaviour change, from reading the code (not
measured):** the local client now pools connections, with one connection
for `:memory:` and for embedded replicas. On a replica, a second
`sync()` therefore waits for the first to release the connection. On
0.17.4 the two ran at once on the same native handle. With `timeout`
set, a sync that outlives the window keeps running natively,
uncancelled, so the next periodic sync queues behind it. No driver
docblock claims either behaviour.
- **The remaining 0.17.4 stamps stay**: outside `CHANGELOG.md`, only
`service-package` `index.ts:192` and `mysql2-tuple.test.ts:172` name
0.17.4 ("Measured on `@libsql/client` 0.17.4"). That is a dated
attestation and stays true; the `result.rows` shape was re-measured
identical on 0.18.0.
- **Environment side effect, nothing committed**: turbo 2.11.5 appends a
managed block to `AGENTS.md` whenever an agent runs a repository-scoped
turbo command. It was restored after each turbo run with `git restore
--source=HEAD --staged --worktree AGENTS.md`. No commit on this branch
touches `AGENTS.md`.
- **Merge-queue ejection and its fix**: objectstack-ai#21160 added driver-turso's
`tsx` at 4.23.12 while this branch removes `tsx@4.23.12`. The two
lockfiles merged into one that `pnpm install --frozen-lockfile` refuses.
Fixed by merging `main` at `e35c40a52`, lifting that `tsx` line, and
regenerating the lockfile with pnpm.

---
_Generated by [Claude
Code](https://claude.ai/code/session_018gA1pE6eJtwHhqx72G8U9X)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants