@vrtmrz/livesync-commonlib 0.1.24 → 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.
Files changed (34) hide show
  1. package/dist/API/processSetting.d.ts +1 -1
  2. package/dist/API/processSetting.js +10 -6
  3. package/dist/common/ConnectionString.js +15 -8
  4. package/dist/common/models/setting.const.qr.js +5 -0
  5. package/dist/common/models/setting.lifecycle.js +5 -3
  6. package/dist/common/models/setting.p2p.d.ts +10 -0
  7. package/dist/common/models/setting.p2p.js +13 -0
  8. package/dist/common/models/setting.type.d.ts +10 -0
  9. package/dist/common/models/tweak.definition.d.ts +5 -0
  10. package/dist/common/settingConstants.d.ts +5 -0
  11. package/dist/common/types.d.ts +3 -3
  12. package/dist/common/types.js +6 -0
  13. package/dist/common/utils.js +4 -1
  14. package/dist/p2p/P2PService.d.ts +7 -1
  15. package/dist/p2p/P2PService.js +13 -7
  16. package/dist/p2p/index.d.ts +3 -1
  17. package/dist/p2p/index.js +6 -0
  18. package/dist/replication/trystero/P2PRoomSessionOwner.d.ts +22 -1
  19. package/dist/replication/trystero/P2PRoomSessionOwner.js +193 -13
  20. package/dist/replication/trystero/TrysteroReplicator.js +9 -3
  21. package/dist/replication/trystero/TrysteroReplicatorP2PServer.d.ts +1 -0
  22. package/dist/replication/trystero/TrysteroReplicatorP2PServer.js +10 -3
  23. package/dist/replication/trystero/p2pReplicatorConfigurationIdentity.js +6 -3
  24. package/dist/replication/trystero/useP2PReplicatorFeature.d.ts +6 -1
  25. package/dist/replication/trystero/useP2PReplicatorFeature.js +7 -4
  26. package/dist/rpc/transports/trysteroUtils.d.ts +2 -2
  27. package/dist/rpc/transports/trysteroUtils.js +32 -2
  28. package/dist/serviceFeatures/remoteConfig.js +3 -0
  29. package/dist/services/base/SettingService.d.ts +1 -0
  30. package/dist/services/base/SettingService.js +37 -9
  31. package/docs/development.md +3 -3
  32. package/docs/p2p-transport-lifecycle.md +86 -4
  33. package/docs/proven-in-use.md +30 -0
  34. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  ---
2
- date: 2026-08-28
3
- commonlib-version: "0.1.20"
4
- self-hosted-livesync-version: "1.0.21"
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; and
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.
@@ -70,6 +70,36 @@ The Obsidian plug-in, CLI, WebApp, and WebPeer compose P2P ownership through `us
70
70
 
71
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.
72
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
+
73
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.
74
104
 
75
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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrtmrz/livesync-commonlib",
3
- "version": "0.1.24",
3
+ "version": "0.1.25",
4
4
  "description": "Shared data, storage, and replication primitives for Self-hosted LiveSync clients.",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",