Sync and storage
Sync has three parts: the @vaultkeepr/sync package merges edits between devices, the @vaultkeepr/ipfs package stores and fetches ciphertext, and the VaultKeeperCidRegistry contract on Base L2 records which ciphertext is current for an address.
CRDT synchronization
Section titled “CRDT synchronization”@vaultkeepr/sync builds on Automerge CRDTs. Each device edits its own copy of the vault document, and merging is conflict-free: two devices that both add or edit entries converge to the same result regardless of merge order. Deletions propagate through tombstones, so an entry deleted on one device disappears on the others; purgeTombstones and countTombstones manage the tombstone log. Vaults in the older non-CRDT format can be migrated with migrateLegacyPayload.
The CRDT binary import surface is fuzzed in CI (fuzz/harness/sync.fuzz.js). Malformed Automerge input must fail with a clean error, never a crash.
IPFS storage
Section titled “IPFS storage”The vault blob is encrypted on the client before upload, so IPFS stores and addresses ciphertext only. @vaultkeepr/ipfs validates and normalizes CIDs and fetches from multiple gateways with failover:
import { fetchFromIpfs, isIpfsCid, setIpfsGateways } from "@vaultkeepr/ipfs";
setIpfsGateways(["https://ipfs.io", "https://cloudflare-ipfs.com", "https://gateway.pinata.cloud"]);if (isIpfsCid(location)) { const blob = await fetchFromIpfs(location);}You can set your own gateway priority. Gateways can hold the ciphertext, but they cannot read it.
Who sees what
Section titled “Who sees what”Gateways and network observers can see that a blob exists, when it changes, and how big it is, and they can fetch it if they learn the CID. They cannot read passwords or notes without your keys. The blob is public in the sense of “reachable if you have the CID”; it is not public in the sense of plaintext exposure.
A separate mapping from wallet address to latest CID exists for convenience, in the registry contract and in hosted APIs. It does not reveal vault contents, but it is public metadata; see the threat model for what that implies.
Publishing updates
Section titled “Publishing updates”IPFS sync expects a linked wallet and signed publishes. The signature proves control of the address; @vaultkeepr/smart-account writes the vault pointer to the registry through the user’s smart account. Some clients support a local-only path before a wallet is linked, but cross-device sync needs the signed on-chain pointer.