Skip to content

fix(deps): update module github.com/go-crdt/crdt to v0.42.0 - #19

Merged
tannevaled merged 1 commit into
mainfrom
renovate/deps
Sep 3, 2026
Merged

fix(deps): update module github.com/go-crdt/crdt to v0.42.0#19
tannevaled merged 1 commit into
mainfrom
renovate/deps

Conversation

@tannevaled

@tannevaled tannevaled commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
github.com/go-crdt/crdt v0.39.0v0.42.0 age confidence

Release Notes

go-crdt/crdt (github.com/go-crdt/crdt)

v0.42.0: — stop reading formats nobody holds

Compare Source

⚠️ Breaking for a stored snapshot. One written by a build older than roughly v0.30 can no longer be opened. There are no production servers on this project, this module has never promised format stability, and since v0.40.0 a caller can ask what a build reads (Reads) rather than find out.

Text versions 1–6, list version 1 and map version 1 are no longer read. This build writes text 8 for a document that has not purged and 9 for one that has, and reads those two. Version 7 stays reserved and refused.

What actually went

718 lines net, and the line count is not the point. Removing the numbers made whole reading modes dead, and they went rather than being left always-true:

  • sameStream and readColumns — the entire pre-columnar reading mode
  • readCharacter / reader.character
  • steppedID's stepped parameter
  • readRun's version parameter, with its conditional clock addition and two conditional step encodings
  • column.plain and both its branches

Every one of those was a place a format change had to be thought about twice — and three tests were found this week passing while testing nothing, two of them confused by exactly this kind of version-conditional reading.

Bytes unchanged

Same document, same trace: version 8, 259 890 bytes, same sha256 as v0.41.0.

What deletion revealed

Nine rejections were reachable only through the version 1 fixture, and all of them guard live code: a site listed twice, two runs claiming one identity, runs in an impossible order, five duplicate-deletion refusals. Deleting a reader deletes the only route to checks that still matter — they were ported to the run builder rather than dropped with the fixture that reached them.

Five fuzz seeds stamped in removed versions were refused at the version byte and reached none of the loader. They are gone, and the four still-live seeds stay.

v0.41.0: — Doc.Purge

Compare Source

Doc.Purge() discards the characters of runs every character of which is
deleted. The run keeps its identity, its length, its origin and the operations
that deleted it; only the characters go. Nothing is re-pointed and nothing moves
— which is the whole difference between this and the collection withdrawn in
v0.35.0, where a survivor that named one of those characters could no longer find
it.

the automerge-paper trace, purged −24.7% (259 890 → 195 669 bytes)
a revised document, purged −33.1% (22 899 → 15 326)

It costs nothing to anyone who does not call it

Snapshot format version 9, written only by a document that has actually
purged
. Everything else writes version 8 and produces byte-identical
snapshots to v0.40.0 — same length, same sha256, verified by running the same
document through both builds rather than by reasoning about it. A Purge() that
finds nothing to take leaves the floor at zero and changes nothing.

Refusing a peer it can no longer serve

Doc.CanServe and Composite.CanServe report the new ErrPurged for a
version that needs characters a purge discarded.

Both, not one: Composite.Text hands out the *Doc, so anything holding a
composite can purge one of its texts — and a safety on the part with none on
the whole is one somebody reaches around without meaning to.

Writing that consumer first is what found that the predicate it was meant to use
answered the wrong question. "Nothing purged was still visible at v" is the
condition for reading the past, and it accepts the worst peer there is: a version
that never saw a purged run at all. Measured — it accepted the empty version
vector, which would have been sent 798 operations and read "" where the
document held eight hundred characters.

Sound without a stability condition

Checked rather than argued, and against the reference: Yjs replaces a deleted
item's content and keeps the item, needs no such condition, and this does the
same thing. Tested against Yjs 13.6.32 over 200 random histories, five peers,
out-of-order delivery, gc: true — all converge, including the case that broke
the withdrawn collection.

No reference implementation computes a safety condition for this. Loro, the only
one that removes records outright, declares the limitation instead.

v0.40.0

Compare Source

Reads, Writes and Formats — this build can now be asked what it understands.

func Reads(f Format) []byte  // the versions of a format this build can load
func Writes(f Format) byte   // the one it produces
func Formats() []Format      // text, list, map, composite

A snapshot travels — a joining participant loads one the server sends, a federated link adopts one from the server it follows — and neither side can negotiate: a reader knows the version byte or refuses the bytes. The only way to avoid sending something unreadable is to have been told what the other side reads, and until now there was nothing to tell with.

A set, not a range

Version 7 of a text is reserved for the purge and refused here, so this build reads 1–6 and 8. A peer told "up to 8" would send a 7 and be refused by the very thing that told it. The first draft of this returned a highest version and its test failed on its first run.

One list, two readers

The accepted versions are a single list, used by Load and by Reads. A second list was the obvious way to write it and the wrong one: a number that has drifted from the loader is worse than no number, because it is believed.

The test tries every version from 1 to 255 against every loader, in both directions: nothing claimed may be refused for its version, and nothing unclaimed may be accepted.

Who calls it

Nothing here. The caller is collab#106 — a peer says this at a join so the other side can send operations rather than a snapshot it cannot read, which replaces the upgrade-order note in v0.38.0's release with something the protocol enforces.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

@tannevaled tannevaled changed the title fix(deps): update module github.com/go-crdt/crdt to v0.40.0 fix(deps): update module github.com/go-crdt/crdt to v0.42.0 Sep 3, 2026
@tannevaled
tannevaled merged commit 2c4f3cf into main Sep 3, 2026
1 check passed
@tannevaled
tannevaled deleted the renovate/deps branch September 3, 2026 19:26
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.

1 participant