Skip to content

feat(channel): port couch account channel client from obsidian#16

Merged
vreshch merged 1 commit into
masterfrom
feat/couch-channel
Jul 6, 2026
Merged

feat(channel): port couch account channel client from obsidian#16
vreshch merged 1 commit into
masterfrom
feat/couch-channel

Conversation

@vreshch

@vreshch vreshch commented Jul 6, 2026

Copy link
Copy Markdown
Member

What

Ports the shipped, adversarially-hardened couch sync channel client from the Obsidian plugin (agentage/obsidian-sync) into memory-core as a transport-agnostic src/channel/ module, so the CLI daemon (and later VS Code) reuse the exact replicator the plugin ships.

The wire behavior is a faithful port - the doc model stays byte-compatible with the plugin so the server bridge reassembles either client's writes. Only the runtime edges are adapted to injected seams (no Obsidian, no node:fs, no HTTP lib).

Module (src/channel/)

File Job
couch-doc.ts pure content-addressed doc model (WebCrypto sha256, 64KiB UTF-8 chunking, leaf h:<hash> + file f:<path> docs)
couch-token.ts CouchTokenClient - mint/cache the couch JWT, re-mint 60s before expiry, invalidate()
couch-state.ts resume state (cursor + rev cache + pending queue) behind an injected CouchStatePersistence
couch-sync.ts CouchSync - paged pull / bulk push / delete over an injected FileStore + fetch
resolve-host.ts /.well-known/agentage-sync parser + channelForVault (degrades to git)
http.ts minimal FetchLike seam (a host injects globalThis.fetch)

Injected edges (only deviations from the plugin)

  • Obsidian Vault/TFile -> FileStore { listMarkdown, read, write, remove } (vault-relative POSIX).
  • Obsidian requestUrl -> injected FetchLike.
  • Plugin saveData -> CouchStatePersistence { load, save } (CLI = JSON file); createCouchState() awaits the async load.
  • window.setTimeout suppress-clear -> global setTimeout().unref() (isomorphic).

Core wire behavior unchanged: missing leaf on pull throws and aborts the page (cursor not advanced), no-op push skips the network, _bulk_docs {new_edits:false} + PUT f:<path>, 401 -> re-mint + retry once, pending-push queue.

Tests

41 new tests (145 total, all green). Includes a byte-for-byte doc-model lock with literal leaf ids/revs cross-checked against the plugin's own test vectors, plus the hardening cases (missing-leaf abort, paged cursor persist, zero-fetch no-op push, rejected-push-not-cached, queue flush, 401 retry, channel degradation).

Release

Bumps 0.2.0 -> 0.3.0 (additive minor). Publishes on squash-merge to master via the chore(release) subject.

Transport-agnostic CouchDB replicator (fetch + FileStore + persistence
injected): content-addressed doc model, resumable paged pull, token
mint/cache, host resolution. Byte-compatible with the obsidian plugin's
wire model. Adds 41 tests. Bumps 0.2.0 -> 0.3.0.
@vreshch vreshch marked this pull request as ready for review July 6, 2026 15:34
@vreshch vreshch merged commit 6c2fd8d into master Jul 6, 2026
1 check passed
@vreshch vreshch deleted the feat/couch-channel branch July 6, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant