Cross-Custodian Attestation Convergence
Companion to Holder Claim Integrity (the first
link — Custodian ↔ Holder, proving a claim belongs to the right person) and
Custodian Onboarding (the two-tier provenance model this assumes:
ISSUED outranks CUSTODIAN_ATTESTED). This is the second and third links: what happens when
the same real-world document crosses two custodians, and what happens when the real original
issuer shows up after one or more custodians already attested it.
Naming note: “supersede” is used elsewhere in this codebase for an unrelated mechanism (a
catalog entry version superseding an older version of the same qualification). Every
“supersede”/“superseded” here refers only to wallet.credentials.superseded_by_credential_id — one
credential pointing to the newer one that succeeds it.
The scenario this closes
- Custodian A uploads document X, attests it. Holder claims it.
- Custodian B, unaware of A, requests evidence of the same credential type. The holder presents the very credential A attested. B has no way to learn A got there first, reviews and attests independently, creating a second, unlinked Tier-2 credential.
- Issuer C, the real original issuing authority, later issues a Tier-1 credential for the same record — also with zero awareness that A or B exist.
- An admin can converge A’s and B’s records onto C’s issuance, but only if they already happen to know all three credential IDs exist and go looking — nothing surfaces the match.
What’s already correct and must not change
- Cryptographic soundness is not in question. Every credential — A’s, B’s, C’s — is signed
independently by its own signer’s key. The
CustodianAttestationCredentialtype marker is embedded in the signed payload itself, so a Tier-2 attestation can never be mistaken for a Tier-1 signature. - The existing supersession-link validation stays exactly as is (tier/type/not-already- superseded checks) — every call site added here, automatic or admin-triggered, goes through it unmodified. What changes is who calls it for the unambiguous case.
- Tenant siloing stays intact. Nothing here adds a query that lets Custodian B browse Custodian A’s data generally — every new visibility mechanism is scoped to one specific credential the holder has already, voluntarily, presented to B, never a directory or search surface.
Design guardrails
| Guardrail | Meaning |
|---|---|
| Visibility is presentation-scoped, never a directory | Custodian B only ever learns about Custodian A’s attestation because the holder handed B that specific credential. B can never browse another custodian’s book. |
| Automation never gates the other party’s operation | Custodian B can always attest anyway; Issuer C can always issue anyway. “Advisory” governs whether attestation/issuance is blocked — it doesn’t mean every convergence link needs a human click. |
| No PII a custodian didn’t already have access to | Cross-custodian visibility surfaces that another party attested (org name, date, credential id) — never that party’s extracted document fields, internal notes, or reviewer identity. |
| Matching stays deterministic | Whether two credentials are about the same record is computed from exact/normalized field equality — holder_did, catalog_entry_version_id, corroborated by a secondary identity key — never an LLM judgment call. |
| No behavior change to Tier-1 issuance’s success path | Issuer C’s issuance succeeds identically whether or not a prior Tier-2 attestation exists, and whether or not this feature auto-links one. |
| Auto-link only on an unambiguous match; anything else escalates | See the decision flow below — anything short of all four conditions goes to the admin queue, never auto-applies and never silently drops. |
| Every auto-applied link is reversible and visible, never silent | Audited under a distinct system-actor identity, immediately visible to the affected custodian on their own credential’s existing detail view, and reversible by an admin at any time. |
Embed an attester display name on the credential
Today the signed VC’s issuer object carries a DID and no name, for every credential. It gains a
name field — additive only, no schema migration, since it lives inside the signed JSON — which is
the prerequisite for everything after it: cross-custodian visibility depends on the presented VC
actually naming its attester.
Cross-custodian visibility at presentation time
When an intake item’s source is holder-presented and the presented VC’s own type array
already contains CustodianAttestationCredential, three facts are extracted straight from the VC
the holder already handed over — no lookup into another custodian’s data required:
- The attesting org’s name.
- The attestation date.
- The presented credential’s own id.
This surfaces as a plain informational fact in the review UI — distinct from the existing “possible duplicate” warning, which means something different (“you might be about to attest something you already attested yourself”). This is “already attested by ‹org› on ‹date›” — informational, never blocking B’s own decision to attest.
Post-issuance convergence check on the issuer path
After a Tier-1 issuance has fully committed — never in the critical path that determines whether
issuance itself succeeds — a best-effort follow-up step queries for existing ACTIVE,
non-superseded CUSTODIAN_ATTESTED credentials sharing the same holder and catalog entry version.
Everything reaching the unambiguous outcome is the only path that skips a human. Every other leaf lands in the escalation queue — no fourth outcome, no path silently drops a match.
Admin surfaces
Two distinct surfaces for two distinct jobs — not one queue that reviews every match:
- Escalation queue — genuinely ambiguous cases only: multiple Tier-1 candidates for one Tier-2 record, or a custodian-internal-code record with no shared identifier to anchor a trustworthy match. Each row shows the full candidate set, so the admin resolves a real question. Resolving a row calls the same, unmodified supersession-link action, same validation, same admin-mediation guarantee as today. A one-time backfill pass at rollout applies the same check retroactively across every pre-existing pair.
- Auto-link oversight — a separate, simple list of links applied automatically, with no expiry on visibility, each entry tagged with the system-actor audit identity. One action: unlink, which clears the supersession pointer back to null without touching either credential’s own status or signature. The affected custodian sees the outcome passively through the existing “superseded by…” notice — the same notice whether a human or the system created the link.