88 W3C_CREDENTIALS_V1 ,
99 DELEGATION_CONTEXT_TERMS ,
1010} from '@docknetwork/wallet-sdk-wasm/src/services/credential/delegatable-credentials' ;
11+ import { credentialService } from '@docknetwork/wallet-sdk-wasm/src/services/credential/service' ;
1112import { didService } from '@docknetwork/wallet-sdk-wasm/src/services/dids/service' ;
13+ import { pexService } from '@docknetwork/wallet-sdk-wasm/src/services/pex' ;
1214import { v4 as uuidv4 } from 'uuid' ;
1315// ============================================================================
1416// TEST-SPECIFIC CONTEXTS (Credit Score Use Case)
@@ -94,7 +96,7 @@ describe('Delegatable Credentials', () => {
9496 issuanceDate : new Date ( ) . toISOString ( ) ,
9597 type : [
9698 'VerifiableCredential' ,
97- 'CreditScoreDelegation ' ,
99+ 'CreditScoreCredential ' ,
98100 'DelegationCredential' ,
99101 ] ,
100102 credentialSubject : {
@@ -114,7 +116,7 @@ describe('Delegatable Credentials', () => {
114116 issuanceDate : new Date ( ) . toISOString ( ) ,
115117 type : [
116118 'VerifiableCredential' ,
117- 'CreditScoreDelegation ' ,
119+ 'CreditScoreCredential ' ,
118120 'DelegationCredential' ,
119121 ] ,
120122 credentialSubject : {
@@ -138,18 +140,22 @@ describe('Delegatable Credentials', () => {
138140 rootCredentialId : rootCredential . id ,
139141 previousCredentialId : credDelegatedToAgent . id ,
140142 '@context' : CREDIT_SCORE_CREDENTIAL_CONTEXT ,
141- type : [ 'VerifiableCredential' , 'CreditScoreDelegation ' ] ,
143+ type : [ 'VerifiableCredential' , 'CreditScoreCredential ' ] ,
142144 } ) ;
143145
144146 // Issue an unauthorized delegation (no creditScore in mayClaim)
145- // unauthorizedDelegationCredential = await issueDelegationCredential(issuerKey, {
146- // id: 'urn:cred:unauthorized-delegation',
147- // issuerDid: issuerDid,
148- // delegateDid: holderDid,
149- // mayClaim: ['someOtherClaim'], // Does NOT include creditScore
150- // context: CREDIT_SCORE_DELEGATION_CONTEXT,
151- // types: ['VerifiableCredential', 'CreditScoreDelegation', 'DelegationCredential'],
152- // });
147+ unauthorizedDelegationCredential = await issueDelegationCredential ( issuerKey , {
148+ id : 'urn:cred:unauthorized-delegation' ,
149+ issuanceDate : new Date ( ) . toISOString ( ) ,
150+ issuer : issuerDid ,
151+ credentialSubject : {
152+ id : holderDid ,
153+ creditScore : 760 ,
154+ [ MAY_CLAIM_IRI ] : [ 'someOtherClaim' ] ,
155+ } ,
156+ '@context' : CREDIT_SCORE_DELEGATION_CONTEXT ,
157+ type : [ 'VerifiableCredential' , 'CreditScoreDelegation' , 'DelegationCredential' ] ,
158+ } ) ;
153159 } ) ;
154160
155161 it ( 'should issue a valid delegation credential' , ( ) => {
@@ -191,40 +197,88 @@ describe('Delegatable Credentials', () => {
191197 expect ( result . verified ) . toBe ( true ) ;
192198 } ) ;
193199
194- it ( 'sub agent present delegated credential from other agent' , async ( ) => {
195- // Create a signed presentation with both credentials
196- const presentation = await createSignedPresentation ( subAgentKey , {
197- credentials : [ rootCredential , credDelegatedToAgent , credDelegatedToSubAgent ] ,
200+ it ( 'should handle pex request with delegated credential' , async ( ) => {
201+
202+ const presentationDefinition = {
203+ id : 'delegation_test' ,
204+ input_descriptors : [
205+ {
206+ id : 'root-credential' ,
207+ name : 'Root Credential' ,
208+ purpose : 'Must be the root credential issued by the required issuer' ,
209+ group : [ '1' ] ,
210+ constraints : {
211+ fields : [
212+ {
213+ path : [ '$.type' ] ,
214+ filter : {
215+ type : 'array' ,
216+ contains : {
217+ const : 'CreditScoreCredential' ,
218+ } ,
219+ } ,
220+ } ,
221+ {
222+ path : [ '$.issuer' , '$.iss' ] ,
223+ filter : {
224+ type : 'string' ,
225+ const : issuerDid ,
226+ } ,
227+ } ,
228+ ] ,
229+ } ,
230+ } ,
231+ {
232+ id : 'other-credentials' ,
233+ name : 'Additional Credentials' ,
234+ purpose :
235+ 'Any number of additional credentials of the specified type from any issuer' ,
236+ group : [ '2' ] ,
237+ constraints : {
238+ fields : [
239+ {
240+ path : [ '$.type' ] ,
241+ filter : {
242+ type : 'array' ,
243+ contains : {
244+ const : 'CreditScoreCredential' ,
245+ } ,
246+ } ,
247+ } ,
248+ ] ,
249+ } ,
250+ } ,
251+ ] ,
252+ submission_requirements : [
253+ {
254+ from : '1' ,
255+ name : 'Root Credential' ,
256+ rule : 'pick' ,
257+ count : 1 ,
258+ } ,
259+ {
260+ from : '2' ,
261+ name : 'Additional Credentials' ,
262+ rule : 'pick' ,
263+ min : 0 , // Minimum 0 = optional
264+ } ,
265+ ] ,
266+ } ;
267+
268+ const result = await credentialService . filterCredentials ( {
269+ credentials : [ rootCredential , credDelegatedToAgent ] ,
270+ presentationDefinition,
198271 holderDid : subAgentDid ,
199- challenge : CHALLENGE ,
200- domain : DOMAIN ,
201272 } ) ;
202273
274+ console . log ( 'PEX Result:' , JSON . stringify ( result , null , 2 ) ) ;
203275
204- const policies = {
205- staticPolicies : `
206- permit(
207- principal in Credential::Chain::"Action:Verify",
208- action == Credential::Action::"Verify",
209- resource
210- ) when {
211- principal == context.vpSigner &&
212- context.tailDepth <= 4 &&
213- context.rootIssuer == Credential::Actor::"${ issuerDid } "
214- context.authorizedClaims.creditScore >= 400
215- }` ,
216- } ;
217-
218- // Verify the presentation
219- const result = await verifyDelegatablePresentation ( presentation , {
220- challenge : CHALLENGE ,
221- domain : DOMAIN ,
222- policies,
223- } ) ;
224276
225- debugger ;
277+ expect ( result . verifiableCredential ?. length ) . toBe ( 2 ) ;
278+ expect ( result . errors ?. length ) . toBe ( 0 ) ;
226279 } ) ;
227280
281+
228282 it ( 'should verify authorized delegation with Cedar policies' , async ( ) => {
229283 // Create a signed presentation with both credentials
230284 const presentation = await createSignedPresentation ( agentKey , {
@@ -276,58 +330,60 @@ permit(
276330 }
277331 } ) ;
278332
279- // it('should deny unauthorized delegation (wrong mayClaim)', async () => {
280- // // Create a credential that uses an unauthorized delegation
281- // // The unauthorizedDelegationCredential only grants 'someOtherClaim', not 'creditScore'
282- // const unauthorizedCreditScore = await issueDelegatedCredential(holderKey, {
283- // id: 'urn:cred:unauthorized-credit-score',
284- // issuerDid: holderDid,
285- // subjectDid: agentDid,
286- // claims: {
287- // creditScore: 500,
288- // },
289- // rootCredentialId: 'urn:cred:unauthorized-delegation',
290- // previousCredentialId: 'urn:cred:unauthorized-delegation',
291- // context: CREDIT_SCORE_CREDENTIAL_CONTEXT,
292- // types: ['VerifiableCredential', 'CreditScoreCredential'],
293- // });
294-
295- // // Create presentation with unauthorized delegation
296- // const presentation = await createSignedPresentation(agentKey, {
297- // credentials: [unauthorizedDelegationCredential, unauthorizedCreditScore],
298- // holderDid: holderDid,
299- // challenge: CHALLENGE,
300- // domain: DOMAIN,
301- // });
302-
303- // // Create Cedar policy that requires creditScore claim authorization
304- // const policies = createCedarPolicy({
305- // maxDepth: 2,
306- // rootIssuer: issuerDid,
307- // requiredClaims: {
308- // creditScore: 0,
309- // },
310- // });
311-
312- // // Verify the presentation - should fail because creditScore is not authorized
313- // const result = await verifyDelegatablePresentation(presentation, {
314- // challenge: CHALLENGE,
315- // domain: DOMAIN,
316- // policies,
317- // });
318-
319- // console.log('Unauthorized delegation result:', {
320- // verified: result.verified,
321- // delegationDecision: result.delegationResult?.decision,
322- // failures: result.delegationResult?.failures?.map(f => f.message),
323- // });
324-
325- // // Delegation should be denied because the delegate doesn't have creditScore authority
326- // expect(result.delegationResult?.decision).toBe('deny');
327- // expect(result.delegationResult?.failures).toBeDefined();
328- // expect(result.delegationResult?.failures?.length).toBeGreaterThan(0);
329- // expect(result.delegationResult?.failures?.[0]?.code).toBe('UNAUTHORIZED_CLAIM');
330- // });
333+ it ( 'should deny unauthorized delegation (wrong mayClaim)' , async ( ) => {
334+ // Create a credential that uses an unauthorized delegation
335+ // The unauthorizedDelegationCredential only grants 'someOtherClaim', not 'creditScore'
336+ const unauthorizedCreditScore = await issueDelegatedCredential ( holderKey , {
337+ id : 'urn:cred:unauthorized-credit-score' ,
338+ issuer : holderDid ,
339+ issuanceDate : new Date ( ) . toISOString ( ) ,
340+ credentialSubject : {
341+ id : agentDid ,
342+ creditScore : 500 ,
343+ [ MAY_CLAIM_IRI ] : [ 'creditScore' ] ,
344+ } ,
345+ rootCredentialId : unauthorizedDelegationCredential . id ,
346+ previousCredentialId : unauthorizedDelegationCredential . id ,
347+ '@context' : CREDIT_SCORE_CREDENTIAL_CONTEXT ,
348+ type : [ 'VerifiableCredential' , 'CreditScoreCredential' ] ,
349+ } ) ;
350+
351+ // Create presentation with unauthorized delegation
352+ const presentation = await createSignedPresentation ( agentKey , {
353+ credentials : [ unauthorizedDelegationCredential , unauthorizedCreditScore ] ,
354+ holderDid : holderDid ,
355+ challenge : CHALLENGE ,
356+ domain : DOMAIN ,
357+ } ) ;
358+
359+ // Create Cedar policy that requires creditScore claim authorization
360+ const policies = createCedarPolicy ( {
361+ maxDepth : 2 ,
362+ rootIssuer : issuerDid ,
363+ requiredClaims : {
364+ creditScore : 0 ,
365+ } ,
366+ } ) ;
367+
368+ // Verify the presentation - should fail because creditScore is not authorized
369+ const result = await verifyDelegatablePresentation ( presentation , {
370+ challenge : CHALLENGE ,
371+ domain : DOMAIN ,
372+ policies,
373+ } ) ;
374+
375+ console . log ( 'Unauthorized delegation result:' , {
376+ verified : result . verified ,
377+ delegationDecision : result . delegationResult ?. decision ,
378+ failures : result . delegationResult ?. failures ?. map ( f => f . message ) ,
379+ } ) ;
380+
381+ // Delegation should be denied because the delegate doesn't have creditScore authority
382+ expect ( result . delegationResult ?. decision ) . toBe ( 'deny' ) ;
383+ expect ( result . delegationResult ?. failures ) . toBeDefined ( ) ;
384+ expect ( result . delegationResult ?. failures ?. length ) . toBeGreaterThan ( 0 ) ;
385+ expect ( result . delegationResult ?. failures ?. [ 0 ] ?. code ) . toBe ( 'UNAUTHORIZED_CLAIM' ) ;
386+ } ) ;
331387
332388 it ( 'should verify delegation without Cedar policies' , async ( ) => {
333389 // Create a signed presentation
0 commit comments