Skip to content

Discovery

Every interaction with a server starts here. A client learns its size limits before uploading; a peer learns its version, its features, and the key that verifies its signatures before federating.

ServerCapabilities Structure
/// Published at /.well-known/cryptid. The single source of truth for what a server supports.
/// Nothing else in the protocol restates any of it.
struct ServerCapabilities {
// Specification version as major.minor. Unrelated to the MLS
// ProtocolVersion inside KeyPackages
cryptid_version: String,
// The server's own domain. MUST match the host it was fetched from
server_name: String,
federation_enabled: bool,
// Ed25519 key verifying X-Origin-Signature on federation requests.
// Distinct from certificate_fingerprint: this authenticates requests
// that outlive their connection
server_signing_key: Ed25519PublicKey,
// Pins the transport. Compared against the observed TLS certificate
certificate_fingerprint: String,
// The real compatibility signal. A version number does not gate interoperability;
// these do
supported_features: Vec<String>,
limits: ServerLimits,
}
struct ServerLimits {
// Bytes. Bulk data goes to the blob store, not into messages
max_message_size: u32,
// Bytes. Each host sets its own; this is how a host bounds its
// storage exposure without the protocol pricing it
max_blob_size: u64,
federated_messages_per_minute: u32,
}

Input: None Output: ServerCapabilities Auth: None Idempotent: Yes Errors: UNKNOWN_OPERATION, SERVICE_UNAVAILABLE

  • Servers implementing Cryptid MUST server this document
  • server_name MUST match the host the document was fetched from
  • The response MUST be cacheable
  • Servers MUST NOT require authentication

A 404 here means the host does not speak Cryptid, or has disabled discovery. It is not an error condition to retry.

GET /.well-known/cryptid

cryptid_version is major.minor, and unrelated to the MLS ProtocolVersion inside KeyPackages.

  • Servers MUST reject federation from a peer whose version they cannot parse
  • Before 1.0, a differing minor SHOULD be logged but MUST NOT block federation
  • From 1.0, servers MUST federate with peers sharing the same major and MUST tolerate a differing minor
  • A differing major MUST block federation
Flag Covers
mls_messaging Base MLS group messaging
cryptid_envelope_v1 Double-encrypted envelope relay and its federation payload
privacypass_0x0001 Token type 0x0001 issuance and redemption
blind_keypackages Derived-handle KeyPackage storage and fetch
blob_store_v1 Blob upload, capability-handle fetch, and reports

certificate_fingerprint and server_signing_key are easy to conflate and do different work.

Pins Checked
certificate_fingerprint the TLS certificate at connection time, against what the transport presents
server_signing_key the Ed25519 federation key per request, against X-Origin-Signature

The fingerprint protects the channel. The signing key protects a request that may sit in a queue, be retried under the same transaction_id, or be replayed later - none of which the connection outlives.

  • Clients and peers MUST compare the observed certificate against certificate_fingerprint
  • A mismatch MUST be treated as an active attack, not a misconfiguration

Discovery is fetched constantly and changes rarely.

  • Clients and servers SHOULD cache the document and honor its cache headers
  • Implementations SHOULD re-fetch on a signature verification failure before rejecting a peer, since the cause may be a rotated signing key
  • Implementations MUST re-fetch before assuming a feature is unsupported

Input: None Output: Health { status, time } Auth: None Idempotent: Yes

Separate from discovery because they answer different questions: discovery says what a server supports, health says whether it is working right now. A server in maintenance still serves accurate capabilities.

GET /api/v1/health
  • 200 - accepting traffic
  • 503 - operational but not accepting traffic; retry per Retry-After