@fedify/fedify 2.0.0-dev.1961 → 2.0.0-dev.211
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 +1 -1
- package/README.md +66 -36
- package/dist/{builder-BrqBKkVi.js → builder-CBUaUcr5.js} +5 -3
- package/dist/{client-BsGzbnV-.d.ts → client-CUTUGgvJ.d.ts} +18 -18
- package/dist/{client-pY7-3icS.js → client-Dg7OfUDA.js} +28 -23
- package/dist/{client-94iWEfQa.d.cts → client-by-PEGAJ.d.cts} +18 -18
- package/dist/compat/mod.cjs +1 -1
- package/dist/compat/mod.d.cts +6 -10
- package/dist/compat/mod.d.ts +6 -10
- package/dist/compat/mod.js +1 -1
- package/dist/compat/transformers.test.js +22 -21
- package/dist/context-Bns6uTJq.js +109 -0
- package/dist/{context-V-XS2_6O.d.ts → context-C7vzWilY.d.ts} +63 -65
- package/dist/{context-PxGADCsD.d.cts → context-CrB9RFy5.d.cts} +63 -65
- package/dist/deno-Ldk6cZ5y.js +117 -0
- package/dist/{testing-DpRy1YTU.js → dist-B5f6a8Tt.js} +90 -110
- package/dist/{docloader-HB61Uc88.js → docloader-CX_8i5G9.js} +3 -3
- package/dist/{esm-DaZiDvFW.js → esm-DGl7uK1r.js} +1 -1
- package/dist/federation/builder.test.js +7 -5
- package/dist/federation/collection.test.js +2 -3
- package/dist/federation/handler.test.js +110 -22
- package/dist/federation/idempotency.test.js +23 -22
- package/dist/federation/inbox.test.js +4 -3
- package/dist/federation/keycache.test.js +4 -4
- package/dist/federation/kv.test.js +56 -3
- package/dist/federation/middleware.test.js +95 -93
- package/dist/federation/mod.cjs +8 -10
- package/dist/federation/mod.d.cts +7 -11
- package/dist/federation/mod.d.ts +7 -11
- package/dist/federation/mod.js +8 -11
- package/dist/federation/mq.test.js +5 -6
- package/dist/federation/negotiation.test.js +2 -3
- package/dist/federation/retry.test.js +2 -3
- package/dist/federation/router.test.js +2 -2
- package/dist/federation/send.test.js +51 -9
- package/dist/{webfinger/handler.test.js → federation/webfinger.test.js} +24 -22
- package/dist/{federation-CRpdnOMS.cjs → federation-B431K2gm.cjs} +22 -0
- package/dist/{federation-jcR8-ZxP.js → federation-BbZwNNWj.js} +28 -6
- package/dist/{http-M8k5mKc0.d.cts → http-ClB3pLcL.d.cts} +1 -1
- package/dist/{http-CUsGQiwU.js → http-CnZ1IHUS.js} +119 -9
- package/dist/{http-BbO0ejuk.d.ts → http-DLBDPal9.d.ts} +1 -1
- package/dist/{http-B2bao4EB.js → http-DNpKjQw7.js} +3 -2
- package/dist/{http-BxgYWxTY.cjs → http-dzRhLC1t.cjs} +132 -16
- package/dist/{inbox-CAojlSWc.js → inbox-DR-Gk02p.js} +2 -1
- package/dist/{key-Dz-KWCap.js → key-C1rxalIW.js} +3 -3
- package/dist/{keycache-Czcf33al.js → keycache-DRxpZ5r9.js} +1 -1
- package/dist/{keys-BN4nelft.js → keys-ZbcByPg9.js} +1 -1
- package/dist/{kv-Bxr0Q87_.d.cts → kv-B4vFhIYL.d.cts} +30 -1
- package/dist/{kv-BKNZ-Tb-.d.ts → kv-CYySNrsn.d.ts} +30 -1
- package/dist/{kv-CRZrzyXm.js → kv-QzKcOQgP.js} +22 -0
- package/dist/{kv-cache-DN9pfMBe.js → kv-cache-BEeqyGER.js} +14 -1
- package/dist/{kv-cache-5j5Pb-V6.cjs → kv-cache-BlS1sett.cjs} +2 -2
- package/dist/{kv-cache-Bq6kUUoG.js → kv-cache-DpIq7Isv.js} +2 -2
- package/dist/{ld-CEJHYq8u.js → ld-Cm6SNnYj.js} +4 -3
- package/dist/middleware-BJ396MAL.cjs +12 -0
- package/dist/{middleware-DW3rJHWy.cjs → middleware-CBBhOrXl.cjs} +210 -194
- package/dist/middleware-CRk4rARo.js +12 -0
- package/dist/middleware-DaemJ_4r.js +26 -0
- package/dist/{middleware-DgrceAHB.js → middleware-DmcjHVg8.js} +162 -165
- package/dist/{middleware-Df9OWALM.js → middleware-JPuzpoIQ.js} +164 -154
- package/dist/{mod-DMpuiKXi.d.cts → mod-0p9zUdzg.d.cts} +6 -6
- package/dist/mod-0qnPv4EC.d.cts +62 -0
- package/dist/{mod-DgxG-byT.d.cts → mod-BrS8tiad.d.cts} +2 -2
- package/dist/mod-C3SOvTD1.d.ts +64 -0
- package/dist/{mod-BoRKfJPE.d.cts → mod-D6pS5_xJ.d.cts} +4 -4
- package/dist/{mod-D5Z2tISD.d.ts → mod-jOa7W503.d.ts} +2 -2
- package/dist/{mod-Cdo6SYlJ.d.ts → mod-waqu-BL_.d.ts} +4 -4
- package/dist/{mod-aAE2wOWV.d.ts → mod-xc20HhMD.d.ts} +6 -6
- package/dist/mod.cjs +11 -93
- package/dist/mod.d.cts +11 -15
- package/dist/mod.d.ts +11 -15
- package/dist/mod.js +11 -15
- package/dist/nodeinfo/client.test.js +3 -4
- package/dist/nodeinfo/handler.test.js +22 -21
- package/dist/nodeinfo/mod.cjs +2 -2
- package/dist/nodeinfo/mod.d.cts +2 -2
- package/dist/nodeinfo/mod.d.ts +2 -2
- package/dist/nodeinfo/mod.js +2 -2
- package/dist/nodeinfo/types.test.js +2 -3
- package/dist/otel/exporter.test.js +893 -0
- package/dist/otel/mod.cjs +256 -0
- package/dist/otel/mod.d.cts +230 -0
- package/dist/otel/mod.d.ts +232 -0
- package/dist/otel/mod.js +255 -0
- package/dist/{owner-kQRGVXG1.d.ts → owner-BgI8C-VY.d.ts} +1 -2
- package/dist/{owner-B4HbyP8s.d.cts → owner-C-zfmVAD.d.cts} +1 -2
- package/dist/{owner-JwI-WzF-.js → owner-D-ZwLwaI.js} +44 -8
- package/dist/{proof-Dhqndmfg.js → proof-B-5l6HNZ.js} +3 -2
- package/dist/{proof-CObJuclI.cjs → proof-C2oMTHcU.cjs} +63 -28
- package/dist/{proof-xH0V1mdD.js → proof-lN5nVUla.js} +46 -11
- package/dist/router-D9eI0s4b.js +118 -0
- package/dist/{send-1o7D-GGL.js → send-D0AlkVEU.js} +9 -4
- package/dist/sig/http.test.js +6 -7
- package/dist/sig/key.test.js +5 -5
- package/dist/sig/ld.test.js +6 -6
- package/dist/sig/mod.cjs +3 -5
- package/dist/sig/mod.d.cts +3 -5
- package/dist/sig/mod.d.ts +3 -5
- package/dist/sig/mod.js +3 -5
- package/dist/sig/owner.test.js +29 -6
- package/dist/sig/proof.test.js +6 -6
- package/dist/testing/mod.d.ts +70 -6999
- package/dist/testing/mod.js +4 -3
- package/dist/{transformers-CoBS-oFG.cjs → transformers-BjBg6Lag.cjs} +2 -2
- package/dist/{transformers-BFT6d7J5.js → transformers-N_ip_y4P.js} +2 -2
- package/dist/{types-BtUjyi5y.js → types-8l28uC8o.js} +30 -25
- package/dist/{types-CWgzGaqk.cjs → types-B6z6CqIz.cjs} +30 -25
- package/dist/{types-C2XVl6gj.js → types-CPz01LGH.js} +3 -3
- package/dist/utils/docloader.test.js +7 -8
- package/dist/utils/kv-cache.test.js +5 -3
- package/dist/utils/mod.cjs +3 -5
- package/dist/utils/mod.d.cts +3 -4
- package/dist/utils/mod.d.ts +3 -4
- package/dist/utils/mod.js +3 -5
- package/package.json +24 -35
- package/dist/actor-DhgrrgXz.cjs +0 -42079
- package/dist/actor-DiKHxw_H.js +0 -41647
- package/dist/actor-DqFajh9s.d.ts +0 -130
- package/dist/actor-Kqyoic-M.js +0 -146
- package/dist/actor-f2NtjyCg.d.cts +0 -128
- package/dist/fixtures/activitypub.academy/users/brauca_darradiul.json +0 -83
- package/dist/fixtures/example.com/announce.json +0 -6
- package/dist/fixtures/example.com/collection.json +0 -19
- package/dist/fixtures/example.com/create.json +0 -6
- package/dist/fixtures/example.com/cross-origin-actor.json +0 -6
- package/dist/fixtures/example.com/hong-gildong.json +0 -11
- package/dist/fixtures/example.com/invite.json +0 -7
- package/dist/fixtures/example.com/key.json +0 -7
- package/dist/fixtures/example.com/key2.json +0 -6
- package/dist/fixtures/example.com/object.json +0 -6
- package/dist/fixtures/example.com/orderedcollectionpage.json +0 -24
- package/dist/fixtures/example.com/paged/a.json +0 -13
- package/dist/fixtures/example.com/paged/b.json +0 -16
- package/dist/fixtures/example.com/paged-collection.json +0 -6
- package/dist/fixtures/example.com/person.json +0 -22
- package/dist/fixtures/example.com/person2.json +0 -40
- package/dist/fixtures/example.com/test.json +0 -5
- package/dist/fixtures/example.com/users/handle.json +0 -16
- package/dist/fixtures/example.com/wrong-type.json +0 -3
- package/dist/fixtures/media.example.com/avatars/test-avatar.jpg.json +0 -6
- package/dist/fixtures/oeee.cafe/ap/users/3609fd4e-d51d-4db8-9f04-4189815864dd.json +0 -24
- package/dist/fixtures/remote.domain/users/bob.json +0 -20
- package/dist/fixtures/server.example/users/alice.json +0 -20
- package/dist/fixtures/w3id.org/identity/v1.json +0 -152
- package/dist/fixtures/w3id.org/security/data-integrity/v1.json +0 -74
- package/dist/fixtures/w3id.org/security/multikey/v1.json +0 -35
- package/dist/fixtures/w3id.org/security/v1.json +0 -50
- package/dist/fixtures/wizard.casa/users/hongminhee.json +0 -69
- package/dist/fixtures/www.w3.org/ns/activitystreams.json +0 -379
- package/dist/fixtures/www.w3.org/ns/did/v1.json +0 -58
- package/dist/lookup-D8hvtZHY.js +0 -42178
- package/dist/lookup-_Hap2IXS.cjs +0 -265
- package/dist/lookup-gMu_9ZKY.js +0 -253
- package/dist/middleware-19QFZj7b.js +0 -26
- package/dist/middleware-BbbcXY4w.cjs +0 -15
- package/dist/middleware-CSTK543z.js +0 -15
- package/dist/mod-BlVovdcy.d.ts +0 -309
- package/dist/mod-BxRCHTz-.d.cts +0 -307
- package/dist/mod-C58MZ7Wx.d.cts +0 -113
- package/dist/mod-CcDPcLJW.d.cts +0 -1
- package/dist/mod-Ds0mpFZU.d.ts +0 -115
- package/dist/mod-bjzj5QIb.d.ts +0 -2
- package/dist/src/vocab/accept.yaml +0 -15
- package/dist/src/vocab/activity.yaml +0 -98
- package/dist/src/vocab/add.yaml +0 -16
- package/dist/src/vocab/announce.yaml +0 -30
- package/dist/src/vocab/application.yaml +0 -324
- package/dist/src/vocab/arrive.yaml +0 -15
- package/dist/src/vocab/article.yaml +0 -46
- package/dist/src/vocab/audio.yaml +0 -11
- package/dist/src/vocab/block.yaml +0 -16
- package/dist/src/vocab/chatmessage.yaml +0 -50
- package/dist/src/vocab/collection.yaml +0 -154
- package/dist/src/vocab/collectionpage.yaml +0 -55
- package/dist/src/vocab/create.yaml +0 -28
- package/dist/src/vocab/dataintegrityproof.yaml +0 -56
- package/dist/src/vocab/delete.yaml +0 -27
- package/dist/src/vocab/didservice.yaml +0 -22
- package/dist/src/vocab/dislike.yaml +0 -14
- package/dist/src/vocab/document.yaml +0 -31
- package/dist/src/vocab/emoji.yaml +0 -12
- package/dist/src/vocab/emojireact.yaml +0 -17
- package/dist/src/vocab/endpoints.yaml +0 -85
- package/dist/src/vocab/event.yaml +0 -11
- package/dist/src/vocab/export.yaml +0 -9
- package/dist/src/vocab/flag.yaml +0 -15
- package/dist/src/vocab/follow.yaml +0 -19
- package/dist/src/vocab/group.yaml +0 -324
- package/dist/src/vocab/hashtag.yaml +0 -14
- package/dist/src/vocab/ignore.yaml +0 -14
- package/dist/src/vocab/image.yaml +0 -9
- package/dist/src/vocab/intransitiveactivity.yaml +0 -15
- package/dist/src/vocab/invite.yaml +0 -14
- package/dist/src/vocab/join.yaml +0 -14
- package/dist/src/vocab/key.yaml +0 -28
- package/dist/src/vocab/leave.yaml +0 -14
- package/dist/src/vocab/like.yaml +0 -16
- package/dist/src/vocab/link.yaml +0 -101
- package/dist/src/vocab/listen.yaml +0 -12
- package/dist/src/vocab/mention.yaml +0 -9
- package/dist/src/vocab/move.yaml +0 -15
- package/dist/src/vocab/multikey.yaml +0 -36
- package/dist/src/vocab/note.yaml +0 -48
- package/dist/src/vocab/object.yaml +0 -404
- package/dist/src/vocab/offer.yaml +0 -15
- package/dist/src/vocab/orderedcollection.yaml +0 -39
- package/dist/src/vocab/orderedcollectionpage.yaml +0 -50
- package/dist/src/vocab/organization.yaml +0 -324
- package/dist/src/vocab/page.yaml +0 -11
- package/dist/src/vocab/person.yaml +0 -324
- package/dist/src/vocab/place.yaml +0 -75
- package/dist/src/vocab/profile.yaml +0 -26
- package/dist/src/vocab/propertyvalue.yaml +0 -32
- package/dist/src/vocab/question.yaml +0 -103
- package/dist/src/vocab/read.yaml +0 -13
- package/dist/src/vocab/reject.yaml +0 -14
- package/dist/src/vocab/relationship.yaml +0 -52
- package/dist/src/vocab/remove.yaml +0 -14
- package/dist/src/vocab/service.yaml +0 -324
- package/dist/src/vocab/source.yaml +0 -26
- package/dist/src/vocab/tentativeaccept.yaml +0 -14
- package/dist/src/vocab/tentativereject.yaml +0 -14
- package/dist/src/vocab/tombstone.yaml +0 -24
- package/dist/src/vocab/travel.yaml +0 -16
- package/dist/src/vocab/undo.yaml +0 -26
- package/dist/src/vocab/update.yaml +0 -58
- package/dist/src/vocab/video.yaml +0 -11
- package/dist/src/vocab/view.yaml +0 -13
- package/dist/testing/docloader.test.js +0 -22
- package/dist/vocab/actor.test.js +0 -5963
- package/dist/vocab/lookup.test.d.ts +0 -3
- package/dist/vocab/lookup.test.js +0 -454
- package/dist/vocab/mod.cjs +0 -86
- package/dist/vocab/mod.d.cts +0 -4
- package/dist/vocab/mod.d.ts +0 -6
- package/dist/vocab/mod.js +0 -9
- package/dist/vocab/type.test.d.ts +0 -3
- package/dist/vocab/type.test.js +0 -24
- package/dist/vocab/vocab.test.d.ts +0 -3
- package/dist/vocab/vocab.test.js +0 -9397
- package/dist/vocab-BCWe1Ih5.d.ts +0 -14905
- package/dist/vocab-CAwj263k.js +0 -255
- package/dist/vocab-CeDBzu-f.d.cts +0 -14903
- package/dist/vocab-DgHGCFcw.cjs +0 -291
- package/dist/webfinger/handler.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.d.ts +0 -3
- package/dist/webfinger/lookup.test.js +0 -193
- package/dist/webfinger/mod.cjs +0 -8
- package/dist/webfinger/mod.d.cts +0 -2
- package/dist/webfinger/mod.d.ts +0 -4
- package/dist/webfinger/mod.js +0 -8
- package/dist/webfinger-C72Y8lrh.js +0 -4
- package/dist/webfinger-vAtLmxOF.cjs +0 -4
- /package/dist/{collection-BzWsN9pB.js → collection-CcnIw1qY.js} +0 -0
- /package/dist/{testing/docloader.test.d.ts → federation/webfinger.test.d.ts} +0 -0
- /package/dist/{mod-CVgZgliM.d.ts → mod-1E3W847c.d.ts} +0 -0
- /package/dist/{mod-B-hUPT2N.d.cts → mod-C81L6_lQ.d.cts} +0 -0
- /package/dist/{negotiation-C4nFufNk.js → negotiation-5NPJL6zp.js} +0 -0
- /package/dist/{nodeinfo-BnthBobC.js → nodeinfo-BlLsRSiT.js} +0 -0
- /package/dist/{nodeinfo-CdN0rEnZ.cjs → nodeinfo-DuMYTpbZ.cjs} +0 -0
- /package/dist/{vocab/actor.test.d.ts → otel/exporter.test.d.ts} +0 -0
- /package/dist/{retry-CfF8Gn4d.js → retry-D4GJ670a.js} +0 -0
- /package/dist/{sig-C34-oHBl.js → sig-CwuONEzF.js} +0 -0
- /package/dist/{sig-YYj5tCnr.cjs → sig-DeXX2xnj.cjs} +0 -0
- /package/dist/{utils-DyRU1gdZ.cjs → utils-Db0ZmjcD.cjs} +0 -0
- /package/dist/{utils-D-Va7aXC.js → utils-Wranxuoe.js} +0 -0
package/dist/otel/mod.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
|
|
2
|
+
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
+
import { URLPattern } from "urlpattern-polyfill";
|
|
4
|
+
|
|
5
|
+
import { getLogger } from "@logtape/logtape";
|
|
6
|
+
import { ExportResultCode } from "@opentelemetry/core";
|
|
7
|
+
|
|
8
|
+
//#region src/otel/exporter.ts
|
|
9
|
+
/**
|
|
10
|
+
* A SpanExporter that persists ActivityPub activity traces to a
|
|
11
|
+
* {@link KvStore}. This enables distributed tracing across multiple
|
|
12
|
+
* nodes in a Fedify deployment.
|
|
13
|
+
*
|
|
14
|
+
* The exporter captures activity data from OpenTelemetry span events
|
|
15
|
+
* (`activitypub.activity.received` and `activitypub.activity.sent`)
|
|
16
|
+
* and stores them in the KvStore with trace context preserved.
|
|
17
|
+
*
|
|
18
|
+
* @example Basic usage with MemoryKvStore
|
|
19
|
+
* ```typescript ignore
|
|
20
|
+
* import { MemoryKvStore } from "@fedify/fedify";
|
|
21
|
+
* import { FedifySpanExporter } from "@fedify/fedify/otel";
|
|
22
|
+
* import {
|
|
23
|
+
* BasicTracerProvider,
|
|
24
|
+
* SimpleSpanProcessor,
|
|
25
|
+
* } from "@opentelemetry/sdk-trace-base";
|
|
26
|
+
*
|
|
27
|
+
* const kv = new MemoryKvStore();
|
|
28
|
+
* const exporter = new FedifySpanExporter(kv, {
|
|
29
|
+
* ttl: Temporal.Duration.from({ hours: 1 }),
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const provider = new BasicTracerProvider({
|
|
33
|
+
* spanProcessors: [new SimpleSpanProcessor(exporter)],
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example Querying stored traces
|
|
38
|
+
* ```typescript ignore
|
|
39
|
+
* import { MemoryKvStore } from "@fedify/fedify";
|
|
40
|
+
* import { FedifySpanExporter } from "@fedify/fedify/otel";
|
|
41
|
+
*
|
|
42
|
+
* const kv = new MemoryKvStore();
|
|
43
|
+
* const exporter = new FedifySpanExporter(kv);
|
|
44
|
+
* const traceId = "abc123";
|
|
45
|
+
*
|
|
46
|
+
* // Get all activities for a specific trace
|
|
47
|
+
* const activities = await exporter.getActivitiesByTraceId(traceId);
|
|
48
|
+
*
|
|
49
|
+
* // Get recent traces
|
|
50
|
+
* const recentTraces = await exporter.getRecentTraces({ limit: 100 });
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @since 1.10.0
|
|
54
|
+
*/
|
|
55
|
+
var FedifySpanExporter = class {
|
|
56
|
+
#kv;
|
|
57
|
+
#ttl;
|
|
58
|
+
#keyPrefix;
|
|
59
|
+
/**
|
|
60
|
+
* Creates a new FedifySpanExporter.
|
|
61
|
+
*
|
|
62
|
+
* @param kv The KvStore to persist trace data to.
|
|
63
|
+
* @param options Configuration options.
|
|
64
|
+
*/
|
|
65
|
+
constructor(kv, options) {
|
|
66
|
+
this.#kv = kv;
|
|
67
|
+
this.#ttl = options?.ttl;
|
|
68
|
+
this.#keyPrefix = options?.keyPrefix ?? ["fedify", "traces"];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Exports spans to the KvStore.
|
|
72
|
+
*
|
|
73
|
+
* @param spans The spans to export.
|
|
74
|
+
* @param resultCallback Callback to invoke with the export result.
|
|
75
|
+
*/
|
|
76
|
+
export(spans, resultCallback) {
|
|
77
|
+
this.#exportAsync(spans).then(() => resultCallback({ code: ExportResultCode.SUCCESS })).catch((error) => {
|
|
78
|
+
getLogger([
|
|
79
|
+
"fedify",
|
|
80
|
+
"otel",
|
|
81
|
+
"exporter"
|
|
82
|
+
]).error("Failed to export spans to KvStore: {error}", { error });
|
|
83
|
+
resultCallback({ code: ExportResultCode.FAILED });
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async #exportAsync(spans) {
|
|
87
|
+
const storeOperations = [];
|
|
88
|
+
for (const span of spans) {
|
|
89
|
+
const records = this.#extractRecords(span);
|
|
90
|
+
for (const record of records) storeOperations.push(this.#storeRecord(record));
|
|
91
|
+
}
|
|
92
|
+
const results = await Promise.allSettled(storeOperations);
|
|
93
|
+
const rejected = results.filter((r) => r.status === "rejected");
|
|
94
|
+
if (rejected.length > 0) throw new AggregateError(rejected.map((r) => r.reason), "Failed to store one or more trace activity records.");
|
|
95
|
+
}
|
|
96
|
+
#extractRecords(span) {
|
|
97
|
+
const records = [];
|
|
98
|
+
const spanContext = span.spanContext();
|
|
99
|
+
const traceId = spanContext.traceId;
|
|
100
|
+
const spanId = spanContext.spanId;
|
|
101
|
+
const parentSpanId = span.parentSpanContext?.spanId;
|
|
102
|
+
for (const event of span.events) if (event.name === "activitypub.activity.received") {
|
|
103
|
+
const record = this.#extractInboundRecord(event, traceId, spanId, parentSpanId);
|
|
104
|
+
if (record != null) records.push(record);
|
|
105
|
+
} else if (event.name === "activitypub.activity.sent") {
|
|
106
|
+
const record = this.#extractOutboundRecord(event, traceId, spanId, parentSpanId);
|
|
107
|
+
if (record != null) records.push(record);
|
|
108
|
+
}
|
|
109
|
+
return records;
|
|
110
|
+
}
|
|
111
|
+
#extractInboundRecord(event, traceId, spanId, parentSpanId) {
|
|
112
|
+
const attrs = event.attributes;
|
|
113
|
+
if (attrs == null) return null;
|
|
114
|
+
const activityJson = attrs["activitypub.activity.json"];
|
|
115
|
+
if (typeof activityJson !== "string") return null;
|
|
116
|
+
let activityType = "Unknown";
|
|
117
|
+
let activityId;
|
|
118
|
+
let actorId;
|
|
119
|
+
try {
|
|
120
|
+
const activity = JSON.parse(activityJson);
|
|
121
|
+
activityType = activity.type ?? "Unknown";
|
|
122
|
+
activityId = activity.id;
|
|
123
|
+
if (typeof activity.actor === "string") actorId = activity.actor;
|
|
124
|
+
else if (activity.actor != null && typeof activity.actor.id === "string") actorId = activity.actor.id;
|
|
125
|
+
} catch {}
|
|
126
|
+
const verified = attrs["activitypub.activity.verified"];
|
|
127
|
+
const httpSigVerified = attrs["http_signatures.verified"];
|
|
128
|
+
const httpSigKeyId = attrs["http_signatures.key_id"];
|
|
129
|
+
const ldSigVerified = attrs["ld_signatures.verified"];
|
|
130
|
+
let signatureDetails;
|
|
131
|
+
if (typeof httpSigVerified === "boolean" || typeof ldSigVerified === "boolean") signatureDetails = {
|
|
132
|
+
httpSignaturesVerified: httpSigVerified === true,
|
|
133
|
+
httpSignaturesKeyId: typeof httpSigKeyId === "string" && httpSigKeyId !== "" ? httpSigKeyId : void 0,
|
|
134
|
+
ldSignaturesVerified: ldSigVerified === true
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
traceId,
|
|
138
|
+
spanId,
|
|
139
|
+
parentSpanId,
|
|
140
|
+
direction: "inbound",
|
|
141
|
+
activityType,
|
|
142
|
+
activityId,
|
|
143
|
+
actorId,
|
|
144
|
+
activityJson,
|
|
145
|
+
verified: typeof verified === "boolean" ? verified : void 0,
|
|
146
|
+
signatureDetails,
|
|
147
|
+
timestamp: (/* @__PURE__ */ new Date(event.time[0] * 1e3 + event.time[1] / 1e6)).toISOString()
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
#extractOutboundRecord(event, traceId, spanId, parentSpanId) {
|
|
151
|
+
const attrs = event.attributes;
|
|
152
|
+
if (attrs == null) return null;
|
|
153
|
+
const activityJson = attrs["activitypub.activity.json"];
|
|
154
|
+
if (typeof activityJson !== "string") return null;
|
|
155
|
+
let activityType = "Unknown";
|
|
156
|
+
let activityId;
|
|
157
|
+
let actorId;
|
|
158
|
+
try {
|
|
159
|
+
const activity = JSON.parse(activityJson);
|
|
160
|
+
activityType = activity.type ?? "Unknown";
|
|
161
|
+
activityId = activity.id;
|
|
162
|
+
if (typeof activity.actor === "string") actorId = activity.actor;
|
|
163
|
+
else if (activity.actor != null && typeof activity.actor.id === "string") actorId = activity.actor.id;
|
|
164
|
+
} catch {}
|
|
165
|
+
const inboxUrl = attrs["activitypub.inbox.url"];
|
|
166
|
+
const explicitActivityId = attrs["activitypub.activity.id"];
|
|
167
|
+
return {
|
|
168
|
+
traceId,
|
|
169
|
+
spanId,
|
|
170
|
+
parentSpanId,
|
|
171
|
+
direction: "outbound",
|
|
172
|
+
activityType,
|
|
173
|
+
activityId: activityId ?? (typeof explicitActivityId === "string" && explicitActivityId !== "" ? explicitActivityId : void 0),
|
|
174
|
+
actorId,
|
|
175
|
+
activityJson,
|
|
176
|
+
timestamp: (/* @__PURE__ */ new Date(event.time[0] * 1e3 + event.time[1] / 1e6)).toISOString(),
|
|
177
|
+
inboxUrl: typeof inboxUrl === "string" ? inboxUrl : void 0
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async #storeRecord(record) {
|
|
181
|
+
const options = this.#ttl != null ? { ttl: this.#ttl } : void 0;
|
|
182
|
+
const key = [
|
|
183
|
+
...this.#keyPrefix,
|
|
184
|
+
record.traceId,
|
|
185
|
+
record.spanId
|
|
186
|
+
];
|
|
187
|
+
await this.#kv.set(key, record, options);
|
|
188
|
+
await this.#updateTraceSummary(record, options);
|
|
189
|
+
}
|
|
190
|
+
async #setWithCasRetry(key, transform, options) {
|
|
191
|
+
if (this.#kv.cas != null) for (let attempt = 0; attempt < 3; attempt++) {
|
|
192
|
+
const existing$1 = await this.#kv.get(key);
|
|
193
|
+
const newValue$1 = transform(existing$1);
|
|
194
|
+
if (await this.#kv.cas(key, existing$1, newValue$1, options)) return;
|
|
195
|
+
}
|
|
196
|
+
const existing = await this.#kv.get(key);
|
|
197
|
+
const newValue = transform(existing);
|
|
198
|
+
await this.#kv.set(key, newValue, options);
|
|
199
|
+
}
|
|
200
|
+
async #updateTraceSummary(record, options) {
|
|
201
|
+
const summaryKey = [
|
|
202
|
+
...this.#keyPrefix,
|
|
203
|
+
"_summaries",
|
|
204
|
+
record.traceId
|
|
205
|
+
];
|
|
206
|
+
await this.#setWithCasRetry(summaryKey, (existing) => {
|
|
207
|
+
const activityCount = existing != null ? existing.activityCount + 1 : 1;
|
|
208
|
+
const activityTypes = existing != null ? existing.activityTypes.includes(record.activityType) ? existing.activityTypes : [...existing.activityTypes, record.activityType] : [record.activityType];
|
|
209
|
+
return {
|
|
210
|
+
traceId: existing?.traceId ?? record.traceId,
|
|
211
|
+
timestamp: existing?.timestamp ?? record.timestamp,
|
|
212
|
+
activityCount,
|
|
213
|
+
activityTypes
|
|
214
|
+
};
|
|
215
|
+
}, options);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Gets all activity records for a specific trace ID.
|
|
219
|
+
*
|
|
220
|
+
* @param traceId The trace ID to query.
|
|
221
|
+
* @returns An array of activity records belonging to the trace.
|
|
222
|
+
*/
|
|
223
|
+
async getActivitiesByTraceId(traceId) {
|
|
224
|
+
const prefix = [...this.#keyPrefix, traceId];
|
|
225
|
+
const records = [];
|
|
226
|
+
for await (const entry of this.#kv.list(prefix)) records.push(entry.value);
|
|
227
|
+
return records;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Gets recent traces with summary information.
|
|
231
|
+
*
|
|
232
|
+
* @param options Options for the query.
|
|
233
|
+
* @returns An array of trace summaries.
|
|
234
|
+
*/
|
|
235
|
+
async getRecentTraces(options) {
|
|
236
|
+
const summaryPrefix = [...this.#keyPrefix, "_summaries"];
|
|
237
|
+
const summaries = [];
|
|
238
|
+
for await (const entry of this.#kv.list(summaryPrefix)) summaries.push(entry.value);
|
|
239
|
+
summaries.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
240
|
+
if (options?.limit != null) return summaries.slice(0, options.limit);
|
|
241
|
+
return summaries;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Forces the exporter to flush any buffered data.
|
|
245
|
+
* This is a no-op because we write directly to the KvStore without buffering.
|
|
246
|
+
*/
|
|
247
|
+
async forceFlush() {}
|
|
248
|
+
/**
|
|
249
|
+
* Shuts down the exporter.
|
|
250
|
+
*/
|
|
251
|
+
async shutdown() {}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
export { FedifySpanExporter };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { Activity, CryptographicKey } from "
|
|
4
|
-
import { Actor } from "./actor-DqFajh9s.js";
|
|
3
|
+
import { Activity, Actor, CryptographicKey } from "@fedify/vocab";
|
|
5
4
|
import { TracerProvider } from "@opentelemetry/api";
|
|
6
5
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
7
6
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Activity, CryptographicKey } from "
|
|
2
|
-
import { Actor } from "./actor-f2NtjyCg.cjs";
|
|
1
|
+
import { Activity, Actor, CryptographicKey } from "@fedify/vocab";
|
|
3
2
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
4
3
|
import { TracerProvider } from "@opentelemetry/api";
|
|
5
4
|
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
globalThis.addEventListener = () => {};
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { isActor } from "
|
|
6
|
+
import { deno_default } from "./deno-Ldk6cZ5y.js";
|
|
7
|
+
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
8
8
|
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
9
|
-
import { trace } from "@opentelemetry/api";
|
|
9
|
+
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
10
10
|
|
|
11
11
|
//#region src/sig/owner.ts
|
|
12
12
|
/**
|
|
@@ -17,11 +17,47 @@ import { trace } from "@opentelemetry/api";
|
|
|
17
17
|
* @returns Whether the actor is the owner of the key.
|
|
18
18
|
*/
|
|
19
19
|
async function doesActorOwnKey(activity, key, options) {
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
|
|
21
|
+
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
22
|
+
return await tracer.startActiveSpan("activitypub.verify_key_ownership", {
|
|
23
|
+
kind: SpanKind.INTERNAL,
|
|
24
|
+
attributes: {
|
|
25
|
+
"activitypub.actor.id": activity.actorId?.href ?? "",
|
|
26
|
+
"activitypub.key.id": key.id?.href ?? ""
|
|
27
|
+
}
|
|
28
|
+
}, async (span) => {
|
|
29
|
+
try {
|
|
30
|
+
if (key.ownerId != null) {
|
|
31
|
+
const owns = key.ownerId.href === activity.actorId?.href;
|
|
32
|
+
span.setAttribute("activitypub.key_ownership.verified", owns);
|
|
33
|
+
span.setAttribute("activitypub.key_ownership.method", "owner_id");
|
|
34
|
+
return owns;
|
|
35
|
+
}
|
|
36
|
+
const actor = await activity.getActor(options);
|
|
37
|
+
if (actor == null || !isActor(actor)) {
|
|
38
|
+
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
39
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
for (const publicKeyId of actor.publicKeyIds) if (key.id != null && publicKeyId.href === key.id.href) {
|
|
43
|
+
span.setAttribute("activitypub.key_ownership.verified", true);
|
|
44
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
48
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
49
|
+
return false;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
span.recordException(error);
|
|
52
|
+
span.setStatus({
|
|
53
|
+
code: SpanStatusCode.ERROR,
|
|
54
|
+
message: String(error)
|
|
55
|
+
});
|
|
56
|
+
throw error;
|
|
57
|
+
} finally {
|
|
58
|
+
span.end();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
25
61
|
}
|
|
26
62
|
/**
|
|
27
63
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
globalThis.addEventListener = () => {};
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { fetchKey, validateCryptoKey } from "./key-
|
|
6
|
+
import { deno_default } from "./deno-Ldk6cZ5y.js";
|
|
7
|
+
import { fetchKey, validateCryptoKey } from "./key-C1rxalIW.js";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
|
+
import { Activity, DataIntegrityProof, Multikey, getTypeId } from "@fedify/vocab";
|
|
9
10
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
10
11
|
import { encodeHex } from "byte-encodings/hex";
|
|
11
12
|
import serialize from "json-canon";
|
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
4
4
|
|
|
5
5
|
const require_chunk = require('./chunk-DqRYRqnO.cjs');
|
|
6
|
-
const
|
|
7
|
-
const require_actor = require('./actor-DhgrrgXz.cjs');
|
|
8
|
-
const require_http = require('./http-BxgYWxTY.cjs');
|
|
6
|
+
const require_http = require('./http-dzRhLC1t.cjs');
|
|
9
7
|
const __logtape_logtape = require_chunk.__toESM(require("@logtape/logtape"));
|
|
8
|
+
const __fedify_vocab = require_chunk.__toESM(require("@fedify/vocab"));
|
|
10
9
|
const __opentelemetry_api = require_chunk.__toESM(require("@opentelemetry/api"));
|
|
11
|
-
const jsonld = require_chunk.__toESM(require("jsonld"));
|
|
12
|
-
const __fedify_vocab_runtime = require_chunk.__toESM(require("@fedify/vocab-runtime"));
|
|
13
10
|
const byte_encodings_hex = require_chunk.__toESM(require("byte-encodings/hex"));
|
|
14
11
|
const byte_encodings_base64 = require_chunk.__toESM(require("byte-encodings/base64"));
|
|
12
|
+
const __fedify_vocab_runtime = require_chunk.__toESM(require("@fedify/vocab-runtime"));
|
|
13
|
+
const jsonld = require_chunk.__toESM(require("jsonld"));
|
|
15
14
|
const json_canon = require_chunk.__toESM(require("json-canon"));
|
|
16
15
|
|
|
17
16
|
//#region src/sig/ld.ts
|
|
@@ -82,7 +81,7 @@ async function createSignature(jsonLd, privateKey, keyId, { contextLoader, creat
|
|
|
82
81
|
*/
|
|
83
82
|
async function signJsonLd(jsonLd, privateKey, keyId, options) {
|
|
84
83
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
85
|
-
const tracer = tracerProvider.getTracer(
|
|
84
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
86
85
|
return await tracer.startActiveSpan("ld_signatures.sign", { attributes: { "ld_signatures.key_id": keyId.href } }, async (span) => {
|
|
87
86
|
try {
|
|
88
87
|
const signature = await createSignature(jsonLd, privateKey, keyId, options);
|
|
@@ -151,7 +150,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
151
150
|
});
|
|
152
151
|
return null;
|
|
153
152
|
}
|
|
154
|
-
const { key, cached } = await require_http.fetchKey(new URL(sig.creator),
|
|
153
|
+
const { key, cached } = await require_http.fetchKey(new URL(sig.creator), __fedify_vocab.CryptographicKey, options);
|
|
155
154
|
if (key == null) return null;
|
|
156
155
|
const sigOpts = {
|
|
157
156
|
...sig,
|
|
@@ -192,7 +191,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
192
191
|
keyId: sig.creator,
|
|
193
192
|
...sig
|
|
194
193
|
});
|
|
195
|
-
const { key: key$1 } = await require_http.fetchKey(new URL(sig.creator),
|
|
194
|
+
const { key: key$1 } = await require_http.fetchKey(new URL(sig.creator), __fedify_vocab.CryptographicKey, {
|
|
196
195
|
...options,
|
|
197
196
|
keyCache: {
|
|
198
197
|
get: () => Promise.resolve(void 0),
|
|
@@ -221,19 +220,19 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
221
220
|
*/
|
|
222
221
|
async function verifyJsonLd(jsonLd, options = {}) {
|
|
223
222
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
224
|
-
const tracer = tracerProvider.getTracer(
|
|
223
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
225
224
|
return await tracer.startActiveSpan("ld_signatures.verify", async (span) => {
|
|
226
225
|
try {
|
|
227
|
-
const object = await
|
|
226
|
+
const object = await __fedify_vocab.Object.fromJsonLd(jsonLd, options);
|
|
228
227
|
if (object.id != null) span.setAttribute("activitypub.object.id", object.id.href);
|
|
229
|
-
span.setAttribute("activitypub.object.type",
|
|
228
|
+
span.setAttribute("activitypub.object.type", (0, __fedify_vocab.getTypeId)(object).href);
|
|
230
229
|
if (typeof jsonLd === "object" && jsonLd != null && "signature" in jsonLd && typeof jsonLd.signature === "object" && jsonLd.signature != null) {
|
|
231
230
|
if ("creator" in jsonLd.signature && typeof jsonLd.signature.creator === "string") span.setAttribute("ld_signatures.key_id", jsonLd.signature.creator);
|
|
232
231
|
if ("signatureValue" in jsonLd.signature && typeof jsonLd.signature.signatureValue === "string") span.setAttribute("ld_signatures.signature", jsonLd.signature.signatureValue);
|
|
233
232
|
if ("type" in jsonLd.signature && typeof jsonLd.signature.type === "string") span.setAttribute("ld_signatures.type", jsonLd.signature.type);
|
|
234
233
|
}
|
|
235
234
|
const attributions = new Set(object.attributionIds.map((uri) => uri.href));
|
|
236
|
-
if (object instanceof
|
|
235
|
+
if (object instanceof __fedify_vocab.Activity) for (const uri of object.actorIds) attributions.add(uri.href);
|
|
237
236
|
const key = await verifySignature(jsonLd, options);
|
|
238
237
|
if (key == null) return false;
|
|
239
238
|
if (key.ownerId == null) {
|
|
@@ -277,11 +276,47 @@ async function hashJsonLd(jsonLd, contextLoader) {
|
|
|
277
276
|
* @returns Whether the actor is the owner of the key.
|
|
278
277
|
*/
|
|
279
278
|
async function doesActorOwnKey(activity, key, options) {
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
279
|
+
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
280
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
281
|
+
return await tracer.startActiveSpan("activitypub.verify_key_ownership", {
|
|
282
|
+
kind: __opentelemetry_api.SpanKind.INTERNAL,
|
|
283
|
+
attributes: {
|
|
284
|
+
"activitypub.actor.id": activity.actorId?.href ?? "",
|
|
285
|
+
"activitypub.key.id": key.id?.href ?? ""
|
|
286
|
+
}
|
|
287
|
+
}, async (span) => {
|
|
288
|
+
try {
|
|
289
|
+
if (key.ownerId != null) {
|
|
290
|
+
const owns = key.ownerId.href === activity.actorId?.href;
|
|
291
|
+
span.setAttribute("activitypub.key_ownership.verified", owns);
|
|
292
|
+
span.setAttribute("activitypub.key_ownership.method", "owner_id");
|
|
293
|
+
return owns;
|
|
294
|
+
}
|
|
295
|
+
const actor = await activity.getActor(options);
|
|
296
|
+
if (actor == null || !(0, __fedify_vocab.isActor)(actor)) {
|
|
297
|
+
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
298
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
for (const publicKeyId of actor.publicKeyIds) if (key.id != null && publicKeyId.href === key.id.href) {
|
|
302
|
+
span.setAttribute("activitypub.key_ownership.verified", true);
|
|
303
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
307
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
308
|
+
return false;
|
|
309
|
+
} catch (error) {
|
|
310
|
+
span.recordException(error);
|
|
311
|
+
span.setStatus({
|
|
312
|
+
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
313
|
+
message: String(error)
|
|
314
|
+
});
|
|
315
|
+
throw error;
|
|
316
|
+
} finally {
|
|
317
|
+
span.end();
|
|
318
|
+
}
|
|
319
|
+
});
|
|
285
320
|
}
|
|
286
321
|
/**
|
|
287
322
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
|
@@ -298,7 +333,7 @@ async function getKeyOwner(keyId, options) {
|
|
|
298
333
|
const documentLoader = options.documentLoader ?? (0, __fedify_vocab_runtime.getDocumentLoader)();
|
|
299
334
|
const contextLoader = options.contextLoader ?? (0, __fedify_vocab_runtime.getDocumentLoader)();
|
|
300
335
|
let object;
|
|
301
|
-
if (keyId instanceof
|
|
336
|
+
if (keyId instanceof __fedify_vocab.CryptographicKey) {
|
|
302
337
|
object = keyId;
|
|
303
338
|
if (object.id == null) return null;
|
|
304
339
|
keyId = object.id;
|
|
@@ -311,7 +346,7 @@ async function getKeyOwner(keyId, options) {
|
|
|
311
346
|
return null;
|
|
312
347
|
}
|
|
313
348
|
try {
|
|
314
|
-
object = await
|
|
349
|
+
object = await __fedify_vocab.Object.fromJsonLd(keyDoc, {
|
|
315
350
|
documentLoader,
|
|
316
351
|
contextLoader,
|
|
317
352
|
tracerProvider
|
|
@@ -319,7 +354,7 @@ async function getKeyOwner(keyId, options) {
|
|
|
319
354
|
} catch (e) {
|
|
320
355
|
if (!(e instanceof TypeError)) throw e;
|
|
321
356
|
try {
|
|
322
|
-
object = await
|
|
357
|
+
object = await __fedify_vocab.CryptographicKey.fromJsonLd(keyDoc, {
|
|
323
358
|
documentLoader,
|
|
324
359
|
contextLoader,
|
|
325
360
|
tracerProvider
|
|
@@ -331,14 +366,14 @@ async function getKeyOwner(keyId, options) {
|
|
|
331
366
|
}
|
|
332
367
|
}
|
|
333
368
|
let owner = null;
|
|
334
|
-
if (object instanceof
|
|
369
|
+
if (object instanceof __fedify_vocab.CryptographicKey) {
|
|
335
370
|
if (object.ownerId == null) return null;
|
|
336
371
|
owner = await object.getOwner({
|
|
337
372
|
documentLoader,
|
|
338
373
|
contextLoader,
|
|
339
374
|
tracerProvider
|
|
340
375
|
});
|
|
341
|
-
} else if (
|
|
376
|
+
} else if ((0, __fedify_vocab.isActor)(object)) owner = object;
|
|
342
377
|
else return null;
|
|
343
378
|
if (owner == null) return null;
|
|
344
379
|
for (const kid of owner.publicKeyIds) if (kid.href === keyId.href) return owner;
|
|
@@ -391,7 +426,7 @@ async function createProof(object, privateKey, keyId, { contextLoader, context,
|
|
|
391
426
|
digest.set(new Uint8Array(proofDigest), 0);
|
|
392
427
|
digest.set(new Uint8Array(msgDigest), proofDigest.byteLength);
|
|
393
428
|
const sig = await crypto.subtle.sign("Ed25519", privateKey, digest);
|
|
394
|
-
return new
|
|
429
|
+
return new __fedify_vocab.DataIntegrityProof({
|
|
395
430
|
cryptosuite: "eddsa-jcs-2022",
|
|
396
431
|
verificationMethod: keyId,
|
|
397
432
|
proofPurpose: "assertionMethod",
|
|
@@ -411,8 +446,8 @@ async function createProof(object, privateKey, keyId, { contextLoader, context,
|
|
|
411
446
|
*/
|
|
412
447
|
async function signObject(object, privateKey, keyId, options = {}) {
|
|
413
448
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
414
|
-
const tracer = tracerProvider.getTracer(
|
|
415
|
-
return await tracer.startActiveSpan("object_integrity_proofs.sign", { attributes: { "activitypub.object.type":
|
|
449
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
450
|
+
return await tracer.startActiveSpan("object_integrity_proofs.sign", { attributes: { "activitypub.object.type": (0, __fedify_vocab.getTypeId)(object).href } }, async (span) => {
|
|
416
451
|
try {
|
|
417
452
|
if (object.id != null) span.setAttribute("activitypub.object.id", object.id.href);
|
|
418
453
|
const existingProofs = [];
|
|
@@ -447,7 +482,7 @@ async function signObject(object, privateKey, keyId, options = {}) {
|
|
|
447
482
|
*/
|
|
448
483
|
async function verifyProof(jsonLd, proof, options = {}) {
|
|
449
484
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
450
|
-
const tracer = tracerProvider.getTracer(
|
|
485
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
451
486
|
return await tracer.startActiveSpan("object_integrity_proofs.verify", async (span) => {
|
|
452
487
|
if (span.isRecording()) {
|
|
453
488
|
if (proof.cryptosuite != null) span.setAttribute("object_integrity_proofs.cryptosuite", proof.cryptosuite);
|
|
@@ -471,7 +506,7 @@ async function verifyProof(jsonLd, proof, options = {}) {
|
|
|
471
506
|
}
|
|
472
507
|
async function verifyProofInternal(jsonLd, proof, options) {
|
|
473
508
|
if (typeof jsonLd !== "object" || proof.cryptosuite !== "eddsa-jcs-2022" || proof.verificationMethodId == null || proof.proofPurpose !== "assertionMethod" || proof.proofValue == null || proof.created == null) return null;
|
|
474
|
-
const publicKeyPromise = require_http.fetchKey(proof.verificationMethodId,
|
|
509
|
+
const publicKeyPromise = require_http.fetchKey(proof.verificationMethodId, __fedify_vocab.Multikey, options);
|
|
475
510
|
const proofConfig = {
|
|
476
511
|
"@context": jsonLd["@context"],
|
|
477
512
|
type: "DataIntegrityProof",
|
|
@@ -576,7 +611,7 @@ async function verifyObject(cls, jsonLd, options = {}) {
|
|
|
576
611
|
]);
|
|
577
612
|
const object = await cls.fromJsonLd(jsonLd, options);
|
|
578
613
|
const attributions = new Set(object.attributionIds.map((uri) => uri.href));
|
|
579
|
-
if (object instanceof
|
|
614
|
+
if (object instanceof __fedify_vocab.Activity) for (const uri of object.actorIds) attributions.add(uri.href);
|
|
580
615
|
for await (const proof of object.getProofs(options)) {
|
|
581
616
|
const key = await verifyProof(jsonLd, proof, options);
|
|
582
617
|
if (key === null) return null;
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
|
|
5
|
-
import { deno_default } from "./
|
|
6
|
-
import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, getTypeId, isActor } from "./actor-DiKHxw_H.js";
|
|
7
|
-
import { fetchKey, validateCryptoKey } from "./http-CUsGQiwU.js";
|
|
5
|
+
import { deno_default, fetchKey, validateCryptoKey } from "./http-CnZ1IHUS.js";
|
|
8
6
|
import { getLogger } from "@logtape/logtape";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
7
|
+
import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, getTypeId, isActor } from "@fedify/vocab";
|
|
8
|
+
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
12
9
|
import { encodeHex } from "byte-encodings/hex";
|
|
13
10
|
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
11
|
+
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
12
|
+
import jsonld from "jsonld";
|
|
14
13
|
import serialize from "json-canon";
|
|
15
14
|
|
|
16
15
|
//#region src/sig/ld.ts
|
|
@@ -276,11 +275,47 @@ async function hashJsonLd(jsonLd, contextLoader) {
|
|
|
276
275
|
* @returns Whether the actor is the owner of the key.
|
|
277
276
|
*/
|
|
278
277
|
async function doesActorOwnKey(activity, key, options) {
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
const tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
|
|
279
|
+
const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
|
|
280
|
+
return await tracer.startActiveSpan("activitypub.verify_key_ownership", {
|
|
281
|
+
kind: SpanKind.INTERNAL,
|
|
282
|
+
attributes: {
|
|
283
|
+
"activitypub.actor.id": activity.actorId?.href ?? "",
|
|
284
|
+
"activitypub.key.id": key.id?.href ?? ""
|
|
285
|
+
}
|
|
286
|
+
}, async (span) => {
|
|
287
|
+
try {
|
|
288
|
+
if (key.ownerId != null) {
|
|
289
|
+
const owns = key.ownerId.href === activity.actorId?.href;
|
|
290
|
+
span.setAttribute("activitypub.key_ownership.verified", owns);
|
|
291
|
+
span.setAttribute("activitypub.key_ownership.method", "owner_id");
|
|
292
|
+
return owns;
|
|
293
|
+
}
|
|
294
|
+
const actor = await activity.getActor(options);
|
|
295
|
+
if (actor == null || !isActor(actor)) {
|
|
296
|
+
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
297
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
for (const publicKeyId of actor.publicKeyIds) if (key.id != null && publicKeyId.href === key.id.href) {
|
|
301
|
+
span.setAttribute("activitypub.key_ownership.verified", true);
|
|
302
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
span.setAttribute("activitypub.key_ownership.verified", false);
|
|
306
|
+
span.setAttribute("activitypub.key_ownership.method", "actor_fetch");
|
|
307
|
+
return false;
|
|
308
|
+
} catch (error) {
|
|
309
|
+
span.recordException(error);
|
|
310
|
+
span.setStatus({
|
|
311
|
+
code: SpanStatusCode.ERROR,
|
|
312
|
+
message: String(error)
|
|
313
|
+
});
|
|
314
|
+
throw error;
|
|
315
|
+
} finally {
|
|
316
|
+
span.end();
|
|
317
|
+
}
|
|
318
|
+
});
|
|
284
319
|
}
|
|
285
320
|
/**
|
|
286
321
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|