Expand description
The link.md client — the five interconnect verbs dbmd speaks against
a hub: resolve, sync, grant, propose, subscribe.
One binary, two specs (the git precedent: one binary carries both the
object format and the wire protocol). The db.md FORMAT is untouched by this
module: a store never needs link.md to be valid db.md, record files stay
plain markdown, and SPEC.md reserves only the @brain/id address shape.
Everything with a wire or a trust boundary — addressing across stores,
pulling/pushing a hosted copy, capability grants, the propose door, feed
polling and signed-entry verification — lives here, as a client
capability, never a format requirement.
§What this client speaks
The v0 HTTP binding a hub serves under its base URL:
| verb | binding |
|---|---|
resolve | GET /api/hub/brains/<brain> (the brain card) and GET /api/hub/brains/<brain>/resolve?id=… / ?path=… (a record) |
sync (pull) | GET /api/hub/brains/<brain>/export?format=pack — an immutable pack, or the granted slice as plain files |
sync (push) | POST /api/hub/brains/<brain>/push for small snapshots; presign/upload/commit for large snapshots |
grant | GET / POST /api/hub/brains/<brain>/grants, DELETE /api/hub/brains/<brain>/grants/<id> |
propose | POST /api/hub/sites/<handle>/inbox — evidence in, without trust (unauthenticated by design) |
subscribe | GET /api/hub/brains/<brain> + /feed for a locally verified signed head |
§Configuration — no default hub, credential never in the store
There is no built-in hub endpoint: the toolkit is neutral and a hub is whatever the user points it at. Resolution order for the hub URL:
- the
--hub <URL>flag, - the
DBMD_HUB_URLenvironment variable, - the
hub = <URL>line in the store-local.dbmd/configfile (toolkit state, not store content — the walkers already skip hidden directories, so.dbmd/never syncs, indexes, or validates).
The credential is the DBMD_HUB_KEY environment variable, full stop. It is
deliberately not read from .dbmd/config: a secret inside the store
tree is one commit or one push away from leaking, so the file carries only
non-secret targets and the agent’s environment carries the key.
Non-HTTPS hubs are refused (the bearer key must never travel in cleartext) with a loopback exemption for local development.
§v0 honesty
This client binds to what a hub enforces today: grantees are hub
principals (an email), grant scopes are store-path prefixes, pushes are
whole-store snapshots, and subscribe reports feed-head movement. The hub
signs each committed snapshot in a hash-chained feed with a per-brain
Ed25519 identity; this client verifies the content-addressed pack before it
touches disk and verifies the signed feed head on every subscription read.
Structs§
- Address
- A parsed
@brain[/target]address.brainis a hub brain reference — the brain’s ULID id (works for any caller, including cross-party on a public brain) or a slug (which a hub resolves only against the caller’s own brains; slugs are unique per owner, not globally). - Head
- One observation of a brain’s feed head.
- HubConfig
- The resolved client configuration for one invocation.
- HubResponse
- One hub response: the status plus the parsed JSON body when there was one.
- Pull
Report - What a pull materialized.
Enums§
- Address
Target - What the part after
@brain/names. - Capability
- The two capabilities a v0 hub enforces.
- Link
Error - Everything that can go wrong on the wire or at its edges. Each variant maps onto one stable CLI error code; messages are single-line and never echo the credential.
Constants§
- CONFIG_
REL_ PATH - The store-local config file, relative to the store root. Holds non-secret
toolkit state (
hub = <URL>); hidden, so every store walk skips it. - HUB_
KEY_ ENV - Environment variable carrying the hub bearer credential. The one and only credential source — see the module docs for why it is never file-based.
- HUB_
URL_ ENV - Environment variable naming the hub base URL (e.g.
https://hub.example.com). - MAX_
PROPOSE_ BYTES - The hub’s inbox cap on one
proposesubmission body, mirrored client-side so an oversized body fails before the upload, not after (the same fail-before-upload contract as the push caps). Public so the CLI can pre-check a--body-filefrom file metadata without reading it.
Functions§
- collect_
push_ files - Collect the files a push sends: the store’s owned text —
DB.md,assets.jsonlwhen present, and every content.mdunderrecords/andsources/(the store walk, which already excludes hidden dirs like.dbmd/, thelog/archive, and derivedindex.*catalogs; the hub derives its own index, and local history stays local). Returns(store-relative path, content)pairs, path-sorted. - grant_
issue - Issue (or refresh) a grant on
braintograntee— a hub principal named by email in v0 (the protocol’s near-term simplification; key-named grantees arrive with the signing layer).scopeis a store-path prefix (the hub’s enforcement unit);untilan ISO 8601 expiry, absent = until revoked. - grant_
list - List the active grants (and pending invites) on
brain. Owner-side. - grant_
revoke - Revoke a grant (or cancel a pending invite) by id. Owner-side; revocation is soft on the hub (the audit trail survives).
- head
- Read and locally verify the brain’s current signed feed head.
subscribepolls this as movement detection; the caller re-pulls or re-queries after an advance. - hub_
config - Resolve the client configuration:
flag_hubbeatsHUB_URL_ENVbeats thehub =line in<dir>/.dbmd/config; no fallback default exists. The credential comes fromHUB_KEY_ENValone and is validated as a clean header token (never echoed on failure). - is_
valid_ handle - A published-site handle (the
proposetarget). Same lexical shape as a slug. - propose
- Submit
bodyto the published sitehandle, addressed to its app pageapp(a page that declares thewrite-inboxcapability). Deliberately unauthenticated — this is the cross-party door; the submission lands as evidence in the owner’ssources/inbox/, never as truth, and the owner’s curator accepts or rejects it. Returns the hub’s{id, path}receipt. - resolve
- Resolve an address. A bare
@brainreturns the brain card (metadata + index stats — the v0 form of the card; keys arrive with the protocol’s signing layer).@brain/<id>and@brain/<path>.mdreturn the full record, frontmatter + body. - safe_
store_ rel_ path - True when
pis a store-relative path this client will read from or write to disk: relative, no.., no empty or dot-leading segment (which shields.dbmd/and.git/), and only the hub-portable character set. Applied to every path an export hands us (the hub is not trusted with local layout) and to every path a push sends (mirroring the hub’s own gate). - sync_
pull - Pull the granted slice of
braintoout(default:./<slug>). Every exported path is safety-gated before it touches disk; files are written atomically; nothing local is ever deleted (locals the export lacks are reported inextra_localinstead). Returns the report; rebuilding the local index catalog afterwards is the caller’s (cheap, optional) step. - sync_
push - Push
filestobrainas a whole-store snapshot — the hub’s push semantics: the hosted copy becomes exactly this set (pull first if the hosted side may have records the local copy lacks). Client-side caps mirror the hub’s JSON-path limits so an oversized push fails before the upload.
Type Aliases§
- Link
Result - Result alias for link.md client operations.