@cooperation/vc-storage 1.0.42 → 1.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,25 @@
1
- import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020';
2
- import { Ed25519Signature2020 } from '@digitalbazaar/ed25519-signature-2020';
3
- import * as dbVc from '@digitalbazaar/vc';
1
+ import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
2
+ import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';
3
+ import * as dbVc from '@digitalcredentials/vc';
4
4
  import { v4 as uuidv4 } from 'uuid';
5
- import { extractKeyPairFromCredential, generateDIDSchema, generateUnsignedEmployment, generateUnsignedPerformanceReview, generateUnsignedRecommendation, generateUnsignedVC, generateUnsignedVolunteering, } from '../utils/credential.js';
6
- import { customDocumentLoader } from '../utils/digitalbazaar.js';
5
+ import { extractKeyPairFromCredential, generateDIDSchema, generateUnsignedEmployment, generateUnsignedPerformanceReview, generateUnsignedRecommendation, generateUnsignedSkillClaim, generateUnsignedVC, generateUnsignedVolunteering, } from '../utils/credential.js';
6
+ import { securityLoader } from '@digitalcredentials/security-document-loader';
7
+ import hrContext from 'hr-context';
8
+ // Add hr-context for SkillClaimCredential; patch socCode (@type→@container)
9
+ const hrCtxData = JSON.parse(JSON.stringify(hrContext.CONTEXT_V1));
10
+ if (hrCtxData?.['@context']?.socCode) {
11
+ delete hrCtxData['@context'].socCode['@type'];
12
+ hrCtxData['@context'].socCode['@container'] = '@set';
13
+ }
14
+ const loader = securityLoader();
15
+ loader.addStatic(hrContext.CONTEXT_URL_V1, hrCtxData);
16
+ loader.addStatic('https://w3id.org/hr/v1', hrCtxData);
17
+ const builtLoader = loader.build();
18
+ /** Document loader compatible with @digitalcredentials/vc */
19
+ export const documentLoader = async (url) => {
20
+ const r = await builtLoader(url);
21
+ return { contextUrl: r.contextUrl ?? null, documentUrl: r.documentUrl ?? url, document: r.document };
22
+ };
7
23
  import { saveToGoogleDrive } from '../utils/google.js';
8
24
  function delay(ms) {
9
25
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -73,6 +89,33 @@ export class CredentialEngine {
73
89
  }));
74
90
  return true;
75
91
  }
