From 8663aee7fc6c608b7e23dd2ec212c22573857d41 Mon Sep 17 00:00:00 2001 From: nitro-neal <5314059+nitro-neal@users.noreply.github.com> Date: Mon, 29 Apr 2024 10:09:47 -0700 Subject: [PATCH] Credential Schema VcDataModel Impl (#491) * cred schema impl * bump package version * remove 1.0.1 * add changesets * wrong dir changeset * update changeset * updated --- .changeset/seven-horses-clap.md | 5 +++ .../credentials/src/verifiable-credential.ts | 13 +++++- .../tests/verifiable-credential.spec.ts | 42 +++++++++++++------ 3 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 .changeset/seven-horses-clap.md diff --git a/.changeset/seven-horses-clap.md b/.changeset/seven-horses-clap.md new file mode 100644 index 000000000..eea61cc00 --- /dev/null +++ b/.changeset/seven-horses-clap.md @@ -0,0 +1,5 @@ +--- +"@web5/credentials": patch +--- + +Added credentialSchema to the VcDataModel diff --git a/packages/credentials/src/verifiable-credential.ts b/packages/credentials/src/verifiable-credential.ts index 4ca6d31d2..b7722a7db 100644 --- a/packages/credentials/src/verifiable-credential.ts +++ b/packages/credentials/src/verifiable-credential.ts @@ -19,6 +19,14 @@ export const DEFAULT_VC_TYPE = 'VerifiableCredential'; */ export type VcDataModel = ICredential; +/** + * A credential schema defines the structure and content of the data, enabling verifiers to assess if the data adheres to the established schema. + */ +export type CredentialSchema = { + id: string; + type: string; +}; + /** * Options for creating a verifiable credential. * @param type Optional. The type of the credential, can be a string or an array of strings. @@ -43,6 +51,8 @@ export type VerifiableCredentialCreateOptions = { issuanceDate?: string; /** The expiration date of the credential, as a string. */ expirationDate?: string; + /** The credential schema of the credential */ + credentialSchema?: CredentialSchema; /** The evidence of the credential, as an array of any. */ evidence?: any[]; }; @@ -147,7 +157,7 @@ export class VerifiableCredential { * @returns A [VerifiableCredential] instance. */ public static async create(options: VerifiableCredentialCreateOptions): Promise { - const { type, issuer, subject, data, issuanceDate, expirationDate, evidence } = options; + const { type, issuer, subject, data, issuanceDate, expirationDate, credentialSchema, evidence } = options; const jsonData = JSON.parse(JSON.stringify(data)); @@ -179,6 +189,7 @@ export class VerifiableCredential { credentialSubject : credentialSubject, // Include optional properties only if they have values ...(expirationDate && { expirationDate }), + ...(credentialSchema && { credentialSchema }), ...(evidence && { evidence }), }; diff --git a/packages/credentials/tests/verifiable-credential.spec.ts b/packages/credentials/tests/verifiable-credential.spec.ts index 356b33546..38451f2ba 100644 --- a/packages/credentials/tests/verifiable-credential.spec.ts +++ b/packages/credentials/tests/verifiable-credential.spec.ts @@ -7,7 +7,7 @@ import { DidDht, DidKey, DidIon, DidJwk } from '@web5/dids'; import { Jwt } from '../src/jwt.js'; import { VerifiableCredential } from '../src/verifiable-credential.js'; import CredentialsVerifyTestVector from '../../../web5-spec/test-vectors/credentials/verify.json' assert { type: 'json' }; -import { getCurrentXmlSchema112Timestamp, getXmlSchema112Timestamp } from '../src/utils.js'; +import { getCurrentXmlSchema112Timestamp } from '../src/utils.js'; describe('Verifiable Credential Tests', async() => { let issuerDid: BearerDid; @@ -92,28 +92,46 @@ describe('Verifiable Credential Tests', async() => { }); it('create and sign kyc vc with did:jwk', async () => { - const did = await DidJwk.create(); + const subjectDid = await DidJwk.create(); + const issuerDid = await DidJwk.create(); const vc = await VerifiableCredential.create({ type : 'KnowYourCustomerCred', - subject : did.uri, - issuer : did.uri, - expirationDate : getXmlSchema112Timestamp(2687920690), // 2055-03-05 + subject : subjectDid.uri, + issuer : issuerDid.uri, + issuanceDate : '2023-05-19T08:02:04Z', + expirationDate : `2055-05-19T08:02:04Z`, data : { - country: 'us' - } + id : subjectDid.uri, + country_of_residence : 'US', + tier : 'Tier 1' + }, + credentialSchema: { + id : ' https://schema.org/PFI', + type : 'JsonSchema' + }, + evidence: [ + { kind: 'document_verification', checks: ['passport', 'utility_bill'] }, + { kind: 'sanctions_check', checks: ['daily'] } + ] }); - const vcJwt = await vc.sign({ did }); + const vcJwt = await vc.sign({ did: issuerDid }); await VerifiableCredential.verify({ vcJwt }); for( const currentVc of [vc, VerifiableCredential.parseJwt({ vcJwt })]){ - expect(currentVc.issuer).to.equal(did.uri); - expect(currentVc.subject).to.equal(did.uri); + expect(currentVc.issuer).to.equal(issuerDid.uri); + expect(currentVc.subject).to.equal(subjectDid.uri); expect(currentVc.type).to.equal('KnowYourCustomerCred'); - expect(currentVc.vcDataModel.issuanceDate).to.not.be.undefined; - expect(currentVc.vcDataModel.credentialSubject).to.deep.equal({ id: did.uri, country: 'us'}); + expect(currentVc.vcDataModel.issuanceDate).to.equal('2023-05-19T08:02:04Z'); + expect(currentVc.vcDataModel.expirationDate).to.equal('2055-05-19T08:02:04Z'); + expect(currentVc.vcDataModel.credentialSubject).to.deep.equal({ id: subjectDid.uri, country_of_residence: 'US', tier: 'Tier 1'}); + expect(currentVc.vcDataModel.credentialSchema).to.deep.equal({ id: ' https://schema.org/PFI', type: 'JsonSchema'}); + expect(currentVc.vcDataModel.evidence).to.deep.equal([ + { kind: 'document_verification', checks: ['passport', 'utility_bill'] }, + { kind: 'sanctions_check', checks: ['daily'] } + ]); } });