Skip to main content

Module linkmd

Module linkmd 

Source
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:

verbbinding
resolveGET /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
grantGET / POST /api/hub/brains/<brain>/grants, DELETE /api/hub/brains/<brain>/grants/<id>
proposePOST /api/hub/sites/<handle>/inbox — evidence in, without trust (unauthenticated by design)
subscribeGET /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:

  1. the --hub <URL> flag,
  2. the DBMD_HUB_URL environment variable,
  3. the hub = <URL> line in the store-local .dbmd/config file (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. brain is 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.
PullReport
What a pull materialized.

Enums§

AddressTarget
What the part after @brain/ names.
Capability
The two capabilities a v0 hub enforces.
LinkError
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 propose submission 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-file from file metadata without reading it.

Functions§

collect_push_files
Collect the files a push sends: the store’s owned text — DB.md, assets.jsonl when present, and every content .md under records/ and sources/ (the store walk, which already excludes hidden dirs like .dbmd/, the log/ archive, and derived index.* 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 brain to grantee — a hub principal named by email in v0 (the protocol’s near-term simplification; key-named grantees arrive with the signing layer). scope is a store-path prefix (the hub’s enforcement unit); until an 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. subscribe polls this as movement detection; the caller re-pulls or re-queries after an advance.
hub_config
Resolve the client configuration: flag_hub beats HUB_URL_ENV beats the hub = line in <dir>/.dbmd/config; no fallback default exists. The credential comes from HUB_KEY_ENV alone and is validated as a clean header token (never echoed on failure).
is_valid_handle
A published-site handle (the propose target). Same lexical shape as a slug.
propose
Submit body to the published site handle, addressed to its app page app (a page that declares the write-inbox capability). Deliberately unauthenticated — this is the cross-party door; the submission lands as evidence in the owner’s sources/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 @brain returns 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>.md return the full record, frontmatter + body.
safe_store_rel_path
True when p is 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 brain to out (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 in extra_local instead). Returns the report; rebuilding the local index catalog afterwards is the caller’s (cheap, optional) step.
sync_push
Push files to brain as 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§

LinkResult
Result alias for link.md client operations.