Product-facing trust signal. Only 'verified' has cryptographic value.
Closed, unlike CryptoAlgorithm and CryptoErrorKind. A product may
switch on this exhaustively, and is meant to: a trust decision with a
silent default branch is the shape this library exists to prevent.
'unverified' — this library holds the device's keys and has no reason
to trust it beyond that. Every device reads this until a comparison
finishes. A device an administrator has blacklisted reads it too: this
build exposes no call that can set that state, so folding it here says
exactly as much as this build can honestly say.
'recognized' — not produced by this build, and that is now a
decision rather than a limit. It is reserved for exactly one state:
a device believable without a person having compared anything, because
its owner signed it with their cross-signing identity. That state used
to be out of reach; since bootstrapCrossSigning it is the ordinary
one, and it arrives as 'verified' instead. See below for why it is
folded and what it costs you.
Declared now because widening a closed union later breaks every
consumer that switched on it exhaustively, and would do so precisely
when a product had stopped expecting the shape to move. Write the
branch; it will not run yet.
'verified' — this library has reason to trust the device, by any of
three routes that this value does not tell apart. A person compared
a short authentication string on this device and on the far one, both
said it matched, and the flow completed. Or a person pointed one
device's camera at the other's screen and the side showing the code
confirmed the scan, which is the same act with a camera in place of a
comparison. Or the device is signed by its owner's cross-signing
identity and this library has verified that identity, in which case
nobody compared or scanned anything on this device at all. The last two
are new in this release and the third is the ordinary one from now on.
This said "either of two routes" while the second was being added, which
is the second time the count here has gone stale. See
getDeviceStatuses, including why your own device reads this from
the moment it exists and therefore proves nothing.
This is about a device, not about an event. A completed verification
does not change what a decrypted event says about its sender, by either
method, because the event path consults cross-signing and a verification
sets local trust. M3 design, section 7, question 6.
Why 'recognized' stays folded into 'verified'
Recorded here rather than left silent, because a value a product was told
to write a branch for and that then quietly never runs is worse than one
that was never declared.
The mapping underneath asks a single boolean -- locally trusted, or signed
by an identity we have verified -- and there is no third answer to carry.
Splitting it would mean asking a different question of the layer below,
and it would mean that a device this library trusts for the second reason
stopped reading 'verified' and started reading 'recognized'. That is a
behaviour change in the direction that hurts: a product's "is this device
trusted" branch would silently stop matching devices it had been matching,
on the same release that changes what 'verified' covers. One change to
this value per release is the most a consumer can reasonably follow.
So the fold stays, and the cost is stated instead of hidden: you cannot
ask this call whether a person compared a string with, or scanned a code
off, one particular device. If your product needs that distinction, it has to record its own
verifications as it performs them, or ask
EventEnvelope.senderVerification the event-level question instead.
If a later release does split them, 'recognized' is already in this
union, so that release adds no member and breaks no exhaustive switch --
which is what declaring it early bought.
Product-facing trust signal. Only 'verified' has cryptographic value.
Closed, unlike
CryptoAlgorithmandCryptoErrorKind. A product may switch on this exhaustively, and is meant to: a trust decision with a silent default branch is the shape this library exists to prevent.'unverified'— this library holds the device's keys and has no reason to trust it beyond that. Every device reads this until a comparison finishes. A device an administrator has blacklisted reads it too: this build exposes no call that can set that state, so folding it here says exactly as much as this build can honestly say.'recognized'— not produced by this build, and that is now a decision rather than a limit. It is reserved for exactly one state: a device believable without a person having compared anything, because its owner signed it with their cross-signing identity. That state used to be out of reach; sincebootstrapCrossSigningit is the ordinary one, and it arrives as'verified'instead. See below for why it is folded and what it costs you. Declared now because widening a closed union later breaks every consumer that switched on it exhaustively, and would do so precisely when a product had stopped expecting the shape to move. Write the branch; it will not run yet.'verified'— this library has reason to trust the device, by any of three routes that this value does not tell apart. A person compared a short authentication string on this device and on the far one, both said it matched, and the flow completed. Or a person pointed one device's camera at the other's screen and the side showing the code confirmed the scan, which is the same act with a camera in place of a comparison. Or the device is signed by its owner's cross-signing identity and this library has verified that identity, in which case nobody compared or scanned anything on this device at all. The last two are new in this release and the third is the ordinary one from now on. This said "either of two routes" while the second was being added, which is the second time the count here has gone stale. See getDeviceStatuses, including why your own device reads this from the moment it exists and therefore proves nothing.This is about a device, not about an event. A completed verification does not change what a decrypted event says about its sender, by either method, because the event path consults cross-signing and a verification sets local trust. M3 design, section 7, question 6.
Why
'recognized'stays folded into'verified'Recorded here rather than left silent, because a value a product was told to write a branch for and that then quietly never runs is worse than one that was never declared.
The mapping underneath asks a single boolean -- locally trusted, or signed by an identity we have verified -- and there is no third answer to carry. Splitting it would mean asking a different question of the layer below, and it would mean that a device this library trusts for the second reason stopped reading
'verified'and started reading'recognized'. That is a behaviour change in the direction that hurts: a product's "is this device trusted" branch would silently stop matching devices it had been matching, on the same release that changes what'verified'covers. One change to this value per release is the most a consumer can reasonably follow.So the fold stays, and the cost is stated instead of hidden: you cannot ask this call whether a person compared a string with, or scanned a code off, one particular device. If your product needs that distinction, it has to record its own verifications as it performs them, or ask EventEnvelope.senderVerification the event-level question instead. If a later release does split them,
'recognized'is already in this union, so that release adds no member and breaks no exhaustive switch -- which is what declaring it early bought.