-
Notifications
You must be signed in to change notification settings - Fork 9
Replace sephereon/PEX presentation definitions with web5 js VCs implementation #112
Conversation
🦋 Changeset detectedLatest commit: b96056a The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
One note is this PR now explicitly types our offering's
It seems like this might be due to conflicting package deps but we've removed the dep from our protocols package. Haven't run into this before so any thoughts from others v welcome! For added info: Here's where Web5 import/exports sphereon's type |
I believe the issue is because So I'm guessing the TypeScript compiler is replacing the type reference w/ So yeah... it's an odd ball out, in that it's the only The other option is, we could change import type { PresentationDefinitionV2 as PexPresDefV2 } from '@sphereon/pex-models';
//...
export type PresentationDefinitionV2 = PexPresDefV2 to this... import type { PresentationDefinitionV2 } from '@sphereon/pex-models';
export type { PresentationDefinitionV2 } from '@sphereon/pex-models'; If we keep it as-is, then I would classify this as technical debt, albeit it's an extremely small amount of debt. The other option is, I think we should include a comment above the |
@@ -77,9 +74,9 @@ export class Rfq extends Message<'rfq'> { | |||
* @throws if rfq's claims do not fulfill the offering's requirements | |||
*/ | |||
async verifyClaims(offering: Offering | ResourceModel<'offering'>) { | |||
const { areRequiredCredentialsPresent } = pex.evaluateCredentials(offering.data.requiredClaims, this.claims) | |||
const requiredCredentialsPresent = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nit-pick, but variable name is slightly misleading IMO, could do either one of these...
const requiredCredentialsPresent = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims) | |
const requiredCredentialsPresent = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims).length > 0 |
And then update the if ()
condition below like this
if (!requiredCredentialsPresent) {
throw new Error(`claims do not fulfill the offering's requirements`)
}
Or, could do...
const requiredCredentialsPresent = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims) | |
const credentials = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims) |
and then keep the if ()
condition as-is (I think I prefer this way)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah good callout, totes agree.
@@ -77,9 +74,9 @@ export class Rfq extends Message<'rfq'> { | |||
* @throws if rfq's claims do not fulfill the offering's requirements | |||
*/ | |||
async verifyClaims(offering: Offering | ResourceModel<'offering'>) { | |||
const { areRequiredCredentialsPresent } = pex.evaluateCredentials(offering.data.requiredClaims, this.claims) | |||
const credentials = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this method return credentials or error encapsulated in an object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/**
* Selects credentials that satisfy a given presentation definition.
*
* @param {string[]} vcJwts The list of Verifiable Credentials to select from.
* @param {PresentationDefinitionV2} presentationDefinition The Presentation Definition to match against.
* @return {string[]} selectedVcJwts A list of Verifiable Credentials that satisfy the Presentation Definition.
*/
public static selectCredentials(
vcJwts: string[],
presentationDefinition: PresentationDefinitionV2
): string[] {
this.resetPex();
const selectResults: SelectResults = this.pex.selectFrom(presentationDefinition, vcJwts);
return selectResults.verifiableCredential as string[] ?? [];
}
it retuns the list of Verifiable Credentials that can satisfy the Presentation Definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually might be helpful to return the error. this way we can surface it back up to the caller
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose we use exceptions for error cases. Two benefits I can think of:
- The return type is scoped to the semantic use case, which makes naming more cohesive and self-evident (ex.
List<Credentials>
as opposed toSelectCredentialsResponse
(which would include acredentials
anderrors
arrays)) - By decoupling the error from the type, we have flexibility to introduce deeper call stacks abstracted behind the
selectCredentials
down the road, which could bubble-up exceptions, rather than having to then concern ourselves with passing errors up the callstack in return types
The counter argument is it makes the consumer have to use try/catch
which can become verbose, but it isn't much more verbose than the subsequent if (selectCredentialsResponse.errors?.length) { ...
@@ -50,8 +50,6 @@ | |||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this PR necessitates a version bump - would you be able to do that? the readme has a section on how to add a changeset and automatically bump the version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
automagic nice!
This is merged in now - decentralized-identity/web5-js#336 |
Took another look at this and wondered why we verify all claims submitted including those that aren't needed to satisfy our PD? Would it make sense to only verify those claims that satisfy the PD? Current: async verifyClaims(offering: Offering | ResourceModel<'offering'>) {
const credentials = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims)
if (!credentials.length) {
throw new Error(`claims do not fulfill the offering's requirements`)
}
for (let claim of this.claims) {
await VerifiableCredential.verify(claim)
}
} Proposed: async verifyClaims(offering: Offering | ResourceModel<'offering'>) {
const credentials = PresentationExchange.selectCredentials(this.claims, offering.data.requiredClaims)
if (!credentials.length) {
throw new Error(`claims do not fulfill the offering's requirements`)
}
for (let credential of credentials) {
await VerifiableCredential.verify(credential)
}
} @mistermoe @jiyoontbd @KendallWeihe |
Yeah, I think so! @jiyoontbd can you think of an instance where we need to verify claims which are not defined in the Offering? That is, the Offering has N-number of claim requirements, and the RFQ has (N+M)-number of requirements, and we need to verify all N+M of them? |
@KendallWeihe @kirahsapong that makes sense to me! The API is a bit different now that we're using web5/credentials, which allows us to get back the credentials that meet the requirements, so i don't see why we should verify all incoming claims from the RFQ. As long as the credential we get back from |
@@ -64,7 +65,9 @@ export class Offering extends Resource<'offering'> { | |||
} | |||
|
|||
/** Articulates the claim(s) required when submitting an RFQ for this offering. */ | |||
get requiredClaims() { | |||
// TODO: Remove type annotation once type alias replaced with direct export in @web5/credentials |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is good to go now, right? Do we have to wait on a release to be cut? If so, and that may be some time, then I'm cool with leaving this comment, opening and issue, and going ahead with a merge here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this lgtm! barring if we can go ahead and use the latest @web5/credentials
change
This PR addresses #25