92
+ /**
93
+ * For recommendations we need the *target VC DID/URI* (VC `id`) in the payload.
94
+ * Callers may still pass a Google Drive file id; if so we resolve and extract the VC `id`.
95
+ */
96
+ async resolveTargetVcId(vcIdOrFileId) {
97
+ if (!vcIdOrFileId)
98
+ throw new Error('Missing target VC reference');
99
+ // Already a DID/URI
100
+ if (vcIdOrFileId.startsWith('urn:') || vcIdOrFileId.startsWith('did:')) {
101
+ return vcIdOrFileId;
102
+ }
103
+ // Otherwise assume it's a Google Drive file id and resolve
104
+ const retrieved = await this.storage.retrieve(vcIdOrFileId);
105
+ if (!retrieved?.data)
106
+ throw new Error(`Unable to resolve VC from file id: ${vcIdOrFileId}`);
107
+ const maybeEnvelope = retrieved.data;
108
+ const payload = typeof maybeEnvelope?.body === 'string'
109
+ ? JSON.parse(maybeEnvelope.body)
110
+ : maybeEnvelope?.body
111
+ ? maybeEnvelope.body
112
+ : maybeEnvelope;
113
+ const resolvedId = payload?.id;
114
+ if (!resolvedId || typeof resolvedId !== 'string') {
115
+ throw new Error(`Resolved VC is missing an 'id' (from file id: ${vcIdOrFileId})`);
116
+ }
117
+ return resolvedId;
118
+ }
76
119
  /**
77
120
  * Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
78
121
  * @returns {Promise<{didDocument: object, keyPair: object}>} The created DID document and key pair.
@@ -143,8 +186,10 @@ export class CredentialEngine {
143
186
  case 'RECOMMENDATION':
144
187
  if (!vcFileId)
145
188
  throw new Error('vcFileId is required for recommendation');
189
+ // Ensure the Recommendation VC references the target VC DID/URI (not a Drive file id)
190
+ const targetVcId = await this.resolveTargetVcId(vcFileId);
146
191
  credential = generateUnsignedRecommendation({
147
- vcId: vcFileId,
192
+ vcId: targetVcId,
148
193
  recommendation: data,
149
194
  issuerDid: issuerId,
150
195
  });
@@ -162,7 +207,7 @@ export class CredentialEngine {
162
207
  throw new Error(`Unsupported credential type: ${type}`);
163
208
  }
164
209
  const suite = new Ed25519Signature2020({ key: keyPair, verificationMethod: keyPair.id });
165
- return dbVc.issue({ credential, suite, documentLoader: customDocumentLoader });
210
+ return dbVc.issue({ credential, suite, documentLoader });
166
211
  }
167
212
  async signEmploymentCredential(data, keyPair, issuerId) {
168
213
  return this.signVC({ data, type: 'EMPLOYMENT', keyPair, issuerId });
@@ -173,6 +218,18 @@ export class CredentialEngine {
173
218
  async signPerformanceReviewCredential(data, keyPair, issuerId) {
174
219
  return this.signVC({ data, type: 'PERFORMANCE_REVIEW', keyPair, issuerId });
175
220
  }
221
+ /**
222
+ * Sign a SkillClaimCredential using the HR Context data model.
223
+ * @param {SkillClaimFormDataI} data - The skill claim form data.
224
+ * @param {KeyPair} keyPair - The key pair to use for signing.
225
+ * @param {string} issuerId - The issuer DID.
226
+ * @returns {Promise<any>} The signed SkillClaimCredential.
227
+ */
228
+ async signSkillClaimVC(data, keyPair, issuerId) {
229
+ const credential = generateUnsignedSkillClaim({ formData: data, issuerDid: issuerId });
230
+ const suite = new Ed25519Signature2020({ key: keyPair, verificationMethod: keyPair.id });
231
+ return dbVc.issue({ credential, suite, documentLoader });
232
+ }
176
233
  /**
177
234
  * Verify a Verifiable Credential (VC)
178
235
  * @param {object} credential - The Verifiable Credential to verify.
@@ -189,10 +246,10 @@ export class CredentialEngine {
189
246
  const result = await dbVc.verifyCredential({
190
247
  credential,
191
248
  suite,
192
- documentLoader: customDocumentLoader,
249
+ documentLoader,
193
250
  });
194
251
  console.log(JSON.stringify(result));
195
- return result;
252
+ return result.verified;
196
253
  }
197
254
  catch (error) {
198
255
  console.error('Verification failed:', error);
@@ -244,7 +301,7 @@ export class CredentialEngine {
244
301
  const signedVP = await dbVc.signPresentation({
245
302
  presentation,
246
303
  suite,
247
- documentLoader: customDocumentLoader,
304
+ documentLoader,
248
305
  challenge: '', // Provide the challenge if required
249
306
  });
250
307
  return signedVP;
@@ -318,7 +375,7 @@ export class CredentialEngine {
318
375
  const signedVC = await dbVc.issue({
319
376
  credential: unsignedCredential,
320
377
  suite,
321
- documentLoader: customDocumentLoader,
378
+ documentLoader,
322
379
  });
323
380
  const rootFolders = await this.storage.findFolders();
324
381
  // Find or create Credentials folder
@@ -1,8 +1,8 @@
1
- import { Ed25519Signature2020 } from '@digitalbazaar/ed25519-signature-2020';
2
- import { customDocumentLoader } from '../utils/digitalbazaar.js';
1
+ import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';
2
+ import { documentLoader } from './CredentialEngine.js';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
- import * as dbVc from '@digitalbazaar/vc';
5
- import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020';
4
+ import * as dbVc from '@digitalcredentials/vc';
5
+ import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
6
6
  import { generateDIDSchema } from '../utils/credential.js';
7
7
  import { inlineResumeContext } from '../utils/context.js';
8
8
  export class ResumeVC {
@@ -20,7 +20,7 @@ export class ResumeVC {
20
20
  const signedProfessionalSummaryVC = await dbVc.issue({
21
21
  credential: professionalSummaryVC,
22
22
  suite,
23
- documentLoader: customDocumentLoader,
23
+ documentLoader,
24
24
  });
25
25
  // Replace the unsigned professional summary with the signed one
26
26
  unsignedCredential.credentialSubject.professionalSummary = signedProfessionalSummaryVC;
@@ -28,7 +28,7 @@ export class ResumeVC {
28
28
  const signedResumeVC = await dbVc.issue({
29
29
  credential: unsignedCredential,
30
30
  suite,
31
- documentLoader: customDocumentLoader,
31
+ documentLoader,
32
32
  });
33
33
  console.log('Signed Resume VC:', signedResumeVC);
34
34
  return signedResumeVC;
@@ -205,7 +205,6 @@ export class ResumeVC {
205
205
  const a = address || keyPair.publicKeyMultibase;
206
206
  keyPair.controller = `did:key:${a}`;
207
207
  keyPair.id = `${keyPair.controller}#${a}`;
208
- keyPair.revoked = false;
209
208
  // The `signer` is already provided by the `Ed25519VerificationKey2020` instance
210
209
  return keyPair;
211
210
  };
@@ -1,4 +1,12 @@
1
- import { DidDocument, KeyPair, FormDataI, RecommendationFormDataI, VerifiableCredential, EmploymentFormDataI, PerformanceReviewFormDataI, VolunteeringFormDataI } from '../../types/credential.js';
1
+ /** Document loader compatible with @digitalcredentials/vc */
2
+ export declare const documentLoader: (url: string) => Promise<{
3
+ contextUrl: string;
4
+ documentUrl: string;
5
+ document: any;
6
+ }>;
7
+ import type { IVerifiableCredential } from '@digitalcredentials/ssi';
8
+ import { DidDocument, KeyPair, FormDataI, RecommendationFormDataI, EmploymentFormDataI, PerformanceReviewFormDataI, VolunteeringFormDataI } from '../../types';
9
+ import type { ISkillClaimCredential } from 'hr-context';
2
10
  import { GoogleDriveStorage } from './GoogleDriveStorage.js';
