@twin.org/dataspace-data-plane-service 0.0.3-next.28 → 0.0.3-next.30

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.
@@ -0,0 +1,83 @@
1
+ // Copyright 2025 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { entity, property, SortDirection } from "@twin.org/entity";
4
+ /**
5
+ * Persists a push subscription. One row per active push transfer.
6
+ * Primary key = consumerPid (same as TransferProcess).
7
+ */
8
+ let PushSubscription = class PushSubscription {
9
+ consumerPid;
10
+ providerPid;
11
+ /**
12
+ * ID of the Follow activity that created this subscription.
13
+ * Used by Undo to reference it on teardown.
14
+ */
15
+ followActivityId;
16
+ datasetId;
17
+ /**
18
+ * The tenant that owns this subscription, captured from the request context at
19
+ * write time. Optional — single-tenant nodes (no `TWIN_TENANT_ENABLED`) register
20
+ * subscriptions without a tenant context. The encrypted tenant token is also baked
21
+ * into `consumerEndpoint` so cross-node push deliveries route to the right tenant.
22
+ */
23
+ tenantId;
24
+ consumerEndpoint;
25
+ consumerAuthToken;
26
+ /**
27
+ * When true deliveries are skipped (transfer SUSPENDED).
28
+ * When false deliveries are flowing normally.
29
+ */
30
+ paused;
31
+ dateCreated;
32
+ /**
33
+ * Last-modified timestamp. Updated on suspend/resume (when `paused` flips) and on
34
+ * any subscription mutation. Matches the codebase convention of pairing `dateCreated`
35
+ * with `dateModified` on entities whose state mutates.
36
+ */
37
+ dateModified;
38
+ };
39
+ __decorate([
40
+ property({ type: "string", isPrimary: true }),
41
+ __metadata("design:type", String)
42
+ ], PushSubscription.prototype, "consumerPid", void 0);
43
+ __decorate([
44
+ property({ type: "string" }),
45
+ __metadata("design:type", String)
46
+ ], PushSubscription.prototype, "providerPid", void 0);
47
+ __decorate([
48
+ property({ type: "string" }),
49
+ __metadata("design:type", String)
50
+ ], PushSubscription.prototype, "followActivityId", void 0);
51
+ __decorate([
52
+ property({ type: "string" }),
53
+ __metadata("design:type", String)
54
+ ], PushSubscription.prototype, "datasetId", void 0);
55
+ __decorate([
56
+ property({ type: "string", optional: true }),
57
+ __metadata("design:type", String)
58
+ ], PushSubscription.prototype, "tenantId", void 0);
59
+ __decorate([
60
+ property({ type: "string" }),
61
+ __metadata("design:type", String)
62
+ ], PushSubscription.prototype, "consumerEndpoint", void 0);
63
+ __decorate([
64
+ property({ type: "string", optional: true }),
65
+ __metadata("design:type", String)
66
+ ], PushSubscription.prototype, "consumerAuthToken", void 0);
67
+ __decorate([
68
+ property({ type: "boolean" }),
69
+ __metadata("design:type", Boolean)
70
+ ], PushSubscription.prototype, "paused", void 0);
71
+ __decorate([
72
+ property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
73
+ __metadata("design:type", String)
74
+ ], PushSubscription.prototype, "dateCreated", void 0);
75
+ __decorate([
76
+ property({ type: "string", format: "date-time" }),
77
+ __metadata("design:type", String)
78
+ ], PushSubscription.prototype, "dateModified", void 0);
79
+ PushSubscription = __decorate([
80
+ entity()
81
+ ], PushSubscription);
82
+ export { PushSubscription };
83
+ //# sourceMappingURL=pushSubscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pushSubscription.js","sourceRoot":"","sources":["../../../src/entities/pushSubscription.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEnE;;;GAGG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAErB,WAAW,CAAU;IAGrB,WAAW,CAAU;IAE5B;;;OAGG;IAEI,gBAAgB,CAAU;IAG1B,SAAS,CAAU;IAE1B;;;;;OAKG;IAEI,QAAQ,CAAU;IAGlB,gBAAgB,CAAU;IAG1B,iBAAiB,CAAU;IAElC;;;OAGG;IAEI,MAAM,CAAW;IAGjB,WAAW,CAAU;IAE5B;;;;OAIG;IAEI,YAAY,CAAU;CAC7B,CAAA;AA/CO;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;qDAClB;AAGrB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;qDACD;AAOrB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;0DACI;AAG1B;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;mDACH;AASnB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;kDACpB;AAGlB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;0DACI;AAG1B;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2DACX;AAO3B;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;gDACN;AAGjB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,CAAC,UAAU,EAAE,CAAC;;qDAC/D;AAQrB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;;sDACrB;AAhDjB,gBAAgB;IAD5B,MAAM,EAAE;GACI,gBAAgB,CAiD5B","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property, SortDirection } from \"@twin.org/entity\";\n\n/**\n * Persists a push subscription. One row per active push transfer.\n * Primary key = consumerPid (same as TransferProcess).\n */\n@entity()\nexport class PushSubscription {\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic consumerPid!: string;\n\n\t@property({ type: \"string\" })\n\tpublic providerPid!: string;\n\n\t/**\n\t * ID of the Follow activity that created this subscription.\n\t * Used by Undo to reference it on teardown.\n\t */\n\t@property({ type: \"string\" })\n\tpublic followActivityId!: string;\n\n\t@property({ type: \"string\" })\n\tpublic datasetId!: string;\n\n\t/**\n\t * The tenant that owns this subscription, captured from the request context at\n\t * write time. Optional — single-tenant nodes (no `TWIN_TENANT_ENABLED`) register\n\t * subscriptions without a tenant context. The encrypted tenant token is also baked\n\t * into `consumerEndpoint` so cross-node push deliveries route to the right tenant.\n\t */\n\t@property({ type: \"string\", optional: true })\n\tpublic tenantId?: string;\n\n\t@property({ type: \"string\" })\n\tpublic consumerEndpoint!: string;\n\n\t@property({ type: \"string\", optional: true })\n\tpublic consumerAuthToken?: string;\n\n\t/**\n\t * When true deliveries are skipped (transfer SUSPENDED).\n\t * When false deliveries are flowing normally.\n\t */\n\t@property({ type: \"boolean\" })\n\tpublic paused!: boolean;\n\n\t@property({ type: \"string\", format: \"date-time\", sortDirection: SortDirection.Descending })\n\tpublic dateCreated!: string;\n\n\t/**\n\t * Last-modified timestamp. Updated on suspend/resume (when `paused` flips) and on\n\t * any subscription mutation. Matches the codebase convention of pairing `dateCreated`\n\t * with `dateModified` on entities whose state mutates.\n\t */\n\t@property({ type: \"string\", format: \"date-time\" })\n\tpublic dateModified!: string;\n}\n"]}
package/dist/es/index.js CHANGED
@@ -5,6 +5,7 @@ export * from "./dataspaceDataPlaneSocketRoutes.js";
5
5
  export * from "./dataspaceDataPlaneService.js";
