@vrtmrz/livesync-commonlib 0.1.29 → 0.1.30

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 (40) hide show
  1. package/README.md +5 -1
  2. package/dist/API/DirectFileManipulatorV2.d.ts +1 -0
  3. package/dist/API/DirectFileManipulatorV2.js +19 -2
  4. package/dist/API/processSetting.d.ts +179 -1
  5. package/dist/API/processSetting.js +5 -1
  6. package/dist/common/configForDoc.d.ts +1 -0
  7. package/dist/common/configForDoc.js +24 -7
  8. package/dist/common/models/db.type.d.ts +1 -0
  9. package/dist/common/models/setting.const.defaults.js +2 -0
  10. package/dist/common/models/setting.const.qr.js +2 -1
  11. package/dist/common/models/setting.lifecycle.js +3 -1
  12. package/dist/common/models/setting.type.d.ts +2 -0
  13. package/dist/common/models/shared.definition.configNames.js +4 -0
  14. package/dist/common/models/tweak.definition.d.ts +6 -0
  15. package/dist/common/models/tweak.definition.js +1 -0
  16. package/dist/common/settingConstants.d.ts +1 -0
  17. package/dist/common/utils.js +2 -1
  18. package/dist/pouchdb/LiveSyncDBFunctions.d.ts +1 -0
  19. package/dist/pouchdb/LiveSyncDBFunctions.js +12 -3
  20. package/dist/pouchdb/StreamingFetch.d.ts +2 -0
  21. package/dist/pouchdb/StreamingFetch.js +28 -0
  22. package/dist/pouchdb/encryption.d.ts +2 -2
  23. package/dist/pouchdb/encryption.js +15 -7
  24. package/dist/pouchdb/negotiation.d.ts +3 -2
  25. package/dist/pouchdb/negotiation.js +84 -32
  26. package/dist/pouchdb/remoteFeatureCompatibility.d.ts +25 -0
  27. package/dist/pouchdb/remoteFeatureCompatibility.js +52 -0
  28. package/dist/replication/couchdb/LiveSyncReplicator.js +21 -9
  29. package/dist/replication/index.d.ts +2 -0
  30. package/dist/replication/index.js +13 -1
  31. package/dist/replication/journal/LiveSyncJournalReplicator.js +2 -5
  32. package/dist/serviceModules/Rebuilder.js +11 -6
  33. package/dist/services/base/CommonlibMessages.d.ts +2 -0
  34. package/dist/services/base/CommonlibMessages.js +2 -0
  35. package/dist/services/base/RemoteConnection.d.ts +2 -0
  36. package/dist/services/base/RemoteService.js +9 -1
  37. package/dist/worker/bgWorker.js +1 -1
  38. package/docs/proven-in-use.md +4 -0
  39. package/docs/remote-feature-compatibility.md +177 -0
  40. package/package.json +1 -1
@@ -12,6 +12,10 @@ Unreleased colon-path regression tests establish that Commonlib preserves ordina
12
12
 
13
13
  Commonlib's encryption tests verify that an obfuscated Metadata document retains its document ID while its HKDF-encrypted path and file properties round-trip, that V1-obfuscated paths remain readable through the fallback, and that PouchDB replication presents a decoded path to both local storage and change events. The Fast Fetch test verifies decryption before storage and checkpointing. On 26th September 2026, a local packed candidate of this fix passed LiveSync 1.0.31's `npm run check` and unit tests, as well as real Obsidian two-Vault synchronisation, encrypted CLI-to-Obsidian transfer, and encrypted Metadata retrieval through Fast Fetch during manual CouchDB onboarding.
14
14
 
15
+ The unreleased 0.1.30 packed candidate adds encryption of Hidden File Sync and Customisation Sync Metadata when CouchDB, E2EE V2, and Property Encryption are active. Focused Commonlib tests cover the `i:f:`, `ix:f:`, and legacy `ps:f:` representations, legacy and new setting defaults, feature declaration, concurrent version updates, and unknown-feature rejection. With that packed candidate in LiveSync, two real-Obsidian scenarios checked the raw CouchDB Metadata marker, zeroed times and size, empty public Chunk-reference list, and generation 13 feature declaration before restoring the files in a second Vault. The Hidden File Sync scenario also rebuilt the remote and verified the accepted writer's feature declaration and encrypted Metadata before the second Vault fetched them. The CLI-to-Obsidian encrypted note scenario also passed with matching effective settings. A separate real-Obsidian scenario kept continuous CouchDB replication active whilst the remote version document acquired an unknown feature; the local document was observed, the active Replicator retired, another replication was refused, and previously accepted Vault content remained intact. After restarting the Vault, both finite replication and the actual continuous connection attempt were refused by the remote declaration, without a KV feature history. These runs establish the tested local package and host build; they do not validate a published registry artefact or recovery under a future compatible client.
16
+
17
+ Additional real-CouchDB integration tests exercise Fast Fetch admission before local reset, generation 12 acceptance, and generation 13 retrieval with plaintext and encrypted internal Metadata together. A real-Obsidian migration scenario enables the preference through the settings UI without Rebuild, verifies that unchanged Metadata retains its original revision while rewritten entries are encrypted with stable IDs, and checks a second device's mismatch rejection and restoration after alignment. After turning the preference OFF, Fast Fetch still retrieves both representations and their Chunks with matching content; the remote feature declaration remains. These checks use the local packed candidate with LiveSync 1.0.32.
18
+
15
19
  The plug-in extends the neutral `ServiceContext` with Obsidian-owned capabilities in `src/modules/services/ObsidianServiceContext.ts`. One context instance carries the LiveSync-owned translator and event hub through the Service Hub rather than placing those dependencies in Commonlib globals. Commonlib supplies its typed English fallback when another host omits the translator.
