@fedify/fedify 1.3.0-dev.564 → 1.3.0-dev.568

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/CHANGES.md CHANGED
@@ -61,6 +61,7 @@ To be released.
61
61
 
62
62
  - Fedify now supports OpenTelemetry for tracing. [[#170]]
63
63
 
64
+ - Added `Context.tracerProvider` property.
64
65
  - Added `CreateFederationOptions.tracerProvider` option.
65
66
  - Added `LookupWebFingerOptions.tracerProvider` option.
66
67
  - Added `LookupObjectOptions.tracerProvider` option.
@@ -68,6 +69,20 @@ To be released.
68
69
  - Added `VerifyRequestOptions.tracerProvider` option.
69
70
  - Added `SignRequestOptions` interface.
70
71
  - Added the optional fourth parameter to `signRequest()` function.
72
+ - Added `VerifyProofOptions.tracerProvider` option.
73
+ - Added `VerifyObjectOptions.tracerProvider` option.
74
+ - Added `SignObjectOptions.tracerProvider` option.
75
+ - Added `VerifySignatureOptions.tracerProvider` option.
76
+ - Added `VerifyJsonLdOptions.tracerProvider` option.
77
+ - Added `SignJsonLdOptions.tracerProvider` option.
78
+ - Added `DoesActorOwnKeyOptions.tracerProvider` option.
79
+ - Added `GetKeyOwnerOptions.tracerProvider` option.
80
+
81
+ - Added `tracerProvider` option to the following Activity Vocabulary APIs:
82
+
83
+ - The second parameters of constructors.
84
+ - The second parameters of `fromJsonLd()` static methods.
85
+ - The second parameters of `get*()` methods.
71
86
 
72
87
  - Added `@fedify/fedify/x/sveltekit` module for integrating with [SvelteKit]
73
88
  hook. [[#171], [#183] by Jiyu Park]
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@fedify/fedify",
3
- "version": "1.3.0-dev.564+dd787d55",
3
+ "version": "1.3.0-dev.568+35cde4e3",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./mod.ts",
@@ -259,6 +259,7 @@ export async function handleInbox(request, { recipient, context, inboxContextFac
259
259
  contextLoader: context.contextLoader,
260
260
  documentLoader: context.documentLoader,
261
261
  keyCache,
262
+ tracerProvider,
262
263
  });
263
264
  const jsonWithoutSig = detachSignature(json);
264
265
  let activity = null;
@@ -273,6 +274,7 @@ export async function handleInbox(request, { recipient, context, inboxContextFac
273
274
  contextLoader: context.contextLoader,
274
275
  documentLoader: context.documentLoader,
275
276
  keyCache,
277
+ tracerProvider,
276
278
  });
277
279
  }
278
280
  catch (error) {
@@ -195,6 +195,7 @@ export class FederationImpl {
195
195
  activityId: message.activityId,
196
196
  inbox: new URL(message.inbox),
197
197
  headers: new Headers(message.headers),
198
+ tracerProvider: this.tracerProvider,
198
199
  });
199
200
  }
200
201
  catch (error) {
@@ -203,6 +204,7 @@ export class FederationImpl {
203
204
  documentLoader: rsaKeyPair == null
204
205
  ? this.documentLoader
205
206
  : this.authenticatedDocumentLoaderFactory(rsaKeyPair),
207
+ tracerProvider: this.tracerProvider,
206
208
  });
207
209
  try {
208
210
  this.onOutboxError?.(error, activity);
@@ -927,6 +929,7 @@ export class FederationImpl {
927
929
  if (privateKey.algorithm.name === "Ed25519") {
928
930
  activity = await signObject(activity, privateKey, keyId, {
929
931
  contextLoader: this.contextLoader,
932
+ tracerProvider: this.tracerProvider,
930
933
  });
931
934
  proofCreated = true;
932
935
  }
@@ -950,6 +953,7 @@ export class FederationImpl {
950
953
  else {
951
954
  jsonLd = await signJsonLd(jsonLd, rsaKey.privateKey, rsaKey.keyId, {
952
955
  contextLoader: this.contextLoader,
956
+ tracerProvider: this.tracerProvider,
953
957
  });
954
958
  }
955
959
  if (!proofCreated) {
@@ -981,6 +985,7 @@ export class FederationImpl {
981
985
  headers: collectionSync == null ? undefined : new Headers({
982
986
  "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox]),
983
987
  }),
988
+ tracerProvider: this.tracerProvider,
984
989
  }));
985
990
  }
986
991
  await Promise.all(promises);
@@ -1297,6 +1302,9 @@ export class ContextImpl {
1297
1302
  get contextLoader() {
1298
1303
  return this.federation.contextLoader;
1299
1304
  }
1305
+ get tracerProvider() {
1306
+ return this.federation.tracerProvider;
1307
+ }
1300
1308
  getNodeInfoUri() {
1301
1309
  const path = this.federation.router.build("nodeInfo", {});
1302
1310
  if (path == null) {
@@ -1634,7 +1642,7 @@ export class ContextImpl {
1634
1642
  documentLoader: options.documentLoader ?? this.documentLoader,
1635
1643
  contextLoader: options.contextLoader ?? this.contextLoader,
1636
1644
  userAgent: options.userAgent ?? this.federation.userAgent,
1637
- tracerProvider: options.tracerProvider ?? this.federation.tracerProvider,
1645
+ tracerProvider: options.tracerProvider ?? this.tracerProvider,
1638
1646
  });
1639
1647
  }
1640
1648
  traverseCollection(collection, options = {}) {
@@ -1801,7 +1809,7 @@ class RequestContextImpl extends ContextImpl {
1801
1809
  return this.#signedKey = await verifyRequest(this.request, {
1802
1810
  ...this,
1803
1811
  timeWindow: this.federation.signatureTimeWindow,
1804
- tracerProvider: this.federation.tracerProvider,
1812
+ tracerProvider: this.tracerProvider,
1805
1813
  });
1806
1814
  }
1807
1815
  #signedKeyOwner = undefined;
@@ -1931,6 +1939,7 @@ export class InboxContextImpl extends ContextImpl {
1931
1939
  activity: this.activity,
1932
1940
  activityId: activityId,
1933
1941
  inbox: new URL(inbox),
1942
+ tracerProvider: this.tracerProvider,
1934
1943
  }));
1935
1944
  }
