pub struct DTGCredential { /* private fields */ }Expand description
Defined DTG Credentials
Implementations§
Source§impl DTGCredential
impl DTGCredential
Sourcepub fn new_vmc(
issuer: String,
subject: String,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
personhood: bool,
) -> Self
pub fn new_vmc( issuer: String, subject: String, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, personhood: bool, ) -> Self
Creates a new community-issued Verifiable Membership Credential (VMC) — the membership grant, the community → member half of a membership edge.
A membership edge is a pair of VMCs, and this is only one of them. The member answers with DTGCredential::new_member_vmc_for, and the edge is not complete until they have: a community can always issue a credential naming somebody as a member, but it cannot produce the acknowledgement without that party’s signature. The pair is what makes an unconsented membership claim unprovable.
The grant MUST NOT carry a digestMultibase — that property is what marks the
other direction — and this constructor does not set one.
§issuerScope is always public
A community’s own identifier can only truthfully be declared public — a community
that cannot be found cannot be joined — so there is no parameter for it: the grant
declares public, and a grant declaring anything else is refused at parse. The
member declares its own scope in the acknowledgement.
issuer: The identifier of the VTC or VTN granting membership subject: The member’s identifier, or the member VTC’s own for VTN membership valid_from: The datetime from which this credential is valid valid_until: Optional: The datetime this credential is valid until personhood: Whether this VMC can be used as a form of Personhood Credential - Adds PersonhoodCredential to the type array if true, as the non-authoritative hint DTG Core Credentials permits. PHC status is determined by governance and trust registries, never by this string.
§Give it an id
Chain DTGCredential::with_id on: the member stores the grant under its id, and
re-issuing is only recognisable as a renewal rather than a duplicate if there is one.
Sourcepub fn new_member_vmc_for(
grant: &Value,
member: &str,
issuer_scope: IssuerScope,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Result<Self, DTGCredentialError>
pub fn new_member_vmc_for( grant: &Value, member: &str, issuer_scope: IssuerScope, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Result<Self, DTGCredentialError>
Creates a new member-issued Verifiable Membership Credential (VMC) — the membership acknowledgement, the member → community half of a membership edge.
The roles of DTGCredential::new_vmc are reversed (the member issues, the community
is the subject) and the subject carries a digestMultibase of the grant being
acknowledged.
That digest is what binds the two halves into one edge: an acknowledgement whose
digest matches no valid grant does not complete anything, and the binding forces an
order — the grant must exist before this can reference it.
This is the member’s consent artifact. Because the member is its issuer, withdrawing consent needs no cooperation from the community.
§Takes the grant in its wire form, deliberately
grant is the JSON the community sent, not a parsed DTGCredential. The digest has
to cover the document the community will recompute it over, and this library does
not model every member a credential may carry — credentialStatus, which every VMC
issued against a status list carries, is dropped by a parse-then-re-serialise round
trip. Building the acknowledgement from a parsed grant would produce a digest that
verifies nowhere, and would do it silently.
So: keep the bytes you were given, and pass them here.
member: The member acknowledging — the party whose key will sign this. Refused unless
the grant names exactly this identifier as its subject.
issuer_scope: The correlation scope the member declares for member — its own
choice, which this specification does not constrain. Declare the same scope
on every credential issued under one identifier.
valid_from: The datetime from which this credential is valid
valid_until: Optional: The datetime this credential is valid until. Must not be later
than the grant’s own validUntil, and must be set if the grant’s is.
§Errors
DTGCredentialError::NotAMembershipGrant if grant is not a JSON object, does not
carry MembershipCredential in its type, has no issuer or
credentialSubject.id, or already carries a digestMultibase — that last is an
acknowledgement, and acknowledging one does not form an edge. Also if its
issuerScope is not public, the only scope a community-issued grant can carry.
It is also DTGCredentialError::NotAMembershipGrant if the grant carries a
validUntil that is not an RFC 3339 timestamp.
DTGCredentialError::NotTheGrantSubject if the grant’s credentialSubject.id is not
member.
DTGCredentialError::OutlivesGrant if the grant expires and valid_until is later
than it, or absent.
DTGCredentialError::InvalidValidityWindow if valid_until is not after
valid_from, and DTGCredentialError::JsonTooDeep if the grant is nested more deeply
than crate::MAX_JSON_DEPTH.
§Give it an id
Chain DTGCredential::with_id on before signing. A community keys a member’s VMC by
id to tell a re-send from a renewal.
§Security
The result is binding evidence, not membership. This constructor does not verify the
grant’s proof, so it builds an acknowledgement of a grant nobody signed as readily as
of one the community did. Verify the grant first — with
verify_grant_with_public_key under the affinidi-signing feature, or against your
own resolver — and treat the edge as complete only once both proofs and both windows
have verified.
Pass as member the identity whose key will sign the acknowledgement, established
independently of the grant. An identifier read out of the grant would make the check
compare the grant with itself.
Sourcepub fn new_vrc(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Self
pub fn new_vrc( issuer: String, issuer_scope: IssuerScope, subject: String, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Self
Creates a new Verified Relationship Credential (VRC)
issuer: The DID of the source party
issuer_scope: The scope the source party declares for issuer. pairwise is
RECOMMENDED; a wider declaration is a disclosure made deliberately.
subject: The DID of the target party as used in this relationship
valid_from: The datetime from which this credential is valid
valid_until: Optional: The datetime this credential is valid until
Sourcepub fn new_vic(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Self
pub fn new_vic( issuer: String, issuer_scope: IssuerScope, subject: String, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Self
Creates a new Verified Invitation Credential (VIC)
issuer: The DID of the VTC or VTN, or of an authorized member or member VTC
issuer_scope: The scope the issuer declares for issuer — public where the issuer
is the VTC or VTN itself
subject: The DID of the prospective member or member VTC
valid_from: The datetime from which this credential is valid
valid_until: Optional: The datetime this credential is valid until. Keep it short:
an invitation should be single-use and short-lived.
Sourcepub fn new_vac(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
scope: String,
actions: Vec<String>,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
) -> Result<Self, DTGCredentialError>
pub fn new_vac( issuer: String, issuer_scope: IssuerScope, subject: String, scope: String, actions: Vec<String>, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, ) -> Result<Self, DTGCredentialError>
Creates a new Verifiable Authority Credential (VAC) — a chain root.
The issuer is the party governing scope. To derive a narrower VAC from one you
already hold, use DTGCredential::attenuate instead: a chain root is a grant made
by the governing party, and minting one directly is how a self-issued grant of
arbitrary authority gets in.
actions MUST NOT be empty — an empty list confers nothing rather than everything.
issuer_scope is the governing party’s declaration for its own identifier —
public where the issuer is the party governing the scope, which a chain root’s
issuer is. For a community conferring a role on a member,
DTGCredential::new_community_role_vac fixes it.
Attenuation below this VAC is permitted by default. To bound or forbid it, chain DTGCredential::with_max_attenuation on before signing.
let vac = DTGCredential::new_vac(
"did:example:room".to_string(),
IssuerScope::Public,
"did:example:member".to_string(),
"did:example:room".to_string(),
vec!["read".to_string(), "write".to_string()],
Utc::now(),
Utc::now() + Duration::days(30),
)
.unwrap();
assert_eq!(vac.credential().authority().unwrap().actions, ["read", "write"]);§valid_until is required
Not optional, unlike the base structure and unlike every other new_* constructor
here. Nothing about the subject’s current standing is consulted when a VAC is
verified, so authority that does not expire is authority nobody can withdraw by
waiting.
§Errors
DTGCredentialError::InvalidValidityWindow if valid_until is not after
valid_from, and DTGCredentialError::EmptyAuthorityActions if actions is empty.
Sourcepub fn new_community_role_vac(
community: String,
member: String,
role: &str,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
) -> Result<Self, DTGCredentialError>
pub fn new_community_role_vac( community: String, member: String, role: &str, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, ) -> Result<Self, DTGCredentialError>
Creates the VAC a community issues to confer a role on one of its members: a
chain root with scope the community’s own DID and actions the single
role:<name> action role_action spells.
A role is authority, not reputation. It is conferred by the party governing the scope — the community — and a verifier reads it as a decision that party made, which is what a VAC is and an endorsement is not. So the vetter role a community makes a member eligible for is:
let vac = DTGCredential::new_community_role_vac(
"did:example:community".to_string(),
"did:example:member".to_string(),
"vetter",
Utc::now(),
Utc::now() + Duration::days(90),
)
.unwrap();
assert_eq!(vac.issuer_scope(), IssuerScope::Public);
let authority = vac.credential().authority().unwrap();
assert_eq!(authority.scope, "did:example:community");
assert_eq!(authority.actions, ["role:vetter"]);issuerScope is public, the only scope a community can truthfully declare. The
role is checked like any other action — exactly and case-sensitively, through
crate::authority::verify_chain with requested_scope the community’s DID and
requested_action the role:<name> string. A member holding several roles holds
several VACs, or one built with DTGCredential::new_vac listing every role action:
actions stays a plain string set, and nothing here privileges the role:
convention over any other action a community defines.
Membership is a separate credential. A role VAC does not attest that its subject is a member, and a verifier requiring both asks for both.
§Errors
As DTGCredential::new_vac. role is not validated beyond being non-empty.
Sourcepub fn with_max_attenuation(
self,
max_attenuation: u32,
) -> Result<Self, DTGCredentialError>
pub fn with_max_attenuation( self, max_attenuation: u32, ) -> Result<Self, DTGCredentialError>
Sets authority.maxAttenuation on a VAC: the number of further attenuations
permitted below it, with 0 forbidding attenuation outright.
For a chain root, where any value is the governing party’s to choose. On a VAC this library attenuated, pass the limit to DTGCredential::attenuate instead, which refuses one above what the parent permits; set here, an over-limit value is not caught until crate::authority::verify_chain rejects the chain.
§Set it before signing
Same caveat as DTGCredential::with_id.
§Errors
DTGCredentialError::NotAnAuthorityCredential on anything but a VAC.
Sourcepub fn attenuate(
&self,
issuer_scope: IssuerScope,
subject: String,
actions: Vec<String>,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
max_attenuation: Option<u32>,
) -> Result<Self, DTGCredentialError>
pub fn attenuate( &self, issuer_scope: IssuerScope, subject: String, actions: Vec<String>, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, max_attenuation: Option<u32>, ) -> Result<Self, DTGCredentialError>
Derive a narrower VAC from one this holder already holds.
This is what lets a member equip an agent, a device, or a short-lived session with
only the authority that task needs, rather than lending it their own. The derived
credential is issued by the holder, not by the party governing the scope, and
carries parent — the digest of the credential it narrows — so a verifier can
walk back to a root.
Refuses anything that would widen. The checks here mirror crate::authority::verify_chain on purpose: a holder should be unable to build a chain a verifier would reject, so the failure surfaces at issue time rather than at use — but the verifier’s checks remain authoritative, because nothing stops a different implementation constructing the JSON by hand.
selfmust be a VAC, and must not bearmaxAttenuation0.actionsmust be a subset of whatselfconfers.valid_untilmust not exceedself’s.max_attenuationmust not exceed one less thanself’s, whereselfbears one.Nonetakes that ceiling — the strictest the chain already imposes — or, whereselfbears none, leaves the derived VAC unbounded too.
issuer_scope is the attenuating holder’s own declaration for its identifier: the
derived VAC’s issuer is self’s subject, and it is that party’s scope to declare.
§Binding the derivative to the agent is subject, not a separate field
A VAC is not a bearer credential: crate::authority::verify_chain requires the
party presenting the leaf to be its subject. So equipping an agent means naming the
agent in subject, and there is nothing further to bind. An earlier version of this
method took an audience for that job; it was removed with the property.
§Digests the model
The parent digest is computed with DTGCredential::digest_multibase, which hashes
this in-memory credential. That is right for a VAC this process built and signed.
For one that arrived from a counterparty, use
DTGCredential::attenuate_from_json and give it the bytes you received — the same
distinction DTGCredential::new_member_vmc_for draws, and for the same reason.
Sourcepub fn attenuate_from_json(
parent: &Value,
issuer_scope: IssuerScope,
subject: String,
actions: Vec<String>,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
max_attenuation: Option<u32>,
) -> Result<Self, DTGCredentialError>
pub fn attenuate_from_json( parent: &Value, issuer_scope: IssuerScope, subject: String, actions: Vec<String>, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, max_attenuation: Option<u32>, ) -> Result<Self, DTGCredentialError>
Derive a narrower VAC from a parent in its wire form.
Identical to DTGCredential::attenuate except that the parent is the JSON a
counterparty sent rather than a parsed credential, so the parent digest covers
the document the verifier will recompute it over. Use this whenever the VAC being
narrowed came from somewhere else.
§Errors
DTGCredentialError::NotAnAuthorityCredential if parent is not a JSON object
carrying AuthorityCredential in its type and a well-formed
credentialSubject.authority, and the same widening errors as
DTGCredential::attenuate.
Sourcepub fn new_vdc(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
scope: Vec<String>,
max_depth: Option<u32>,
) -> Result<Self, DTGCredentialError>
pub fn new_vdc( issuer: String, issuer_scope: IssuerScope, subject: String, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, scope: Vec<String>, max_depth: Option<u32>, ) -> Result<Self, DTGCredentialError>
Creates a new Verifiable Delegation Credential (VDC) — the delegation grant, the delegator → delegate half of a delegation edge.
Establishes that subject may act in the issuer’s name, for the acts named in
scope, until valid_until. Within that scope what the delegate does is
attributable to the delegator.
§This is not authority
A VDC never supplies permission the delegator did not itself hold. A verifier substitutes the delegator for the delegate and then asks the permission question it would have asked of the delegator directly — so withdrawing the delegator’s own permission ends the delegate’s ability to act immediately, without revoking anything. See DTGCredential::new_vac for the credential that answers that question.
§The edge is not complete without the acceptance
This is one half. The delegate answers with DTGCredential::new_delegate_vdc_for, and a verifier MUST obtain and verify that half before accepting any party as acting under the delegation: a grant alone establishes what the delegator appointed, not what the delegate agreed to. Same consent rule as a membership edge, and for the same reason — a delegator can always name someone as its delegate, but cannot produce the countersignature.
scope MUST NOT be empty: a VDC cannot express an unbounded appointment by
omitting it.
max_depth is the number of further re-delegations permitted below this one.
None and Some(0) both prohibit re-delegation — the default is a single hop, and
setting it above zero is the delegator’s explicit authorisation, of which there is
no other kind.
issuer_scope is the delegator’s declaration for issuer. A VDC is presented to
every verifier the delegate acts toward, so pairwise is seldom truthful and
directed is the ordinary declaration.
§valid_until is required
An appointment with no expiry cannot be reasoned about by a verifier that cannot reach the delegator.
§Errors
DTGCredentialError::MalformedDelegation if scope is empty, and
DTGCredentialError::InvalidValidityWindow if valid_until is not after
valid_from.
Sourcepub fn redelegate(
&self,
issuer_scope: IssuerScope,
subject: String,
scope: Vec<String>,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
) -> Result<Self, DTGCredentialError>
pub fn redelegate( &self, issuer_scope: IssuerScope, subject: String, scope: Vec<String>, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, ) -> Result<Self, DTGCredentialError>
Derive a further VDC from one this delegate already holds — a re-delegation.
Only permitted where the held VDC sets maxDepth above zero, and only for a subset
of the acts it was itself appointed for. The default is a single hop: a delegate
that needs a further delegate and is not authorised to re-delegate asks the
principal, who issues a fresh root delegation directly — so that the principal
always holds the complete register of who may speak in its name.
The derived VDC carries parent, the digest of the VDC it derives from, and a
maxDepth one less than its parent’s.
Like DTGCredential::attenuate, this digests the in-memory model; for a grant that arrived from a counterparty, use DTGCredential::redelegate_from_json.
issuer_scope is the re-delegating delegate’s own declaration for its identifier.
§Errors
DTGCredentialError::MalformedDelegation if self is not a delegation grant, if
it does not permit re-delegation, if scope is empty or not a subset of the
parent’s, or if valid_until is later than the parent’s.
DTGCredentialError::InvalidValidityWindow if valid_until is not after
valid_from.
Sourcepub fn redelegate_from_json(
parent: &Value,
issuer_scope: IssuerScope,
subject: String,
scope: Vec<String>,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
) -> Result<Self, DTGCredentialError>
pub fn redelegate_from_json( parent: &Value, issuer_scope: IssuerScope, subject: String, scope: Vec<String>, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, ) -> Result<Self, DTGCredentialError>
Derive a further VDC from a parent grant in its wire form.
Identical to DTGCredential::redelegate except that the parent is the JSON the
delegator sent, so the parent digest covers the document a verifier will
recompute it over.
Sourcepub fn new_delegate_vdc_for(
grant: &Value,
delegate: &str,
issuer_scope: IssuerScope,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>,
) -> Result<Self, DTGCredentialError>
pub fn new_delegate_vdc_for( grant: &Value, delegate: &str, issuer_scope: IssuerScope, valid_from: DateTime<Utc>, valid_until: DateTime<Utc>, ) -> Result<Self, DTGCredentialError>
Creates the delegate-issued half of a delegation edge — the acceptance.
The roles of DTGCredential::new_vdc are reversed (the delegate issues, the
delegator is the subject) and the subject carries accepts, the digest of the
grant being taken on. That digest is what binds the two halves into one edge.
An acceptance carries no scope of its own. What the delegate consented to is the
scope of the grant it names, which a verifier holds in any case; restating it would
require an equality check across the two credentials that cannot be satisfied under
selective disclosure of either.
This is the delegate’s consent artifact, and its accountability for acting in another’s name. Because a delegator cannot produce it, a party holding only the delegate’s key cannot manufacture appointments either.
§Takes the grant in its wire form, deliberately
Same reasoning as DTGCredential::new_member_vmc_for: the digest has to cover the document the delegator will recompute it over. Keep the bytes you were given and pass them here.
§Errors
DTGCredentialError::NotADelegationGrant if grant is not a JSON object carrying
DelegationCredential in its type, has no issuer or credentialSubject.id, or
already carries accepts — that last is itself an acceptance, and accepting one
forms no edge.
It is also DTGCredentialError::NotADelegationGrant if the grant carries a
validUntil that is not an RFC 3339 timestamp.
DTGCredentialError::NotTheGrantSubject if the grant’s credentialSubject.id is not
delegate.
DTGCredentialError::OutlivesGrant if valid_until is later than the grant’s.
DTGCredentialError::InvalidValidityWindow if valid_until is not after
valid_from, and DTGCredentialError::JsonTooDeep if the grant is nested more deeply
than crate::MAX_JSON_DEPTH.
§Security
The result is binding evidence, not an appointment. This constructor does not verify
the grant’s proof, so it builds an acceptance of a grant nobody signed as readily as of
one the delegator did. Verify the grant first — with verify_grant_with_public_key
under the affinidi-signing feature, or against your own resolver — and treat the edge
as complete only once both proofs and both windows have verified.
Pass as delegate the identity whose key will sign the acceptance, established
independently of the grant. An identifier read out of the grant would make the check
compare the grant with itself.
Sourcepub fn new_vpc(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Self
pub fn new_vpc( issuer: String, issuer_scope: IssuerScope, subject: String, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Self
Creates a new Verified Persona Credential (VPC)
issuer: The DID under which the persona is asserted
issuer_scope: The scope declared for issuer — ordinarily directed, since a
persona exists to be recognized across counterparties the holder chooses
subject: The DID of the counterparty as used in the relationship
valid_from: The datetime from which this credential is valid
valid_until: Optional: The datetime this credential is valid until
Sourcepub fn with_id(self, id: impl Into<String>) -> Self
pub fn with_id(self, id: impl Into<String>) -> Self
Sets this credential’s own identifier, consuming and returning it so it chains onto
any of the new_* constructors above.
id MUST be a single URL per the W3C VC Data Model; urn:uuid:<uuid> is the usual
choice for a credential with no dereferenceable home. This crate does not validate it.
let vmc = DTGCredential::new_vmc(
"did:example:community".to_string(),
"did:example:member".to_string(),
Utc::now(),
None,
false,
)
.with_id("urn:uuid:2a4e1d90-6e0c-4d3f-9a4a-6d0a8f7c1b52");
assert_eq!(vmc.id(), Some("urn:uuid:2a4e1d90-6e0c-4d3f-9a4a-6d0a8f7c1b52"));§Set it before signing
A Data Integrity proof covers the credential minus its proof, so id is part of what
is signed. Chain this onto the constructor, before DTGCredential::sign — adding an id
to an already-signed credential leaves a document whose proof no longer verifies.
Sourcepub fn set_id(&mut self, id: impl Into<String>)
pub fn set_id(&mut self, id: impl Into<String>)
Sets this credential’s own identifier in place.
The non-consuming form of DTGCredential::with_id; the same “before signing” caveat applies.
Sourcepub fn with_task_citation(
self,
document: &Value,
) -> Result<Self, DTGCredentialError>
pub fn with_task_citation( self, document: &Value, ) -> Result<Self, DTGCredentialError>
Cites a Trust Task document: sets taskContext to its id and
taskDigestMultibase to its task digest, together.
Use it for any credential whose meaning depends on an exchange — a VSC under a
profile requiring taskContext, such as a VWC or a statement a vetting/session
produces. Name the innermost exchange that attests
what the credential states, by the document that initiated it (Trust Tasks §4.9.1).
Setting both halves from one document is the point: the id locates the exchange
and the digest binds the credential to it, and a pair taken from two places binds
nothing. See crate::task_digest_multibase_json for how the digest is computed.
Replaces a taskContext and taskDigestMultibase already set.
§Set it before signing
Both members are covered by the credential’s proof, as for DTGCredential::with_id.
§Errors
DTGCredentialError::MalformedTaskDocument if document is not an object with a
string id; DTGCredentialError::JsonTooDeep if it is nested past
crate::MAX_JSON_DEPTH.
Sourcepub fn set_task_citation(
&mut self,
document: &Value,
) -> Result<(), DTGCredentialError>
pub fn set_task_citation( &mut self, document: &Value, ) -> Result<(), DTGCredentialError>
Cites a Trust Task document in place.
The non-consuming form of DTGCredential::with_task_citation; the same caveats apply. On error, the credential is left unchanged.
Sourcepub fn with_credential_status(self, status: Value) -> Self
pub fn with_credential_status(self, status: Value) -> Self
Attaches the status mechanism through which a verifier determines whether this credential has been revoked.
The entry is opaque to this library: the mechanism is chosen by the governing VTC
or VTN, and nothing here selects one or resolves it. BitstringStatusListEntry is
the common choice.
let vdc = DTGCredential::new_vdc(
"did:example:delegator".to_string(),
IssuerScope::Directed,
"did:example:delegate".to_string(),
Utc::now(),
Utc::now() + Duration::days(90),
vec!["sign:invoices".to_string()],
None,
)
.unwrap()
.with_credential_status(json!({
"id": "https://example.com/status/3#94567",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "94567",
"statusListCredential": "https://example.com/status/3"
}));
assert!(vdc.credential().credential_status.is_some());§When a VDC needs one
CONDITIONAL, not required. A verifier MUST be able to establish that an appointment
is in force without contacting the delegator, and either of two things satisfies
that: a validUntil short enough that expiry alone bounds the exposure, or a status
entry the verifier can check. A VDC MUST carry one where its validity period exceeds
the freshness window the governing VTC or VTN defines for delegations, and MAY omit
it otherwise.
That window is governance this library does not know, so it cannot decide for a caller which side of the condition a given VDC falls on — hence a setter rather than a constructor parameter. Prefer short validity and re-issuance wherever the delegator is reachable: a status check is a live lookup that reveals the verification event to whoever hosts the status list. A long-lived appointment made in advance of a delegator’s unavailability is the case this exists for.
§Set it before signing
Same caveat as DTGCredential::with_id — a Data Integrity proof covers the
credential minus its proof, so attaching a status entry to an already-signed
credential leaves a document whose proof no longer verifies.
§This library does not check it
Neither crate::delegation::verify_chain nor crate::authority::verify_chain
resolves a status entry; both verify structure, scope and validity only. Revocation
is a live lookup the caller performs.
§Security
The entry is embedded verbatim and nothing about it is checked when it is attached. It tells a verifier where to look, so a verifier must check the credential’s proof before following it, and should apply its own policy to where it leads. Nesting past crate::MAX_JSON_DEPTH is refused when the credential is validated, digested or signed, because this setter cannot return an error.
Sourcepub fn set_credential_status(&mut self, status: Value)
pub fn set_credential_status(&mut self, status: Value)
Attaches a revocation status mechanism in place.
The non-consuming form of DTGCredential::with_credential_status; the same “before signing” caveat, the same CONDITIONAL rule and the same security notes apply.
Source§impl DTGCredential
impl DTGCredential
Sourcepub fn new_vsc(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
predicate: impl Into<String>,
object: StatementObject,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Result<Self, DTGCredentialError>
pub fn new_vsc( issuer: String, issuer_scope: IssuerScope, subject: String, predicate: impl Into<String>, object: StatementObject, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Result<Self, DTGCredentialError>
Creates a Verifiable Statement Credential (VSC) under any predicate.
issuer/issuer_scope: the party making the statement, and the correlation scope it declares for that identifier.subject: the DID of the node the statement is about.predicate: the absolute IRI fixing the statement’s meaning — one of the core constants (ENDORSES_V1, WITNESSED_V1, VETTED_V1, PRESENTED_V1) or a predicate a community defines in a namespace it controls.object: exactly one ofid,digestMultibaseorvalue.
Prefer the profile constructors for the core predicates — Self::new_endorses_vsc,
Self::new_witnessed_vsc, Self::new_vetted_vsc, Self::new_presented_vsc — which
set the citation a profile requires and enforce its subject–object rule. This one
checks what it can without them: the predicate, the object kind and the minimum
issuerScope of a core profile. A profile that REQUIRES taskContext is completed
with DTGCredential::with_task_citation, and DTGCredential::validate — so also
DTGCredential::sign — refuses it until it is.
§Errors
DTGCredentialError::InvalidPredicate for a predicate that is not an absolute NFC
IRI, DTGCredentialError::ProfileViolation for an object a core profile does not
permit, DTGCredentialError::IssuerScopeTooNarrow for a scope below a core
profile’s minimum, DTGCredentialError::InvalidValidityWindow for a window that
closes before it opens, and DTGCredentialError::JsonTooDeep for an object.value
nested past crate::MAX_JSON_DEPTH.
Sourcepub fn new_endorses_vsc(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
endorsement: Value,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Result<Self, DTGCredentialError>
pub fn new_endorses_vsc( issuer: String, issuer_scope: IssuerScope, subject: String, endorsement: Value, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Result<Self, DTGCredentialError>
Creates a VEC — a statement under ENDORSES_V1 — endorsing subject with
endorsement as object.value.
The endorsement’s schema is the governing community’s vocabulary, and nothing about it is checked but its depth. A VEC says only that its issuer said this: a verifier must establish that the issuer is one whose endorsements it accepts for this purpose before relying on any member of it.
Not a role grant. A role confers something, and conferring is a VAC’s job: see DTGCredential::new_community_role_vac.
§Errors
Sourcepub fn new_witnessed_vsc(
issuer: String,
issuer_scope: IssuerScope,
witnessed: &Value,
session: &Value,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
witness_context: Option<WitnessContext>,
) -> Result<Self, DTGCredentialError>
pub fn new_witnessed_vsc( issuer: String, issuer_scope: IssuerScope, witnessed: &Value, session: &Value, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, witness_context: Option<WitnessContext>, ) -> Result<Self, DTGCredentialError>
Creates a VWC — a statement under WITNESSED_V1 — attesting that the witness
observed a party issue witnessed, in the witness/session that session opened.
Both halves of every binding are read from the documents themselves, so none of them can disagree:
credentialSubject.idiswitnessed’sissuer— the profile’s subject–object rule: the witness observed the subject issue it. One VWC per direction, so a witnessed VRC pair takes two calls, one with each VRC.object.digestMultibaseis the digest ofwitnessedin its wire form, top-levelproofexcluded, as crate::digest_multibase_json computes it.taskContextis theidofsession, andtaskDigestMultibaseits task digest (witness/session/submitConformance, item 1).
issuer is the witness — a member, or a VTA acting under VTC policy — and must
declare at least directed: a witness’s identifier must be recognizable to both
parties and to the community, so pairwise cannot describe it truthfully.
§Errors
- DTGCredentialError::IssuerScopeTooNarrow for
pairwise. - DTGCredentialError::ProfileViolation if
witnessedis not a JSON object with anissuer. - DTGCredentialError::MalformedTaskDocument if
sessionis not an object with a stringid; DTGCredentialError::NotAWitnessSession if itstypeis not awitness/sessionversion or itsthreadIdis not its ownid— which catches citing thesubmitdocument, or the relationship exchange the session is nested in. - DTGCredentialError::InvalidValidityWindow and DTGCredentialError::JsonTooDeep.
§Security
Pass the session document the witness itself received and answered, not one the party supplies alongside its submission, and the edge credential the witness itself observed. The digests are load-bearing because the witness signs them.
Sourcepub fn new_vetted_vsc(
issuer: String,
issuer_scope: IssuerScope,
subject: String,
vetting: Value,
session: &Value,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Result<Self, DTGCredentialError>
pub fn new_vetted_vsc( issuer: String, issuer_scope: IssuerScope, subject: String, vetting: Value, session: &Value, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Result<Self, DTGCredentialError>
Creates a vetting statement — a statement under VETTED_V1 — recording that the
issuer checked subject’s claimed identity in the vetting exchange session
opened.
vetting is object.value. This library is generic about it: the payload’s schema
is the registry definition’s, and a typed payload belongs with the code that fills
it in. session is the initiating document of the vetting exchange;
taskContext and taskDigestMultibase are both read from it.
issuer is the vetter, issuing under the member identifier its VMC names, and must
declare at least directed. Whether it was eligible to vet is a fact about the
community, checked separately — a community-issued VAC is the credential that
answers it (see DTGCredential::new_community_role_vac).
§Errors
DTGCredentialError::IssuerScopeTooNarrow for pairwise,
DTGCredentialError::MalformedTaskDocument if session has no string id, and the
errors of DTGCredential::new_vsc.
Sourcepub fn new_presented_vsc(
issuer: String,
issuer_scope: IssuerScope,
presented: &Value,
session: &Value,
valid_from: DateTime<Utc>,
valid_until: Option<DateTime<Utc>>,
) -> Result<Self, DTGCredentialError>
pub fn new_presented_vsc( issuer: String, issuer_scope: IssuerScope, presented: &Value, session: &Value, valid_from: DateTime<Utc>, valid_until: Option<DateTime<Utc>>, ) -> Result<Self, DTGCredentialError>
Creates a statement under PRESENTED_V1, attesting that the issuer observed a
party present presented in the exchange session opened.
As for DTGCredential::new_witnessed_vsc, both halves of each binding are read
from the documents: credentialSubject.id is presented’s own
credentialSubject.id — the party who holds it, and the profile’s subject–object
rule — object.digestMultibase its digest, and the citation session’s id and
task digest.
§Errors
DTGCredentialError::IssuerScopeTooNarrow for pairwise,
DTGCredentialError::ProfileViolation if presented has no credentialSubject.id,
DTGCredentialError::MalformedTaskDocument if session has no string id, and the
errors of DTGCredential::new_vsc.
Sourcepub fn witnesses_issuance_of(
&self,
credential: &Value,
) -> Result<bool, DTGCredentialError>
pub fn witnesses_issuance_of( &self, credential: &Value, ) -> Result<bool, DTGCredentialError>
Is this a WITNESSED_V1 statement about credential — the edge credential in its
wire form — and does the profile’s subject–object rule hold?
True when the predicate is witnessed/1, object.digestMultibase matches
credential’s recomputed digest (decoded bytes, not strings), and
credentialSubject.id is credential’s issuer. A verifier holding the referenced
credential MUST check both, and this is those two checks.
§What this does not check
The statement’s proof, its window, whether its issuer is a witness the verifier
trusts, its taskContext against the session (see DTGCredential::cites_task), and
whether credential is itself valid: a witness attestation is about claims at the
moment of witnessing, not about their being current.
§Errors
DTGCredentialError::InvalidDigest or DTGCredentialError::UnsupportedDigestAlgorithm
if the carried digest cannot be read, rather than Ok(false).
Sourcepub fn witnesses_presentation_of(
&self,
credential: &Value,
) -> Result<bool, DTGCredentialError>
pub fn witnesses_presentation_of( &self, credential: &Value, ) -> Result<bool, DTGCredentialError>
Is this a PRESENTED_V1 statement about credential in its wire form, with
credentialSubject.id equal to credential’s own credentialSubject.id?
The PRESENTED_V1 counterpart of DTGCredential::witnesses_issuance_of, with the same caveats.
Source§impl DTGCredential
impl DTGCredential
Sourcepub fn credential(&self) -> &DTGCommon
pub fn credential(&self) -> &DTGCommon
get the raw credential
Sourcepub fn credential_mut(&mut self) -> &mut DTGCommon
pub fn credential_mut(&mut self) -> &mut DTGCommon
Get the raw credential as mutable
Sourcepub fn type_(&self) -> DTGCredentialType
pub fn type_(&self) -> DTGCredentialType
get the credential type
Sourcepub fn id(&self) -> Option<&str>
pub fn id(&self) -> Option<&str>
This credential’s own identifier, if it has one.
None for a credential built by one of the new_* constructors and never given one
with DTGCredential::with_id. See DTGCommon::id for why a counterparty may require
it.
Sourcepub fn issuer_scope(&self) -> IssuerScope
pub fn issuer_scope(&self) -> IssuerScope
The correlation scope the issuer declares for its own identifier. See IssuerScope.
Sourcepub fn statement(&self) -> Option<&CredentialSubjectStatement>
pub fn statement(&self) -> Option<&CredentialSubjectStatement>
The statement, when this credential is a VSC. See DTGCommon::statement.
Sourcepub fn predicate(&self) -> Option<&str>
pub fn predicate(&self) -> Option<&str>
The predicate IRI, when this credential is a VSC.
Compare it byte for byte — PredicateAcceptList does — and never by spelling, prefix or a published equivalence.
Sourcepub fn valid_from(&self) -> DateTime<Utc>
pub fn valid_from(&self) -> DateTime<Utc>
Returns the valid_from timestamp
Sourcepub fn valid_until(&self) -> Option<DateTime<Utc>>
pub fn valid_until(&self) -> Option<DateTime<Utc>>
Returns the valid until timestamp
Sourcepub fn task_context(&self) -> Option<&str>
pub fn task_context(&self) -> Option<&str>
The id naming the trust task exchange this credential cites, if set. See
DTGCommon::task_context.
This is always Some for a VSC under a predicate profile that makes taskContext
REQUIRED — WITNESSED_V1, VETTED_V1 and PRESENTED_V1.
Sourcepub fn task_digest_multibase(&self) -> Option<&str>
pub fn task_digest_multibase(&self) -> Option<&str>
The task digest of the Trust Task document taskContext names, if set. See
DTGCommon::task_digest_multibase.
Sourcepub fn cites_task(&self, document: &Value) -> Result<bool, DTGCredentialError>
pub fn cites_task(&self, document: &Value) -> Result<bool, DTGCredentialError>
Does this credential cite document — the Trust Task document its taskContext
names — and is it bound to that document’s content?
Both halves of the citation have to hold:
taskContextequals the document’sid, which locates the exchange;taskDigestMultibasematches the task digest recomputed fromdocument, which binds the credential to it.
Returns Ok(false) where either fails, and where the credential carries no
taskContext or no taskDigestMultibase. The last case is deliberate: Trust Tasks
§4.9.3 forbids falling back to comparing ids alone, because an id is a name
anyone may reuse on a counterfeit.
§Compares bytes, not strings
The digest is recomputed with the top-level proof removed, so a signed and an
unsigned copy of the same document agree, and compared as decoded multihash bytes.
A task digest may be base58btc or base64url: two conforming encodings of one digest
are different strings, and a string comparison would reject an honest citation.
§What this does not check
That the exchange completed, which needs the outcome evidence of DTG Core Credentials §Outcome Interpretability, and that the document was attributable, which needs its own proof. A task digest attests content, not authenticity. It is load-bearing because it is the credential’s issuer who signed it.
§Errors
DTGCredentialError::InvalidDigest if the carried value is not a well-formed
multibase multihash, and DTGCredentialError::UnsupportedDigestAlgorithm if it
names a hash this library does not implement. Trust Tasks §4.9.3 requires such a
citation to be treated as unverified, never recomputed under another algorithm, so
it is reported rather than folded into Ok(false). DTGCredentialError::JsonTooDeep
if document is nested past MAX_JSON_DEPTH.
Sourcepub fn digest_multibase(&self) -> Result<String, DTGCredentialError>
pub fn digest_multibase(&self) -> Result<String, DTGCredentialError>
This credential’s digest, in the encoding a credential that references it carries —
a member-issued VMC acknowledging a membership grant, a VSC whose object names it
(a VWC attesting an edge credential), or the parent of an attenuated VAC.
Per DTG Core Credentials Digest Encoding, that is the SHA-256 hash of the
credential’s JSON representation excluding its top-level proof member,
canonicalized with the JSON Canonicalization Scheme
(JCS, RFC 8785), wrapped in a
sha2-256 multihash and encoded base58btc with a multibase z prefix.
§Why proof is excluded
The digest binds to what the credential says, not to a particular signature over it. A referencing credential therefore survives a re-proofing of its referent: a re-signed grant carrying identical claims still satisfies an acknowledgement made against the earlier signature. It also means the digest can be computed before the referent is signed, and is stable whichever of its proofs a holder happens to have.
§Prefer the wire form for a credential you received
This digests the model. DTGCommon::extra carries top-level members this library
does not model through a round trip, so for most received credentials the two agree
— but a member inside credentialSubject that the subject types do not model is
still not represented. Where you still hold the bytes a counterparty sent, digest
those with digest_multibase_json.
§Errors
DTGCredentialError::JsonTooDeep if an open JSON member takes the credential past
MAX_JSON_DEPTH, checked before the credential is cloned or serialized.
Sourcepub fn digest(&self) -> Result<String, DTGCredentialError>
👎Deprecated since 0.7.0: Working Draft 02 replaced the sha256:<hex> digest with a base58btc multibase multihash under the property name digestMultibase. Use DTGCredential::digest_multibase. This method will be removed in a future release.
pub fn digest(&self) -> Result<String, DTGCredentialError>
Working Draft 02 replaced the sha256:<hex> digest with a base58btc multibase multihash under the property name digestMultibase. Use DTGCredential::digest_multibase. This method will be removed in a future release.
This credential’s digest in the superseded sha256:<hex> encoding.
Sourcepub fn subject_digest(&self) -> Option<&str>
pub fn subject_digest(&self) -> Option<&str>
The digest this credential carries of the credential it references, if it carries one.
Some for a member-issued VMC (which MUST carry one), for a VSC whose object is a
digestMultibase (a VWC bound to the edge credential it attests, among them), for an
attenuated VAC (authority.parent), and for a derived or accepting VDC
(delegation.parent / delegation.accepts). None for a community-issued VMC,
which MUST omit it, and for a credential that references nothing.
Sourcepub fn verify_digest(
&self,
referenced: &DTGCredential,
) -> Result<bool, DTGCredentialError>
pub fn verify_digest( &self, referenced: &DTGCredential, ) -> Result<bool, DTGCredentialError>
Checks that the digest this credential carries matches the credential it claims to reference.
Answers one question only — whether the hashes agree. It does not check that the two credentials are of the types the reference requires, nor that their issuers and subjects line up. For a membership acknowledgement, DTGCredential::acknowledges checks all of that together and is what a verifier completing an edge should call.
§Compares bytes, not strings
The specification requires a verifier to decode the multibase envelope and the multihash inside it, and to compare the algorithm identifier and the raw digest — never the encoded strings. Two equal digests can be written differently, and a string comparison would report a mismatch where the credentials agree.
Returns Ok(false) if the digests do not match, or if this credential carries no
digest, in which case there is nothing to rely on.
§Errors
DTGCredentialError::InvalidDigest if the carried value is not a well-formed
digestMultibase — a Working Draft 01 sha256:<hex> value among them — and
DTGCredentialError::UnsupportedDigestAlgorithm if it names a hash this library
does not implement. Both are reported rather than folded into Ok(false): a digest
that cannot be read is not a digest that disagrees.
Sourcepub fn acknowledges(
&self,
grant: &DTGCredential,
) -> Result<bool, DTGCredentialError>
pub fn acknowledges( &self, grant: &DTGCredential, ) -> Result<bool, DTGCredentialError>
Does this member-issued VMC acknowledge grant, completing that membership edge?
A membership edge is complete only when both VMCs of the pair exist and are valid: the community-issued VMC that grants membership, and the member-issued VMC that acknowledges it. This checks everything that binds the two together:
grantis aMembershipCredentialcarrying nodigest— a community-issued grantselfis aMembershipCredentialcarrying one — a member-issued acknowledgement- the two name the same pair of parties, in mirrored roles: this credential’s issuer is the grant’s subject, and its subject is the grant’s issuer
- the
digestmatches the grant
Returns Ok(false) where any of those does not hold, rather than distinguishing
them: a caller deciding whether an edge is complete has one decision to make, and
every failing case answers it the same way.
§What this does not check
Neither credential’s proof, and neither validity window. Both are the caller’s to verify — proof verification needs a resolver this crate does not hold, and whether a window is current is a question about an instant the caller chooses. An edge is complete when both VMCs are valid as well as bound, and this covers only the binding.
§Security
Ok(true) is binding evidence, not membership. A pair binds whether or not anybody
signed either half: an acknowledgement can be built against a grant the community
never issued, and this accepts the two together. Before treating an edge as complete,
verify the grant’s proof against the community’s key and the acknowledgement’s
against the member’s — each made by a verification method of that credential’s
issuer — and check both windows at the instant you care about.
verify_grant_with_public_key, under the affinidi-signing feature, does that for
the grant in its wire form.
Sourcepub fn accepts(&self, grant: &DTGCredential) -> Result<bool, DTGCredentialError>
pub fn accepts(&self, grant: &DTGCredential) -> Result<bool, DTGCredentialError>
Does this delegate-issued VDC accept grant, completing that delegation edge?
A delegation edge is complete only when both VDCs exist and are valid: the delegator’s grant, and the delegate’s acceptance of it. This checks everything that binds the two together:
grantis aDelegationCredentialcarryingscopeand noaccepts— a grantselfis aDelegationCredentialcarryingaccepts— an acceptance- the two name the same pair of parties in mirrored roles: this credential’s issuer is the grant’s subject, and its subject is the grant’s issuer
- the
acceptsdigest matches the grant
Returns Ok(false) where any of those does not hold, rather than distinguishing
them: a caller deciding whether an edge is complete has one decision to make, and
every failing case answers it the same way.
§What this does not check
Neither credential’s proof, neither validity window, and neither’s revocation status. Nor does it establish that the delegator may perform the act in question — that is a separate question, asked of the delegator at the time of the act, which a VDC moves but never answers. This covers the binding.
§Security
As with DTGCredential::acknowledges, Ok(true) is binding evidence only. Verify
both proofs, each against a verification method of its own credential’s issuer, and
both windows, before accepting anybody as acting under the delegation.
Sourcepub fn proof_value(&self) -> Option<&str>
pub fn proof_value(&self) -> Option<&str>
Returns the proof value if signed else None
Sourcepub fn validate(&self) -> Result<(), DTGCredentialError>
pub fn validate(&self) -> Result<(), DTGCredentialError>
Checks the invariants this library holds a credential to before putting a proof on it.
- The validity window is well formed:
validUntil, where present, is aftervalidFrom(DTGCredentialError::InvalidValidityWindow). - No open JSON member — a statement’s
object.value,credentialStatus, an unmodelled member — takes the document pastMAX_JSON_DEPTH(DTGCredentialError::JsonTooDeep). The check does not recurse. - Everything a parse checks still holds: the
@contextandtypearrays, the subject’s shape for the type,issuerScopewhere the type or profile constrains it, a VSC’spredicate, and the constraints of its core profile —taskContextandtaskDigestMultibasewhere WITNESSED_V1, VETTED_V1 or PRESENTED_V1 require them. DTGCredential::credential_mut can break any of these, and this is where a broken credential is caught before it is signed.
DTGCredential::sign calls this first, so this library never signs a credential
that fails it, and DTGCredential::verify_proof_with_public_key calls it before
examining a proof. The new_* constructors that return a plain Self have no way to
refuse, so a credential built by one of them is checked here rather than there. If
you sign with another backend, call this yourself before you do.
A validFrom in the past is accepted. Backdating is legitimate — re-issuing a
credential with the date the original took effect is the usual case — so only the
ordering of the two ends is checked, never either end against the clock.
Sourcepub async fn sign(
&mut self,
signing_secret: &Secret,
create_time: Option<DateTime<Utc>>,
) -> Result<DataIntegrityProof, DTGCredentialError>
pub async fn sign( &mut self, signing_secret: &Secret, create_time: Option<DateTime<Utc>>, ) -> Result<DataIntegrityProof, DTGCredentialError>
Sign the credential using W3C Data Integrity Proof with JCS EdDSA 2022 signing_secret: The secret key to use to sign the credential create_time: Optional creation time for the proof, defaults to now if None
§Errors
Anything DTGCredential::validate refuses, before any signing is attempted.
Sourcepub fn verify_proof_with_public_key(
&self,
public_key_bytes: &[u8],
) -> Result<(), DTGCredentialError>
pub fn verify_proof_with_public_key( &self, public_key_bytes: &[u8], ) -> Result<(), DTGCredentialError>
Verify the credential if you already know the public key bytes otherwise use the affinidi_tdk:verify_data() method public_key_bytes: The public key bytes to use to verify the credential
§Errors
Anything DTGCredential::validate refuses, before the proof is examined: a credential this library would not have signed does not verify either.
Sourcepub fn get_w3c_vc_version(&self) -> W3CVCVersion
pub fn get_w3c_vc_version(&self) -> W3CVCVersion
Is this credential a W3C VC Version 1.1 or 2.0 credential?
Sourcepub fn is_personhood_credential(&self) -> bool
pub fn is_personhood_credential(&self) -> bool
returns true if this credential a personhood credential (PHC)
Trait Implementations§
Source§impl Clone for DTGCredential
impl Clone for DTGCredential
Source§impl Debug for DTGCredential
impl Debug for DTGCredential
Source§impl<'de> Deserialize<'de> for DTGCredential
impl<'de> Deserialize<'de> for DTGCredential
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Serialize for DTGCredential
impl Serialize for DTGCredential
Source§impl TryFrom<DTGCommon> for DTGCredential
Post deserialize setup of a CredentialSubject and CredentialType
impl TryFrom<DTGCommon> for DTGCredential
Post deserialize setup of a CredentialSubject and CredentialType
Source§impl TryFrom<Value> for DTGCredential
Deserialization: @context and type are checked on the raw document first, so that a
credential of a retired type, or under an unrecognized context, is refused with an error
that says so — rather than with whatever the subject’s shape happens to fail on.
impl TryFrom<Value> for DTGCredential
Deserialization: @context and type are checked on the raw document first, so that a
credential of a retired type, or under an unrecognized context, is refused with an error
that says so — rather than with whatever the subject’s shape happens to fail on.