6
6
  export * from "./entities/activityLogDetails.js";
7
7
  export * from "./entities/activityTask.js";
8
+ export * from "./entities/pushSubscription.js";
8
9
  export * from "./models/IDataspaceDataPlaneServiceConfig.js";
9
10
  export * from "./models/IDataspaceDataPlaneServiceConstructorOptions.js";
10
11
  export * from "./restEntryPoints.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,0DAA0D,CAAC;AACzE,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./dataspaceDataPlaneRoutes.js\";\nexport * from \"./dataspaceDataPlaneSocketRoutes.js\";\nexport * from \"./dataspaceDataPlaneService.js\";\nexport * from \"./entities/activityLogDetails.js\";\nexport * from \"./entities/activityTask.js\";\nexport * from \"./models/IDataspaceDataPlaneServiceConfig.js\";\nexport * from \"./models/IDataspaceDataPlaneServiceConstructorOptions.js\";\nexport * from \"./restEntryPoints.js\";\nexport * from \"./schema.js\";\nexport * from \"./socketEntryPoints.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8CAA8C,CAAC;AAC7D,cAAc,0DAA0D,CAAC;AACzE,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./dataspaceDataPlaneRoutes.js\";\nexport * from \"./dataspaceDataPlaneSocketRoutes.js\";\nexport * from \"./dataspaceDataPlaneService.js\";\nexport * from \"./entities/activityLogDetails.js\";\nexport * from \"./entities/activityTask.js\";\nexport * from \"./entities/pushSubscription.js\";\nexport * from \"./models/IDataspaceDataPlaneServiceConfig.js\";\nexport * from \"./models/IDataspaceDataPlaneServiceConstructorOptions.js\";\nexport * from \"./restEntryPoints.js\";\nexport * from \"./schema.js\";\nexport * from \"./socketEntryPoints.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"IDataspaceDataPlaneServiceConfig.js","sourceRoot":"","sources":["../../../src/models/IDataspaceDataPlaneServiceConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Dataspace Data Plane service configuration\n */\nexport interface IDataspaceDataPlaneServiceConfig {\n\t/**\n\t * The amount of time in minutes to retain activity log entries until removal, set to -1 to keep forever.\n\t * @default 10\n\t */\n\tretainActivityLogsFor?: number;\n\n\t/**\n\t * The interval in minutes in between activity log clean ups. -1 indicates no clean up shall be done.\n\t * @default 60 minutes\n\t */\n\tactivityLogsCleanUpInterval?: number;\n\n\t/**\n\t * The number of times to retry failed tasks, defaults to forever.\n\t * @default undefined.\n\t */\n\tretryCount?: number;\n}\n"]}
