@fedify/fedify 2.3.0-dev.994 → 2.3.0-pr.809.37

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.
Files changed (138) hide show
  1. package/README.md +16 -7
  2. package/dist/{assert-DikXweDx.mjs → assert-OguE97r2.mjs} +1 -1
  3. package/dist/{assert_instance_of-C4Ri6VuN.mjs → assert_instance_of-DBC5X09g.mjs} +1 -1
  4. package/dist/{assert_not_equals--wG9hV7u.mjs → assert_not_equals-DkVK8oqV.mjs} +1 -1
  5. package/dist/{assert_rejects-B-qJtC9Z.mjs → assert_rejects-DN60FHPX.mjs} +28 -3
  6. package/dist/{assert_strict_equals-Dmjbg-bA.mjs → assert_strict_equals-XEgZAlrj.mjs} +1 -1
  7. package/dist/{assert_throws-4NwKEy2q.mjs → assert_throws-BOkhLGYc.mjs} +1 -1
  8. package/dist/{builder-yAlpiIqP.mjs → builder-Dl5Sdmc9.mjs} +96 -42
  9. package/dist/{chunk-nlSIicah.js → chunk-CRNNMoPX.js} +2 -2
  10. package/dist/circuit-breaker-CSWsyoef.mjs +337 -0
  11. package/dist/{client-z-8dc-e1.d.cts → client-CAM_bQXx.d.cts} +1 -0
  12. package/dist/{client-AtlibPOU.d.ts → client-CSddvgWN.d.ts} +1 -2
  13. package/dist/compat/mod.d.cts +2 -1
  14. package/dist/compat/mod.d.ts +2 -3
  15. package/dist/compat/mod.js +3 -3
  16. package/dist/compat/outgoing-jsonld.test.mjs +4 -4
  17. package/dist/compat/public-audience.test.mjs +4 -4
  18. package/dist/compat/transformers.test.mjs +5 -5
  19. package/dist/{context-BzH2-ajs.d.ts → context-BBVLF7lx.d.cts} +342 -269
  20. package/dist/{context-DJGagtNd.d.cts → context-BU6jSQdo.d.ts} +344 -266
  21. package/dist/{context-Dk_tacqz.mjs → context-DVoTs_wM.mjs} +64 -5
  22. package/dist/{deno-XBVlKnOX.mjs → deno-BID9qTPk.mjs} +1 -1
  23. package/dist/{docloader-DPp-X6gk.mjs → docloader-BYFuVwwi.mjs} +4 -4
  24. package/dist/{esm-DVILvP5e.mjs → esm-vrlUxr60.mjs} +4 -7
  25. package/dist/federation/builder.test.mjs +163 -11
  26. package/dist/federation/circuit-breaker.test.d.mts +2 -0
  27. package/dist/federation/circuit-breaker.test.mjs +446 -0
  28. package/dist/federation/collection.test.mjs +3 -3
  29. package/dist/federation/handler.test.mjs +1770 -29
  30. package/dist/federation/idempotency.test.mjs +5 -5
  31. package/dist/federation/inbox.test.mjs +4 -4
  32. package/dist/federation/keycache.test.mjs +5 -5
  33. package/dist/federation/kv.test.mjs +2 -2
  34. package/dist/federation/metrics.test.d.mts +2 -0
  35. package/dist/federation/metrics.test.mjs +634 -0
  36. package/dist/federation/middleware.test.mjs +4036 -146
  37. package/dist/federation/mod.cjs +195 -14
  38. package/dist/federation/mod.d.cts +6 -4
  39. package/dist/federation/mod.d.ts +6 -6
  40. package/dist/federation/mod.js +192 -14
  41. package/dist/federation/mq.test.mjs +176 -15
  42. package/dist/federation/negotiation.test.mjs +4 -4
  43. package/dist/federation/retry.test.mjs +3 -3
  44. package/dist/federation/router.test.mjs +190 -9
  45. package/dist/federation/send.test.mjs +153 -15
  46. package/dist/federation/temporal.test.d.mts +2 -0
  47. package/dist/federation/temporal.test.mjs +71 -0
  48. package/dist/federation/webfinger.test.mjs +150 -5
  49. package/dist/{http-B4rrzxtg.js → http-B47Jg9iX.js} +994 -64
  50. package/dist/{http-CSlLA54v.mjs → http-CO59u1Yk.mjs} +146 -47
  51. package/dist/{http-BrGqJDXL.cjs → http-CjZwUPiT.cjs} +1099 -61
  52. package/dist/{http-aQzN9Ayi.d.ts → http-VyDTd4G3.d.cts} +15 -3
  53. package/dist/{http-CrGuipxe.d.cts → http-lf8Hsd91.d.ts} +15 -1
  54. package/dist/{key-Bzx--sHD.mjs → key-Dqdlo3mG.mjs} +43 -18
  55. package/dist/{kv-CbLNp3zQ.d.cts → kv-D6hNiMTK.d.ts} +1 -0
  56. package/dist/{kv-cache-DI-Sk7-I.cjs → kv-cache-BQ1-zDKX.cjs} +20 -3
  57. package/dist/{kv-cache-EMIqoIuB.js → kv-cache-Dh2ZH9Gr.js} +20 -3
  58. package/dist/{kv-cache-U__xU4qR.mjs → kv-cache-DhLkLv0P.mjs} +21 -3
  59. package/dist/{kv-GFYnFoOl.d.ts → kv-gJ8LYbxX.d.cts} +1 -3
  60. package/dist/ld-JbCByP5P.mjs +626 -0
  61. package/dist/metrics-ColY3QKj.mjs +815 -0
  62. package/dist/{middleware-zjZ6AFCW.mjs → middleware-Buqzuiaf.mjs} +1 -1
  63. package/dist/{middleware-An4DjES4.cjs → middleware-CWQ3Yi07.cjs} +2318 -623
  64. package/dist/{middleware-K1g6bEkV.mjs → middleware-Cg4EyWsq.mjs} +1639 -373
  65. package/dist/{middleware-nidH7VZH.js → middleware-iAJY2aU-.js} +2260 -556
  66. package/dist/{mod-CR8soWa9.d.ts → mod-B0hW12_O.d.cts} +26 -4
  67. package/dist/mod-C0F6kvgS.d.cts +182 -0
  68. package/dist/{mod-Cr3f-ACa.d.cts → mod-COIAjwRS.d.ts} +26 -2
  69. package/dist/{mod-CMEbIaNh.d.cts → mod-DFvNJcNb.d.ts} +56 -4
  70. package/dist/mod-vPYVoa5n.d.ts +182 -0
  71. package/dist/{mod-CLgIXe9w.d.ts → mod-yvIXFAEi.d.cts} +56 -6
  72. package/dist/mod.cjs +9 -6
  73. package/dist/mod.d.cts +12 -10
  74. package/dist/mod.d.ts +12 -12
  75. package/dist/mod.js +11 -11
  76. package/dist/mq-D-nlpY04.d.ts +208 -0
  77. package/dist/mq-D8uSFzxe.d.cts +208 -0
  78. package/dist/{negotiation-SQvQgUqe.mjs → negotiation-DDstyBvc.mjs} +29 -0
  79. package/dist/nodeinfo/client.test.mjs +4 -4
  80. package/dist/nodeinfo/handler.test.mjs +4 -4
  81. package/dist/nodeinfo/mod.d.cts +2 -1
  82. package/dist/nodeinfo/mod.d.ts +2 -3
  83. package/dist/nodeinfo/mod.js +3 -3
  84. package/dist/nodeinfo/types.test.mjs +3 -3
  85. package/dist/otel/exporter.test.mjs +28 -25
  86. package/dist/otel/mod.cjs +6 -5
  87. package/dist/otel/mod.d.cts +5 -3
  88. package/dist/otel/mod.d.ts +5 -5
  89. package/dist/otel/mod.js +8 -7
  90. package/dist/{outgoing-jsonld-CNmZLixq.mjs → outgoing-jsonld-L_DbOaFe.mjs} +2 -2
  91. package/dist/{owner-C-tqfvxn.mjs → owner-B4LgOmzV.mjs} +2 -2
  92. package/dist/{owner-CptqhsOy.d.cts → owner-CnngXDNJ.d.ts} +2 -1
  93. package/dist/{owner-74ARJ5TL.d.ts → owner-DEvZuyOE.d.cts} +2 -3
  94. package/dist/{proof-BlmRPzrK.mjs → proof-BoSGOq9q.mjs} +26 -8
  95. package/dist/{proof-Bbbwf8_x.js → proof-CzhZuawt.js} +378 -15
  96. package/dist/{proof-BW89QMVB.cjs → proof-DvMI-3vq.cjs} +432 -15
  97. package/dist/runtime/mod.d.cts +1 -0
  98. package/dist/runtime/mod.d.ts +1 -2
  99. package/dist/runtime/mod.js +3 -3
  100. package/dist/{send-05pJLcb6.mjs → send-ByK1Q7DK.mjs} +72 -26
  101. package/dist/sig/http.test.mjs +356 -33
  102. package/dist/sig/key.test.mjs +103 -6
  103. package/dist/sig/ld.test.mjs +696 -7
  104. package/dist/sig/mod.cjs +2 -2
  105. package/dist/sig/mod.d.cts +4 -3
  106. package/dist/sig/mod.d.ts +4 -5
  107. package/dist/sig/mod.js +4 -4
  108. package/dist/sig/owner.test.mjs +6 -6
  109. package/dist/sig/proof.test.mjs +169 -8
  110. package/dist/{std__assert-CRDpx_HF.mjs → std__assert-BBjXFNOb.mjs} +5 -30
  111. package/dist/temporal-LpjyAjKb.mjs +95 -0
  112. package/dist/testing/mod.d.mts +110 -10
  113. package/dist/testing/mod.mjs +1 -2
  114. package/dist/{transformers-ve6e2xcg.js → transformers-BGMIq1cs.js} +2 -2
  115. package/dist/{types-hvL8ElAs.js → types-CAY3OdLq.js} +2 -2
  116. package/dist/utils/docloader.test.mjs +6 -6
  117. package/dist/utils/kv-cache.test.mjs +67 -2
  118. package/dist/utils/mod.cjs +1 -1
  119. package/dist/utils/mod.d.cts +2 -1
  120. package/dist/utils/mod.d.ts +2 -3
  121. package/dist/utils/mod.js +3 -3
  122. package/dist/vocab/cjs.test.mjs +1 -1
  123. package/dist/vocab/mod.d.cts +1 -0
  124. package/dist/vocab/mod.d.ts +1 -2
  125. package/dist/vocab/mod.js +2 -2
  126. package/package.json +16 -16
  127. package/dist/ld-DR78beiv.mjs +0 -279
  128. package/dist/middleware-BFBaR0mF.cjs +0 -4
  129. package/dist/mod-2d12ffz3.d.ts +0 -64
  130. package/dist/mod-D35TRn09.d.cts +0 -62
  131. package/dist/router-CrMLXoOr.mjs +0 -114
  132. package/dist/{activity-listener-ell7W1s9.mjs → activity-listener-tztVvlNb.mjs} +0 -0
  133. package/dist/{assert_equals-Ew3jOFa3.mjs → assert_equals-C-ZRDbaf.mjs} +0 -0
  134. package/dist/{client-D_1QpnWt.mjs → client-ByXmQhYD.mjs} +1 -1
  135. package/dist/{collection-D-HqUuA2.mjs → collection-Cc3DVAhE.mjs} +0 -0
  136. package/dist/{keycache-EGATflN-.mjs → keycache-BeU0LCII.mjs} +0 -0
  137. package/dist/{public-audience-DYFHzm_c.mjs → public-audience-Cvbr2Gzt.mjs} +1 -1
  138. /package/dist/{retry-bMXBL97A.mjs → retry-CXg_MBI-.mjs} +0 -0
