Future Sync and Extension Platform
Sync model
The app owns the local source of truth and its full revision graph. This document is a future-design reference, not an initial-release feature specification. Release 1 ships no sync coordinator, destination adapter, connection settings, transfer queue, or plugin runtime. It preserves a small set of contracts and data boundaries so later work can introduce those components without breaking local data.
future workflow:
local edit -> transaction: current note + immutable revision + outbox event
|
sync coordinator
|
+------------------------------+------------------------------+
| |
history-aware destination file/current-state destination
can exchange revision graph exchanges current .md + metadata
Placeholder contract for future destinations
Every future destination should declare a capability document rather than relying on its name or implementation type. These declarations may live as documentation/types in Release 1, but no adapter executes them.
| Capability | Meaning |
|---|---|
remoteHistory | Destination stores and returns immutable revisions/parents |
remoteTombstones | Destination can propagate deletions safely |
stableItemIds | Files/items keep a stable identity across rename/move |
changeTokens | Destination can provide incremental change discovery |
atomicWrite | Destination can commit an item without exposing partial content |
backgroundSync | Adapter can operate under the platform’s background constraints |
bidirectional | Adapter can both upload and import changes |
conflictSignals | Adapter exposes version/ETag/precondition information |
When implemented, the coordinator must use conservative behavior when a capability is unavailable. For example, a folder destination without remoteHistory must not claim remote version recovery, and a destination without conflictSignals should surface potentially concurrent changes instead of overwriting them optimistically.
Future adapter operations
The API should use domain-neutral values and avoid exposing database entities directly. A minimum contract includes:
describeCapabilities()— return the capability document and user-facing destination description.authorize()/deauthorize()— obtain and remove access; secrets remain platform-owned.discover(cursor)— list remote changes incrementally where supported, or perform a bounded scan.fetch(item)— retrieve a current document or revision payload.push(change, precondition)— write a change, with a remote version precondition when supported.delete(item, precondition)— propagate tombstones when supported.getStatus()— report connection health, last action, retryability, and user action needed.
Define transfer payload versions from the first implementation. Future apps must be able to recognize an unsupported payload and leave data intact rather than corrupting it.
Future sync lifecycle
- Local commit: save note and revision; enqueue an idempotent outbox event.
- Discovery: collect destination changes using a change token, version manifest, or constrained folder scan.
- Reconciliation: identify items using stable note IDs; compare revision parent/hash/version metadata.
- Apply: fast-forward safe remote changes or stage conflicts; never replace an unacknowledged local change.
- Upload: push queued local changes with preconditions when available.
- Acknowledge: update per-destination metadata only after the remote action succeeds.
- Report: expose pending count, last successful completion, meaningful warnings, and recovery actions.
Make operations idempotent. Sync may be interrupted, retried, or run concurrently by foreground and background scheduling.
Future Android local-folder sync extension
This is the planned first sync extension and should act as the reference implementation for the extension contract when that future phase begins.
User setup
- User selects a folder through Android’s Storage Access Framework.
- The app stores the persistable permission URI and validates read/write access.
- The extension writes a small app manifest (for example
.notes-app-manifest.json) in the selected root to identify its managed layout and format version. - The user is told that the folder preserves current Markdown notes, not the app’s complete revision history.
File behavior
- Export every current, non-deleted note as deterministic
.mdwith portable front matter. - Do not modify files outside the extension’s managed directory/layout.
- Write via a temporary file plus replace/rename if the selected provider supports it; otherwise verify the completed content hash after write.
- Detect changed files by metadata/hash and import them as new local revisions.
- Treat an externally deleted managed file as a potential deletion request only after clear conflict checks; offer a safe confirmation/recovery path.
- Keep a local mapping of note ID to provider document URI/version. Do not depend on filenames as identity.
Limitations to state explicitly
- Folder copies/backups may retain historical versions, but the app cannot assume or manage them.
- Concurrent edits on two devices can create conflicts; the future implementation must preserve both local and imported content rather than auto-merging silently.
- Android background folder access and provider behavior vary. Failed background work must be retryable from the app.
Extension strategy
Release 1: placeholder only
Ship only documented/stubbed capability and extension contracts where they help preserve module boundaries. Do not package an extension registry, Android local-folder implementation, destination configuration, or third-party plugin runtime. This avoids premature lifecycle and security commitments while retaining a clear implementation path.
Future Android distribution
Consider separately installed Android companion apps or signed packages only after defining:
- signature/trust policy and compatibility/version negotiation;
- narrow IPC contracts and permission grants;
- install/update/disable behavior;
- background execution and crash isolation;
- privacy disclosure, review, and revocation UX.
iOS constraint
iOS does not support arbitrary code plugins in the same model. On iOS, extensions should be built-in integrations, app extensions where Apple permits them, or protocol-compatible sync services. The shared capability contract still applies, but distribution is platform-specific.
For the broader set of expected plugin categories—templates/capture, metadata-driven views, research integrations, automation, and AI—see the extension design reference. These surfaces should use their own narrow contracts rather than overloading the sync API.
Future cloud destination requirements
Before committing to cloud sync, select a conflict model and threat model. A suitable history-aware cloud destination should support stable item IDs, revision parent links, change tokens, conditional writes, tombstones, and encrypted transport. If end-to-end encryption is required, design key generation, recovery, device enrollment, metadata leakage, sharing limits, and multi-device conflict recovery before implementation.