1
+ {"version":3,"file":"IDataspaceDataPlaneServiceConfig.js","sourceRoot":"","sources":["../../../src/models/IDataspaceDataPlaneServiceConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Dataspace Data Plane service configuration\n */\nexport interface IDataspaceDataPlaneServiceConfig {\n\t/**\n\t * The amount of time in minutes to retain activity log entries until removal, set to -1 to keep forever.\n\t * @default 10\n\t */\n\tretainActivityLogsFor?: number;\n\n\t/**\n\t * The interval in minutes in between activity log clean ups. -1 indicates no clean up shall be done.\n\t * @default 60 minutes\n\t */\n\tactivityLogsCleanUpInterval?: number;\n\n\t/**\n\t * The number of times to retry failed tasks, defaults to forever.\n\t * @default undefined.\n\t */\n\tretryCount?: number;\n\n\t/**\n\t * Max HTTP retry attempts per push delivery task execution.\n\t * @default 3\n\t */\n\tpushRetryCount?: number;\n\n\t/**\n\t * Base delay (ms) for exponential backoff between push HTTP retries.\n\t * Effective delay = baseDelayMs * 2^attempt.\n\t * @default 1000\n\t */\n\tpushRetryBaseDelayMs?: number;\n\n\t/**\n\t * Timeout (ms) for each push delivery HTTP POST request.\n\t * @default 30000\n\t */\n\tpushTimeoutMs?: number;\n\n\t/**\n\t * Interval (ms) between orphaned PushSubscription cleanup scans.\n\t * @default 3600000 (1 hour)\n\t */\n\tpushSubscriptionCleanupIntervalMs?: number;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"IDataspaceDataPlaneServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IDataspaceDataPlaneServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IDataspaceDataPlaneServiceConfig } from \"./IDataspaceDataPlaneServiceConfig.js\";\n\n/**\n * Dataspace Data Plane service options\n */\nexport interface IDataspaceDataPlaneServiceConstructorOptions {\n\t/**\n\t * Logging component type.\n\t * @default logging\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * Background task component.\n\t * @default background-task\n\t */\n\tbackgroundTaskComponentType?: string;\n\n\t/**\n\t * Task Scheduler Component Type.\n\t * @default task-scheduler\n\t */\n\ttaskSchedulerComponentType?: string;\n\n\t/**\n\t * The entity storage for activity log details.\n\t * @default activity-log-details\n\t */\n\tactivityLogEntityStorageType?: string;\n\n\t/**\n\t * The entity storage for the association between Activities and Tasks.\n\t * @default activity-task\n\t */\n\tactivityTaskEntityStorageType?: string;\n\n\t/**\n\t * The entity storage type for Transfer Process entities.\n\t * Used to read Transfer Process state from shared storage.\n\t * @default transfer-process\n\t */\n\ttransferProcessEntityStorageType?: string;\n\n\t/**\n\t * The entity storage type for Dataspace App Dataset entities.\n\t * @default dataspace-app-dataset\n\t */\n\tdataspaceAppDatasetEntityStorageType?: string;\n\n\t/**\n\t * The keys to use from the context ids to cleanup partitions.\n\t */\n\tpartitionContextIds?: string[];\n\n\t/**\n\t * Trust component type.\n\t * @default trust\n\t */\n\ttrustComponentType?: string;\n\n\t/**\n\t * Policy enforcement point component type for ODRL policy enforcement.\n\t * @default policy-enforcement-point-service\n\t */\n\tpepComponentType?: string;\n\n\t/**\n\t * Tenant admin component type.\n\t * @default tenant-admin\n\t */\n\ttenantAdminType?: string;\n\n\t/**\n\t * The configuration of the Dataspace Data Plane Service.\n\t */\n\tconfig?: IDataspaceDataPlaneServiceConfig;\n}\n"]}
1
+ {"version":3,"file":"IDataspaceDataPlaneServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IDataspaceDataPlaneServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IDataspaceDataPlaneServiceConfig } from \"./IDataspaceDataPlaneServiceConfig.js\";\n\n/**\n * Dataspace Data Plane service options\n */\nexport interface IDataspaceDataPlaneServiceConstructorOptions {\n\t/**\n\t * Logging component type.\n\t * @default logging\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * Background task component.\n\t * @default background-task\n\t */\n\tbackgroundTaskComponentType?: string;\n\n\t/**\n\t * Task Scheduler Component Type.\n\t * @default task-scheduler\n\t */\n\ttaskSchedulerComponentType?: string;\n\n\t/**\n\t * The entity storage for activity log details.\n\t * @default activity-log-details\n\t */\n\tactivityLogEntityStorageType?: string;\n\n\t/**\n\t * The entity storage for the association between Activities and Tasks.\n\t * @default activity-task\n\t */\n\tactivityTaskEntityStorageType?: string;\n\n\t/**\n\t * The entity storage type for Transfer Process entities.\n\t * Used to read Transfer Process state from shared storage.\n\t * @default transfer-process\n\t */\n\ttransferProcessEntityStorageType?: string;\n\n\t/**\n\t * The entity storage type for PushSubscription entities.\n\t * @default push-subscription\n\t */\n\tpushSubscriptionEntityStorageType?: string;\n\n\t/**\n\t * The entity storage type for Dataspace App Dataset entities.\n\t * @default dataspace-app-dataset\n\t */\n\tdataspaceAppDatasetEntityStorageType?: string;\n\n\t/**\n\t * The keys to use from the context ids to cleanup partitions.\n\t */\n\tpartitionContextIds?: string[];\n\n\t/**\n\t * Trust component type.\n\t * @default trust\n\t */\n\ttrustComponentType?: string;\n\n\t/**\n\t * Policy enforcement point component type for ODRL policy enforcement.\n\t * @default policy-enforcement-point-service\n\t */\n\tpepComponentType?: string;\n\n\t/**\n\t * Tenant admin component type.\n\t * @default tenant-admin\n\t */\n\ttenantAdminType?: string;\n\n\t/**\n\t * The configuration of the Dataspace Data Plane Service.\n\t */\n\tconfig?: IDataspaceDataPlaneServiceConfig;\n}\n"]}
package/dist/es/schema.js CHANGED
@@ -3,11 +3,13 @@
3
3
  import { EntitySchemaFactory, EntitySchemaHelper } from "@twin.org/entity";
