@vrtmrz/livesync-commonlib 0.1.44 → 0.2.0
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/README.md +37 -4
- package/dist/API/DirectFileManipulatorV2.d.ts +2 -0
- package/dist/API/DirectFileManipulatorV2.js +3 -0
- package/dist/common/configForDoc.d.ts +1 -0
- package/dist/common/configForDoc.js +11 -1
- package/dist/common/models/db.definition.d.ts +1 -0
- package/dist/common/models/setting.const.preferred.js +1 -3
- package/dist/managers/EntryManager/EntryManagerImpls.js +3 -2
- package/dist/pouchdb/LiveSyncDBFunctions.js +4 -0
- package/dist/pouchdb/StreamingFetch.d.ts +5 -1
- package/dist/pouchdb/StreamingFetch.js +529 -65
- package/dist/replication/RemoteResource.d.ts +23 -2
- package/dist/replication/RemoteResource.js +6 -2
- package/dist/replication/couchdb/LiveSyncReplicator.d.ts +8 -0
- package/dist/replication/couchdb/LiveSyncReplicator.js +132 -1
- package/dist/replication/couchdb/fastForward.d.ts +19 -0
- package/dist/replication/couchdb/fastForward.js +119 -0
- package/dist/replication/index.d.ts +3 -1
- package/dist/replication/joinedDevices.d.ts +25 -0
- package/dist/replication/joinedDevices.js +123 -0
- package/dist/replication/journal/JournalSyncCore.d.ts +2 -1
- package/dist/replication/journal/JournalSyncCore.js +11 -1
- package/dist/replication/journal/LiveSyncJournalReplicator.d.ts +4 -0
- package/dist/replication/journal/LiveSyncJournalReplicator.js +56 -1
- package/dist/replication/journal/objectstore/JournalStorageAdapter.d.ts +3 -0
- package/dist/replication/journal/objectstore/MinioStorageAdapter.d.ts +2 -1
- package/dist/replication/journal/objectstore/MinioStorageAdapter.js +27 -1
- package/dist/replication/trystero/P2PRoomSessionOwner.d.ts +1 -1
- package/dist/replication/trystero/P2PRoomSessionOwner.js +27 -14
- package/dist/serviceModules/Rebuilder.js +41 -15
- package/dist/services/BrowserServices.d.ts +4 -2
- package/dist/services/BrowserServices.js +2 -5
- package/dist/services/HeadlessServices.d.ts +3 -0
- package/dist/services/HeadlessServices.js +2 -5
- package/dist/services/ServiceHub.d.ts +4 -4
- package/dist/services/base/IService.d.ts +10 -18
- package/dist/services/base/ReplicatorService.remoteResourceResolver.js +1 -1
- package/dist/services/base/SettingService.d.ts +8 -18
- package/dist/services/base/SettingService.js +28 -46
- package/dist/services/implements/base/SvelteDialog.d.ts +2 -2
- package/dist/services/implements/base/UIService.d.ts +2 -0
- package/dist/services/implements/base/UIService.js +5 -0
- package/dist/services/implements/injectable/InjectableServiceHub.d.ts +4 -4
- package/dist/services/implements/injectable/InjectableServices.d.ts +2 -2
- package/dist/services/implements/injectable/InjectableSettingService.d.ts +0 -3
- package/dist/services/implements/injectable/InjectableSettingService.js +0 -11
- package/dist/string_and_binary/chunks.js +7 -5
- package/dist/uiCommands.d.ts +26 -0
- package/dist/uiCommands.js +57 -0
- package/dist/worker/bgWorker.js +1 -1
- package/docs/development.md +15 -3
- package/docs/proven-in-use.md +38 -4
- package/docs/releasing.md +20 -13
- package/docs/settings-lifecycle.md +37 -5
- package/package.json +12 -17
- package/dist/services/base/ConfigService.d.ts +0 -7
- package/dist/services/base/ConfigService.js +0 -6
- package/dist/services/implements/browser/ConfigServiceBrowserCompat.d.ts +0 -16
- package/dist/services/implements/browser/ConfigServiceBrowserCompat.js +0 -23
package/docs/development.md
CHANGED
|
@@ -18,6 +18,16 @@ The source tree is larger than the supported package surface. Consumers may impo
|
|
|
18
18
|
|
|
19
19
|
Files elsewhere under `src` are implementation details unless a focused entry re-exports them or the compatibility inventory names them. Do not use the source layout, TypeScript path aliases, or the presence of generated declarations as evidence of a supported consumer import.
|
|
20
20
|
|
|
21
|
+
## Module filenames
|
|
22
|
+
|
|
23
|
+
For new or renamed TypeScript and JavaScript source modules, start the filename
|
|
24
|
+
with an upper-case letter when the file contains a class with the same name,
|
|
25
|
+
such as `ServiceHub.ts`. Use a lower-case initial when the module primarily
|
|
26
|
+
exports functions, such as `fastForward.ts`. Follow the surrounding filename
|
|
27
|
+
style for the rest of the basename. Corresponding test files use the same
|
|
28
|
+
basename, such as `fastForward.unit.spec.ts`. Retain established names for
|
|
29
|
+
unrelated files and separate conventions for components or other file types.
|
|
30
|
+
|
|
21
31
|
## Service composition and state ownership
|
|
22
32
|
|
|
23
33
|
Commonlib uses four related forms of composition. Choose between them by ownership and dependency direction, not merely by whether an implementation has mutable state.
|
|
@@ -29,6 +39,8 @@ Commonlib uses four related forms of composition. Choose between them by ownersh
|
|
|
29
39
|
|
|
30
40
|
When a feature needs state, separate the component which owns that state, its transitions, and its invariants from the code which connects it to application lifecycle events and downstream effects. Give the stateful component narrow collaborators or callbacks rather than the complete Service Hub or application core. Keep application-level handler registration and host-specific presentation in the surrounding serviceFeature. A handler or effect which is part of the state contract, such as querying unresolved errors or reporting their first occurrence, may remain inside the stateful component when its input and output ports are explicit and bounded.
|
|
31
41
|
|
|
42
|
+
Settings storage follows the same ownership boundary. Each host selects one exact-key asynchronous `ValueStore & ValueDeleter` at its composition root and supplies it as the setting service's required `deviceValues` dependency. `setting.deviceValues` is that root; `setting.config` wraps it with the existing Vault and database-suffix scope, and the Service Hub `config` property aliases the same view. Commonlib does not discover browser globals or provide a module-global fallback. Keep existing local keys on the exact-key root, preserve configuration key names, and await Value Store operations. See [Settings lifecycle](settings-lifecycle.md#host-storage-for-device-values-and-configuration) for the key mapping and host example.
|
|
43
|
+
|
|
32
44
|
Existing features illustrate this direction:
|
|
33
45
|
|
|
34
46
|
- `targetFilter.ts` keeps each cache or readiness gate inside the factory which owns the corresponding predicate. `useTargetFilters` composes those predicates and registers them in the required order.
|
|
@@ -127,15 +139,15 @@ The compatibility event bridge delegates lifecycle and status requests to the st
|
|
|
127
139
|
|
|
128
140
|
The physical room, WebRTC peer, and relay-socket boundaries are documented in [P2P transport lifecycle](p2p-transport-lifecycle.md). In particular, normal shutdown leaves the Trystero room without closing raw peer connections directly.
|
|
129
141
|
|
|
130
|
-
Self-hosted LiveSync remains
|
|
142
|
+
Self-hosted LiveSync remains a principal maintained consumer. Commonlib's normal publication gate is its own type, unit, integration, and packed-boundary checks, as described in [the release runbook](releasing.md). Run targeted downstream or real-runtime checks against the exact packed artefact when a named host-specific risk is not established by those owner tests; consumer adoption and downstream test completion are not general release prerequisites.
|
|
131
143
|
|
|
132
144
|
Commonlib owner tests exercise the real implementation behind each focused result and lifecycle contract. A consumer-owned unit test may inject the smallest structural capability it uses and provide its own fake or spy when that current test needs isolation. Do not publish Vitest-specific mocks, expose private service constructors, or refactor a production boundary merely to create possible future test infrastructure. Mock and spy helpers are not a prerequisite for the LiveSync 1.0 package-boundary work; add them only with the consumer test which requires them, or after that release work.
|
|
133
145
|
|
|
134
|
-
Prefer an object or callback injected at the host composition boundary over replacing an ESM module namespace. If a proposed focused API would require global mutation, import-order coupling, hidden construction, or private nominal types to substitute later, stop and review the production design before stabilising it.
|
|
146
|
+
Prefer an object or callback injected at the host composition boundary over replacing an ESM module namespace. If a proposed focused API would require global mutation, import-order coupling, hidden construction, or private nominal types to substitute later, stop and review the production design before stabilising it. Use exact-package downstream checks and focused real-runtime E2E for named host-specific risks which the owner tests cannot establish.
|
|
135
147
|
|
|
136
148
|
Commonlib publishes the typed English messages which it owns and uses them when a host does not provide a translator. A host may inject a translator through `ServiceContext`; the full multilingual catalogue and language-selection state belong to that host and are not part of the Commonlib package.
|
|
137
149
|
|
|
138
|
-
|
|
150
|
+
The [maintained-host examples and evidence](proven-in-use.md) are optional context, not a support entitlement or release or adoption gate. When that page is updated, distinguish current use, historical use, Commonlib-owned results, downstream tests, and real-runtime observations, and keep each claim within the evidence.
|
|
139
151
|
|
|
140
152
|
## Integration tests
|
|
141
153
|
|
package/docs/proven-in-use.md
CHANGED
|
@@ -1,13 +1,43 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Maintained-host examples and evidence
|
|
2
2
|
|
|
3
3
|
Commonlib is extracted from the implementation shared by [Self-hosted LiveSync](https://github.com/vrtmrz/obsidian-livesync) and its host applications. The package is therefore exercised by a substantial maintained consumer, but it does not yet claim a separate ecosystem of independent applications or a stable end-to-end SDK.
|
|
4
4
|
|
|
5
5
|
The useful evidence is host- and contract-specific. Focused Commonlib tests establish reusable result semantics; Self-hosted LiveSync tests establish how those contracts compose into the Obsidian plug-in, CLI, WebApp, and WebPeer. The Obsidian plug-in and CLI retain the strongest device and long-running synchronisation evidence. The browser applications add focused adapter and runtime tests, browser smoke tests, a cross-application P2P scenario ending at the production CLI, and public Pages smoke validation.
|
|
6
6
|
|
|
7
|
-
The code paths below identify
|
|
7
|
+
The code paths below identify maintained Self-hosted LiveSync composition points as examples. The reviewed downstream revision and compatibility imports are recorded in [`migration/downstream-imports.json`](migration/downstream-imports.json), which is regenerated by the package-boundary tooling rather than copied into prose links. These snapshots may become historical as the maintained downstream changes; this page is optional context, not a support entitlement or release or adoption gate.
|
|
8
8
|
|
|
9
9
|
## Obsidian plug-in
|
|
10
10
|
|
|
11
|
+
The unreleased V3 Rabin–Karp correction uses proportional binary thresholds,
|
|
12
|
+
including at values 0 and 1. Regression tests cover natural boundaries, suffix
|
|
13
|
+
reuse, forced caps, explicit minima, EOF tails, and large UTF-8 text. The packed
|
|
14
|
+
old/new CLI matrix verifies 810 file-stage digests over CouchDB, Journal, and
|
|
15
|
+
P2P in both directions. Separate revision tests retain conflict coverage.
|
|
16
|
+
The Linux Obsidian manual-setup workflow verifies value 0, eight 32 KiB binary
|
|
17
|
+
pieces, unchanged Metadata revision and complete local Chunk inventory after
|
|
18
|
+
restart, exact binary reception through Fast Fetch, and a bidirectional note
|
|
19
|
+
round-trip. These checks use the unpublished local candidate with LiveSync
|
|
20
|
+
1.0.39; they do not establish mobile or Cloudant-service behaviour.
|
|
21
|
+
|
|
22
|
+
Unreleased Fast Fetch tests verify all current conflict leaves, including deleted
|
|
23
|
+
leaves, before advancing the durable stream cursor. CouchDB 3.5.0 integration
|
|
24
|
+
tests exercise revision ancestry retrieval and a fresh-import handoff to the
|
|
25
|
+
ordinary PouchDB checkpoints, followed by a batch-size change and receipt of a
|
|
26
|
+
new revision in LiveSync mode. Unit tests cover unimported local writes, missing
|
|
27
|
+
or replaced checkpoint guards, partial publication, and exclusion of persisted
|
|
28
|
+
resume cursors. A controlled connection delay also verifies that disposing the
|
|
29
|
+
resource during preparation closes the connection when it arrives. Rebuilder
|
|
30
|
+
tests also delay and reject device-local checkpoint
|
|
31
|
+
writes, verifying that handoff, completion, and checkpoint removal wait for
|
|
32
|
+
successful persistence. The handoff requires an empty local database, suspended local
|
|
33
|
+
writers, and a remote database which is not replaced during the operation.
|
|
34
|
+
These package-owned tests do not establish arbitrary-time fast-forwarding,
|
|
35
|
+
On Demand repair, or real Obsidian runtime behaviour.
|
|
36
|
+
|
|
37
|
+
The unreleased joined-device resource and UI-command work adds instance-owned typed UI handlers, legacy-compatible device projections, and device-record removal. Focused unit tests cover missing records, preservation of other devices and unknown fields, self-removal rejection, conflict retries, unsupported writes, verification failures, and handler disposal. CouchDB 3.5.0 integration tests verify that reading or forgetting never creates a missing database, and verify removal and preservation while retaining a fixture which demonstrates that local documents accept stale revisions. Object Storage integration tests against RustFS verify conditional removal and rejection of stale ETags. These checks do not make concurrent CouchDB updates atomic.
|
|
38
|
+
|
|
39
|
+
Before integration with Commonlib 0.2.0, a local packed candidate based on 0.1.44 passed Self-hosted LiveSync 1.0.39 checks, unit tests, and production build. Its focused real-Obsidian 1.12.7 scenario on Linux verifies the settings entry, self-first and locked-out records, current metadata, manual refresh, confirmed removal, and preservation of other records and remote state. Mobile emulation verifies the command-palette entry, scrolling, viewport and safe-area bounds, and touch targets. Self-hosted LiveSync owns the dialogue and advisory version Notices. These results establish the tested build's behaviour; publication and native iOS and Android behaviour remain unverified.
|
|
40
|
+
|
|
11
41
|
Unreleased remote-inspection tests compare individual and bulk reads against CouchDB 3.5.0. A fixture with 65 Metadata documents and 130 Chunks produces identical integrity reports while reducing HTTP requests from 198 to 8. Encrypted bulk reads preserve current conflicts, exact revision access, missing-document evidence, and unchanged database and Security Seed state. Unit tests cover bounded GET batches, encoded URL limits, per-document failures, cancellation, and explicitly excluded remote coverage. These counts describe the fixture; they do not establish large-Vault elapsed-time improvements.
|
|
12
42
|
|
|
13
43
|
Unreleased [database diagnostics](database-diagnostics.md) tests cover preserved Usage accounting, normal-file identity classification, current conflict branches, byte comparisons, embedded Chunks, missing and unreadable content, cancellation, concurrent changes, and consistent pseudonyms. Real in-memory PouchDB tests verify pagination and conflict revision reads while retaining the original database handle. A CouchDB 3.5.0 integration test verifies GET-only access, encrypted Metadata and Chunk reads with an existing Security Seed, missing-seed failure without initialisation, and unchanged database update sequences and Seed documents. Focused tests also reject ciphertext which remains undecoded after an ID mismatch. Commonlib owns the result contract and compact Integrity Markdown formatter; Self-hosted LiveSync owns the serviceFeature, run-time name choice, dialogue lifecycle, and report copy and download controls. Its real Obsidian 1.12.7 test on Linux verifies cancellation before a run, both name modes, the nine-column Usage report, copy and download payloads, local integrity findings when CouchDB is unavailable, and unchanged settings, database update sequences, and Vault file names. Mobile emulation verifies the choice dialogue's viewport, safe-area, and touch-target layout; native iOS and Android behaviour remains unverified.
|
|
@@ -28,10 +58,14 @@ The CouchDB connection fix bypasses browser HTTP caching so encrypted replicatio
|
|
|
28
58
|
|
|
29
59
|
Unreleased settings tests verify that Object Storage-only credentials, JWT values, and authentication headers reach the host persistence handler only after connection encryption, and that unavailable or failed required encryption preserves the previous persisted settings. The focused `/settings` entry also supplies conditional whole-profile Markdown preparation and import preservation. A clean packed consumer checks the exhaustive property policy and prepared output types with an ES2018 compile fixture. Commonlib owns these result and type contracts; Self-hosted LiveSync owns Markdown file writes, its settings interface, and restoration through a real Obsidian restart.
|
|
30
60
|
|
|
61
|
+
The setting-service tests also cover the injected device-value boundary: exact local keys remain unchanged, the existing Vault and database-suffix configuration key layout is preserved, and separately injected stores remain isolated. These are Commonlib-owned asynchronous store contracts. Each host owns selecting its persistent adapter and verifying host storage across restart; this evidence does not claim additional real-runtime coverage.
|
|
62
|
+
|
|
31
63
|
Unreleased colon-path regression tests establish that Commonlib preserves ordinary file paths through Metadata storage, Chunk retrieval, and storage reflection, with path obfuscation enabled or disabled. They use real PouchDB with injected storage. This result does not establish which filenames a host's file-creation API accepts; that boundary requires host runtime verification.
|
|
32
64
|
|
|
33
65
|
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.
|
|
34
66
|
|
|
67
|
+
The EntryManager selection tests distinguish Hidden File Sync documents by their original `i:` prefix. They check that the normal-file allow-list applies to ordinary paths while prefixed hidden documents remain eligible, that the normal-file ignore-list still excludes matching hidden documents, and that hidden-file disablement and the Customisation Sync exceptions retain their behaviour. Hidden File Sync owns its additional target and ignore patterns in Self-hosted LiveSync; storage reflection and native Obsidian behaviour remain downstream verification boundaries.
|
|
68
|
+
|
|
35
69
|
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.
|
|
36
70
|
|
|
37
71
|
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.
|
|
@@ -182,6 +216,6 @@ A new integration should start with the focused entries, not by reproducing Self
|
|
|
182
216
|
|
|
183
217
|
Use the named consumer paths as integration examples, while retaining the ownership and limitations stated in the [root README](../readme.md), [storage guide](platform-storage.md), [standard-I/O guide](platform-standard-io.md), and [remote configuration profile guide](remote-configurations.md).
|
|
184
218
|
|
|
185
|
-
##
|
|
219
|
+
## Scope and maintenance
|
|
186
220
|
|
|
187
|
-
This page
|
|
221
|
+
This optional page preserves examples, current integration evidence, and history. It does not define supported behaviour or create a release or adoption gate; package guarantees are described by the published contracts and release policy. When this page is updated, distinguish current use, historical use, Commonlib-owned tests, downstream tests, and real-runtime observations, and keep each claim within its evidence.
|
package/docs/releasing.md
CHANGED
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
This document is the developer and maintainer runbook for preparing and publishing `@vrtmrz/livesync-commonlib`. Package-consumer guidance belongs in the root README.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Commonlib-owned release checks
|
|
6
6
|
|
|
7
|
-
Run the
|
|
7
|
+
Run the normal owner checks from a clean checkout:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm ci
|
|
11
11
|
npm run verify:package
|
|
12
|
+
npm run test:integration:managed
|
|
12
13
|
```
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
Together these checks type-check Commonlib, run its unit and integration suites, verify the source boundary, build the distributable package, install its exact tarball into a clean consumer, and bundle representative browser and Node entry points. These Commonlib-owned checks are the normal publication criteria. The source `package.json` remains private to prevent publishing the repository root. Only the generated `.package` directory is publishable, and its manifest defaults to public publication on the `next` dist-tag.
|
|
16
|
+
|
|
17
|
+
Downstream or real-runtime checks are appropriate when a named host-specific risk is not established by the owner tests; run those checks against the exact packed artefact and record the risk and result. LiveSync adoption and downstream validation are not general publication prerequisites. The [maintained-host examples and evidence](proven-in-use.md) page is optional context, not a release or update gate.
|
|
15
18
|
|
|
16
19
|
The package builder normalises generated directories to `0755`, ordinary files to `0644`, and declared `bin` targets to `0755` before validation. `test:package` uses a restrictive umask and verifies the packed modes, so local and hosted builds do not differ only because their caller environments use different umasks.
|
|
17
20
|
|
|
@@ -29,13 +32,17 @@ npm run verify:package
|
|
|
29
32
|
|
|
30
33
|
Inspect the lockfile diff before committing it. A dependency-only maintenance change must not alter the source package version, and lockfile normalisation must not be described as a package upgrade when resolved versions and integrity values are unchanged. When the workflow selects a newer reviewed npm CLI, update this example in the same change.
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
When a named host-specific risk is not established by the Commonlib owner checks, run the relevant downstream workflow against an exact Self-hosted LiveSync ref which consumes the package. It installs the tarball produced from the selected Commonlib commit and runs LiveSync type checks, unit tests, plug-in and application builds, and CLI E2E. Real Obsidian E2E remains local-only and is appropriate when the named risk concerns actual plug-in composition, storage, UI, or platform behaviour. These checks are conditional on the risk; LiveSync adoption is not a general release prerequisite.
|
|
36
|
+
|
|
37
|
+
## Version compatibility policy
|
|
38
|
+
|
|
39
|
+
The Commonlib 0.2 policy begins with 0.2.0 and does not retroactively change compatibility expectations for published 0.1.x versions. Within 0.2.x, preserve published APIs, types, behaviour, supported persisted data, and exported `compat/*` paths. Intentional breaking changes belong in 0.3.0. Consumers may declare a range such as `^0.2.0`; lockfiles and `npm ci` remain the reproducible install path.
|
|
33
40
|
|
|
34
41
|
## Preparing a release
|
|
35
42
|
|
|
36
|
-
Choose the version explicitly.
|
|
43
|
+
Choose the version explicitly. For the 0.2 line, start at 0.2.0. A stable candidate can use its final version on the `next` dist-tag, then be checked by exact source revision and tarball SHA-256 before the same version is promoted to `latest`. No `-next.N` or `-rc.N` version is required; use a separate prerelease version only when it is useful for a distinct candidate. Package-proof versions are local artefacts and cannot be staged.
|
|
37
44
|
|
|
38
|
-
Prepare
|
|
45
|
+
Prepare stable releases and any optional prereleases on a reviewed pull request based on `main`. An optional prerelease may be staged from the exact reviewed pull-request branch commit. A stable release must be staged only after its exact reviewed release commit is present on `main`.
|
|
39
46
|
|
|
40
47
|
```bash
|
|
41
48
|
npm ci
|
|
@@ -44,7 +51,7 @@ npm run verify:package
|
|
|
44
51
|
npm publish --dry-run .package --tag next --access public
|
|
45
52
|
```
|
|
46
53
|
|
|
47
|
-
Review `package.json`, `package-lock.json`, the generated manifest, the tarball contents, the test results
|
|
54
|
+
Review `package.json`, `package-lock.json`, the generated manifest, the tarball contents, and the Commonlib-owned test results. Add downstream evidence when a named host-specific risk requires it. Commit only the source manifest and lockfile for the version change; `.package`, `.package-consumer`, and `artifacts` are generated and ignored. Push and open a release pull request only after the usual user checkpoint. Keep a pull request in draft while a specifically planned downstream check is in progress; that check is not required when no such risk remains. Merge and publication remain separate later checkpoints.
|
|
48
55
|
|
|
49
56
|
## Historical initial npm bootstrap
|
|
50
57
|
|
|
@@ -58,9 +65,9 @@ npm run verify:package
|
|
|
58
65
|
npm publish .package --tag next --access public
|
|
59
66
|
```
|
|
60
67
|
|
|
61
|
-
Confirm the authenticated npm account, `@vrtmrz` scope ownership, package name, version, tarball checksum, packed contents, source commit, and target tag immediately before publication. Treat bootstrap publication as a separate user-authorised operation. npm may assign `latest` to the first published version even when `next` is requested; leave the immutable version in place and replace `latest` only after a stable release has passed
|
|
68
|
+
Confirm the authenticated npm account, `@vrtmrz` scope ownership, package name, version, tarball checksum, packed contents, source commit, and target tag immediately before publication. Treat bootstrap publication as a separate user-authorised operation. npm may assign `latest` to the first published version even when `next` is requested; leave the immutable version in place and replace `latest` only after a stable release has passed the Commonlib owner checks and any applicable targeted host checks.
|
|
62
69
|
|
|
63
|
-
Bootstrap publication was the one historical exception which used direct `npm publish`. Do not repeat that operation for routine releases.
|
|
70
|
+
Bootstrap publication was the one historical exception which used direct `npm publish`. Do not repeat that operation for routine releases. Optional prereleases use protected staged publishing and may select an exact reviewed branch commit; stable releases use an exact `main` commit. If the owner checks or an applicable targeted host check fails, leave the published version immutable and prepare a new version.
|
|
64
71
|
|
|
65
72
|
## Trusted staged publishing
|
|
66
73
|
|
|
@@ -73,9 +80,9 @@ After bootstrap, configure the npm Trusted Publisher for:
|
|
|
73
80
|
|
|
74
81
|
Protect the GitHub `npm` environment with a required reviewer and permit only `main`. The trusted workflow definition always runs from `main`. A pre-release may package an exact commit from a reviewed draft branch, while a stable release also requires the package source and workflow-triggering commit to be the exact current `main` commit. The workflow confirms that the selected source branch still points to the requested full commit SHA, checks out that SHA, runs `verify:package`, validates the requested version and confirmation text, packs the reviewed output, records its checksum, and passes the same tarball to the protected staging job.
|
|
75
82
|
|
|
76
|
-
npm's automatic provenance identifies the `main` commit which triggered the trusted workflow. For
|
|
83
|
+
npm's automatic provenance identifies the `main` commit which triggered the trusted workflow. For an optional prerelease selected from a draft branch, this identifies the trusted workflow source rather than the packaged source commit. Record and verify the separate `source_ref`, exact package SHA, and tarball checksum before approving the staged version. This provenance distinction is accepted for an immutable prerelease when a consumer check is planned before merge. A stable release requires the workflow and package source to be the same exact `main` commit.
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
When using an optional pre-release, dispatch it from its exact reviewed draft branch commit:
|
|
79
86
|
|
|
80
87
|
```bash
|
|
81
88
|
source_ref=separate-setting-lifecycle
|
|
@@ -91,11 +98,11 @@ gh workflow run publish-npm.yml \
|
|
|
91
98
|
|
|
92
99
|
For a stable release, use `source_ref=main`. The workflow rejects a stable release selected from another branch, rejects a stable release without its trusted workflow commit, and requires the workflow-triggering SHA to equal the packaged `main` SHA. The workflow dispatch itself uses `--ref main` for every release, so an unmerged branch cannot change the trusted publication job or acquire access to the `npm` environment.
|
|
93
100
|
|
|
94
|
-
The workflow always stages to `next`. Inspect the staged package name, version, access, dist-tag, provenance, checksum, files, selected source branch, and source commit before approving
|
|
101
|
+
The workflow always stages to `next`. Inspect the staged package name, version, access, dist-tag, provenance, checksum, files, selected source branch, and source commit before approving publication to npm. After approval publishes the version, fetch that exact registry version and compare its SHA-256, package name and version, and provenance with the reviewed staged artefact and source revision; confirm that `next` points to that version. Install the fetched registry artefact in a clean consumer and run the relevant package checks before requesting promotion. Stage approval and later promotion to `latest` are separate user-authorised operations. Promote the same version only after those registry checks pass and any applicable targeted host checks are complete. If a check fails, leave the published version immutable and prepare a new version. Keep consumer pull requests in draft only while a specifically planned host check is in progress; consumer adoption is not a precondition for Commonlib merge or release.
|
|
95
102
|
|
|
96
103
|
## Publishing a GitHub Release
|
|
97
104
|
|
|
98
|
-
Create a GitHub Release for each stable Commonlib release after the exact registry artefact has passed
|
|
105
|
+
Create a GitHub Release for each stable Commonlib release after the exact registry artefact has passed the Commonlib owner checks and the version has been promoted to `latest`. Complete any applicable targeted host checks before release. Target the exact `main` commit used to build the published package.
|
|
99
106
|
|
|
100
107
|
Protect the GitHub `github-release` environment with a required reviewer and permit only `main`. The manually dispatched workflow first verifies the release with read-only repository access. Only its protected publication job receives `contents: write` access.
|
|
101
108
|
|
|
@@ -18,7 +18,7 @@ import { createNewVaultSettings } from "@vrtmrz/livesync-commonlib/settings";
|
|
|
18
18
|
const initialSettings = createNewVaultSettings();
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
The recommended base currently selects a 50 MB maximum synchronised file size, Rabin–Karp chunk splitting, Plug-in Sync V2, case-insensitive file-name handling, and E2EE V2. Chunk revisions are always derived from their content; the obsolete `doNotUseFixedRevisionForChunks` stored key is retained only for compatibility and is not a recommendation or tweak. The recommended base does not enable synchronisation or encryption on behalf of the user.
|
|
21
|
+
The recommended base currently selects a 50 MB maximum synchronised file size, a `customChunkSize` value of 0, Rabin–Karp chunk splitting, Plug-in Sync V2, case-insensitive file-name handling, and E2EE V2. Chunk revisions are always derived from their content; the obsolete `doNotUseFixedRevisionForChunks` stored key is retained only for compatibility and is not a recommendation or tweak. The recommended base does not enable synchronisation or encryption on behalf of the user.
|
|
22
22
|
|
|
23
23
|
Compared with the conservative stored-setting fallbacks, the current new-Vault object has exactly two semantic differences:
|
|
24
24
|
|
|
@@ -27,15 +27,23 @@ Compared with the conservative stored-setting fallbacks, the current new-Vault o
|
|
|
27
27
|
| `usePluginSyncV2` | `false` | `true` |
|
|
28
28
|
| `handleFilenameCaseSensitive` | normalised from the legacy absent value to `false` | `false` |
|
|
29
29
|
|
|
30
|
-
The other headline recommendations are already the conservative fallbacks: `syncMaxSizeInMB` is 50, `chunkSplitterVersion` is `v3-rabin-karp`, and `E2EEAlgorithm` is `v2`. Data Compression, Eden, V1 dynamic iteration, the legacy IndexedDB adapter, Hidden File Sync, and automatic synchronisation remain disabled when their stored values are absent. Explicit stored values take precedence.
|
|
30
|
+
The other headline recommendations are already the conservative fallbacks: `syncMaxSizeInMB` is 50, `customChunkSize` is 0, `chunkSplitterVersion` is `v3-rabin-karp`, and `E2EEAlgorithm` is `v2`. Data Compression, Eden, V1 dynamic iteration, the legacy IndexedDB adapter, Hidden File Sync, and automatic synchronisation remain disabled when their stored values are absent. Explicit stored values take precedence.
|
|
31
31
|
|
|
32
|
-
Apply a remote-specific preferred object only while configuring that remote. Do not merge it into an existing stored configuration merely because the remote type can be inferred.
|
|
32
|
+
Apply a remote-specific preferred object only while configuring that remote. Do not merge it into an existing stored configuration merely because the remote type can be inferred. Cloudant, self-hosted CouchDB, and Journal Sync setup all use the common `customChunkSize` value of 0. Their unrelated request and bulk settings remain service-specific. The current Doctor regulation no longer recommends changing the value to 60 universally, and existing explicit values remain valid.
|
|
33
|
+
|
|
34
|
+
The new Doctor rule set inherits 1.0.33 and withdraws the Chunk-size rule with
|
|
35
|
+
`customChunkSize: undefined`. Historical regulations keep their original rules.
|
|
36
|
+
This removes the recommendation, rather than deleting a stored setting or
|
|
37
|
+
forcing it to 0. Its consultation version deliberately remains 1.0.33: removing
|
|
38
|
+
a recommendation does not require users to review unchanged recommendations
|
|
39
|
+
again. Existing dismissals remain effective; an explicit forced rescan still
|
|
40
|
+
checks the remaining rules.
|
|
33
41
|
|
|
34
42
|
| Explicitly selected remote | `customChunkSize` | `concurrencyOfReadChunksOnline` | `minimumIntervalOfReadChunksOnline` |
|
|
35
43
|
| --- | ---: | ---: | ---: |
|
|
36
44
|
| Cloudant | 0 | 100 | 333 |
|
|
37
|
-
| Self-hosted CouchDB |
|
|
38
|
-
| Object Storage |
|
|
45
|
+
| Self-hosted CouchDB | 0 | 30 | 25 |
|
|
46
|
+
| Journal Sync (Object Storage) | 0 | 30 | 25 |
|
|
39
47
|
|
|
40
48
|
These are setup-time recommendations, not upgrade migrations. Selecting or detecting a remote does not apply them to an existing configuration unless the person is actively configuring that remote.
|
|
41
49
|
|
|
@@ -72,6 +80,30 @@ Two other values deliberately remain unset until their owning lifecycle supplies
|
|
|
72
80
|
|
|
73
81
|
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
82
|
|
|
83
|
+
## Host storage for device values and configuration
|
|
84
|
+
|
|
85
|
+
The host selects an asynchronous `ValueStore & ValueDeleter` for each application instance and injects it into the setting service as `deviceValues`. Commonlib does not discover `globalThis.localStorage`, create module-global storage, or fall back to another store. `setting.deviceValues` exposes the injected exact-key root. `setting.config` is an asynchronous view over the same root, scoped to the current Vault name and `additionalSuffixOfDatabaseName`; the Service Hub `config` property refers to that same view.
|
|
86
|
+
|
|
87
|
+
For an existing Web Storage layout, pass the selected storage object explicitly and use an empty adapter prefix so the service can address existing raw keys:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { createWebStorageValueStore } from "@vrtmrz/value-store/web-storage";
|
|
91
|
+
|
|
92
|
+
const deviceValues = createWebStorageValueStore(window.localStorage, { prefix: "" });
|
|
93
|
+
// Supply deviceValues as the setting service's required composition dependency.
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use `deviceValues` for exact device-local keys, including existing keys such as `ls-setting-passphrase`. Use `config` for logical configuration keys; the service retains the established Vault and database-suffix key format. For example, the `checkpoint` key for Vault `notes` remains `notes--checkpoint` with an empty suffix and `notes-team-checkpoint` with suffix `team`. Keep the existing key names and await every read, write, and deletion:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const passphrase = await setting.deviceValues.getValue("ls-setting-passphrase");
|
|
100
|
+
const checkpoint = await setting.config.getValue("checkpoint");
|
|
101
|
+
await setting.config.setValue("checkpoint", "revision-42");
|
|
102
|
+
await setting.config.delete("checkpoint");
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`getValue` returns `null` when a key is absent. Use `getObject` and `setObject` for values stored as JSON; Commonlib does not automatically reinterpret old strings or migrate entries between the exact-key root and the scoped view.
|
|
106
|
+
|
|
75
107
|
## Preparing settings for persistence and Markdown
|
|
76
108
|
|
|
77
109
|
The existing `SettingService` provides `changeConfigurationEncryption(store, passphrase?)` for hosts which edit the configuration encryption mode or device-local custom key. Await it before marking those edits as saved. It prepares one wrapper key for connection credentials, the E2EE passphrase, remote profile URIs, and the independent ID key, and serialises the change with ordinary settings saves. It rejects empty keys and unreadable existing protected items. A failed write attempts to restore the previous device key and does not send a success event. The device key and settings document use separate host writes, so this is not a guarantee of rollback after process termination or an uncertain persistence error.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vrtmrz/livesync-commonlib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
|
@@ -92,6 +92,11 @@
|
|
|
92
92
|
"import": "./dist/setupUri.js",
|
|
93
93
|
"default": "./dist/setupUri.js"
|
|
94
94
|
},
|
|
95
|
+
"./ui-commands": {
|
|
96
|
+
"types": "./dist/uiCommands.d.ts",
|
|
97
|
+
"import": "./dist/uiCommands.js",
|
|
98
|
+
"default": "./dist/uiCommands.js"
|
|
99
|
+
},
|
|
95
100
|
"./compat/API/processSetting": {
|
|
96
101
|
"types": "./dist/API/processSetting.d.ts",
|
|
97
102
|
"import": "./dist/API/processSetting.js",
|
|
@@ -457,11 +462,6 @@
|
|
|
457
462
|
"import": "./dist/services/base/AppLifecycleService.js",
|
|
458
463
|
"default": "./dist/services/base/AppLifecycleService.js"
|
|
459
464
|
},
|
|
460
|
-
"./compat/services/base/ConfigService": {
|
|
461
|
-
"types": "./dist/services/base/ConfigService.d.ts",
|
|
462
|
-
"import": "./dist/services/base/ConfigService.js",
|
|
463
|
-
"default": "./dist/services/base/ConfigService.js"
|
|
464
|
-
},
|
|
465
465
|
"./compat/services/base/ControlService": {
|
|
466
466
|
"types": "./dist/services/base/ControlService.d.ts",
|
|
467
467
|
"import": "./dist/services/base/ControlService.js",
|
|
@@ -522,11 +522,6 @@
|
|
|
522
522
|
"import": "./dist/services/implements/base/UIService.js",
|
|
523
523
|
"default": "./dist/services/implements/base/UIService.js"
|
|
524
524
|
},
|
|
525
|
-
"./compat/services/implements/browser/ConfigServiceBrowserCompat": {
|
|
526
|
-
"types": "./dist/services/implements/browser/ConfigServiceBrowserCompat.d.ts",
|
|
527
|
-
"import": "./dist/services/implements/browser/ConfigServiceBrowserCompat.js",
|
|
528
|
-
"default": "./dist/services/implements/browser/ConfigServiceBrowserCompat.js"
|
|
529
|
-
},
|
|
530
525
|
"./compat/services/implements/headless/HeadlessAPIService": {
|
|
531
526
|
"types": "./dist/services/implements/headless/HeadlessAPIService.d.ts",
|
|
532
527
|
"import": "./dist/services/implements/headless/HeadlessAPIService.js",
|
|
@@ -675,6 +670,9 @@
|
|
|
675
670
|
"setup-uri": [
|
|
676
671
|
"dist/setupUri.d.ts"
|
|
677
672
|
],
|
|
673
|
+
"ui-commands": [
|
|
674
|
+
"dist/uiCommands.d.ts"
|
|
675
|
+
],
|
|
678
676
|
"compat/API/processSetting": [
|
|
679
677
|
"dist/API/processSetting.d.ts"
|
|
680
678
|
],
|
|
@@ -894,9 +892,6 @@
|
|
|
894
892
|
"compat/services/base/AppLifecycleService": [
|
|
895
893
|
"dist/services/base/AppLifecycleService.d.ts"
|
|
896
894
|
],
|
|
897
|
-
"compat/services/base/ConfigService": [
|
|
898
|
-
"dist/services/base/ConfigService.d.ts"
|
|
899
|
-
],
|
|
900
895
|
"compat/services/base/ControlService": [
|
|
901
896
|
"dist/services/base/ControlService.d.ts"
|
|
902
897
|
],
|
|
@@ -933,9 +928,6 @@
|
|
|
933
928
|
"compat/services/implements/base/UIService": [
|
|
934
929
|
"dist/services/implements/base/UIService.d.ts"
|
|
935
930
|
],
|
|
936
|
-
"compat/services/implements/browser/ConfigServiceBrowserCompat": [
|
|
937
|
-
"dist/services/implements/browser/ConfigServiceBrowserCompat.d.ts"
|
|
938
|
-
],
|
|
939
931
|
"compat/services/implements/headless/HeadlessAPIService": [
|
|
940
932
|
"dist/services/implements/headless/HeadlessAPIService.d.ts"
|
|
941
933
|
],
|
|
@@ -1013,6 +1005,7 @@
|
|
|
1013
1005
|
"@smithy/types": "^4.14.3",
|
|
1014
1006
|
"@smithy/util-retry": "^4.4.5",
|
|
1015
1007
|
"@trystero-p2p/nostr": "0.25.3",
|
|
1008
|
+
"@vrtmrz/value-store": "0.1.0",
|
|
1016
1009
|
"diff-match-patch": "^1.0.5",
|
|
1017
1010
|
"events": "^3.3.0",
|
|
1018
1011
|
"fflate": "^0.8.2",
|
|
@@ -1024,9 +1017,11 @@
|
|
|
1024
1017
|
"pouchdb-adapter-idb": "^9.0.0",
|
|
1025
1018
|
"pouchdb-adapter-indexeddb": "^9.0.0",
|
|
1026
1019
|
"pouchdb-adapter-memory": "^9.0.0",
|
|
1020
|
+
"pouchdb-checkpointer": "9.0.0",
|
|
1027
1021
|
"pouchdb-core": "^9.0.0",
|
|
1028
1022
|
"pouchdb-errors": "^9.0.0",
|
|
1029
1023
|
"pouchdb-find": "^9.0.0",
|
|
1024
|
+
"pouchdb-generate-replication-id": "9.0.0",
|
|
1030
1025
|
"pouchdb-mapreduce": "^9.0.0",
|
|
1031
1026
|
"pouchdb-merge": "^9.0.0",
|
|
1032
1027
|
"pouchdb-replication": "^9.0.0",
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { IConfigService } from "./IService.js";
|
|
2
|
-
import { ServiceBase, type ServiceContext } from "./ServiceBase.js";
|
|
3
|
-
export declare abstract class ConfigService<T extends ServiceContext = ServiceContext> extends ServiceBase<T> implements IConfigService {
|
|
4
|
-
abstract getSmallConfig(key: string): string | null;
|
|
5
|
-
abstract setSmallConfig(key: string, value: string): void;
|
|
6
|
-
abstract deleteSmallConfig(key: string): void;
|
|
7
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ConfigService } from "../../base/ConfigService.js";
|
|
2
|
-
import type { IAPIService, ISettingService } from "../../base/IService.js";
|
|
3
|
-
import type { ServiceContext } from "../../base/ServiceBase.js";
|
|
4
|
-
import { createInstanceLogFunction } from "../../lib/logUtils.js";
|
|
5
|
-
export interface ConfigServiceBrowserCompatDependencies {
|
|
6
|
-
settingService: ISettingService;
|
|
7
|
-
APIService: IAPIService;
|
|
8
|
-
}
|
|
9
|
-
export declare class ConfigServiceBrowserCompat<T extends ServiceContext = ServiceContext> extends ConfigService<T> {
|
|
10
|
-
private _settingService;
|
|
11
|
-
_log: ReturnType<typeof createInstanceLogFunction>;
|
|
12
|
-
constructor(context: T, dependencies: ConfigServiceBrowserCompatDependencies);
|
|
13
|
-
getSmallConfig(key: string): string;
|
|
14
|
-
setSmallConfig(key: string, value: string): void;
|
|
15
|
-
deleteSmallConfig(key: string): void;
|
|
16
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { ConfigService } from "../../base/ConfigService.js";
|
|
2
|
-
import { createInstanceLogFunction } from "../../lib/logUtils.js";
|
|
3
|
-
class ConfigServiceBrowserCompat extends ConfigService {
|
|
4
|
-
_settingService;
|
|
5
|
-
_log;
|
|
6
|
-
constructor(context, dependencies) {
|
|
7
|
-
super(context);
|
|
8
|
-
this._settingService = dependencies.settingService;
|
|
9
|
-
this._log = createInstanceLogFunction("ConfigService", dependencies.APIService);
|
|
10
|
-
}
|
|
11
|
-
getSmallConfig(key) {
|
|
12
|
-
return this._settingService.getSmallConfig(key);
|
|
13
|
-
}
|
|
14
|
-
setSmallConfig(key, value) {
|
|
15
|
-
return this._settingService.setSmallConfig(key, value);
|
|
16
|
-
}
|
|
17
|
-
deleteSmallConfig(key) {
|
|
18
|
-
return this._settingService.deleteSmallConfig(key);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export {
|
|
22
|
-
ConfigServiceBrowserCompat
|
|
23
|
-
};
|