@twin.org/dataspace-control-plane-service 0.0.3-next.15
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/LICENSE +201 -0
- package/README.md +119 -0
- package/dist/es/dataspaceControlPlanePolicyRequester.js +228 -0
- package/dist/es/dataspaceControlPlanePolicyRequester.js.map +1 -0
- package/dist/es/dataspaceControlPlaneRoutes.js +202 -0
- package/dist/es/dataspaceControlPlaneRoutes.js.map +1 -0
- package/dist/es/dataspaceControlPlaneService.js +1420 -0
- package/dist/es/dataspaceControlPlaneService.js.map +1 -0
- package/dist/es/index.js +11 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IDataspaceControlPlaneServiceConfig.js +4 -0
- package/dist/es/models/IDataspaceControlPlaneServiceConfig.js.map +1 -0
- package/dist/es/models/IDataspaceControlPlaneServiceConstructorOptions.js +2 -0
- package/dist/es/models/IDataspaceControlPlaneServiceConstructorOptions.js.map +1 -0
- package/dist/es/models/INegotiationState.js +4 -0
- package/dist/es/models/INegotiationState.js.map +1 -0
- package/dist/es/restEntryPoints.js +15 -0
- package/dist/es/restEntryPoints.js.map +1 -0
- package/dist/es/schema.js +11 -0
- package/dist/es/schema.js.map +1 -0
- package/dist/es/utils/dataHelpers.js +22 -0
- package/dist/es/utils/dataHelpers.js.map +1 -0
- package/dist/es/utils/transferErrorUtils.js +78 -0
- package/dist/es/utils/transferErrorUtils.js.map +1 -0
- package/dist/types/dataspaceControlPlanePolicyRequester.d.ts +80 -0
- package/dist/types/dataspaceControlPlaneRoutes.d.ts +17 -0
- package/dist/types/dataspaceControlPlaneService.d.ts +153 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/models/IDataspaceControlPlaneServiceConfig.d.ts +20 -0
- package/dist/types/models/IDataspaceControlPlaneServiceConstructorOptions.d.ts +69 -0
- package/dist/types/models/INegotiationState.d.ts +27 -0
- package/dist/types/restEntryPoints.d.ts +7 -0
- package/dist/types/schema.d.ts +4 -0
- package/dist/types/utils/dataHelpers.d.ts +1 -0
- package/dist/types/utils/transferErrorUtils.d.ts +39 -0
- package/docs/API.md +341 -0
- package/docs/changelog.md +31 -0
- package/docs/examples.md +1 -0
- package/docs/reference/classes/DataspaceControlPlanePolicyRequester.md +244 -0
- package/docs/reference/classes/DataspaceControlPlaneService.md +549 -0
- package/docs/reference/functions/generateRestRoutesDataspaceControlPlane.md +29 -0
- package/docs/reference/functions/initSchema.md +9 -0
- package/docs/reference/index.md +22 -0
- package/docs/reference/interfaces/IDataspaceControlPlaneServiceConfig.md +26 -0
- package/docs/reference/interfaces/IDataspaceControlPlaneServiceConstructorOptions.md +160 -0
- package/docs/reference/interfaces/INegotiationState.md +43 -0
- package/docs/reference/variables/restEntryPoints.md +7 -0
- package/docs/reference/variables/tagsDataspaceControlPlane.md +5 -0
- package/locales/en.json +93 -0
- package/package.json +70 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Interface: IDataspaceControlPlaneServiceConstructorOptions
|
|
2
|
+
|
|
3
|
+
Dataspace Control Plane service constructor options.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
### policyAdministrationPointComponentType?
|
|
8
|
+
|
|
9
|
+
> `optional` **policyAdministrationPointComponentType**: `string`
|
|
10
|
+
|
|
11
|
+
Policy Administration Point component type.
|
|
12
|
+
Used for Agreement lookup and validation during Transfer Process initiation.
|
|
13
|
+
|
|
14
|
+
#### Default
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
policy-administration-point
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
***
|
|
21
|
+
|
|
22
|
+
### policyNegotiationPointComponentType?
|
|
23
|
+
|
|
24
|
+
> `optional` **policyNegotiationPointComponentType**: `string`
|
|
25
|
+
|
|
26
|
+
Policy Negotiation Point component type.
|
|
27
|
+
Used for contract negotiation to create agreements before transfer processes.
|
|
28
|
+
|
|
29
|
+
#### Default
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
policy-negotiation-point
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
***
|
|
36
|
+
|
|
37
|
+
### policyNegotiationAdminPointComponentType?
|
|
38
|
+
|
|
39
|
+
> `optional` **policyNegotiationAdminPointComponentType**: `string`
|
|
40
|
+
|
|
41
|
+
Policy Negotiation Admin Point component type.
|
|
42
|
+
Used for querying negotiation history.
|
|
43
|
+
Optional - if not provided, negotiation history will not be available.
|
|
44
|
+
|
|
45
|
+
#### Default
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
policy-negotiation-admin-point
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
***
|
|
52
|
+
|
|
53
|
+
### federatedCatalogueComponentType?
|
|
54
|
+
|
|
55
|
+
> `optional` **federatedCatalogueComponentType**: `string`
|
|
56
|
+
|
|
57
|
+
Federated Catalogue component type.
|
|
58
|
+
Used for dataset validation during Transfer Process initiation.
|
|
59
|
+
Validates that Agreements reference valid catalog datasets.
|
|
60
|
+
|
|
61
|
+
#### Default
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
federated-catalogue
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
***
|
|
68
|
+
|
|
69
|
+
### loggingComponentType?
|
|
70
|
+
|
|
71
|
+
> `optional` **loggingComponentType**: `string`
|
|
72
|
+
|
|
73
|
+
Logging component type.
|
|
74
|
+
|
|
75
|
+
#### Default
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
logging
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
***
|
|
82
|
+
|
|
83
|
+
### identityComponentType?
|
|
84
|
+
|
|
85
|
+
> `optional` **identityComponentType**: `string`
|
|
86
|
+
|
|
87
|
+
Identity component type (for token signing/verification).
|
|
88
|
+
|
|
89
|
+
#### Default
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
identity
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
***
|
|
96
|
+
|
|
97
|
+
### identityAuthenticationComponentType?
|
|
98
|
+
|
|
99
|
+
> `optional` **identityAuthenticationComponentType**: `string`
|
|
100
|
+
|
|
101
|
+
Identity Authentication component type (for token validation).
|
|
102
|
+
|
|
103
|
+
#### Default
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
identity-authentication
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
***
|
|
110
|
+
|
|
111
|
+
### trustComponentType?
|
|
112
|
+
|
|
113
|
+
> `optional` **trustComponentType**: `string`
|
|
114
|
+
|
|
115
|
+
Trust component type for trust verification.
|
|
116
|
+
Used to verify JWT/VC tokens and extract identity information.
|
|
117
|
+
|
|
118
|
+
#### Default
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
trust
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
***
|
|
125
|
+
|
|
126
|
+
### transferProcessEntityStorageType?
|
|
127
|
+
|
|
128
|
+
> `optional` **transferProcessEntityStorageType**: `string`
|
|
129
|
+
|
|
130
|
+
Entity storage type for Transfer Process entities.
|
|
131
|
+
Used to persist transfer state for the consumerPid flow.
|
|
132
|
+
Must match the Data Plane's transferProcessEntityStorageType for shared storage.
|
|
133
|
+
|
|
134
|
+
#### Default
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
transfer-process
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
***
|
|
141
|
+
|
|
142
|
+
### taskSchedulerComponentType?
|
|
143
|
+
|
|
144
|
+
> `optional` **taskSchedulerComponentType**: `string`
|
|
145
|
+
|
|
146
|
+
Task scheduler component type for periodic cleanup of stalled negotiations.
|
|
147
|
+
|
|
148
|
+
#### Default
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
task-scheduler
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
***
|
|
155
|
+
|
|
156
|
+
### config?
|
|
157
|
+
|
|
158
|
+
> `optional` **config**: [`IDataspaceControlPlaneServiceConfig`](IDataspaceControlPlaneServiceConfig.md)
|
|
159
|
+
|
|
160
|
+
The configuration of the Dataspace Control Plane Service.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Interface: INegotiationState
|
|
2
|
+
|
|
3
|
+
Negotiation state tracked internally for callback routing.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
### negotiationId
|
|
8
|
+
|
|
9
|
+
> **negotiationId**: `string`
|
|
10
|
+
|
|
11
|
+
The negotiation ID (self-reference for lookup).
|
|
12
|
+
|
|
13
|
+
***
|
|
14
|
+
|
|
15
|
+
### state
|
|
16
|
+
|
|
17
|
+
> **state**: `DataspaceProtocolContractNegotiationStateType`
|
|
18
|
+
|
|
19
|
+
Current negotiation state.
|
|
20
|
+
|
|
21
|
+
***
|
|
22
|
+
|
|
23
|
+
### agreement?
|
|
24
|
+
|
|
25
|
+
> `optional` **agreement**: `IOdrlAgreement`
|
|
26
|
+
|
|
27
|
+
Agreement received from provider (stored until finalized).
|
|
28
|
+
|
|
29
|
+
***
|
|
30
|
+
|
|
31
|
+
### startedAt
|
|
32
|
+
|
|
33
|
+
> **startedAt**: `number`
|
|
34
|
+
|
|
35
|
+
Timestamp when negotiation started.
|
|
36
|
+
|
|
37
|
+
***
|
|
38
|
+
|
|
39
|
+
### updatedAt
|
|
40
|
+
|
|
41
|
+
> **updatedAt**: `number`
|
|
42
|
+
|
|
43
|
+
Timestamp when negotiation state was last updated.
|
package/locales/en.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"info": {
|
|
3
|
+
"dataspaceControlPlaneService": {
|
|
4
|
+
"transferProcessInitiated": "Transfer Process initiated",
|
|
5
|
+
"transferProcessQueried": "Transfer Process queried (role: {role})",
|
|
6
|
+
"transferProcessStarted": "Transfer Process started",
|
|
7
|
+
"dataAccessTokenGenerated": "Data access token generated for PULL transfer",
|
|
8
|
+
"transferProcessCompleted": "Transfer Process completed",
|
|
9
|
+
"transferProcessSuspended": "Transfer Process suspended",
|
|
10
|
+
"transferProcessTerminated": "Transfer Process terminated",
|
|
11
|
+
"resolvedConsumerPid": "Resolved consumerPid to Transfer Context",
|
|
12
|
+
"resolvedProviderPid": "Resolved providerPid to Transfer Context",
|
|
13
|
+
"catalogDatasetFound": "Dataset validated in Federated Catalogue",
|
|
14
|
+
"agreementMatchedOffer": "Agreement matched Catalog Offer",
|
|
15
|
+
"populatingFederatedCatalogue": "Populating Federated Catalogue with datasets from registered apps",
|
|
16
|
+
"federatedCataloguePopulated": "Federated Catalogue population completed (registered: {registeredCount}, errors: {errorCount}, apps: {totalApps})",
|
|
17
|
+
"startingContractNegotiation": "Starting contract negotiation with provider",
|
|
18
|
+
"offerFoundInCatalog": "Offer found in Federated Catalogue and validated",
|
|
19
|
+
"negotiationInitiated": "Contract negotiation initiated successfully",
|
|
20
|
+
"getNegotiation": "Retrieving negotiation status",
|
|
21
|
+
"negotiationStateRetrieved": "Negotiation state retrieved successfully",
|
|
22
|
+
"getNegotiationHistory": "Retrieving negotiation history",
|
|
23
|
+
"negotiationHistoryRetrieved": "Negotiation history retrieved successfully",
|
|
24
|
+
"stalledNegotiationsCleanupComplete": "Stalled negotiations cleanup completed (cleanedUp: {cleanedUp})"
|
|
25
|
+
},
|
|
26
|
+
"dataspaceControlPlanePolicyRequester": {
|
|
27
|
+
"offerReceived": "Offer received from provider (negotiationId: {negotiationId}, offerId: {offerId})",
|
|
28
|
+
"agreementReceived": "Agreement received from provider (negotiationId: {negotiationId}, agreementId: {agreementId})",
|
|
29
|
+
"negotiationFinalized": "Negotiation finalized by provider (negotiationId: {negotiationId})",
|
|
30
|
+
"negotiationCompleted": "Negotiation completed successfully (negotiationId: {negotiationId}, agreementId: {agreementId}, duration: {durationMs}ms)",
|
|
31
|
+
"negotiationRejected": "Negotiation was rejected/terminated (negotiationId: {negotiationId}, duration: {durationMs}ms)"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"debug": {
|
|
35
|
+
"dataspaceControlPlaneService": {
|
|
36
|
+
"engineCloneStart": "Skipping Federated Catalogue population (engine clone or no engine)",
|
|
37
|
+
"discoveredApps": "Discovered {count} registered Dataspace apps",
|
|
38
|
+
"datasetRegistered": "Dataset {datasetId} registered from app {appName}"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"warn": {
|
|
42
|
+
"dataspaceControlPlaneService": {
|
|
43
|
+
"catalogDatasetHasNoOffers": "Dataset has no Offers (odrl:hasPolicy) in Federated Catalogue",
|
|
44
|
+
"pushTransferModeNotImplemented": "PUSH transfer mode requested but not implemented. Consumer provided dataAddress endpoint but data push is not yet supported.",
|
|
45
|
+
"stalledNegotiationCleanedUp": "Stalled negotiation cleaned up (negotiationId: {negotiationId})"
|
|
46
|
+
},
|
|
47
|
+
"dataspaceControlPlanePolicyRequester": {
|
|
48
|
+
"unknownNegotiationFinalized": "Unknown negotiation finalized (negotiationId: {negotiationId})",
|
|
49
|
+
"negotiationTerminated": "Negotiation terminated by provider (negotiationId: {negotiationId})",
|
|
50
|
+
"unknownNegotiationTerminated": "Unknown negotiation terminated (negotiationId: {negotiationId})"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"error": {
|
|
54
|
+
"dataspaceControlPlaneService": {
|
|
55
|
+
"transferProcessNotFound": "Transfer Process not found",
|
|
56
|
+
"pullTransfersNotSupported": "PULL transfers are not supported. Configure dataPlanePath in service configuration to enable PULL transfers.",
|
|
57
|
+
"datasetRegistrationFailed": "Failed to register dataset {datasetId} from app {appName}",
|
|
58
|
+
"appDatasetsRetrievalFailed": "Failed to retrieve datasets from app {appName}",
|
|
59
|
+
"transferProcessTerminated": "Transfer Process \"{consumerPid}\" is terminated and cannot be used",
|
|
60
|
+
"transferProcessTerminatedProvider": "Transfer Process \"{providerPid}\" is terminated and cannot be used",
|
|
61
|
+
"invalidTransferRequest": "Transfer Request does not conform to Dataspace Protocol specification",
|
|
62
|
+
"invalidStateForStart": "Transfer Process cannot be started: current state is \"{currentState}\", expected REQUESTED or SUSPENDED",
|
|
63
|
+
"invalidStateForComplete": "Transfer Process cannot be completed: current state is \"{currentState}\", expected STARTED",
|
|
64
|
+
"invalidStateForSuspend": "Transfer Process cannot be suspended: current state is \"{currentState}\", expected STARTED",
|
|
65
|
+
"invalidTransferStartMessage": "Transfer Start Message does not conform to Dataspace Protocol specification",
|
|
66
|
+
"invalidTransferCompletionMessage": "Transfer Completion Message does not conform to Dataspace Protocol specification",
|
|
67
|
+
"invalidTransferSuspensionMessage": "Transfer Suspension Message does not conform to Dataspace Protocol specification",
|
|
68
|
+
"invalidTransferTerminationMessage": "Transfer Termination Message does not conform to Dataspace Protocol specification",
|
|
69
|
+
"agreementLookupFailed": "Failed to lookup Agreement: {agreementId}",
|
|
70
|
+
"agreementNotFound": "Agreement not found",
|
|
71
|
+
"agreementMissingTarget": "Agreement is missing target (dataset): {agreementId}",
|
|
72
|
+
"agreementMultipleTargetsNotSupported": "Agreement has multiple targets which is not supported. Only single target Agreements are allowed: {agreementId}, target count: {targetCount}",
|
|
73
|
+
"agreementTargetMissingUid": "Agreement target object is missing required \"uid\" property: {agreementId}",
|
|
74
|
+
"datasetNotInCatalog": "Dataset \"{datasetId}\" not found in Federated Catalogue (Agreement: {agreementId})",
|
|
75
|
+
"catalogLookupFailed": "Failed to lookup dataset in Federated Catalogue: {datasetId} (Agreement: {agreementId})",
|
|
76
|
+
"agreementNotMatchingOffer": "Agreement \"{agreementId}\" does not match any Catalog Offer for dataset {datasetId}. Available Offers: {availableOffers}",
|
|
77
|
+
"organizationContextMissing": "Organization context is missing. Cannot verify Agreement authorization for consumerPid: {consumerPid}",
|
|
78
|
+
"organizationContextMissingProvider": "Organization context is missing. Cannot verify Agreement authorization for providerPid: {providerPid}",
|
|
79
|
+
"agreementAssignerMismatch": "Agreement assigner does not match current organization. Agreement: {agreementId}, consumerPid: {consumerPid}, expected: {expectedOrgId}, actual: {actualAssigner}",
|
|
80
|
+
"agreementAssignerMismatchProvider": "Agreement assigner does not match current organization. Agreement: {agreementId}, providerPid: {providerPid}, expected: {expectedOrgId}, actual: {actualAssigner}",
|
|
81
|
+
"agreementAssigneeMismatch": "Agreement assignee does not match expected consumer identity. Agreement: {agreementId}, providerPid: {providerPid}, expected: {expectedConsumerIdentity}, actual: {actualAssignee}",
|
|
82
|
+
"negotiationInitiationFailed": "Failed to initiate contract negotiation",
|
|
83
|
+
"datasetNotFoundInCatalog": "Dataset/Offer \"{offerId}\" not found in Federated Catalogue. Cannot initiate negotiation for non-existent offer.",
|
|
84
|
+
"catalogLookupFailedForNegotiation": "Failed to lookup dataset/offer in Federated Catalogue before negotiation: {offerId}",
|
|
85
|
+
"datasetHasNoOffers": "Dataset \"{datasetId}\" has no ODRL offers (odrl:hasPolicy). Cannot negotiate without an offer.",
|
|
86
|
+
"datasetHasNoValidOffers": "Dataset \"{datasetId}\" has no valid ODRL offer objects. Cannot negotiate without a valid offer.",
|
|
87
|
+
"offerNotFoundInDataset": "Offer \"{offerId}\" not found in dataset \"{datasetId}\". Available offers: {availableOffers}",
|
|
88
|
+
"pnapNotConfigured": "Policy Negotiation Admin Point not configured. Cannot retrieve negotiation history without PNAP.",
|
|
89
|
+
"negotiationCallbackError": "Negotiation callback \"{key}\" threw an error during {method} for negotiation {negotiationId}"
|
|
90
|
+
},
|
|
91
|
+
"dataspaceControlPlanePolicyRequester": {}
|
|
92
|
+
}
|
|
93
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@twin.org/dataspace-control-plane-service",
|
|
3
|
+
"version": "0.0.3-next.15",
|
|
4
|
+
"description": "Dataspace Control Plane service implementation for Eclipse Dataspace Protocol Transfer Process Protocol",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/twinfoundation/dataspace.git",
|
|
8
|
+
"directory": "packages/dataspace-control-plane-service"
|
|
9
|
+
},
|
|
10
|
+
"author": "martyn.janes@iota.org",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=20.0.0"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@twin.org/api-models": "next",
|
|
18
|
+
"@twin.org/context": "next",
|
|
19
|
+
"@twin.org/core": "next",
|
|
20
|
+
"@twin.org/dataspace-models": "0.0.3-next.15",
|
|
21
|
+
"@twin.org/entity": "next",
|
|
22
|
+
"@twin.org/entity-storage-models": "next",
|
|
23
|
+
"@twin.org/federated-catalogue-models": "next",
|
|
24
|
+
"@twin.org/logging-models": "next",
|
|
25
|
+
"@twin.org/nameof": "next",
|
|
26
|
+
"@twin.org/rights-management-models": "next",
|
|
27
|
+
"@twin.org/standards-dataspace-protocol": "next",
|
|
28
|
+
"@twin.org/standards-w3c-odrl": "next",
|
|
29
|
+
"@twin.org/trust-models": "next"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/es/index.js",
|
|
32
|
+
"types": "./dist/types/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/types/index.d.ts",
|
|
36
|
+
"import": "./dist/es/index.js",
|
|
37
|
+
"default": "./dist/es/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./locales/*.json": "./locales/*.json"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist/es",
|
|
43
|
+
"dist/types",
|
|
44
|
+
"locales",
|
|
45
|
+
"docs"
|
|
46
|
+
],
|
|
47
|
+
"keywords": [
|
|
48
|
+
"twin",
|
|
49
|
+
"trade",
|
|
50
|
+
"iota",
|
|
51
|
+
"framework",
|
|
52
|
+
"blockchain",
|
|
53
|
+
"data",
|
|
54
|
+
"space",
|
|
55
|
+
"control",
|
|
56
|
+
"plane",
|
|
57
|
+
"service",
|
|
58
|
+
"dataspace",
|
|
59
|
+
"protocol",
|
|
60
|
+
"dsp",
|
|
61
|
+
"transfer",
|
|
62
|
+
"process",
|
|
63
|
+
"microservice",
|
|
64
|
+
"business-logic"
|
|
65
|
+
],
|
|
66
|
+
"bugs": {
|
|
67
|
+
"url": "git+https://github.com/twinfoundation/dataspace/issues"
|
|
68
|
+
},
|
|
69
|
+
"homepage": "https://twindev.org"
|
|
70
|
+
}
|