3
11
  interface SignPropsI {
4
12
  data: FormDataI | RecommendationFormDataI | EmploymentFormDataI | VolunteeringFormDataI | PerformanceReviewFormDataI;
@@ -25,6 +33,11 @@ export declare class CredentialEngine {
25
33
  private getKeyPair;
26
34
  private generateKeyPair;
27
35
  private verifyCreds;
36
+ /**
37
+ * For recommendations we need the *target VC DID/URI* (VC `id`) in the payload.
38
+ * Callers may still pass a Google Drive file id; if so we resolve and extract the VC `id`.
39
+ */
40
+ private resolveTargetVcId;
28
41
  /**
29
42
  * Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
30
43
  * @returns {Promise<{didDocument: object, keyPair: object}>} The created DID document and key pair.
@@ -62,25 +75,33 @@ export declare class CredentialEngine {
62
75
  signEmploymentCredential(data: EmploymentFormDataI, keyPair: KeyPair, issuerId: string): Promise<any>;
63
76
  signVolunteeringCredential(data: VolunteeringFormDataI, keyPair: KeyPair, issuerId: string): Promise<any>;
64
77
  signPerformanceReviewCredential(data: PerformanceReviewFormDataI, keyPair: KeyPair, issuerId: string): Promise<any>;
78
+ /**
79
+ * Sign a SkillClaimCredential using the HR Context data model.
80
+ * @param {SkillClaimFormDataI} data - The skill claim form data.
81
+ * @param {KeyPair} keyPair - The key pair to use for signing.
82
+ * @param {string} issuerId - The issuer DID.
83
+ * @returns {Promise<any>} The signed SkillClaimCredential.
84
+ */
85
+ signSkillClaimVC(data: ISkillClaimCredential, keyPair: KeyPair, issuerId: string): Promise<any>;
65
86
  /**
66
87
  * Verify a Verifiable Credential (VC)
67
88
  * @param {object} credential - The Verifiable Credential to verify.
68
89
  * @returns {Promise<boolean>} The verification result.
69
90
  * @throws Will throw an error if VC verification fails.
70
91
  */
71
- verifyCredential(credential: VerifiableCredential): Promise<boolean>;
92
+ verifyCredential(credential: IVerifiableCredential): Promise<boolean>;
72
93
  /**
73
94
  * Create a Verifiable Presentation (VP)
74
95
  * @param verifiableCredential
75
96
  * @returns
76
97
  */
77
- createPresentation(verifiableCredential: VerifiableCredential[]): Promise<any>;
98
+ createPresentation(verifiableCredential: IVerifiableCredential[]): Promise<object>;
78
99
  /**
79
100
  * Sign a Verifiable Presentation (VP)
80
101
  * @param presentation
81
102
  * @returns
82
103
  */
83
- signPresentation(presentation: any): Promise<any>;
104
+ signPresentation(presentation: any): Promise<object>;
84
105
  /**
85
106
  * Generate and sign an email Verifiable Credential (VC)
86
107
  * @param {string} email - The email address to create the VC for
@@ -1,3 +1,4 @@
1
+ import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
1
2
  export declare class ResumeVC {
2
3
  sign({ formData, issuerDid, keyPair }: {
3
4
  formData: any;
@@ -20,7 +21,7 @@ export declare class ResumeVC {
20
21
  formData: any;
21
22
  issuerDid: string;
22
23
  }): any;
23
- generateKeyPair: (address?: string) => Promise<any>;
24
+ generateKeyPair: (address?: string) => Promise<Ed25519VerificationKey2020>;
24
25
  /**
25
26
  * Create a new DID with Digital Bazaar's Ed25519VerificationKey2020 key pair.
26
27
  * @returns {Promise<{didDocument: object, keyPair: object}>} The created DID document and key pair.
@@ -28,5 +29,5 @@ export declare class ResumeVC {
28
29
  */
29
30
  createDID({ keyPair }: {
30
31
  keyPair: any;
31
- }): Promise<import("../../types/credential.js").DidDocument>;
32
+ }): Promise<import("../../types/Credential.js").DidDocument>;
32
33
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Ed25519 signer compatible with @wallet.storage/fetch-client.
3
+ * Uses @digitalcredentials packages instead of @digitalbazaar.
4
+ */
5
+ import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
6
+ export declare class Ed25519Signer {
7
+ private readonly keyPair;
8
+ private readonly verificationMethod;
9
+ readonly algorithm = "Ed25519";
10
+ constructor(keyPair: Ed25519VerificationKey2020, verificationMethod: {
11
+ id: string;
12
+ type: string;
13
+ controller: string;
14
+ publicKeyMultibase: string;
15
+ });
16
+ static generate(): Promise<Ed25519Signer>;
17
+ static fromJSON(json: string): Promise<Ed25519Signer>;
18
+ get controller(): string;
19
+ get id(): string;
20
+ get publicKeyMultibase(): string;
21
+ sign({ data }: {
22
+ data: Uint8Array;
23
+ }): Promise<Uint8Array>;
24
+ toJSON(): object;
25
+ }