@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.
- package/dist/models/CredentialEngine.js +68 -11
- package/dist/models/ResumeVC.js +6 -7
- package/dist/types/models/CredentialEngine.d.ts +25 -4
- package/dist/types/models/ResumeVC.d.ts +3 -2
- package/dist/types/utils/Ed25519Signer.d.ts +25 -0
- package/dist/types/utils/context.d.ts +0 -538
- package/dist/types/utils/credential.d.ts +27 -159
- package/dist/types/utils/customDocumentLoader.d.ts +6 -0
- package/dist/types/utils/digitalbazaar.d.ts +1 -1
- package/dist/types/utils/getOrCreateAppDID.d.ts +1 -1
- package/dist/types/utils/google.d.ts +2 -2
- package/dist/utils/Ed25519Signer.js +71 -0
- package/dist/utils/context.js +0 -538
- package/dist/utils/credential.js +55 -7
- package/dist/utils/customDocumentLoader.js +20 -0
- package/dist/utils/decodedSeed.js +1 -1
- package/dist/utils/digitalbazaar.js +25 -11
- package/dist/utils/getOrCreateAppDID.js +1 -2
- package/dist/utils/google.js +18 -2
- package/package.json +7 -5
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import { Ed25519VerificationKey2020 } from '@
|
|
2
|
-
import { Ed25519Signature2020 } from '@
|
|
3
|
-
import * as dbVc from '@
|
|
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 {
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
378
|
+
documentLoader,
|
|
322
379
|
});
|
|
323
380
|
const rootFolders = await this.storage.findFolders();
|
|
324
381
|
// Find or create Credentials folder
|
package/dist/models/ResumeVC.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Ed25519Signature2020 } from '@
|
|
2
|
-
import {
|
|
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 '@
|
|
5
|
-
import { Ed25519VerificationKey2020 } from '@
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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<
|
|
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<
|
|
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/
|
|
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
|
+
}
|