@@ -1,7 +1,7 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  const require_chunk = require("./chunk-DDcVe30Y.cjs");
4
- const require_http = require("./http-BrGqJDXL.cjs");
4
+ const require_http = require("./http-CjZwUPiT.cjs");
5
5
  let _logtape_logtape = require("@logtape/logtape");
6
6
  let _fedify_vocab = require("@fedify/vocab");
7
7
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -9,15 +9,299 @@ let byte_encodings_hex = require("byte-encodings/hex");
9
9
  let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
10
10
  let byte_encodings_base64 = require("byte-encodings/base64");
11
11
  let _fedify_vocab_runtime_jsonld = require("@fedify/vocab-runtime/jsonld");
12
- _fedify_vocab_runtime_jsonld = require_chunk.__toESM(_fedify_vocab_runtime_jsonld);
12
+ _fedify_vocab_runtime_jsonld = require_chunk.__toESM(_fedify_vocab_runtime_jsonld, 1);
13
13
  let json_canon = require("json-canon");
14
- json_canon = require_chunk.__toESM(json_canon);
14
+ json_canon = require_chunk.__toESM(json_canon, 1);
15
15
  //#region src/sig/ld.ts
16
16
  const logger$3 = (0, _logtape_logtape.getLogger)([
17
17
  "fedify",
18
18
  "sig",
19
19
  "ld"
20
20
  ]);
