SSyncropel Docs

Federation Discovery

Find instances two ways — fetch and verify a peer directly by URL with `spl discover`, or search the opt-in public directory by handle and topic. Plus how to make your own work public and read what others share.

Overview

Discovery answers a simple question: how do you find an instance worth connecting to? Syncropel gives you two paths, and they compose:

  • Direct, by URL — if you already know (or can guess) a peer's address, fetch its signed manifest and verify exactly what it advertises before you connect. This is the sovereign, no-middleman path. Covered first, below.
  • The public directory — if you don't know who's out there, search an opt-in index by handle and topic. Instances choose to list themselves; the directory only ever holds a handle and a few topics, never your content.

Both end the same way: you reach a real instance at a real URL, and everything it shows you is cryptographically attributable to it. No central authority gates who you can find or reach.

If you already have a peer's URL and want to sync records with them, see the federation pairing guide. This guide is for finding instances and for sharing or reading public work.

Direct discovery — spl discover

Every instance serves a manifest at /.well-known/syncropel. spl discover fetches it, verifies the signature, and shows you what the peer advertises — without you having to trust anything you can't check.

Prerequisites

An instance only publishes a federation manifest if it has a cryptographic identity configured:

# On the publishing instance (first time only).
spl init
# Or, if init was already run without a keypair:
spl identity generate

This writes a keypair the instance uses to sign its manifest. Without it, /.well-known/syncropel still serves the capability manifest — but the federation block is omitted, and any caller will see federation.enabled = false.

Fetch and verify a peer

spl discover --peer-url https://alice.example.com
Peer:             https://alice.example.com
DID:              did:key:z6Mkf7...
Federation:       enabled
Manifest version: 1
Signature:        valid (expires 2026-07-21)
Advertises kinds: music.catalog.track, music.catalog.album
Pair endpoint:    https://alice.example.com/v1/sync

Under the hood the command fetches the manifest, resolves the peer's identity to its public key, and verifies the signature over the manifest body. A tampered manifest or a signature mismatch exits non-zero with a clear error — the command never reports a claim it could not verify.

From a script, take structured output:

spl discover --peer-url https://alice.example.com --json \
  | jq '{did: .federation_manifest.daemon.did, kinds: .federation_manifest.advertises.kinds}'

Filter by what a peer accepts

--kind narrows the result to peers whose manifest advertises a given body.kind:

spl discover --peer-url https://alice.example.com --kind music.catalog.track

If the peer doesn't advertise a match, the command exits non-zero — a quick scripted "is this peer willing to accept this kind?" check before you initiate a pair.

What's in the manifest

{
  "manifest_version": 1,
  "daemon": { "did": "did:key:z6MkfYVB...", "version": "0.X.Y" },
  "federation": {
    "enabled": true,
    "pair_endpoint": "/v1/sync",
    "consent_policy": { "directory": "opt-in" }
  },
  "advertises": { "kinds": ["music.catalog.track"], "refs": [], "namespaces": [] },
  "signature": { "alg": "Ed25519", "key_id": "did:key:z6MkfYVB...#key-1", "signature": "<base64>", "expires_at": "2026-07-21T00:00:00Z" }
}
  • daemon.did is the peer's identity. The signature is verified against the public key this DID resolves to; a manifest signed by a different key is rejected.
  • advertises.kinds is the opt-in list of record kinds the peer is willing to receive. An empty list is legitimate — open to pairing, but advertising no menu.
  • signature.expires_at is a freshness window, not a revocation list. Instances re-sign on each start; a manifest past its expiry is rejected.

The public directory

Direct discovery works when you already know a URL. The public directory is how instances find each other when they don't — a voluntary, searchable index of instances that have chosen to be listed.

It is a phone book, not a gatekeeper:

  • Opt-in. An instance is invisible until its operator turns discovery on. Off by default.
  • Minimal. A listing carries a handle and a few topics — never your records, threads, or content.
  • Self-attested. Each listing is signed by the instance that owns it and verified before it's indexed. The directory cannot forge or alter a listing.
  • Not authoritative. The directory is a convenience. Any instance can still be reached and verified directly by URL, regardless of whether it's listed.

Make your instance discoverable

On a Syncropic-hosted instance, discovery is a choice you make at signup — a single "list me in the directory" opt-in. Turn it on and your instance publishes its listing automatically; turn it off and the listing is withdrawn. The listing advertises only your handle and the topics you choose.

