@twin.org/rights-management-service 0.0.1-next.3

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,420 @@
1
+ import { HttpParameterHelper } from '@twin.org/api-models';
2
+ import { Guards, ComponentFactory, Coerce, GeneralError, Is } from '@twin.org/core';
3
+ import { HttpStatusCode, HeaderTypes } from '@twin.org/web';
4
+ import { PolicyAdministrationPointComponentEntityStorage } from '@twin.org/rights-management-pap-entity-storage';
5
+
6
+ // Copyright 2024 IOTA Stiftung.
7
+ // SPDX-License-Identifier: Apache-2.0.
8
+ /**
9
+ * The source used when communicating about these routes.
10
+ */
11
+ const ROUTES_SOURCE = "rightsManagementRoutes";
12
+ /**
13
+ * The tag to associate with the routes.
14
+ */
15
+ const tags = [
16
+ {
17
+ name: "Policy Administration Point",
18
+ description: "Endpoints for managing ODRL policies in the Policy Administration Point"
19
+ }
20
+ ];
21
+ /**
22
+ * The REST routes for the Rights Management.
23
+ * @param baseRouteName Prefix to prepend to the paths.
24
+ * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
25
+ * @returns The generated routes.
26
+ */
27
+ function generateRestRoutes(baseRouteName, componentName) {
28
+ const storeRoute = {
29
+ operationId: "papStore",
30
+ summary: "Store a policy",
31
+ tag: tags[0].name,
32
+ method: "POST",
33
+ path: `${baseRouteName}/pap/`,
34
+ handler: async (httpRequestContext, request) => papStore(httpRequestContext, componentName, request),
35
+ requestType: {
36
+ type: "IPapStoreRequest",
37
+ examples: [
38
+ {
39
+ id: "papStoreExample",
40
+ request: {
41
+ body: {
42
+ policy: {
43
+ "@context": "https://www.w3.org/ns/odrl.jsonld",
44
+ "@type": "Set",
45
+ uid: "http://example.com/policy/1",
46
+ permission: [
47
+ {
48
+ target: "http://example.com/asset/1",
49
+ action: "use"
50
+ }
51
+ ]
52
+ }
53
+ }
54
+ }
55
+ }
56
+ ]
57
+ },
58
+ responseType: [
59
+ {
60
+ type: "ICreatedResponse",
61
+ examples: [
62
+ {
63
+ id: "papStoreResponseExample",
64
+ response: {
65
+ statusCode: HttpStatusCode.created,
66
+ headers: {
67
+ [HeaderTypes.Location]: "http://example.com/policy/1"
68
+ }
69
+ }
70
+ }
71
+ ]
72
+ }
73
+ ]
74
+ };
75
+ const retrieveRoute = {
76
+ operationId: "papRetrieve",
77
+ summary: "Retrieve a policy",
78
+ tag: tags[0].name,
79
+ method: "GET",
80
+ path: `${baseRouteName}/pap/:id`,
81
+ handler: async (httpRequestContext, request) => papRetrieve(httpRequestContext, componentName, request),
82
+ requestType: {
83
+ type: "IPapRetrieveRequest",
84
+ examples: [
85
+ {
86
+ id: "papRetrieveExample",
87
+ request: {
88
+ pathParams: {
89
+ id: "http://example.com/policy/1"
90
+ }
91
+ }
92
+ }
93
+ ]
94
+ },
95
+ responseType: [
96
+ {
97
+ type: "IPapRetrieveResponse",
98
+ examples: [
99
+ {
100
+ id: "papRetrieveResponseExample",
101
+ response: {
102
+ body: {
103
+ "@context": "https://www.w3.org/ns/odrl.jsonld",
104
+ "@type": "Set",
105
+ uid: "http://example.com/policy/1",
106
+ permission: [
107
+ {
108
+ target: "http://example.com/asset/1",
109
+ action: "use"
110
+ }
111
+ ]
112
+ }
113
+ }
114
+ }
115
+ ]
116
+ }
117
+ ]
118
+ };
119
+ const removeRoute = {
120
+ operationId: "papRemove",
121
+ summary: "Remove a policy",
122
+ tag: tags[0].name,
123
+ method: "DELETE",
124
+ path: `${baseRouteName}/pap/:id`,
125
+ handler: async (httpRequestContext, request) => papRemove(httpRequestContext, componentName, request),
126
+ requestType: {
127
+ type: "IPapRemoveRequest",
128
+ examples: [
129
+ {
130
+ id: "papRemoveExample",
131
+ request: {
132
+ pathParams: {
133
+ id: "http://example.com/policy/1"
134
+ }
135
+ }
136
+ }
137
+ ]
138
+ },
139
+ responseType: [
140
+ {
141
+ type: "INoContentResponse"
142
+ }
143
+ ]
144
+ };
145
+ const queryRoute = {
146
+ operationId: "papQuery",
147
+ summary: "Query policies",
148
+ tag: tags[0].name,
149
+ method: "POST",
150
+ path: `${baseRouteName}/pap/query`,
151
+ handler: async (httpRequestContext, request) => papQuery(httpRequestContext, componentName, request),
152
+ requestType: {
153
+ type: "IPapQueryRequest",
154
+ examples: [
155
+ {
156
+ id: "papQueryExample",
157
+ request: {
158
+ query: {
159
+ cursor: "optional-pagination-cursor"
160
+ }
161
+ }
162
+ }
163
+ ]
164
+ },
165
+ responseType: [
166
+ {
167
+ type: "IPapQueryResponse",
168
+ examples: [
169
+ {
170
+ id: "papQueryResponseExample",
171
+ response: {
172
+ body: {
173
+ cursor: "next-page-cursor",
174
+ policies: [
175
+ {
176
+ "@context": "https://www.w3.org/ns/odrl.jsonld",
177
+ "@type": "Set",
178
+ uid: "http://example.com/policy/1",
179
+ permission: [
180
+ {
181
+ target: "http://example.com/asset/1",
182
+ action: "use"
183
+ }
184
+ ]
185
+ }
186
+ ]
187
+ }
188
+ }
189
+ }
190
+ ]
191
+ }
192
+ ]
193
+ };
194
+ return [storeRoute, retrieveRoute, removeRoute, queryRoute];
195
+ }
196
+ /**
197
+ * PAP: Store a policy.
198
+ * @param httpRequestContext The request context for the API.
199
+ * @param componentName The name of the component to use in the routes.
200
+ * @param request The request.
201
+ * @returns The response object with additional http response properties.
202
+ */
203
+ async function papStore(httpRequestContext, componentName, request) {
204
+ Guards.object(ROUTES_SOURCE, "request", request);
205
+ Guards.object(ROUTES_SOURCE, "request.body", request.body);
206
+ Guards.object(ROUTES_SOURCE, "request.body.policy", request.body.policy);
207
+ Guards.stringValue(ROUTES_SOURCE, "httpRequestContext.nodeIdentity", httpRequestContext.nodeIdentity);
208
+ const component = ComponentFactory.get(componentName);
209
+ const policy = request.body.policy;
210
+ await component.papStore(policy, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
211
+ return {
212
+ statusCode: HttpStatusCode.created,
213
+ headers: {
214
+ [HeaderTypes.Location]: policy.uid ?? ""
215
+ }
216
+ };
217
+ }
218
+ /**
219
+ * PAP: Retrieve a policy.
220
+ * @param httpRequestContext The request context for the API.
221
+ * @param componentName The name of the component to use in the routes.
222
+ * @param request The request.
223
+ * @returns The response object with additional http response properties.
224
+ */
225
+ async function papRetrieve(httpRequestContext, componentName, request) {
226
+ Guards.object(ROUTES_SOURCE, "request", request);
227
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
228
+ Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
229
+ Guards.stringValue(ROUTES_SOURCE, "httpRequestContext.nodeIdentity", httpRequestContext.nodeIdentity);
230
+ const component = ComponentFactory.get(componentName);
231
+ const policy = await component.papRetrieve(request.pathParams.id, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
232
+ return {
233
+ body: policy
234
+ };
235
+ }
236
+ /**
237
+ * PAP: Remove a policy.
238
+ * @param httpRequestContext The request context for the API.
239
+ * @param componentName The name of the component to use in the routes.
240
+ * @param request The request.
241
+ * @returns The response object with additional http response properties.
242
+ */
243
+ async function papRemove(httpRequestContext, componentName, request) {
244
+ Guards.object(ROUTES_SOURCE, "request", request);
245
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
246
+ Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
247
+ Guards.stringValue(ROUTES_SOURCE, "httpRequestContext.nodeIdentity", httpRequestContext.nodeIdentity);
248
+ const component = ComponentFactory.get(componentName);
249
+ await component.papRemove(request.pathParams.id, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
250
+ return {
251
+ statusCode: HttpStatusCode.noContent
252
+ };
253
+ }
254
+ /**
255
+ * PAP: Query policies.
256
+ * @param httpRequestContext The request context for the API.
257
+ * @param componentName The name of the component to use in the routes.
258
+ * @param request The request.
259
+ * @returns The response object with additional http response properties.
260
+ */
261
+ async function papQuery(httpRequestContext, componentName, request) {
262
+ Guards.object(ROUTES_SOURCE, "request", request);
263
+ Guards.stringValue(ROUTES_SOURCE, "httpRequestContext.nodeIdentity", httpRequestContext.nodeIdentity);
264
+ const queryParams = request.query || {};
265
+ const cursor = queryParams.cursor;
266
+ const pageSize = Coerce.number(queryParams.pageSize);
267
+ const component = ComponentFactory.get(componentName);
268
+ const result = await component.papQuery(HttpParameterHelper.objectFromString(request.query?.conditions), cursor, pageSize, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
269
+ return {
270
+ body: {
271
+ cursor: result.cursor,
272
+ policies: result.policies
273
+ }
274
+ };
275
+ }
276
+
277
+ // Copyright 2024 IOTA Stiftung.
278
+ // SPDX-License-Identifier: Apache-2.0.
279
+ /**
280
+ * Service for performing Rights Management operations.
281
+ * This is a unified service that provides access to all Rights Management components.
282
+ */
283
+ class RightsManagementService {
284
+ /**
285
+ * The namespace supported by the Rights Management service.
286
+ */
287
+ static NAMESPACE = "rights-management";
288
+ /**
289
+ * Runtime name for the class.
290
+ */
291
+ CLASS_NAME = "RightsManagementService";
292
+ /**
293
+ * The PAP component implementation.
294
+ * @internal
295
+ */
296
+ _papComponent;
297
+ /**
298
+ * Create a new instance of RightsManagementService.
299
+ * @param options The options for the service.
300
+ */
301
+ constructor(options) {
302
+ // Initialize PAP component
303
+ const papNamespace = options?.config?.papNamespace ?? PolicyAdministrationPointComponentEntityStorage.NAMESPACE;
304
+ // Get the component from the factory
305
+ this._papComponent = ComponentFactory.get(papNamespace);
306
+ }
307
+ /**
308
+ * PAP: Store a policy.
309
+ * @param policy The policy to store.
310
+ * @param userIdentity The identity of the user performing the operation.
311
+ * @param nodeIdentity The identity of the node the operation is performed on.
312
+ * @returns Nothing.
313
+ */
314
+ async papStore(policy, userIdentity, nodeIdentity) {
315
+ try {
316
+ Guards.object(this.CLASS_NAME, "policy", policy);
317
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
318
+ if (userIdentity !== undefined) {
319
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
320
+ }
321
+ await this._papComponent.store(policy, userIdentity, nodeIdentity);
322
+ }
323
+ catch (error) {
324
+ throw new GeneralError(this.CLASS_NAME, "papStoreFailed", undefined, error);
325
+ }
326
+ }
327
+ /**
328
+ * PAP: Retrieve a policy.
329
+ * @param policyId The id of the policy to retrieve.
330
+ * @param userIdentity The identity of the user performing the operation.
331
+ * @param nodeIdentity The identity of the node the operation is performed on.
332
+ * @returns The policy.
333
+ */
334
+ async papRetrieve(policyId, userIdentity, nodeIdentity) {
335
+ try {
336
+ Guards.stringValue(this.CLASS_NAME, "policyId", policyId);
337
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
338
+ if (userIdentity !== undefined) {
339
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
340
+ }
341
+ const policy = await this._papComponent.retrieve(policyId, userIdentity, nodeIdentity);
342
+ return policy;
343
+ }
344
+ catch (error) {
345
+ throw new GeneralError(this.CLASS_NAME, "papRetrieveFailed", undefined, error);
346
+ }
347
+ }
348
+ /**
349
+ * PAP: Remove a policy.
350
+ * @param policyId The id of the policy to remove.
351
+ * @param userIdentity The identity of the user performing the operation.
352
+ * @param nodeIdentity The identity of the node the operation is performed on.
353
+ * @returns Nothing.
354
+ */
355
+ async papRemove(policyId, userIdentity, nodeIdentity) {
356
+ try {
357
+ Guards.stringValue(this.CLASS_NAME, "policyId", policyId);
358
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
359
+ if (userIdentity !== undefined) {
360
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
361
+ }
362
+ await this._papComponent.remove(policyId, userIdentity, nodeIdentity);
363
+ }
364
+ catch (error) {
365
+ throw new GeneralError(this.CLASS_NAME, "papRemoveFailed", undefined, error);
366
+ }
367
+ }
368
+ /**
369
+ * PAP: Query the policies using the specified conditions.
370
+ * @param conditions The conditions to use for the query.
371
+ * @param cursor The cursor to use for pagination.
372
+ * @param pageSize The number of results to return per page.
373
+ * @param userIdentity The identity of the user performing the operation.
374
+ * @param nodeIdentity The identity of the node the operation is performed on.
375
+ * @returns Cursor for next page of results and the policies matching the query.
376
+ */
377
+ async papQuery(conditions, cursor, pageSize, userIdentity, nodeIdentity) {
378
+ try {
379
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
380
+ if (conditions !== undefined) {
381
+ Guards.stringValue(this.CLASS_NAME, "conditions", conditions);
382
+ }
383
+ if (cursor !== undefined) {
384
+ Guards.stringValue(this.CLASS_NAME, "cursor", cursor);
385
+ }
386
+ if (pageSize !== undefined) {
387
+ Guards.number(this.CLASS_NAME, "pageSize", pageSize);
388
+ }
389
+ if (userIdentity !== undefined) {
390
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
391
+ }
392
+ let conditionsObj;
393
+ if (conditions) {
394
+ conditionsObj = HttpParameterHelper.objectFromString(conditions);
395
+ if (Is.object(conditionsObj)) {
396
+ conditionsObj = conditionsObj;
397
+ }
398
+ }
399
+ const result = await this._papComponent.query(conditionsObj, cursor, pageSize, userIdentity, nodeIdentity);
400
+ return result;
401
+ }
402
+ catch (error) {
403
+ throw new GeneralError(this.CLASS_NAME, "papQueryFailed", undefined, error);
404
+ }
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Entry points for the REST API.
410
+ */
411
+ const restEntryPoints = [
412
+ {
413
+ name: "rights-management",
414
+ defaultBaseRoute: "rights-management",
415
+ tags,
416
+ generateRoutes: generateRestRoutes
417
+ }
418
+ ];
419
+
420
+ export { RightsManagementService, generateRestRoutes, papQuery, papRemove, papRetrieve, papStore, restEntryPoints, tags };
@@ -0,0 +1,5 @@
1
+ export * from "./models/IRightsManagementServiceConfig";
2
+ export * from "./models/IRightsManagementServiceConstructorOptions";
3
+ export * from "./rightsManagementRoutes";
4
+ export * from "./rightsManagementService";
5
+ export * from "./restEntryPoints";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The configuration for the RightsManagementService.
3
+ */
4
+ export interface IRightsManagementServiceConfig {
5
+ /**
6
+ * The namespace for the PAP component.
7
+ */
8
+ papNamespace?: string;
9
+ /**
10
+ * The default entity storage type.
11
+ */
12
+ defaultEntityStorageType?: string;
13
+ /**
14
+ * Should the user identity be included in entity storage operations.
15
+ */
16
+ includeUserIdentity?: boolean;
17
+ /**
18
+ * Should the node identity be included in entity storage operations.
19
+ */
20
+ includeNodeIdentity?: boolean;
21
+ /**
22
+ * The maximum number of results to return in a query.
23
+ */
24
+ maxQueryResults?: number;
25
+ }
@@ -0,0 +1,10 @@
1
+ import type { IRightsManagementServiceConfig } from "./IRightsManagementServiceConfig";
2
+ /**
3
+ * The constructor options for the RightsManagementService.
4
+ */
5
+ export interface IRightsManagementServiceConstructorOptions {
6
+ /**
7
+ * The configuration for the service.
8
+ */
9
+ config?: IRightsManagementServiceConfig;
10
+ }
@@ -0,0 +1,5 @@
1
+ import type { IRestRouteEntryPoint } from "@twin.org/api-models";
2
+ /**
3
+ * Entry points for the REST API.
4
+ */
5
+ export declare const restEntryPoints: IRestRouteEntryPoint[];
@@ -0,0 +1,45 @@
1
+ import { type ICreatedResponse, type IHttpRequestContext, type INoContentResponse, type IRestRoute, type ITag } from "@twin.org/api-models";
2
+ import type { IPapQueryRequest, IPapQueryResponse, IPapRemoveRequest, IPapRetrieveRequest, IPapRetrieveResponse, IPapStoreRequest } from "@twin.org/rights-management-models";
3
+ /**
4
+ * The tag to associate with the routes.
5
+ */
6
+ export declare const tags: ITag[];
7
+ /**
8
+ * The REST routes for the Rights Management.
9
+ * @param baseRouteName Prefix to prepend to the paths.
10
+ * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
11
+ * @returns The generated routes.
12
+ */
13
+ export declare function generateRestRoutes(baseRouteName: string, componentName: string): IRestRoute[];
14
+ /**
15
+ * PAP: Store a policy.
16
+ * @param httpRequestContext The request context for the API.
17
+ * @param componentName The name of the component to use in the routes.
18
+ * @param request The request.
19
+ * @returns The response object with additional http response properties.
20
+ */
21
+ export declare function papStore(httpRequestContext: IHttpRequestContext, componentName: string, request: IPapStoreRequest): Promise<ICreatedResponse>;
22
+ /**
23
+ * PAP: Retrieve a policy.
24
+ * @param httpRequestContext The request context for the API.
25
+ * @param componentName The name of the component to use in the routes.
26
+ * @param request The request.
27
+ * @returns The response object with additional http response properties.
28
+ */
29
+ export declare function papRetrieve(httpRequestContext: IHttpRequestContext, componentName: string, request: IPapRetrieveRequest): Promise<IPapRetrieveResponse>;
30
+ /**
31
+ * PAP: Remove a policy.
32
+ * @param httpRequestContext The request context for the API.
33
+ * @param componentName The name of the component to use in the routes.
34
+ * @param request The request.
35
+ * @returns The response object with additional http response properties.
36
+ */
37
+ export declare function papRemove(httpRequestContext: IHttpRequestContext, componentName: string, request: IPapRemoveRequest): Promise<INoContentResponse>;
38
+ /**
39
+ * PAP: Query policies.
40
+ * @param httpRequestContext The request context for the API.
41
+ * @param componentName The name of the component to use in the routes.
42
+ * @param request The request.
43
+ * @returns The response object with additional http response properties.
44
+ */
45
+ export declare function papQuery(httpRequestContext: IHttpRequestContext, componentName: string, request: IPapQueryRequest): Promise<IPapQueryResponse>;
@@ -0,0 +1,60 @@
1
+ import type { EntityCondition } from "@twin.org/entity";
2
+ import type { IRightsManagementComponent } from "@twin.org/rights-management-models";
3
+ import type { IOdrlPolicy } from "@twin.org/standards-w3c-odrl";
4
+ import type { IRightsManagementServiceConstructorOptions } from "./models/IRightsManagementServiceConstructorOptions";
5
+ /**
6
+ * Service for performing Rights Management operations.
7
+ * This is a unified service that provides access to all Rights Management components.
8
+ */
9
+ export declare class RightsManagementService implements IRightsManagementComponent {
10
+ /**
11
+ * The namespace supported by the Rights Management service.
12
+ */
13
+ static readonly NAMESPACE: string;
14
+ /**
15
+ * Runtime name for the class.
16
+ */
17
+ readonly CLASS_NAME: string;
18
+ /**
19
+ * Create a new instance of RightsManagementService.
20
+ * @param options The options for the service.
21
+ */
22
+ constructor(options?: IRightsManagementServiceConstructorOptions);
23
+ /**
24
+ * PAP: Store a policy.
25
+ * @param policy The policy to store.
26
+ * @param userIdentity The identity of the user performing the operation.
27
+ * @param nodeIdentity The identity of the node the operation is performed on.
28
+ * @returns Nothing.
29
+ */
30
+ papStore(policy: IOdrlPolicy, userIdentity: string | undefined, nodeIdentity: string): Promise<void>;
31
+ /**
32
+ * PAP: Retrieve a policy.
33
+ * @param policyId The id of the policy to retrieve.
34
+ * @param userIdentity The identity of the user performing the operation.
35
+ * @param nodeIdentity The identity of the node the operation is performed on.
36
+ * @returns The policy.
37
+ */
38
+ papRetrieve(policyId: string, userIdentity: string | undefined, nodeIdentity: string): Promise<IOdrlPolicy>;
39
+ /**
40
+ * PAP: Remove a policy.
41
+ * @param policyId The id of the policy to remove.
42
+ * @param userIdentity The identity of the user performing the operation.
43
+ * @param nodeIdentity The identity of the node the operation is performed on.
44
+ * @returns Nothing.
45
+ */
46
+ papRemove(policyId: string, userIdentity: string | undefined, nodeIdentity: string): Promise<void>;
47
+ /**
48
+ * PAP: Query the policies using the specified conditions.
49
+ * @param conditions The conditions to use for the query.
50
+ * @param cursor The cursor to use for pagination.
51
+ * @param pageSize The number of results to return per page.
52
+ * @param userIdentity The identity of the user performing the operation.
53
+ * @param nodeIdentity The identity of the node the operation is performed on.
54
+ * @returns Cursor for next page of results and the policies matching the query.
55
+ */
56
+ papQuery(conditions?: EntityCondition<IOdrlPolicy>, cursor?: string, pageSize?: number, userIdentity?: string, nodeIdentity?: string): Promise<{
57
+ cursor?: string;
58
+ policies: IOdrlPolicy[];
59
+ }>;
60
+ }
@@ -0,0 +1,20 @@
1
+ # @twin.org/rights-management-pap-service - Changelog
2
+
3
+ ## [0.0.1-next.3](https://github.com/twinfoundation/rights-management/compare/rights-management-service-v0.0.1-next.2...rights-management-service-v0.0.1-next.3) (2025-05-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * rights management pap ([#4](https://github.com/twinfoundation/rights-management/issues/4)) ([d1165a9](https://github.com/twinfoundation/rights-management/commit/d1165a92f57128731cfb308d977832e28cf33493))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/rights-management-models bumped from 0.0.1-next.2 to 0.0.1-next.3
16
+ * @twin.org/rights-management-pap-entity-storage bumped from 0.0.1-next.2 to 0.0.1-next.3
17
+
18
+ ## 0.0.1-next.1
19
+
20
+ - Initial release.
@@ -0,0 +1 @@
1
+ # @twin.org/rights-management-pap-service - Examples