Releases: interop-alliance/was-sync
Releases · interop-alliance/was-sync
Release list
v0.2.6
v0.2.5
Fixed
- Fix pnpm workspace, bump latest was-teaching-server devDep.
v0.2.4
Changed
- The undecryptable-side conflict warnings carry a
reason(unknown-epoch,
key-unwrap, orother), classified through@interop/was-client/sync's
isUnknownEpochErrorandisKeyUnwrapError, so a spent or unwired descriptor
refresh is told apart from a key this reader was never given. - Documented where the unknown-epoch refresh rule sits relative to the driver:
it runs inside the injecteddecryptclosure, which on an encrypted
collection should be@interop/was-client/edv's
createRefreshingEdvDocCipher. The driver holds no cipher and runs no refresh
of its own.
v0.2.3
Changed
- The controller assigns
@interop/was-client's sync port directly, and
WireDocis aliased from the client like the other wire types. Theunknown
cast and the runtimeputMetaprobe are gone, since@interop/was-client
0.54.0 types the port as what it implements, so a divergence in any port
member is now a compile error at the seam rather than anerror$event inside
a push or pull cycle (WS-10).
Fixed
- A delete with no assumed primary (a row created and deleted locally before the
replica's first push) is skipped instead of sent as a header-lessDELETE.
Ids are content-addressed, so that unconditional delete tombstoned another
replica's live copy of the same id. The row is reported accepted with no ack;
the live copy stays on the server and comes down on its next feed change
(WS-3). - The
/metawrite's delete-race recovery now fires on the default port. A
metadata-only edit against a resource another replica deleted used to reject
the batch there (the recovery matched only themapAuthErrorsport's masked
404), so RxDB retried the same write forever. One classifier now takes the
default port's not-found signal and the auth port'sstatus: 404to the same
corroborating feed re-read, and the row resolves as a tombstone conflict
entry. Needs@interop/was-client0.54.0, whose default-portputMetaraises
the not-found signal (WS-4).
v0.2.2
Changed
- Update to latest was-client.
v0.2.1
Fixed
- Fix the was-client dependency from link to npm.
Tests
- The live-server integration suite now covers resurrecting a row that carries
custom: the content create and the/metacreate-if-absent land in one push
cycle with a single conflict resolution, and a/metaIf-Matchcarrying the
pre-delete metadataETagis refused with 412 after the re-create.
v0.2.0
Changed
- Breaking:
putContent/deleteContent/putMetaon the sync port now
resolve aWriteAck({ version, etag? }) instead of a bare revision number,
matching was-client's opaqueETagcontract.MasterState/WireDoc/
SyncedDocgainetag/metaEtag, and a conditional write'sifMatchis
now the validator echoed back verbatim -- it can no longer be rebuilt from a
version number. The replica schema's shape changed to carry the new fields, so
an existing replica is forgotten and re-pulled at the next login (schema
versionstays0).
Fixed
- Resurrecting a resource another replica deleted converges in one cycle on the
plain was-client port (WS-2). A412whose re-read resolvesnullnow builds
a tombstone conflict entry withversion: 0and noetaginstead of a
version copied from local state, and an assumed primary that is a tombstone
routes the next content write toIf-None-Match: *(the one precondition a
server accepts against a tombstone) and a delete to an unconditionalDELETE.
Before the opaque-ETag change the re-push sentIf-Matchwith the fabricated
version and looped hot; after it, an unconditionalPUTthat could overwrite
a concurrent re-create.
v0.1.2
Added
- The driver's swallow points now log: the ack write-back failure at
warn, and
the benign-412 delete re-issue and the conflict hand-back atdebug.
Changed
- Breaking:
FakeWasServeris removed from@interop/was-sync/testing. The
integration suite now runs against a live in-processwas-teaching-server
through the realcreateWasSyncPortfrom@interop/was-client, so the
server's conditional-write, tombstone, andchanges-feed behavior is
exercised rather than modeled (WS-11). The stub port and the memory schedule
and online source remain on the subpath. - Breaking:
SyncLogPortand the per-calllogoptions on
createSyncController,makeConflictHandler,lwwResolver, and
makeLwwConflictHandlerare removed. The package adopts the ecosystem logging
library port instead:setLoggerand theLoggertype on the root entry. An
app wires one logger once at bootstrap, e.g.
setLogger(createLogger('sync')); the console fallback (prefixed
[was-sync]) applies otherwise (WS-12).
Fixed
- A delete's
404no longer wedges the push batch on the default was-client
port. The push handler reads the not-found signal fromdeleteContent(by
err.name) as the already-gone outcome, matching what amapAuthErrors: true
port already resolves itself, so the batch completes and its other rows land
(WS-1). A spec-conformant server answers204for an authorized delete of an
absent resource; the404on that path is a masked authorization refusal,
which still surfaces on the next feed pull. - The packaging suite (formerly
test:dist) is nowtest:packagingand lives
intest/packaging/. The oldtest/dist/directory matched the unanchored
distline in.gitignore, so the suite was never committed and CI failed
with "No test files found". The ignore entry is now anchored to/dist.
v0.1.1
Added
- Initial release. The WAS replication driver for RxDB, merged from the two
copies that had drifted apart in@interop/was-react(src/sync/) and in the
Freewallet browser wallet (src/lib/sync/). Neither consumer may depend on
the other, so a shared package is the one home the driver can have. The
placement, its rejected alternatives, and its revisit criteria are recorded in
decisions/0001-rxdb-replication-driver-package.md. - Three entries.
@interop/was-synccarries the wire and replica types, the
synced-document schema, the conflict-handler seam with its last-write-wins
default, and the writer-id mint; it is free ofrxdbin its module graph and
in its emitted declarations, so an app that never builds a replica resolves it
withrxdbabsent.@interop/was-sync/rxdbcarries the pull and push
handlers, thereplicateRxCollectionwiring, the feed-backed conflict
re-read, and the controller core.@interop/was-sync/testingcarries the
fixtures.@interop/was-clientandrxdbare peer dependencies;rxdbis
marked optional. - The pull side: the
changes-feed handler and the wire-to-replica mapping,
with the empty-page rule keyed on a nullish response checkpoint so the feed
never restarts from its origin. - The push side: content-then-metadata write routing (a metadata clear writes
the cleared state rather than being skipped), the 412 conflict assembler, the
benign-412 delete retry that keeps a stale revision from leaving a deleted
resource live on the server, the per-batch primary-read memo, the/meta404
corroboration, and the acked-revision write-back. - The conflict-handler seam.
makeConflictHandlertakes the decision as an
injected resolver receiving the whole RxDB conflict input, so a wallet can
delegate to its own comparator while an app framework uses the packaged
lwwResolver(which scores an undecryptable side apart from an absent one).
makeLwwConflictHandleris the two together. - The controller core: one serialized FIFO lifecycle over a session's
collections, a terminalstop(), a failed bring-up that unwinds and rethrows
without latching, the skip-and-flag for a collection no delegated capability
covers, the auth escalation over RxDB's wrapped error graph, the remote-change
subscription off the collection stream, and injected timer and reachability
ports. - The writer-id mint, over a required key prefix and an injected storage port. A
storage that cannot answer mints a fresh id per call and remembers nothing. - An injected
{ warn, error }log port on the controller core, the
conflict-handler factory, and the last-write-wins resolver, defaulting to a
no-op, so diagnostics ride each consumer's own logging seam. The factory logs
one thing of its own: a resolver that throws, which RxDB treats as a fatal
replication error, is reported with the row it happened on before it
propagates. The port's metadata argument isRecord<string, unknown>, which a
namespaced logger satisfies directly.
Changed
- The behavior set is the union of the two source copies, with each side's
deltas ported into the merge base before the move: the benign-412 delete
retry, JCS-canonical body equality, the server-managedcreatedBycarried
across live documents and tombstones, anderr.nameclassification in place
ofinstanceof(@interop/was-client's
decisions/0001-cross-package-errors-match-by-name.md). - The synced-document schema is the union of the two copies (
createdBy, the
requiredlist, and theupdatedAtindex), shipped atversion: 0with no
migration strategy. RxDB refuses to open a replica whose stored schema hash
differs at the same version, so every remembered browser in both consuming
apps needs one forget-and-log-in-again after the upgrade. Transient sessions
are unaffected. - The server-side state a 412 re-read resolves is named "primary" throughout
(PrimaryState,PrimaryReadCache,withFeedPrimaryRead,
feedPrimaryPort.ts), renamed from the merge base's "master". RxDB's own
field names on a push row (assumedMasterState,realMasterState) are RxDB's
API and are unchanged.