21
+ const localContext = [
22
+ "https://w3id.org/identity/v1",
23
+ "https://www.w3.org/ns/activitystreams",
24
+ "https://w3id.org/security/v1",
25
+ "https://w3id.org/security/data-integrity/v1"
26
+ ];
27
+ const localContextUrls = new Set(localContext);
28
+ const builtInContextLoader = (0, _fedify_vocab_runtime.getDocumentLoader)();
29
+ const disallowedJsonLdKeywords = new Set([
30
+ "@graph",
31
+ "@included",
32
+ "@reverse"
33
+ ]);
34
+ /** @internal */
35
+ var UnsafeJsonLdError = class extends TypeError {
36
+ keyword;
37
+ constructor(keyword) {
38
+ super(`Unsupported JSON-LD keyword: ${keyword}.`);
39
+ this.keyword = keyword;
40
+ this.name = "UnsafeJsonLdError";
41
+ }
42
+ };
43
+ /** @internal */
44
+ var InvalidContextReferenceError = class extends TypeError {
45
+ reference;
46
+ constructor(reference) {
47
+ super(`Invalid JSON-LD context reference: ${reference}.`);
48
+ this.reference = reference;
49
+ this.name = "InvalidContextReferenceError";
50
+ }
51
+ };
52
+ function createLoadingRemoteContextFailedError(reference, cause) {
53
+ const message = cause instanceof Error ? cause.message : String(cause);
54
+ const error = /* @__PURE__ */ new Error(`Dereferencing a URL did not result in a valid JSON-LD context: ${reference}. ${message}`);
55
+ error.name = "jsonld.InvalidUrl";
56
+ error.details = {
57
+ code: "loading remote context failed",
58
+ url: reference
59
+ };
60
+ error.cause = cause;
61
+ return error;
62
+ }
63
+ /** @internal */
64
+ function isClearlyMalformedContextReference(reference) {
65
+ for (const char of reference) {
66
+ const code = char.charCodeAt(0);
67
+ if (code <= 32 || code === 127) return true;
68
+ }
69
+ if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(reference) && !URL.canParse(reference)) return true;
70
+ for (let i = 0; i < reference.length; i++) {
71
+ if (reference[i] !== "%") continue;
72
+ if (i + 2 >= reference.length || !/[0-9A-Fa-f]/.test(reference[i + 1]) || !/[0-9A-Fa-f]/.test(reference[i + 2])) return true;
73
+ i += 2;
74
+ }
75
+ if (reference.startsWith("./") || reference.startsWith("../") || reference.startsWith("/") || reference.startsWith("//")) {
76
+ for (const char of reference) if ("[]<>\"\\^`{|}".includes(char)) return true;
77
+ }
78
+ return false;
79
+ }
80
+ function cloneRemoteDocument(remoteDocument) {
81
+ return structuredClone(remoteDocument);
82
+ }
83
+ function createMemoizedDocumentLoader(documentLoader) {
84
+ const cache = /* @__PURE__ */ new Map();
85
+ return async (url, options) => {
86
+ const cacheKey = URL.canParse(url) ? new URL(url).href : url;
87
+ let remoteDocument = cache.get(cacheKey);
88
+ if (remoteDocument == null) {
89
+ remoteDocument = Promise.resolve(documentLoader(url, options)).then(cloneRemoteDocument);
90
+ remoteDocument.catch(() => {
91
+ if (cache.get(cacheKey) === remoteDocument) cache.delete(cacheKey);
92
+ });
93
+ cache.set(cacheKey, remoteDocument);
94
+ }
95
+ return cloneRemoteDocument(await remoteDocument);
96
+ };
97
+ }
98
+ /** @internal */
99
+ function wrapContextLoaderForJsonLd(contextLoader) {
100
+ const loader = contextLoader ?? builtInContextLoader;
101
+ return async (url, options) => {
102
+ try {
103
+ return await loader(url, options);
104
+ } catch (error) {
105
+ if (!isInvalidUrlTypeError(error)) throw error;
106
+ if (isClearlyMalformedContextReference(url)) throw new InvalidContextReferenceError(url);
107
+ throw createLoadingRemoteContextFailedError(url, error);
108
+ }
109
+ };
110
+ }
111
+ /** @internal */
112
+ function getNormalizationContextLoader(contextLoader) {
113
+ const loader = wrapContextLoaderForJsonLd(contextLoader);
114
+ return createMemoizedDocumentLoader(async (url, options) => {
115
+ if (URL.canParse(url)) {
116
+ const normalizedUrl = new URL(url).href;
117
+ if (localContextUrls.has(normalizedUrl)) return await builtInContextLoader(normalizedUrl, options);
118
+ }
119
+ return await loader(url, options);
120
+ });
121
+ }
122
+ /** @internal */
123
+ async function compactJsonLd(jsonLd, contextLoader) {
124
+ const hasLds = typeof jsonLd === "object" && jsonLd != null && "signature" in jsonLd;
125
+ const signature = hasLds ? jsonLd.signature : void 0;
126
+ const normalizationContextLoader = getNormalizationContextLoader(contextLoader);
127
+ const document = hasLds ? detachSignature(jsonLd) : jsonLd;
128
+ await assertNoGraphBeforeCompaction(document, normalizationContextLoader);
129
+ const compacted = await _fedify_vocab_runtime_jsonld.default.compact(document, localContext, { documentLoader: normalizationContextLoader });
130
+ if (hasLds && typeof compacted === "object" && compacted != null) compacted.signature = signature;
131
+ assertSafeJsonLd(compacted);
132
+ return compacted;
133
+ }
134
+ function createInvalidRemoteContextError(reference) {
135
+ const error = /* @__PURE__ */ new Error(`Dereferencing a URL did not result in a JSON object. The response was valid JSON, but it was not a JSON object. URL: "${reference}".`);
136
+ error.name = "jsonld.InvalidUrl";
137
+ error.details = {
138
+ code: "invalid remote context",
139
+ url: reference
140
+ };
141
+ return error;
142
+ }
143
+ function getRemoteContext(remoteDocument, reference) {
144
+ const { contextUrl, documentUrl } = remoteDocument;
145
+ let { document } = remoteDocument;
146
+ if (typeof document === "string") document = JSON.parse(document);
147
+ if (typeof document !== "object" || document == null || Array.isArray(document)) throw createInvalidRemoteContextError(reference);
148
+ let context = "@context" in document ? document["@context"] : {};
149
+ if (contextUrl != null) context = Array.isArray(context) ? [...context, contextUrl] : [context, contextUrl];
150
+ return {
151
+ context,
152
+ baseUrl: documentUrl ?? reference
153
+ };
154
+ }
155
+ function createGraphAliasContextState() {
156
+ return {
157
+ graphTerms: /* @__PURE__ */ new Set(),
158
+ jsonTerms: /* @__PURE__ */ new Set(),
159
+ propertyContexts: /* @__PURE__ */ new Map(),
160
+ termTargets: /* @__PURE__ */ new Map()
161
+ };
162
+ }
163
+ function cloneGraphAliasContextState(state) {
164
+ return {
165
+ graphTerms: new Set(state.graphTerms),
166
+ jsonTerms: new Set(state.jsonTerms),
167
+ propertyContexts: new Map(state.propertyContexts),
168
+ termTargets: new Map(state.termTargets)
169
+ };
170
+ }
171
+ function resolveContextTarget(target, state) {
172
+ if (target === "@graph") return target;
173
+ const mapped = state.termTargets.get(target);
174
+ if (mapped == null) return target;
175
+ return mapped;
176
+ }
177
+ function getDirectContextTarget(definition) {
178
+ if (definition === null) return null;
179
+ if (typeof definition === "string") return definition;
180
+ if (typeof definition === "object" && definition != null && "@id" in definition) {
181
+ const id = definition["@id"];
182
+ if (id === null) return null;
183
+ if (typeof id === "string") return id;
184
+ }
185
+ }
186
+ function isJsonTypedDefinition(definition) {
187
+ return typeof definition === "object" && definition != null && "@type" in definition && definition["@type"] === "@json";
188
+ }
189
+ function resolveLocalContextTarget(target, state, localTargets, seen = /* @__PURE__ */ new Set()) {
190
+ if (target === "@graph") return target;
191
+ if (seen.has(target)) return target;
192
+ seen.add(target);
193
+ if (localTargets.has(target)) {
194
+ const localTarget = localTargets.get(target);
195
+ return localTarget == null ? target : resolveLocalContextTarget(localTarget, state, localTargets, seen);
196
+ }
197
+ return resolveContextTarget(target, state);
198
+ }
199
+ function refreshGraphAliases(state) {
200
+ state.graphTerms.clear();
201
+ for (const [term, target] of state.termTargets) if (target === "@graph") state.graphTerms.add(term);
202
+ }
203
+ function normalizeContextReference(reference, baseUrl) {
204
+ if (baseUrl != null) return new URL(reference, baseUrl).href;
205
+ return URL.canParse(reference) ? new URL(reference).href : reference;
206
+ }
207
+ /** @internal */
208
+ function isInvalidUrlTypeError(error) {
209
+ const code = error.code;
210
+ return error instanceof TypeError && (code === "ERR_INVALID_URL" || /^Invalid URL(?::|$)/.test(error.message) || / cannot be parsed as a URL\.?$/.test(error.message));
211
+ }
212
+ async function applyGraphAliasContext(state, context, documentLoader, remoteContextCache, baseUrl = null, processingContexts = /* @__PURE__ */ new Set()) {
213
+ if (context === null) return createGraphAliasContextState();
214
+ let nextState = cloneGraphAliasContextState(state);
215
+ if (Array.isArray(context)) {
216
+ for (const item of context) nextState = await applyGraphAliasContext(nextState, item, documentLoader, remoteContextCache, baseUrl, processingContexts);
217
+ return nextState;
218
+ }
219
+ if (typeof context === "string") {
220
+ const reference = normalizeContextReference(context, baseUrl);
221
+ const cacheKey = `${baseUrl ?? ""}\n${reference}`;
222
+ if (processingContexts.has(cacheKey)) return nextState;
223
+ processingContexts.add(cacheKey);
224
+ try {
225
+ let remoteContext = remoteContextCache.get(cacheKey);
226
+ if (remoteContext == null) {
227
+ remoteContext = (async () => {
228
+ try {
229
+ return getRemoteContext(await documentLoader(reference), reference);
230
+ } catch (error) {
231
+ if (reference === context && isInvalidUrlTypeError(error) && isClearlyMalformedContextReference(context)) throw new InvalidContextReferenceError(context);
232
+ throw error;
233
+ }
234
+ })();
235
+ remoteContextCache.set(cacheKey, remoteContext);
236
+ }
237
+ const loadedRemoteContext = await remoteContext;
238
+ return await applyGraphAliasContext(nextState, loadedRemoteContext.context, documentLoader, remoteContextCache, loadedRemoteContext.baseUrl, processingContexts);
239
+ } finally {
240
+ processingContexts.delete(cacheKey);
241
+ }
242
+ }
243
+ if (typeof context === "object" && context != null) {
244
+ if ("@import" in context && typeof context["@import"] === "string") nextState = await applyGraphAliasContext(nextState, context["@import"], documentLoader, remoteContextCache, baseUrl, processingContexts);
245
+ const localTargets = /* @__PURE__ */ new Map();
246
+ for (const [term, definition] of globalThis.Object.entries(context)) {
247
+ if (term.startsWith("@")) continue;
248
+ const target = getDirectContextTarget(definition);
249
+ if (target == null) localTargets.set(term, null);
250
+ else if (typeof target === "string") localTargets.set(term, target);
251
+ else localTargets.delete(term);
252
+ }
253
+ for (const [term, definition] of globalThis.Object.entries(context)) {
254
+ if (term.startsWith("@")) continue;
255
+ if (localTargets.has(term)) {
256
+ const directTarget = localTargets.get(term);
257
+ if (directTarget == null) nextState.termTargets.set(term, null);
258
+ else nextState.termTargets.set(term, resolveLocalContextTarget(directTarget, nextState, localTargets));
259
+ } else nextState.termTargets.delete(term);
260
+ if (typeof definition === "object" && definition != null && "@context" in definition) nextState.propertyContexts.set(term, {
261
+ context: definition["@context"],
262
+ baseUrl
263
+ });
264
+ else nextState.propertyContexts.delete(term);
265
+ if (isJsonTypedDefinition(definition)) nextState.jsonTerms.add(term);
266
+ else nextState.jsonTerms.delete(term);
267
+ }
268
+ refreshGraphAliases(nextState);
269
+ }
270
+ return nextState;
271
+ }
272
+ async function assertNoGraphBeforeCompaction(jsonLd, documentLoader, inheritedState = createGraphAliasContextState(), propertyContext, remoteContextCache = /* @__PURE__ */ new Map()) {
273
+ if (Array.isArray(jsonLd)) {
274
+ for (const item of jsonLd) await assertNoGraphBeforeCompaction(item, documentLoader, inheritedState, propertyContext, remoteContextCache);
275
+ return;
276
+ }
277
+ if (typeof jsonLd !== "object" || jsonLd == null) return;
278
+ const jsonLiteralWrapper = isJsonLiteralWrapper(jsonLd);
279
+ let state = inheritedState;
280
+ if (propertyContext !== void 0) state = await applyGraphAliasContext(state, propertyContext.context, documentLoader, remoteContextCache, propertyContext.baseUrl);
281
+ if ("@context" in jsonLd) state = await applyGraphAliasContext(state, jsonLd["@context"], documentLoader, remoteContextCache);
282
+ for (const [key, value] of globalThis.Object.entries(jsonLd)) {
283
+ if (key === "@context") continue;
284
+ if (jsonLiteralWrapper && key === "@value") continue;
285
+ if (key === "@graph" || state.graphTerms.has(key)) throw new UnsafeJsonLdError("@graph");
286
+ if (state.jsonTerms.has(key)) continue;
287
+ await assertNoGraphBeforeCompaction(value, documentLoader, state, state.propertyContexts.get(key), remoteContextCache);
288
+ }
289
+ }
290
+ function isJsonLiteralWrapper(value) {
291
+ return "@value" in value && (value["@type"] === "@json" || value.type === "@json");
292
+ }
293
+ /** @internal */
294
+ function assertSafeJsonLd(jsonLd) {
295
+ if (Array.isArray(jsonLd)) for (const item of jsonLd) assertSafeJsonLd(item);
296
+ else if (typeof jsonLd === "object" && jsonLd != null) {
297
+ const jsonLiteralWrapper = isJsonLiteralWrapper(jsonLd);
298
+ for (const [key, value] of globalThis.Object.entries(jsonLd)) {
299
+ if (disallowedJsonLdKeywords.has(key)) throw new UnsafeJsonLdError(key);
300
+ if (jsonLiteralWrapper && key === "@value") continue;
301
+ assertSafeJsonLd(value);
302
+ }
303
+ }
304
+ }
21
305
  /**
22
306
  * Attaches a LD signature to the given JSON-LD document.
23
307
  * @param jsonLd The JSON-LD document to attach the signature to. It is not
@@ -148,6 +432,17 @@ function detachSignature(jsonLd) {
148
432
  }
149
433
  /**
150
434
  * Verifies Linked Data Signatures of the given JSON-LD document.
435
+ *
436
+ * This is a low-level utility that only checks the cryptographic signature
437
+ * and (optionally) the cached key. It does not run the JSON-LD parsing,
438
+ * attribution, and owner checks that a complete inbound LD verification
439
+ * needs. For incoming activities, prefer {@link verifyJsonLd}, which is
440
+ * the public verification entry point and the one that emits the
441
+ * `activitypub.signature.verification.duration` metric for the LD path.
442
+ * `verifySignature` itself only emits
443
+ * `activitypub.signature.key_fetch.duration`, since the rest of the work
444
+ * that the verification-duration metric is meant to cover happens in
445
+ * `verifyJsonLd`.
151
446
  * @param jsonLd The JSON-LD document to verify.
152
447
  * @param options Options for verifying the signature.
153
448
  * @returns The public key that signed the document or `null` if the signature
@@ -167,7 +462,7 @@ async function verifySignature(jsonLd, options = {}) {
167
462
  });
168
463
  return null;
169
464
  }
170
- const { key, cached } = await require_http.fetchKey(new URL(sig.creator), _fedify_vocab.CryptographicKey, options);
465
+ const { key, cached } = await require_http.measureSignatureKeyFetch(options.meterProvider, "linked_data", () => require_http.fetchKey(new URL(sig.creator), _fedify_vocab.CryptographicKey, options));
171
466
  if (key == null) return null;
172
467
  const sigOpts = {
173
468
  ...sig,
@@ -207,13 +502,13 @@ async function verifySignature(jsonLd, options = {}) {
207
502
  keyId: sig.creator,
208
503
  ...sig
209
504
  });
210
- const { key } = await require_http.fetchKey(new URL(sig.creator), _fedify_vocab.CryptographicKey, {
505
+ const { key } = await require_http.measureSignatureKeyFetch(options.meterProvider, "linked_data", () => require_http.fetchKey(new URL(sig.creator), _fedify_vocab.CryptographicKey, {
211
506
  ...options,
212
507
  keyCache: {
213
508
  get: () => Promise.resolve(void 0),
214
509
  set: async (keyId, key) => await options.keyCache?.set(keyId, key)
215
510
  }
216
- });
511
+ }));
217
512
  if (key == null) return null;
218
513
  return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, signature.slice(), messageBytes) ? key : null;
219
514
  }
@@ -225,6 +520,33 @@ async function verifySignature(jsonLd, options = {}) {
225
520
  return null;
226
521
  }
227
522
  /**
523
+ * Known Linked Data Signature `type` values, used to keep
524
+ * `ld_signatures.type` on a bounded set of spec-defined string values.
525
+ * Fedify only signs and verifies `RsaSignature2017`; other values come in
526
+ * only from external documents and are dropped from the metric attribute to
527
+ * avoid attacker-controlled cardinality.
528
+ */
529
+ const LD_KNOWN_SIGNATURE_TYPES = new Set(["RsaSignature2017"]);
530
+ /**
531
+ * Reports only whether a `signature` key is present on the document, with
532
+ * no shape check on its value. This is intentionally looser than
533
+ * {@link hasSignature} (which validates a full `RsaSignature2017` shape)
534
+ * and {@link hasSignatureLike} (which structurally accepts several known
535
+ * suites): `verifyJsonLd` needs to tell a document with a malformed or
536
+ * unsupported signature payload (classified as `rejected`) apart from a
537
+ * truly unsigned document (classified as `missing`), and only this
538
+ * presence-only check captures both cases.
539
+ */
540
+ function hasLdSignatureProperty(jsonLd) {
541
+ return typeof jsonLd === "object" && jsonLd != null && "signature" in jsonLd;
542
+ }
543
+ function getLdSignatureObject(jsonLd) {
544
+ if (!hasLdSignatureProperty(jsonLd)) return void 0;
545
+ const { signature } = jsonLd;
546
+ if (typeof signature !== "object" || signature == null || Array.isArray(signature)) return;
547
+ return signature;
548
+ }
549
+ /**
228
550
  * Verify the authenticity of the given JSON-LD document using Linked Data
229
551
  * Signatures. If the document is signed, this function verifies the signature
230
552
  * and checks if the document is attributed to the owner of the public key.
@@ -234,19 +556,39 @@ async function verifySignature(jsonLd, options = {}) {
234
556
  * @returns `true` if the document is authentic; `false` otherwise.
235
557
  */
