sos-sdk-node-ts 0.1.17 → 0.1.19
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/CHANGELOG.md +15 -0
- package/README.md +8 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/portable-professional-evidence.d.ts +15 -0
- package/dist/portable-professional-evidence.js +98 -14
- package/dist/subject-card-provider-catalog-client.d.ts +32 -0
- package/dist/subject-card-provider-catalog-client.js +100 -0
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.19 - 2026-11-04
|
|
6
|
+
|
|
7
|
+
- Discover existing professional employee DID documents from an exact
|
|
8
|
+
configured provider using country, optional regional jurisdiction,
|
|
9
|
+
organization legal identifier, sector and verified email. Return only roles
|
|
10
|
+
whose authoritative DID document binds the expected employee authorization.
|
|
11
|
+
|
|
12
|
+
## 0.1.18 - 2026-11-03
|
|
13
|
+
|
|
14
|
+
- Add a trusted Node client for subject-card provider advertisements and
|
|
15
|
+
federated authorized-subject reads. Provider failures remain visible while
|
|
16
|
+
successful directories continue to return their cards.
|
|
17
|
+
- Consume `sos-data-utils-ts@0.6.21` and `sos-sdk-core-ts@0.5.4`, the exact
|
|
18
|
+
published provider-discovery contracts validated by this release.
|
|
19
|
+
|
|
5
20
|
## 0.1.17 - 2026-10-22
|
|
6
21
|
|
|
7
22
|
- Consume the shared historical NCBI OBO taxonomy read compatibility used by
|
package/README.md
CHANGED
|
@@ -78,6 +78,14 @@ BFF. It matches exact aliases inside `Organization.sameAs` CSV values and
|
|
|
78
78
|
rejects removed animal-card DID layouts before UI mapping. See
|
|
79
79
|
[the authorized subject directory contract](docs/AUTHORIZED_SUBJECT_DIRECTORY.md).
|
|
80
80
|
|
|
81
|
+
`sos-sdk-node-ts/portable-professional-evidence` lets a trusted BFF discover
|
|
82
|
+
existing professional roles from an exact configured provider using country,
|
|
83
|
+
optional ISO 3166-2 region, organization legal identifier, sector and verified
|
|
84
|
+
email. It derives candidate employee DIDs only from the governed role catalog
|
|
85
|
+
and returns a role only when the authoritative employee DID document binds the
|
|
86
|
+
expected authorization URN. These routing inputs and a later browser role
|
|
87
|
+
choice grant no authority by themselves.
|
|
88
|
+
|
|
81
89
|
`sos-sdk-node-ts/host-organization-directory-client` is the separate trusted-
|
|
82
90
|
BFF client for a host operator's organization directory. It sends the
|
|
83
91
|
canonical `org.schema/Organization/_search` request, polls the matching
|
package/dist/index.d.ts
CHANGED
|
@@ -11,3 +11,4 @@ export * from './server-passkey-profile.js';
|
|
|
11
11
|
export * from './host-organization-directory-client.js';
|
|
12
12
|
export * from './secure-organization-registration.js';
|
|
13
13
|
export * from './portable-professional-evidence.js';
|
|
14
|
+
export * from './subject-card-provider-catalog-client.js';
|
package/dist/index.js
CHANGED
|
@@ -11,3 +11,4 @@ export * from './server-passkey-profile.js';
|
|
|
11
11
|
export * from './host-organization-directory-client.js';
|
|
12
12
|
export * from './secure-organization-registration.js';
|
|
13
13
|
export * from './portable-professional-evidence.js';
|
|
14
|
+
export * from './subject-card-provider-catalog-client.js';
|
|
@@ -14,6 +14,21 @@ export type PortableProfessionalEnrollment = Readonly<{
|
|
|
14
14
|
jurisdiction: string;
|
|
15
15
|
role: string;
|
|
16
16
|
}>;
|
|
17
|
+
/**
|
|
18
|
+
* Finds the signed professional DID documents already published beneath one
|
|
19
|
+
* exact organization. Country, optional region, legal identifier and sector
|
|
20
|
+
* only reconstruct routing; the authoritative employee DID and authorization
|
|
21
|
+
* URN still determine every returned role.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolvePortableProfessionalOrganizationEnrollments(input: Readonly<{
|
|
24
|
+
country: unknown;
|
|
25
|
+
region?: unknown;
|
|
26
|
+
organizationIdentifier: unknown;
|
|
27
|
+
sector: unknown;
|
|
28
|
+
verifiedEmail: unknown;
|
|
29
|
+
providers: readonly PortableProfessionalProvider[];
|
|
30
|
+
fetchImpl?: typeof fetch;
|
|
31
|
+
}>): Promise<readonly PortableProfessionalEnrollment[]>;
|
|
17
32
|
/**
|
|
18
33
|
* Derives routing candidates only from evidence shape plus a server-owned host
|
|
19
34
|
* and sector allowlist. The returned candidate grants no authority: the signed
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createPublicKey, verify } from 'node:crypto';
|
|
2
2
|
import { inflateRawSync } from 'node:zlib';
|
|
3
3
|
import { buildProfessionalDidWeb } from 'gdc-common-utils-ts/utils/did';
|
|
4
|
+
import { getHealthcareProfessionalRolesBySector } from 'gdc-common-utils-ts/constants/healthcare';
|
|
4
5
|
const EMPLOYEE_AUTHORIZATION_URN_PATTERN = /^urn:cds-([a-z]{2}(?:-[a-z0-9]{2,3})?):v[1-9][0-9]*:organization:([a-z][a-z0-9-]*):([^:]+):member:(z[1-9A-HJ-NP-Za-km-z]+):([0-9]+)$/i;
|
|
5
6
|
function record(value) {
|
|
6
7
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
@@ -16,6 +17,102 @@ function identifiers(resource) {
|
|
|
16
17
|
function providerIssuer(provider) {
|
|
17
18
|
return `${new URL(provider.baseUrl).origin}/${encodeURIComponent(provider.tenantId)}/cds-${encodeURIComponent(provider.jurisdiction)}/v1/${encodeURIComponent(provider.sector)}`;
|
|
18
19
|
}
|
|
20
|
+
async function resolveProviderDid(provider, fetchImpl) {
|
|
21
|
+
const response = await fetchImpl(`${providerIssuer(provider)}/.well-known/did.json`, {
|
|
22
|
+
headers: { accept: 'application/did+json, application/json' },
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok)
|
|
25
|
+
throw new TypeError('professional_tenant_did_unavailable');
|
|
26
|
+
const document = record(await response.json());
|
|
27
|
+
const providerDid = text(document.id);
|
|
28
|
+
const expectedContext = `:${provider.tenantId}:cds-${provider.jurisdiction}:v1:${provider.sector}`;
|
|
29
|
+
const services = Array.isArray(document.service) ? document.service : [];
|
|
30
|
+
const hasJwks = services.some(service => text(record(service).type) === 'JsonWebKeyService2020'
|
|
31
|
+
&& /^https:\/\//i.test(text(record(service).serviceEndpoint)));
|
|
32
|
+
if (!providerDid.startsWith('did:web:') || !providerDid.endsWith(expectedContext) || !hasJwks) {
|
|
33
|
+
throw new TypeError('professional_tenant_did_invalid');
|
|
34
|
+
}
|
|
35
|
+
return providerDid;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Finds the signed professional DID documents already published beneath one
|
|
39
|
+
* exact organization. Country, optional region, legal identifier and sector
|
|
40
|
+
* only reconstruct routing; the authoritative employee DID and authorization
|
|
41
|
+
* URN still determine every returned role.
|
|
42
|
+
*/
|
|
43
|
+
export async function resolvePortableProfessionalOrganizationEnrollments(input) {
|
|
44
|
+
const country = text(input.country).toUpperCase();
|
|
45
|
+
const region = text(input.region).toUpperCase();
|
|
46
|
+
const jurisdiction = region || country;
|
|
47
|
+
const organizationIdentifier = text(input.organizationIdentifier);
|
|
48
|
+
const sector = text(input.sector).toLowerCase();
|
|
49
|
+
const verifiedEmail = text(input.verifiedEmail).toLowerCase();
|
|
50
|
+
if (!/^[A-Z]{2}$/.test(country))
|
|
51
|
+
throw new TypeError('professional_country_invalid');
|
|
52
|
+
if (region && (!new RegExp(`^${country}-[A-Z0-9]{1,3}$`).test(region))) {
|
|
53
|
+
throw new TypeError('professional_region_country_mismatch');
|
|
54
|
+
}
|
|
55
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{1,127}$/.test(organizationIdentifier)) {
|
|
56
|
+
throw new TypeError('professional_organization_identifier_invalid');
|
|
57
|
+
}
|
|
58
|
+
if (!verifiedEmail)
|
|
59
|
+
throw new TypeError('verified_email_required');
|
|
60
|
+
const roleCatalog = getHealthcareProfessionalRolesBySector(sector);
|
|
61
|
+
const roles = Object.values(roleCatalog).filter(role => role.claim.startsWith('ISCO-08|'));
|
|
62
|
+
if (!roles.length)
|
|
63
|
+
throw new TypeError('professional_sector_not_allowed');
|
|
64
|
+
const providers = input.providers.filter(provider => provider.tenantId === organizationIdentifier
|
|
65
|
+
&& provider.jurisdiction.toUpperCase() === jurisdiction
|
|
66
|
+
&& provider.sector.toLowerCase() === sector);
|
|
67
|
+
if (providers.length === 0)
|
|
68
|
+
throw new TypeError('professional_provider_not_found');
|
|
69
|
+
if (providers.length > 1)
|
|
70
|
+
throw new TypeError('multiple_professional_providers_found');
|
|
71
|
+
const provider = providers[0];
|
|
72
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
73
|
+
const providerDid = await resolveProviderDid(provider, fetchImpl);
|
|
74
|
+
const results = [];
|
|
75
|
+
for (const role of roles) {
|
|
76
|
+
const professionalDid = buildProfessionalDidWeb({
|
|
77
|
+
organizationDidWeb: providerDid,
|
|
78
|
+
email: verifiedEmail,
|
|
79
|
+
role: role.claim,
|
|
80
|
+
});
|
|
81
|
+
const memberPath = professionalDid.slice(`${providerDid}:employee:`.length);
|
|
82
|
+
const memberId = memberPath.slice(0, memberPath.indexOf(':'));
|
|
83
|
+
const didUrl = `${providerIssuer(provider)}/employee/${encodeURIComponent(memberId)}/${encodeURIComponent(role.claim)}/did.json`;
|
|
84
|
+
const response = await fetchImpl(didUrl, { headers: { accept: 'application/did+json, application/json' } });
|
|
85
|
+
if (response.status === 404)
|
|
86
|
+
continue;
|
|
87
|
+
if (!response.ok)
|
|
88
|
+
throw new TypeError('professional_directory_unavailable');
|
|
89
|
+
const document = record(await response.json());
|
|
90
|
+
if (text(document.id) !== professionalDid)
|
|
91
|
+
throw new TypeError('professional_did_invalid');
|
|
92
|
+
const employeeAuthorizationUrn = (Array.isArray(document.alsoKnownAs) ? document.alsoKnownAs : [])
|
|
93
|
+
.map(String).find(value => EMPLOYEE_AUTHORIZATION_URN_PATTERN.test(value)) || '';
|
|
94
|
+
const authorization = EMPLOYEE_AUTHORIZATION_URN_PATTERN.exec(employeeAuthorizationUrn);
|
|
95
|
+
if (!authorization
|
|
96
|
+
|| authorization[1].toUpperCase() !== jurisdiction
|
|
97
|
+
|| authorization[3] !== organizationIdentifier
|
|
98
|
+
|| authorization[5] !== role.code) {
|
|
99
|
+
throw new TypeError('professional_credential_binding_invalid');
|
|
100
|
+
}
|
|
101
|
+
results.push(Object.freeze({
|
|
102
|
+
sector: provider.sector,
|
|
103
|
+
employeeAuthorizationUrn,
|
|
104
|
+
professionalDid,
|
|
105
|
+
providerDid,
|
|
106
|
+
gatewayBaseUrl: new URL(provider.baseUrl).origin,
|
|
107
|
+
tenantId: provider.tenantId,
|
|
108
|
+
jurisdiction,
|
|
109
|
+
role: role.claim,
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
if (!results.length)
|
|
113
|
+
throw new TypeError('professional_profile_not_found');
|
|
114
|
+
return Object.freeze(results);
|
|
115
|
+
}
|
|
19
116
|
function decodeShcQr(value) {
|
|
20
117
|
const normalized = text(value);
|
|
21
118
|
if (!/^shc:\/\d+$/.test(normalized))
|
|
@@ -231,20 +328,7 @@ export async function resolvePortableProfessionalEnrollment(input) {
|
|
|
231
328
|
throw new TypeError('multiple_professional_providers_found');
|
|
232
329
|
const provider = matches[0];
|
|
233
330
|
const gatewayBaseUrl = new URL(provider.baseUrl).origin;
|
|
234
|
-
const
|
|
235
|
-
headers: { accept: 'application/did+json, application/json' },
|
|
236
|
-
});
|
|
237
|
-
if (!response.ok)
|
|
238
|
-
throw new TypeError('professional_tenant_did_unavailable');
|
|
239
|
-
const document = record(await response.json());
|
|
240
|
-
const providerDid = text(document.id);
|
|
241
|
-
const expectedContext = `:${provider.tenantId}:cds-${provider.jurisdiction}:v1:${provider.sector}`;
|
|
242
|
-
const services = Array.isArray(document.service) ? document.service : [];
|
|
243
|
-
const hasJwks = services.some(service => text(record(service).type) === 'JsonWebKeyService2020'
|
|
244
|
-
&& /^https:\/\//i.test(text(record(service).serviceEndpoint)));
|
|
245
|
-
if (!providerDid.startsWith('did:web:') || !providerDid.endsWith(expectedContext) || !hasJwks) {
|
|
246
|
-
throw new TypeError('professional_tenant_did_invalid');
|
|
247
|
-
}
|
|
331
|
+
const providerDid = await resolveProviderDid(provider, fetchImpl);
|
|
248
332
|
const role = `ISCO-08|${authorizationRoleCode}`;
|
|
249
333
|
const professionalDid = buildProfessionalDidWeb({ organizationDidWeb: providerDid, email: verifiedEmail, role });
|
|
250
334
|
return Object.freeze({
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { SubjectCardProviderDescriptor } from 'sos-data-utils-ts/subject-card-directory';
|
|
2
|
+
import { type SubjectCardProviderDiscoveryFilter } from 'sos-sdk-core-ts/subject-card-provider-discovery';
|
|
3
|
+
import { type AuthorizedIndividualSubject, type AuthorizedSubjectVerifiedContact } from './subject-card-directory-client.js';
|
|
4
|
+
export type SosSubjectCardProviderCatalogClientOptions = Readonly<{
|
|
5
|
+
catalogUrl: string;
|
|
6
|
+
bearerToken?: string;
|
|
7
|
+
fetchImpl?: typeof fetch;
|
|
8
|
+
}>;
|
|
9
|
+
/** Reads public provider advertisements from a data-space JSON:API catalog. */
|
|
10
|
+
export declare class SosSubjectCardProviderCatalogClient {
|
|
11
|
+
private readonly catalogUrl;
|
|
12
|
+
private readonly bearerToken?;
|
|
13
|
+
private readonly fetchImpl;
|
|
14
|
+
constructor(options: SosSubjectCardProviderCatalogClientOptions);
|
|
15
|
+
discover(filter: SubjectCardProviderDiscoveryFilter): Promise<readonly SubjectCardProviderDescriptor[]>;
|
|
16
|
+
}
|
|
17
|
+
export type FederatedProviderSubject = Readonly<{
|
|
18
|
+
providerId: string;
|
|
19
|
+
subject: AuthorizedIndividualSubject;
|
|
20
|
+
}>;
|
|
21
|
+
export type FederatedProviderSubjectResult = Readonly<{
|
|
22
|
+
subjects: readonly FederatedProviderSubject[];
|
|
23
|
+
unavailableProviderIds: readonly string[];
|
|
24
|
+
}>;
|
|
25
|
+
/** Queries every advertised directory independently and keeps partial success. */
|
|
26
|
+
export declare function readFederatedProviderSubjects(input: Readonly<{
|
|
27
|
+
providers: readonly SubjectCardProviderDescriptor[];
|
|
28
|
+
subjectKind?: 'human' | 'animal';
|
|
29
|
+
verifiedContact: AuthorizedSubjectVerifiedContact;
|
|
30
|
+
bearerToken?: string;
|
|
31
|
+
readProvider?: (provider: SubjectCardProviderDescriptor, verifiedContact: AuthorizedSubjectVerifiedContact) => Promise<readonly AuthorizedIndividualSubject[]>;
|
|
32
|
+
}>): Promise<FederatedProviderSubjectResult>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { discoverSubjectCardProviders, } from 'sos-sdk-core-ts/subject-card-provider-discovery';
|
|
2
|
+
import { SosGatewaySubjectDirectoryClient, } from './subject-card-directory-client.js';
|
|
3
|
+
/** Reads public provider advertisements from a data-space JSON:API catalog. */
|
|
4
|
+
export class SosSubjectCardProviderCatalogClient {
|
|
5
|
+
catalogUrl;
|
|
6
|
+
bearerToken;
|
|
7
|
+
fetchImpl;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.catalogUrl = secureUrl(options.catalogUrl);
|
|
10
|
+
this.bearerToken = optional(options.bearerToken);
|
|
11
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
12
|
+
}
|
|
13
|
+
async discover(filter) {
|
|
14
|
+
const url = new URL(this.catalogUrl);
|
|
15
|
+
url.searchParams.set('subjectKind', filter.subjectKind);
|
|
16
|
+
url.searchParams.set('operation', filter.operation);
|
|
17
|
+
const response = await this.fetchImpl(url, {
|
|
18
|
+
headers: {
|
|
19
|
+
Accept: 'application/vnd.api+json',
|
|
20
|
+
...(this.bearerToken ? { Authorization: `Bearer ${this.bearerToken}` } : {}),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok)
|
|
24
|
+
throw new Error(`provider_catalog_failed:${response.status}`);
|
|
25
|
+
const body = await response.json();
|
|
26
|
+
if (!Array.isArray(body.data))
|
|
27
|
+
throw new Error('provider_catalog_response_invalid');
|
|
28
|
+
const catalog = body.data.map(entry => {
|
|
29
|
+
const row = record(entry);
|
|
30
|
+
if (row.type !== 'subject-card-provider')
|
|
31
|
+
throw new Error('provider_catalog_entry_invalid');
|
|
32
|
+
return record(row.attributes);
|
|
33
|
+
});
|
|
34
|
+
return discoverSubjectCardProviders(catalog, filter);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Queries every advertised directory independently and keeps partial success. */
|
|
38
|
+
export async function readFederatedProviderSubjects(input) {
|
|
39
|
+
const providers = discoverSubjectCardProviders(input.providers, {
|
|
40
|
+
subjectKind: input.subjectKind ?? commonSubjectKind(input.providers),
|
|
41
|
+
operation: 'directory',
|
|
42
|
+
});
|
|
43
|
+
const readProvider = input.readProvider ?? (async (provider) => {
|
|
44
|
+
const route = parseDirectoryRoute(provider.directoryRoute);
|
|
45
|
+
const client = new SosGatewaySubjectDirectoryClient({
|
|
46
|
+
baseUrl: route.baseUrl,
|
|
47
|
+
bearerToken: input.bearerToken,
|
|
48
|
+
});
|
|
49
|
+
return client.listAuthorizedIndividualSubjects(route.context, {
|
|
50
|
+
verifiedContact: input.verifiedContact,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const settled = await Promise.allSettled(providers.map(provider => readProvider(provider, input.verifiedContact)));
|
|
54
|
+
const subjects = [];
|
|
55
|
+
const unavailableProviderIds = [];
|
|
56
|
+
for (const [index, result] of settled.entries()) {
|
|
57
|
+
const provider = providers[index];
|
|
58
|
+
if (result.status === 'rejected') {
|
|
59
|
+
unavailableProviderIds.push(provider.providerId);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
for (const subject of result.value)
|
|
63
|
+
subjects.push(Object.freeze({ providerId: provider.providerId, subject }));
|
|
64
|
+
}
|
|
65
|
+
return Object.freeze({
|
|
66
|
+
subjects: Object.freeze(subjects),
|
|
67
|
+
unavailableProviderIds: Object.freeze(unavailableProviderIds),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function commonSubjectKind(providers) {
|
|
71
|
+
const kinds = new Set(providers.flatMap(provider => provider.subjectKinds));
|
|
72
|
+
if (kinds.size !== 1)
|
|
73
|
+
throw new Error('provider_subject_kind_filter_required');
|
|
74
|
+
return [...kinds][0];
|
|
75
|
+
}
|
|
76
|
+
function parseDirectoryRoute(value) {
|
|
77
|
+
const url = secureUrl(value);
|
|
78
|
+
const segments = url.pathname.split('/').filter(Boolean);
|
|
79
|
+
if (segments.length !== 4 || !segments[1]?.startsWith('cds-') || segments[2] !== 'v1') {
|
|
80
|
+
throw new Error('provider_directory_route_invalid');
|
|
81
|
+
}
|
|
82
|
+
return Object.freeze({
|
|
83
|
+
baseUrl: url.origin,
|
|
84
|
+
context: Object.freeze({ tenantId: segments[0], jurisdiction: segments[1].slice(4), sector: segments[3] }),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function secureUrl(value) {
|
|
88
|
+
const url = new URL(value);
|
|
89
|
+
const local = url.hostname === 'localhost' || url.hostname === '127.0.0.1';
|
|
90
|
+
if (url.protocol !== 'https:' && !(url.protocol === 'http:' && local))
|
|
91
|
+
throw new Error('provider_url_insecure');
|
|
92
|
+
return url;
|
|
93
|
+
}
|
|
94
|
+
function optional(value) {
|
|
95
|
+
const normalized = String(value ?? '').trim();
|
|
96
|
+
return normalized || undefined;
|
|
97
|
+
}
|
|
98
|
+
function record(value) {
|
|
99
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
100
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sos-sdk-node-ts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Product-neutral Node adapters shared by SOSChain, Vet and UHC runtimes",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Connecting Solution & Applications Ltd",
|
|
@@ -59,6 +59,10 @@
|
|
|
59
59
|
"./portable-professional-evidence": {
|
|
60
60
|
"types": "./dist/portable-professional-evidence.d.ts",
|
|
61
61
|
"default": "./dist/portable-professional-evidence.js"
|
|
62
|
+
},
|
|
63
|
+
"./subject-card-provider-catalog-client": {
|
|
64
|
+
"types": "./dist/subject-card-provider-catalog-client.d.ts",
|
|
65
|
+
"default": "./dist/subject-card-provider-catalog-client.js"
|
|
62
66
|
}
|
|
63
67
|
},
|
|
64
68
|
"files": [
|
|
@@ -80,8 +84,8 @@
|
|
|
80
84
|
"@simplewebauthn/server": "13.3.2",
|
|
81
85
|
"gdc-common-utils-ts": "2.9.30",
|
|
82
86
|
"gdc-sdk-node-ts": "2.9.32",
|
|
83
|
-
"sos-data-utils-ts": "0.6.
|
|
84
|
-
"sos-sdk-core-ts": "0.5.
|
|
87
|
+
"sos-data-utils-ts": "0.6.21",
|
|
88
|
+
"sos-sdk-core-ts": "0.5.4"
|
|
85
89
|
},
|
|
86
90
|
"devDependencies": {
|
|
87
91
|
"@types/node": "^24.10.0",
|