Credential format
Baselayer’s KYA credential is a~-joined SD-JWT-VC:
typ: vc+sd-jwt, alg: EdDSA) carries the always-disclosed verification block in cleartext, the agent-key binding (cnf), and a _sd array of digests: one per selectively disclosable attribute. The plaintext values are never in this part:
base64url(JSON [salt, claim_path, claim_value]) — the only place the plaintext appears. The trailing empty segment is where the agent appends its Key Binding JWT at present time.
status.status_list is the credential’s live revocation check — an OAuth Token Status List (IETF draft-ietf-oauth-status-list) bit; a verifier fetches the list at uri and confirms this credential’s idx isn’t flagged revoked, independent of the expiry and digest checks below. This is what lets a credential be killed before it naturally expires.
How a verifier checks for tampering
For each Disclosure, computebase64url(sha-256(<wire segment exactly as received>)) and confirm it’s present in the signed _sd array. Only after that membership check passes is the claim read. Because the digest covers the exact encoded bytes, altering a single value changes the digest, drops it out of _sd, and the presentation is rejected as DISCLOSURE_DIGEST_MISMATCH. The issuer never re-signs — integrity rides entirely on the one signed digest set.
Omitting a Disclosure leaves its digest harmlessly in _sd (a digest alone reveals nothing) with the value simply absent — this is what lets one mint serve a narrower use case, and what lets a verifier enforce SCOPE_VIOLATION against any Disclosure outside a published scope.
Business credentials
A business credential carries two independently signed scopes end to end:<business JWT> ~ <business Disclosures> ~ <actor JWT> ~ <actor Disclosures> ~. Each scope’s verification / active_keys is always-disclosed; business.* and actor.user.* leaves are the salted Disclosures.
Counterparty credentials
One plain EdDSA JWS (typ: bl-counterparty+jwt), no Disclosures, no Key Binding JWT. Every claim is public-record fact and the credential is served verbatim at a well-known path rather than presented per-request.
Its sub is not the domain-based pairwise DID individual/business credentials use — it is keyed on the business’s public registry coordinates: did:web:<registry-domain>:businesses:<jurisdiction>:<filing-number>, resolved via GET /businesses/{jurisdiction}/{filing_number}/did.json rather than the issuer’s main .well-known/did.json. The separate domain claim is what a verifier actually matches against the site it’s visiting.