16
20
 
17
21
  The consumer contract in `test/contracts/serviceContext.ts` checks shared result semantics and exact context identity across the composed services. The real-Obsidian suite documented in `test/e2e-obsidian/README.md` then covers plug-in loading, representative Svelte dialogue mounts, Vault reflection, CouchDB and Object Storage synchronisation, a two-device P2P Setup URI round-trip, two-Vault behaviour, and other Obsidian-owned boundaries.
@@ -0,0 +1,177 @@
1
+ ---
2
+ date: 2026-09-27
3
+ commonlib-version: "0.1.30"
4
+ self-hosted-livesync-version: "1.0.32"
5
+ status: unreleased
6
+ ---
7
+
8
+ # Remote feature compatibility
9
+
10
+ This document defines the persisted feature contract for CouchDB databases and
11
+ the checks required of Commonlib consumers. It describes unreleased behaviour
12
+ being implemented in this branch.
13
+ The first feature is encrypted Metadata for Hidden File Sync and Customisation
14
+ Sync. Journal and P2P retain their existing transport contracts.
15
+
16
+ ## Ownership and compatibility dimensions
17
+
18
+ Commonlib owns the wire representation, validation, feature identifiers, shared
19
+ assessment, and admission requirements. Hosts own presentation, scheduling, and
20
+ the application of received documents to their files.
21
+
22
+ Keep these independent dimensions separate:
23
+
24
+ - the remote protocol generation states how to interpret the control document;
25
+ - the used-feature set states which representations the database may contain;
26
+ - the supported-feature set belongs to the running client implementation;
27
+ - Tweak values describe settings which participating writers should share; and
28
+ - the existing Chunk version range describes Chunk format compatibility.
29
+
30
+ A feature is supported only when the client can interpret its data and preserve
31
+ its dependencies during applicable operations, including maintenance. Ignoring
32
+ an unfamiliar file path is not sufficient: encrypted Chunk references must not
33
+ be mistaken for an empty reference set.
34
+
35
+ ## Control document
36
+
37
+ Extend the existing ordinary document, preserving its existing identifier:
38
+
39
+ ```json
40
+ {
41
+ "_id": "obsydian_livesync_version",
42
+ "type": "versioninfo",
43
+ "version": 13,
44
+ "used_features": ["encrypted-internal-metadata-v1"]
45
+ }
46
+ ```
47
+
48
+ Generation 13 is the introduction boundary. It makes legacy clients
49
+ which understand only generation 12 reject the enabled remote through their
50
+ existing version check. Subsequent independent features use the feature list;
51
+ they do not each require another protocol generation.
52
+
53
+ Generation 12 remains readable without a feature list. Connecting with a newer
54
+ client must not promote a legacy database. The existing local compatibility
55
+ acknowledgement and settings-schema version remain separate concerns; adding
56
+ this remote contract must not implicitly advance those markers for every user.
57
+
58
+ The document remains readable before Metadata decryption and is replicated to
59
+ local databases. The `_local/obsydian_livesync_milestone` document continues to
60
+ hold participant and Tweak information; it is not the sole source of feature
61
+ requirements. The ordinary version document also provides the existing route
62
+ for observing compatibility changes during replication.
63
+
64
+ ### Validation and unknown identifiers
65
+
66
+ Read `used_features` as an array of opaque, non-empty strings. Preserve unknown
67
+ strings before comparing them with the client-owned supported set. A closed
68
+ enum must not discard the evidence needed to diagnose an unknown feature.
69
+ Order and duplicates do not change the set's meaning.
70
+
71
+ Assessment returns distinct outcomes for a compatible document, an unsupported
72
+ protocol generation, unknown feature identifiers, and malformed control data.
73
+ Unknown identifiers are included in the result so any host can render a generic
74
+ message such as `Unknown features are in use: example-feature-v2` without a
75
+ feature-specific label or translation. Hosts render identifiers as text.
76
+
77
+ A missing list is accepted as legacy input only in the legacy generation. A
78
+ new-generation document with a missing or invalid list is not silently treated
79
+ as an empty set. Deleting or corrupting the control document does not authorise
80
+ ordinary data operations or recreate a legacy declaration over a non-empty DB.
81
+
82
+ ### Updating requirements
83
+
84
+ Declare a feature before writing documents which depend on it. Introduce the
85
+ new generation and its initial feature set in the same control-document update.
86
+ Preserve existing identifiers and unrelated fields when updating the document.
87
+ On a revision conflict, fetch and reassess the current document before merging
88
+ or retrying; never replace another writer's requirements with a stale snapshot.
89
+
90
+ The used-feature set is retained when a writer turns its corresponding setting
91
+ off. Older documents or revisions may still depend on that feature. Removing
92
+ a requirement needs a verified data-history transition, such as an explicit
93
+ reconstruction which removes that representation. Manually shortening the declaration is not a supported migration.
94
+
95
+ This is a client compatibility contract, not CouchDB access control. It cannot
96
+ retrofit checks into legacy direct-access clients or revoke requests which a
97
+ server has already accepted.
98
+
99
+ ## Admission and changes during replication
100
+
101
+ Use the same assessment before ordinary replication, Fast Fetch, direct file
102
+ access, and cleaned-remote recovery before counting Chunk references. Declare
103
+ required write features after admission, including for the writer accepted by a
104
+ Rebuild lock. A locked-out device cannot declare or upload a new representation.
105
+
106
+ Fast Fetch reads the version document with its configured HTTP credentials and
107
+ custom headers before opening or resetting the local database, including when
108
+ resuming a checkpoint. Rejection leaves local data and the checkpoint intact.
109
+ An empty remote and legacy generations retain their existing completion and
110
+ migration paths; a missing version document in a populated remote is rejected.
111
+
112
+ The remote document is the source of requirements. The milestone retains its
113
+ participant, Tweak comparison, and lock responsibilities. Hosts do not need a
114
+ second persistent feature list or rejection history in KV storage.
115
+
116
+ The existing received-version handler also uses the shared assessment. An
117
+ unknown identifier, unsupported generation, or malformed document requests
118
+ Replicator retirement and reports the reason. Supported requirements do not
119
+ interrupt the connection merely because the revision or feature list changed.
120
+ Do not await retirement inside the change callback: the owner may be waiting
121
+ for that callback to settle before it can drain and close the operation.
122
+
123
+ A received notification can follow persistence to the local database. The
124
+ handler is a best-effort response to an exceptional live change; it does not
125
+ fence every queued file application or atomically revoke admitted requests.
126
+ Use the established rollout workflow: update every synchronising client, enable
127
+ the preference, and perform the strongly recommended manual Rebuild. Rebuild
128
+ uses the existing remote lock. Merely changing the preference does not lock the
129
+ remote, so continuing without rebuilding requires compatible devices first,
130
+ including those with an active connection.
131
+
132
+ The next connection assesses the current remote declaration, including after
133
+ restart. Existing host snapshot and startup behaviour remain unchanged. After
134
+ updating, use the host's normal reconciliation or Fetch facilities as needed;
135
+ this contract does not add permanent local rejection flags or repair unrelated
136
+ snapshot inconsistencies.
137
+
138
+ ## First feature: encrypted internal Metadata
139
+
140
+ `encrypted-internal-metadata-v1` denotes the first specification of this feature,
141
+ not the legacy E2EE V1 algorithm. It uses E2EE V2's existing HKDF Metadata
142
+ representation for obfuscated `i:`, `ix:`, and supported legacy `ps:` entries.
143
+ Document IDs and path-to-ID conversion remain unchanged.
144
+
145
+ Supporting readers decode by the encrypted Metadata marker, independently of
146
+ the current write preference. Existing plaintext and encrypted Metadata may
147
+ coexist. Activating the preference affects subsequent writes; it does not
148
+ rewrite unchanged documents or erase earlier plaintext revisions. Reconstruction
149
+ is strongly recommended for existing-data privacy, and remains a manual choice.
150
+
151
+ Garbage Collection V3 remains a beta, manually initiated operation. Its
152
+ workflow first performs an ordinary bidirectional synchronisation, which checks
153
+ the remote feature contract. It does not add another check at every collection
154
+ step. The separate cleaned-remote recovery path checks the local contract
155
+ before its first Chunk-reference count because that path does not begin with
156
+ ordinary synchronisation.
157
+
158
+ ## Verification required before acceptance
159
+
160
+ Protect the wire contract with tests for unknown names, multiple unknown names,
161
+ malformed lists, legacy absence, new-generation absence, duplicate and reordered
162
+ entries, concurrent updates, and preservation of existing fields. Use a made-up
163
+ future identifier so the test does not depend on a known feature's label.
164
+
165
+ Protect runtime behaviour with tests for initial admission, an admitted writer
166
+ on a locked remote, unknown names received at the same generation, and
167
+ retirement without a circular wait. Keep direct access, Fast Fetch, and
168
+ maintenance admission checks covered. Host tests should preserve existing
169
+ startup and queue semantics, including snapshot failures.
170
+
171
+ Use real CouchDB and downstream Obsidian and CLI tests to validate encrypted
172
+ Metadata, file restoration, receipt of a changed declaration, and rejection
173
+ before synchronisation after restart. These checks do not establish atomic
174
+ cancellation timing or automatic recovery under a future compatible client.
175
+
176
+ Related contracts: [local database lifecycle](database-lifecycle.md) and
177
+ [settings lifecycle](settings-lifecycle.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vrtmrz/livesync-commonlib",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
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",