SolidusBeta
DIDComm v2 protocol

How the mediator works.

A sender encrypts a message to the recipient, then wraps that ciphertext in a forward envelope addressed to the mediator. The mediator unwraps only the outer envelope — the inner ciphertext, still sealed to the recipient, is never exposed. Below is the full sequence: CoordinateMediation 2.0 to set up routing, Routing to forward, Pickup 3.0 to collect — chain-anchored and credential-gated where Solidus diverges from a stock mediator.

The full sequence

Every hop, named.

From mediate-request to purge — the exact DIDComm v2 messages, with the chain-anchored resolution and credential gate marked where they apply.

Recipient agentSolidus Relay

mediate-request

CoordinateMediation 2.0

The recipient's own agent asks the mediator to coordinate delivery on its behalf.

Solidus RelayRecipient agent

mediate-grant

CoordinateMediation 2.0

Mediator grants mediation and returns a routing key the recipient publishes in its did:solidus document.

Gate: pass
Recipient agentSolidus Relay

keylist-update

CoordinateMediation 2.0

Recipient registers the DID keys it wants routed through this mediator.

Sender agentSolidus Relay

forward

Routing

Sender resolves the recipient's did:solidus document on-chain to find the routing key and mediator endpoint, wraps its JWE-encrypted message in a forward envelope, and sends it to the mediator.

blk #4,827,391JWE
Recipient agentSolidus Relay

delivery-request · live-delivery

Pickup 3.0

Recipient asks what is waiting with delivery-request — or, if a live-delivery connection is already open, the mediator pushes new messages automatically as they arrive.

Gate: pass
Recipient agentSolidus Relay

messages-received

Pickup 3.0

Recipient acknowledges receipt; the mediator marks those messages delivered.

Solidus Relay— internal

purge

Retention policy · 14d, purge-on-ack

Acknowledged ciphertext is purged on this schedule — the relay does not keep messages it no longer needs to hold.

Protocol reference

Three protocols, nothing proprietary.

CoordinateMediation 2.0, Pickup Protocol 3.0, and Routing are the DIDComm v2 protocols in play — the relay implements the standard, not a fork of it.

ProtocolMessages it definesWhat the relay does
CoordinateMediation 2.0
mediate-requestmediate-grantkeylist-updatekeylist-query
Grants or denies mediation, issues a routing key, and maintains the keylist of DIDs the relay will forward messages to.
Pickup Protocol 3.0
status-requestdelivery-requestmessages-receivedlive-delivery
Holds messages for an offline recipient and delivers them on request, or streams them immediately over an open live-delivery connection.
Routing
forward
Unwraps only the outer forward envelope to find the next hop. The inner ciphertext, still encrypted to the recipient, is never exposed.
Chain-anchored

Routing keys resolve on-chain, block-cited.

A stock mediator publishes its routing key and endpoint in a DID document hosted off-chain — a did:web file, a registry, a database row an operator controls. Change it, and every sender silently starts trusting a new destination.

A did:solidus document resolves from the chain. The routing key and service endpoint a sender reads back are the ones written at a specific, citable block — not whatever an operator's server happens to return today.

That is what the chain-anchor badge on every resolved route in the operator console means: this route was read from the chain, not a cache or a registry the mediator itself controls.

resolved-did-document.json
1{
2 "id": "did:solidus:z6MkrQT4pWnvKb8sVdE2mHhXNfJcyLu3gA9tCiDoZxSe1RmF",
3 "service": [
4 {
5 "id": "#didcomm-mediator",
6 "type": "DIDCommMessaging",
7 "serviceEndpoint": {
8 "uri": "https://relay.solidus.network/didcomm",
9 "routingKeys": [
10 "z6LSfj9q…QtU0S1"
11 ]
12 }
13 }
14 ],
15 "_resolution": {
16 "source": "on-chain (testnet)",
17 "block": 4827391
18 }
19}
Credential-gated

Delivery can require a verified credential.

A gate policy can require the recipient to hold a specific verifiable credential before the relay grants mediate-request or accepts a forward on its behalf. The check runs against verify.solidus.network — the same credential stack, not a bolted-on integration.

The example policy below only mediates for recipients holding a SolidusKYCCredential, disclosed selectively with BBS+ — the relay confirms the credential exists and is unrevoked without seeing fields the policy doesn't ask for.

No open-source mediator has a credential layer beneath it — a gate policy there is unconditional, protocol-level, or absent.

gate-policy.json
1{
2 "id": "pol_kyc",
3 "name": "KYC-verified recipients",
4 "credentialType": "SolidusKYCCredential",
5 "issuerDid": "did:solidus:z6MkverifyIssuer4tRq8wYbGd2kEuC9vHsNa1pLoZi5xVeW",
6 "disclosure": "selective (BBS+)",
7 "appliesTo": "mediation",
8 "enabled": true
9}
Concrete example

An issuer reaches an offline wallet.

One path through the sequence above, end to end: an issuer sending a credential offer to a wallet that's currently offline.

Setup · once

The wallet requests mediation

An offline-first wallet has no public IP of its own — it registers with the mediator once, in advance.

mediate-requestmediate-grantkeylist-update

The wallet is granted mediation and registers the DID keys it wants routed. From now on, its did:solidus document points senders at this mediator.

Resolution

The issuer resolves the wallet's DID on-chain

Before sending anything, the issuer looks up the wallet's did:solidus document.

The document resolves at blk #4,827,391 — the routing key and mediator endpoint it returns are exactly what's written on-chain, not a cached copy.

Delivery attempt

The issuer forwards the encrypted credential offer

The offer is a JWE addressed to the wallet, wrapped in a forward envelope addressed to the mediator.

forwardJWE

The mediator holds the ciphertext — it cannot read the credential offer inside. The wallet is offline right now, so nothing more happens yet.

Pickup

The wallet comes online and picks it up

Later, the wallet opens a live-delivery connection — or sends a delivery-request if it isn't currently connected.

delivery-request·live-delivery

The mediator hands over the queued offer. The wallet decrypts it locally — the mediator was never able to.

Acknowledged

The wallet confirms receipt

messages-received tells the mediator the offer arrived; it's purged per the retention policy (14 days, purge-on-ack).

messages-received

Nothing about this exchange is stored beyond the retention window — the mediator's job was to hold ciphertext until the wallet was ready, then let it go.

Same sequence for any two DIDComm v2 agents — a credential offer, a presentation request, or an ordinary application message.

Point a mediator URL. Not a Kubernetes chart.

Planned launch pricing: $0 for the first 1,000 messages a day, no enterprise sales call. Testnet, pre-launch — the console runs on sample data while the mediator comes online.