236
558
  async function verifyJsonLd(jsonLd, options = {}) {
559
+ return await verifyJsonLdInternal(jsonLd, options, true);
560
+ }
561
+ /** @internal */
562
+ async function verifyCompactJsonLd(jsonLd, options = {}) {
563
+ return await verifyJsonLdInternal(jsonLd, options, false);
564
+ }
565
+ async function verifyJsonLdInternal(jsonLd, options, compact) {
237
566
  return await (options.tracerProvider ?? _opentelemetry_api.trace.getTracerProvider()).getTracer(require_http.name, require_http.version).startActiveSpan("ld_signatures.verify", async (span) => {
567
+ const start = performance.now();
568
+ let verified = false;
569
+ let threw = false;
570
+ let signatureType;
238
571
  try {
239
- const object = await _fedify_vocab.Object.fromJsonLd(jsonLd, options);
572
+ const verificationOptions = hasSignature(jsonLd) ? {
573
+ ...options,
574
+ contextLoader: getNormalizationContextLoader(options.contextLoader)
575
+ } : options;
576
+ const compacted = compact ? hasSignature(jsonLd) ? await compactJsonLd(jsonLd, options.contextLoader) : jsonLd : jsonLd;
577
+ const object = await _fedify_vocab.Object.fromJsonLd(compacted, verificationOptions);
240
578
  if (object.id != null) span.setAttribute("activitypub.object.id", object.id.href);
241
579
  span.setAttribute("activitypub.object.type", (0, _fedify_vocab.getTypeId)(object).href);
242
- if (typeof jsonLd === "object" && jsonLd != null && "signature" in jsonLd && typeof jsonLd.signature === "object" && jsonLd.signature != null) {
243
- if ("creator" in jsonLd.signature && typeof jsonLd.signature.creator === "string") span.setAttribute("ld_signatures.key_id", jsonLd.signature.creator);
244
- if ("signatureValue" in jsonLd.signature && typeof jsonLd.signature.signatureValue === "string") span.setAttribute("ld_signatures.signature", jsonLd.signature.signatureValue);
245
- if ("type" in jsonLd.signature && typeof jsonLd.signature.type === "string") span.setAttribute("ld_signatures.type", jsonLd.signature.type);
580
+ const sig = getLdSignatureObject(jsonLd);
581
+ if (sig != null) {
582
+ if (typeof sig.creator === "string") span.setAttribute("ld_signatures.key_id", sig.creator);
583
+ if (typeof sig.signatureValue === "string") span.setAttribute("ld_signatures.signature", sig.signatureValue);
584
+ if (typeof sig.type === "string") {
585
+ span.setAttribute("ld_signatures.type", sig.type);
586
+ if (LD_KNOWN_SIGNATURE_TYPES.has(sig.type)) signatureType = sig.type;
587
+ }
246
588
  }
247
589
  const attributions = new Set(object.attributionIds.map((uri) => uri.href));
248
590
  if (object instanceof _fedify_vocab.Activity) for (const uri of object.actorIds) attributions.add(uri.href);
249
- const key = await verifySignature(jsonLd, options);
591
+ const key = await verifySignature(compacted, verificationOptions);
250
592
  if (key == null) return false;
251
593
  if (key.ownerId == null) {
252
594
  logger$3.debug("Key {keyId} has no owner.", { keyId: key.id?.href });
@@ -257,14 +599,18 @@ async function verifyJsonLd(jsonLd, options = {}) {
257
599
  logger$3.debug("Some attributions are not authenticated by the Linked Data Signatures: {attributions}.", { attributions: [...attributions] });
258
600
  return false;
259
601
  }
602
+ verified = true;
260
603
  return true;
261
604
  } catch (error) {
605
+ threw = true;
262
606
  span.setStatus({
263
607
  code: _opentelemetry_api.SpanStatusCode.ERROR,
264
608
  message: String(error)
265
609
  });
266
610
  throw error;
267
611
  } finally {
612
+ const classified = threw ? "error" : verified ? "verified" : hasLdSignatureProperty(jsonLd) ? "rejected" : "missing";
613
+ require_http.getFederationMetrics(options.meterProvider).recordSignatureVerificationDuration(require_http.getDurationMs(start), "linked_data", classified, { ldType: signatureType });
268
614
  span.end();
269
615
  }
270
616
  });
@@ -769,6 +1115,15 @@ async function normalizeOutgoingActivityJsonLd(jsonLd, contextLoader) {
769
1115
  }
770
1116
  //#endregion
771
1117
  //#region src/sig/proof.ts
1118
+ /**
1119
+ * Known Object Integrity Proof `cryptosuite` values, used to keep
1120
+ * `object_integrity_proofs.cryptosuite` on a bounded set of spec-defined
1121
+ * string values. Fedify currently signs and verifies only
1122
+ * `eddsa-jcs-2022`; other values come in only from external proofs and are
1123
+ * dropped from the metric attribute to avoid attacker-controlled
1124
+ * cardinality.
1125
+ */
1126
+ const OIP_KNOWN_CRYPTOSUITES = new Set(["eddsa-jcs-2022"]);
772
1127
  const logger = (0, _logtape_logtape.getLogger)([
773
1128
  "fedify",
774
1129
  "sig",
@@ -895,6 +1250,10 @@ async function signObject(object, privateKey, keyId, options = {}) {
895
1250
  */
896
1251
  async function verifyProof(jsonLd, proof, options = {}) {
897
1252
  return await (options.tracerProvider ?? _opentelemetry_api.trace.getTracerProvider()).getTracer(require_http.name, require_http.version).startActiveSpan("object_integrity_proofs.verify", async (span) => {
1253
+ const start = performance.now();
1254
+ let verified = false;
1255
+ let threw = false;
1256
+ const cryptosuite = proof.cryptosuite != null && OIP_KNOWN_CRYPTOSUITES.has(proof.cryptosuite) ? proof.cryptosuite : void 0;
898
1257
  if (span.isRecording()) {
899
1258
  if (proof.cryptosuite != null) span.setAttribute("object_integrity_proofs.cryptosuite", proof.cryptosuite);
900
1259
  if (proof.verificationMethodId != null) span.setAttribute("object_integrity_proofs.key_id", proof.verificationMethodId.href);
@@ -903,21 +1262,25 @@ async function verifyProof(jsonLd, proof, options = {}) {
903
1262
  try {
904
1263
  const key = await verifyProofInternal(jsonLd, proof, options);
905
1264
  if (key == null) span.setStatus({ code: _opentelemetry_api.SpanStatusCode.ERROR });
1265
+ else verified = true;
906
1266
  return key;
907
1267
  } catch (error) {
1268
+ threw = true;
908
1269
  span.setStatus({
909
1270
  code: _opentelemetry_api.SpanStatusCode.ERROR,
910
1271
  message: String(error)
911
1272
  });
912
1273
  throw error;
913
1274
  } finally {
1275
+ const classified = threw ? "error" : verified ? "verified" : "rejected";
1276
+ require_http.getFederationMetrics(options.meterProvider).recordSignatureVerificationDuration(require_http.getDurationMs(start), "object_integrity", classified, { cryptosuite });
914
1277
  span.end();
915
1278
  }
916
1279
  });
917
1280
  }
918
1281
  async function verifyProofInternal(jsonLd, proof, options) {
919
1282
  if (typeof jsonLd !== "object" || jsonLd == null || Array.isArray(jsonLd) || proof.cryptosuite !== "eddsa-jcs-2022" || proof.verificationMethodId == null || proof.proofPurpose !== "assertionMethod" || proof.proofValue == null || proof.created == null) return null;
920
- const publicKeyPromise = require_http.fetchKey(proof.verificationMethodId, _fedify_vocab.Multikey, options);
1283
+ const publicKeyPromise = require_http.measureSignatureKeyFetch(options.meterProvider, "object_integrity", () => require_http.fetchKey(proof.verificationMethodId, _fedify_vocab.Multikey, options));
921
1284
  const proofConfig = {
922
1285
  "@context": jsonLd["@context"],
923
1286
  type: "DataIntegrityProof",
@@ -957,7 +1320,7 @@ async function verifyProofInternal(jsonLd, proof, options) {
957
1320
  proof,
958
1321
  keyId: proof.verificationMethodId.href
959
1322
  });
960
- return await verifyProof(jsonLd, proof, {
1323
+ return await verifyProofInternal(jsonLd, proof, {
961
1324
  ...options,
962
1325
  keyCache: {
963
1326
  get: () => Promise.resolve(void 0),
@@ -988,7 +1351,7 @@ async function verifyProofInternal(jsonLd, proof, options) {
988
1351
  keyId: proof.verificationMethodId.href,
989
1352
  proof
990
1353
  });
991
- return await verifyProof(jsonLd, proof, {
1354
+ return await verifyProofInternal(jsonLd, proof, {
992
1355
  ...options,
993
1356
  keyCache: {
994
1357
  get: () => Promise.resolve(void 0),
@@ -1041,12 +1404,30 @@ async function verifyObject(cls, jsonLd, options = {}) {
1041
1404
  return object;
1042
1405
  }
1043
1406
  //#endregion
1407
+ Object.defineProperty(exports, "InvalidContextReferenceError", {
1408
+ enumerable: true,
1409
+ get: function() {
1410
+ return InvalidContextReferenceError;
1411
+ }
1412
+ });
1413
+ Object.defineProperty(exports, "assertSafeJsonLd", {
1414
+ enumerable: true,
1415
+ get: function() {
1416
+ return assertSafeJsonLd;
1417
+ }
1418
+ });
1044
1419
  Object.defineProperty(exports, "attachSignature", {
1045
1420
  enumerable: true,
1046
1421
  get: function() {
1047
1422
  return attachSignature;
1048
1423
  }
1049
1424
  });
1425
+ Object.defineProperty(exports, "compactJsonLd", {
1426
+ enumerable: true,
1427
+ get: function() {
1428
+ return compactJsonLd;
1429
+ }
1430
+ });
1050
1431
  Object.defineProperty(exports, "createProof", {
1051
1432
  enumerable: true,
1052
1433
  get: function() {
@@ -1077,18 +1458,42 @@ Object.defineProperty(exports, "getKeyOwner", {
1077
1458
  return getKeyOwner;
1078
1459
  }
1079
1460
  });
1461
+ Object.defineProperty(exports, "getNormalizationContextLoader", {
1462
+ enumerable: true,
1463
+ get: function() {
1464
+ return getNormalizationContextLoader;
1465
+ }
1466
+ });
1080
1467
  Object.defineProperty(exports, "hasProofLike", {
1081
1468
  enumerable: true,
1082
1469
  get: function() {
1083
1470
  return hasProofLike;
1084
1471
  }
1085
1472
  });
1473
+ Object.defineProperty(exports, "hasSignature", {
1474
+ enumerable: true,
1475
+ get: function() {
1476
+ return hasSignature;
1477
+ }
1478
+ });
1086
1479
  Object.defineProperty(exports, "hasSignatureLike", {
1087
1480
  enumerable: true,
1088
1481
  get: function() {
1089
1482
  return hasSignatureLike;
1090
1483
  }
1091
1484
  });
1485
+ Object.defineProperty(exports, "isClearlyMalformedContextReference", {
1486
+ enumerable: true,
1487
+ get: function() {
1488
+ return isClearlyMalformedContextReference;
1489
+ }
1490
+ });
1491
+ Object.defineProperty(exports, "isInvalidUrlTypeError", {
1492
+ enumerable: true,
1493
+ get: function() {
1494
+ return isInvalidUrlTypeError;
1495
+ }
1496
+ });
1092
1497
  Object.defineProperty(exports, "normalizeOutgoingActivityJsonLd", {
1093
1498
  enumerable: true,
1094
1499
  get: function() {
@@ -1107,6 +1512,12 @@ Object.defineProperty(exports, "signObject", {
1107
1512
  return signObject;
1108
1513
  }
1109
1514
  });
1515
+ Object.defineProperty(exports, "verifyCompactJsonLd", {
1516
+ enumerable: true,
1517
+ get: function() {
1518
+ return verifyCompactJsonLd;
1519
+ }
1520
+ });
1110
1521
  Object.defineProperty(exports, "verifyJsonLd", {
1111
1522
  enumerable: true,
1112
1523
  get: function() {
@@ -1131,3 +1542,9 @@ Object.defineProperty(exports, "verifySignature", {
1131
1542
  return verifySignature;
1132
1543
  }
1133
1544
  });
1545
+ Object.defineProperty(exports, "wrapContextLoaderForJsonLd", {
1546
+ enumerable: true,
1547
+ get: function() {
1548
+ return wrapContextLoaderForJsonLd;
1549
+ }
1550
+ });
@@ -1,3 +1,4 @@
1
+ /// <reference lib="esnext.temporal" />
1
2
  export * from "@fedify/vocab-runtime";
2
3
 
3
4
  //#region \0rolldown/runtime.js
@@ -1,3 +1,2 @@
1
- import { Temporal } from "@js-temporal/polyfill";
2
- import { URLPattern } from "urlpattern-polyfill";
1
+ /// <reference lib="esnext.temporal" />
3
2
  export * from "@fedify/vocab-runtime";
@@ -1,4 +1,4 @@
1
- import "@js-temporal/polyfill";
2
- import "urlpattern-polyfill";
3
- import "../chunk-nlSIicah.js";
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ import { URLPattern } from "urlpattern-polyfill";
3
+ import "../chunk-CRNNMoPX.js";
4
4
  export * from "@fedify/vocab-runtime";