@twin.org/dataspace-control-plane-service 0.9.1-next.8 → 0.9.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This package implements agreement negotiation and transfer process lifecycle management for control plane operations. It coordinates protocol-compliant state transitions and persists transfer state that can be consumed by downstream data plane components.
4
4
 
5
- Its behaviour follows the [Eclipse Dataspace Protocol](https://eclipse-dataspace-protocol-base.github.io/DataspaceProtocol/) and is designed for policy-aware transfer orchestration.
5
+ Its behaviour follows the [Eclipse Dataspace Protocol](https://eclipse-dataspace-protocol-base.github.io/DataspaceProtocol/) and is designed for policy-aware transfer orchestration. For the architectural context see the [dataspace architecture documentation](https://github.com/iotaledger/twin-dataspace/blob/next/docs/architecture/dataspace.mdx).
6
6
 
7
7
  ## Installation
8
8
 
@@ -445,13 +445,14 @@ export class DataspaceControlPlaneService {
445
445
  * @param trustPayload Trust payload for authenticating this call.
446
446
  * @returns The consumerPid of the newly created TransferProcess.
447
447
  *
448
- * **Engine configuration requirement:** The outbound call to the provider uses
448
+ * **Engine configuration requirement (remote transfers only):** when `providerEndpoint` is a
449
+ * remote origin the outbound call uses
449
450
  * `ComponentFactory.create(remoteControlPlaneComponentType, { endpoint, pathPrefix })`.
450
451
  * For the runtime `providerEndpoint` to be forwarded correctly, the engine **must** register
451
452
  * the component type (default: `dataspace-control-plane-rest-client`) as a
452
453
  * **multi-instance** component (`isMultiInstance: true` in engine config). A singleton
453
454
  * registration ignores the runtime `endpoint` arg and silently POSTs to its
454
- * static endpoint instead.
455
+ * static endpoint instead. Local-origin (same-node) transfers run in-process and are unaffected.
455
456
  */
456
457
  async prepareTransfer(agreementId, providerEndpoint, format, trustPayload) {
457
458
  Guards.stringValue(DataspaceControlPlaneService.CLASS_NAME, "agreementId", agreementId);
@@ -514,9 +515,10 @@ export class DataspaceControlPlaneService {
514
515
  });
515
516
  // Generate outbound trust token to authenticate this node to the provider.
516
517
  const outboundToken = await this._trustComponent.generate(organizationIdentity, this._overrideTrustGeneratorType, { subject: { consumerPid, agreementId } });
517
- // Create a remote REST client pointed at the provider endpoint and call requestTransfer.
518
- const remoteControlPlane = ComponentFactory.create(this._remoteControlPlaneComponentType, { endpoint: providerEndpoint, pathPrefix: "" });
519
- const result = await remoteControlPlane.requestTransfer(transferRequestMessage, outboundToken);
518
+ // Call the provider's requestTransfer. When providerEndpoint resolves to a local origin this
519
+ // runs in-process (no loopback HTTP, no multi-instance client required); otherwise it uses a
520
+ // remote REST client. Mirrors how state-change deliveries route via withControlPlaneComponent.
521
+ const result = await this.withControlPlaneComponent(providerEndpoint, async (component) => component.requestTransfer(transferRequestMessage, outboundToken));
520
522
  if (getJsonLdType(result) === DataspaceProtocolTransferProcessTypes.TransferError) {
521
523
  const transferError = result;
522
524
  throw new GeneralError(DataspaceControlPlaneService.CLASS_NAME, "transferRequestRejectedByProvider", {
@@ -1538,7 +1540,7 @@ export class DataspaceControlPlaneService {
1538
1540
  datasetId: id,
1539
1541
  tenantId: existing.tenantId ?? "",
1540
1542
  catalogErrorCode: removeResult.code
1541
- });
1543
+ }, BaseError.expand(removeResult.reason));
1542
1544
  }
1543
1545
  await this._dataspaceAppDatasetStorage.remove(id);
1544
1546
  await MetricHelper.metricIncrement(this._telemetryComponent, DataspaceControlPlaneMetricIds.AppDatasetsDeleted);
@@ -2348,18 +2350,15 @@ export class DataspaceControlPlaneService {
2348
2350
  const tenantContextIds = { ...contextIds, [ContextIdKeys.Tenant]: appDataset.tenantId };
2349
2351
  await ContextIdStore.run(tenantContextIds, async () => {
2350
2352
  const datasetPayload = this.restampDatasetId(appDataset.dataset, appDataset.id);
2351
- const rawDatasets = [datasetPayload];
2352
- const datasets = await Promise.all(rawDatasets.map(async (d) => this.populateDefaults(d)));
2353
- for (const dataset of datasets) {
2354
- const publishResult = await this._federatedCatalogueComponent.set(dataset, localTrustPayload);
2355
- if (isCatalogError(publishResult)) {
2356
- throw new GeneralError(DataspaceControlPlaneService.CLASS_NAME, "datasetPublishFailed", {
2357
- datasetId: appDataset.id,
2358
- appId: appDataset.appId,
2359
- tenantId: appDataset.tenantId ?? "",
2360
- catalogErrorCode: publishResult.code
2361
- });
2362
- }
2353
+ const dataset = await this.populateDefaults(datasetPayload);
2354
+ const publishResult = await this._federatedCatalogueComponent.set(dataset, localTrustPayload);
2355
+ if (isCatalogError(publishResult)) {
2356
+ throw new GeneralError(DataspaceControlPlaneService.CLASS_NAME, "datasetPublishFailed", {
2357
+ datasetId: appDataset.id,
2358
+ appId: appDataset.appId,
2359
+ tenantId: appDataset.tenantId ?? "",
2360
+ catalogErrorCode: publishResult.code
2361
+ }, BaseError.expand(publishResult.reason));
2363
2362
  }
2364
2363
  });
2365
2364
  }