dataspace-client-sdk-node 0.1.2 → 0.2.1

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 CHANGED
@@ -18,6 +18,10 @@ All notable changes to this project will be documented in this file.
18
18
  - Offer/Order process clarified as part of the onboarding contract even when commercial amount is zero:
19
19
  - Offer extraction for UI review/acceptance
20
20
  - Explicit Order acceptance using offer identifier
21
+ - Activation trust-chain contract aligned with ICA/GW:
22
+ - `_activate` uses `vp_token` in message payload (not as HTTP Bearer),
23
+ - legal representative binding relies on `org.schema.Person.memberOf.taxID` and
24
+ `org.schema.Person.hasCredential.material` for key continuity between `_verify` and `vp_token` signature.
21
25
 
22
26
  ### Documentation
23
27
  - Updated:
@@ -25,4 +29,3 @@ All notable changes to this project will be documented in this file.
25
29
  - Clarified:
26
30
  - `/host` + `auth` alignment with current gateway model
27
31
  - namespace symmetry with ICA (`/ica`) and DataConv (`/publisher`)
28
-
package/README.md CHANGED
@@ -1,350 +1,23 @@
1
1
  # dataspace-client-sdk-node
2
2
 
3
- Node.js SDK to consume GW/UNID async DIDComm plain endpoints.
4
-
5
- **[→ Full API Reference](docs/API.md)**
6
- **[→ Data Model Alignment (GW + Chat + SDK)](docs/DATA_MODEL_ALIGNMENT.md)**
7
- **[ Frontend/Backend SDK Ownership Matrix](../docs/SDK_AUTH_OWNERSHIP.md)**
8
- **[ Developer Use-Case Cookbook (UC5 + additional patterns)](docs/DEVELOPER_USE_CASES.md)**
9
- **[ React Web Integration Guide](docs/REACT_WEB_INTEGRATION.md)**
10
- **[ Backend Node Integration Guide](docs/BACKEND_NODE_INTEGRATION.md)**
11
- **[ Portal Backend Integration Handover](docs/PORTAL_BACKEND_INTEGRATION_HANDOVER.md)**
12
-
13
- ## Onboarding flows (split by business case)
14
-
15
- Do not mix these two flows in the same narrative:
16
-
17
- 1. Legal Organization Onboarding (B2B/tenant/controller)
18
- 2. Personal Organization Onboarding (individual/family/subject)
19
-
20
- ### 1) Legal Organization Onboarding (B2B/tenant/controller)
21
-
22
- Canonical order when ICA proof is involved:
23
-
24
- 1. ICA proof/verification (`_verify`, external to this SDK).
25
- 2. GW activation in host registry: `Organization/_activate`.
26
- 3. Offer/Order phase for legal organization onboarding (always; if amount is 0, no payment step).
27
- 4. Device onboarding (DCR): `identity/openid/Device/_dcr`.
28
- 5. Post-DCR token exchange / SMART authorization for protected API calls.
29
-
30
- Node SDK helpers:
31
- - `activateOrganizationInGatewayFromIcaProof(...)` (UC5.2)
32
- - `activateEmployeeDeviceWithActivationCode(...)` (UC5.4)
33
- - `authenticateBackendPkceAndExchange(...)` or `authenticateBackendSmartStandard(...)`
34
-
35
- ### 2) Personal Organization Onboarding (individual/family/subject)
36
-
37
- Canonical order:
38
-
39
- 1. Personal/family registration: `individual/org.schema/Organization/_batch`.
40
- 2. Offer acceptance/order confirmation: `individual/org.schema/Order/_batch`.
41
- 3. Continue with consent + subject data workflows.
42
-
43
- Node SDK helper:
44
- - `bootstrapSubjectOrganizationIndex(...)` (UC5.1: registration + optional order confirmation)
45
-
46
- See:
47
- - `docs/DEVELOPER_USE_CASES.md` (UC5.1..UC5.7)
48
- - `docs/E2E_BOOTSTRAP.md` (host activation bootstrap)
49
-
50
- ## Scope
51
- - Generic async batch client (`_batch` + `_batch-response`) and JSON POST helper.
52
- - Route builders that cover Swagger v1 route families:
53
- - `host/registry`: `Organization _batch/_activate`, `Order`,
54
- - `entity`: `Employee`,
55
- - `identity`: `Device/_dcr`, `Token/_exchange`, `License/_issue`, SMART token, Firebase custom token,
56
- - `individual`: `Organization`, `Order`, `Person (legacy)`, `Consent`, `Composition`, `Communication`, `RelatedPerson`, `Observation`, `Task`,
57
- - `digitaltwin`: `Composition` (`org.hl7.fhir.api` and `org.hl7.fhir.r4`),
58
- - debug UHC task endpoints: `_call-start`, `_logs`.
59
-
60
- ## Claims Placement Contract
61
- - Canonical batch-entry claims location: `entry.resource.meta.claims`.
62
- - Legacy compatibility location: `entry.meta.claims`.
63
- - This SDK now emits both during migration; new consumers should read/write `resource.meta.claims`.
64
-
65
- ## Install (local workspace)
66
-
67
- ```bash
68
- cd tools/dataspace-client-sdk-node
69
- npm install
70
- npm run type-check
71
- npm run build
72
- ```
73
-
74
- ## Tests (mocked, no network)
75
-
76
- The SDK includes mocked tests (Python-SDK style) for:
77
- - route/path building,
78
- - async `submit + poll`,
79
- - multipart conversion upload.
80
-
81
- Run:
82
- ```bash
83
- cd sdk/dataspace-client-sdk-node
84
-
85
- npm test
86
-
87
- ```
88
-
89
-
90
- ```ts
91
- import { DataspaceNodeClient, createDidcommPlainMessage } from './dist/index.js';
92
- const client = new DataspaceNodeClient({
93
- baseUrl: 'http://localhost:3000',
94
- bearerToken: 'demo-token',
95
- });
96
-
97
- const ctx = { tenantId: 'acme', jurisdiction: 'ES', sector: 'health-care' };
98
- iss: 'adult1@example.com',
99
- aud: 'did:web:api.acme.org',
100
- body: {
101
- data: [
102
- {
103
- type: 'Family-registration-form-v1.0',
104
- meta: {
105
- claims: {
106
- '@context': 'org.schema',
107
- '@type': 'template',
108
- 'org.schema.Organization.address.addressCountry': 'ES',
109
- 'org.schema.Organization.identifier.additionalType': 'UUID',
110
- 'org.schema.Organization.identifier.value': 'f0d4b66d-7e28-4fa2-91b7-7041e57f4f90',
111
- 'org.schema.Person.email': 'adult1@example.com',
112
- 'org.schema.Service.category': 'health-care',
113
- 'org.schema.Service.identifier': 'did:web:api-provider.example.com',
114
- 'org.schema.Service.serviceType': 'http://terminology.hl7.org/CodeSystem/v3-ActReason|SRVC',
115
- 'org.schema.Service.termsOfService': 'https://provider.example.com/terms',
116
- },
117
- },
118
- },
119
- ],
120
- },
121
- });
122
-
123
- const submitPath = client.individualFamilyOrganizationBatchPath(ctx);
124
- const pollPath = client.individualFamilyOrganizationPollPath(ctx);
125
- const result = await client.submitAndPoll(submitPath, pollPath, payload);
126
- console.log(result.poll.status, result.poll.body);
127
- ```
128
-
129
- ## Backend auth: identity-exchange.v1 (B2B PKCE flow)
130
-
131
- For server-to-server integration (e.g. `uhc-unid-chat-node` calling the GW), the SDK implements the
132
- full `identity-exchange.v1` flow: DCR binding → PKCE code → token → SMART bearer exchange.
133
-
134
- This is the Node equivalent of Python's `authenticate_backend_pkce_and_exchange` in `connector-sdk-py`.
135
-
136
- **Prerequisites:**
137
- 1. Your tenant org is activated in the GW (`registry/org.schema/Organization/_activate` with ICA VC).
138
- 2. An API key with the required scopes has been issued by ICA (`identity/api-key/_create`).
139
- 3. You have your service's public JWK (EC P-384 recommended).
140
-
141
- **Usage:**
142
-
143
- ```ts
144
- import { DataspaceNodeClient } from './dist/index.js';
145
-
146
- const client = new DataspaceNodeClient({ baseUrl: 'https://gw.example.com' });
147
-
148
- const ctx = { tenantId: 'acme', jurisdiction: 'ES', sector: 'health-care' };
149
-
150
- // Run once per key pair; result is cached automatically.
151
- const auth = await client.authenticateBackendPkceAndExchange({
152
- ctx,
153
- apiKey: process.env.GW_API_KEY!,
154
- controllerPublicJwk: JSON.parse(process.env.GW_PUBLIC_JWK!),
155
- scopes: ['onboarding', 'family-registration', 'license-order'],
156
- endpointId: 'chatbot-main', // cache key; re-auth on expiry is automatic
157
- });
158
-
159
- if (auth.status === 'failed') {
160
- throw new Error(`Backend auth failed at step: ${auth.step}`);
161
- }
162
-
163
- // Use the bearer for subsequent requests:
164
- const authedClient = new DataspaceNodeClient({
165
- baseUrl: 'https://gw.example.com',
166
- bearerToken: auth.accessToken,
167
- });
168
- ```
169
-
170
- **Demo / local bypass (never for production):**
171
-
172
- ```ts
173
- // .env: SECURITY_MODE=demo GW_AUTH_BEARER=static-demo-token
174
- const client = new DataspaceNodeClient({
175
- baseUrl: process.env.BASE_URL!,
176
- bearerToken: process.env.GW_AUTH_BEARER, // skip identity-exchange.v1 entirely
177
- });
178
- ```
179
-
180
- ## Backend auth: smart-backend.v1 (client_credentials + private_key_jwt)
181
-
182
- For direct OAuth2 machine-to-machine flows (bypassing the PKCE device flow), use the
183
- `smart-backend.v1` profile. The SDK signs the `client_assertion` JWT locally using an
184
- in-memory ES384 wallet.
185
-
186
- This is the Node equivalent of Python's `authenticate_backend_smart_standard` in
187
- `connector-sdk-py`.
188
-
189
- **Usage:**
190
-
191
- ```ts
192
- import { DataspaceNodeClient, MemoryWalletProvider } from './dist/index.js';
193
-
194
- const wallet = new MemoryWalletProvider();
195
-
196
- // walletContext scopes the key pair. Use the service's logical identity.
197
- const walletContext = { tenantId: 'service-a', jurisdiction: 'ES', sector: 'health-care' };
198
-
199
- const client = new DataspaceNodeClient({
200
- baseUrl: 'https://gw.example.com',
201
- wallet,
202
- });
203
-
204
- // On first call, authenticates. On subsequent calls within token TTL, returns cached.
205
- const result = await client.authenticateBackendSmartStandard({
206
- clientId: 'service-a',
207
- scopes: ['system/*.read', 'system/*.write'],
208
- walletContext,
209
- // tokenUrl: optional absolute URL; defaults to `${baseUrl}/token`
210
- // audience: optional; defaults to the resolved tokenUrl
211
- // assertionTtlSeconds: optional; defaults to 300
212
- });
213
-
214
- if (result.status === 'failed') {
215
- throw new Error(`smart-backend.v1 auth failed: HTTP ${result.statusCode}`);
216
- }
217
-
218
- const authedClient = new DataspaceNodeClient({
219
- baseUrl: 'https://gw.example.com',
220
- bearerToken: result.accessToken,
221
- });
222
- ```
223
-
224
- **How it works internally:**
225
- 1. `MemoryWalletProvider` generates a dedicated EC P-384 key (`use: sig`, `alg: ES384`).
226
- 2. `signCompactJws(...)` produces the `client_assertion` JWT signed with that key.
227
- 3. A single `client_credentials` POST to the token endpoint returns the bearer.
228
- 4. The token is cached until 30s before expiry; subsequent calls return `status: 'cached'`.
229
-
230
- ## DIDComm encrypted (nested JWS-in-JWE)
231
-
232
- For GW endpoints that require `application/didcomm-encrypted+json`, use `submitBatchEncrypted`.
233
- This implements the nested JOSE pattern expected by the backend: sign first (ES384 compact JWS),
234
- then encrypt (ML-KEM-768 + A256GCM compact JWE with `cty: JWS`).
235
-
236
- Requires a wallet provider and the recipient's ML-KEM-768 encryption JWK (from GW
237
- `.well-known/jwks.json`, `use: enc`). The `MemoryWalletProvider` generates ML-KEM-768 keys
238
- automatically — no RSA setup required.
239
-
240
- ### ML-KEM-768 JWK format
241
-
242
- Encryption keys use the OKP JWK type with `crv: "ML-KEM-768"`:
243
-
244
- ```json
245
- {
246
- "kty": "OKP",
247
- "crv": "ML-KEM-768",
248
- "use": "enc",
249
- "alg": "ML-KEM-768",
250
- "x": "<base64url-encoded 1184-byte public key>",
251
- "kid": "wallet:acme:ES:health-care:abc123"
252
- }
253
- ```
254
-
255
- The `encrypted_key` slot in the compact JWE is the 1088-byte ML-KEM ciphertext (base64url).
256
- The 32-byte shared secret derived by KEM encapsulation is used directly as the AES-256-GCM CEK.
257
-
258
- ```ts
259
- import { DataspaceNodeClient, MemoryWalletProvider } from './dist/index.js';
260
-
261
- const wallet = new MemoryWalletProvider();
262
- const walletContext = { tenantId: 'acme', jurisdiction: 'ES', sector: 'health-care' };
263
- const client = new DataspaceNodeClient({ baseUrl: 'https://gw.example.com', wallet });
264
-
265
- // Wallet's own ML-KEM enc JWK (share with backend so it can encrypt to you):
266
- const [, encJwk] = await wallet.getPublicJwks(walletContext);
267
-
268
- // Fetch GW encryption JWK from well-known endpoint for outbound encryption:
269
- // const { keys } = await (await fetch('https://gw.example.com/.well-known/jwks.json')).json();
270
- // const recipientEncJwk = keys.find(k => k.use === 'enc' && k.crv === 'ML-KEM-768');
271
-
272
- // For local roundtrip test, use wallet's own enc key as recipient:
273
- const recipientEncJwk = encJwk;
274
-
275
- const payload = { thid: 'my-thid', body: { data: [] } };
276
- const result = await client.submitBatchEncrypted(
277
- client.individualFamilyOrganizationBatchPath(ctx),
278
- payload,
279
- recipientEncJwk,
280
- walletContext,
281
- );
282
- ```
283
-
284
- **Cache helper** — if you need the current bearer without re-running the flow:
285
-
286
- ```ts
287
- const bearer = client.getCachedBearerToken('chatbot-main');
288
- // Returns undefined if not cached or expired (>30s remaining).
289
- ```
290
-
291
- Full runnable example: `examples/backend-pkce-auth.mjs`
292
-
293
- ## Swagger parity strategy
294
- - For any v1 route exposed in Swagger, use:
295
- - `client.v1Path(ctx, section, format, resourceType, action)` for tenant routes.
296
- - `client.hostRegistryPath(ctx, resourceType, action)` for host registry routes.
297
- - Then call one of:
298
- - `submitBatch(path, didcommPayload)` for DIDComm plain submit routes,
299
- - `pollBatchResponse(path, { thid })` / `pollUntilComplete(...)`,
300
- - `postJson(path, payload)` for non-batch JSON routes.
301
-
302
- This avoids hardcoding curl scripts per endpoint.
303
-
304
- ## Notes for telephony tests
305
- - Keep GW/UHC unit/integration tests direct (service/router level).
306
- - Use this SDK for consumer-style E2E tests and external Node.js service integrations.
307
- - If individual onboarding moves to a separate service, telephony tests should consume that service and only use GW/UHC for reminders/calls.
308
-
309
- ## DataConversion / Excel
310
-
311
- This SDK now includes conversion helpers:
312
- - `conversionUploadPath(ctx, softwareId, sourceFormat)`
313
- - `conversionUploadPollPath(ctx, softwareId, sourceFormat)`
314
- - `uploadConversionFile({ path, fileName, fileContent, fields })`
315
-
316
- Example:
317
- - `examples/conversion-upload.mjs`
318
-
319
- Run:
320
- ```bash
321
- cd sdk/dataspace-client-sdk-node
322
- npm run build
323
- BASE_URL="http://localhost:3000" \
324
- AUTH_BEARER="demo-token" \
325
- TENANT_ID="acme" \
326
- JURISDICTION="ES" \
327
- SECTOR="animal-care" \
328
- SOFTWARE_ID="excel-adapter" \
329
- SOURCE_FORMAT="xlsx" \
330
- SOURCE_FILE="/absolute/path/to/input.xlsx" \
331
- node examples/conversion-upload.mjs
332
- ```
333
-
334
- Notes:
335
- - Exact multipart field names may vary by DataConversion deployment.
336
- - If your conversion API is synchronous, polling is optional.
337
- - If it is async, provide/resolve `thid` and poll `.../_upload-response`.
338
-
339
- ## Next planned additions
340
- - Typed payload builders per flow (`family`, `relatedPerson`, `observation`, `task`).
341
- - Claims mappers (`ClaimName` <-> SQL internal name with `_`).
342
- - Retry/backoff + richer error mapping.
343
-
344
- ## Planning and Parity Docs
345
-
346
- - TODO / execution prompt: `TODO_PROMPT_NEXT_STEPS.md`
347
- - Node/Python API parity map: `SDK_PARITY_MAP.md`
348
-
349
- ## Pending Compatibility TODO
350
- - See [SMART EHR compatibility TODO](docs/TODO_SMART_EHR_COMPAT.md).
3
+ Node.js SDK to consume GW/UNID async DIDComm endpoints.
4
+
5
+ ## Documentation Index
6
+
7
+ 1. [Full API Reference](docs/API.md)
8
+ 2. [Data Model Alignment (GW + Chat + SDK)](docs/DATA_MODEL_ALIGNMENT.md)
9
+ 3. [Frontend/Backend SDK Ownership Matrix](../docs/SDK_AUTH_OWNERSHIP.md)
10
+ 4. [Developer Use-Case Cookbook (UC5 + additional patterns)](docs/DEVELOPER_USE_CASES.md)
11
+ 5. [Live Local GW UC5 E2E (no mocks)](docs/E2E_LOCAL_GW_UC5.md)
12
+ 6. [React Web Integration Guide](docs/REACT_WEB_INTEGRATION.md)
13
+ 7. [Backend Node Integration Guide](docs/BACKEND_NODE_INTEGRATION.md)
14
+ 8. [Controller Flow Step by Step](docs/CONTROLLER_FLOW_STEP_BY_STEP.md)
15
+ 9. [Legal Organization Flow Step by Step](docs/LEGAL_ORGANIZATION_FLOW_STEP_BY_STEP.md)
16
+ 10. [Practitioner Flow Step by Step](docs/PRACTITIONER_FLOW_STEP_BY_STEP.md)
17
+ 11. [Portal Backend Integration Handover](docs/PORTAL_BACKEND_INTEGRATION_HANDOVER.md)
18
+
19
+ ## TODO and Roadmap
20
+
21
+ 1. [Prompt Next Steps TODO](TODO_PROMPT_NEXT_STEPS.md)
22
+ 2. [SMART EHR Compatibility TODO](docs/TODO_SMART_EHR_COMPAT.md)
23
+ 3. [SDK Parity Map](../SDK_PARITY_MAP.md)
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AsyncPollRequest, BackendPkceAuthOptions, BackendPkceAuthResult, BackendSmartAuthOptions, BackendSmartAuthResult, ClientOptions, CreatePhoneReminderTasksInput, GrantProfessionalAccessSimpleInput, GrantProfessionalAccessSimpleResult, DigitalTwinGenerationInput, EmployeeDeviceActivationInput, EmployeeDeviceActivationSimpleInput, EmployeeDeviceActivationResult, FamilyOrganizationSummary, GatewayOrganizationActivationInput, GatewayOrganizationActivationSimpleInput, HostRouteContext, IpsOrFhirImportInput, MedicationOverlapCheckInput, MedicationRegistrationInput, OrganizationEmployeeCreationInput, PollOptions, PollResult, OfferPreview, RouteContext, SmartTokenExchangeInput, SmartTokenExchangeResult, SmartTokenRequestSimpleInput, LegalOrganizationOrderSimpleInput, SubjectOrganizationBootstrapInput, SubjectOrganizationBootstrapResult, IndividualOrganizationBootstrapSimpleInput, IndividualOrganizationBootstrapSimpleResult, IndividualOrganizationStartSimpleResult, IndividualOrganizationConfirmOrderSimpleInput, SubmitAndPollResult, SubmitResponse, V1Action, V1Section } from './types.js';
1
+ import type { AsyncPollRequest, BackendPkceAuthOptions, BackendPkceAuthResult, BackendSmartAuthOptions, BackendSmartAuthResult, ClientOptions, CreatePhoneReminderTasksInput, GrantProfessionalAccessSimpleInput, GrantProfessionalAccessSimpleResult, DigitalTwinGenerationInput, EmployeeDeviceActivationInput, EndpointSelector, EmployeeDeviceActivationSimpleInput, EmployeeDeviceActivationResult, FamilyOrganizationSummary, GatewayOrganizationActivationInput, GatewayOrganizationActivationSimpleInput, HostRouteContext, IpsOrFhirImportInput, MedicationOverlapCheckInput, MedicationRegistrationInput, OrganizationEmployeeCreationInput, PollOptions, PollResult, OfferPreview, OfferInfo, RouteContext, SmartTokenExchangeInput, SmartTokenExchangeResult, SmartTokenRequestSimpleInput, LegalOrganizationOrderSimpleInput, SubjectOrganizationBootstrapInput, SubjectOrganizationBootstrapResult, IndividualOrganizationBootstrapSimpleInput, IndividualOrganizationBootstrapSimpleResult, IndividualOrganizationStartSimpleResult, IndividualOrganizationConfirmOrderSimpleInput, SubmitAndPollResult, SubmitResponse, V1Action, V1Section } from './types.js';
2
2
  import type { WalletProvider } from './sdk/dataspace-wallet-sdk-node/provider.js';