You can change this at any time from your instance settings. Nothing about your records or threads is shared by being listed — discoverability and making a thread public (below) are separate, independent choices.

Search the directory

The directory is searchable from Studio — open discovery and search by handle or topic; matching instances appear with their handle, topics, and a link to view their public work.

To query it directly, the directory exposes a public read:

curl "https://graph.syncropel.com/v1/directory/search?q=research"
{
  "results": [
    {
      "handle": "rae",
      "advertise_topics": ["research", "writing"],
      "public_threads": ["th_..."],
      "peer_url": "https://rae.syncropel.app",
      "matched_on": ["topic"]
    }
  ]
}

A result with a peer_url is reachable; public_threads lists the threads that instance has chosen to make readable (next section).

There is no spl directory command yet — the directory is reachable from Studio and over HTTP. Direct-by-URL discovery remains spl discover --peer-url.

Make your work public

Discoverability lists your instance. Making a thread public is what lets someone actually read it. The two are independent: you can be listed with nothing public, or make a thread public without being listed.

From Studio, open a note or workspace thread you own and use its visibility control:

  • Full content — readers see the whole thread. This is the default for a document you mean to share.
  • Structure only — readers see that the thread exists and its shape, but not its contents.

A thread stays public for about a week, then the grant expires on its own; you can make it private again at any time. The visibility you see in Studio is read from the live grant, so it always reflects reality.

To do the same over HTTP:

curl -X POST https://<your-instance>/v1/consent/grants \
  -H "Authorization: Bearer $SPL_TOKEN" \
  -d '{ "public": true, "thread": "th_...", "granted_level": "L0" }'

granted_level is L0 for full content or L2 for structure-only. Revoke by deleting the grant (DELETE /v1/consent/grants/{grant_id}).

Making a thread public is done in Studio or over the API. The spl consent grant command covers cross-namespace and per-recipient sharing, but not the public scope.

Read someone's public work

From Studio, a directory result with public threads offers View public work — it reads the peer's public threads and renders them read-only, the same way your own threads render.

Over HTTP, a peer's public thread is an auth-exempt, record-gated read against the peer's own instance:

# Returns the thread's records only if an active public grant covers it.
curl "https://rae.syncropel.app/v1/public/thread/th_..."

A thread that isn't public returns 404 — the read never reveals whether a private thread exists. Content comes back projected to the level the owner granted: a Full content grant returns the readable body; a Structure only grant returns shape without contents.

Connections

Discovering and reading a peer is read-only. To record an ongoing relationship — view, follow, or pair — you create a connection. Studio offers one-click connect from a directory result; the underlying connections are managed with spl connection (add, list, archive, revoke). Pairing, which enables two-way record sync, is covered in the federation pairing guide.

Security properties

  1. Attributable. Both a peer's manifest and a directory listing are signed by the instance that owns them and verified before they're trusted. A proxy or the directory itself cannot alter what an instance advertises without detection.
  2. Freshness-bounded. Manifests carry an expiry and are re-signed on each start; expired manifests are rejected.
  3. Opt-in, twice over. Being listed and making a thread public are separate, deliberate choices. The default is private and unlisted.
  4. Projected reads. A public read returns only what the owner's grant exposes — full content, or structure only — never more.
  5. No central authority. The directory is a convenience, not a gate. Any instance is reachable and verifiable directly by URL.

Common troubleshooting

  • peer served /.well-known/syncropel but no federation_manifest key — the peer has no identity configured. Run spl init or spl identity generate on it.
  • signature verification failed — the manifest was altered in transit, or the peer's DID resolves to a different key than the one that signed. Re-fetch; if it persists, the peer's identity is misconfigured.
  • manifest expired — the peer hasn't re-signed within its freshness window. Ask the operator to restart it.
  • A directory result won't load its public work — the owner may have made the thread private again, or set it to structure only. A 404 on a public read is indistinguishable from "no such thread" by design.

Next steps

  • Federation pairing — once you've found a peer, pair to sync records two-way.
  • Consent — the grant model behind public threads and cross-namespace sharing.
  • Async federation — deliver records to peers that are offline via a store-and-forward relay.
  • Capability manifest — the sibling manifest at /.well-known/syncropel, covering non-federation API surfaces.

On this page