4
4
  import { ActivityLogDetails } from "./entities/activityLogDetails.js";
5
5
  import { ActivityTask } from "./entities/activityTask.js";
6
+ import { PushSubscription } from "./entities/pushSubscription.js";
6
7
  /**
7
8
  * Inits schemas.
8
9
  */
9
10
  export function initSchema() {
10
11
  EntitySchemaFactory.register("ActivityLogDetails", () => EntitySchemaHelper.getSchema(ActivityLogDetails));
11
12
  EntitySchemaFactory.register("ActivityTask", () => EntitySchemaHelper.getSchema(ActivityTask));
13
+ EntitySchemaFactory.register("PushSubscription", () => EntitySchemaHelper.getSchema(PushSubscription));
12
14
  }
13
15
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,mBAAmB,CAAC,QAAQ,uBAA+B,GAAG,EAAE,CAC/D,kBAAkB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAChD,CAAC;IAEF,mBAAmB,CAAC,QAAQ,iBAAyB,GAAG,EAAE,CACzD,kBAAkB,CAAC,SAAS,CAAC,YAAY,CAAC,CAC1C,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { EntitySchemaFactory, EntitySchemaHelper } from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { ActivityLogDetails } from \"./entities/activityLogDetails.js\";\nimport { ActivityTask } from \"./entities/activityTask.js\";\n\n/**\n * Inits schemas.\n */\nexport function initSchema(): void {\n\tEntitySchemaFactory.register(nameof<ActivityLogDetails>(), () =>\n\t\tEntitySchemaHelper.getSchema(ActivityLogDetails)\n\t);\n\n\tEntitySchemaFactory.register(nameof<ActivityTask>(), () =>\n\t\tEntitySchemaHelper.getSchema(ActivityTask)\n\t);\n}\n"]}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,mBAAmB,CAAC,QAAQ,uBAA+B,GAAG,EAAE,CAC/D,kBAAkB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAChD,CAAC;IAEF,mBAAmB,CAAC,QAAQ,iBAAyB,GAAG,EAAE,CACzD,kBAAkB,CAAC,SAAS,CAAC,YAAY,CAAC,CAC1C,CAAC;IAEF,mBAAmB,CAAC,QAAQ,qBAA6B,GAAG,EAAE,CAC7D,kBAAkB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAC9C,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { EntitySchemaFactory, EntitySchemaHelper } from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { ActivityLogDetails } from \"./entities/activityLogDetails.js\";\nimport { ActivityTask } from \"./entities/activityTask.js\";\nimport { PushSubscription } from \"./entities/pushSubscription.js\";\n\n/**\n * Inits schemas.\n */\nexport function initSchema(): void {\n\tEntitySchemaFactory.register(nameof<ActivityLogDetails>(), () =>\n\t\tEntitySchemaHelper.getSchema(ActivityLogDetails)\n\t);\n\n\tEntitySchemaFactory.register(nameof<ActivityTask>(), () =>\n\t\tEntitySchemaHelper.getSchema(ActivityTask)\n\t);\n\n\tEntitySchemaFactory.register(nameof<PushSubscription>(), () =>\n\t\tEntitySchemaHelper.getSchema(PushSubscription)\n\t);\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { type IJsonLdContextDefinitionElement } from "@twin.org/data-json-ld";
2
2
  import { type IActivityLogEntry, type IActivityLogStatusNotification, type IDataAssetItemListResult, type IDataspaceDataPlaneComponent, type IEntitySet, type IFilteringQuery, type ITransferContext } from "@twin.org/dataspace-models";
