<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>SSSync</title>
    <link>https://sssync.joodaloop.com/</link>
    <description>Recent content on SSSync</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <managingEditor>judah@example.org (Judah)</managingEditor>
    <webMaster>judah@example.org (Judah)</webMaster>
    <atom:link href="https://sssync.joodaloop.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title></title>
      <link>https://sssync.joodaloop.com/steal/electric/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/steal/electric/</guid>
      <description>&lt;h1 id=&#34;learning-from-electric-typescript-client&#34;&gt;Learning from Electric (TypeScript client)&lt;/h1&gt;&#xA;&lt;p&gt;A study of &lt;a href=&#34;https://electric.ax/docs/sync/api/clients/typescript&#34;&gt;Electric&lt;/a&gt;&amp;rsquo;s TypeScript client (&lt;code&gt;@electric-sql/client&lt;/code&gt;), read from source (&lt;code&gt;electric-sql/electric@main&lt;/code&gt;, &lt;code&gt;packages/typescript-client&lt;/code&gt;). Same goal as &lt;a href=&#34;./LEARN.md&#34;&gt;LEARN.md&lt;/a&gt; (Replicache/Zero), &lt;a href=&#34;./TINYBASE.md&#34;&gt;TINYBASE.md&lt;/a&gt;, and &lt;a href=&#34;./POWERSYNC.md&#34;&gt;POWERSYNC.md&lt;/a&gt;: understand what a mature local-first sync system decided its users needed, to inform &lt;code&gt;sssync&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Electric is the &lt;strong&gt;smallest and most opinionated-by-omission&lt;/strong&gt; of the five systems studied. Its entire premise: &lt;strong&gt;sync a single Postgres query (a &amp;ldquo;Shape&amp;rdquo;) to the client over plain HTTP as a log of row changes.&lt;/strong&gt; That&amp;rsquo;s it. There is:&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://sssync.joodaloop.com/steal/pouch/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/steal/pouch/</guid>
      <description>&lt;h1 id=&#34;pouchdb--public-api-surface&#34;&gt;PouchDB — public API surface&lt;/h1&gt;&#xA;&lt;p&gt;A rundown of &lt;a href=&#34;https://pouchdb.com/api.html&#34;&gt;PouchDB&lt;/a&gt;&amp;rsquo;s public API, from the official API reference. Same goal as the other notes in this repo (&lt;a href=&#34;./ROCICORP.md&#34;&gt;ROCICORP.md&lt;/a&gt;, &lt;a href=&#34;./TINYBASE.md&#34;&gt;TINYBASE.md&lt;/a&gt;, &lt;a href=&#34;./POWERSYNC.md&#34;&gt;POWERSYNC.md&lt;/a&gt;, &lt;a href=&#34;./ELECTRIC.md&#34;&gt;ELECTRIC.md&lt;/a&gt;, &lt;a href=&#34;./RX.md&#34;&gt;RX.md&lt;/a&gt;): understand what a mature local-first database exposes to users, to inform &lt;code&gt;sssync&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;PouchDB is the JavaScript implementation of &lt;strong&gt;CouchDB&amp;rsquo;s data model and replication protocol&lt;/strong&gt;, designed to run in the browser (IndexedDB), Node (LevelDB), or against a remote CouchDB over HTTP. Its defining characteristics: &lt;strong&gt;every document is a JSON doc with an &lt;code&gt;_id&lt;/code&gt; and a revision &lt;code&gt;_rev&lt;/code&gt;&lt;/strong&gt;; writes are &lt;strong&gt;MVCC&lt;/strong&gt; (multi-version concurrency control — you must supply the current &lt;code&gt;_rev&lt;/code&gt; to update, and conflicts are first-class, not errors); and &lt;strong&gt;sync is the CouchDB replication protocol&lt;/strong&gt; — bidirectional, incremental, checkpoint-based, and able to run against any CouchDB-compatible server with no custom backend code. Every method &lt;strong&gt;returns a Promise and also accepts a Node-style callback&lt;/strong&gt;; the streaming methods (&lt;code&gt;changes&lt;/code&gt;, &lt;code&gt;replicate&lt;/code&gt;, &lt;code&gt;sync&lt;/code&gt;) return &lt;strong&gt;event emitters&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://sssync.joodaloop.com/steal/powersync/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/steal/powersync/</guid>
      <description>&lt;h1 id=&#34;learning-from-powersync-web-sdk&#34;&gt;Learning from PowerSync (Web SDK)&lt;/h1&gt;&#xA;&lt;p&gt;A study of &lt;a href=&#34;https://powersync-ja.github.io/powersync-js/web-sdk&#34;&gt;PowerSync&lt;/a&gt;&amp;rsquo;s public API, read from source (&lt;code&gt;powersync-ja/powersync-js@main&lt;/code&gt;). The Web SDK (&lt;code&gt;@powersync/web&lt;/code&gt;) is a thin platform shim over &lt;code&gt;@powersync/common&lt;/code&gt;, which holds essentially the whole public surface. Same goal as &lt;a href=&#34;./LEARN.md&#34;&gt;LEARN.md&lt;/a&gt; (Replicache/Zero) and &lt;a href=&#34;./TINYBASE.md&#34;&gt;TINYBASE.md&lt;/a&gt;: understand what a mature local-first sync library decided its users needed, to inform &lt;code&gt;sssync&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;PowerSync&amp;rsquo;s defining bet, and the thing that makes it different from all three prior systems: &lt;strong&gt;the local store is a real SQLite database, and the developer talks to it in SQL.&lt;/strong&gt; There is no KV API (Replicache), no relational query DSL (Zero/ZQL), no reactive-cell tree (TinyBase). You write &lt;code&gt;SELECT ... FROM todos WHERE ...&lt;/code&gt;, you get rows, and you &lt;code&gt;watch()&lt;/code&gt; the SQL to make it reactive. Sync is server-driven (a PowerSync Service streams &amp;ldquo;buckets&amp;rdquo; of rows down; local writes queue up and you upload them yourself). The mental model is closest to Zero&amp;rsquo;s server-authoritative sync, but the client API is &amp;ldquo;SQLite that happens to sync.&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://sssync.joodaloop.com/steal/rocicorp/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/steal/rocicorp/</guid>
      <description>&lt;h1 id=&#34;learning-from-replicache--zero&#34;&gt;Learning from Replicache &amp;amp; Zero&lt;/h1&gt;&#xA;&lt;p&gt;A study of the public APIs of &lt;a href=&#34;https://github.com/rocicorp/mono/tree/main/packages/replicache/src&#34;&gt;&lt;code&gt;@rocicorp/replicache&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/rocicorp/mono/tree/main/packages/zero&#34;&gt;&lt;code&gt;@rocicorp/zero&lt;/code&gt;&lt;/a&gt; (the rocicorp/mono monorepo), done to understand what a mature sync library decided its users needed. The goal is to inform &lt;code&gt;sssync&lt;/code&gt;&amp;rsquo;s own public surface.&lt;/p&gt;&#xA;&lt;p&gt;Replicache is the older, lower-level KV-sync engine (a sorted key/value cache with mutators + pull/push). Zero is the newer, higher-level system built on the same persistence/sync machinery but exposing a &lt;strong&gt;typed relational query language (ZQL)&lt;/strong&gt;, server-authoritative incremental view maintenance (IVM), and a schema/permissions system. Reading them side-by-side is essentially watching the same team&amp;rsquo;s opinion evolve from &amp;ldquo;sync a KV store&amp;rdquo; to &amp;ldquo;sync the results of relational queries.&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://sssync.joodaloop.com/steal/rx/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/steal/rx/</guid>
      <description>&lt;h1 id=&#34;learning-from-rxdb&#34;&gt;Learning from RxDB&lt;/h1&gt;&#xA;&lt;p&gt;A study of &lt;a href=&#34;https://rxdb.info/&#34;&gt;RxDB&lt;/a&gt;&amp;rsquo;s public API, read from source (&lt;code&gt;pubkey/rxdb@main&lt;/code&gt;, &lt;code&gt;src/&lt;/code&gt; + &lt;code&gt;src/types&lt;/code&gt;). Same goal as &lt;a href=&#34;./LEARN.md&#34;&gt;LEARN.md&lt;/a&gt; (Replicache/Zero), &lt;a href=&#34;./TINYBASE.md&#34;&gt;TINYBASE.md&lt;/a&gt;, &lt;a href=&#34;./POWERSYNC.md&#34;&gt;POWERSYNC.md&lt;/a&gt;, and &lt;a href=&#34;./ELECTRIC.md&#34;&gt;ELECTRIC.md&lt;/a&gt;: understand what a mature local-first database decided its users needed, to inform &lt;code&gt;sssync&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;RxDB (&amp;ldquo;Reactive Database&amp;rdquo;) is the &lt;strong&gt;oldest and most batteries-included&lt;/strong&gt; of the systems studied — a full client-side NoSQL document database whose defining traits are: &lt;strong&gt;everything is an RxJS &lt;code&gt;Observable&lt;/code&gt;&lt;/strong&gt; (queries, documents, even individual fields emit), a &lt;strong&gt;MongoDB-style query language (Mango)&lt;/strong&gt;, a &lt;strong&gt;pluggable storage engine&lt;/strong&gt; abstraction underneath, and a &lt;strong&gt;generic, transport-agnostic replication protocol&lt;/strong&gt; on top. Where Electric is &amp;ldquo;just a change-log&amp;rdquo; and TinyBase is &amp;ldquo;just a reactive store,&amp;rdquo; RxDB is the maximalist: schema + ORM + reactive queries + migrations + attachments + encryption + conflict handling + a dozen replication backends, all assembled from plugins.&lt;/p&gt;</description>
    </item>
    <item>
      <title></title>
      <link>https://sssync.joodaloop.com/steal/tinybase/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/steal/tinybase/</guid>
      <description>&lt;h1 id=&#34;learning-from-tinybase&#34;&gt;Learning from TinyBase&lt;/h1&gt;&#xA;&lt;p&gt;A study of &lt;a href=&#34;https://tinybase.org&#34;&gt;TinyBase&lt;/a&gt;&amp;rsquo;s public API (&lt;a href=&#34;https://tinybase.org/api/the-essentials/&#34;&gt;essentials guide&lt;/a&gt;), read from source (&lt;code&gt;tinyplex/tinybase@main&lt;/code&gt;, the published type definitions in &lt;code&gt;src/@types/&amp;lt;module&amp;gt;/index.d.ts&lt;/code&gt;). Same goal as &lt;a href=&#34;./LEARN.md&#34;&gt;LEARN.md&lt;/a&gt; (Replicache/Zero): understand what a mature local-first data library decided its users needed, to inform &lt;code&gt;sssync&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;TinyBase is a different animal from Replicache/Zero. It is a &lt;strong&gt;reactive in-memory data store&lt;/strong&gt; first, with sync/persistence/CRDT as &lt;em&gt;optional layers bolted on&lt;/em&gt;, not the core premise. Where Zero starts from &amp;ldquo;sync relational queries&amp;rdquo; and works inward, TinyBase starts from &amp;ldquo;a tiny reactive store&amp;rdquo; and works outward. It has &lt;strong&gt;no server, no mutators, no optimistic-rollback model&lt;/strong&gt; in the core — those are someone else&amp;rsquo;s concern. Its bet is: give people a fast, fully-reactive, schema-optional local store with a rich set of &lt;em&gt;derived&lt;/em&gt; data structures (queries, indexes, metrics, relationships, undo), and let sync/persistence plug in underneath via small interfaces.&lt;/p&gt;</description>
    </item>
    <item>
      <title>1.0 Roadmap</title>
      <link>https://sssync.joodaloop.com/v1-roadmap/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/v1-roadmap/</guid>
      <description>&lt;h2 id=&#34;schema&#34;&gt;Schema&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/dcffe4bb57ab88fe9d021634e394943c82f6b098&#34;&gt;Copy over code from Zero Schema so that we can drop that dependency and gain flexibility if needed in the future&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/952f4623ef2f045b8ee46d9500145bf4743a17ef&#34;&gt;Use minimal internal validators instead of Valibot&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;mutators&#34;&gt;Mutators&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/8230a567fbeb45c02e03815f82cc5f98ab6c4968&#34;&gt;Switch over to using mutators instead of the event/projector separation&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/blob/80360dfddba47bd1c9bb33cabeb7b15798ae4072/website/content/docs/events.md&#34;&gt;Decide on a mutator design&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/15d512c14b0d23aa6c9fd88b18e7811a5b95fd55&#34;&gt;Build type-safe mutator definitions, with a Standard Schema &lt;code&gt;data&lt;/code&gt; field&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Build cross-tab ordering system&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Connect to IDB for persistence&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Choose an incrementing Mutation ID format per (client|browser)&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Connect mutations rebasing to store&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;queries&#34;&gt;Queries&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/3e255be4fd00f77772a3ee91b83d3dd02c0c10e7&#34;&gt;Finalise design for query DSL&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Design system for subscriptions&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Make sure updates to queries are batched before revealing to the UI&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Add lazy accessor to queries to track just insert/update/delete (like experimental &lt;code&gt;watch()&lt;/code&gt; API)&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Connect query layer with the coverage tracker&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;batcher&#34;&gt;Batcher&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/14e178c136b6ddbfe431a6a00076394d405f57d4&#34;&gt;Connect batch loader with the store&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/a96a3bfef518a3c44f3be8f6470fa5ba5dfa4fbc&#34;&gt;Design batch loader that dedupes query satisfactions and validates responses&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/54d199d3d9bc435ca532ada96fa653bedccee3fe&#34;&gt;Connect the coverage tracker with the batch loader&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;bootstrap&#34;&gt;Bootstrap&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/74e8d6d3b1781efca79094acb81996f080b83b61&#34;&gt;Handle the &lt;code&gt;bootstraps&lt;/code&gt; Broadcast Channel updates&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/fb47175bf0f13d76d9d0c43247ca3a65e3d3f694&#34;&gt;Build bootstrap lifecycle manager&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/208bb9e729cbeec807de16a06ce0782234bf3fa5&#34;&gt;Connect bootstrap layer to store&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Persist and load BoostrapStatus(es) from IDB&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Expose BoostrapStatus as an Observable&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;store&#34;&gt;Store&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Design APIs to write to the store from:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Mutations&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Syncers&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/068f1bcd36abd5f8bac0887c67458e94988811c5&#34;&gt;Batch/bootstrap&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Handle the &lt;code&gt;store-updated&lt;/code&gt; Broadcast Channel coordinator&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;persistence-idb&#34;&gt;Persistence (IDB)&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Handle the &lt;code&gt;schema-changed&lt;/code&gt; Broadcast Channel coordinator&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Build an IndexedDB database management system&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Coordinate the startup sequence (check for database, create if needed)&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Design API for storing mutation queue&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/18c53c26654781be9035c87ffa6723c6049c5941&#34;&gt;Design API for persisting store data&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/7b2c6376a0b315d3bc7618d0be0fa7985e3bf89e&#34;&gt;Provide namespaced KV store&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;integrations&#34;&gt;Integrations&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Solid.js wrapper with Stores on the reactive layers&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; React wrapper with stable identity&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Figure out how to play well with SSR:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Surface query interface in a way that allows usage with a Loader function&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Make IDB storage purely pluggable&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Guard &lt;code&gt;BroadcastChannel&lt;/code&gt; messages to only run on client&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;performance&#34;&gt;Performance&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Make sure store APIs are fast&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Add perf tests for store =&amp;gt; query connection&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Ensure that rebasing is fast&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;qol&#34;&gt;QoL&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Add thorough docstrings to all files to drive agents and test creation&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Come up with a minimal set of key/id formats for everything&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Decide on a single format for passing along row changes&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/828689ae2f701543653da3e9f06bf7f013ab1f9a&#34;&gt;Design error types for library&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/1fadf96a23db72fde0ef75cebdbb0d2662b5b10c&#34;&gt;Switch to using tagged union Result type for typed error handling&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;a href=&#34;https://github.com/joodaloop/sssync/commit/d5cdd8df0184687eda048468189122052754fcfa&#34;&gt;Flatten all table row vaildation into one shape (across network + persistence)&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;br/&gt;&#xA;&lt;h2 id=&#34;future&#34;&gt;Future&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Play code golf on largest modules to get things down to &amp;lt;10kb total&lt;/li&gt;&#xA;&lt;li&gt;Add &lt;a href=&#34;https://rxdb.info/key-compression.html&#34;&gt;https://rxdb.info/key-compression.html&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Go through &lt;a href=&#34;https://github.com/rocicorp/replicache/releases&#34;&gt;https://github.com/rocicorp/replicache/releases&lt;/a&gt; and implement all useful features.&lt;/li&gt;&#xA;&lt;li&gt;Eviction&lt;/li&gt;&#xA;&lt;li&gt;Partial migrations&lt;/li&gt;&#xA;&lt;li&gt;Give materializers access to the database&lt;/li&gt;&#xA;&lt;li&gt;Figure out a syncgroups abstraction (with shared data)&lt;/li&gt;&#xA;&lt;li&gt;Add IVM for &lt;code&gt;where&lt;/code&gt; queries (&lt;code&gt;store.issues.where(q =&amp;gt; q.eq(&amp;quot;status&amp;quot;, &amp;quot;open&amp;quot;))&lt;/code&gt;) to the query language, with &lt;code&gt;sorted-btree&lt;/code&gt; for indexing.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;gte&lt;/li&gt;&#xA;&lt;li&gt;lte&lt;/li&gt;&#xA;&lt;li&gt;eq&lt;/li&gt;&#xA;&lt;li&gt;in&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;br/&gt;&#xA;&lt;h2 id=&#34;dead-ends&#34;&gt;Dead ends&lt;/h2&gt;&#xA;&lt;h3 id=&#34;events--projectors&#34;&gt;&lt;del&gt;Events &amp;amp; Projectors&lt;/del&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;del&gt;&lt;a href=&#34;https://github.com/joodaloop/sssync/commit/a7d7db728759c1e1fe64387cbd8a213ea9c0ed63&#34;&gt;Switch to using &lt;code&gt;better-result&lt;/code&gt; for typed error handling&lt;/a&gt;&lt;/del&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;del&gt;Decide on an event schema format&lt;/del&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;del&gt;Figure out a nice projector API that is easy to use across backend and frontend&lt;/del&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;del&gt;Build type-safe projectors that connect &lt;strong&gt;events&lt;/strong&gt; and &lt;strong&gt;schema&lt;/strong&gt; in a SSSync client&lt;/del&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>An Overview of the System</title>
      <link>https://sssync.joodaloop.com/overview/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/overview/</guid>
      <description>&lt;p&gt;It is opinionated when being so helps enforce robustness, and very flexible otherwise.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Rebasing the offline event queue each time a loader or puller runs&lt;/li&gt;&#xA;&lt;li&gt;Clearing confirmed events from the offline queue once the backend has confirmed them, rebase the rest&lt;/li&gt;&#xA;&lt;li&gt;Making sure that puller data is queued and rebased over in-flight loaders&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The core SSSync class looks like:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sss&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SSSync&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;/**&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * A unique identifier for the user.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * Omit this, or set to `null`, for logged-out clients.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * Each userID gets its own client-side storage so that the app can switch&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * between users without losing state.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;schema&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Tables&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;mutators&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Mutators&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;storage&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IDBStorage&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;/**&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * Distinguishes the storage used by this Zero instance from that of other&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * instances with the same userID. Useful in the case where the app wants to&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * have multiple Zero instances for the same user for different parts of the&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * app.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;storageKey?&lt;/span&gt;: &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;mutationURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/mutate&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;/**&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;    * Custom headers to include in mutation requests sent to your API server.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;    */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;mutateHeaders?&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Record&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;string&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;undefined&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;batchURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/batch&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;/**&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;     * Custom headers to include in query requests sent to your API server.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;  */&lt;/span&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;batchHeaders?&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Record&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;string&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;undefined&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;bootstrapURL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/bootstrap&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;handleErrors&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; (Error) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; {&lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;} &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;commit&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;eventName&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;eventArgs&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;metadata&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;loaders&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;loaderName&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;args&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Schemas are declared using Zero&amp;rsquo;s syntax:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Best Practices</title>
      <link>https://sssync.joodaloop.com/practices/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/practices/</guid>
      <description>&lt;h3 id=&#34;ensure-you-actually-want-a-local-first-application&#34;&gt;Ensure you actually want a local-first application&lt;/h3&gt;&#xA;&lt;p&gt;Bad fit for:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Random data access. Like Youtube, or Twitter.&lt;/li&gt;&#xA;&lt;li&gt;Apps that interact with physical resources like money, or&amp;hellip;a railwway crossing gate.&lt;/li&gt;&#xA;&lt;li&gt;Domains that need to preserve invariants&lt;/li&gt;&#xA;&lt;li&gt;Content websites. Try using a Service Worker cache instead.&lt;/li&gt;&#xA;&lt;li&gt;Low session duration, many visitors.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;fractional-indexes&#34;&gt;Fractional indexes&lt;/h3&gt;&#xA;&lt;h3 id=&#34;local-only-events&#34;&gt;Local-only events&lt;/h3&gt;&#xA;&lt;h3 id=&#34;data-modelling&#34;&gt;Data modelling&lt;/h3&gt;&#xA;&lt;p&gt;Use junction tables and foreign keys instead of nested JSON objects.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Design Notes (June 2026)</title>
      <link>https://sssync.joodaloop.com/design-june-2026/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/design-june-2026/</guid>
      <description>&lt;p&gt;How i&amp;rsquo;m thinking about things rn&lt;/p&gt;&#xA;&lt;h2 id=&#34;event-lifecycle&#34;&gt;Event lifecycle&lt;/h2&gt;&#xA;&lt;p&gt;Transactions progress through the following states during their lifecycle:&lt;/p&gt;&#xA;&lt;p&gt;pending: Initial state when a transaction is created and optimistic mutations can be applied&lt;/p&gt;&#xA;&lt;p&gt;persisting: Transaction is being persisted to the backend&lt;/p&gt;&#xA;&lt;p&gt;completed: Transaction has been successfully persisted and any backend changes have been synced back&lt;/p&gt;&#xA;&lt;p&gt;failed: An error was thrown while persisting or syncing back the transaction&lt;/p&gt;&#xA;&lt;h2 id=&#34;event-compression&#34;&gt;Event compression&lt;/h2&gt;&#xA;&lt;p&gt;Existing → New&#x9;Result&#x9;Description&#xA;insert + update&#x9;insert&#x9;Keeps insert type, merges changes, empty original&#xA;insert + delete&#x9;removed&#x9;Mutations cancel each other out&#xA;update + delete&#x9;delete&#x9;Delete dominates&#xA;update + update&#x9;update&#x9;Union changes, keep first original&lt;/p&gt;</description>
    </item>
    <item>
      <title>Design Notes (May 2026)</title>
      <link>https://sssync.joodaloop.com/design-may-2026/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/design-may-2026/</guid>
      <description>&lt;h2 id=&#34;i-need-to-reduce-my-operators-to-non-rescan-ones&#34;&gt;I need to reduce my operators to non-rescan ones&lt;/h2&gt;&#xA;&lt;h2 id=&#34;reducing-memory-usage-in-the-aggregate-will-include&#34;&gt;Reducing memory usage in the aggregate will include&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Re-running queries against disk as much as possible to have the minimum in-use set.&lt;/li&gt;&#xA;&lt;li&gt;BUT:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If mutations can read local state before rebasing, then having everything in memory makes replaying mutations cheap.&lt;/li&gt;&#xA;&lt;li&gt;You can sometimes miss next-frame rendering&lt;/li&gt;&#xA;&lt;li&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;possible-solution-use-zeros-server-tracking-method&#34;&gt;Possible solution: use Zero&amp;rsquo;s server tracking method&lt;/h3&gt;&#xA;&lt;p&gt;They track when data is a prefix, complete, etc. So my Zero query client can just pretend like going to disk is like going to the server.&#xA;&lt;strong&gt;This will need testing&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Mutators</title>
      <link>https://sssync.joodaloop.com/mutators/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/mutators/</guid>
      <description>&lt;p&gt;Writing data is done through mutators, these are named and versioned descriptions of user intent.&lt;/p&gt;&#xA;&lt;p&gt;THese mutators are eventually sent to the backend in the form:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;v1_PostCreated&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Mutators&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;description&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;An explanation of the event system at the heart of SSSync&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;evt_01J...&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;2026-06-22T10:15:30Z&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#e6db74&#34;&gt;```&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;- `&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;experimentalPendingMutations&lt;/span&gt;()&lt;span style=&#34;color:#e6db74&#34;&gt;` — inspect not-yet-confirmed local mutations.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;- `&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mutationID&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`, `&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;reason&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;` (`&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;initial&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rebase&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;authoritative&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;`)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>Querying data</title>
      <link>https://sssync.joodaloop.com/queries/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/queries/</guid>
      <description>&lt;p&gt;&lt;code&gt;subscribe(body, {onData, onError, isEqual})&lt;/code&gt;&#xA;onChange&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;initialValuesInFirstDiff&lt;code&gt;— if true, the first callback synthesizes an&lt;/code&gt;add` diff for &lt;em&gt;all existing matching values&lt;/em&gt;, so a watcher can build initial state and then stay live from one code path.&lt;/li&gt;&#xA;&lt;li&gt;DeepReadonly&lt;T&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Accessing all items in a collection:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-tsx&#34; data-lang=&#34;tsx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// React: returns a tuple&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IssueList() {&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; [&lt;span style=&#34;color:#a6e22e&#34;&gt;issues&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;pending&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SSS&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;useAll&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;issues&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// issues: Issue[]        — empty [] until ready (or undefined; see note)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// pending: boolean       — true on initial load, false once authoritative&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;pending&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;Spinner&lt;/span&gt; /&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      {&lt;span style=&#34;color:#a6e22e&#34;&gt;issues&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;map&lt;/span&gt;((&lt;span style=&#34;color:#a6e22e&#34;&gt;issue&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;issue&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;}&amp;gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;issue&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;}&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ))}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Solid: returns an async memo accessor&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;IssueList() {&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;issues&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SSS&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;useAll&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;issues&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// issues: () =&amp;gt; Issue[]   — async memo accessor; reading it suspends until ready&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;Loading&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fallback&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;Spinner&lt;/span&gt; /&amp;gt;}&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;For&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;each&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;issues&lt;/span&gt;()}&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        {(&lt;span style=&#34;color:#a6e22e&#34;&gt;issue&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;issue&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;title&lt;/span&gt;}&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;div&lt;/span&gt;&amp;gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;For&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;Loading&lt;/span&gt;&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Accessing a single item (and relations of an item):&lt;/p&gt;</description>
    </item>
    <item>
      <title>Stats</title>
      <link>https://sssync.joodaloop.com/stats/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/stats/</guid>
      <description>&lt;h2 id=&#34;june-29-2026&#34;&gt;June 29, 2026&lt;/h2&gt;&#xA;&lt;p&gt;Bundle size:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Core library: 12.5 KB raw / 3.5 KB gzip&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Syncers</title>
      <link>https://sssync.joodaloop.com/syncers/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/syncers/</guid>
      <description>&lt;p&gt;Syncers are modules that keep the client database up to date. They get:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Direct, read-only access to the client database&lt;/li&gt;&#xA;&lt;li&gt;Mediated write access in the form of CREATE, UPDATE, and DELETE operations passed to the SSSync client, along with a SyncCursor.&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Tables &amp; persistence</title>
      <link>https://sssync.joodaloop.com/storage/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/storage/</guid>
      <description>&lt;p&gt;Schema is declared using &lt;a href=&#34;https://zero.rocicorp.dev/docs/schema&#34;&gt;Zero schema&lt;/a&gt;, which produces validators, etc.&lt;/p&gt;&#xA;&lt;p&gt;Data is stored in IndexedDB tables, with the schema hash used as the database name.&#xA;A &amp;ldquo;databases&amp;rdquo; table will keep track of upgrade version, schema hashing, etc.&lt;/p&gt;&#xA;&lt;p&gt;Will need functions for bulk storing rows, reading all data out of the database into Map(), and validating all the time.&lt;/p&gt;&#xA;&lt;p&gt;SSSync can be configured with either &amp;ldquo;idb&amp;rdquo; or &amp;ldquo;memory&amp;rdquo; adapters. Tree-shakeable.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;linear_296285d9d399ac9fa0a6ffa3912f109b&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;createdAt&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1782578364787&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;userId&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a4fcb064-a41e-4082-9b47-9b10b2e66f29&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;schemaHash&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;bb68955e032c43a09a9e83c4f43da32a&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;schemaVersion&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;version&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;63&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>The SSSync Server Protocol</title>
      <link>https://sssync.joodaloop.com/server/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>judah@example.org (Judah)</author>
      <guid>https://sssync.joodaloop.com/server/</guid>
      <description>&lt;p&gt;You will need to provide two endpoints.&lt;/p&gt;&#xA;&lt;h3 id=&#34;batch-endpoint&#34;&gt;Batch endpoint&lt;/h3&gt;&#xA;&lt;p&gt;The server receives &lt;code&gt;{model: &amp;quot;issue&amp;quot;, id: 1, relation?: &amp;quot;comments&amp;quot;}&lt;/code&gt; and has to be able to satisfy that request, for all relations that the client schema has. Possible return values are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;200 -&amp;gt; Array of relations object (will count as satisfaction)&lt;/li&gt;&#xA;&lt;li&gt;400 -&amp;gt; Authorization error (will not be retried)&lt;/li&gt;&#xA;&lt;li&gt;500 -&amp;gt; Server error (will be retried)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;bootstrap-endpoint&#34;&gt;Bootstrap endpoint&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;/bootstrap?models=issue,project&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;These 3 things can be composed to achieve:&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
