Security and timeouts
What the exchange proves and what it leaves to you, how receivers treat problems, and how cancelling and timeouts work. The rules are in the spec; this page explains them and links each one.
What the signatures prove
The wallet signs its own mdoc, as both issuer and device, with keys it controls WRS-4 WRS-6. The signatures make the response a complete, verifiable ISO mdoc that strict mdoc software accepts. They show the bytes are intact and well formed. They don't show who issued the content: the wallet may make new keys for every response, and anyone holding a SMART response can wrap it in a new, valid mdoc.
- The encryption is what protects the response in transit. Only the holder of the Verifier's private key, for this origin and this request, can open it, and a changed ciphertext doesn't open VRS-3.
- The origin comes from the browser or platform, never from the request TR-3. It tells the wallet which page asked; it doesn't tell anyone that the page belongs to an organization you trust.
- Evidence about clinical content lives in the content. A SMART Health Card is signed by its issuer, and the Verifier checks that signature against its own trust policy XV-13. Raw FHIR and form answers are what the patient chose to share.
The spec's §7 has the full table: each signal, what it proves, what it doesn't, and the threats it does and doesn't cover.
Warnings, not failures
Whoever builds a message builds it exactly as the spec says RCV-0. Whoever receives one stops only when it can't go on, and reports everything else as a warning RCV-1 RCV-2. This lets exchanges work while implementations are still being corrected, without anyone producing sloppy messages.
| The receiver stops (fail) when | Everything else is a warn, for example |
|---|---|
|
It can't decode the message WRQ-2 VRS-2 It can't decrypt the response VRS-3 It can't find the request or the response text WRQ-4 WRQ-5 VRS-8 The wallet has no usable key or no origin WRQ-7 WRQ-8 The JSON is invalid, or answers another request XV-1 XV-2 |
A signature or digest that doesn't verify VRS-5 VRS-6 VRS-7 An MSO outside its validity window VRS-10 An unknown algorithm value ALG-2 A wrong version or status, or an extra document VRS-4A duplicate CBOR map key the decoder tolerates ENC-5 |
The JSON has its own, narrower rule: one bad record or status row costs only that record or item (Request and response). The Testing EHR lists warnings separately from failures, so a wallet developer sees both.
Reader authentication
A Verifier may sign its request with readerAuth RA-1. A wallet that checks it puts the result
in exactly one of five states TRUST-2:
| State | Meaning |
|---|---|
| absent | The request isn't signed. |
| malformed | The signature structure can't be read. |
| invalid | The signature, or its binding to this session, fails. |
| valid but untrusted | It verifies, but the wallet doesn't recognize the certificate. |
| trusted | It verifies, and a deployment trust list recognizes the certificate. |
The wallet shows a verifier identity only for trusted. Without a deployment trust list, valid but untrusted is the normal result. No state stops the exchange WRQ-9.
Cancel and decline
If the patient reviews the request and declines everything, the wallet still answers, with every item
declined. The clinic learns the patient saw the request and chose not to share.
If the patient closes the wallet without reviewing, nothing comes back, and the browser call ends with the
platform's cancellation error HOLD-4.
A request the wallet can't process at all, such as one with no request text, also ends the call with an error
WRQ-1. Problems inside one item make only that item unsupported.
Timeouts
A Verifier sets its own timeout on the browser call VRQ-10, because on some platforms a failed delivery
never settles the call. The client library gives a web wallet 5 minutes by default; for the phone's
own wallet, pass an AbortSignal to runCheckin. A response that arrives after the
Verifier gave up is not acted on SEC-1.