@vrtmrz/livesync-commonlib 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/API/processSetting.d.ts +1 -1
- package/dist/API/processSetting.js +10 -6
- package/dist/common/ConnectionString.js +15 -8
- package/dist/common/models/setting.const.qr.js +5 -0
- package/dist/common/models/setting.lifecycle.js +5 -3
- package/dist/common/models/setting.p2p.d.ts +10 -0
- package/dist/common/models/setting.p2p.js +13 -0
- package/dist/common/models/setting.type.d.ts +10 -0
- package/dist/common/models/tweak.compatibility.d.ts +34 -0
- package/dist/common/models/tweak.compatibility.js +110 -0
- package/dist/common/models/tweak.definition.d.ts +110 -19
- package/dist/common/models/tweak.definition.js +62 -29
- package/dist/common/settingConstants.d.ts +5 -0
- package/dist/common/types.d.ts +6 -3
- package/dist/common/types.js +6 -0
- package/dist/common/utils.js +4 -1
- package/dist/p2p/P2PService.d.ts +7 -1
- package/dist/p2p/P2PService.js +13 -7
- package/dist/p2p/index.d.ts +3 -1
- package/dist/p2p/index.js +6 -0
- package/dist/pouchdb/LiveSyncDBFunctions.d.ts +3 -3
- package/dist/pouchdb/LiveSyncDBFunctions.js +9 -15
- package/dist/replication/CentralCompatibility.d.ts +4 -2
- package/dist/replication/CentralCompatibility.js +5 -3
- package/dist/replication/couchdb/LiveSyncReplicator.js +10 -2
- package/dist/replication/journal/LiveSyncJournalReplicator.d.ts +2 -2
- package/dist/replication/journal/LiveSyncJournalReplicator.js +18 -4
- package/dist/replication/trystero/P2PRoomSessionOwner.d.ts +22 -1
- package/dist/replication/trystero/P2PRoomSessionOwner.js +193 -13
- package/dist/replication/trystero/TrysteroReplicator.js +12 -7
- package/dist/replication/trystero/TrysteroReplicatorP2PServer.d.ts +1 -0
- package/dist/replication/trystero/TrysteroReplicatorP2PServer.js +10 -3
- package/dist/replication/trystero/p2pReplicatorConfigurationIdentity.js +6 -3
- package/dist/replication/trystero/useP2PReplicatorFeature.d.ts +6 -1
- package/dist/replication/trystero/useP2PReplicatorFeature.js +7 -4
- package/dist/rpc/transports/trysteroUtils.d.ts +2 -2
- package/dist/rpc/transports/trysteroUtils.js +32 -2
- package/dist/serviceFeatures/remoteConfig.js +3 -0
- package/dist/services/base/IService.d.ts +3 -3
- package/dist/services/base/ReplicationService.d.ts +2 -2
- package/dist/services/base/ReplicationService.js +14 -11
- package/dist/services/base/SettingService.d.ts +1 -0
- package/dist/services/base/SettingService.js +37 -9
- package/dist/services/base/TweakValueService.d.ts +5 -3
- package/dist/services/implements/injectable/InjectableTweakValueService.d.ts +5 -5
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +2 -0
- package/dist/worker/bgWorker.js +1 -1
- package/docs/development.md +3 -3
- package/docs/p2p-transport-lifecycle.md +86 -4
- package/docs/proven-in-use.md +32 -0
- package/docs/settings-lifecycle.md +20 -1
- package/package.json +1 -1
package/docs/development.md
CHANGED
|
@@ -134,15 +134,15 @@ Keep [the maintained-host evidence](proven-in-use.md) aligned with the downstrea
|
|
|
134
134
|
|
|
135
135
|
## Integration tests
|
|
136
136
|
|
|
137
|
-
The integration suite owns Commonlib's direct CouchDB and S3-compatible storage checks. Run it with managed, disposable CouchDB and
|
|
137
|
+
The integration suite owns Commonlib's direct CouchDB and S3-compatible storage checks. Run it with managed, disposable CouchDB and RustFS containers:
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
140
|
npm run test:integration:managed
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
This command requires Docker Compose, creates only test credentials and data, and removes the containers and their volumes after the run. It is the same entry point used by package CI.
|
|
143
|
+
This command requires Docker Compose, creates only test credentials and data, and removes the containers and their volumes after the run. It is the same entry point used by package CI. The RustFS server and client images are pinned by digest; the Compose services retain the names `minio` and `minio-init`.
|
|
144
144
|
|
|
145
|
-
To test services that are already running, use `npm run test:integration`. The runner accepts `hostname`, `username`, and `password` for CouchDB, and `minioEndpoint`, `accessKey`, `secretKey`, and `bucketName` for S3-compatible storage. Without overrides, it uses the endpoints and test credentials from the managed Compose environment. The selected
|
|
145
|
+
To test services that are already running, use `npm run test:integration`. The runner accepts `hostname`, `username`, and `password` for CouchDB, and `minioEndpoint`, `accessKey`, `secretKey`, and `bucketName` for S3-compatible storage. Without overrides, it uses the endpoints and test credentials from the managed Compose environment. The selected S3-compatible bucket must already exist when services are not managed by the runner.
|
|
146
146
|
|
|
147
147
|
## Messages and translation
|
|
148
148
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
date: 2026-
|
|
3
|
-
commonlib-version: "0.1.
|
|
4
|
-
self-hosted-livesync-version: "1.0.
|
|
2
|
+
date: 2026-09-16
|
|
3
|
+
commonlib-version: "0.1.25-dev.turn-credentials.6"
|
|
4
|
+
self-hosted-livesync-version: "1.0.28"
|
|
5
5
|
status: unreleased
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -173,6 +173,87 @@ Do not close the raw values returned by `room.getPeers()`. Both closing them bef
|
|
|
173
173
|
|
|
174
174
|
Commonlib consequently does not expose a forced physical-disconnection command. Such an operation requires a future Trystero API which removes and destroys peers through its shared-peer manager, followed by proof that immediate reconnection remains possible.
|
|
175
175
|
|
|
176
|
+
## Optional host preparation
|
|
177
|
+
|
|
178
|
+
The `/p2p` entry exposes the optional `prepareP2PSettings(settings, signal)`
|
|
179
|
+
hook through `P2PReplicatorFeatureOptions` and `P2PServiceOptions`. The hook
|
|
180
|
+
receives the requested settings snapshot before a new room is created. It may
|
|
181
|
+
return `P2P_iceServers` and `P2P_iceServersExpiresAt`; the latter is an absolute
|
|
182
|
+
Unix time in milliseconds. Commonlib copies only those two runtime values onto
|
|
183
|
+
its own connection snapshot, so changes to room identity or other static
|
|
184
|
+
settings in the returned object cannot rewrite the requested binding.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
useP2PReplicatorFeature(core, openReplicationUiFactory, openRebuildUiFactory, {
|
|
188
|
+
prepareP2PSettings: async (settings, signal) => ({
|
|
189
|
+
...settings,
|
|
190
|
+
...(await prepareHostIceSettings(settings, signal)),
|
|
191
|
+
}),
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The hook is called for every new room when supplied, including manual profiles;
|
|
196
|
+
a manual host branch can return the settings unchanged. A consumer which omits
|
|
197
|
+
the hook retains existing manual TURN behaviour. A non-empty
|
|
198
|
+
`P2P_managedType` explicitly requests host preparation and fails safely when
|
|
199
|
+
the hook is absent or does not return usable TURN settings. Provider choice,
|
|
200
|
+
HTTP requests, response validation, timeouts within the provider call, and
|
|
201
|
+
credential-safe error detail belong to the host. Commonlib checks only that a
|
|
202
|
+
managed result has a TURN route and a finite expiry beyond the 30-second room
|
|
203
|
+
establishment margin.
|
|
204
|
+
|
|
205
|
+
A host can also return a non-empty ICE override without selecting a managed
|
|
206
|
+
provider. This supports ordinary STUN-only or TURN settings, and does not
|
|
207
|
+
require an expiry. When the host supplies an expiry, Commonlib applies the same
|
|
208
|
+
30-second establishment margin. A runtime override used with relay-only routing
|
|
209
|
+
must contain a TURN route; Commonlib rejects it rather than silently changing
|
|
210
|
+
the route policy. The host remains responsible for validating the individual
|
|
211
|
+
ICE server values.
|
|
212
|
+
|
|
213
|
+
`P2PRoomSessionOwner` retains prepared settings only in the active room's
|
|
214
|
+
immutable connection snapshot. Matching requested settings and usable runtime
|
|
215
|
+
credentials retain that room. An expiry inside the margin causes the next
|
|
216
|
+
reconciliation to retire the room, prepare another snapshot, and open its
|
|
217
|
+
replacement. Explicit reconnect always prepares again. Disconnect, settings
|
|
218
|
+
changes, and suspension abort or invalidate pending preparation; a late result
|
|
219
|
+
cannot publish an obsolete room. Preparation and room opening both have bounded
|
|
220
|
+
owner waits.
|
|
221
|
+
|
|
222
|
+
There is no periodic renewal, per-peer preparation, provider retry engine, or
|
|
223
|
+
update of a live `RTCPeerConnection`. Internal Trystero reconnection within an
|
|
224
|
+
existing room does not recheck expiry. A host can use the existing
|
|
225
|
+
disconnect/connect flow when a long-lived room needs fresh credentials.
|
|
226
|
+
Trystero retains ownership of physical peers and its offer pool.
|
|
227
|
+
|
|
228
|
+
Room retirement may cancel a transfer. The next replication attempt uses the
|
|
229
|
+
existing database checkpoint and revision comparison, retaining saved Metadata
|
|
230
|
+
and Chunks. This is document-level continuation; a partial network message may
|
|
231
|
+
be resent. An unfinished automatic baseline remains eligible under the existing
|
|
232
|
+
peer policy, while an interrupted manual operation requires another request.
|
|
233
|
+
|
|
234
|
+
Managed profiles use the ordinary `sls+p2p://` URI query fields
|
|
235
|
+
`managedType`, `managedId`, and `token`. Commonlib preserves the corresponding
|
|
236
|
+
`P2P_managedType`, `P2P_managedId`, and `P2P_managedToken` scalar projections
|
|
237
|
+
when it parses, serialises, or activates a profile. Provider names and the
|
|
238
|
+
meaning of identifiers and tokens remain host-defined.
|
|
239
|
+
|
|
240
|
+
The token is persisted only inside the selected P2P profile URI, using the
|
|
241
|
+
existing whole-profile encryption. General settings saves omit the three
|
|
242
|
+
duplicate top-level projections and never synthesise a profile from flat
|
|
243
|
+
fields. Explicit profile operations own URI updates. Flat-settings migration
|
|
244
|
+
creates and selects `legacy-p2p` once, including when CouchDB remains the main
|
|
245
|
+
remote. An encryption failure refuses to replace a managed profile with
|
|
246
|
+
plaintext data.
|
|
247
|
+
|
|
248
|
+
Encrypted Setup sharing and plain QR sharing already include
|
|
249
|
+
`remoteConfigurations`, so they carry managed settings through the profile
|
|
250
|
+
without new compact fields. Storage, Setup, QR, configuration exchange, and
|
|
251
|
+
external-import boundaries omit `P2P_iceServers` and
|
|
252
|
+
`P2P_iceServersExpiresAt`. Setup, QR, and configuration exchange also omit the
|
|
253
|
+
duplicate top-level provider projections. Runtime credentials therefore do not
|
|
254
|
+
become a later connection override. Hosts must redact tokens, issued
|
|
255
|
+
credentials, and provider responses from logs and reports.
|
|
256
|
+
|
|
176
257
|
## Verification
|
|
177
258
|
|
|
178
259
|
Maintain all five boundaries when this lifecycle changes:
|
|
@@ -182,7 +263,8 @@ Maintain all five boundaries when this lifecycle changes:
|
|
|
182
263
|
- target-aware automation tests must prove bounded delayed advertisement discovery, non-interactive acceptance outcomes, explicit partial and blocked results, baseline de-duplication across AutoSync and configured targets, cancellation of delayed AutoStart after suspension, and a finite demand beside an AutoStart-held room;
|
|
183
264
|
- Commonlib rebuild tests must prove that first-device P2P initialisation does not reset a remote database and that an additional-device P2P Fetch performs one explicit peer-selection pass before resuming reflection;
|
|
184
265
|
- the Self-hosted LiveSync Compose P2P lifecycle test must replace a current replicator, rediscover the same real peer, perform bidirectional RPC, and verify transferred content from a separate process;
|
|
185
|
-
- the Self-hosted LiveSync real-Obsidian P2P Setup URI workflow must generate the second-device URI on the first device, accept both peer directions visibly, and verify a two-way note round-trip;
|
|
266
|
+
- the Self-hosted LiveSync real-Obsidian P2P Setup URI workflow must generate the second-device URI on the first device, accept both peer directions visibly, and verify a two-way note round-trip;
|
|
267
|
+
- prepared-settings tests must prove managed TURN and expiry requirements, an unmanaged STUN-only override without expiry, relay-only rejection without TURN, immutable requested values, cancellation, expiry replacement, and late-result fencing; and
|
|
186
268
|
- the relay-disconnect test must observe the original WebSocket reach `CLOSED`, remain closed while reconnection is paused, and be replaced after reconnection resumes.
|
|
187
269
|
|
|
188
270
|
The corresponding product decision and rejected alternatives are recorded in Self-hosted LiveSync's P2P room and transport lifecycle ADR.
|
package/docs/proven-in-use.md
CHANGED
|
@@ -24,6 +24,8 @@ Commonlib's injected remote-service tests verify that an owning operation can ab
|
|
|
24
24
|
|
|
25
25
|
Commonlib's remote-preference result contract distinguishes available synchronisation settings, a remote which has not stored those settings yet, a failed read, and a remote type which does not support central preferences. Focused CouchDB and Object Storage tests cover absent milestone data separately from transport failures, while Self-hosted LiveSync owns the initialisation choices, cancellation policy, and user-facing explanation.
|
|
26
26
|
|
|
27
|
+
The focused `/settings` entry also supplies the immutable tweak assessment used by central compatibility checks and host-owned mismatch resolution. Commonlib preserves the exact assessment from a failed CouchDB or Object Storage attempt in its recovery hint, derives directional setting changes and reconstruction impact from one rule table, and keeps P2P's warning policy separate from central rejection. Self-hosted LiveSync consumes the supplied assessment for its two resolution interfaces, compatible chunk-setting auto-acceptance, and Red Flag Fetch setting adoption. The host remains responsible for user choice, settings persistence, Fetch or Rebuild execution, and verifying that the active publication and settings still match before applying a choice.
|
|
28
|
+
|
|
27
29
|
Commonlib's full offline scanner distinguishes completed, deliberately skipped, and failed storage/database pairs. Before pair construction, it withholds Metadata whose actual document ID disagrees with its recorded path, without reflection, deletion, or last-seen side effects. A consistently addressed entry for the same logical path continues through the established path-based flow; only a path without such an entry also withholds storage processing. The read-only actual-ID Inspector and separately invoked one-entry repair retain ambiguous states for review, revalidate an exact source revision, verify a target-first copy, and preserve the source on failure. Snapshot-restoration tests additionally verify that restored inclusions use current storage content, stale deletions are suppressed, rename halves are admitted from their current path states, and an inspection failure does not become evidence of absence. The following full scan remains the final reconciliation step.
|
|
28
30
|
|
|
29
31
|
The strict aggregate remains the default for Fast Setup, Fetch, Rebuild, direct scans, and CLI mirror or daemon paths. Self-hosted LiveSync opts only ordinary Obsidian start-up into continuing after individual pair failures. Commonlib returns the distinct `completed-with-file-failures` result, retains each failed result and retry state, records each affected path at verbose level, and leaves any user-facing notice to the host. Focused Commonlib tests cover the default and an explicitly continuing scan; downstream type checks, unit tests, and builds exercise the exact packed implementation and host call. Android-specific storage behaviour remains real-device and reporter-environment evidence rather than a Commonlib guarantee.
|
|
@@ -68,6 +70,36 @@ The Obsidian plug-in, CLI, WebApp, and WebPeer compose P2P ownership through `us
|
|
|
68
70
|
|
|
69
71
|
Commonlib's focused P2P compatibility tests establish legacy defaulting, bounded outgoing message sizes, connection-string and QR-setting round trips, application of the configured bound across its Trystero server and client surfaces, relay-only ICE mapping when a valid TURN URL is present, and replacement of a serving transport when an effective compatibility value changes. They do not prove that a particular network path requires a smaller preset or that a configured TURN service can allocate a relay. Self-hosted LiveSync owns profile selection, user-facing controls, and real-Obsidian composition; device- and network-specific connectivity remains downstream or reporter-environment evidence.
|
|
70
72
|
|
|
73
|
+
The optional P2P settings-preparation hook lets a host supply connection-only
|
|
74
|
+
ICE servers without adding provider logic to Commonlib. Focused Commonlib tests
|
|
75
|
+
cover immutable requested settings, provider-scalar identity, room reuse before
|
|
76
|
+
expiry, replacement inside the 30-second expiry margin, explicit reconnect,
|
|
77
|
+
bounded preparation, cancellation, late-result fencing, manual compatibility,
|
|
78
|
+
an unmanaged STUN-only override without provider metadata or expiry,
|
|
79
|
+
relay-only rejection without TURN, relay-only mapping with TURN, and omission
|
|
80
|
+
of runtime credentials from persistence and sharing. Profile tests cover the
|
|
81
|
+
`managedType`, `managedId`, and `token` URI fields, one-profile flat migration,
|
|
82
|
+
activation, whole-profile encryption, and failure without plaintext
|
|
83
|
+
replacement.
|
|
84
|
+
|
|
85
|
+
Self-hosted LiveSync supplies the Cloudflare HTTP function, response validation,
|
|
86
|
+
provider selection, settings UI, and host hook. Mocked HTTP and injected-room
|
|
87
|
+
tests establish those boundaries without calling Cloudflare. On 16 September
|
|
88
|
+
2026, two isolated Obsidian 1.12.7 instances on one Linux host exercised the
|
|
89
|
+
exact `0.1.25-dev.turn-credentials.6` package. Both acquired real Cloudflare
|
|
90
|
+
credentials and selected relay candidates, and a note reached the receiving
|
|
91
|
+
Vault. Explicit disconnection and reconnection issued fresh credentials,
|
|
92
|
+
selected relay candidates at both endpoints again, and allowed a second note
|
|
93
|
+
to reach the other Vault. A separate real-Obsidian check with dummy credentials
|
|
94
|
+
verified encrypted profile persistence and restoration after restart, with
|
|
95
|
+
issued ICE credentials excluded from saved settings.
|
|
96
|
+
|
|
97
|
+
Natural TTL expiry, interruption during a replication batch, mobile lifecycle,
|
|
98
|
+
mixed manual and managed peers, and different-network connectivity retain
|
|
99
|
+
separate downstream runtime validation requirements. The live-provider check
|
|
100
|
+
establishes issuance and explicit reconnection for the tested package; it does
|
|
101
|
+
not establish those additional behaviours or the eventual published artefact.
|
|
102
|
+
|
|
71
103
|
Focused room-session and RPC tests additionally establish that a manual stop delivers cancellation to every concurrent finite replication while leaving the room reusable, that session retirement rejects new work and awaits admitted work before leaving, and that caller cancellation reaches a cancellation-aware incoming RPC handler. The replication-shim tests establish cancellation at safe batch boundaries and preserve the checkpoint for an atomic database write which has already settled. Self-hosted LiveSync composes the provider stop capability into its manual command; physical transport interruption and operating-system process termination remain host and runtime boundaries rather than rollback guarantees.
|
|
72
104
|
|
|
73
105
|
This is evidence that the current package boundary can be consumed without the Obsidian host, but it is not yet a recommended standalone Commonlib client factory. The high-level lifecycle, readiness, error, and disposal contract remains future package work after Self-hosted LiveSync 1.0 rather than a gate for that release.
|
|
@@ -72,6 +72,25 @@ Two other values deliberately remain unset until their owning lifecycle supplies
|
|
|
72
72
|
|
|
73
73
|
The standard Commonlib `SettingService` performs this preparation automatically. Hosts which use that service can inspect `getSettingsMigrationState()` after `loadSettings()` instead of calling the function themselves.
|
|
74
74
|
|
|
75
|
+
## Assessing synchronisation tweaks
|
|
76
|
+
|
|
77
|
+
Use `assessTweakCompatibility(current, preferred)` from the focused `/settings` entry when comparing the synchronisation settings advertised by two sides. The result contains immutable, whitelisted snapshots, one entry for each compared setting, and directional `adoptPreferred` and `adoptCurrent` change sets. Each entry keeps the raw value and key-presence state separately from the effective value.
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { assessTweakCompatibility } from "@vrtmrz/livesync-commonlib/settings";
|
|
81
|
+
|
|
82
|
+
const assessment = assessTweakCompatibility(localTweaks, remoteTweaks);
|
|
83
|
+
if (assessment.alignment === "mismatched") {
|
|
84
|
+
host.requestTweakResolution(assessment);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
An absent or `undefined` `handleFilenameCaseSensitive` value has the established effective value `false`. It is therefore equal to an explicit `false` value, while an explicit `true` value is mismatched. The historical defaults in `TweakValuesDefault` receive the same treatment. A missing value without a proven historical default is reported as `unadvertised` and does not by itself make `alignment` mismatched. Explicit `false`, `0`, and empty-string values remain advertised values.
|
|
89
|
+
|
|
90
|
+
The transition change sets never contain `undefined`. They can fill a missing target from an advertised source, and can use a proven effective default when that changes the target's effective value. Each transition reports `none`, `recommended`, or `required` reconstruction impact and identifies the settings which contribute that impact. Commonlib does not apply the transition, save settings, start Fetch or Rebuild, or grant permission to retry an operation.
|
|
91
|
+
|
|
92
|
+
`representationDiffers` reports raw value or key-presence differences among the compared settings. The maintained P2P transport uses this to preserve its warning for representational differences while continuing replication after ordinary tweak differences; passphrase authentication remains a separate rejection check.
|
|
93
|
+
|
|
75
94
|
## Review and downgrade boundary
|
|
76
95
|
|
|
77
96
|
A migration may report `requiresSyncReview` when automatic synchronisation should wait for a human decision. Commonlib reports that requirement but does not disable synchronisation settings, persist an acknowledgement, display a dialogue, or decide whether replication may proceed. Those are host-local responsibilities because one device must not acknowledge a safety review for another device through synchronised settings.
|
|
@@ -82,6 +101,6 @@ The settings schema version is independent of the package version and of any rem
|
|
|
82
101
|
|
|
83
102
|
## Tests owned by Commonlib
|
|
84
103
|
|
|
85
|
-
The settings lifecycle unit tests cover blank stores, representative legacy choices, migration idempotence, legacy file-name case normalisation, legacy review state, future-schema downgrade protection, and the distinction between new-Vault recommendations and stored-setting fallbacks. The packed-package test imports the focused `/settings` entry from a clean consumer and checks its declarations and runtime exports.
|
|
104
|
+
The settings lifecycle unit tests cover blank stores, representative legacy choices, migration idempotence, legacy file-name case normalisation, legacy review state, future-schema downgrade protection, and the distinction between new-Vault recommendations and stored-setting fallbacks. Tweak-assessment tests cover effective defaults, unadvertised values, directional change sets, reconstruction impact, raw representation differences, immutable snapshots, and document-ID case behaviour. The packed-package test imports the focused `/settings` entry from a clean consumer and checks its declarations and runtime exports.
|
|
86
105
|
|
|
87
106
|
Hosts remain responsible for testing when setup is classified as new, how local review acknowledgement is stored, how replication is gated, and how their settings interface presents the result.
|
package/package.json
CHANGED