3
- import type { IActivityStreamsActivity } from "@twin.org/standards-w3c-activity-streams";
3
+ import { type IActivityStreamsActivity } from "@twin.org/standards-w3c-activity-streams";
4
4
  import type { IDataspaceDataPlaneServiceConstructorOptions } from "./models/IDataspaceDataPlaneServiceConstructorOptions.js";
5
5
  /**
6
6
  * Dataspace Data Plane Service.
@@ -10,6 +10,10 @@ export declare class DataspaceDataPlaneService implements IDataspaceDataPlaneCom
10
10
  * Runtime name for the class.
11
11
  */
12
12
  static readonly CLASS_NAME: string;
13
+ /**
14
+ * Background task type identifier for push delivery tasks.
15
+ */
16
+ static readonly PUSH_DELIVERY_TASK_TYPE = "push-delivery";
13
17
  /**
14
18
  * Create a new instance of DataspaceDataPlane.
15
19
  * @param options The options for the data plane.
@@ -28,9 +32,10 @@ export declare class DataspaceDataPlaneService implements IDataspaceDataPlaneCom
28
32
  /**
29
33
  * Notify an Activity.
30
34
  * @param activity The Activity notified.
35
+ * @param trustPayload Optional trust payload to verify the requester's identity.
31
36
  * @returns The activity's id or entry.
32
37
  */
33
- notifyActivity(activity: IActivityStreamsActivity): Promise<string | IActivityLogEntry>;
38
+ notifyActivity(activity: IActivityStreamsActivity, trustPayload?: unknown): Promise<string | IActivityLogEntry>;
34
39
  /**
35
40
  * Subscribes to the activity log.
36
41
  * @param callback The callback to be called when Activity Log is called.
@@ -87,4 +92,34 @@ export declare class DataspaceDataPlaneService implements IDataspaceDataPlaneCom
87
92
  * @throws GeneralError if transfer is not in STARTED state.
88
93
  */
89
94
  validateTransfer(consumerPid: string, trustPayload: unknown): Promise<ITransferContext>;
95
+ /**
96
+ * Set up a push subscription after a transfer enters STARTED from REQUESTED.
97
+ * Reads the TransferProcess, builds an IFollowActivity, calls the app's
98
+ * subscribeToData, and persists a PushSubscription entity.
99
+ * @param consumerPid The consumer process ID identifying the transfer.
100
+ */
101
+ setupPushSubscription(consumerPid: string): Promise<void>;
102
+ /**
103
+ * Pause deliveries for a push subscription. The subscription entity stays
104
+ * alive with status=Paused. No app unsubscribe call.
105
+ * @param consumerPid The consumer process ID identifying the transfer.
106
+ */
107
+ suspendPushSubscription(consumerPid: string): Promise<void>;
108
+ /**
109
+ * Resume deliveries after a SUSPENDED → STARTED transition. Flips status
110
+ * back to Active. No app subscribeToData call.
111
+ * @param consumerPid The consumer process ID identifying the transfer.
112
+ */
113
+ resumePushSubscription(consumerPid: string): Promise<void>;
114
+ /**
115
+ * Tear down a push subscription. Builds an IUndoActivity, calls the app's
116
+ * unsubscribeToData, and deletes the PushSubscription entity.
117
+ * @param consumerPid The consumer process ID identifying the transfer.
118
+ */
119
+ teardownPushSubscription(consumerPid: string): Promise<void>;
120
+ /**
121
+ * Schedule a push delivery when the app has new outbound data.
122
+ * @param activity The outbound activity carrying the data payload.
123
+ */
124
+ processOutboxActivity(activity: IActivityStreamsActivity): Promise<void>;
90
125
  }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Persists a push subscription. One row per active push transfer.
3
+ * Primary key = consumerPid (same as TransferProcess).
4
+ */
5
+ export declare class PushSubscription {
6
+ consumerPid: string;
7
+ providerPid: string;
8
+ /**
9
+ * ID of the Follow activity that created this subscription.
10
+ * Used by Undo to reference it on teardown.
11
+ */
12
+ followActivityId: string;
13
+ datasetId: string;
14
+ /**
15
+ * The tenant that owns this subscription, captured from the request context at
16
+ * write time. Optional — single-tenant nodes (no `TWIN_TENANT_ENABLED`) register
17
+ * subscriptions without a tenant context. The encrypted tenant token is also baked
18
+ * into `consumerEndpoint` so cross-node push deliveries route to the right tenant.
19
+ */
20
+ tenantId?: string;
21
+ consumerEndpoint: string;
22
+ consumerAuthToken?: string;
23
+ /**
24
+ * When true deliveries are skipped (transfer SUSPENDED).
25
+ * When false deliveries are flowing normally.
26
+ */
27
+ paused: boolean;
28
+ dateCreated: string;
29
+ /**
30
+ * Last-modified timestamp. Updated on suspend/resume (when `paused` flips) and on
31
+ * any subscription mutation. Matches the codebase convention of pairing `dateCreated`
32
+ * with `dateModified` on entities whose state mutates.
33
+ */
34
+ dateModified: string;
35
+ }
@@ -3,6 +3,7 @@ export * from "./dataspaceDataPlaneSocketRoutes.js";
3
3
  export * from "./dataspaceDataPlaneService.js";
