Synapse: Discovery Without a Registry

by CMN Contributors

A federated indexer for the Code Mycelial Network — pulse ingestion, Nostr relay sync, lineage traversal, and semantic search. No central registry. No trust required.

Package registries are chokepoints. npm, PyPI, crates.io — each one is a single database that every consumer must query and every publisher must trust. When the registry goes down, the ecosystem stops. When the registry is compromised, every downstream consumer inherits the damage. When the registry changes its policies, you comply or leave.

The Code Mycelial Network (CMN) eliminates the registry. Every domain is its own publisher. Every spore is signed by its author and verifiable by anyone. But without a central index, how do you find anything? How do you search across thousands of domains? How does a new participant discover what’s out there?

Synapse is the answer — a federated indexer that any operator can run. It crawls domains, indexes spores, serves queries, and synchronizes with other instances through the Nostr relay network. No single Synapse owns the index. No trust is placed in any instance. Every piece of data is independently verified against the publisher’s public key before it enters the index.

The trust model: verify everything, trust nothing

Synapse is not a cache sitting in front of a trusted source. There is no trusted source. Every manifest that enters the index — spore, mycelium, taste report — arrives as a signed capsule. Synapse verifies both layers:

  1. Core signature — the author’s Ed25519 key signs capsule.core
  2. Capsule signature — the host domain’s key signs the full capsule

The host’s public key is fetched from https://{domain}/.well-known/cmn.json and cached with a TTL. If signature verification fails, the data is rejected. If the domain’s key rotates, the cache expires and the new key is fetched on the next pulse.

This means you can run a Synapse instance, subscribe to public Nostr relays, ingest thousands of events from domains you’ve never heard of, and every single one is cryptographically verified before it touches your index. A compromised relay cannot inject false data. A malicious Synapse instance cannot poison your index. The signatures are end-to-end.

Four data channels

Data enters a Synapse instance through four independent channels:

SourceMechanism
HTTP PulseDomains push signed manifests via POST /synapse/pulse
Nostr SubscriptionYour instance pulls historical + real-time CMN events from external relays
Nostr RelayOther instances or clients push events to your /synapse/nostr WebSocket endpoint
CrawlerBackground retry loop re-fetches cmn.json → mycelium → spores from known domains

No seed list. No manual domain configuration. Domains become known through pulses and Nostr events. Once known, the crawler handles the rest — fetching the full domain manifest, indexing every spore, and retrying on failure with exponential backoff.

A publisher pushes a pulse after releasing:

hypha mycelium pulse --synapse https://synapse.example.com

The pulse carries a signed capsule. Synapse verifies it, indexes it, and — if Nostr forwarding is enabled — broadcasts it to the relay network for other instances to pick up.

Cross-instance sync via Nostr

This is the mechanism that makes Synapse federated rather than just distributed. Every instance can act as both a Nostr relay and a Nostr client:

Instance A                 Public Relays              Instance B
    │                          │                          │
    │  forward_pulse ────────→ │                          │
    │                          │ ────────→ subscribe      │
    │                          │                          │
    │      subscribe ←──────── │                          │
    │                          │ ←──────── forward_pulse  │

Public Nostr relays (relay.damus.io, nos.lol, etc.) act as the shared transport. CMN events are NIP-78 application events (kind 30078) with structured tags for URI, domain, hash, and content type. Any Nostr relay stores them. Any Synapse instance can subscribe and ingest them.

Bootstrapping a new instance is one config change:

nostr:
  enabled: true
  relays:
    - "wss://relay.damus.io"
    - "wss://nos.lol"
  subscribe: true
  forward_pulse: true

On startup, the subscription sends a REQ to each relay for all historical CMN events, receives the backlog, then streams new events in real-time. Every event is verified through the same CMN signature pipeline as HTTP pulses. Within minutes, a fresh instance has the full network index — rebuilt from cryptographically verified data, without trusting any single source.

Lineage traversal: the bond graph

Synapse doesn’t just store spores — it indexes the relationships between them. Every bond declared in spore.core.json is stored as a graph edge. The API exposes traversal in both directions:

# Who forked from this spore? (inbound bonds)
curl 'https://synapse.example.com/synapse/spore/b3.<hash>/bonds?direction=inbound&max_depth=3'

# What does this spore depend on? (outbound bonds)
curl 'https://synapse.example.com/synapse/spore/b3.<hash>/bonds?direction=outbound'

The response includes the full lineage with relationship types — spawned_from, absorbed_from, depends_on, follows — and spore metadata for each node. Traversal depth is configurable per-request and capped by the server to prevent expensive unbounded walks.

The PostgreSQL backend uses recursive CTEs for lineage queries — one round-trip regardless of depth. The embedded redb backend uses BFS with the same interface. Both batch-fetch spore summaries to avoid N+1 queries.

With an embedding service (Ollama or OpenAI), Synapse indexes spore names, synopses, and intents as vectors. Search queries are embedded and matched against the index:

curl 'https://synapse.example.com/synapse/search?q=http+service&license=MIT'

Results are ranked by relevance with optional filters for domain, license, strain, bonds, and time range. Each result includes aggregated taste verdicts from the network — the signal that community evaluators have reviewed the code.

The search index includes a bond graph overlay for fast lineage lookups without hitting the database. On startup, the graph is rebuilt from indexed data.

Taste aggregation

Every spore and domain has a reputation surface built from taste reports. The network’s evaluators submit signed verdicts — sweet, fresh, safe, rotten, toxic — and Synapse aggregates them:

# Taste verdicts for a specific spore
curl 'https://synapse.example.com/synapse/spore/b3.<hash>/tastes'

# Aggregated reputation for an entire domain
curl 'https://synapse.example.com/synapse/cmn/example.com/tastes'

Synapse does not adjudicate. It aggregates and serves. Each visitor decides which taster domains to trust and how to weigh their reports. The verdicts are advisory — a trust signal, not an authority.

Two storage backends

BackendUse Case
redbDevelopment, single-node, zero config — one file, embedded
PostgreSQLProduction, high traffic, concurrent queries

Both compiled in by default. Switch with one config line. The storage trait is the same — lineage traversal, taste aggregation, batch queries, Nostr event persistence — so behavior is identical regardless of backend.

Deploy in five minutes

# Build
git clone https://github.com/cmnspore/cmn-synapse.git
cd cmn-synapse && cargo build --release

# Minimal config
cat > config.yml <<YAML
debug: true
storage:
  backend: "redb"
  redb_path: "synapse.db"
http:
  enabled: true
  address: "0.0.0.0:3000"
YAML

# Run
./target/release/synapse

Built-in ACME for automatic TLS certificates. Built-in Nostr relay. Built-in semantic search. One binary, one config file. For production, point a reverse proxy at it or enable the ACME provider for standalone TLS.

Agent-first output

Like all CMN tools, Synapse emits Agent-First Data structured logs. Every request, every pulse, every crawl event is a JSON event with stable fields. Pipe to ELK, Loki, CloudWatch, or any log aggregator. Secrets (database URLs, API keys) are auto-redacted via the _secret suffix convention.

{"$afdata":"request","method":"POST","path":"/synapse/pulse","status_code":200,"result":"indexed","trace":{"duration_ms":42}}

Install

brew install cmnspore/tap/synapse     # macOS/Linux
scoop bucket add cmnspore https://github.com/cmnspore/scoop-bucket && scoop install synapse  # Windows
cargo install cmn-synapse             # any platform

The network has no center

Any operator can run a Synapse instance. Any instance can sync with any other through public Nostr relays. No instance is authoritative. No instance is required. If every Synapse goes offline, the data still lives on the Nostr relay network, waiting for the next instance to subscribe and rebuild.

This is the discovery layer that CMN needs — one that matches the sovereignty model of the protocol itself. Your domain is your registry. Your Synapse is your index. The network is the union of all of them.

Docs: cmn.dev/tools/synapse Source: github.com/cmnspore/cmn-synapse License: MIT