diff --git a/src/cr1/validator/w3c.ts b/src/cr1/validator/w3c.ts index 3f6a1cd..ddf88d5 100644 --- a/src/cr1/validator/w3c.ts +++ b/src/cr1/validator/w3c.ts @@ -79,6 +79,27 @@ const holder = (result: ValidationResult, pointer: string, value: any) => { } } +// https://www.w3.org/TR/vc-data-model-2.0/#presentations-0 +const verifiableCredential = (result: ValidationResult, pointer: string, value: any) => { + const nonObjectPointer = pointer?.split('/verifiableCredential/').pop() as string + if (pointer.startsWith('/verifiableCredential/') && nonObjectPointer.length === 1 && !Number.isNaN(parseInt(nonObjectPointer))) { + console.log("VAL:", pointer, value); + if (typeof value !== 'object') { + result.warnings.push({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + message: `verifiableCredential MUST NOT be non-object values such as numbers, strings, or URLs`, + pointer, + reference: 'https://www.w3.org/TR/vc-data-model-2.0/#presentations-0' + }) + } + // Check Enveloped Cred + + // + } +} + + + // https://www.w3.org/TR/2024/CRD-vc-data-model-2.0-20240205/#types const types = (result: ValidationResult, pointer: string, value: any) => { // I'm not writing a test for: @@ -130,6 +151,7 @@ export const conformance = (result: ValidationResult) => { names_and_descriptions(result, pointer, value) issuer(result, pointer, value) holder(result, pointer, value) + verifiableCredential(result, pointer, value); } return result diff --git a/test/w3c-cr-1/5-data-model.test.ts b/test/w3c-cr-1/5-data-model.test.ts index 816c3f9..b3a3141 100644 --- a/test/w3c-cr-1/5-data-model.test.ts +++ b/test/w3c-cr-1/5-data-model.test.ts @@ -262,7 +262,58 @@ credentialSubject: // https://www.w3.org/TR/2024/CRD-vc-data-model-2.0-20240205/#presentations-0 describe("Presentations", () => { describe("Presentation - verifiableCredential", () => { - it.todo("complete me") + it("can be an array of enveloped credentials and credentials", async () => { + const validation = await review( + text(` + "@context": + - https://www.w3.org/ns/credentials/v2 + type: + - VerifiablePresentation + holder: + id: https://university.example/issuers/565049 + verifiableCredential: + - "@context": https://www.w3.org/ns/credentials/v2 + id: data:application/vc+ld+json+sd-jwt;QzVjV...RMjU + type: EnvelopedVerifiableCredential + - "@context": + - https://www.w3.org/ns/credentials/v2 + type: + - VerifiableCredential + issuer: + id: https://university.example/issuers/565049 + credentialSubject: + - id: https://university.example/issuers/1 + - id: https://university.example/issuers/2 + `) + ); + expect(validation.warnings).toEqual([{ + message: 'Identifier will not be well understood: data:application/vc+ld+json+sd-jwt;QzVjV...RMjU', + pointer: '/verifiableCredential/0/id', + reference: 'https://www.w3.org/TR/2024/CRD-vc-data-model-2.0-20240205/#identifiers' + }]); + }) + + it("warns when non-object value is used", async () => { + const validation = await review( + text(` + "@context": + - https://www.w3.org/ns/credentials/v2 + type: + - VerifiablePresentation + holder: + id: https://university.example/issuers/565049 + verifiableCredential: + - badValue + `) + ); + + expect(validation.warnings).toEqual([{ + message: 'verifiableCredential MUST NOT be non-object values such as numbers, strings, or URLs', + pointer: '/verifiableCredential/0', + reference: 'https://www.w3.org/TR/vc-data-model-2.0/#presentations-0' + }]); + + }) }); describe("Presentation - holder", () => { it("can be object with id as url", async () => {