Credential Data Model 1.1 and 2.0, and a Proof Block That Names the Wrong Thing

The credential data model had a version change, and most of what people say about it is about two date fields. The version change is the easy part. What a proof block claims is the hard part, and this page is mostly about that.

What actually changed between the versions

The dates were renamed. Issuance and expiry became validity-from and validity-until, which is a better description of what they mean: a credential can be issued before it becomes valid.

The context changed, which is how a processor tells the versions apart.

Some looseness was tightened, and several things that had been conventions became requirements.

That is genuinely most of it at the level a holder cares about. A rename is not an architecture change, and anybody presenting the version bump as transformative is padding.

Where we are, verified in the type rather than in a changelog

Our credential type carries the 2.0 date fields, with the older names recorded in comments as what they replaced, and the context names the 2.0 vocabulary.

We checked that in the type definition rather than trusting our own release notes, which is the same discipline this estate applies to everything else and which matters here because a changelog is a statement about intent.

And now the part that is against us

Our chain-backed credential builds a proof block that declares a named signature suite.

The value it carries is a hash, not a signature. Both places that construct one put a hash of the payload where the suite expects a signature verifiable against the key named in the same block.

The model behind it is coherent. The inline comment says so directly: on-chain, the proof is the hash, because the credential is anchored and the chain record is what a verifier is meant to consult. Anchoring is a real design and a defensible one.

The label is the defect. Naming a suite is a promise about a verification procedure. A third-party verifier that follows that procedure will try to check a hash as a signature and fail; one that does not follow it will trust a field that proves nothing on its own. Either way the name is making a claim the bytes do not support.

The honest fix is small: stop naming a suite whose procedure does not apply, and say that verification means resolving the chain record.

Our own verifier reports a check it does not run

The verification function asks the chain and then returns three results.

Two of them are constants. The signature result is hardcoded true, with a comment explaining that the chain validated at submission time, and the expiry result is hardcoded true because these credentials do not expire on-chain.

Only the revocation result reflects the answer that came back.

One of the three fields is genuinely computed, so the other two being constants is a fact about those two rather than about the function returning a fixed object.

The comments are honest. The field names are not. A caller reading a signature check as true reasonably believes this call checked a signature, and it checked nothing of the kind.

Why both of these matter more than a date rename

A version number describes a format. A proof block describes a guarantee. Getting the first right and the second wrong is worse than the reverse, because the first is checkable by a parser and the second is checkable only by somebody who reads the bytes.

Both findings are recorded rather than fixed, because this estate measures and does not edit the code it measures.

Keep reading

Credential Data Model 1.1 and 2.0, and a Proof Block That Names the Wrong Thing · Solidus