4
4
  export * from "./entities/activityLogDetails.js";
5
5
  export * from "./entities/activityTask.js";
6
+ export * from "./entities/pushSubscription.js";
6
7
  export * from "./models/IDataspaceDataPlaneServiceConfig.js";
7
8
  export * from "./models/IDataspaceDataPlaneServiceConstructorOptions.js";
8
9
  export * from "./restEntryPoints.js";
@@ -17,4 +17,25 @@ export interface IDataspaceDataPlaneServiceConfig {
17
17
  * @default undefined.
18
18
  */
19
19
  retryCount?: number;
20
+ /**
21
+ * Max HTTP retry attempts per push delivery task execution.
22
+ * @default 3
23
+ */
24
+ pushRetryCount?: number;
25
+ /**
26
+ * Base delay (ms) for exponential backoff between push HTTP retries.
27
+ * Effective delay = baseDelayMs * 2^attempt.
28
+ * @default 1000
29
+ */
30
+ pushRetryBaseDelayMs?: number;
31
+ /**
32
+ * Timeout (ms) for each push delivery HTTP POST request.
33
+ * @default 30000
34
+ */
35
+ pushTimeoutMs?: number;
36
+ /**
37
+ * Interval (ms) between orphaned PushSubscription cleanup scans.
38
+ * @default 3600000 (1 hour)
39
+ */
40
+ pushSubscriptionCleanupIntervalMs?: number;
20
41
  }