1936
1945
  await Promise.all(promises);
@@ -30,7 +30,7 @@ export function extractInboxes({ recipients, preferSharedInbox, excludeBaseUris
30
30
  * See also {@link SendActivityParameters}.
31
31
  * @throws {Error} If the activity fails to send.
32
32
  */
33
- export async function sendActivity({ activity, activityId, keys, inbox, headers, }) {
33
+ export async function sendActivity({ activity, activityId, keys, inbox, headers, tracerProvider, }) {
34
34
  const logger = getLogger(["fedify", "federation", "outbox"]);
35
35
  headers = new Headers(headers);
36
36
  headers.set("Content-Type", "application/activity+json");
@@ -59,7 +59,7 @@ export async function sendActivity({ activity, activityId, keys, inbox, headers,
59
59
  });
60
60
  }
61
61
  else {
62
- request = await signRequest(request, rsaKey.privateKey, rsaKey.keyId);
62
+ request = await signRequest(request, rsaKey.privateKey, rsaKey.keyId, { tracerProvider });
63
63
  }
64
64
  let response;
65
65
  try {
package/esm/sig/http.js CHANGED
@@ -29,7 +29,7 @@ export async function signRequest(request, privateKey, keyId, options = {}) {
29
29
  for (const [name, value] of signed.headers) {
30
30
  span.setAttribute(ATTR_HTTP_REQUEST_HEADER(name), value);
31
31
  }
32
- span.setAttribute("httpsignatures.key_id", keyId.href);
32
+ span.setAttribute("http_signatures.key_id", keyId.href);
33
33
  }
34
34
  return signed;
35
35
  }
@@ -62,7 +62,7 @@ async function signRequestInternal(request, privateKey, keyId, span) {
62
62
  const digest = await dntShim.crypto.subtle.digest("SHA-256", body);
63
63
  headers.set("Digest", `SHA-256=${encodeBase64(digest)}`);
64
64
  if (span.isRecording()) {
65
- span.setAttribute("httpsignatures.digest.sha-256", encodeHex(digest));
65
+ span.setAttribute("http_signatures.digest.sha-256", encodeHex(digest));
66
66
  }
67
67
  }
68
68
  if (!headers.has("Date")) {
@@ -80,8 +80,8 @@ async function signRequestInternal(request, privateKey, keyId, span) {
80
80
  const sigHeader = `keyId="${keyId.href}",algorithm="rsa-sha256",headers="${headerNames.join(" ")}",signature="${encodeBase64(signature)}"`;
81
81
  headers.set("Signature", sigHeader);
82
82
  if (span.isRecording()) {
83
- span.setAttribute("httpsignatures.algorithm", "rsa-sha256");
84
- span.setAttribute("httpsignatures.signature", encodeHex(signature));
83
+ span.setAttribute("http_signatures.algorithm", "rsa-sha256");
84
+ span.setAttribute("http_signatures.signature", encodeHex(signature));
85
85
  }
86
86
  return new Request(request, {
87
87
  headers,
@@ -135,7 +135,7 @@ export async function verifyRequest(request, options = {}) {
135
135
  }
136
136
  });
137
137
  }
138
- async function verifyRequestInternal(request, span, { documentLoader, contextLoader, timeWindow, currentTime, keyCache, } = {}) {
138
+ async function verifyRequestInternal(request, span, { documentLoader, contextLoader, timeWindow, currentTime, keyCache, tracerProvider, } = {}) {
139
139
  const logger = getLogger(["fedify", "sig", "http"]);
140
140
  if (request.bodyUsed) {
141
141
  logger.error("Failed to verify; the request body is already consumed.", { url: request.url });
@@ -184,7 +184,7 @@ async function verifyRequestInternal(request, span, { documentLoader, contextLoa
184
184
  return null;
185
185
  }
186
186
  if (span.isRecording()) {
187
- span.setAttribute(`httpsignatures.digest.${algo}`, encodeHex(digest));
187
+ span.setAttribute(`http_signatures.digest.${algo}`, encodeHex(digest));
188
188
  }
189
189
  const expectedDigest = await dntShim.crypto.subtle.digest(supportedHashAlgorithms[algo], body);
190
190
  if (!equals(digest, new Uint8Array(expectedDigest))) {
@@ -235,15 +235,16 @@ async function verifyRequestInternal(request, span, { documentLoader, contextLoa
235
235
  return null;
236
236
  }
237
237
  const { keyId, headers, signature } = sigValues;
238
- span?.setAttribute("httpsignatures.key_id", keyId);
239
- span?.setAttribute("httpsignatures.signature", signature);
238
+ span?.setAttribute("http_signatures.key_id", keyId);
239
+ span?.setAttribute("http_signatures.signature", signature);
240
240
  if ("algorithm" in sigValues) {
241
- span?.setAttribute("httpsignatures.algorithm", sigValues.algorithm);
241
+ span?.setAttribute("http_signatures.algorithm", sigValues.algorithm);
242
242
  }
243
243
  const { key, cached } = await fetchKey(new URL(keyId), CryptographicKey, {
244
244
  documentLoader,
245
245
  contextLoader,
246
246
  keyCache,
247
+ tracerProvider,
247
248
  });
248
249
  if (key == null)
249
250
  return null;
package/esm/sig/key.js CHANGED
@@ -106,7 +106,7 @@ export async function importJwk(jwk, type) {
106
106
  */
107
107
  export async function fetchKey(keyId,
108
108
  // deno-lint-ignore no-explicit-any
109
- cls, { documentLoader, contextLoader, keyCache } = {}) {
109
+ cls, { documentLoader, contextLoader, keyCache, tracerProvider } = {}) {
110
110
  const logger = getLogger(["fedify", "sig", "key"]);
111
111
  const cacheKey = typeof keyId === "string" ? new URL(keyId) : keyId;
112
112
  keyId = typeof keyId === "string" ? keyId : keyId.href;
@@ -140,6 +140,7 @@ cls, { documentLoader, contextLoader, keyCache } = {}) {
140
140
  object = await Object.fromJsonLd(document, {
141
141
  documentLoader,
142
142
  contextLoader,
143
+ tracerProvider,
143
144
  });
144
145
  }
145
146
  catch (e) {
@@ -149,6 +150,7 @@ cls, { documentLoader, contextLoader, keyCache } = {}) {
149
150
  object = await cls.fromJsonLd(document, {
150
151
  documentLoader,
151
152
  contextLoader,
153
+ tracerProvider,
152
154
  });
153
155
  }
154
156
  catch (e) {
@@ -166,8 +168,12 @@ cls, { documentLoader, contextLoader, keyCache } = {}) {
166
168
  else if (isActor(object)) {
167
169
  // @ts-ignore: cls is either CryptographicKey or Multikey
168
170
  const keys = cls === CryptographicKey
169
- ? object.getPublicKeys({ documentLoader, contextLoader })
170
- : object.getAssertionMethods({ documentLoader, contextLoader });
171
+ ? object.getPublicKeys({ documentLoader, contextLoader, tracerProvider })
172
+ : object.getAssertionMethods({
173
+ documentLoader,
174
+ contextLoader,
175
+ tracerProvider,
176
+ });
171
177
  for await (const k of keys) {
172
178
  if (k.id?.href === keyId) {
173
179
  key = k;
package/esm/sig/ld.js CHANGED
@@ -1,10 +1,13 @@
1
1
  import * as dntShim from "../_dnt.shims.js";
2
2
  import { getLogger } from "@logtape/logtape";
3
+ import { SpanStatusCode, trace } from "@opentelemetry/api";
3
4
  import { decodeBase64, encodeBase64 } from "../deps/jsr.io/@std/encoding/1.0.5/base64.js";
4
5
  import { encodeHex } from "../deps/jsr.io/@std/encoding/1.0.5/hex.js";
5
6
  // @ts-ignore TS7016
6
7
  import jsonld from "jsonld";
8
+ import metadata from "../deno.js";
7
9
  import { getDocumentLoader, } from "../runtime/docloader.js";
10
+ import { getTypeId } from "../vocab/type.js";
8
11
  import { Activity, CryptographicKey, Object } from "../vocab/vocab.js";
9
12
  import { fetchKey, validateCryptoKey } from "./key.js";
10
13
  const logger = getLogger(["fedify", "sig", "ld"]);
@@ -70,8 +73,30 @@ export async function createSignature(jsonLd, privateKey, keyId, { contextLoader
70
73
  * @since 1.0.0
71
74
  */
72
75
  export async function signJsonLd(jsonLd, privateKey, keyId, options) {
73
- const signature = await createSignature(jsonLd, privateKey, keyId, options);
74
- return attachSignature(jsonLd, signature);
76
+ const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
77
+ const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
78
+ return await tracer.startActiveSpan("ld_signatures.sign", {
79
+ attributes: { "ld_signatures.key_id": keyId.href },
80
+ }, async (span) => {
81
+ try {
82
+ const signature = await createSignature(jsonLd, privateKey, keyId, options);
83
+ if (span.isRecording()) {
84
+ span.setAttribute("ld_signatures.type", signature.type);
85
+ span.setAttribute("ld_signatures.signature", encodeHex(decodeBase64(signature.signatureValue)));
86
+ }
87
+ return attachSignature(jsonLd, signature);
88
+ }
89
+ catch (error) {
90
+ span.setStatus({
91
+ code: SpanStatusCode.ERROR,
92
+ message: String(error),
93
+ });
94
+ throw error;
95
+ }
96
+ finally {
97
+ span.end();
98
+ }
99
+ });
75
100
  }
76
101
  /**
77
102
  * Checks if the given JSON-LD document has a Linked Data Signature.
@@ -194,26 +219,62 @@ export async function verifySignature(jsonLd, options = {}) {
194
219
  * @returns `true` if the document is authentic; `false` otherwise.
195
220
  */
196
221
  export async function verifyJsonLd(jsonLd, options = {}) {
197
- const object = await Object.fromJsonLd(jsonLd, options);
198
- const attributions = new Set(object.attributionIds.map((uri) => uri.href));
199
- if (object instanceof Activity) {
200
- for (const uri of object.actorIds)
201
- attributions.add(uri.href);
202
- }
203
- const key = await verifySignature(jsonLd, options);
204
- if (key == null)
205
- return false;
206
- if (key.ownerId == null) {
207
- logger.debug("Key {keyId} has no owner.", { keyId: key.id?.href });
208
- return false;
209
- }
210
- attributions.delete(key.ownerId.href);
211
- if (attributions.size > 0) {
212
- logger.debug("Some attributions are not authenticated by the Linked Data Signatures" +
213
- ": {attributions}.", { attributions: [...attributions] });
214
- return false;
215
- }
216
- return true;
222
+ const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
223
+ const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
224
+ return await tracer.startActiveSpan("ld_signatures.verify", async (span) => {
225
+ try {
226
+ const object = await Object.fromJsonLd(jsonLd, options);
227
+ if (object.id != null) {
228
+ span.setAttribute("activitypub.object.id", object.id.href);
229
+ }
230
+ span.setAttribute("activitypub.object.type", getTypeId(object).href);
231
+ if (typeof jsonLd === "object" && jsonLd != null &&
232
+ "signature" in jsonLd && typeof jsonLd.signature === "object" &&
233
+ jsonLd.signature != null) {
234
+ if ("creator" in jsonLd.signature &&
235
+ typeof jsonLd.signature.creator === "string") {
236
+ span.setAttribute("ld_signatures.key_id", jsonLd.signature.creator);
237
+ }
238
+ if ("signatureValue" in jsonLd.signature &&
239
+ typeof jsonLd.signature.signatureValue === "string") {
240
+ span.setAttribute("ld_signatures.signature", jsonLd.signature.signatureValue);
241
+ }
242
+ if ("type" in jsonLd.signature &&
243
+ typeof jsonLd.signature.type === "string") {
244
+ span.setAttribute("ld_signatures.type", jsonLd.signature.type);
245
+ }
246
+ }
247
+ const attributions = new Set(object.attributionIds.map((uri) => uri.href));
248
+ if (object instanceof Activity) {
249
+ for (const uri of object.actorIds)
250
+ attributions.add(uri.href);
251
+ }
252
+ const key = await verifySignature(jsonLd, options);
253
+ if (key == null)
254
+ return false;
255
+ if (key.ownerId == null) {
256
+ logger.debug("Key {keyId} has no owner.", { keyId: key.id?.href });
257
+ return false;
258
+ }
259
+ attributions.delete(key.ownerId.href);
260
+ if (attributions.size > 0) {
261
+ logger.debug("Some attributions are not authenticated by the Linked Data " +
262
+ "Signatures: {attributions}.", { attributions: [...attributions] });
263
+ return false;
264
+ }
265
+ return true;
266
+ }
267
+ catch (error) {
268
+ span.setStatus({
269
+ code: SpanStatusCode.ERROR,
270
+ message: String(error),
271
+ });
272
+ throw error;
273
+ }
274
+ finally {
275
+ span.end();
276
+ }
277
+ });
217
278
  }
218
279
  async function hashJsonLd(jsonLd, contextLoader) {
219
280
  const canon = await jsonld.canonize(jsonLd, {
package/esm/sig/owner.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { trace } from "@opentelemetry/api";
1
2
  import { getDocumentLoader, } from "../runtime/docloader.js";
2
3
  import { isActor } from "../vocab/actor.js";
3
4
  import { CryptographicKey, Object as ASObject, } from "../vocab/vocab.js";
@@ -30,8 +31,10 @@ export async function doesActorOwnKey(activity, key, options) {
30
31
  * @param options Options for getting the key owner.
31
32
  * @returns The actor that owns the key, or `null` if the key has no known
32
33
  * owner.
34
+ * @since 0.7.0
33
35
  */
34
36
  export async function getKeyOwner(keyId, options) {
37
+ const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
35
38
  const documentLoader = options.documentLoader ?? getDocumentLoader();
36
39
  const contextLoader = options.contextLoader ?? getDocumentLoader();
37
40
  let object;
@@ -54,6 +57,7 @@ export async function getKeyOwner(keyId, options) {
54
57
  object = await ASObject.fromJsonLd(keyDoc, {
55
58
  documentLoader,
56
59
  contextLoader,
60
+ tracerProvider,
57
61
  });
58
62
  }
59
63
  catch (e) {
@@ -63,6 +67,7 @@ export async function getKeyOwner(keyId, options) {
63
67
  object = await CryptographicKey.fromJsonLd(keyDoc, {
64
68
  documentLoader,
65
69
  contextLoader,
70
+ tracerProvider,
66
71
  });
67
72
  }
68
73
  catch (e) {
@@ -76,7 +81,11 @@ export async function getKeyOwner(keyId, options) {
76
81
  if (object instanceof CryptographicKey) {
77
82
  if (object.ownerId == null)
78
83
  return null;
79
- owner = await object.getOwner({ documentLoader, contextLoader });
84
+ owner = await object.getOwner({
85
+ documentLoader,
86
+ contextLoader,
87
+ tracerProvider,
88
+ });
80
89
  }
81
90
  else if (isActor(object)) {
82
91
  owner = object;
package/esm/sig/proof.js CHANGED
@@ -1,9 +1,12 @@
1
1
  import * as dntShim from "../_dnt.shims.js";
2
2
  import { getLogger } from "@logtape/logtape";
3
- import { Activity, Multikey } from "../vocab/vocab.js";
3
+ import { SpanStatusCode, trace } from "@opentelemetry/api";
4
+ import { encodeHex } from "../deps/jsr.io/@std/encoding/1.0.5/hex.js";
4
5
  // @ts-ignore: json-canon is not typed
5
6
  import serialize from "json-canon";
6
- import { DataIntegrityProof } from "../vocab/vocab.js";
7
+ import metadata from "../deno.js";
8
+ import { getTypeId } from "../vocab/type.js";
9
+ import { Activity, DataIntegrityProof, Multikey, } from "../vocab/vocab.js";
7
10
  import { fetchKey, validateCryptoKey, } from "./key.js";
8
11
  const logger = getLogger(["fedify", "sig", "proof"]);
9
12
  /**
@@ -67,12 +70,41 @@ export async function createProof(object, privateKey, keyId, { contextLoader, co
67
70
  * @since 0.10.0
68
71
  */
69
72
  export async function signObject(object, privateKey, keyId, options = {}) {
70
- const existingProofs = [];
71
- for await (const proof of object.getProofs(options)) {
72
- existingProofs.push(proof);
73
- }
74
- const proof = await createProof(object, privateKey, keyId, options);
75
- return object.clone({ proofs: [...existingProofs, proof] });
73
+ const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
74
+ const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
75
+ return await tracer.startActiveSpan("object_integrity_proofs.sign", {
76
+ attributes: { "activitypub.object.type": getTypeId(object).href },
77
+ }, async (span) => {
78
+ try {
79
+ if (object.id != null) {
80
+ span.setAttribute("activitypub.object.id", object.id.href);
81
+ }
82
+ const existingProofs = [];
83
+ for await (const proof of object.getProofs(options)) {
84
+ existingProofs.push(proof);
85
+ }
86
+ const proof = await createProof(object, privateKey, keyId, options);
87
+ if (span.isRecording()) {
88
+ if (proof.cryptosuite != null) {
89
+ span.setAttribute("object_integrity_proofs.cryptosuite", proof.cryptosuite);
90
+ }
91
+ if (proof.verificationMethodId != null) {
92
+ span.setAttribute("object_integrity_proofs.key_id", proof.verificationMethodId.href);
93
+ }
94
+ if (proof.proofValue != null) {
95
+ span.setAttribute("object_integrity_proofs.signature", encodeHex(proof.proofValue));
96
+ }
97
+ }
98
+ return object.clone({ proofs: [...existingProofs, proof] });
99
+ }
100
+ catch (error) {
101
+ span.setStatus({ code: SpanStatusCode.ERROR, message: String(error) });
102
+ throw error;
103
+ }
104
+ finally {
105
+ span.end();
106
+ }
107
+ });
76
108
  }
77
109
  /**
78
110
  * Verifies the given proof for the object.
@@ -85,6 +117,39 @@ export async function signObject(object, privateKey, keyId, options = {}) {
85
117
  * @since 0.10.0
86
118
  */
87
119
  export async function verifyProof(jsonLd, proof, options = {}) {
120
+ const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
121
+ const tracer = tracerProvider.getTracer(metadata.name, metadata.version);
122
+ return await tracer.startActiveSpan("object_integrity_proofs.verify", async (span) => {
123
+ if (span.isRecording()) {
124
+ if (proof.cryptosuite != null) {
125
+ span.setAttribute("object_integrity_proofs.cryptosuite", proof.cryptosuite);
126
+ }
127
+ if (proof.verificationMethodId != null) {
128
+ span.setAttribute("object_integrity_proofs.key_id", proof.verificationMethodId.href);
129
+ }
130
+ if (proof.proofValue != null) {
131
+ span.setAttribute("object_integrity_proofs.signature", encodeHex(proof.proofValue));
132
+ }
133
+ }
134
+ try {
135
+ const key = await verifyProofInternal(jsonLd, proof, options);
136
+ if (key == null)
137
+ span.setStatus({ code: SpanStatusCode.ERROR });
138
+ return key;
139
+ }
140
+ catch (error) {
141
+ span.setStatus({
142
+ code: SpanStatusCode.ERROR,
143
+ message: String(error),
144
+ });
145
+ throw error;
146
+ }
147
+ finally {
148
+ span.end();
149
+ }
150
+ });
151
+ }
152
+ async function verifyProofInternal(jsonLd, proof, options) {
88
153
  if (typeof jsonLd !== "object" ||
89
154
  proof.cryptosuite !== "eddsa-jcs-2022" ||
90
155
  proof.verificationMethodId == null ||
@@ -119,6 +119,7 @@ async function lookupObjectInternal(identifier, options = {}) {
119
119
  return await Object.fromJsonLd(document, {
120
120
  documentLoader,
121
121
  contextLoader: options.contextLoader,
122
+ tracerProvider: options.tracerProvider,
122
123
  });
123
124
  }
124
125
  catch (error) {