-
Notifications
You must be signed in to change notification settings - Fork 1
Support status checks via workflows. #152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #152 +/- ##
==========================================
+ Coverage 82.38% 82.69% +0.31%
==========================================
Files 15 15
Lines 4529 4611 +82
==========================================
+ Hits 3731 3813 +82
Misses 798 798
Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
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.
A few questions / suggestions.
The new tests look a little gnarly but I do not have specific suggestions yet.
if(verifyPresentationOptions.checks !== undefined) { | ||
for(const check in verifyPresentationOptions.checks) { | ||
if(verifyPresentationOptions.checks[check] == true) { | ||
if(!checks.includes(check)) { | ||
checks.push(check); | ||
} | ||
} | ||
} | ||
} | ||
options.checks = checks; |
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.
if(verifyPresentationOptions.checks !== undefined) { | |
for(const check in verifyPresentationOptions.checks) { | |
if(verifyPresentationOptions.checks[check] == true) { | |
if(!checks.includes(check)) { | |
checks.push(check); | |
} | |
} | |
} | |
} | |
options.checks = checks; | |
const checksSet = new Set(checks); | |
if(verifyPresentationOptions.checks) { | |
for(const [check, enabled] of Object.entries(verifyPresentationOptions.checks)) { | |
if(enabled) { | |
checksSet.add(check); | |
} | |
} | |
} | |
options.checks = Array.from(checksSet); |
I'm not sure what's being checked with verifyPresentationOptions.checks[check]
.
result = await zcapClient.write({ | ||
capability, | ||
json: { | ||
options: { | ||
// FIXME: support multi-proof presentations? |
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 FIXME
need to be preserved?
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.
Hmm, no, I'd say we can remove it. If we want to support that in the future we can figure out where to add it (which may even be in a different spot or something).
// validate against the verify presentation result schema, if applicable | ||
if(verifyPresentationResultSchema) { | ||
const {jsonSchema: schema} = verifyPresentationResultSchema; | ||
const validate = compile({schema}); |
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.
Should this be compiled prior to make the zcap call to ensure it fails as early as possible if there's something invalid 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.
I'm not sure how much earlier it can actually be compiled. Only once the step executes are you guaranteed to have all the variables to construct the step (if it is a template itself, which is common). Therefore, there might not be any earlier time this can happen. We do want, in the future, some better "test" tools for this sort of thing if we can figure out how to accomplish that nicely.
const validate = compile({schema}); | ||
const {valid, error} = validate(result.data); | ||
if(!valid) { | ||
throw error; |
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.
Should this be wrapped or provide some logging in case of failure 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.
It's hard to tell from the diff so I'll need to go look at the source, but I believe this follows the pattern we have with the presentation schema, which is wrapped/handled properly now (IIRC). If this is in the same code path/outer wrapper somewhere then this is ok. Will need to go look and confirm.
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.
Reviewed most of this modulo the test, will take a look at that later, LGTM so far.
// update 'checks' with anything additional from 'verifyPresentationOptions' | ||
if(verifyPresentationOptions.checks !== undefined) { | ||
for(const check in verifyPresentationOptions.checks) { | ||
if(verifyPresentationOptions.checks[check] == true) { | ||
if(!checks.includes(check)) { | ||
checks.push(check); | ||
} | ||
} | ||
} | ||
} | ||
options.checks = checks; |
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 I like Tyler's suggestion better (seems more readable), but if you were looking for a functional way to do it, it could look like this:
// update 'checks' with anything additional from 'verifyPresentationOptions' | |
if(verifyPresentationOptions.checks !== undefined) { | |
for(const check in verifyPresentationOptions.checks) { | |
if(verifyPresentationOptions.checks[check] == true) { | |
if(!checks.includes(check)) { | |
checks.push(check); | |
} | |
} | |
} | |
} | |
options.checks = checks; | |
options.checks = checks; | |
// update 'checks' with anything additional from 'verifyPresentationOptions' | |
if(verifyPresentationOptions.checks) { | |
options.checks = [...new Set([ | |
...options.checks, | |
...Object.entries(verifyPresentationOptions.checks) | |
.filter(([, v]) => v).map(([k]) => k)] | |
])]; | |
} |
result = await zcapClient.write({ | ||
capability, | ||
json: { | ||
options: { | ||
// FIXME: support multi-proof presentations? |
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.
Hmm, no, I'd say we can remove it. If we want to support that in the future we can figure out where to add it (which may even be in a different spot or something).
// validate against the verify presentation result schema, if applicable | ||
if(verifyPresentationResultSchema) { | ||
const {jsonSchema: schema} = verifyPresentationResultSchema; | ||
const validate = compile({schema}); |
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'm not sure how much earlier it can actually be compiled. Only once the step executes are you guaranteed to have all the variables to construct the step (if it is a template itself, which is common). Therefore, there might not be any earlier time this can happen. We do want, in the future, some better "test" tools for this sort of thing if we can figure out how to accomplish that nicely.
const validate = compile({schema}); | ||
const {valid, error} = validate(result.data); | ||
if(!valid) { | ||
throw error; |
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.
It's hard to tell from the diff so I'll need to go look at the source, but I believe this follows the pattern we have with the presentation schema, which is wrapped/handled properly now (IIRC). If this is in the same code path/outer wrapper somewhere then this is ok. Will need to go look and confirm.
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.
Minor nits here -- I think all style / maintenance related. Will approve and merge in once those are addressed. Thanks!
let workflowId; | ||
let workflowRootZcap; | ||
beforeEach(async () => { | ||
|
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.
describe('exchange with `verifyPresentationResultSchema` checking correct' + | ||
' usage of `verifyPresentationOptions`', () => { |
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.
describe('exchange with `verifyPresentationResultSchema` checking correct' + | |
' usage of `verifyPresentationOptions`', () => { | |
describe('exchange with `verifyPresentationResultSchema` checking correct ' + | |
'usage of `verifyPresentationOptions`', () => { |
it('should fail when `verifyPresentationOptions` does not match' + | ||
' `verifyPresentationResultSchema`', async () => { |
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.
Style is off here, but the test name doesn't make sense to me. The result schema isn't used to check the presentation options ... well, perhaps for some definition of "match". Maybe this instead:
it('should fail when `verifyPresentationOptions` does not match' + | |
' `verifyPresentationResultSchema`', async () => { | |
it('should fail when status checks are disabled but required by ' + | |
'`verifyPresentationResultSchema`', async () => { |
// DID Authn step, additionally require VC that was issued from | ||
// workflow 1 |
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.
// DID Authn step, additionally require VC that was issued from | |
// workflow 1 | |
// DID Authn step, additionally require VC that was issued from | |
// workflow 1 |
it('should pass when `verifyPresentationOptions` matches ' + | ||
'`verifyPresentationResultSchema`', async () => { | ||
|
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.
it('should pass when `verifyPresentationOptions` matches ' + | |
'`verifyPresentationResultSchema`', async () => { | |
it('should pass when `verifyPresentationOptions` enables status check ' + | |
'and `verifyPresentationResultSchema` requires is', async () => { |
See comments on test name language in the other test below.
let workflowId; | ||
let workflowRootZcap; | ||
beforeEach(async () => { | ||
|
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.
// DID Authn step, additionally require VC that was issued from | ||
// workflow 1 |
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.
// DID Authn step, additionally require VC that was issued from | |
// workflow 1 | |
// DID Authn step, additionally require VC that was issued from | |
// workflow 1 |
didAuthn: { | ||
createChallenge: true, | ||
verifiablePresentationRequest: { | ||
query: [{ | ||
type: 'DIDAuthentication', | ||
acceptedMethods: [{method: 'key'}] | ||
}, { | ||
type: 'QueryByExample', | ||
credentialQuery: [{ | ||
reason: 'We require a verifiable credential to pass this test', | ||
example: { | ||
'@context': [ | ||
'https://www.w3.org/ns/credentials/v2' | ||
], | ||
} | ||
}] | ||
}], | ||
domain: baseUrl | ||
}, | ||
verifyPresentationOptions: { | ||
checks: { | ||
credentialStatus: true | ||
} | ||
}, | ||
verifyPresentationResultSchema: { | ||
type: 'JsonSchema', | ||
jsonSchema: checksIncludeStatusVerificationResultSchema | ||
} | ||
} | ||
}; |
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.
Lots of repetition with all this in various tests here, could use a helper function to DRY it up. I'll just file an issue on this because I expect this to be common throughout the test suite.
{ | ||
"@context": [ | ||
"https://www.w3.org/ns/credentials/v2" | ||
], | ||
"id": credentialId, | ||
"type": [ | ||
"VerifiableCredential" | ||
], | ||
"credentialStatus: { | ||
"id": "https://example.com/credentials/status/3#94567", | ||
"type": "BitstringStatusListEntry", | ||
"statusPurpose": "revocation", | ||
"statusListIndex": "94567", | ||
"statusListCredential": "https://example.com/credentials/status/3" | ||
}, | ||
"credentialSubject": { | ||
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21" | ||
} | ||
} |
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.
Unnecessary indentation when using a big string interpolation block; though perhaps this would be better added with an eslint disable block before and after instead. There should be examples of that in various test suites.
{ | |
"@context": [ | |
"https://www.w3.org/ns/credentials/v2" | |
], | |
"id": credentialId, | |
"type": [ | |
"VerifiableCredential" | |
], | |
"credentialStatus: { | |
"id": "https://example.com/credentials/status/3#94567", | |
"type": "BitstringStatusListEntry", | |
"statusPurpose": "revocation", | |
"statusListIndex": "94567", | |
"statusListCredential": "https://example.com/credentials/status/3" | |
}, | |
"credentialSubject": { | |
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21" | |
} | |
} | |
{ | |
"@context": [ | |
"https://www.w3.org/ns/credentials/v2" | |
], | |
"id": credentialId, | |
"type": [ | |
"VerifiableCredential" | |
], | |
"credentialStatus: { | |
"id": "https://example.com/credentials/status/3#94567", | |
"type": "BitstringStatusListEntry", | |
"statusPurpose": "revocation", | |
"statusListIndex": "94567", | |
"statusListCredential": "https://example.com/credentials/status/3" | |
}, | |
"credentialSubject": { | |
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21" | |
} | |
} |
This PR adds two features:
verifyPresentationOptions
to appear on exchange steps,allowing for more extensible and general step option expression.
verifyPresentationResponseSchema
to appear on exchangesteps, allowing for enforcing validation constraints at the workflow layer.