@@ -34,6 +34,11 @@ export interface IDataspaceDataPlaneServiceConstructorOptions {
34
34
  * @default transfer-process
35
35
  */
36
36
  transferProcessEntityStorageType?: string;
37
+ /**
38
+ * The entity storage type for PushSubscription entities.
39
+ * @default push-subscription
40
+ */
41
+ pushSubscriptionEntityStorageType?: string;
37
42
  /**
38
43
  * The entity storage type for Dataspace App Dataset entities.
39
44
  * @default dataspace-app-dataset
package/docs/changelog.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.30](https://github.com/iotaledger/twin-dataspace/compare/dataspace-data-plane-service-v0.0.3-next.29...dataspace-data-plane-service-v0.0.3-next.30) (2026-05-26)
4
+
5
+
6
+ ### Features
7
+
8
+ * implement DSP push transfer mode ([#109](https://github.com/iotaledger/twin-dataspace/issues/109)) ([71f5fee](https://github.com/iotaledger/twin-dataspace/commit/71f5feec1d92dfec8ed6899c951809818e1bf2a3))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/dataspace-app-runner bumped from 0.0.3-next.29 to 0.0.3-next.30
16
+ * @twin.org/dataspace-models bumped from 0.0.3-next.29 to 0.0.3-next.30
17
+ * devDependencies
18
+ * @twin.org/dataspace-test-app bumped from 0.0.3-next.29 to 0.0.3-next.30
19
+
20
+ ## [0.0.3-next.29](https://github.com/iotaledger/twin-dataspace/compare/dataspace-data-plane-service-v0.0.3-next.28...dataspace-data-plane-service-v0.0.3-next.29) (2026-05-20)
21
+
22
+
23
+ ### Features
24
+
25
+ * update dependencies ([55cb41c](https://github.com/iotaledger/twin-dataspace/commit/55cb41c1d0ce7ebddcce41c60fe944650bcf0499))
26
+
27
+
28
+ ### Dependencies
29
+
30
+ * The following workspace dependencies were updated
31
+ * dependencies
32
+ * @twin.org/dataspace-app-runner bumped from 0.0.3-next.28 to 0.0.3-next.29
33
+ * @twin.org/dataspace-models bumped from 0.0.3-next.28 to 0.0.3-next.29
34
+ * devDependencies
35
+ * @twin.org/dataspace-test-app bumped from 0.0.3-next.28 to 0.0.3-next.29
36
+
3
37
  ## [0.0.3-next.28](https://github.com/iotaledger/twin-dataspace/compare/dataspace-data-plane-service-v0.0.3-next.27...dataspace-data-plane-service-v0.0.3-next.28) (2026-05-12)
4
38
 
5
39
 
@@ -21,16 +21,22 @@
21
21
  }
22
22
  ],
23
23
  "paths": {
24
- "/dataspace-data-plane/notify": {
24
+ "/dataspace-data-plane/inbox": {
25
25
  "post": {
26
26
  "operationId": "activityStreamNotify",
27
27
  "summary": "Notify of a new Activity",
28
28
  "tags": [
29
29
  "Dataspace Data Plane"
30
30
  ],
31
- "security": [
31
+ "parameters": [
32
32
  {
33
- "jwtBearerAuthScheme": []
33
+ "name": "authorization",
34
+ "in": "header",
35
+ "required": true,
36
+ "schema": {
37
+ "type": "string"
38
+ },
39
+ "style": "simple"
34
40
  }
35
41
  ],
36
42
  "requestBody": {
@@ -93,24 +99,6 @@
93
99
  }
94
100
  }
95
101
  },
96
- "401": {
97
- "description": "You are not authorized to use the API or no credentials were supplied, see the content for more details.",
98
- "content": {
99
- "application/json": {
100
- "schema": {
101
- "$ref": "#/components/schemas/Error"
102
- },
103
- "examples": {
104
- "exampleResponse": {
105
- "value": {
106
- "name": "UnauthorizedError",
107
- "message": "errorMessage"
108
- }
109
- }
110
- }
111
- }
112
- }
113
- },
114
102
  "422": {
115
103
  "description": "The server cannot process the request, see the content for more details.",
116
104
  "content": {
@@ -34,6 +34,14 @@ The options for the data plane.
34
34
 
35
35
  Runtime name for the class.
36
36
 
37
+ ***
38
+
39
+ ### PUSH\_DELIVERY\_TASK\_TYPE {#push_delivery_task_type}
40
+
41
+ > `readonly` `static` **PUSH\_DELIVERY\_TASK\_TYPE**: `"push-delivery"` = `"push-delivery"`
42
+
43
+ Background task type identifier for push delivery tasks.
44
+
37
45
  ## Methods
38
46
 
39
47
  ### className() {#classname}
@@ -80,7 +88,7 @@ The node logging component type.
80
88
 
81
89
  ### notifyActivity() {#notifyactivity}
82
90
 
83
- > **notifyActivity**(`activity`): `Promise`\<`string` \| `IActivityLogEntry`\>
91
+ > **notifyActivity**(`activity`, `trustPayload?`): `Promise`\<`string` \| `IActivityLogEntry`\>
84
92
 
85
93
  Notify an Activity.
86
94
 
@@ -92,6 +100,12 @@ Notify an Activity.
92
100
 
93
101
  The Activity notified.
94
102
 
103
+ ##### trustPayload?
104
+
105
+ `unknown`
106
+
107
+ Optional trust payload to verify the requester's identity.
108
+
95
109
  #### Returns
96
110
 
97
111
  `Promise`\<`string` \| `IActivityLogEntry`\>
@@ -334,3 +348,128 @@ UnauthorizedError if trust verification fails.
334
348
  #### Throws
335
349
 
336
350
  GeneralError if transfer is not in STARTED state.
351
+
352
+ ***
353
+
354
+ ### setupPushSubscription() {#setuppushsubscription}
355
+
356
+ > **setupPushSubscription**(`consumerPid`): `Promise`\<`void`\>
357
+
358
+ Set up a push subscription after a transfer enters STARTED from REQUESTED.
359
+ Reads the TransferProcess, builds an IFollowActivity, calls the app's
360
+ subscribeToData, and persists a PushSubscription entity.
361
+
362
+ #### Parameters
363
+
364
+ ##### consumerPid
365
+
366
+ `string`
367
+
368
+ The consumer process ID identifying the transfer.
369
+
370
+ #### Returns
371
+
372
+ `Promise`\<`void`\>
373
+
374
+ #### Implementation of
375
+
376
+ `IDataspaceDataPlaneComponent.setupPushSubscription`
377
+
378
+ ***
379
+
380
+ ### suspendPushSubscription() {#suspendpushsubscription}
381
+
382
+ > **suspendPushSubscription**(`consumerPid`): `Promise`\<`void`\>
383
+
384
+ Pause deliveries for a push subscription. The subscription entity stays
385
+ alive with status=Paused. No app unsubscribe call.
386
+
387
+ #### Parameters
388
+
389
+ ##### consumerPid
390
+
391
+ `string`
392
+
393
+ The consumer process ID identifying the transfer.
394
+
395
+ #### Returns
396
+
397
+ `Promise`\<`void`\>
398
+
399
+ #### Implementation of
400
+
401
+ `IDataspaceDataPlaneComponent.suspendPushSubscription`
402
+
403
+ ***
404
+
405
+ ### resumePushSubscription() {#resumepushsubscription}
406
+
407
+ > **resumePushSubscription**(`consumerPid`): `Promise`\<`void`\>
408
+
409
+ Resume deliveries after a SUSPENDED → STARTED transition. Flips status
410
+ back to Active. No app subscribeToData call.
411
+
412
+ #### Parameters
413
+
414
+ ##### consumerPid
415
+
416
+ `string`
417
+
418
+ The consumer process ID identifying the transfer.
419
+
420
+ #### Returns
421
+
422
+ `Promise`\<`void`\>
423
+
424
+ #### Implementation of
425
+
426
+ `IDataspaceDataPlaneComponent.resumePushSubscription`
427
+
428
+ ***
429
+
430
+ ### teardownPushSubscription() {#teardownpushsubscription}
431
+
432
+ > **teardownPushSubscription**(`consumerPid`): `Promise`\<`void`\>
433
+
434
+ Tear down a push subscription. Builds an IUndoActivity, calls the app's
435
+ unsubscribeToData, and deletes the PushSubscription entity.
436
+
437
+ #### Parameters
438
+
439
+ ##### consumerPid
440
+
441
+ `string`
442
+
443
+ The consumer process ID identifying the transfer.
444
+
445
+ #### Returns
446
+
447
+ `Promise`\<`void`\>
448
+
449
+ #### Implementation of
450
+
451
+ `IDataspaceDataPlaneComponent.teardownPushSubscription`
452
+
453
+ ***
454
+
455
+ ### processOutboxActivity() {#processoutboxactivity}
456
+
457
+ > **processOutboxActivity**(`activity`): `Promise`\<`void`\>
458
+
459
+ Schedule a push delivery when the app has new outbound data.
460
+
461
+ #### Parameters
462
+
463
+ ##### activity
464
+
465
+ `IActivityStreamsActivity`
466
+
467
+ The outbound activity carrying the data payload.
468
+
469
+ #### Returns
470
+
471
+ `Promise`\<`void`\>
472
+
473
+ #### Implementation of
474
+
475
+ `IDataspaceDataPlaneComponent.processOutboxActivity`
@@ -0,0 +1,89 @@
1
+ # Class: PushSubscription
2
+
3
+ Persists a push subscription. One row per active push transfer.
4
+ Primary key = consumerPid (same as TransferProcess).
5
+
6
+ ## Constructors
7
+
8
+ ### Constructor
9
+
10
+ > **new PushSubscription**(): `PushSubscription`
11
+
12
+ #### Returns
13
+
14
+ `PushSubscription`
15
+
16
+ ## Properties
17
+
18
+ ### consumerPid {#consumerpid}
19
+
20
+ > **consumerPid**: `string`
21
+
22
+ ***
23
+
24
+ ### providerPid {#providerpid}
25
+
26
+ > **providerPid**: `string`
27
+
28
+ ***
29
+
30
+ ### followActivityId {#followactivityid}
31
+
32
+ > **followActivityId**: `string`
33
+
34
+ ID of the Follow activity that created this subscription.
35
+ Used by Undo to reference it on teardown.
36
+
37
+ ***
38
+
39
+ ### datasetId {#datasetid}
40
+
41
+ > **datasetId**: `string`
42
+
43
+ ***
44
+
45
+ ### tenantId? {#tenantid}
46
+
47
+ > `optional` **tenantId?**: `string`
48
+
49
+ The tenant that owns this subscription, captured from the request context at
50
+ write time. Optional — single-tenant nodes (no `TWIN_TENANT_ENABLED`) register
51
+ subscriptions without a tenant context. The encrypted tenant token is also baked
52
+ into `consumerEndpoint` so cross-node push deliveries route to the right tenant.
53
+
54
+ ***
55
+
56
+ ### consumerEndpoint {#consumerendpoint}
57
+
58
+ > **consumerEndpoint**: `string`
59
+
60
+ ***
61
+
62
+ ### consumerAuthToken? {#consumerauthtoken}
63
+
64
+ > `optional` **consumerAuthToken?**: `string`
65
+
66
+ ***
67
+
68
+ ### paused {#paused}
69
+
70
+ > **paused**: `boolean`
71
+
72
+ When true deliveries are skipped (transfer SUSPENDED).
73
+ When false deliveries are flowing normally.
74
+
75
+ ***
76
+
77
+ ### dateCreated {#datecreated}
78
+
79
+ > **dateCreated**: `string`
80
+
81
+ ***
82
+
83
+ ### dateModified {#datemodified}
84
+
85
+ > **dateModified**: `string`
86
+
87
+ Last-modified timestamp. Updated on suspend/resume (when `paused` flips) and on
88
+ any subscription mutation. Matches the codebase convention of pairing `dateCreated`
89
+ with `dateModified` on entities whose state mutates.
@@ -5,6 +5,7 @@
5
5
  - [DataspaceDataPlaneService](classes/DataspaceDataPlaneService.md)
6
6
  - [ActivityLogDetails](classes/ActivityLogDetails.md)
7
7
  - [ActivityTask](classes/ActivityTask.md)
8
+ - [PushSubscription](classes/PushSubscription.md)
8
9
 
9
10
  ## Interfaces
10
11