3
3
  import type { PublicJwk, WalletContext } from './sdk/dataspace-wallet-sdk-node/types.js';
4
4
  export declare class DataspaceNodeClient {
@@ -25,6 +25,14 @@ export declare class DataspaceNodeClient {
25
25
  setSector(sector: string): this;
26
26
  setDefaultTimeoutSeconds(seconds: number): this;
27
27
  setDefaultIntervalSeconds(seconds: number): this;
28
+ /**
29
+ * Builds a deterministic endpoint id for token cache and auth/session reuse.
30
+ * If `providerDid` is provided, returns a full DID service id:
31
+ * did:web:...#section:format:resourceType:action
32
+ * Otherwise returns the canonical fragment without '#':
33
+ * section:format:resourceType:action
34
+ */
35
+ getEndpointId(selector: EndpointSelector, providerDid?: string): string;
28
36
  private resolveSimplePollOptions;
29
37
  private requireRouteContext;
30
38
  private requireHostRouteContext;
@@ -178,7 +186,7 @@ export declare class DataspaceNodeClient {
178
186
  * Returns the cached SMART bearer for the given endpointId if still valid (>30s remaining).
179
187
  * Returns `undefined` if not cached or expired.
180
188
  */
181
- getCachedBearerToken(endpointId: string): string | undefined;
189
+ getCachedBearerToken(tokenCacheKey: string): string | undefined;
182
190
  /**
183
191
  * smart-backend.v1: obtain an OAuth2 backend token using client_credentials + private_key_jwt.
184
192
  */
@@ -200,6 +208,22 @@ export declare class DataspaceNodeClient {
200
208
  private signSmartBackendClientAssertion;
201
209
  private preferredJwtAlg;
202
210
  /**
211
+ * POST a DIDComm bundle payload.
212
+ * This is the preferred high-level method for DIDComm submission of
213
+ * FHIR/API bundles (batch, transaction, message, etc.).
214
+ *
215
+ * Returns immediately with the HTTP response — pair with `pollUntilComplete` or use `submitAndPoll`.
216
+ */
217
+ submitBundle(path: string, payload: {
218
+ thid?: string;
219
+ } & Record<string, unknown>, options?: {
220
+ mode?: 'plain' | 'strict';
221
+ recipientEncryptionJwk?: PublicJwk;
222
+ walletContext?: WalletContext;
223
+ }): Promise<SubmitResponse>;
224
+ /**
225
+ * @deprecated Use `submitBundle` instead.
226
+ *
203
227
  * POST a DIDComm plaintext payload to a batch submit path.
204
228
  * Use this for all `_batch` routes (family registration, observations, tasks, etc.).
205
229
  * Content-Type: `application/didcomm-plaintext+json`.
@@ -225,6 +249,11 @@ export declare class DataspaceNodeClient {
225
249
  * Content-Type: `application/json`.
226
250
  */
227
251
  postJson(path: string, payload: unknown): Promise<SubmitResponse>;
252
+ /**
253
+ * Legacy JSON submit for non-bundle payloads (openid/token/resource JSON bodies).
254
+ * Keeps JSON flows explicit and semantically separated from DIDComm bundle flows.
255
+ */
256
+ submitLegacyJson(path: string, payload: unknown): Promise<SubmitResponse>;
228
257
  /**
229
258
  * POST a multipart/form-data payload.
230
259
  * Use for file upload endpoints. Prefer `uploadConversionFile` for DataConversion uploads.
@@ -350,6 +379,15 @@ export declare class DataspaceNodeClient {
350
379
  * Extract a UI-ready Offer preview from activation/registration responses.
351
380
  */
352
381
  getOfferPreviewFromResponse(result: SubmitAndPollResult | PollResult | unknown): OfferPreview;
382
+ /**
383
+ * Alias of `getOfferPreviewFromResponse` with business naming.
384
+ */
385
+ getOfferInfoFromResponse(result: SubmitAndPollResult | PollResult | unknown): OfferInfo;
386
+ /**
387
+ * Extract activation code from response payload or claims.
388
+ * Supports common response shapes used in onboarding and license issuance flows.
389
+ */
390
+ getActivationCodeFromResponse(result: SubmitAndPollResult | PollResult | unknown): string | undefined;
353
391
  /**
354
392
  * Throws when first DIDComm entry contains a business-level error status.
355
393
  */