Repository navigation
Conversation
A versioned key -> record store for Node and browsers, ported from the Python core: staging, commits, sorted iteration, diff, three-way merge and reconciling a moved pointer, over memory, a Bee node (/bytes) or Freedom Browser's window.swarm. Plain modules with JSDoc types and no npm dependencies; keccak from js-sha3 0.9.3, vendored as swarmlite vendors it. js/tools/make_fixtures.py runs the Python code in src/ and records canonical encodings, Swarm addresses, the root after every commit of scripted and random stores (362 commits, both addressings) and three-way merges; the JS tests must reach the same bytes and roots. Live: OntoDAG's space pack (5,134 records, written by Python) listed from Swarm through Freedom's Ant node, every blob checked against its reference. Not ported yet: feed pointers, proofs, history, local-first. The package stays private until it has a name on npm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
js runs npm test (no install: no dependencies). js-fixtures reruns js/tools/make_fixtures.py --check against the Python code in src/, so a change to the wire format that leaves the JS fixtures stale turns the build red until they are regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test/freedom/freedom_check.cjs runs test/freedom/provider-check.html in Freedom built from a checkout (throwaway profile, prompts answered). On 8 November, with Swarm Desktop's Bee as Freedom's node, a store written through window.swarm got exactly the root computed offline under Swarm addressing and read back equal (9 chunks, 3.1 s); reads also ran through Freedom's own Ant node. Writing through Ant itself waits for a funded node: unfunded, it refuses with node-not-ready. SwarmProviderBytesStore now sends its first chunk alone. Freedom asks before each publish until "Always allow this site" is ticked, and chunks sent in parallel from the start each waited on a prompt: five for one commit, now one. A refused connection is asked again on the next write. test/provider.test.js covers the store offline with a fake provider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ported from the Python pointer and swarmfs's feeds: bee-js's update
format, signed with noble-secp256k1 2.3.0 (vendored from swarmlite, as
js-sha3 was). Signing is RFC 6979 with low S, as libsecp256k1, so the
fixtures pin whole signed updates: swarmfs's own FeedOps.update, run with
the clock fixed, and the JS must write the same bytes. The same defences
against light-node lookups: read-your-writes cache, monotonic index floor,
the tip probed over the update chunks, backoff that never goes back.
verifyFeedUpdate and verifyEquivocation check envelopes offline;
swarmStore(topic, {signer | owner, batch}) is Python's swarm_store.
Transports: Bee's API, and Freedom's window.swarm for reading
(swarm_readSingleOwnerChunk, re-checked here; writing waits for #647).
Live on 8 November: loopmarket's test maker book followed through its
feed (Bee, and Freedom's own Ant through window.swarm: the same root);
the OntoDAG page feed's 11 updates; a store published behind a new feed
from JS and read back from JS and from Python, both updates verified.
js-fixtures now installs the feeds extra for signing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
store.prove(key), provePrefix(prefix), extends(base, prefixes) and proveExtension(base, prefixes), with verifyProof, verifyPrefix and verifyExtension: a key's record or its absence, every record under a prefix, a later root keeping an earlier one's records. Same formats as Python; every envelope checked before it is handed out. ProofError moves to proofs.js, shared with the feed updates. The fixtures require JavaScript's envelopes to equal Python's for the same store (key, prefix and extension proofs under both addressings), the same verdicts from Python's envelopes, the same refused extensions (naming the same key), and every tampered proof refused. Live: proofs about OntoDAG's space pack made through Bee (abbey present, 4 nodes; abbeyz absent; the 11 records under 'ab'), checked offline in JS and accepted by Python's verifiers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
A JavaScript port of recordstore in
js/, for Node 22+ and browsers, including Freedom Browser'swindow.swarm. Same data model and wire format: a store written by either reads in the other, and equal content gives the same root in both.What's in it
getMany, diff, three-way merge with resolvers, andcommit({reconcile})for writers sharing a pointer (MemoryPointerwith compare-and-set).MemoryBytesStore(SHA-256 or Swarm addressing),BeeBytesStore(Bee's/bytes; every read and write checked against its reference),SwarmProviderBytesStore(Freedom'swindow.swarm:swarm_readDatato read, chunks published withswarm_publishChunkso references match Bee's).js/vendor/js-sha3/PROVENANCE.md).getresolves toundefinedfor an absent key, anddeletetofalse.How it is checked against Python
js/tools/make_fixtures.pyruns the Python code insrc/and records:The JavaScript tests replay the same operations and must reach the same bytes and roots. Locally: 37 tests pass on Node 22 and 24. Two new CI jobs run them (
js) and fail when the fixtures no longer match the Python code (js-fixtures).Live, 8 November: OntoDAG's
spacepack (5,134 records, written by Python) was listed in full from Swarm through the Ant node in Freedom Browser, every blob checked against its reference: 391 s cold.test/live.test.jsruns this whenRECORDSTORE_BEE_URLis set.Known differences and gaps
1.0read and written back becomes1(a different blob). Large integers stay exact asBigInt. Documented injs/README.md.window.swarminside Freedom.private.recordstoreis free on npm, butrecord-storeexists, and npm blocks names that differ only by punctuation;@petfold/recordstoreis free.🤖 Generated with Claude Code