No description
Find a file
2026-07-17 06:56:53 +00:00
.github/workflows fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00
scripts fix: emit per-asset release provenance 2026-07-17 04:45:31 +00:00
src fix: keep children pending behind stale parents 2026-07-16 11:32:17 +00:00
test fix: keep children pending behind stale parents 2026-07-16 11:32:17 +00:00
.editorconfig feat: add revision-safe central vault sync plugin 2026-07-13 03:03:03 +00:00
.gitignore feat: add revision-safe central vault sync plugin 2026-07-13 03:03:03 +00:00
.npmrc feat: add revision-safe central vault sync plugin 2026-07-13 03:03:03 +00:00
esbuild.config.mjs fix: emit per-asset release provenance 2026-07-17 04:45:31 +00:00
eslint.config.mts perf: accelerate large vault bootstrap with live progress 2026-07-16 09:53:08 +00:00
LICENSE feat: add revision-safe central vault sync plugin 2026-07-13 03:03:03 +00:00
manifest.json fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00
package-lock.json fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00
package.json fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00
README.md fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00
SECURITY.md docs: disclose SecretStorage keychain fallback 2026-07-13 05:23:24 +00:00
styles.css fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00
tsconfig.json feat: add revision-safe central vault sync plugin 2026-07-13 03:03:03 +00:00
version-bump.mjs fix: emit per-asset release provenance 2026-07-17 04:45:31 +00:00
versions.json fix: omit incompatible review attestations 2026-07-17 06:56:53 +00:00

Central Vault Sync

Revision-safe two-way synchronization between an Obsidian vault and a self-hosted WebObsidian server. The server is authoritative: every accepted mutation receives a stable entry identity, revision, content hash, and ordered journal sequence.

Community review release: 0.1.22 is the current normal GitHub review release for directory scanning and backed-up testing. It is not yet listed in Community Plugins. Use the validation checklist for feedback; never post credentials, private vault content, or unredacted diagnostics.

Safety properties

  • Never silently overwrites a stale server revision.
  • Publishes durable local operations before pulling newer remote bytes, so the server can merge or preserve both versions.
  • Uses deterministic three-way merge only for independent UTF-8 text edits; overlaps and binary divergence become conflict copies.
  • Persists queue markers, blob-reference operations, cursor, and apply intents before acknowledging work.
  • Verifies every downloaded and uploaded file by SHA-256 and byte length.
  • Suppresses remote-apply echoes by expected path and hash, not a timer-only flag.
  • Defers remote replacement, rename, or deletion while the affected path has durable local work or an unsaved open editor; overlapping edits become server conflict copies rather than disappearing.
  • Keeps credentials out of the vault and plugin data.json through Obsidian SecretStorage.
  • Shows live aggregate recovery, manifest, scan, upload, publication, apply, and finalization progress without exposing paths or note content.
  • Uses at most four concurrent uploads and capability-gated ordered operation batches; older servers safely fall back to one operation per request.

Requirements

  • Obsidian 1.11.4 or newer on desktop, Android, or iOS.
  • A reachable WebObsidian server with Central Sync Protocol 1.0.
  • HTTPS for every non-loopback server URL.
  • A 10-minute one-use pairing code created in WebObsidian Settings → Central Sync.

Install for local testing

  1. Run npm install && npm run check.
  2. Copy main.js, manifest.json, and styles.css to: <vault>/.obsidian/plugins/central-vault-sync/.
  3. Reload Obsidian and enable Central Vault Sync in Community plugins.
  4. Open plugin settings, enter the server URL, device name, and one-use pairing code.
  5. Run Central Vault Sync: Sync now from the command palette.

A public release attaches those same three files to a GitHub release whose tag exactly matches manifest.json.

Behavior

  • Initial load waits for Obsidian's workspace layout, uses indexed projection lookups, skips persistence for unchanged files, yields every 100 paths, reconciles durable local work, then applies ordered changes.
  • WebSocket messages are sequence-only wake-ups. REST manifest/change/file/blob endpoints remain authoritative.
  • Fallback polling runs while the app is active; reconnect uses bounded exponential backoff.
  • Create, modify, rename, delete, attachments, empty folders, Unicode paths, and case-sensitive identities use the native Vault API.
  • Local editor bursts debounce for 750 ms by default. Rename/modify bursts preserve the original identity, commit rename first, and rehash the destination; rename/delete collapses safely to deletion of the original identity. Plugin unload attempts to flush and always leaves a durable marker for unfinished paths.
  • Status refreshes the authoritative unresolved-conflict count after startup, every successful sync, and each resolution. Commands: Sync now, Pause or resume, View status, View conflicts, Reconnect, and Reset local sync state.

Mobile lifecycle

Mobile operating systems suspend background apps. This plugin does not promise sync while suspended. It catches up on plugin load, app focus, visible foreground, active-leaf changes, reconnect, and manual sync. Files at or above the configurable threshold (100 MiB by default) require confirmation before download on mobile.

Exclusions

The server always excludes the configured Obsidian settings directory, .git/**, .trash/**, temporary/editor files, OS metadata, and Central Sync internals. Device-specific exclude globs may be stricter but can never re-include server exclusions. Workspace layout remains device-local.

Conflicts

The status bar and notices report unresolved conflicts without blocking unrelated files. Open WebObsidian Settings → Central Sync to compare base/server/client text, edit a merged result, choose either winner, retain both copies, or download both binary versions. Canonical server bytes remain unchanged until an explicit resolution.

Privacy and network behavior

  • Connects only to the server URL configured by the user.
  • Enumerates folders and files in the vault during startup reconciliation so it can detect local work, compare the durable projection, and apply exclusions. It does not use enumeration to access files outside the vault.
  • Sends vault file paths, content/hashes, device name, revisions, queue operations, acknowledgements, pairing exchange, and diagnostics needed for synchronization.
  • Clipboard access is write-only and occurs only when the user explicitly selects Copy redacted diagnostics. The plugin writes its redacted diagnostic text and never reads existing clipboard content.
  • Does not use analytics, advertising, telemetry, third-party APIs, or remote code execution.
  • The device bearer token is stored only through Obsidian SecretStorage and is never written to plugin data, logs, diagnostics, or the vault. Encryption at rest depends on a working platform keychain; Obsidian shows its own warning and may use an unencrypted fallback when no secret store is available. Configure a keychain on shared/untrusted systems.
  • Redacted diagnostics include server origin, device/vault IDs, cursor/queue counts, platform flags, exclusions, and sanitized errors; they exclude credentials and note content.
  • Server administrators can revoke a device immediately.

See SECURITY.md for reporting and threat-model details.

Development

npm install
npm run check

The plugin consumes the public, exact @picassio/sync-core@0.1.3 package used by the server, browser, and headless client; protocol code is not duplicated in this repository.

License

MIT — see LICENSE.