# Hosting your DID document

Where the public key that verifies your passports is published, the three hosting modes, how to move to your own domain, and exactly what stays verifiable if SealTrust disappears.

Source: https://docs.sealtrust.io/en/hebergement-du-did/

---

By the end of this page you will know where the key that verifies your passports is
published, which three hosting modes exist, which one to choose, and exactly what
stays verifiable the day SealTrust ceases to exist.

## The principle

Every passport we issue for you is signed. Checking a signature requires the matching
public key. That key is published in a **DID document**, at a fixed address, and the
address is written inside the passport itself.

A passport therefore carries an identifier shaped like this:

```
did:web:api.sealtrust.io:brand:42
```

The `did:web` rule turns that identifier into a web address:

```
https://api.sealtrust.io/brand/42/did.json
```

Any standard `did:web` and SD-JWT-VC library makes that transformation, fetches the
document, takes the key from it and checks the signature itself. We do not return a
verdict, we publish a key.

> [!INFO] Where the private key lives
> The key that **signs** never leaves our hardware security module. None of the three
> modes below changes that: they only move where the **public** key is published.

## The three modes

| Mode | Who hosts the document | What you provide |
| --- | --- | --- |
| `platform` | us | nothing |
| `delegated` | us, on your own domain | your custom domain, already verified with us |
| `self_hosted` | you | the file, on your server |

### `platform`, the default

Your identifier is `did:web:api.sealtrust.io:brand:<your number>`. Nothing to do,
nothing to maintain, and the document updates itself when your key changes.

The trade-off: the first verification of a passport goes through our servers.

### `delegated`

This mode requires the Inside plan and a custom domain already verified with us. It is
not a separate subdomain: it is the same hostname that already serves your verification
pages, for example `id.example.com`. You request that domain from SealTrust, then prove
you control it by publishing the DNS records the console gives you. Until it reaches
the verified state, the switch is refused.

The address becomes yours and key updates stay automatic.

### `self_hosted`, full independence

You serve `https://id.example.com/.well-known/did.json` from your own infrastructure.
We no longer serve the document you issue under.

One trade-off to understand before choosing this mode: **every time your signing key is
rotated, you must republish the file**. If you forget, passports issued after the
rotation no longer verify, and nothing will warn you.

> [!ATTENTION] What `did:web` does not protect
> A `did:web` identifier is worth exactly what control of the domain is worth. There is
> no authority above it: whoever takes over the domain name can publish their own keys.
> Treat that domain and its DNS account as a production secret, with the same protection
> as your most sensitive access.

## Changing mode is permanent

> [!ATTENTION] Decide before your first passport
> Change mode **before issuing your first passport**, never after.

A passport carries the identifier it was signed under, sealed inside its signature.
Changing your mode changes the identifier you issue under, but not the ones already
signed. You end up with two identifiers in circulation, and earlier passports keep
pointing at the old one.

That old address stays served by us, with your non-revoked keys, so that passports
signed before the switch remain verifiable by a standard tool. Our own check
`GET /passport/{identifier}/vc/verify`, however, only knows how to verify under the
current identifier: after a switch it answers with an error on your earlier passports,
even when they are valid. Warn your auditors before switching.

That is why the switch is requested explicitly, and is not available from your settings.

## What survives if SealTrust disappears

This is the question an auditor asks, and here is the exact answer, unrounded.

| Item | Survives? | Why |
| --- | --- | --- |
| The on-chain anchor | **yes, permanently** | the transaction is public, we can neither withdraw nor rewrite it |
| The signature, on `self_hosted` | **yes** | the file already sits on your server |
| The signature, on `delegated` | **yes, after one move** | we serve the file today, repoint your DNS and republish the document |
| The signature, on `platform` | yes, if you kept the document | the address is ours |
| The passport content | yes, through your export | it is only served by our API |
| The inclusion proof | yes, if you collected the four values | they only come from our API |
| The IPFS copy | **no by default** | a file stays there only while someone pins it, and today that is us |
| The addresses burned into your QR codes and chips | **no if they point at our domains** | a chip cannot be rewritten remotely |

### The four moves that turn this list green

**Keep a copy of your DID document.** It is public, at the address shown above. Download
it and store it with your archives. It is the file that lets anyone check a signature
without us, and it is only a few lines long.

**Download your reversibility export, regularly.** It holds your full data and your
signed passports. Without it, the signature stays valid but you no longer hold the
content it protects.

**Collect your inclusion proofs, passport by passport.** Call
`GET /passport/{identifier}/proof` and record, from the `passport_anchor` block, the
values `merkle_root`, `leaf`, `leaf_index` and `proof`. Nobody will be able to rebuild
them once our API is switched off.

**Pin your IPFS copies on your side.** The addresses of your copies are in your export,
under the `ipfs_uri` field. Not every passport has an IPFS copy, and the address does
not always appear in the public proof. Pinning them with a provider of your choice costs
little and makes the copy independent of our subscription.

## Key rotation

A signing key can be replaced without invalidating the past. Each key carries a version
number, and each passport states in its header which version signed it. The DID document
publishes all of your non-revoked keys, so an older passport keeps verifying with its
older key.

Revoking a key is a stronger move: it leaves the document, and passports signed with it
stop verifying. Only revoke when the key is compromised.

One thing to remember: on `self_hosted`, republish the document after every rotation.
