dataspace-client-sdk-node 0.1.1 → 0.2.0
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 +31 -0
- package/README.md +44 -1
- package/dist/client.d.ts +153 -33
- package/dist/client.js +619 -93
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types.d.ts +112 -1
- package/dist/vp-token.d.ts +37 -0
- package/dist/vp-token.js +56 -0
- package/docs/API.md +19 -4
- package/docs/BACKEND_NODE_INTEGRATION.md +249 -0
- package/docs/CONTROLLER_FLOW_STEP_BY_STEP.md +283 -0
- package/docs/DATA_MODEL_ALIGNMENT.md +37 -13
- package/docs/DEVELOPER_USE_CASES.md +10 -2
- package/docs/E2E_LOCAL_GW_UC5.md +49 -0
- package/docs/ENDPOINT_ID_CATALOG.md +90 -0
- package/docs/LEGAL_ORGANIZATION_FLOW_STEP_BY_STEP.md +84 -0
- package/docs/PERSONAL_FLOW_STEP_BY_STEP.md +70 -0
- package/docs/PORTAL_BACKEND_INTEGRATION_HANDOVER.md +343 -0
- package/docs/PRACTITIONER_FLOW_STEP_BY_STEP.md +182 -0
- package/docs/REACT_WEB_INTEGRATION.md +72 -0
- package/examples/e2e-bootstrap-tenant.mjs +3 -2
- package/examples/e2e-individual-flow.mjs +13 -8
- package/examples/host-activate-and-employee.mjs +3 -2
- package/examples/smoke-legal-org-local.mjs +40 -0
- package/package.json +4 -3
- package/src/client.ts +784 -132
- package/src/index.ts +1 -0
- package/src/types.ts +123 -1
- package/src/vp-token.ts +91 -0
- package/tests/client.test.mjs +491 -0
- package/tests/fixtures/ica-vp-minimal.json +67 -0
- package/tests/helpers/vp-token-fixture.mjs +23 -0
- package/tests/live-gw-uc5.e2e.test.mjs +108 -0
- package/SDK_PARITY_MAP.md +0 -120
- package/TODO_PROMPT_NEXT_STEPS.md +0 -185
- package/artifacts/update-smart-wallet.js +0 -1016
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -195,6 +195,26 @@ export type FamilyOrganizationSummary = {
|
|
|
195
195
|
updatedAt?: string;
|
|
196
196
|
};
|
|
197
197
|
|
|
198
|
+
export type OfferPreview = {
|
|
199
|
+
offerId?: string;
|
|
200
|
+
amount?: string;
|
|
201
|
+
currency?: string;
|
|
202
|
+
seats?: number;
|
|
203
|
+
planName?: string;
|
|
204
|
+
sku?: string;
|
|
205
|
+
paymentMethod?: string;
|
|
206
|
+
checkoutUrl?: string;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
export type OfferInfo = OfferPreview;
|
|
210
|
+
|
|
211
|
+
export type EndpointSelector = {
|
|
212
|
+
section: string;
|
|
213
|
+
format: string;
|
|
214
|
+
resourceType: string;
|
|
215
|
+
action: string;
|
|
216
|
+
};
|
|
217
|
+
|
|
198
218
|
/**
|
|
199
219
|
* Input for organization activation in GW using ICA-derived proof material.
|
|
200
220
|
*
|
|
@@ -203,9 +223,40 @@ export type FamilyOrganizationSummary = {
|
|
|
203
223
|
*/
|
|
204
224
|
export type GatewayOrganizationActivationInput = {
|
|
205
225
|
vpToken: string;
|
|
226
|
+
/** Generic requested seats/members for initial offer sizing. Defaults to 2. */
|
|
227
|
+
numberOfMembers?: number;
|
|
206
228
|
organizationVc?: string;
|
|
207
229
|
legalRepresentativeVc?: string;
|
|
208
230
|
regulatoryEvidence?: Record<string, unknown>;
|
|
231
|
+
/** @deprecated Prefer `numberOfMembers` and explicit input fields. */
|
|
232
|
+
additionalClaims?: Record<string, unknown>;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export type GatewayOrganizationActivationSimpleInput = {
|
|
236
|
+
jurisdiction?: string;
|
|
237
|
+
sector?: string;
|
|
238
|
+
vpToken: string;
|
|
239
|
+
serviceProviderDidWeb?: string;
|
|
240
|
+
serviceProviderUrl?: string;
|
|
241
|
+
controllerEmail?: string;
|
|
242
|
+
controllerTelephone?: string;
|
|
243
|
+
controllerRole: string;
|
|
244
|
+
numberOfMembers?: number;
|
|
245
|
+
timeoutSeconds?: number;
|
|
246
|
+
intervalSeconds?: number;
|
|
247
|
+
organizationVc?: string;
|
|
248
|
+
legalRepresentativeVc?: string;
|
|
249
|
+
regulatoryEvidence?: Record<string, unknown>;
|
|
250
|
+
additionalClaims?: Record<string, unknown>;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export type LegalOrganizationOrderSimpleInput = {
|
|
254
|
+
jurisdiction?: string;
|
|
255
|
+
sector?: string;
|
|
256
|
+
offerId: string;
|
|
257
|
+
timeoutSeconds?: number;
|
|
258
|
+
intervalSeconds?: number;
|
|
259
|
+
dataType?: string;
|
|
209
260
|
additionalClaims?: Record<string, unknown>;
|
|
210
261
|
};
|
|
211
262
|
|
|
@@ -219,6 +270,17 @@ export type EmployeeDeviceActivationInput = {
|
|
|
219
270
|
pollOptions?: PollOptions;
|
|
220
271
|
};
|
|
221
272
|
|
|
273
|
+
export type EmployeeDeviceActivationSimpleInput = {
|
|
274
|
+
tenantId?: string;
|
|
275
|
+
jurisdiction?: string;
|
|
276
|
+
sector?: string;
|
|
277
|
+
activationCode: string;
|
|
278
|
+
idToken: string;
|
|
279
|
+
dcrPayload: Record<string, unknown>;
|
|
280
|
+
timeoutSeconds?: number;
|
|
281
|
+
intervalSeconds?: number;
|
|
282
|
+
};
|
|
283
|
+
|
|
222
284
|
/**
|
|
223
285
|
* Result of device activation flow.
|
|
224
286
|
*
|
|
@@ -256,6 +318,40 @@ export type SubjectOrganizationBootstrapResult = {
|
|
|
256
318
|
confirmation?: SubmitAndPollResult;
|
|
257
319
|
};
|
|
258
320
|
|
|
321
|
+
export type IndividualOrganizationBootstrapSimpleInput = {
|
|
322
|
+
tenantId?: string;
|
|
323
|
+
jurisdiction?: string;
|
|
324
|
+
sector?: string;
|
|
325
|
+
alternateName: string;
|
|
326
|
+
controllerEmail?: string;
|
|
327
|
+
controllerTelephone?: string;
|
|
328
|
+
controllerRole?: string; // default org.hl7.v3.RoleCode|RESPRSN
|
|
329
|
+
timeoutSeconds?: number;
|
|
330
|
+
intervalSeconds?: number;
|
|
331
|
+
additionalClaims?: Record<string, unknown>;
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
export type IndividualOrganizationBootstrapSimpleResult = {
|
|
335
|
+
registration: SubmitAndPollResult;
|
|
336
|
+
offerId: string;
|
|
337
|
+
confirmation: SubmitAndPollResult;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export type IndividualOrganizationStartSimpleResult = {
|
|
341
|
+
registration: SubmitAndPollResult;
|
|
342
|
+
offerId: string;
|
|
343
|
+
offerPreview: OfferPreview;
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
export type IndividualOrganizationConfirmOrderSimpleInput = {
|
|
347
|
+
tenantId?: string;
|
|
348
|
+
jurisdiction?: string;
|
|
349
|
+
sector?: string;
|
|
350
|
+
offerId: string;
|
|
351
|
+
timeoutSeconds?: number;
|
|
352
|
+
intervalSeconds?: number;
|
|
353
|
+
};
|
|
354
|
+
|
|
259
355
|
/**
|
|
260
356
|
* Input for UC 5.5 IPS/FHIR import and index update.
|
|
261
357
|
*/
|
|
@@ -413,6 +509,8 @@ export type ClientOptions = {
|
|
|
413
509
|
bearerToken?: string;
|
|
414
510
|
defaultHeaders?: Record<string, string>;
|
|
415
511
|
wallet?: WalletProvider;
|
|
512
|
+
/** Optional default tenant context so calls can omit ctx repeatedly. */
|
|
513
|
+
ctx?: RouteContext;
|
|
416
514
|
};
|
|
417
515
|
|
|
418
516
|
/**
|
|
@@ -437,6 +535,8 @@ export type BackendPkceAuthOptions = {
|
|
|
437
535
|
/** Requested scopes for the SMART bearer token. */
|
|
438
536
|
scopes: string[];
|
|
439
537
|
/** Cache key for the resulting bearer token. Defaults to `pkce:<apiKey prefix>`. */
|
|
538
|
+
tokenCacheKey?: string;
|
|
539
|
+
/** @deprecated Use `tokenCacheKey`. */
|
|
440
540
|
endpointId?: string;
|
|
441
541
|
/** PKCE code verifier. Auto-generated with randomUUID if not provided. */
|
|
442
542
|
codeVerifier?: string;
|
|
@@ -447,6 +547,8 @@ export type BackendPkceAuthOptions = {
|
|
|
447
547
|
export type BackendPkceAuthResult = {
|
|
448
548
|
/** `fetched`: new token obtained. `cached`: valid token already in cache. `failed`: flow error. */
|
|
449
549
|
status: 'fetched' | 'cached' | 'failed';
|
|
550
|
+
tokenCacheKey: string;
|
|
551
|
+
/** @deprecated Use `tokenCacheKey`. */
|
|
450
552
|
endpointId: string;
|
|
451
553
|
accessToken: string;
|
|
452
554
|
tokenType: string;
|
|
@@ -458,6 +560,8 @@ export type BackendPkceAuthResult = {
|
|
|
458
560
|
export type BackendSmartAuthOptions = {
|
|
459
561
|
clientId: string;
|
|
460
562
|
scopes: string[];
|
|
563
|
+
tokenCacheKey?: string;
|
|
564
|
+
/** @deprecated Use `tokenCacheKey`. */
|
|
461
565
|
endpointId?: string;
|
|
462
566
|
tokenUrl?: string;
|
|
463
567
|
tokenPath?: string;
|
|
@@ -471,6 +575,8 @@ export type BackendSmartAuthOptions = {
|
|
|
471
575
|
export type BackendSmartAuthResult = {
|
|
472
576
|
status: 'fetched' | 'cached' | 'failed';
|
|
473
577
|
profile: 'smart-backend.v1';
|
|
578
|
+
tokenCacheKey: string;
|
|
579
|
+
/** @deprecated Use `tokenCacheKey`. */
|
|
474
580
|
endpointId: string;
|
|
475
581
|
accessToken?: string;
|
|
476
582
|
tokenType?: string;
|
|
@@ -481,12 +587,28 @@ export type BackendSmartAuthResult = {
|
|
|
481
587
|
};
|
|
482
588
|
|
|
483
589
|
export type SmartTokenExchangeInput = {
|
|
484
|
-
|
|
590
|
+
tokenCacheKey: string;
|
|
591
|
+
/** @deprecated Use `tokenCacheKey`. */
|
|
592
|
+
endpointId?: string;
|
|
485
593
|
scopes: string[];
|
|
486
594
|
exchangePayload: Record<string, unknown>;
|
|
487
595
|
path?: string;
|
|
488
596
|
};
|
|
489
597
|
|
|
598
|
+
export type SmartTokenRequestSimpleInput = {
|
|
599
|
+
tenantId?: string;
|
|
600
|
+
jurisdiction?: string;
|
|
601
|
+
sector?: string;
|
|
602
|
+
idToken: string;
|
|
603
|
+
scopes: string[];
|
|
604
|
+
tokenCacheKey?: string;
|
|
605
|
+
/** @deprecated Use `tokenCacheKey`. */
|
|
606
|
+
endpointId?: string;
|
|
607
|
+
timeoutSeconds?: number;
|
|
608
|
+
intervalSeconds?: number;
|
|
609
|
+
additionalClaims?: Record<string, unknown>;
|
|
610
|
+
};
|
|
611
|
+
|
|
490
612
|
export type SmartTokenExchangeResult = {
|
|
491
613
|
status: 'fetched' | 'cached' | 'failed';
|
|
492
614
|
accessToken?: string;
|
package/src/vp-token.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export type VpTokenHeader = {
|
|
2
|
+
alg: string;
|
|
3
|
+
typ?: string;
|
|
4
|
+
kid?: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type VpTokenPayload = {
|
|
9
|
+
iss: string;
|
|
10
|
+
sub?: string;
|
|
11
|
+
aud?: string;
|
|
12
|
+
jti?: string;
|
|
13
|
+
iat?: number;
|
|
14
|
+
exp?: number;
|
|
15
|
+
nonce?: string;
|
|
16
|
+
vp: {
|
|
17
|
+
'@context'?: unknown;
|
|
18
|
+
type?: unknown;
|
|
19
|
+
holder?: string;
|
|
20
|
+
verifiableCredential: string[];
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function toB64UrlJson(input: unknown): string {
|
|
27
|
+
return Buffer.from(JSON.stringify(input), 'utf-8').toString('base64url');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function fallbackId(): string {
|
|
31
|
+
const rand = Math.random().toString(36).slice(2, 10);
|
|
32
|
+
return `id-${Date.now()}-${rand}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function generateUuidLike(): string {
|
|
36
|
+
const fn = (globalThis as any)?.crypto?.randomUUID;
|
|
37
|
+
if (typeof fn === 'function') return fn.call((globalThis as any).crypto);
|
|
38
|
+
return fallbackId();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function buildEpochWindow(ttlSeconds = 300): { iat: number; exp: number } {
|
|
42
|
+
const iat = Math.floor(Date.now() / 1000);
|
|
43
|
+
return { iat, exp: iat + Math.max(1, Math.floor(ttlSeconds)) };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function createVP(input?: Partial<VpTokenPayload>): VpTokenPayload {
|
|
47
|
+
const ttl = input?.exp && input?.iat ? undefined : buildEpochWindow(300);
|
|
48
|
+
const jti = input?.jti || generateUuidLike();
|
|
49
|
+
const nonce = input?.nonce || generateUuidLike();
|
|
50
|
+
return {
|
|
51
|
+
iss: String(input?.iss || ''),
|
|
52
|
+
sub: input?.sub,
|
|
53
|
+
aud: input?.aud,
|
|
54
|
+
jti,
|
|
55
|
+
iat: input?.iat ?? ttl?.iat,
|
|
56
|
+
exp: input?.exp ?? ttl?.exp,
|
|
57
|
+
nonce,
|
|
58
|
+
vp: {
|
|
59
|
+
'@context': ['https://www.w3.org/2018/credentials/v1'],
|
|
60
|
+
type: ['VerifiablePresentation'],
|
|
61
|
+
holder: input?.vp?.holder || input?.iss || '',
|
|
62
|
+
verifiableCredential: [],
|
|
63
|
+
...(input?.vp || {}),
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function addVC(vpPayload: VpTokenPayload, vcJwt: string): VpTokenPayload {
|
|
69
|
+
const v = String(vcJwt || '').trim();
|
|
70
|
+
if (v) vpPayload.vp.verifiableCredential.push(v);
|
|
71
|
+
return vpPayload;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function prepareForSignature(header: VpTokenHeader, payload: VpTokenPayload): {
|
|
75
|
+
encodedHeader: string;
|
|
76
|
+
encodedPayload: string;
|
|
77
|
+
signingInput: string;
|
|
78
|
+
} {
|
|
79
|
+
const encodedHeader = toB64UrlJson(header);
|
|
80
|
+
const encodedPayload = toB64UrlJson(payload);
|
|
81
|
+
return { encodedHeader, encodedPayload, signingInput: `${encodedHeader}.${encodedPayload}` };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function prepareBytesForSignature(header: VpTokenHeader, payload: VpTokenPayload): Uint8Array {
|
|
85
|
+
const { signingInput } = prepareForSignature(header, payload);
|
|
86
|
+
return new TextEncoder().encode(signingInput);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function buildVpTokenCompact(encodedHeader: string, encodedPayload: string, signatureBase64Url: string): string {
|
|
90
|
+
return `${encodedHeader}.${encodedPayload}.${String(signatureBase64Url || '').trim()}`;
|
|
91
|
+
}
|