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.
/// 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,}GetServerCapabilities
Section titled “GetServerCapabilities”Input: None
Output: ServerCapabilities
Auth: None
Idempotent: Yes
Errors: UNKNOWN_OPERATION, SERVICE_UNAVAILABLE
Requirements
Section titled “Requirements”- Servers implementing Cryptid MUST server this document
server_nameMUST 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.
HTTP Binding
Section titled “HTTP Binding”GET /.well-known/cryptidVersion Compatibility
Section titled “Version Compatibility”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
minorSHOULD be logged but MUST NOT block federation - From 1.0, servers MUST federate with peers sharing the same
majorand MUST tolerate a differingminor - A differing
majorMUST 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 |
Two Keys, Two Jobs
Section titled “Two Keys, Two Jobs”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
Caching
Section titled “Caching”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
Health
Section titled “Health”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/health200- accepting traffic503- operational but not accepting traffic; retry perRetry-After