@fedify/fedify 2.0.0-dev.1690 → 2.0.0-dev.170
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 +70 -34
- package/dist/{assert_rejects-DiIiJbZn.js → assert_rejects-Ce45JcFg.js} +1 -1
- package/dist/{assert_is_error-BPGph1Jx.js → assert_throws-BNXdRGWP.js} +31 -1
- package/dist/{builder-CYOcDUkj.js → builder-_MVsWtsS.js} +9 -8
- package/dist/{client-bgSdkFa2.d.ts → client-CUTUGgvJ.d.ts} +19 -19
- package/dist/{client-CnOdwLLN.js → client-Dg7OfUDA.js} +28 -23
- package/dist/{client-CegPX0Rn.d.cts → client-by-PEGAJ.d.cts} +19 -19
- package/dist/compat/mod.cjs +1 -1
- package/dist/compat/mod.d.cts +6 -12
- package/dist/compat/mod.d.ts +6 -12
- package/dist/compat/mod.js +1 -1
- package/dist/compat/transformers.test.js +19 -18
- package/dist/context-Bns6uTJq.js +109 -0
- package/dist/{context-ByZprN0S.d.ts → context-C7vzWilY.d.ts} +314 -182
- package/dist/{context-C5BsZkDr.d.cts → context-CrB9RFy5.d.cts} +314 -182
- package/dist/deno-DhWON59o.js +117 -0
- package/dist/{testing-BWNCAbL-.js → dist-B5f6a8Tt.js} +90 -111
- package/dist/{authdocloader-Brax1A32.js → docloader-Cni79dmb.js} +17 -8
- package/dist/{esm-DnIzfEj0.js → esm-DGl7uK1r.js} +32 -17
- package/dist/federation/builder.test.js +11 -11
- package/dist/federation/collection.test.js +5 -8
- package/dist/federation/handler.test.js +111 -24
- package/dist/federation/idempotency.test.js +24 -24
- package/dist/federation/inbox.test.js +5 -6
- package/dist/federation/keycache.test.js +4 -5
- package/dist/federation/kv.test.js +60 -9
- package/dist/federation/middleware.test.js +102 -101
- package/dist/federation/mod.cjs +8 -12
- package/dist/federation/mod.d.cts +7 -13
- package/dist/federation/mod.d.ts +7 -13
- package/dist/federation/mod.js +8 -13
- package/dist/federation/mq.test.js +9 -10
- package/dist/federation/negotiation.test.js +5 -8
- package/dist/federation/retry.test.js +2 -4
- package/dist/federation/router.test.js +6 -8
- package/dist/federation/send.test.js +55 -15
- package/dist/{webfinger/handler.test.js → federation/webfinger.test.js} +25 -24
- package/dist/{federation-H2_En3j5.cjs → federation-B431K2gm.cjs} +22 -0
- package/dist/{federation-D1U8YY9t.js → federation-BbZwNNWj.js} +28 -6
- package/dist/{http-C7vbQwbz.cjs → http-7RQPvAkX.cjs} +410 -14
- package/dist/{http-BxbM8sEy.js → http-CZXlv4xU.js} +371 -11
- package/dist/{http-D-e6AFwR.d.cts → http-ClB3pLcL.d.cts} +2 -2
- package/dist/{http-BNOYnVsU.js → http-CwsBL5_A.js} +3 -2
- package/dist/{http-D6Uj2x2y.d.ts → http-DLBDPal9.d.ts} +2 -2
- package/dist/{inbox-BRru9pX3.js → inbox-CukSCwad.js} +2 -1
- package/dist/{key-1KXru8Ug.js → key-DKkHKzvg.js} +3 -2
- package/dist/{keycache-CN61iGVj.js → keycache-DRxpZ5r9.js} +1 -1
- package/dist/{keys-BPdFKgiy.js → keys-ZbcByPg9.js} +2 -1
- package/dist/{kv-63Cil1MD.d.cts → kv-B4vFhIYL.d.cts} +30 -1
- package/dist/{kv-C7sopW2E.d.ts → kv-CYySNrsn.d.ts} +30 -1
- package/dist/{kv-CRZrzyXm.js → kv-QzKcOQgP.js} +22 -0
- package/dist/kv-cache-BEeqyGER.js +107 -0
- package/dist/kv-cache-BVA7CrnS.cjs +134 -0
- package/dist/kv-cache-HDuc4ZaJ.js +122 -0
- package/dist/{ld-Dv8DNNAT.js → ld-CM6OO5ar.js} +4 -2
- package/dist/middleware--i9t8nKh.js +26 -0
- package/dist/middleware-C567nJlD.cjs +12 -0
- package/dist/middleware-D9oWuacw.js +12 -0
- package/dist/{middleware-DY9B2lL8.js → middleware-DXRcwk_y.js} +185 -192
- package/dist/{middleware-BmoOlgc1.cjs → middleware-TufpQUzj.cjs} +251 -241
- package/dist/{middleware-Bz_A2jeJ.js → middleware-eDeNdyRA.js} +195 -191
- package/dist/mod-0p9zUdzg.d.cts +107 -0
- package/dist/mod-0qnPv4EC.d.cts +62 -0
- package/dist/{mod-Djzcw2ry.d.cts → mod-BrS8tiad.d.cts} +3 -3
- package/dist/mod-C3SOvTD1.d.ts +64 -0
- package/dist/{mod-8DMWKtQE.d.cts → mod-D6pS5_xJ.d.cts} +4 -4
- package/dist/{mod-BhUKmBJD.d.ts → mod-jOa7W503.d.ts} +3 -3
- package/dist/{mod-D6hQoxC5.d.ts → mod-waqu-BL_.d.ts} +4 -4
- package/dist/mod-xc20HhMD.d.ts +109 -0
- package/dist/mod.cjs +17 -112
- package/dist/mod.d.cts +11 -17
- package/dist/mod.d.ts +11 -17
- package/dist/mod.js +11 -17
- package/dist/nodeinfo/client.test.js +7 -10
- package/dist/nodeinfo/handler.test.js +23 -23
- package/dist/nodeinfo/mod.cjs +2 -3
- package/dist/nodeinfo/mod.d.cts +2 -4
- package/dist/nodeinfo/mod.d.ts +2 -4
- package/dist/nodeinfo/mod.js +2 -3
- package/dist/nodeinfo/types.test.js +6 -9
- 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-e3FYDhsk.js → owner-BOEfZQv2.js} +45 -8
- package/dist/{owner-hd9lvQcP.d.ts → owner-BgI8C-VY.d.ts} +2 -3
- package/dist/{owner-BN_tO3cY.d.cts → owner-C-zfmVAD.d.cts} +2 -3
- package/dist/{proof-B-eqv0Ug.cjs → proof-CaDQpGJD.cjs} +69 -33
- package/dist/{proof-DfgvA3al.js → proof-iYIDiv8I.js} +47 -11
- package/dist/{proof-6gFMwMNJ.js → proof-iw6KtIyj.js} +3 -2
- package/dist/router-D9eI0s4b.js +118 -0
- package/dist/{send-Tl9NOnmO.js → send-Bn8o0mjW.js} +9 -4
- package/dist/sig/http.test.js +11 -13
- package/dist/sig/key.test.js +9 -11
- package/dist/sig/ld.test.js +8 -10
- package/dist/sig/mod.cjs +7 -11
- package/dist/sig/mod.d.cts +3 -7
- package/dist/sig/mod.d.ts +3 -7
- package/dist/sig/mod.js +3 -7
- package/dist/sig/owner.test.js +33 -12
- package/dist/sig/proof.test.js +13 -14
- package/dist/testing/mod.d.ts +183 -7194
- package/dist/testing/mod.js +4 -4
- 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-DqxyTxOf.js → types-8l28uC8o.js} +31 -26
- package/dist/{types-zqdWZh4O.cjs → types-B6z6CqIz.cjs} +33 -28
- package/dist/{types-BSuWJsOm.js → types-CPz01LGH.js} +3 -3
- package/dist/{runtime/authdocloader.test.js → utils/docloader.test.js} +13 -15
- package/dist/utils/kv-cache.test.js +211 -0
- package/dist/utils/mod.cjs +10 -0
- package/dist/utils/mod.d.cts +4 -0
- package/dist/utils/mod.d.ts +6 -0
- package/dist/utils/mod.js +9 -0
- package/package.json +34 -75
- package/dist/actor-Be0ThtXy.cjs +0 -42609
- package/dist/actor-ChbPLm6n.js +0 -42135
- package/dist/actor-D6K058Tb.d.cts +0 -128
- package/dist/actor-DuCeRiNh.js +0 -146
- package/dist/actor-T6RyhRgk.d.ts +0 -130
- package/dist/assert_throws-BOO88avQ.js +0 -39
- package/dist/authdocloader-CrxhFL8e.js +0 -52
- package/dist/authdocloader-OSn_teLV.cjs +0 -58
- package/dist/denokv-Bv33Xxea.js +0 -57
- package/dist/docloader-CCqXeagZ.cjs +0 -4861
- package/dist/docloader-CxWcuWqQ.d.ts +0 -221
- package/dist/docloader-D-MrRyHl.d.cts +0 -219
- package/dist/docloader-XK3y2jn5.js +0 -4795
- 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/key-B3uag-rz.js +0 -10
- package/dist/key-BiBmb1Yy.cjs +0 -10
- package/dist/key-DK_nfU4I.js +0 -10
- package/dist/key-Z6ceKnZC.cjs +0 -290
- package/dist/key-jyNTxCvK.js +0 -260
- package/dist/lookup-BPviO8ij.js +0 -131
- package/dist/lookup-hnMAAU5r.cjs +0 -137
- package/dist/lookup-pV0JOsuV.js +0 -331
- package/dist/middleware-CI0-zw4U.js +0 -26
- package/dist/middleware-QNK-W-jE.cjs +0 -17
- package/dist/middleware-_vjt6FWU.js +0 -17
- package/dist/mod-CerN_Sza.d.ts +0 -104
- package/dist/mod-Cj1tHXBR.d.cts +0 -102
- package/dist/mod-CxkWO3Mg.d.cts +0 -307
- package/dist/mod-DBzN0aCM.d.ts +0 -115
- package/dist/mod-DlU8ISoa.d.ts +0 -309
- package/dist/mod-FZd39qVq.d.cts +0 -1
- package/dist/mod-g0xFzAP9.d.ts +0 -2
- package/dist/mod-jQ4OODsl.d.cts +0 -113
- package/dist/mq-B7R1Q-M5.d.cts +0 -140
- package/dist/mq-CRGm1e_F.d.ts +0 -143
- package/dist/runtime/docloader.test.js +0 -522
- package/dist/runtime/key.test.js +0 -103
- package/dist/runtime/langstr.test.d.ts +0 -3
- package/dist/runtime/langstr.test.js +0 -39
- package/dist/runtime/link.test.d.ts +0 -3
- package/dist/runtime/link.test.js +0 -61
- package/dist/runtime/mod.cjs +0 -25
- package/dist/runtime/mod.d.cts +0 -6
- package/dist/runtime/mod.d.ts +0 -8
- package/dist/runtime/mod.js +0 -13
- package/dist/runtime/multibase/multibase.test.d.ts +0 -3
- package/dist/runtime/multibase/multibase.test.js +0 -358
- package/dist/runtime/url.test.d.ts +0 -3
- package/dist/runtime/url.test.js +0 -45
- 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 -24
- package/dist/type-C69ZBu7f.js +0 -47010
- package/dist/vocab/actor.test.d.ts +0 -3
- package/dist/vocab/actor.test.js +0 -5965
- package/dist/vocab/lookup.test.d.ts +0 -3
- package/dist/vocab/lookup.test.js +0 -456
- package/dist/vocab/mod.cjs +0 -87
- package/dist/vocab/mod.d.cts +0 -6
- package/dist/vocab/mod.d.ts +0 -8
- package/dist/vocab/mod.js +0 -10
- package/dist/vocab/schema.yaml +0 -247
- package/dist/vocab/type.test.d.ts +0 -3
- package/dist/vocab/type.test.js +0 -25
- package/dist/vocab/vocab.test.d.ts +0 -3
- package/dist/vocab/vocab.test.js +0 -3787
- package/dist/vocab-B39-pFl9.cjs +0 -291
- package/dist/vocab-BI0Ak5lL.d.ts +0 -14924
- package/dist/vocab-BWoeZsME.js +0 -255
- package/dist/vocab-Dw1-yVGg.d.cts +0 -14922
- 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 -195
- package/dist/webfinger/mod.cjs +0 -9
- package/dist/webfinger/mod.d.cts +0 -4
- package/dist/webfinger/mod.d.ts +0 -6
- package/dist/webfinger/mod.js +0 -9
- package/dist/webfinger-BjOEdFPs.cjs +0 -4
- package/dist/webfinger-De_bU0iE.js +0 -4
- package/dist/x/cfworkers.cjs +0 -100
- package/dist/x/cfworkers.d.cts +0 -59
- package/dist/x/cfworkers.d.ts +0 -61
- package/dist/x/cfworkers.js +0 -98
- package/dist/x/cfworkers.test.d.ts +0 -3
- package/dist/x/cfworkers.test.js +0 -179
- package/dist/x/hono.cjs +0 -61
- package/dist/x/hono.d.cts +0 -54
- package/dist/x/hono.d.ts +0 -56
- package/dist/x/hono.js +0 -60
- package/dist/x/sveltekit.cjs +0 -69
- package/dist/x/sveltekit.d.cts +0 -46
- package/dist/x/sveltekit.d.ts +0 -48
- package/dist/x/sveltekit.js +0 -68
- /package/dist/{assert_not_equals-f3m3epl3.js → assert_not_equals-C80BG-_5.js} +0 -0
- /package/dist/{runtime/authdocloader.test.d.ts → federation/webfinger.test.d.ts} +0 -0
- /package/dist/{mod-1pDWKvUL.d.ts → mod-1E3W847c.d.ts} +0 -0
- /package/dist/{mod-C2tOeRkN.d.cts → mod-C81L6_lQ.d.cts} +0 -0
- /package/dist/{nodeinfo-DfycQ8Wf.js → nodeinfo-BlLsRSiT.js} +0 -0
- /package/dist/{nodeinfo-Co9lJrWl.cjs → nodeinfo-DuMYTpbZ.cjs} +0 -0
- /package/dist/{runtime/docloader.test.d.ts → otel/exporter.test.d.ts} +0 -0
- /package/dist/{runtime-DPYEDf-o.js → sig-CwuONEzF.js} +0 -0
- /package/dist/{runtime-C58AJWSv.cjs → sig-DeXX2xnj.cjs} +0 -0
- /package/dist/{std__assert-X-_kMxKM.js → std__assert-DWivtrGR.js} +0 -0
- /package/dist/{testing → utils}/docloader.test.d.ts +0 -0
- /package/dist/{runtime/key.test.d.ts → utils/kv-cache.test.d.ts} +0 -0
- /package/dist/{sig-ByHXzqUi.cjs → utils-Db0ZmjcD.cjs} +0 -0
- /package/dist/{sig-Cj3tk-ig.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 };
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
globalThis.addEventListener = () => {};
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { isActor } from "
|
|
8
|
-
import {
|
|
6
|
+
import { deno_default } from "./deno-DhWON59o.js";
|
|
7
|
+
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
8
|
+
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
9
|
+
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
9
10
|
|
|
10
11
|
//#region src/sig/owner.ts
|
|
11
12
|
/**
|
|
@@ -16,11 +17,47 @@ import { trace } from "@opentelemetry/api";
|
|
|
16
17
|
* @returns Whether the actor is the owner of the key.
|
|
17
18
|
*/
|
|
18
19
|
async function doesActorOwnKey(activity, key, options) {
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
+
});
|
|
24
61
|
}
|
|
25
62
|
/**
|
|
26
63
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import {
|
|
4
|
-
import { Activity, CryptographicKey } from "./vocab-BI0Ak5lL.js";
|
|
5
|
-
import { Actor } from "./actor-T6RyhRgk.js";
|
|
3
|
+
import { Activity, Actor, CryptographicKey } from "@fedify/vocab";
|
|
6
4
|
import { TracerProvider } from "@opentelemetry/api";
|
|
5
|
+
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
7
6
|
|
|
8
7
|
//#region src/sig/owner.d.ts
|
|
9
8
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Actor } from "./actor-D6K058Tb.cjs";
|
|
1
|
+
import { Activity, Actor, CryptographicKey } from "@fedify/vocab";
|
|
2
|
+
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
4
3
|
import { TracerProvider } from "@opentelemetry/api";
|
|
5
4
|
|
|
6
5
|
//#region src/sig/owner.d.ts
|
|
@@ -3,14 +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-Be0ThtXy.cjs');
|
|
8
|
-
const require_key = require('./key-Z6ceKnZC.cjs');
|
|
6
|
+
const require_http = require('./http-7RQPvAkX.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 byte_encodings_base64 = require_chunk.__toESM(require("byte-encodings/base64"));
|
|
13
10
|
const byte_encodings_hex = require_chunk.__toESM(require("byte-encodings/hex"));
|
|
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"));
|
|
14
14
|
const json_canon = require_chunk.__toESM(require("json-canon"));
|
|
15
15
|
|
|
16
16
|
//#region src/sig/ld.ts
|
|
@@ -47,7 +47,7 @@ function attachSignature(jsonLd, signature) {
|
|
|
47
47
|
* @since 1.0.0
|
|
48
48
|
*/
|
|
49
49
|
async function createSignature(jsonLd, privateKey, keyId, { contextLoader, created } = {}) {
|
|
50
|
-
|
|
50
|
+
require_http.validateCryptoKey(privateKey, "private");
|
|
51
51
|
if (privateKey.algorithm.name !== "RSASSA-PKCS1-v1_5") throw new TypeError("Unsupported algorithm: " + privateKey.algorithm.name);
|
|
52
52
|
const options = {
|
|
53
53
|
"@context": "https://w3id.org/identity/v1",
|
|
@@ -81,7 +81,7 @@ async function createSignature(jsonLd, privateKey, keyId, { contextLoader, creat
|
|
|
81
81
|
*/
|
|
82
82
|
async function signJsonLd(jsonLd, privateKey, keyId, options) {
|
|
83
83
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
84
|
-
const tracer = tracerProvider.getTracer(
|
|
84
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
85
85
|
return await tracer.startActiveSpan("ld_signatures.sign", { attributes: { "ld_signatures.key_id": keyId.href } }, async (span) => {
|
|
86
86
|
try {
|
|
87
87
|
const signature = await createSignature(jsonLd, privateKey, keyId, options);
|
|
@@ -150,7 +150,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
150
150
|
});
|
|
151
151
|
return null;
|
|
152
152
|
}
|
|
153
|
-
const { key, cached } = await
|
|
153
|
+
const { key, cached } = await require_http.fetchKey(new URL(sig.creator), __fedify_vocab.CryptographicKey, options);
|
|
154
154
|
if (key == null) return null;
|
|
155
155
|
const sigOpts = {
|
|
156
156
|
...sig,
|
|
@@ -191,7 +191,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
191
191
|
keyId: sig.creator,
|
|
192
192
|
...sig
|
|
193
193
|
});
|
|
194
|
-
const { key: key$1 } = await
|
|
194
|
+
const { key: key$1 } = await require_http.fetchKey(new URL(sig.creator), __fedify_vocab.CryptographicKey, {
|
|
195
195
|
...options,
|
|
196
196
|
keyCache: {
|
|
197
197
|
get: () => Promise.resolve(void 0),
|
|
@@ -220,19 +220,19 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
220
220
|
*/
|
|
221
221
|
async function verifyJsonLd(jsonLd, options = {}) {
|
|
222
222
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
223
|
-
const tracer = tracerProvider.getTracer(
|
|
223
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
224
224
|
return await tracer.startActiveSpan("ld_signatures.verify", async (span) => {
|
|
225
225
|
try {
|
|
226
|
-
const object = await
|
|
226
|
+
const object = await __fedify_vocab.Object.fromJsonLd(jsonLd, options);
|
|
227
227
|
if (object.id != null) span.setAttribute("activitypub.object.id", object.id.href);
|
|
228
|
-
span.setAttribute("activitypub.object.type",
|
|
228
|
+
span.setAttribute("activitypub.object.type", (0, __fedify_vocab.getTypeId)(object).href);
|
|
229
229
|
if (typeof jsonLd === "object" && jsonLd != null && "signature" in jsonLd && typeof jsonLd.signature === "object" && jsonLd.signature != null) {
|
|
230
230
|
if ("creator" in jsonLd.signature && typeof jsonLd.signature.creator === "string") span.setAttribute("ld_signatures.key_id", jsonLd.signature.creator);
|
|
231
231
|
if ("signatureValue" in jsonLd.signature && typeof jsonLd.signature.signatureValue === "string") span.setAttribute("ld_signatures.signature", jsonLd.signature.signatureValue);
|
|
232
232
|
if ("type" in jsonLd.signature && typeof jsonLd.signature.type === "string") span.setAttribute("ld_signatures.type", jsonLd.signature.type);
|
|
233
233
|
}
|
|
234
234
|
const attributions = new Set(object.attributionIds.map((uri) => uri.href));
|
|
235
|
-
if (object instanceof
|
|
235
|
+
if (object instanceof __fedify_vocab.Activity) for (const uri of object.actorIds) attributions.add(uri.href);
|
|
236
236
|
const key = await verifySignature(jsonLd, options);
|
|
237
237
|
if (key == null) return false;
|
|
238
238
|
if (key.ownerId == null) {
|
|
@@ -259,7 +259,7 @@ async function verifyJsonLd(jsonLd, options = {}) {
|
|
|
259
259
|
async function hashJsonLd(jsonLd, contextLoader) {
|
|
260
260
|
const canon = await jsonld.default.canonize(jsonLd, {
|
|
261
261
|
format: "application/n-quads",
|
|
262
|
-
documentLoader: contextLoader ??
|
|
262
|
+
documentLoader: contextLoader ?? (0, __fedify_vocab_runtime.getDocumentLoader)()
|
|
263
263
|
});
|
|
264
264
|
const encoder = new TextEncoder();
|
|
265
265
|
const hash = await crypto.subtle.digest("SHA-256", encoder.encode(canon));
|
|
@@ -276,11 +276,47 @@ async function hashJsonLd(jsonLd, contextLoader) {
|
|
|
276
276
|
* @returns Whether the actor is the owner of the key.
|
|
277
277
|
*/
|
|
278
278
|
async function doesActorOwnKey(activity, key, options) {
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
+
});
|
|
284
320
|
}
|
|
285
321
|
/**
|
|
286
322
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
|
@@ -294,10 +330,10 @@ async function doesActorOwnKey(activity, key, options) {
|
|
|
294
330
|
*/
|
|
295
331
|
async function getKeyOwner(keyId, options) {
|
|
296
332
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
297
|
-
const documentLoader = options.documentLoader ??
|
|
298
|
-
const contextLoader = options.contextLoader ??
|
|
333
|
+
const documentLoader = options.documentLoader ?? (0, __fedify_vocab_runtime.getDocumentLoader)();
|
|
334
|
+
const contextLoader = options.contextLoader ?? (0, __fedify_vocab_runtime.getDocumentLoader)();
|
|
299
335
|
let object;
|
|
300
|
-
if (keyId instanceof
|
|
336
|
+
if (keyId instanceof __fedify_vocab.CryptographicKey) {
|
|
301
337
|
object = keyId;
|
|
302
338
|
if (object.id == null) return null;
|
|
303
339
|
keyId = object.id;
|
|
@@ -310,7 +346,7 @@ async function getKeyOwner(keyId, options) {
|
|
|
310
346
|
return null;
|
|
311
347
|
}
|
|
312
348
|
try {
|
|
313
|
-
object = await
|
|
349
|
+
object = await __fedify_vocab.Object.fromJsonLd(keyDoc, {
|
|
314
350
|
documentLoader,
|
|
315
351
|
contextLoader,
|
|
316
352
|
tracerProvider
|
|
@@ -318,7 +354,7 @@ async function getKeyOwner(keyId, options) {
|
|
|
318
354
|
} catch (e) {
|
|
319
355
|
if (!(e instanceof TypeError)) throw e;
|
|
320
356
|
try {
|
|
321
|
-
object = await
|
|
357
|
+
object = await __fedify_vocab.CryptographicKey.fromJsonLd(keyDoc, {
|
|
322
358
|
documentLoader,
|
|
323
359
|
contextLoader,
|
|
324
360
|
tracerProvider
|
|
@@ -330,14 +366,14 @@ async function getKeyOwner(keyId, options) {
|
|
|
330
366
|
}
|
|
331
367
|
}
|
|
332
368
|
let owner = null;
|
|
333
|
-
if (object instanceof
|
|
369
|
+
if (object instanceof __fedify_vocab.CryptographicKey) {
|
|
334
370
|
if (object.ownerId == null) return null;
|
|
335
371
|
owner = await object.getOwner({
|
|
336
372
|
documentLoader,
|
|
337
373
|
contextLoader,
|
|
338
374
|
tracerProvider
|
|
339
375
|
});
|
|
340
|
-
} else if (
|
|
376
|
+
} else if ((0, __fedify_vocab.isActor)(object)) owner = object;
|
|
341
377
|
else return null;
|
|
342
378
|
if (owner == null) return null;
|
|
343
379
|
for (const kid of owner.publicKeyIds) if (kid.href === keyId.href) return owner;
|
|
@@ -362,7 +398,7 @@ const logger = (0, __logtape_logtape.getLogger)([
|
|
|
362
398
|
* @since 0.10.0
|
|
363
399
|
*/
|
|
364
400
|
async function createProof(object, privateKey, keyId, { contextLoader, context, created } = {}) {
|
|
365
|
-
|
|
401
|
+
require_http.validateCryptoKey(privateKey, "private");
|
|
366
402
|
if (privateKey.algorithm.name !== "Ed25519") throw new TypeError("Unsupported algorithm: " + privateKey.algorithm.name);
|
|
367
403
|
const objectWithoutProofs = object.clone({ proofs: [] });
|
|
368
404
|
const compactMsg = await objectWithoutProofs.toJsonLd({
|
|
@@ -390,7 +426,7 @@ async function createProof(object, privateKey, keyId, { contextLoader, context,
|
|
|
390
426
|
digest.set(new Uint8Array(proofDigest), 0);
|
|
391
427
|
digest.set(new Uint8Array(msgDigest), proofDigest.byteLength);
|
|
392
428
|
const sig = await crypto.subtle.sign("Ed25519", privateKey, digest);
|
|
393
|
-
return new
|
|
429
|
+
return new __fedify_vocab.DataIntegrityProof({
|
|
394
430
|
cryptosuite: "eddsa-jcs-2022",
|
|
395
431
|
verificationMethod: keyId,
|
|
396
432
|
proofPurpose: "assertionMethod",
|
|
@@ -410,8 +446,8 @@ async function createProof(object, privateKey, keyId, { contextLoader, context,
|
|
|
410
446
|
*/
|
|
411
447
|
async function signObject(object, privateKey, keyId, options = {}) {
|
|
412
448
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
413
|
-
const tracer = tracerProvider.getTracer(
|
|
414
|
-
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) => {
|
|
415
451
|
try {
|
|
416
452
|
if (object.id != null) span.setAttribute("activitypub.object.id", object.id.href);
|
|
417
453
|
const existingProofs = [];
|
|
@@ -446,7 +482,7 @@ async function signObject(object, privateKey, keyId, options = {}) {
|
|
|
446
482
|
*/
|
|
447
483
|
async function verifyProof(jsonLd, proof, options = {}) {
|
|
448
484
|
const tracerProvider = options.tracerProvider ?? __opentelemetry_api.trace.getTracerProvider();
|
|
449
|
-
const tracer = tracerProvider.getTracer(
|
|
485
|
+
const tracer = tracerProvider.getTracer(require_http.deno_default.name, require_http.deno_default.version);
|
|
450
486
|
return await tracer.startActiveSpan("object_integrity_proofs.verify", async (span) => {
|
|
451
487
|
if (span.isRecording()) {
|
|
452
488
|
if (proof.cryptosuite != null) span.setAttribute("object_integrity_proofs.cryptosuite", proof.cryptosuite);
|
|
@@ -470,7 +506,7 @@ async function verifyProof(jsonLd, proof, options = {}) {
|
|
|
470
506
|
}
|
|
471
507
|
async function verifyProofInternal(jsonLd, proof, options) {
|
|
472
508
|
if (typeof jsonLd !== "object" || proof.cryptosuite !== "eddsa-jcs-2022" || proof.verificationMethodId == null || proof.proofPurpose !== "assertionMethod" || proof.proofValue == null || proof.created == null) return null;
|
|
473
|
-
const publicKeyPromise =
|
|
509
|
+
const publicKeyPromise = require_http.fetchKey(proof.verificationMethodId, __fedify_vocab.Multikey, options);
|
|
474
510
|
const proofConfig = {
|
|
475
511
|
"@context": jsonLd["@context"],
|
|
476
512
|
type: "DataIntegrityProof",
|
|
@@ -575,7 +611,7 @@ async function verifyObject(cls, jsonLd, options = {}) {
|
|
|
575
611
|
]);
|
|
576
612
|
const object = await cls.fromJsonLd(jsonLd, options);
|
|
577
613
|
const attributions = new Set(object.attributionIds.map((uri) => uri.href));
|
|
578
|
-
if (object instanceof
|
|
614
|
+
if (object instanceof __fedify_vocab.Activity) for (const uri of object.actorIds) attributions.add(uri.href);
|
|
579
615
|
for await (const proof of object.getProofs(options)) {
|
|
580
616
|
const key = await verifyProof(jsonLd, proof, options);
|
|
581
617
|
if (key === null) return null;
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { Temporal } from "@js-temporal/polyfill";
|
|
3
3
|
import { URLPattern } from "urlpattern-polyfill";
|
|
4
4
|
|
|
5
|
-
import { deno_default,
|
|
6
|
-
import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, getTypeId, isActor } from "./actor-ChbPLm6n.js";
|
|
7
|
-
import { fetchKey, validateCryptoKey } from "./key-jyNTxCvK.js";
|
|
5
|
+
import { deno_default, fetchKey, validateCryptoKey } from "./http-CZXlv4xU.js";
|
|
8
6
|
import { getLogger } from "@logtape/logtape";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
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";
|
|
10
|
+
import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
11
|
+
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
12
|
+
import jsonld from "jsonld";
|
|
13
13
|
import serialize from "json-canon";
|
|
14
14
|
|
|
15
15
|
//#region src/sig/ld.ts
|
|
@@ -275,11 +275,47 @@ async function hashJsonLd(jsonLd, contextLoader) {
|
|
|
275
275
|
* @returns Whether the actor is the owner of the key.
|
|
276
276
|
*/
|
|
277
277
|
async function doesActorOwnKey(activity, key, options) {
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
+
});
|
|
283
319
|
}
|
|
284
320
|
/**
|
|
285
321
|
* Gets the actor that owns the specified key. Returns `null` if the key has no
|