Who decides when a credential has been replaced?
A new credential cannot tell a wallet whether an older one has become obsolete. During ordinary issuance, revocation must provide that signal. A retained link makes automatic background refresh the exception.
A new credential can mean two things
You transfer from Finance to Legal. Your employer issues a fresh employee credential with your new department. That is exactly what should happen.
Your wallet now holds two employee credentials. One says Finance; the other says Legal. The old credential is still signed, unexpired, and not revoked.
The next time a verifier asks for your department, the wallet may offer both. Your employer has left Finance valid, so the wallet has no authoritative reason to suppress it.
Now change one fact. You did not leave Finance; you joined Legal as a second department. In that case, both credentials should remain valid.
- Type
- same as one you hold
- Issuer
- same as one you hold
- Attributes
- differ from the stored credential
- Type
- same as one you hold
- Issuer
- same as one you hold
- Attributes
- differ from the stored credential
The wallet sees the same pattern in both cases: same type, same issuer, different attributes. Yet one case keeps both credentials valid, while the other makes the old one obsolete.
Attribute names do not resolve the ambiguity. A field describes its value, not whether an older statement remains true.
The employer knows what happened; the wallet does not. During ordinary issuance, the issuer must express that the old credential is obsolete by revoking it.
Replacement hides two mechanisms
Here, a logical credential is the unit shown to the user as one card: one credential type from one provider with one set of attribute values.
Behind that card, the wallet may store several signed technical copies. Their salts, keys, signatures, and validity timestamps may differ, but each makes the same statement.
In other words, one logical credential consists of a batch of one or more technical credentials.
When attribute values change, the result is a new logical credential. The issuer decides whether the older credential remains valid by leaving it valid, letting it expire, or revoking it.
The word replacement therefore covers two mechanisms:
- Content identity groups new technical copies with the same logical credential during refresh.
- Revocation status tells wallets and verifiers that an old logical credential is no longer valid.
Content identity is calculated from the credential. Revocation is an issuer action on a credential it previously issued.
These mechanisms answer different questions: “Are these new copies of the same statement?” and “Is the former statement still valid?”
What content matching can decide
Yivi treats an arriving credential as another copy of a stored logical credential when three things match:
- the type (
vctfor SD-JWT VC,docTypefor mdoc), - the issuer,
- the attribute values.
The wallet hashes those inputs. A matching hash lets the new batch refresh the stored batch. A different hash represents a different logical credential.
The hash omits salts, digests, holder keys, signatures, and validity timestamps. Those values change between issuances, even when the logical credential does not.
The ARF describes the same rule in a note attached to PAD_02:
Physical PIDs or attestations correspond to a logical one if they have not only the same attestation type and Provider, but also the same attribute values.
This works well for routine refresh. Credentials expire, and batches of single-use copies run out. The wallet can fetch fresh copies with new keys and timestamps but unchanged attributes.
An age credential, for example, keeps saying age_over_18: true. Its hash still matches, so fresh copies update the batch and the wallet shows one card rather than twelve.
Content matching may also group exact duplicates during ordinary issuance. It cannot decide that a different logical credential has made an older one obsolete.
OpenID4VCI describes the alternative plainly: a wallet may hold several credentials of the same type “without knowing which one is the latest”.
View the complete content-matching comparison
| What really happened | Type | Issuer | Attributes | Required handling |
|---|---|---|---|---|
| PID renewed, nothing changed | Same | Same | Same | Refresh copies |
| Email credential re-issued unchanged | Same | Same | Same | Refresh copies |
| You transfer departments | Same | Same | Differ | Revoke old |
| You join a second department | Same | Same | Differ | Keep both valid |
| A second diploma from the same university | Same | Same | Differ | Keep both valid |
| Age credential from the state and from a shop | Same | Differ | Same | Keep both valid |
| Email attested by your employer and by the state | Same | Differ | Same | Keep both valid |
Revocation is the replacement signal
When changed values make an old credential obsolete, the provider should issue the updated credential and revoke the old one.
The provider controls the status of the credentials it issued. It can invalidate the exact old technical copies without asking the wallet to reconstruct a relationship from new contents.
After revocation, the old copies are no longer valid. Under VCR_19, the wallet should regularly check their status and notify the user.
Under ISSU_62, the wallet stops presenting the obsolete credential and should delete it. A verifier that checks status can reject any surviving copy.
Revocation does not name the replacement. It solves the safety problem: the former statement is invalid, while the newly issued statement is valid.
The VCR_09 mandate applies when the credential is revocable and would otherwise remain valid for at least 24 hours. Otherwise, expiry limits the overlap.
The wallet still cannot declare the credential invalid on the issuer's behalf.
Background refresh is the exception
The relationship missing from an ordinary issuance can exist in the wallet's local refresh context.
If an automatic refresh starts from a stored credential, Yivi can retain that association throughout the issuance session: “this issuance updates credential X”.
That is not an inference from credential contents. The wallet knows which stored credential initiated the refresh.
Today, Yivi discards the association and later tries to reconstruct it from the content hash. Content comparison cannot recover context after it has been discarded.
OpenID4VCI lets a wallet obtain an updated credential with a valid access token, or use a refresh token to obtain one.
For a device-bound PID or attestation, ARF ISSU_65 requires the provider to verify that the re-issued credential goes to the same Wallet Unit.
Neither mechanism identifies a particular stored credential as the predecessor. A refresh token is not, by itself, a stable pointer to one logical credential.
ISSU_59 requires the wallet to compare old and new values during re-issuance and notify the user. Retaining the local association gives Yivi the context needed for that comparison.
User-initiated issuance is different. A universal link, QR code, or link in an email starts an authorization with no stored credential attached.
The result carries no more context than a first-time issuance. The provider must revoke any obsolete credential; Yivi should store the new one and follow the status of the old one.
Technical details
The following details explain why Yivi hashes type, issuer, and attributes, and why the issuer input must remain stable. They support the rule; they do not determine validity.
Why type and issuer both matter
The type says what kind of credential this is. In SD-JWT VC it is the vct claim; in mdoc it is the docType. It identifies neither the subject nor the issuer.
The issuer says who stands behind the claims. Yivi derives that identity differently by format:
- SD-JWT VC uses the
issclaim when present. Otherwise, it uses the identity in the certificate that signed the credential. - mdoc has no issuer field in the document. Its issuer identity comes from the certificate chain used to sign it.
- If neither yields a usable name, Yivi falls back to the credential issuer URL used during issuance.
Consider two age_verification credentials that say age_over_18: true. One comes from the Dutch state and the other from a supermarket loyalty programme.
They make the same statement, but at different trust levels. A verifier may accept one issuer and reject the other, as the trust levels post explains.
Why issuers are fragile
The hash assumes that Yivi derives the same identity every time the same provider issues a credential. That assumption is more fragile than it looks.
For SD-JWT VC, a changed iss value changes the issuer input. For mdoc, a changed name in the signing certificate can do the same.
When the credential issuer URL is the fallback, a new domain, path, or trailing slash can also produce a different issuer identity.
If the type and attributes stay the same but the derived issuer identity changes, the complete hash changes. Yivi then treats the new technical credentials as a different logical credential.
The new credential may still be valid and verifiable. The failure is local continuity: the incoming batch no longer replaces the existing card, so the wallet keeps both.
Rotating keys or certificates is harmless to grouping only when the issuer identity that Yivi derives remains unchanged.
Today, issuers must keep that identity stable across renewals. Supporting intentional changes would require an explicit migration or alias mechanism; content hashing alone cannot connect the old and new identities.
If you issue credentials
Credential replacement starts with the issuer:
- Issue the updated credential.
- Revoke the obsolete technical copies when their claims are no longer true.
- Support automatic refresh so the wallet can update its local record without interrupting the user.
- Keep the issuer identity stable across renewals as much as possible.
Do not rely on matching type, issuer, or attributes to make a wallet invalidate an old credential. Those fields cannot distinguish a department transfer from an additional department.
During ordinary issuance, Yivi should follow revocation status. Only an automatic refresh may use a retained local association to replace the credential that initiated it.
If a credential cannot be revoked, its validity period determines how long an obsolete value remains usable. That is part of the issuer's credential design.
If you run an issuer and want to discuss your re-issuance flow, or think we have this wrong, we would like to hear from you: support@yivi.app.
Sources
- OpenID for Verifiable Credential Issuance 1.0 — batch issuance and refreshing issued credentials
- EUDI Architecture and Reference Framework — logical versus technical attestations,
VCR_03,VCR_09,VCR_19,ISSU_59,ISSU_62,ISSU_65,PAD_02 - ARF discussion topic B: re-issuance and batch issuance of PIDs and attestations
- SD-JWT-based Verifiable Credentials —
vctandissclaims - Who vouches for you? How the Yivi wallet will decide whom to trust
