@learncard/network-plugin 2.13.15 → 2.13.17
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/lcn-plugin.cjs.development.cjs +81 -18
- package/dist/lcn-plugin.cjs.development.cjs.map +3 -3
- package/dist/lcn-plugin.cjs.production.min.cjs +34 -34
- package/dist/lcn-plugin.cjs.production.min.cjs.map +3 -3
- package/dist/lcn-plugin.esm.js +81 -18
- package/dist/lcn-plugin.esm.js.map +3 -3
- package/dist/plugin.d.ts +26 -6
- package/dist/plugin.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/plugin.ts +177 -36
package/dist/plugin.d.ts
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
import { LearnCard } from '@learncard/core';
|
|
2
2
|
import { VerifyExtension } from '@learncard/vc-plugin';
|
|
3
3
|
import { LearnCardNetworkPluginDependentMethods, LearnCardNetworkPlugin, VerifyBoostPlugin } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for federation URL validation.
|
|
6
|
+
*/
|
|
7
|
+
export interface FederationConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Explicit list of trusted hosts. If not provided, federation is open (any HTTPS host allowed).
|
|
10
|
+
* This is safe for client-side code where SSRF doesn't apply.
|
|
11
|
+
* Server-side code should provide an explicit allowlist.
|
|
12
|
+
*/
|
|
13
|
+
trustedFederationHosts?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Allow localhost/127.0.0.1 for development.
|
|
16
|
+
* Auto-detected: defaults to true when serviceUrl is localhost, false otherwise.
|
|
17
|
+
*/
|
|
18
|
+
allowLocalhostFederation?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The origin of this plugin's service URL. When set, endpoints matching this origin
|
|
21
|
+
* skip validation (they're self-generated, not from external DID documents).
|
|
22
|
+
*/
|
|
23
|
+
serviceOrigin?: string;
|
|
24
|
+
}
|
|
4
25
|
export * from './types';
|
|
5
26
|
export type GuardianApprovalGetter = () => string | undefined | Promise<string | undefined>;
|
|
6
27
|
/**
|
|
7
28
|
* @group Plugins
|
|
8
29
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
extraHeaders?: Record<string, string>;
|
|
12
|
-
}): Promise<LearnCardNetworkPlugin>;
|
|
13
|
-
export declare function getLearnCardNetworkPlugin(learnCard: LearnCard<any, any, LearnCardNetworkPluginDependentMethods>, url: string, apiToken: string, options?: {
|
|
30
|
+
/** Options for the LearnCard Network Plugin */
|
|
31
|
+
export interface LearnCardNetworkPluginOptions extends FederationConfig {
|
|
14
32
|
guardianApprovalGetter?: GuardianApprovalGetter;
|
|
15
33
|
extraHeaders?: Record<string, string>;
|
|
16
|
-
}
|
|
34
|
+
}
|
|
35
|
+
export declare function getLearnCardNetworkPlugin(learnCard: LearnCard<any, 'id', LearnCardNetworkPluginDependentMethods>, url: string, apiTokenOrOptions?: LearnCardNetworkPluginOptions): Promise<LearnCardNetworkPlugin>;
|
|
36
|
+
export declare function getLearnCardNetworkPlugin(learnCard: LearnCard<any, any, LearnCardNetworkPluginDependentMethods>, url: string, apiToken: string, options?: LearnCardNetworkPluginOptions): Promise<LearnCardNetworkPlugin>;
|
|
17
37
|
/**
|
|
18
38
|
* @group Plugins
|
|
19
39
|
*/
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQvD,OAAO,EACH,sCAAsC,EACtC,sBAAsB,EACtB,iBAAiB,EAEpB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQvD,OAAO,EACH,sCAAsC,EACtC,sBAAsB,EACtB,iBAAiB,EAEpB,MAAM,SAAS,CAAC;AAUjB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AA2XD,cAAc,SAAS,CAAC;AAExB,MAAM,MAAM,sBAAsB,GAAG,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;AAE5F;;GAEG;AACH,+CAA+C;AAC/C,MAAM,WAAW,6BAA8B,SAAQ,gBAAgB;IACnE,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,wBAAsB,yBAAyB,CAC3C,SAAS,EAAE,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,sCAAsC,CAAC,EACvE,GAAG,EAAE,MAAM,EACX,iBAAiB,CAAC,EAAE,6BAA6B,GAClD,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACnC,wBAAsB,yBAAyB,CAC3C,SAAS,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,sCAAsC,CAAC,EACtE,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,6BAA6B,GACxC,OAAO,CAAC,sBAAsB,CAAC,CAAC;AA6xEnC;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAC7B,WAAW,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC,EAC/C,0BAA0B,MAAM,KACjC,OAAO,CAAC,iBAAiB,CA8G3B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@learncard/network-plugin",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.17",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"url": "https://github.com/learningeconomy/LearnCard/issues"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@learncard/didkey-plugin": "^1.1.
|
|
43
|
-
"@learncard/didkit-plugin": "^1.9.
|
|
44
|
-
"@learncard/types": "5.18.
|
|
45
|
-
"@learncard/vc-plugin": "^1.5.
|
|
42
|
+
"@learncard/didkey-plugin": "^1.1.33",
|
|
43
|
+
"@learncard/didkit-plugin": "^1.9.13",
|
|
44
|
+
"@learncard/types": "5.18.3",
|
|
45
|
+
"@learncard/vc-plugin": "^1.5.13",
|
|
46
46
|
"@types/node": "^17.0.31",
|
|
47
47
|
"aqu": "0.4.3",
|
|
48
48
|
"esbuild": "^0.27.1",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
},
|
|
53
53
|
"types": "./dist/index.d.ts",
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@learncard/core": "9.4.
|
|
56
|
-
"@learncard/helpers": "1.
|
|
57
|
-
"@learncard/network-brain-client": "2.5.
|
|
55
|
+
"@learncard/core": "9.4.33",
|
|
56
|
+
"@learncard/helpers": "1.4.1",
|
|
57
|
+
"@learncard/network-brain-client": "2.5.54",
|
|
58
58
|
"mustache": "^4.2.0"
|
|
59
59
|
},
|
|
60
60
|
"sideEffects": false
|
package/src/plugin.ts
CHANGED
|
@@ -34,6 +34,135 @@ import {
|
|
|
34
34
|
TrustedBoostRegistryEntry,
|
|
35
35
|
} from './types';
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Trusted LearnCard domain suffixes for federation.
|
|
39
|
+
* Only dotted suffixes - the isLearnCardDomain check handles apex domains via
|
|
40
|
+
* `host === suffix.replace(/^\./, '')`. Bare entries would allow bypass
|
|
41
|
+
* (e.g., 'evillearncard.com'.endsWith('learncard.com') === true).
|
|
42
|
+
*/
|
|
43
|
+
const LEARNCARD_DOMAIN_SUFFIXES = ['.learncard.com', '.learncard.app', '.learncard.ai'];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Configuration for federation URL validation.
|
|
47
|
+
*/
|
|
48
|
+
export interface FederationConfig {
|
|
49
|
+
/**
|
|
50
|
+
* Explicit list of trusted hosts. If not provided, federation is open (any HTTPS host allowed).
|
|
51
|
+
* This is safe for client-side code where SSRF doesn't apply.
|
|
52
|
+
* Server-side code should provide an explicit allowlist.
|
|
53
|
+
*/
|
|
54
|
+
trustedFederationHosts?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* Allow localhost/127.0.0.1 for development.
|
|
57
|
+
* Auto-detected: defaults to true when serviceUrl is localhost, false otherwise.
|
|
58
|
+
*/
|
|
59
|
+
allowLocalhostFederation?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* The origin of this plugin's service URL. When set, endpoints matching this origin
|
|
62
|
+
* skip validation (they're self-generated, not from external DID documents).
|
|
63
|
+
*/
|
|
64
|
+
serviceOrigin?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Checks if a hostname matches any LearnCard domain suffix.
|
|
69
|
+
*/
|
|
70
|
+
const isLearnCardDomain = (host: string): boolean => {
|
|
71
|
+
return LEARNCARD_DOMAIN_SUFFIXES.some(
|
|
72
|
+
suffix => host === suffix.replace(/^\./, '') || host.endsWith(suffix)
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Checks if a hostname is localhost or loopback.
|
|
78
|
+
*/
|
|
79
|
+
const isLocalhostHost = (host: string): boolean => {
|
|
80
|
+
const lower = host.toLowerCase();
|
|
81
|
+
return lower === 'localhost' || lower === '127.0.0.1';
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Validates and normalizes a federation URL.
|
|
86
|
+
*
|
|
87
|
+
* This runs in the CLIENT plugin where SSRF risk is lower (the browser's same-origin
|
|
88
|
+
* policy provides protection). By default, federation is open to any HTTPS host.
|
|
89
|
+
* Server-side code should provide an explicit trustedFederationHosts list.
|
|
90
|
+
*
|
|
91
|
+
* Note: For local-service recipients, getInboxEndpointForDid returns a fixed
|
|
92
|
+
* `/api/inbox/receive` path. Only external DID doc serviceEndpoints preserve
|
|
93
|
+
* their original path.
|
|
94
|
+
*
|
|
95
|
+
* @param userProvidedUrl - The inbox endpoint URL (from DID doc or local service)
|
|
96
|
+
* @param config - Federation configuration with trusted hosts
|
|
97
|
+
* @returns The validated URL
|
|
98
|
+
* @throws Error if the URL is invalid or host is not trusted
|
|
99
|
+
*/
|
|
100
|
+
const validateFederationUrl = (userProvidedUrl: string, config: FederationConfig): string => {
|
|
101
|
+
let parsed: URL;
|
|
102
|
+
try {
|
|
103
|
+
parsed = new URL(userProvidedUrl);
|
|
104
|
+
} catch {
|
|
105
|
+
throw new Error(`Invalid federation endpoint URL: ${userProvidedUrl}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// If this endpoint matches our own service origin, skip validation entirely.
|
|
109
|
+
// These URLs are self-generated (e.g., from getInboxEndpointForDid when the recipient
|
|
110
|
+
// resolves to our local service), not from external DID documents.
|
|
111
|
+
if (config.serviceOrigin) {
|
|
112
|
+
const endpointOrigin = parsed.origin;
|
|
113
|
+
if (endpointOrigin === config.serviceOrigin) {
|
|
114
|
+
// Self-referential URL - return parsed.href so CodeQL sees URL sanitization
|
|
115
|
+
return parsed.href;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const host = parsed.hostname.toLowerCase();
|
|
120
|
+
const isLocalhost = isLocalhostHost(host);
|
|
121
|
+
|
|
122
|
+
// Handle localhost: check allowLocalhostFederation and convert https->http
|
|
123
|
+
if (isLocalhost) {
|
|
124
|
+
if (!config.allowLocalhostFederation) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`Localhost federation is disabled. Set allowLocalhostFederation: true for development.`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
// Local dev typically doesn't have TLS - convert https to http
|
|
130
|
+
if (parsed.protocol === 'https:') {
|
|
131
|
+
parsed.protocol = 'http:';
|
|
132
|
+
}
|
|
133
|
+
// Return the validated/normalized URL
|
|
134
|
+
return parsed.href;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Validate protocol - require HTTPS for non-localhost
|
|
138
|
+
if (parsed.protocol !== 'https:') {
|
|
139
|
+
throw new Error(`Federation requires HTTPS for non-localhost hosts: ${userProvidedUrl}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// If trustedFederationHosts is provided, use explicit allowlist mode
|
|
143
|
+
if (config.trustedFederationHosts !== undefined) {
|
|
144
|
+
const trustedHosts = new Set(config.trustedFederationHosts);
|
|
145
|
+
const allowAnyHost = trustedHosts.has('*');
|
|
146
|
+
|
|
147
|
+
// Check explicit list, LearnCard domains, or wildcard.
|
|
148
|
+
// Note: LearnCard domains are always trusted even with an explicit allowlist -
|
|
149
|
+
// this is intentional to ensure core federation always works.
|
|
150
|
+
if (!allowAnyHost && !isLearnCardDomain(host) && !trustedHosts.has(host)) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Federation host '${host}' is not trusted. ` +
|
|
153
|
+
`Add it to trustedFederationHosts or use '*' to allow any host.`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// If trustedFederationHosts is not provided, allow any HTTPS host (client-side default)
|
|
158
|
+
// This enables third-party did:web federation without requiring explicit opt-in
|
|
159
|
+
|
|
160
|
+
// Return the validated URL - CodeQL: at this point the URL has been validated
|
|
161
|
+
// as either matching our service origin, being localhost with permission, or
|
|
162
|
+
// being HTTPS with a trusted/allowed host
|
|
163
|
+
return parsed.href;
|
|
164
|
+
};
|
|
165
|
+
|
|
37
166
|
const uint8ArrayToBase64Url = (bytes: Uint8Array): string => {
|
|
38
167
|
let binary = '';
|
|
39
168
|
for (let i = 0; i < bytes.length; i += 1) binary += String.fromCharCode(bytes[i]!);
|
|
@@ -319,46 +448,52 @@ export type GuardianApprovalGetter = () => string | undefined | Promise<string |
|
|
|
319
448
|
/**
|
|
320
449
|
* @group Plugins
|
|
321
450
|
*/
|
|
451
|
+
/** Options for the LearnCard Network Plugin */
|
|
452
|
+
export interface LearnCardNetworkPluginOptions extends FederationConfig {
|
|
453
|
+
guardianApprovalGetter?: GuardianApprovalGetter;
|
|
454
|
+
extraHeaders?: Record<string, string>;
|
|
455
|
+
}
|
|
456
|
+
|
|
322
457
|
export async function getLearnCardNetworkPlugin(
|
|
323
458
|
learnCard: LearnCard<any, 'id', LearnCardNetworkPluginDependentMethods>,
|
|
324
459
|
url: string,
|
|
325
|
-
apiTokenOrOptions?:
|
|
326
|
-
guardianApprovalGetter?: GuardianApprovalGetter;
|
|
327
|
-
extraHeaders?: Record<string, string>;
|
|
328
|
-
}
|
|
460
|
+
apiTokenOrOptions?: LearnCardNetworkPluginOptions
|
|
329
461
|
): Promise<LearnCardNetworkPlugin>;
|
|
330
462
|
export async function getLearnCardNetworkPlugin(
|
|
331
463
|
learnCard: LearnCard<any, any, LearnCardNetworkPluginDependentMethods>,
|
|
332
464
|
url: string,
|
|
333
465
|
apiToken: string,
|
|
334
|
-
options?:
|
|
335
|
-
guardianApprovalGetter?: GuardianApprovalGetter;
|
|
336
|
-
extraHeaders?: Record<string, string>;
|
|
337
|
-
}
|
|
466
|
+
options?: LearnCardNetworkPluginOptions
|
|
338
467
|
): Promise<LearnCardNetworkPlugin>;
|
|
339
468
|
export async function getLearnCardNetworkPlugin(
|
|
340
469
|
learnCard: LearnCard<any, any, LearnCardNetworkPluginDependentMethods>,
|
|
341
470
|
url: string,
|
|
342
|
-
apiTokenOrOptions?:
|
|
343
|
-
|
|
344
|
-
| {
|
|
345
|
-
guardianApprovalGetter?: GuardianApprovalGetter;
|
|
346
|
-
extraHeaders?: Record<string, string>;
|
|
347
|
-
},
|
|
348
|
-
options?: {
|
|
349
|
-
guardianApprovalGetter?: GuardianApprovalGetter;
|
|
350
|
-
extraHeaders?: Record<string, string>;
|
|
351
|
-
}
|
|
471
|
+
apiTokenOrOptions?: string | LearnCardNetworkPluginOptions,
|
|
472
|
+
options?: LearnCardNetworkPluginOptions
|
|
352
473
|
): Promise<LearnCardNetworkPlugin> {
|
|
353
474
|
const apiToken = typeof apiTokenOrOptions === 'string' ? apiTokenOrOptions : undefined;
|
|
354
|
-
const
|
|
355
|
-
(typeof apiTokenOrOptions === 'object'
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
475
|
+
const resolvedOptions: LearnCardNetworkPluginOptions =
|
|
476
|
+
(typeof apiTokenOrOptions === 'object' ? apiTokenOrOptions : options) ?? {};
|
|
477
|
+
|
|
478
|
+
const {
|
|
479
|
+
guardianApprovalGetter,
|
|
480
|
+
extraHeaders,
|
|
481
|
+
trustedFederationHosts,
|
|
482
|
+
allowLocalhostFederation,
|
|
483
|
+
} = resolvedOptions;
|
|
484
|
+
|
|
485
|
+
// Parse service URL to determine origin and auto-detect localhost
|
|
486
|
+
const serviceUrl = new URL(url);
|
|
487
|
+
const serviceIsLocalhost = isLocalhostHost(serviceUrl.hostname);
|
|
488
|
+
|
|
489
|
+
// Federation config for URL validation
|
|
490
|
+
// - serviceOrigin: skip validation for self-referential URLs
|
|
491
|
+
// - allowLocalhostFederation: auto-detect from service URL if not explicitly set
|
|
492
|
+
const federationConfig: FederationConfig = {
|
|
493
|
+
trustedFederationHosts,
|
|
494
|
+
allowLocalhostFederation: allowLocalhostFederation ?? serviceIsLocalhost,
|
|
495
|
+
serviceOrigin: serviceUrl.origin,
|
|
496
|
+
};
|
|
362
497
|
// Initialize DID safely: in API-key mode there may be no local ID plane provider
|
|
363
498
|
let did = '';
|
|
364
499
|
try {
|
|
@@ -713,7 +848,11 @@ export async function getLearnCardNetworkPlugin(
|
|
|
713
848
|
return client.profileManager.updateProfileManager.mutate(manager);
|
|
714
849
|
},
|
|
715
850
|
deleteProfile: async () => {
|
|
716
|
-
|
|
851
|
+
// Settle initialization before deletion so it cannot repopulate userData later.
|
|
852
|
+
await initialQuery;
|
|
853
|
+
// API tokens may grant profiles:delete without profiles:read. The server
|
|
854
|
+
// validates the profile and scope; a local read must not gate deletion.
|
|
855
|
+
if (!apiToken) await ensureUser();
|
|
717
856
|
|
|
718
857
|
const result = await client.profile.deleteProfile.mutate();
|
|
719
858
|
|
|
@@ -910,13 +1049,14 @@ export async function getLearnCardNetworkPlugin(
|
|
|
910
1049
|
challenge: `inbox-federation-${crypto.randomUUID()}`,
|
|
911
1050
|
});
|
|
912
1051
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
}
|
|
1052
|
+
// Validate the federation URL. For external DIDs, inboxEndpoint comes
|
|
1053
|
+
// from the DID doc's serviceEndpoint; for local-service DIDs, it's
|
|
1054
|
+
// a fixed /api/inbox/receive path from getInboxEndpointForDid.
|
|
1055
|
+
const receiveUrl = validateFederationUrl(inboxEndpoint, federationConfig);
|
|
918
1056
|
|
|
919
1057
|
const response = await fetch(receiveUrl, {
|
|
1058
|
+
// A redirect must not bypass endpoint validation or forward credentials.
|
|
1059
|
+
redirect: 'error',
|
|
920
1060
|
method: 'POST',
|
|
921
1061
|
headers: {
|
|
922
1062
|
'Content-Type': 'application/json',
|
|
@@ -2645,7 +2785,9 @@ export async function getLearnCardNetworkPlugin(
|
|
|
2645
2785
|
|
|
2646
2786
|
isServiceTrusted: async (_learnCard, serviceDid) => {
|
|
2647
2787
|
const trustedServices = await client.federation.getTrustedServices.query({});
|
|
2648
|
-
return trustedServices.some(
|
|
2788
|
+
return trustedServices.some(
|
|
2789
|
+
(service: { did: string }) => service.did === serviceDid
|
|
2790
|
+
);
|
|
2649
2791
|
},
|
|
2650
2792
|
|
|
2651
2793
|
getTrustedServices: async () => {
|
|
@@ -2713,9 +2855,8 @@ export const getVerifyBoostPlugin = async (
|
|
|
2713
2855
|
const boostCredential = credential?.boostCredential;
|
|
2714
2856
|
try {
|
|
2715
2857
|
if (boostCredential) {
|
|
2716
|
-
const verifyBoostCredential =
|
|
2717
|
-
boostCredential
|
|
2718
|
-
);
|
|
2858
|
+
const verifyBoostCredential =
|
|
2859
|
+
await learnCard.invoke.verifyCredential(boostCredential);
|
|
2719
2860
|
const boostCredentialErrors = verifyBoostCredential.errors ?? [];
|
|
2720
2861
|
if (verifyBoostCredential.status?.length) {
|
|
2721
2862
|
verificationCheck.status = [
|