@twin.org/immutable-proof-service 0.0.2-next.2 → 0.0.3-next.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.
@@ -0,0 +1,335 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { BackgroundTaskConnectorFactory, TaskStatus } from "@twin.org/background-task-models";
4
+ import { ContextIdHelper, ContextIdKeys, ContextIdStore } from "@twin.org/context";
5
+ import { ComponentFactory, Converter, GeneralError, Guards, Is, JsonHelper, NotFoundError, ObjectHelper, RandomHelper, Urn, Validation } from "@twin.org/core";
6
+ import { Sha256 } from "@twin.org/crypto";
7
+ import { JsonLdHelper, JsonLdProcessor } from "@twin.org/data-json-ld";
8
+ import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
9
+ import { IdentityConnectorFactory } from "@twin.org/identity-models";
10
+ import { ImmutableProofContexts, ImmutableProofFailure, ImmutableProofTopics, ImmutableProofTypes } from "@twin.org/immutable-proof-models";
11
+ import { DidCryptoSuites, ProofTypes } from "@twin.org/standards-w3c-did";
12
+ import { VerifiableStorageConnectorFactory } from "@twin.org/verifiable-storage-models";
13
+ /**
14
+ * Class for performing immutable proof operations.
15
+ */
16
+ export class ImmutableProofService {
17
+ /**
18
+ * Runtime name for the class.
19
+ */
20
+ static CLASS_NAME = "ImmutableProofService";
21
+ /**
22
+ * The namespace for the service.
23
+ * @internal
24
+ */
25
+ static _NAMESPACE = "immutable-proof";
26
+ /**
27
+ * The configuration for the connector.
28
+ * @internal
29
+ */
30
+ _config;
31
+ /**
32
+ * The identity connector.
33
+ * @internal
34
+ */
35
+ _identityConnector;
36
+ /**
37
+ * The entity storage for proofs.
38
+ * @internal
39
+ */
40
+ _proofStorage;
41
+ /**
42
+ * The verifiable storage for the credentials.
43
+ * @internal
44
+ */
45
+ _verifiableStorage;
46
+ /**
47
+ * The background task connector.
48
+ * @internal
49
+ */
50
+ _backgroundTaskConnector;
51
+ /**
52
+ * The event bus component.
53
+ * @internal
54
+ */
55
+ _eventBusComponent;
56
+ /**
57
+ * The verification method id to use for the proofs.
58
+ * @internal
59
+ */
60
+ _verificationMethodId;
61
+ /**
62
+ * The identity connector type.
63
+ * @internal
64
+ */
65
+ _identityConnectorType;
66
+ /**
67
+ * Create a new instance of ImmutableProofService.
68
+ * @param options The dependencies for the immutable proof connector.
69
+ */
70
+ constructor(options) {
71
+ this._proofStorage = EntityStorageConnectorFactory.get(options?.immutableProofEntityStorageType ?? "immutable-proof");
72
+ this._verifiableStorage = VerifiableStorageConnectorFactory.get(options?.verifiableStorageType ?? "verifiable-storage");
73
+ this._identityConnectorType = options?.identityConnectorType ?? "identity";
74
+ this._identityConnector = IdentityConnectorFactory.get(this._identityConnectorType);
75
+ this._backgroundTaskConnector = BackgroundTaskConnectorFactory.get(options?.backgroundTaskConnectorType ?? "background-task");
76
+ if (Is.stringValue(options?.eventBusComponentType)) {
77
+ this._eventBusComponent = ComponentFactory.get(options.eventBusComponentType);
78
+ }
79
+ this._config = options?.config ?? {};
80
+ this._verificationMethodId = this._config.verificationMethodId ?? "immutable-proof-assertion";
81
+ }
82
+ /**
83
+ * Returns the class name of the component.
84
+ * @returns The class name of the component.
85
+ */
86
+ className() {
87
+ return ImmutableProofService.CLASS_NAME;
88
+ }
89
+ /**
90
+ * The component needs to be started when the node is initialized.
91
+ * @param nodeLoggingComponentType The node logging component type.
92
+ * @returns Nothing.
93
+ */
94
+ async start(nodeLoggingComponentType) {
95
+ await this._backgroundTaskConnector.registerHandler("immutable-proof", "@twin.org/immutable-proof-task", "processProofTask", async (task) => {
96
+ await this.finaliseTask(task);
97
+ });
98
+ }
99
+ /**
100
+ * Create a new proof.
101
+ * @param document The document to create the proof for.
102
+ * @returns The id of the new proof.
103
+ */
104
+ async create(document) {
105
+ Guards.object(ImmutableProofService.CLASS_NAME, "document", document);
106
+ const contextIds = await ContextIdStore.getContextIds();
107
+ ContextIdHelper.guard(contextIds, ContextIdKeys.Organization);
108
+ try {
109
+ const validationFailures = [];
110
+ await JsonLdHelper.validate(document, validationFailures);
111
+ Validation.asValidationError(ImmutableProofService.CLASS_NAME, "document", validationFailures);
112
+ const id = Converter.bytesToHex(RandomHelper.generate(32), false);
113
+ const dateCreated = new Date(Date.now()).toISOString();
114
+ const proofObjectId = ObjectHelper.extractProperty(document, ["@id", "id"], false);
115
+ // We don't want to store the whole document in the immutable proof, as this could be large
116
+ // and also reveal information that should not be stored in the proof so we hash the document
117
+ // and store the hash
118
+ const proofObjectHash = this.calculateDocumentHash(document);
119
+ const proofEntity = {
120
+ id,
121
+ dateCreated,
122
+ proofObjectId,
123
+ proofObjectHash
124
+ };
125
+ await this._proofStorage.set(proofEntity);
126
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
127
+ const proofTaskPayload = {
128
+ proofId: id,
129
+ identity: contextIds[ContextIdKeys.Organization],
130
+ identityConnectorType: this._identityConnectorType,
131
+ verificationMethodId: this._verificationMethodId,
132
+ document: immutableProof
133
+ };
134
+ await this._backgroundTaskConnector.create("immutable-proof", proofTaskPayload);
135
+ return new Urn(ImmutableProofService._NAMESPACE, id).toString();
136
+ }
137
+ catch (error) {
138
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "createFailed", undefined, error);
139
+ }
140
+ }
141
+ /**
142
+ * Get a proof.
143
+ * @param id The id of the proof to get.
144
+ * @returns The proof.
145
+ * @throws NotFoundError if the proof is not found.
146
+ */
147
+ async get(id) {
148
+ Guards.stringValue(ImmutableProofService.CLASS_NAME, "id", id);
149
+ const urnParsed = Urn.fromValidString(id);
150
+ if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
151
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "namespaceMismatch", {
152
+ namespace: ImmutableProofService._NAMESPACE,
153
+ id
154
+ });
155
+ }
156
+ try {
157
+ const { immutableProof } = await this.internalGet(id, false);
158
+ const result = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
159
+ return result;
160
+ }
161
+ catch (error) {
162
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "getFailed", undefined, error);
163
+ }
164
+ }
165
+ /**
166
+ * Verify a proof.
167
+ * @param id The id of the proof to verify.
168
+ * @returns The result of the verification and any failures.
169
+ * @throws NotFoundError if the proof is not found.
170
+ */
171
+ async verify(id) {
172
+ Guards.stringValue(ImmutableProofService.CLASS_NAME, "id", id);
173
+ const urnParsed = Urn.fromValidString(id);
174
+ if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
175
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "namespaceMismatch", {
176
+ namespace: ImmutableProofService._NAMESPACE,
177
+ id
178
+ });
179
+ }
180
+ try {
181
+ const { verified, failure } = await this.internalGet(id, true);
182
+ return {
183
+ "@context": ImmutableProofContexts.ContextRoot,
184
+ type: ImmutableProofTypes.ImmutableProofVerification,
185
+ verified,
186
+ failure
187
+ };
188
+ }
189
+ catch (error) {
190
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "verifyFailed", undefined, error);
191
+ }
192
+ }
193
+ /**
194
+ * Remove the verifiable storage for the proof.
195
+ * @param id The id of the proof to remove the storage from.
196
+ * @returns Nothing.
197
+ * @throws NotFoundError if the proof is not found.
198
+ */
199
+ async removeVerifiable(id) {
200
+ Guards.stringValue(ImmutableProofService.CLASS_NAME, "id", id);
201
+ const contextIds = await ContextIdStore.getContextIds();
202
+ ContextIdHelper.guard(contextIds, ContextIdKeys.Organization);
203
+ const urnParsed = Urn.fromValidString(id);
204
+ if (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {
205
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "namespaceMismatch", {
206
+ namespace: ImmutableProofService._NAMESPACE,
207
+ id
208
+ });
209
+ }
210
+ try {
211
+ const streamId = urnParsed.namespaceSpecific(0);
212
+ const streamEntity = await this._proofStorage.get(streamId);
213
+ if (Is.empty(streamEntity)) {
214
+ throw new NotFoundError(ImmutableProofService.CLASS_NAME, "proofNotFound", id);
215
+ }
216
+ if (Is.stringValue(streamEntity.verifiableStorageId)) {
217
+ await this._verifiableStorage.remove(contextIds[ContextIdKeys.Organization], streamEntity.verifiableStorageId);
218
+ delete streamEntity.verifiableStorageId;
219
+ await this._proofStorage.set(streamEntity);
220
+ }
221
+ }
222
+ catch (error) {
223
+ throw new GeneralError(ImmutableProofService.CLASS_NAME, "removeVerifiableFailed", undefined, error);
224
+ }
225
+ }
226
+ /**
227
+ * Calculate the object hash.
228
+ * @param object The entry to calculate the hash for.
229
+ * @returns The hash.
230
+ * @internal
231
+ */
232
+ calculateDocumentHash(nodeObject) {
233
+ return `sha256:${Converter.bytesToBase64(Sha256.sum256(ObjectHelper.toBytes(JsonHelper.canonicalize(nodeObject))))}`;
234
+ }
235
+ /**
236
+ * Map the stream entity to a model.
237
+ * @param proofEntity The stream entity.
238
+ * @returns The model.
239
+ * @internal
240
+ */
241
+ proofEntityToJsonLd(proofEntity) {
242
+ const jsonLd = {
243
+ "@context": [ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon],
244
+ type: ImmutableProofTypes.ImmutableProof,
245
+ id: proofEntity.id,
246
+ proofObjectId: proofEntity.proofObjectId,
247
+ proofObjectHash: proofEntity.proofObjectHash,
248
+ verifiableStorageId: proofEntity.verifiableStorageId
249
+ };
250
+ return jsonLd;
251
+ }
252
+ /**
253
+ * Process a proof.
254
+ * @param proofEntity The proof entity to process.
255
+ * @internal
256
+ */
257
+ async finaliseTask(task) {
258
+ if (task.status === TaskStatus.Success && Is.object(task.payload) && Is.object(task.result)) {
259
+ const proofEntity = await this._proofStorage.get(task.payload.proofId);
260
+ if (Is.object(proofEntity)) {
261
+ const immutableProof = this.proofEntityToJsonLd(proofEntity);
262
+ // As we are adding the proof to the data we update its context
263
+ immutableProof["@context"] = JsonLdProcessor.combineContexts([ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon], task.result.proof["@context"]);
264
+ immutableProof.proof = task.result.proof;
265
+ ObjectHelper.propertyDelete(immutableProof.proof, "@context");
266
+ if (Is.stringValue(immutableProof.proof.created)) {
267
+ proofEntity.dateCreated = immutableProof.proof.created;
268
+ }
269
+ const compacted = await JsonLdProcessor.compact(immutableProof, immutableProof["@context"]);
270
+ const verifiableCreateResult = await this._verifiableStorage.create(task.payload.identity, ObjectHelper.toBytes(compacted));
271
+ proofEntity.verifiableStorageId = verifiableCreateResult.id;
272
+ await this._proofStorage.set(proofEntity);
273
+ await this._eventBusComponent?.publish(ImmutableProofTopics.ProofCreated, { id: new Urn(ImmutableProofService._NAMESPACE, task.payload.proofId).toString() });
274
+ }
275
+ }
276
+ }
277
+ /**
278
+ * Verify a proof.
279
+ * @param id The id of the proof to verify.
280
+ * @param verify Validate the proof.
281
+ * @returns The result of the verification and any failures.
282
+ * @throws NotFoundError if the proof is not found.
283
+ * @internal
284
+ */
285
+ async internalGet(id, verify) {
286
+ const urnParsed = Urn.fromValidString(id);
287
+ const proofId = urnParsed.namespaceSpecific(0);
288
+ const proofEntity = await this._proofStorage.get(proofId);
289
+ if (Is.empty(proofEntity)) {
290
+ throw new NotFoundError(ImmutableProofService.CLASS_NAME, "proofNotFound", id);
291
+ }
292
+ let proofJsonLd = this.proofEntityToJsonLd(proofEntity);
293
+ let verified = false;
294
+ let failure = ImmutableProofFailure.NotIssued;
295
+ if (Is.stringValue(proofEntity.verifiableStorageId)) {
296
+ failure = ImmutableProofFailure.ProofMissing;
297
+ const immutableResult = await this._verifiableStorage.get(proofEntity.verifiableStorageId);
298
+ if (Is.uint8Array(immutableResult.data)) {
299
+ proofJsonLd = ObjectHelper.fromBytes(immutableResult.data);
300
+ const unsecureDocument = ObjectHelper.clone(proofJsonLd);
301
+ proofJsonLd.immutableReceipt = immutableResult.receipt;
302
+ proofJsonLd.verifiableStorageId = proofEntity.verifiableStorageId;
303
+ // As we are adding the receipt to the data we update the JSON-LD context
304
+ const receiptContext = immutableResult.receipt["@context"];
305
+ if (!Is.empty(receiptContext)) {
306
+ proofJsonLd["@context"] = JsonLdProcessor.combineContexts(proofJsonLd["@context"], receiptContext);
307
+ }
308
+ if (verify && Is.object(proofJsonLd.proof)) {
309
+ if (proofJsonLd.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {
310
+ failure = ImmutableProofFailure.CryptoSuiteMismatch;
311
+ }
312
+ else if (proofJsonLd.proof.type !== ProofTypes.DataIntegrityProof) {
313
+ failure = ImmutableProofFailure.ProofTypeMismatch;
314
+ }
315
+ else {
316
+ const isVerified = await this._identityConnector.verifyProof(unsecureDocument, proofJsonLd.proof);
317
+ if (isVerified) {
318
+ verified = true;
319
+ failure = undefined;
320
+ }
321
+ else {
322
+ failure = ImmutableProofFailure.SignatureMismatch;
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ return {
329
+ immutableProof: proofJsonLd,
330
+ verified,
331
+ failure
332
+ };
333
+ }
334
+ }
335
+ //# sourceMappingURL=immutableProofService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"immutableProofService.js","sourceRoot":"","sources":["../../src/immutableProofService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tBackgroundTaskConnectorFactory,\n\tTaskStatus,\n\ttype IBackgroundTask,\n\ttype IBackgroundTaskConnector\n} from \"@twin.org/background-task-models\";\nimport { ContextIdHelper, ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport {\n\tComponentFactory,\n\tConverter,\n\tGeneralError,\n\tGuards,\n\tIs,\n\tJsonHelper,\n\tNotFoundError,\n\tObjectHelper,\n\tRandomHelper,\n\tUrn,\n\tValidation,\n\ttype IValidationFailure\n} from \"@twin.org/core\";\nimport { Sha256 } from \"@twin.org/crypto\";\nimport { JsonLdHelper, JsonLdProcessor, type IJsonLdNodeObject } from \"@twin.org/data-json-ld\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport type { IEventBusComponent } from \"@twin.org/event-bus-models\";\nimport { IdentityConnectorFactory, type IIdentityConnector } from \"@twin.org/identity-models\";\nimport {\n\tImmutableProofContexts,\n\tImmutableProofFailure,\n\tImmutableProofTopics,\n\tImmutableProofTypes,\n\ttype IImmutableProof,\n\ttype IImmutableProofComponent,\n\ttype IImmutableProofEventBusProofCreated,\n\ttype IImmutableProofVerification\n} from \"@twin.org/immutable-proof-models\";\nimport type {\n\tIImmutableProofTaskPayload,\n\tIImmutableProofTaskResult\n} from \"@twin.org/immutable-proof-task\";\nimport { nameof, nameofKebabCase } from \"@twin.org/nameof\";\nimport { DidCryptoSuites, ProofTypes } from \"@twin.org/standards-w3c-did\";\nimport {\n\tVerifiableStorageConnectorFactory,\n\ttype IVerifiableStorageConnector\n} from \"@twin.org/verifiable-storage-models\";\nimport type { ImmutableProof } from \"./entities/immutableProof.js\";\nimport type { IImmutableProofServiceConfig } from \"./models/IImmutableProofServiceConfig.js\";\nimport type { IImmutableProofServiceConstructorOptions } from \"./models/IImmutableProofServiceConstructorOptions.js\";\n\n/**\n * Class for performing immutable proof operations.\n */\nexport class ImmutableProofService implements IImmutableProofComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<ImmutableProofService>();\n\n\t/**\n\t * The namespace for the service.\n\t * @internal\n\t */\n\tprivate static readonly _NAMESPACE: string = \"immutable-proof\";\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: IImmutableProofServiceConfig;\n\n\t/**\n\t * The identity connector.\n\t * @internal\n\t */\n\tprivate readonly _identityConnector: IIdentityConnector;\n\n\t/**\n\t * The entity storage for proofs.\n\t * @internal\n\t */\n\tprivate readonly _proofStorage: IEntityStorageConnector<ImmutableProof>;\n\n\t/**\n\t * The verifiable storage for the credentials.\n\t * @internal\n\t */\n\tprivate readonly _verifiableStorage: IVerifiableStorageConnector;\n\n\t/**\n\t * The background task connector.\n\t * @internal\n\t */\n\tprivate readonly _backgroundTaskConnector: IBackgroundTaskConnector;\n\n\t/**\n\t * The event bus component.\n\t * @internal\n\t */\n\tprivate readonly _eventBusComponent?: IEventBusComponent;\n\n\t/**\n\t * The verification method id to use for the proofs.\n\t * @internal\n\t */\n\tprivate readonly _verificationMethodId: string;\n\n\t/**\n\t * The identity connector type.\n\t * @internal\n\t */\n\tprivate readonly _identityConnectorType: string;\n\n\t/**\n\t * Create a new instance of ImmutableProofService.\n\t * @param options The dependencies for the immutable proof connector.\n\t */\n\tconstructor(options?: IImmutableProofServiceConstructorOptions) {\n\t\tthis._proofStorage = EntityStorageConnectorFactory.get(\n\t\t\toptions?.immutableProofEntityStorageType ?? nameofKebabCase<ImmutableProof>()\n\t\t);\n\n\t\tthis._verifiableStorage = VerifiableStorageConnectorFactory.get(\n\t\t\toptions?.verifiableStorageType ?? \"verifiable-storage\"\n\t\t);\n\n\t\tthis._identityConnectorType = options?.identityConnectorType ?? \"identity\";\n\n\t\tthis._identityConnector = IdentityConnectorFactory.get(this._identityConnectorType);\n\n\t\tthis._backgroundTaskConnector = BackgroundTaskConnectorFactory.get(\n\t\t\toptions?.backgroundTaskConnectorType ?? \"background-task\"\n\t\t);\n\n\t\tif (Is.stringValue(options?.eventBusComponentType)) {\n\t\t\tthis._eventBusComponent = ComponentFactory.get(options.eventBusComponentType);\n\t\t}\n\n\t\tthis._config = options?.config ?? {};\n\t\tthis._verificationMethodId = this._config.verificationMethodId ?? \"immutable-proof-assertion\";\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn ImmutableProofService.CLASS_NAME;\n\t}\n\n\t/**\n\t * The component needs to be started when the node is initialized.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns Nothing.\n\t */\n\tpublic async start(nodeLoggingComponentType?: string): Promise<void> {\n\t\tawait this._backgroundTaskConnector.registerHandler<\n\t\t\tIImmutableProofTaskPayload,\n\t\t\tIImmutableProofTaskResult\n\t\t>(\"immutable-proof\", \"@twin.org/immutable-proof-task\", \"processProofTask\", async task => {\n\t\t\tawait this.finaliseTask(task);\n\t\t});\n\t}\n\n\t/**\n\t * Create a new proof.\n\t * @param document The document to create the proof for.\n\t * @returns The id of the new proof.\n\t */\n\tpublic async create(document: IJsonLdNodeObject): Promise<string> {\n\t\tGuards.object<IJsonLdNodeObject>(ImmutableProofService.CLASS_NAME, nameof(document), document);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Organization);\n\n\t\ttry {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tawait JsonLdHelper.validate(document, validationFailures);\n\t\t\tValidation.asValidationError(\n\t\t\t\tImmutableProofService.CLASS_NAME,\n\t\t\t\tnameof(document),\n\t\t\t\tvalidationFailures\n\t\t\t);\n\n\t\t\tconst id = Converter.bytesToHex(RandomHelper.generate(32), false);\n\n\t\t\tconst dateCreated = new Date(Date.now()).toISOString();\n\n\t\t\tconst proofObjectId = ObjectHelper.extractProperty<string>(document, [\"@id\", \"id\"], false);\n\n\t\t\t// We don't want to store the whole document in the immutable proof, as this could be large\n\t\t\t// and also reveal information that should not be stored in the proof so we hash the document\n\t\t\t// and store the hash\n\t\t\tconst proofObjectHash = this.calculateDocumentHash(document);\n\n\t\t\tconst proofEntity: ImmutableProof = {\n\t\t\t\tid,\n\t\t\t\tdateCreated,\n\t\t\t\tproofObjectId,\n\t\t\t\tproofObjectHash\n\t\t\t};\n\t\t\tawait this._proofStorage.set(proofEntity);\n\n\t\t\tconst immutableProof = this.proofEntityToJsonLd(proofEntity);\n\n\t\t\tconst proofTaskPayload: IImmutableProofTaskPayload = {\n\t\t\t\tproofId: id,\n\t\t\t\tidentity: contextIds[ContextIdKeys.Organization],\n\t\t\t\tidentityConnectorType: this._identityConnectorType,\n\t\t\t\tverificationMethodId: this._verificationMethodId,\n\t\t\t\tdocument: immutableProof as unknown as IJsonLdNodeObject\n\t\t\t};\n\n\t\t\tawait this._backgroundTaskConnector.create(\"immutable-proof\", proofTaskPayload);\n\n\t\t\treturn new Urn(ImmutableProofService._NAMESPACE, id).toString();\n\t\t} catch (error) {\n\t\t\tthrow new GeneralError(ImmutableProofService.CLASS_NAME, \"createFailed\", undefined, error);\n\t\t}\n\t}\n\n\t/**\n\t * Get a proof.\n\t * @param id The id of the proof to get.\n\t * @returns The proof.\n\t * @throws NotFoundError if the proof is not found.\n\t */\n\tpublic async get(id: string): Promise<IImmutableProof> {\n\t\tGuards.stringValue(ImmutableProofService.CLASS_NAME, nameof(id), id);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {\n\t\t\tthrow new GeneralError(ImmutableProofService.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: ImmutableProofService._NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst { immutableProof } = await this.internalGet(id, false);\n\n\t\t\tconst result = await JsonLdProcessor.compact(immutableProof, immutableProof[\"@context\"]);\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tthrow new GeneralError(ImmutableProofService.CLASS_NAME, \"getFailed\", undefined, error);\n\t\t}\n\t}\n\n\t/**\n\t * Verify a proof.\n\t * @param id The id of the proof to verify.\n\t * @returns The result of the verification and any failures.\n\t * @throws NotFoundError if the proof is not found.\n\t */\n\tpublic async verify(id: string): Promise<IImmutableProofVerification> {\n\t\tGuards.stringValue(ImmutableProofService.CLASS_NAME, nameof(id), id);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {\n\t\t\tthrow new GeneralError(ImmutableProofService.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: ImmutableProofService._NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst { verified, failure } = await this.internalGet(id, true);\n\n\t\t\treturn {\n\t\t\t\t\"@context\": ImmutableProofContexts.ContextRoot,\n\t\t\t\ttype: ImmutableProofTypes.ImmutableProofVerification,\n\t\t\t\tverified,\n\t\t\t\tfailure\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new GeneralError(ImmutableProofService.CLASS_NAME, \"verifyFailed\", undefined, error);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the verifiable storage for the proof.\n\t * @param id The id of the proof to remove the storage from.\n\t * @returns Nothing.\n\t * @throws NotFoundError if the proof is not found.\n\t */\n\tpublic async removeVerifiable(id: string): Promise<void> {\n\t\tGuards.stringValue(ImmutableProofService.CLASS_NAME, nameof(id), id);\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tContextIdHelper.guard(contextIds, ContextIdKeys.Organization);\n\n\t\tconst urnParsed = Urn.fromValidString(id);\n\n\t\tif (urnParsed.namespaceIdentifier() !== ImmutableProofService._NAMESPACE) {\n\t\t\tthrow new GeneralError(ImmutableProofService.CLASS_NAME, \"namespaceMismatch\", {\n\t\t\t\tnamespace: ImmutableProofService._NAMESPACE,\n\t\t\t\tid\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst streamId = urnParsed.namespaceSpecific(0);\n\t\t\tconst streamEntity = await this._proofStorage.get(streamId);\n\n\t\t\tif (Is.empty(streamEntity)) {\n\t\t\t\tthrow new NotFoundError(ImmutableProofService.CLASS_NAME, \"proofNotFound\", id);\n\t\t\t}\n\n\t\t\tif (Is.stringValue(streamEntity.verifiableStorageId)) {\n\t\t\t\tawait this._verifiableStorage.remove(\n\t\t\t\t\tcontextIds[ContextIdKeys.Organization],\n\t\t\t\t\tstreamEntity.verifiableStorageId\n\t\t\t\t);\n\t\t\t\tdelete streamEntity.verifiableStorageId;\n\t\t\t\tawait this._proofStorage.set(streamEntity);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tImmutableProofService.CLASS_NAME,\n\t\t\t\t\"removeVerifiableFailed\",\n\t\t\t\tundefined,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Calculate the object hash.\n\t * @param object The entry to calculate the hash for.\n\t * @returns The hash.\n\t * @internal\n\t */\n\tprivate calculateDocumentHash(nodeObject: IJsonLdNodeObject): string {\n\t\treturn `sha256:${Converter.bytesToBase64(Sha256.sum256(ObjectHelper.toBytes(JsonHelper.canonicalize(nodeObject))))}`;\n\t}\n\n\t/**\n\t * Map the stream entity to a model.\n\t * @param proofEntity The stream entity.\n\t * @returns The model.\n\t * @internal\n\t */\n\tprivate proofEntityToJsonLd(proofEntity: ImmutableProof): IImmutableProof {\n\t\tconst jsonLd: IImmutableProof = {\n\t\t\t\"@context\": [ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon],\n\t\t\ttype: ImmutableProofTypes.ImmutableProof,\n\t\t\tid: proofEntity.id,\n\t\t\tproofObjectId: proofEntity.proofObjectId,\n\t\t\tproofObjectHash: proofEntity.proofObjectHash,\n\t\t\tverifiableStorageId: proofEntity.verifiableStorageId\n\t\t};\n\n\t\treturn jsonLd;\n\t}\n\n\t/**\n\t * Process a proof.\n\t * @param proofEntity The proof entity to process.\n\t * @internal\n\t */\n\tprivate async finaliseTask(\n\t\ttask: IBackgroundTask<IImmutableProofTaskPayload, IImmutableProofTaskResult>\n\t): Promise<void> {\n\t\tif (task.status === TaskStatus.Success && Is.object(task.payload) && Is.object(task.result)) {\n\t\t\tconst proofEntity = await this._proofStorage.get(task.payload.proofId);\n\n\t\t\tif (Is.object(proofEntity)) {\n\t\t\t\tconst immutableProof: IImmutableProof = this.proofEntityToJsonLd(proofEntity);\n\n\t\t\t\t// As we are adding the proof to the data we update its context\n\t\t\t\timmutableProof[\"@context\"] = JsonLdProcessor.combineContexts(\n\t\t\t\t\t[ImmutableProofContexts.ContextRoot, ImmutableProofContexts.ContextRootCommon],\n\t\t\t\t\ttask.result.proof[\"@context\"]\n\t\t\t\t) as IImmutableProof[\"@context\"];\n\t\t\t\timmutableProof.proof = task.result.proof;\n\t\t\t\tObjectHelper.propertyDelete(immutableProof.proof, \"@context\");\n\n\t\t\t\tif (Is.stringValue(immutableProof.proof.created)) {\n\t\t\t\t\tproofEntity.dateCreated = immutableProof.proof.created;\n\t\t\t\t}\n\n\t\t\t\tconst compacted = await JsonLdProcessor.compact(immutableProof, immutableProof[\"@context\"]);\n\n\t\t\t\tconst verifiableCreateResult = await this._verifiableStorage.create(\n\t\t\t\t\ttask.payload.identity,\n\t\t\t\t\tObjectHelper.toBytes(compacted)\n\t\t\t\t);\n\n\t\t\t\tproofEntity.verifiableStorageId = verifiableCreateResult.id;\n\n\t\t\t\tawait this._proofStorage.set(proofEntity);\n\n\t\t\t\tawait this._eventBusComponent?.publish<IImmutableProofEventBusProofCreated>(\n\t\t\t\t\tImmutableProofTopics.ProofCreated,\n\t\t\t\t\t{ id: new Urn(ImmutableProofService._NAMESPACE, task.payload.proofId).toString() }\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Verify a proof.\n\t * @param id The id of the proof to verify.\n\t * @param verify Validate the proof.\n\t * @returns The result of the verification and any failures.\n\t * @throws NotFoundError if the proof is not found.\n\t * @internal\n\t */\n\tprivate async internalGet(\n\t\tid: string,\n\t\tverify: boolean\n\t): Promise<{\n\t\tverified: boolean;\n\t\tfailure?: ImmutableProofFailure;\n\t\timmutableProof: IImmutableProof;\n\t}> {\n\t\tconst urnParsed = Urn.fromValidString(id);\n\t\tconst proofId = urnParsed.namespaceSpecific(0);\n\t\tconst proofEntity = await this._proofStorage.get(proofId);\n\n\t\tif (Is.empty(proofEntity)) {\n\t\t\tthrow new NotFoundError(ImmutableProofService.CLASS_NAME, \"proofNotFound\", id);\n\t\t}\n\n\t\tlet proofJsonLd = this.proofEntityToJsonLd(proofEntity);\n\t\tlet verified = false;\n\t\tlet failure: ImmutableProofFailure | undefined = ImmutableProofFailure.NotIssued;\n\n\t\tif (Is.stringValue(proofEntity.verifiableStorageId)) {\n\t\t\tfailure = ImmutableProofFailure.ProofMissing;\n\t\t\tconst immutableResult = await this._verifiableStorage.get(proofEntity.verifiableStorageId);\n\n\t\t\tif (Is.uint8Array(immutableResult.data)) {\n\t\t\t\tproofJsonLd = ObjectHelper.fromBytes<IImmutableProof>(immutableResult.data);\n\n\t\t\t\tconst unsecureDocument = ObjectHelper.clone(proofJsonLd) as unknown as IJsonLdNodeObject;\n\t\t\t\tproofJsonLd.immutableReceipt = immutableResult.receipt;\n\t\t\t\tproofJsonLd.verifiableStorageId = proofEntity.verifiableStorageId;\n\n\t\t\t\t// As we are adding the receipt to the data we update the JSON-LD context\n\t\t\t\tconst receiptContext = immutableResult.receipt[\"@context\"];\n\t\t\t\tif (!Is.empty(receiptContext)) {\n\t\t\t\t\tproofJsonLd[\"@context\"] = JsonLdProcessor.combineContexts(\n\t\t\t\t\t\tproofJsonLd[\"@context\"],\n\t\t\t\t\t\treceiptContext\n\t\t\t\t\t) as IImmutableProof[\"@context\"];\n\t\t\t\t}\n\n\t\t\t\tif (verify && Is.object(proofJsonLd.proof)) {\n\t\t\t\t\tif (proofJsonLd.proof.cryptosuite !== DidCryptoSuites.EdDSAJcs2022) {\n\t\t\t\t\t\tfailure = ImmutableProofFailure.CryptoSuiteMismatch;\n\t\t\t\t\t} else if (proofJsonLd.proof.type !== ProofTypes.DataIntegrityProof) {\n\t\t\t\t\t\tfailure = ImmutableProofFailure.ProofTypeMismatch;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst isVerified = await this._identityConnector.verifyProof(\n\t\t\t\t\t\t\tunsecureDocument,\n\t\t\t\t\t\t\tproofJsonLd.proof\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tif (isVerified) {\n\t\t\t\t\t\t\tverified = true;\n\t\t\t\t\t\t\tfailure = undefined;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfailure = ImmutableProofFailure.SignatureMismatch;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\timmutableProof: proofJsonLd,\n\t\t\tverified,\n\t\t\tfailure\n\t\t};\n\t}\n}\n"]}
@@ -0,0 +1,10 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export * from "./entities/immutableProof.js";
4
+ export * from "./immutableProofRoutes.js";
5
+ export * from "./immutableProofService.js";
6
+ export * from "./models/IImmutableProofServiceConfig.js";
7
+ export * from "./models/IImmutableProofServiceConstructorOptions.js";
8
+ export * from "./restEntryPoints.js";
9
+ export * from "./schema.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0CAA0C,CAAC;AACzD,cAAc,sDAAsD,CAAC;AACrE,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/immutableProof.js\";\nexport * from \"./immutableProofRoutes.js\";\nexport * from \"./immutableProofService.js\";\nexport * from \"./models/IImmutableProofServiceConfig.js\";\nexport * from \"./models/IImmutableProofServiceConstructorOptions.js\";\nexport * from \"./restEntryPoints.js\";\nexport * from \"./schema.js\";\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=IImmutableProofServiceConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IImmutableProofServiceConfig.js","sourceRoot":"","sources":["../../../src/models/IImmutableProofServiceConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the immutable proof service.\n */\nexport interface IImmutableProofServiceConfig {\n\t/**\n\t * The verification method id to use for the proof.\n\t * @default immutable-proof-assertion\n\t */\n\tverificationMethodId?: string;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IImmutableProofServiceConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IImmutableProofServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IImmutableProofServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IImmutableProofServiceConfig } from \"./IImmutableProofServiceConfig.js\";\n\n/**\n * Options for the immutable proof service constructor.\n */\nexport interface IImmutableProofServiceConstructorOptions {\n\t/**\n\t * The entity storage for proofs.\n\t * @default immutable-proof\n\t */\n\timmutableProofEntityStorageType?: string;\n\n\t/**\n\t * The verifiable storage.\n\t * @default verifiable-storage\n\t */\n\tverifiableStorageType?: string;\n\n\t/**\n\t * The identity connector type.\n\t * @default identity\n\t */\n\tidentityConnectorType?: string;\n\n\t/**\n\t * The background task connector type.\n\t * @default background-task\n\t */\n\tbackgroundTaskConnectorType?: string;\n\n\t/**\n\t * The event bus component type, defaults to no event bus.\n\t */\n\teventBusComponentType?: string;\n\n\t/**\n\t * The configuration for the connector.\n\t */\n\tconfig?: IImmutableProofServiceConfig;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import { generateRestRoutesImmutableProof, tagsImmutableProof } from "./immutableProofRoutes.js";
2
+ export const restEntryPoints = [
3
+ {
4
+ name: "immutable-proof",
5
+ defaultBaseRoute: "immutable-proof",
6
+ tags: tagsImmutableProof,
7
+ generateRoutes: generateRestRoutesImmutableProof
8
+ }
9
+ ];
10
+ //# sourceMappingURL=restEntryPoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restEntryPoints.js","sourceRoot":"","sources":["../../src/restEntryPoints.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gCAAgC,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEjG,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD;QACC,IAAI,EAAE,iBAAiB;QACvB,gBAAgB,EAAE,iBAAiB;QACnC,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,gCAAgC;KAChD;CACD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRestRouteEntryPoint } from \"@twin.org/api-models\";\nimport { generateRestRoutesImmutableProof, tagsImmutableProof } from \"./immutableProofRoutes.js\";\n\nexport const restEntryPoints: IRestRouteEntryPoint[] = [\n\t{\n\t\tname: \"immutable-proof\",\n\t\tdefaultBaseRoute: \"immutable-proof\",\n\t\ttags: tagsImmutableProof,\n\t\tgenerateRoutes: generateRestRoutesImmutableProof\n\t}\n];\n"]}
@@ -0,0 +1,11 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { EntitySchemaFactory, EntitySchemaHelper } from "@twin.org/entity";
4
+ import { ImmutableProof } from "./entities/immutableProof.js";
5
+ /**
6
+ * Initialize the schema for the immutable proof entity storage connector.
7
+ */
8
+ export function initSchema() {
9
+ EntitySchemaFactory.register("ImmutableProof", () => EntitySchemaHelper.getSchema(ImmutableProof));
10
+ }
11
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +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,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,mBAAmB,CAAC,QAAQ,mBAA2B,GAAG,EAAE,CAC3D,kBAAkB,CAAC,SAAS,CAAC,cAAc,CAAC,CAC5C,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { EntitySchemaFactory, EntitySchemaHelper } from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { ImmutableProof } from \"./entities/immutableProof.js\";\n\n/**\n * Initialize the schema for the immutable proof entity storage connector.\n */\nexport function initSchema(): void {\n\tEntitySchemaFactory.register(nameof<ImmutableProof>(), () =>\n\t\tEntitySchemaHelper.getSchema(ImmutableProof)\n\t);\n}\n"]}
@@ -6,14 +6,6 @@ export declare class ImmutableProof {
6
6
  * The id of the proof.
7
7
  */
8
8
  id: string;
9
- /**
10
- * The identity of the node which controls the proof.
11
- */
12
- nodeIdentity: string;
13
- /**
14
- * The identity of the user which created the proof.
15
- */
16
- userIdentity: string;
17
9
  /**
18
10
  * The date/time of when the proof was created.
19
11
  */
@@ -1,6 +1,6 @@
1
1
  import { type IJsonLdNodeObject } from "@twin.org/data-json-ld";
2
2
  import { type IImmutableProof, type IImmutableProofComponent, type IImmutableProofVerification } from "@twin.org/immutable-proof-models";
3
- import type { IImmutableProofServiceConstructorOptions } from "./models/IImmutableProofServiceConstructorOptions";
3
+ import type { IImmutableProofServiceConstructorOptions } from "./models/IImmutableProofServiceConstructorOptions.js";
4
4
  /**
5
5
  * Class for performing immutable proof operations.
6
6
  */
@@ -8,20 +8,29 @@ export declare class ImmutableProofService implements IImmutableProofComponent {
8
8
  /**
9
9
  * Runtime name for the class.
10
10
  */
11
- readonly CLASS_NAME: string;
11
+ static readonly CLASS_NAME: string;
12
12
  /**
13
13
  * Create a new instance of ImmutableProofService.
14
14
  * @param options The dependencies for the immutable proof connector.
15
15
  */
16
16
  constructor(options?: IImmutableProofServiceConstructorOptions);
17
+ /**
18
+ * Returns the class name of the component.
19
+ * @returns The class name of the component.
20
+ */
21
+ className(): string;
22
+ /**
23
+ * The component needs to be started when the node is initialized.
24
+ * @param nodeLoggingComponentType The node logging component type.
25
+ * @returns Nothing.
26
+ */
27
+ start(nodeLoggingComponentType?: string): Promise<void>;
17
28
  /**
18
29
  * Create a new proof.
19
30
  * @param document The document to create the proof for.
20
- * @param userIdentity The identity to create the immutable proof operation with.
21
- * @param nodeIdentity The node identity to use for vault operations.
22
31
  * @returns The id of the new proof.
23
32
  */
24
- create(document: IJsonLdNodeObject, userIdentity?: string, nodeIdentity?: string): Promise<string>;
33
+ create(document: IJsonLdNodeObject): Promise<string>;
25
34
  /**
26
35
  * Get a proof.
27
36
  * @param id The id of the proof to get.
@@ -39,9 +48,8 @@ export declare class ImmutableProofService implements IImmutableProofComponent {
39
48
  /**
40
49
  * Remove the verifiable storage for the proof.
41
50
  * @param id The id of the proof to remove the storage from.
42
- * @param nodeIdentity The node identity to use for vault operations.
43
51
  * @returns Nothing.
44
52
  * @throws NotFoundError if the proof is not found.
45
53
  */
46
- removeVerifiable(id: string, nodeIdentity?: string): Promise<void>;
54
+ removeVerifiable(id: string): Promise<void>;
47
55
  }
@@ -1,7 +1,7 @@
1
- export * from "./entities/immutableProof";
2
- export * from "./immutableProofRoutes";
3
- export * from "./immutableProofService";
4
- export * from "./models/IImmutableProofServiceConfig";
5
- export * from "./models/IImmutableProofServiceConstructorOptions";
6
- export * from "./restEntryPoints";
7
- export * from "./schema";
1
+ export * from "./entities/immutableProof.js";
2
+ export * from "./immutableProofRoutes.js";
3
+ export * from "./immutableProofService.js";
4
+ export * from "./models/IImmutableProofServiceConfig.js";
5
+ export * from "./models/IImmutableProofServiceConstructorOptions.js";
6
+ export * from "./restEntryPoints.js";
7
+ export * from "./schema.js";
@@ -1,4 +1,4 @@
1
- import type { IImmutableProofServiceConfig } from "./IImmutableProofServiceConfig";
1
+ import type { IImmutableProofServiceConfig } from "./IImmutableProofServiceConfig.js";
2
2
  /**
3
3
  * Options for the immutable proof service constructor.
4
4
  */
package/docs/changelog.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # @twin.org/immutable-proof-service - Changelog
2
2
 
3
+ ## [0.0.3-next.1](https://github.com/twinfoundation/immutable-proof/compare/immutable-proof-service-v0.0.3-next.0...immutable-proof-service-v0.0.3-next.1) (2025-11-12)
4
+
5
+
6
+ ### Features
7
+
8
+ * add context id features ([#14](https://github.com/twinfoundation/immutable-proof/issues/14)) ([ed5a594](https://github.com/twinfoundation/immutable-proof/commit/ed5a594eaa7d50f74b1c09a7a560d48b33a4ecd1))
9
+ * add validate-locales ([d6a7c07](https://github.com/twinfoundation/immutable-proof/commit/d6a7c0794a1922981a42f56cc24724d7cee727f6))
10
+ * eslint migration to flat config ([c8536f2](https://github.com/twinfoundation/immutable-proof/commit/c8536f219c7709c6c08b9266e537831f9054dda9))
11
+ * remove unused namespace ([a39864c](https://github.com/twinfoundation/immutable-proof/commit/a39864c0b2ca8753334a34028b8e5823a14162b4))
12
+ * update data types to use fully qualified names ([e94d0f5](https://github.com/twinfoundation/immutable-proof/commit/e94d0f5db93856b5b59cfd34e55252fa13a7f4e0))
13
+ * update dependencies ([7d6b321](https://github.com/twinfoundation/immutable-proof/commit/7d6b321928ca0434ee530816b1440f1687b94a6e))
14
+ * update framework core ([e708d4d](https://github.com/twinfoundation/immutable-proof/commit/e708d4dd3febcfbcd64663d5be004eab1d26c0fb))
15
+ * use shared store mechanism ([#3](https://github.com/twinfoundation/immutable-proof/issues/3)) ([7042a40](https://github.com/twinfoundation/immutable-proof/commit/7042a40f0ef8b01463f07aeb1efae4f417162fa1))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * Missing user and node identity on create ([#1](https://github.com/twinfoundation/immutable-proof/issues/1)) ([80ea2f9](https://github.com/twinfoundation/immutable-proof/commit/80ea2f901afc7531f4a522227a61e6fa1482484d))
21
+
22
+
23
+ ### Dependencies
24
+
25
+ * The following workspace dependencies were updated
26
+ * dependencies
27
+ * @twin.org/immutable-proof-models bumped from 0.0.3-next.0 to 0.0.3-next.1
28
+ * @twin.org/immutable-proof-task bumped from 0.0.3-next.0 to 0.0.3-next.1
29
+
30
+ ## [0.0.2-next.3](https://github.com/twinfoundation/immutable-proof/compare/immutable-proof-service-v0.0.2-next.2...immutable-proof-service-v0.0.2-next.3) (2025-10-09)
31
+
32
+
33
+ ### Features
34
+
35
+ * add validate-locales ([d6a7c07](https://github.com/twinfoundation/immutable-proof/commit/d6a7c0794a1922981a42f56cc24724d7cee727f6))
36
+
37
+
38
+ ### Dependencies
39
+
40
+ * The following workspace dependencies were updated
41
+ * dependencies
42
+ * @twin.org/immutable-proof-models bumped from 0.0.2-next.2 to 0.0.2-next.3
43
+ * @twin.org/immutable-proof-task bumped from 0.0.2-next.2 to 0.0.2-next.3
44
+
3
45
  ## [0.0.2-next.2](https://github.com/twinfoundation/immutable-proof/compare/immutable-proof-service-v0.0.2-next.1...immutable-proof-service-v0.0.2-next.2) (2025-08-29)
4
46
 
5
47