chore(deps): drop the prosemirror pins, gate dedupe in CI - #19
Merged
Conversation
The three exact `prosemirror-*` overrides in web/pnpm-workspace.yaml existed to deduplicate the editor core that @tiptap/pm and y-prosemirror both pulled in. y-prosemirror is gone — @tiptap/y-tiptap replaced it in the Tiptap 3 migration, and it declares prosemirror-* as PEER dependencies, so it resolves to the consumer's copy and cannot introduce a second one. The pins had outlived their reason. They had also started doing harm. @tiptap/pm@3.31.3 declares prosemirror-model ^1.25.11 and prosemirror-view ^1.42.3; the overrides held the tree at 1.25.7 and 1.41.8, BELOW both. pnpm `overrides` bypass range checks silently, so this installed without a warning. Dropping them moves prosemirror-model 1.25.7 -> 1.25.11 and prosemirror-view 1.41.8 -> 1.42.3. prosemirror-view 1.42.3 also carries an XSS fix in clipboard handling — attribute validators were not run on attributes arriving via slice context. No advisory was ever filed, so no vulnerability scanner would have surfaced it. knot was not reachable through it: Tiptap only sets `spec.validate` when an extension declares one, and knot declares none. Being on the patched version closes the exposure the moment that stops being true. a5c7042 introduced these pins blaming prosemirror-view 1.42 for a history-restore failure, and ccf5dbd retracted that diagnosis — the real defect was ReplaceWithMarkdown broadcasting only its insertion. This commit deletes the last in-tree record of that exchange, so: e2e/flows/history.spec.ts is the test that motivated the pin, and it passes on 1.42.3. CI gains `pnpm dedupe --check`. This is not belt-and-braces. While preparing this change the tree was genuinely split for one run — @tiptap/pm linked prosemirror-view@1.41.8 while @tiptap/y-tiptap linked 1.42.3 — and tsc, eslint and all 153 unit tests passed anyway. The old override comment claimed tsc would catch duplication with a wall of "not assignable" errors. It does not; TypeScript is structural and the two Node classes match. Nothing else in CI looks at resolution, and lockFileMaintenance runs `pnpm update` and automerges itself once green, so an automated lockfile refresh could re-split the editor core unobserved. `--check` fails only when duplication is avoidable, which is exactly the condition worth failing on. Renovate: the prosemirror packageRule is dead config now that the overrides are gone (Renovate does not raise PRs for transitive npm deps outside lockFileMaintenance). Replaced with a rule grouping @tiptap/y-tiptap into the `tiptap` group — it is published from ueberdosis/y-tiptap, a different repo, so the monorepo preset does not group it, and it would otherwise be bumped in its own PR without the tiptap version it has to work with. Verified: tsc, eslint --max-warnings 0, 153 unit tests, and 18/18 of the editor-critical Playwright specs. The full suite on a freshly restarted stack is 60/63, with the three failures accounted for: tree-reorder "nest" is the known macOS-only dnd-kit failure that passes in CI, ws-reconnect cannot reach the toxiproxy admin API on this machine, and comment-anchors:100 timed out waiting for the add-comment float — upstream of any anchor logic, while the two sibling tests that drive the identical helper and assert on the resolved highlight both passed in the same run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WP-8, the follow-up to the Tiptap 3 migration (#18). Removes the three exact
prosemirror-*overrides and replaces the Renovate rule that documented them.Why the pins can go
They existed to deduplicate the ProseMirror core that
@tiptap/pmandy-prosemirrorboth pulled in.y-prosemirroris gone —@tiptap/y-tiptapreplaced it in #18, and it declares
prosemirror-*as peer dependencies,so it resolves to the consumer's copy and structurally cannot introduce a
second one.
Why they had to go
@tiptap/pm@3.31.3declaresprosemirror-model ^1.25.11andprosemirror-view ^1.42.3. The overrides held the tree at 1.25.7 and1.41.8 — below both. pnpm
overridesbypass range checks silently, sothis installed without a warning.
@tiptap/pmwants^1.25.11^1.42.3^1.4.4prosemirror-view1.42.3 also carries an XSS fix in clipboard handling —attribute validators were not run on attributes arriving via slice context.
No advisory was ever filed for it (OSV returns nothing for 1.41.8), so no
scanner would have surfaced it. knot was not reachable through it: Tiptap
only sets
spec.validatewhen an extension declares one, and knot declaresnone. Being on the patched release closes the exposure the moment that stops
being true.
a5c7042introduced these pins blamingprosemirror-view1.42 for ahistory-restore failure, and
ccf5dbdretracted that. This PR deletes thelast in-tree record of the exchange, so for the record:
e2e/flows/history.spec.tsis the test that motivated the pin, and it passeson 1.42.3.
Why CI gains
pnpm dedupe --checkNot belt-and-braces. While preparing this the tree was genuinely split for one
run —
@tiptap/pmlinkedprosemirror-view@1.41.8while@tiptap/y-tiptaplinked
1.42.3— and tsc, eslint and all 153 unit tests passed anyway.The old override comment claimed tsc would catch duplication with a wall of
"not assignable" errors. It does not: TypeScript is structural and the two
Nodeclasses match.Nothing else in CI looks at resolution, and
lockFileMaintenancerunspnpm updateand automerges itself once green — so an automated lockfilerefresh could re-split the editor core unobserved. A split tree is silent by
construction: two
ySyncPluginKeyobjects (y-sync$andy-sync$1),getState()returnsundefined, and every comment anchor resolves to nullwith nothing thrown.
--checkfails only when duplication is avoidable,which is exactly the condition worth failing on.
Note for reviewers: plain
pnpm installafter removing the overrides leaves astale split tree;
pnpm dedupefixes the lockfile but does not relinknode_modules.pnpm install --frozen-lockfile(what CI does) produces thecorrect tree. If you pull this branch, reinstall from the lockfile.
Renovate
The
prosemirror-*rule is dead config now — Renovate does not raise PRs fortransitive npm deps outside
lockFileMaintenance. Replaced with a rulegrouping
@tiptap/y-tiptapinto thetiptapgroup: it is published fromueberdosis/y-tiptap, a different repo fromueberdosis/tiptap, so themonorepo preset does not group it and it would otherwise be bumped in its own
PR without the tiptap version it has to work against.
Verification
tsc --noEmit,eslint --max-warnings 0, 153/153 unit teststwo-users-converge, markdown round-trip, excalidraw, mermaid, upload-image)
tree-reorder"nest" isthe known macOS-only dnd-kit failure that passes in CI;
ws-reconnectcannot reach the toxiproxy admin API on this machine;
comment-anchors:100timed out waiting for the add-comment float — upstream of any anchor logic,
and the two sibling tests driving the identical helper and asserting on the
resolved highlight both passed in the same run. All three pass in isolation.
Unrelated, worth filing separately
The collab room leaks a Postgres backend in
idle in transactionholdingSELECT seq, doc_id, update_bytes, by_user_id, created_at FROM doc_updates(
knot-storage/src/updates_store.rs:107,UpdatesStore::since). Capturedmid-run: one such backend 2m37s old with four
UPDATE sessions SET last_seen_atblocked behind it for the identical duration. Enough of them ande2e/support/reset.tscan no longer take its table locks and the suite failsin ways that look like editor bugs.
since()uses no explicit transaction, sothe likely path is future cancellation —
Registry::acquire→Room::spawnawaits the hydrating
since()inside the WS request future, which axum dropswhen a client disconnects mid-upgrade, orphaning the sqlx connection
mid-protocol. Not touched here.
🤖 Generated with Claude Code