Local-first sync for an Obsidian vault, in Rust, over iroh
dragon-glass docs roadmap.md
5.6 kB
Markdown
at main

Roadmap #

What shipped, when, and what's genuinely not built yet. For the full reasoning behind any specific decision, see decisions.md; for the behaviour catalogue itself, see behaviors.md.

Shipped #

Date Commits What
2026-07-28 – 29 473ce8a, c624473 Design, behaviour catalogue, and workspace skeleton — written before any code, so "done" has a mechanical definition
2026-08-04 cfd44fb .. 96d2f18 Local engine: VaultPath, the index data model, a real filesystem scanner, content-addressed blob storage with append-only history and GC, atomic apply/restore, the watcher — one machine can index a vault, store its contents, and recover any prior version, no network
2026-08-16 a9b136a, 5aa0bd1 Fixed a real bootstrap bug: an NFD-spelled filename was indexed but its content never stored, since the disk path was reconstructed from the canonical NFC spelling rather than resolved against what's actually there
2026-08-16 6be1d03 .. 12ca487 Sync protocol: pure reconciliation (core::plan), a simulated multi-device mesh proven to converge under proptest, the versioned wire format, a real iroh endpoint (gossip + blob transfer), and a daemon that reconciles against a real peer — shadow mode throughout, nothing written yet
2026-08-16 c335f74, d82bf66 Writes turned on for real: a computed plan can now be applied to disk (Engine::apply_plan), and the two separate blob stores (iroh-blobs' and dragon-glass's own on-disk one) are bridged explicitly
2026-08-18 62eb0e7 Live sync, in full: a real daemon event loop, gossip-triggered propagation (not just periodic polling), corrupted-index recovery, offline mode, large-file admission control, archive snapshots, a signed device roster, a Unix control socket, and a working dragon-glass-cli — verified against two real daemons over real iroh, not mocked
2026-08-19 0a33bcf Fixed the daemon being unable to start on a stock Mac at all — the control socket's natural path (beside the index) was one byte over macOS's Unix-socket path limit; moved to a short, dedicated runtime directory
2026-08-19 43dbe18, 44dfbfd dragon-glass-cli install/uninstall — the daemon runs as a persistent systemd/launchd service instead of a hand-run process
2026-08-19 a856ddb Found running two vaults on one already-live machine: the wire protocol had no notion of which vault a connection was about, so any two reachable daemons — including two vaults sharing one machine's device identity — would merge indices regardless. Fixed by scoping every message to a vault_id, checked before the payload is ever touched
2026-08-19 4683bca Two things a synthetic test vault never surfaced that a real one did: Google Drive's own upload-staging directory needed excluding from sync, and the vault-identity rule above got written down properly

just coverage: 99/103. NET-1 and BOOT-6 are permanently-open notes — real informal evidence collected (see decisions.md's "Corrected along the way" and "direct connections" entries) without the harder formal half ever being worth chasing down. SAFE-7 is a pre-existing gap outside anything built so far. SVC-4 (a persistent service actually starts and stops) is verified by hand against a real systemctl/launchctl, not a unit test — there's nothing to grep for.

Currently in progress: real day-to-day use across a Mac, two Linux boxes, and a NAS, running in parallel with the git-based backup this project exists to replace. See decisions.md for why that mitigation replaced the original shadow-mode-against-git-history plan.

Not yet built #

  • Interactive pairing (dragon-glass pair [code]). The mechanism it would call — signing, verification, tamper detection — is built and tested (roster.rs); what's missing is the live two-daemon handshake. Today, pairing is manual: copy each machine's printed ticket into the other's config.toml.
  • dragon-glass log / dragon-glass conflicts. Both are stubbed with an honest "not implemented" rather than a fake answer — neither has a queryable data model behind it yet (a sync activity log, a conflict list).
  • Faster reconnect after sleep/wake. A laptop coming back online currently waits for the next periodic dial (up to 30s) rather than reacting to the OS's own wake notification.
  • Obsidian status-bar plugin (TypeScript, over the control socket) and any conflict-resolution UI that doesn't require a terminal.
  • Multi-arch static musl image for the NAS, and cleaner packaging generally — install/uninstall wrap a dev build today, not a distributed binary.
  • Loro text CRDTs for .md, only if conflict-copy frequency in real use ever justifies the added complexity over per-file version vectors.

Tooling #

Concern Tool Where
Unused dependencies cargo-machete CI, stable toolchain
Unused deps (precise) cargo-udeps occasional, needs nightly
Advisories, licences, duplicate deps cargo-deny CI
Dead code within a crate rustc dead_code + unreachable_pub lints compile
Public API drift cargo-public-api pre-release
Unused files/exports/deps in TS knip once the status-bar plugin exists

knip is JS/TS-only and has nothing to analyse in a Rust workspace yet — worth wiring in the moment the first package.json appears (the status-bar plugin above), not before.