@fedify/fedify 2.4.0-dev.2027 → 2.4.0-dev.2030

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 (61) hide show
  1. package/dist/{builder-BM255b90.mjs → builder-BYJ5otJa.mjs} +2 -2
  2. package/dist/compat/transformers.test.mjs +1 -1
  3. package/dist/{compound-proof-CPvNisT2.mjs → compound-proof-BIvUoJxm.mjs} +74 -2
  4. package/dist/{deno-BcZNXlJn.mjs → deno-Vj_9wePq.mjs} +1 -1
  5. package/dist/{docloader-iHi0-9mK.mjs → docloader-qUudHZVH.mjs} +2 -2
  6. package/dist/federation/builder.test.mjs +1 -1
  7. package/dist/federation/compound-fanout.test.mjs +3 -3
  8. package/dist/federation/handler-compound-proof.test.mjs +3 -3
  9. package/dist/federation/handler.test.mjs +5 -5
  10. package/dist/federation/idempotency.test.mjs +2 -2
  11. package/dist/federation/metrics.test.mjs +1 -1
  12. package/dist/federation/middleware.test.mjs +7 -7
  13. package/dist/federation/mod.cjs +1 -1
  14. package/dist/federation/mod.js +1 -1
  15. package/dist/federation/outgoing-proof.test.d.mts +2 -0
  16. package/dist/federation/outgoing-proof.test.mjs +396 -0
  17. package/dist/federation/send.test.mjs +3 -3
  18. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  19. package/dist/federation/tasks/tasks.test.mjs +2 -2
  20. package/dist/federation/temporal.test.mjs +1 -1
  21. package/dist/federation/webfinger.test.mjs +1 -1
  22. package/dist/{federation-C0ijTwhx.cjs → federation-CTnaljmy.cjs} +200 -50
  23. package/dist/{http-CWXKwHPv.cjs → http-B5F1JMh0.cjs} +1 -1
  24. package/dist/{http-KZWtR1H8.js → http-By8tnmEr.js} +1 -1
  25. package/dist/{http-fIK5D83n.mjs → http-D4WPcJUe.mjs} +3 -3
  26. package/dist/{key-Xb1hVVZO.mjs → key-B_Zc5Jbd.mjs} +2 -2
  27. package/dist/{kv-cache-Dos4tOWb.cjs → kv-cache-8K70pjtX.cjs} +1 -1
  28. package/dist/{kv-cache-CU1rmQFB.mjs → kv-cache-BXdT7pJQ.mjs} +1 -1
  29. package/dist/{kv-cache-HOO6BsuW.js → kv-cache-BswMKQjC.js} +1 -1
  30. package/dist/{ld-DFHvxLtx.mjs → ld-B16KUSIQ.mjs} +3 -3
  31. package/dist/{metrics-D7RydU_p.mjs → metrics-DpQqUAmh.mjs} +1 -1
  32. package/dist/{middleware-DgU5bJnn.mjs → middleware-BL5HFFVU.mjs} +1 -1
  33. package/dist/{middleware-BsYD_ufs.mjs → middleware-C7_hqDnl.mjs} +139 -61
  34. package/dist/{middleware-iffqYoTV.js → middleware-Cxto6Bq2.js} +201 -51
  35. package/dist/mod.cjs +4 -4
  36. package/dist/mod.js +4 -4
  37. package/dist/nodeinfo/handler.test.mjs +1 -1
  38. package/dist/{owner-D53bUI-n.mjs → owner-BIOIhZoM.mjs} +2 -2
  39. package/dist/{owner-B7lgRMdU.js → owner-D-E0bT2O.js} +1 -1
  40. package/dist/{owner-DffLVeYC.cjs → owner-WUYke16i.cjs} +1 -1
  41. package/dist/{proof-4ADU3qy0.mjs → proof-BVxJu5vv.mjs} +4 -4
  42. package/dist/{send-n-W6bG7y.mjs → send-Cr5FJ7iu.mjs} +3 -3
  43. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  44. package/dist/sig/compound-proof-producer.test.d.mts +2 -0
  45. package/dist/sig/compound-proof-producer.test.mjs +107 -0
  46. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  47. package/dist/sig/compound-proof.test.mjs +2 -2
  48. package/dist/sig/http.test.mjs +2 -2
  49. package/dist/sig/key.test.mjs +1 -1
  50. package/dist/sig/ld.test.mjs +2 -2
  51. package/dist/sig/mod.cjs +2 -2
  52. package/dist/sig/mod.js +2 -2
  53. package/dist/sig/owner.test.mjs +1 -1
  54. package/dist/sig/proof.test.mjs +1 -1
  55. package/dist/{temporal-BFUyXrYg.mjs → temporal-CCf0lZV3.mjs} +1 -1
  56. package/dist/testing/kv.test.mjs +1 -1
  57. package/dist/utils/docloader.test.mjs +2 -2
  58. package/dist/utils/kv-cache.test.mjs +1 -1
  59. package/dist/utils/mod.cjs +1 -1
  60. package/dist/utils/mod.js +1 -1
  61. package/package.json +6 -6
@@ -1,27 +1,27 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-BcZNXlJn.mjs";
5
- import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-D7RydU_p.mjs";
4
+ import { n as version, t as name } from "./deno-Vj_9wePq.mjs";
5
+ import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-DpQqUAmh.mjs";
6
6
  import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
7
- import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-Xb1hVVZO.mjs";
8
- import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-fIK5D83n.mjs";
9
- import { t as getAuthenticatedDocumentLoader } from "./docloader-iHi0-9mK.mjs";
10
- import { n as kvCache } from "./kv-cache-CU1rmQFB.mjs";
7
+ import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-B_Zc5Jbd.mjs";
8
+ import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-D4WPcJUe.mjs";
9
+ import { t as getAuthenticatedDocumentLoader } from "./docloader-qUudHZVH.mjs";
10
+ import { n as kvCache } from "./kv-cache-BXdT7pJQ.mjs";
11
11
  import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
12
12
  import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-DpnpgjyX.mjs";
13
13
  import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
14
- import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-DFHvxLtx.mjs";
15
- import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-D53bUI-n.mjs";
16
- import { a as verifyObject, n as hasProofLike, r as signObject } from "./proof-4ADU3qy0.mjs";
17
- import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-n-W6bG7y.mjs";
18
- import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BM255b90.mjs";
14
+ import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-B16KUSIQ.mjs";
15
+ import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-BIOIhZoM.mjs";
16
+ import { a as verifyObject, n as hasProofLike, r as signObject } from "./proof-BVxJu5vv.mjs";
17
+ import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-Cr5FJ7iu.mjs";
18
+ import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BYJ5otJa.mjs";
19
19
  import { t as CircuitBreaker } from "./circuit-breaker-C5NqoLBJ.mjs";
20
20
  import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
21
- import { n as inspectCompoundPortableObjectApplicability, r as verifyCompoundPortableObjectProofs } from "./compound-proof-CPvNisT2.mjs";
21
+ import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-BIvUoJxm.mjs";
22
22
  import { t as KvKeyCache } from "./keycache-BUDHB5rY.mjs";
23
23
  import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
24
- import { t as hasMalformedKnownTemporalLiteral } from "./temporal-BFUyXrYg.mjs";
24
+ import { t as hasMalformedKnownTemporalLiteral } from "./temporal-CCf0lZV3.mjs";
25
25
  import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
26
26
  import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
27
27
  import { getLogger, withContext } from "@logtape/logtape";
@@ -30,7 +30,7 @@ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey,
30
30
  import { lookupWebFinger } from "@fedify/webfinger";
31
31
  import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
32
32
  import { uniq } from "es-toolkit";
33
- import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
33
+ import { FetchError, getDocumentLoader, getFe34Origin, haveSameFe34Origin } from "@fedify/vocab-runtime";
34
34
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
35
35
  import { DataPointType, MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
36
36
  import { domainToASCII } from "node:url";
@@ -2326,6 +2326,102 @@ const MIN_COMPONENTS = [
2326
2326
  "@authority"
2327
2327
  ];
2328
2328
  //#endregion
2329
+ //#region src/federation/outgoing-proof.ts
2330
+ function isPortableUrl(url) {
2331
+ return url.protocol === "ap:" || url.protocol === "ap+ef61:";
2332
+ }
2333
+ function formatKeyIds(candidates) {
2334
+ return candidates.map((c) => c.verificationMethod.href).join(", ");
2335
+ }
2336
+ /**
2337
+ * Creates the Object Integrity Proofs Fedify attaches to an outgoing activity.
2338
+ *
2339
+ * Outside the map-local compound-proof profile, i.e., when the activity
2340
+ * embeds no portable object, every Ed25519 key signs the activity, as it
2341
+ * always has. Inside the profile, which accepts exactly one direct proof per
2342
+ * map, Fedify creates at most one proof:
2343
+ *
2344
+ * - An activity that already carries a proof is kept as is.
2345
+ * - A single Ed25519 key signs the activity.
2346
+ * - With several Ed25519 keys, a portable activity is signed by the one key
2347
+ * whose verification method is a DID URL for the activity's DID, the only
2348
+ * proof the FEP-ef61 policy can accept. If no key or more than one key
2349
+ * qualifies, or the activity is not portable itself, the choice is
2350
+ * ambiguous and this function throws.
2351
+ *
2352
+ * @throws {TypeError} If a single proof key cannot be chosen.
2353
+ * @internal
2354
+ */
2355
+ async function signOutgoingActivity(activity, candidates, options) {
2356
+ const { contextLoader, tracerProvider } = options;
2357
+ let hasProof = false;
2358
+ for await (const _ of activity.getProofs({ contextLoader })) {
2359
+ hasProof = true;
2360
+ break;
2361
+ }
2362
+ const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519");
2363
+ if (keys.length < 1 || hasProof && !options.appendToExistingProofs) return {
2364
+ activity,
2365
+ hasProof,
2366
+ proofCreated: false
2367
+ };
2368
+ const sign = async (selected) => {
2369
+ for (const { verificationMethod, privateKey } of selected) activity = await signObject(activity, privateKey, verificationMethod, {
2370
+ contextLoader,
2371
+ tracerProvider
2372
+ });
2373
+ return {
2374
+ activity,
2375
+ hasProof: true,
2376
+ proofCreated: true
2377
+ };
2378
+ };
2379
+ if (keys.length < 2 && !hasProof) return await sign(keys);
2380
+ if (!containsCompoundPortableObject(await activity.toJsonLd({
2381
+ format: "compact",
2382
+ contextLoader
2383
+ }))) return await sign(keys);
2384
+ const logger = getLogger([
2385
+ "fedify",
2386
+ "federation",
2387
+ "outbox"
2388
+ ]);
2389
+ const activityId = activity.id?.href;
2390
+ if (hasProof) {
2391
+ logger.debug("The activity {activityId} embeds portable objects and already carries a proof, so no further proof is added; the map-local compound-proof profile accepts exactly one direct proof per map.", { activityId });
2392
+ return {
2393
+ activity,
2394
+ hasProof,
2395
+ proofCreated: false
2396
+ };
2397
+ }
2398
+ if (activity.id == null || !isPortableUrl(activity.id)) throw new TypeError(`Cannot choose an Object Integrity Proof key for the activity ${activityId}: it embeds portable objects, so it falls under the map-local compound-proof profile, which accepts exactly one direct proof per map, but ${keys.length} Ed25519 keys were supplied (${formatKeyIds(keys)}). Send it with explicit sender keys that contain exactly one Ed25519 key (RSA keys for HTTP Signatures may stay), or sign it with signObject() before sending it.`);
2399
+ const activityDid = getFe34Origin(activity.id);
2400
+ const eligible = keys.filter((c) => c.verificationMethod.protocol === "did:" && haveSameFe34Origin(activity.id, c.verificationMethod));
2401
+ if (eligible.length !== 1) throw new TypeError(`Cannot choose an Object Integrity Proof key for the portable activity ${activityId}: ` + (eligible.length < 1 ? `none of its ${keys.length} Ed25519 keys (${formatKeyIds(keys)}) ` : `${eligible.length} of its Ed25519 keys (${formatKeyIds(eligible)}) `) + `${eligible.length < 1 ? "is" : "are"} a DID URL verification method for ${activityDid}. The map-local compound-proof profile accepts exactly one direct proof per map, and FEP-ef61 requires that proof's verification method to be a DID URL for the activity's DID. Supply exactly one Ed25519 key whose key ID is a DID URL for ${activityDid}, or sign the activity with signObject() before sending it.`);
2402
+ logger.debug("The portable activity {activityId} is signed only by {keyId}, the one Ed25519 key whose verification method matches its DID; the map-local compound-proof profile accepts exactly one direct proof per map.", {
2403
+ activityId,
2404
+ keyId: eligible[0].verificationMethod.href
2405
+ });
2406
+ return await sign(eligible);
2407
+ }
2408
+ /**
2409
+ * Rejects an outgoing activity whose proofs Fedify's own inbox would reject
2410
+ * as unsupported: a document with portable objects in which some map carries
2411
+ * a proof set or another value that is not a single proof map.
2412
+ *
2413
+ * @param jsonLd The compact JSON-LD document about to be delivered.
2414
+ * @param activityId The activity ID, for the error message.
2415
+ * @throws {TypeError} If the document has an unsupported proof shape.
2416
+ * @internal
2417
+ */
2418
+ function assertSupportedCompoundProofShape(jsonLd, activityId) {
2419
+ if (!containsCompoundPortableObject(jsonLd)) return;
2420
+ const path = findUnsupportedCompoundProofShape(jsonLd);
2421
+ if (path == null) return;
2422
+ throw new TypeError(`Cannot send the activity ${activityId}: it embeds portable objects, but its proof at the JSON Pointer ${JSON.stringify(path)} is not a single proof map. The map-local compound-proof profile accepts exactly one direct proof per map, so Fedify inboxes would reject the activity. Sign each object with exactly one key.`);
2423
+ }
2424
+ //#endregion
2329
2425
  //#region src/federation/tasks/enqueue.ts
2330
2426
  /**
2331
2427
  * The enqueue pipeline for custom background tasks. `ContextImpl.enqueueTask`
@@ -3954,8 +4050,6 @@ var FederationImpl = class extends FederationBuilderImpl {
3954
4050
  else if (keys.length < 1) throw new TypeError("The keys must not be empty.");
3955
4051
  const contextLoader = this.contextLoaderFactory(this.#getLoaderOptions(ctx.origin));
3956
4052
  const activityId = activity.id.href;
3957
- let hasProof = false;
3958
- let proofCreated = false;
3959
4053
  let rsaKey = null;
3960
4054
  for (const { keyId, privateKey } of keys) {
3961
4055
  validateCryptoKey(privateKey, "private");
@@ -3964,25 +4058,22 @@ var FederationImpl = class extends FederationBuilderImpl {
3964
4058
  privateKey
3965
4059
  };
3966
4060
  }
3967
- for await (const _ of activity.getProofs({ contextLoader })) {
3968
- hasProof = true;
3969
- break;
3970
- }
3971
- if (!hasProof) {
3972
- for (const { keyId, privateKey } of keys) if (privateKey.algorithm.name === "Ed25519") {
3973
- activity = await signObject(activity, privateKey, keyId, {
3974
- contextLoader,
3975
- tracerProvider: this.tracerProvider
3976
- });
3977
- hasProof = true;
3978
- proofCreated = true;
3979
- }
3980
- }
4061
+ const signed = await signOutgoingActivity(activity, keys.map(({ keyId, privateKey }) => ({
4062
+ verificationMethod: keyId,
4063
+ privateKey
4064
+ })), {
4065
+ contextLoader,
4066
+ tracerProvider: this.tracerProvider,
4067
+ appendToExistingProofs: false
4068
+ });
4069
+ activity = signed.activity;
4070
+ const { hasProof, proofCreated } = signed;
3981
4071
  let jsonLd = !proofCreated && options.activityJsonLd != null ? options.activityJsonLd : await activity.toJsonLd({
3982
4072
  format: "compact",
3983
4073
  contextLoader
3984
4074
  });
3985
4075
  if (proofCreated || !hasProof || options.normalizeExistingProofs) jsonLd = await normalizeOutgoingActivityJsonLd(jsonLd, contextLoader, { preserveNestedSecuredDocuments: true });
4076
+ assertSupportedCompoundProofShape(jsonLd, activityId);
3986
4077
  if (rsaKey == null) logger.warn("No supported key found to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature. In order to create a Linked Data signature, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
3987
4078
  activityId,
3988
4079
  keys: keys.map((pair) => ({
@@ -4954,33 +5045,18 @@ var ContextImpl = class ContextImpl {
4954
5045
  });
4955
5046
  throw new TypeError("The activity to send must have at least one actor property.");
4956
5047
  }
4957
- let proofCreated = false;
4958
- if (actorKeyPairs != null) {
4959
- const contextLoader = this.contextLoader;
4960
- for (const kp of actorKeyPairs) {
4961
- if (kp.privateKey.algorithm.name !== "Ed25519" || kp.multikey.id == null) continue;
4962
- activity = await signObject(activity, kp.privateKey, kp.multikey.id, {
4963
- contextLoader,
4964
- tracerProvider: this.tracerProvider
4965
- });
4966
- proofCreated = true;
4967
- }
4968
- } else {
4969
- const contextLoader = this.contextLoader;
4970
- let hasProof = false;
4971
- for await (const _ of activity.getProofs({ contextLoader })) {
4972
- hasProof = true;
4973
- break;
4974
- }
4975
- if (!hasProof) for (const { keyId, privateKey } of keys) {
4976
- if (privateKey.algorithm.name !== "Ed25519") continue;
4977
- activity = await signObject(activity, privateKey, keyId, {
4978
- contextLoader,
4979
- tracerProvider: this.tracerProvider
4980
- });
4981
- proofCreated = true;
4982
- }
4983
- }
5048
+ const { activity: signedActivity, proofCreated } = await signOutgoingActivity(activity, actorKeyPairs == null ? keys.map(({ keyId, privateKey }) => ({
5049
+ verificationMethod: keyId,
5050
+ privateKey
5051
+ })) : actorKeyPairs.flatMap((kp) => kp.multikey.id == null ? [] : [{
5052
+ verificationMethod: kp.multikey.id,
5053
+ privateKey: kp.privateKey
5054
+ }]), {
5055
+ contextLoader: this.contextLoader,
5056
+ tracerProvider: this.tracerProvider,
5057
+ appendToExistingProofs: actorKeyPairs != null
5058
+ });
5059
+ activity = signedActivity;
4984
5060
  const inboxes = extractInboxes({
4985
5061
  recipients: expandedRecipients,
4986
5062
  preferSharedInbox: options.preferSharedInbox,
@@ -5005,6 +5081,11 @@ var ContextImpl = class ContextImpl {
5005
5081
  });
5006
5082
  return true;
5007
5083
  }
5084
+ const activityJsonLd = await activity.toJsonLd({
5085
+ format: "compact",
5086
+ contextLoader: this.contextLoader
5087
+ });
5088
+ assertSupportedCompoundProofShape(activityJsonLd, activity.id?.href);
5008
5089
  const keyJwkPairs = await Promise.all(keys.map(async ({ keyId, privateKey }) => ({
5009
5090
  keyId: keyId.href,
5010
5091
  privateKey: await exportJwk(privateKey)
@@ -5020,10 +5101,7 @@ var ContextImpl = class ContextImpl {
5020
5101
  actorIds: [...actorIds],
5021
5102
  sharedInbox
5022
5103
  }])),
5023
- activity: await activity.toJsonLd({
5024
- format: "compact",
5025
- contextLoader: this.contextLoader
5026
- }),
5104
+ activity: activityJsonLd,
5027
5105
  activityId: activity.id?.href,
5028
5106
  activityType: getTypeId(activity).href,
5029
5107
  collectionSync: opts.collectionSync,
@@ -2,16 +2,16 @@ import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { t as __exportAll } from "./rolldown-runtime-BC-Eo5Mj.js";
4
4
  import { r as getDefaultActivityTransformers } from "./transformers-DAtXl_Kc.js";
5
- import { A as recordWebFingerHandle, C as recordCollectionRequest, D as recordInboxActivity, E as recordFanoutRecipients, I as name, L as version, M as formatAcceptSignature, O as recordOutboxActivity, S as recordCollectionPageItems, _ as instrumentDocumentLoader, a as verifyRequestDetailed, b as recordCircuitBreakerStateChange, d as importJwk, f as validateCryptoKey, g as getRemoteHost, h as getFederationMetrics, i as verifyRequest, j as registerQueueDepthGauge, k as recordOutboxEnqueue, m as getDurationMs, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as isAbortError, w as recordCollectionTotalItems, x as recordCollectionDispatchDuration } from "./http-KZWtR1H8.js";
5
+ import { A as recordWebFingerHandle, C as recordCollectionRequest, D as recordInboxActivity, E as recordFanoutRecipients, I as name, L as version, M as formatAcceptSignature, O as recordOutboxActivity, S as recordCollectionPageItems, _ as instrumentDocumentLoader, a as verifyRequestDetailed, b as recordCircuitBreakerStateChange, d as importJwk, f as validateCryptoKey, g as getRemoteHost, h as getFederationMetrics, i as verifyRequest, j as registerQueueDepthGauge, k as recordOutboxEnqueue, m as getDurationMs, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as isAbortError, w as recordCollectionTotalItems, x as recordCollectionDispatchDuration } from "./http-By8tnmEr.js";
6
6
  import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-C_cNlNVK.js";
7
- import { C as verifyCompactJsonLd, D as normalizeOutgoingActivityJsonLd, E as wrapContextLoaderForJsonLd, S as signJsonLd, _ as getNormalizationContextLoader, a as signObject, b as isClearlyMalformedContextReference, d as InvalidContextReferenceError, f as assertSafeJsonLd, g as detachSignature, i as hasProofLike, l as verifyPortableObjectProofPolicy, m as compactJsonLd, n as getKeyOwner, o as verifyMapLocalProof, s as verifyObject, t as doesActorOwnKey, v as hasSignature, x as isInvalidUrlTypeError, y as hasSignatureLike } from "./owner-B7lgRMdU.js";
8
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-HOO6BsuW.js";
7
+ import { C as verifyCompactJsonLd, D as normalizeOutgoingActivityJsonLd, E as wrapContextLoaderForJsonLd, S as signJsonLd, _ as getNormalizationContextLoader, a as signObject, b as isClearlyMalformedContextReference, d as InvalidContextReferenceError, f as assertSafeJsonLd, g as detachSignature, i as hasProofLike, l as verifyPortableObjectProofPolicy, m as compactJsonLd, n as getKeyOwner, o as verifyMapLocalProof, s as verifyObject, t as doesActorOwnKey, v as hasSignature, x as isInvalidUrlTypeError, y as hasSignatureLike } from "./owner-D-E0bT2O.js";
8
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BswMKQjC.js";
9
9
  import { getLogger, withContext } from "@logtape/logtape";
10
10
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
11
11
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
12
12
  import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
13
13
  import { encodeHex } from "byte-encodings/hex";
14
- import { FetchError, UrlError, getDocumentLoader, validatePublicUrl } from "@fedify/vocab-runtime";
14
+ import { FetchError, UrlError, getDocumentLoader, getFe34Origin, haveSameFe34Origin, validatePublicUrl } from "@fedify/vocab-runtime";
15
15
  import { uniq } from "es-toolkit";
16
16
  import jsonld from "@fedify/vocab-runtime/jsonld";
17
17
  import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
@@ -1643,6 +1643,78 @@ function inspectCompoundPortableObjectApplicability(json, limits) {
1643
1643
  return "absent";
1644
1644
  }
1645
1645
  /**
1646
+ * Walks every JSON map in a finite, already-materialized JSON tree, depth
1647
+ * first in insertion order, skipping the values of `proof` and `@context`
1648
+ * members. A map reached a second time through a repeated reference is not
1649
+ * visited again, so a cyclic input terminates. The walk stops as soon as
1650
+ * the visitor returns a value other than `undefined`.
1651
+ */
1652
+ function findInJsonMaps(json, visit) {
1653
+ const seen = /* @__PURE__ */ new Set();
1654
+ const pending = [{
1655
+ value: json,
1656
+ path: ""
1657
+ }];
1658
+ while (pending.length > 0) {
1659
+ const { value, path } = pending.pop();
1660
+ if (typeof value !== "object" || value == null || seen.has(value)) continue;
1661
+ seen.add(value);
1662
+ if (Array.isArray(value)) {
1663
+ for (let index = value.length - 1; index >= 0; index--) pending.push({
1664
+ value: value[index],
1665
+ path: childPath(path, String(index))
1666
+ });
1667
+ continue;
1668
+ }
1669
+ const map = value;
1670
+ const result = visit(map, path);
1671
+ if (result !== void 0) return result;
1672
+ const keys = Object.keys(map);
1673
+ for (let index = keys.length - 1; index >= 0; index--) {
1674
+ const key = keys[index];
1675
+ if (key === "proof" || key === "@context") continue;
1676
+ pending.push({
1677
+ value: map[key],
1678
+ path: childPath(path, key)
1679
+ });
1680
+ }
1681
+ }
1682
+ }
1683
+ /**
1684
+ * Determines whether an outgoing JSON tree contains portable content that
1685
+ * requires producer-side proof-shape checks: a map, outside proof and context
1686
+ * values, whose direct `id` or `@id` is a portable ActivityPub URI.
1687
+ *
1688
+ * This deliberately differs from
1689
+ * {@link inspectCompoundPortableObjectApplicability}: it applies no resource
1690
+ * limits, so a portable map or an unsupported proof beyond the inbox limits
1691
+ * is still found, and a large document without portable maps stays outside
1692
+ * the compound-proof profile. The input must be a finite JSON tree that has
1693
+ * already been materialized, such as a compact JSON-LD document about to be
1694
+ * sent.
1695
+ *
1696
+ * @internal
1697
+ */
1698
+ function containsCompoundPortableObject(json) {
1699
+ return findInJsonMaps(json, (map) => [map.id, map["@id"]].some((id) => typeof id === "string" && PORTABLE_OBJECT_ID_PATTERN.test(id)) ? true : void 0) ?? false;
1700
+ }
1701
+ /**
1702
+ * Finds the first direct `proof` member whose value the map-local
1703
+ * compound-proof profile does not accept, i.e., anything other than a single
1704
+ * JSON map: a proof set, `null`, or a scalar. Like the inbox discovery, it
1705
+ * does not look inside proof or context values.
1706
+ *
1707
+ * The input must be a finite, already-materialized JSON tree; see
1708
+ * {@link containsCompoundPortableObject}.
1709
+ *
1710
+ * @returns The RFC 6901 JSON Pointer to the unsupported `proof` member, or
1711
+ * `null` if every direct proof is a single JSON map.
1712
+ * @internal
1713
+ */
1714
+ function findUnsupportedCompoundProofShape(json) {
1715
+ return findInJsonMaps(json, (map, path) => Object.hasOwn(map, "proof") && !isJsonMap(map.proof) ? childPath(path, "proof") : void 0) ?? null;
1716
+ }
1717
+ /**
1646
1718
  * Discovers direct literal proof-bearing maps in an immutable JSON snapshot.
1647
1719
  *
1648
1720
  * Discovery is bounded and atomic. Unsupported proof shapes, non-JSON input,
@@ -4535,6 +4607,102 @@ function serializeDataPointType(dataPointType) {
4535
4607
  }
4536
4608
  }
4537
4609
  //#endregion
4610
+ //#region src/federation/outgoing-proof.ts
4611
+ function isPortableUrl(url) {
4612
+ return url.protocol === "ap:" || url.protocol === "ap+ef61:";
4613
+ }
4614
+ function formatKeyIds(candidates) {
4615
+ return candidates.map((c) => c.verificationMethod.href).join(", ");
4616
+ }
4617
+ /**
4618
+ * Creates the Object Integrity Proofs Fedify attaches to an outgoing activity.
4619
+ *
4620
+ * Outside the map-local compound-proof profile, i.e., when the activity
4621
+ * embeds no portable object, every Ed25519 key signs the activity, as it
4622
+ * always has. Inside the profile, which accepts exactly one direct proof per
4623
+ * map, Fedify creates at most one proof:
4624
+ *
4625
+ * - An activity that already carries a proof is kept as is.
4626
+ * - A single Ed25519 key signs the activity.
4627
+ * - With several Ed25519 keys, a portable activity is signed by the one key
4628
+ * whose verification method is a DID URL for the activity's DID, the only
4629
+ * proof the FEP-ef61 policy can accept. If no key or more than one key
4630
+ * qualifies, or the activity is not portable itself, the choice is
4631
+ * ambiguous and this function throws.
4632
+ *
4633
+ * @throws {TypeError} If a single proof key cannot be chosen.
4634
+ * @internal
4635
+ */
4636
+ async function signOutgoingActivity(activity, candidates, options) {
4637
+ const { contextLoader, tracerProvider } = options;
4638
+ let hasProof = false;
4639
+ for await (const _ of activity.getProofs({ contextLoader })) {
4640
+ hasProof = true;
4641
+ break;
4642
+ }
4643
+ const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519");
4644
+ if (keys.length < 1 || hasProof && !options.appendToExistingProofs) return {
4645
+ activity,
4646
+ hasProof,
4647
+ proofCreated: false
4648
+ };
4649
+ const sign = async (selected) => {
4650
+ for (const { verificationMethod, privateKey } of selected) activity = await signObject(activity, privateKey, verificationMethod, {
4651
+ contextLoader,
4652
+ tracerProvider
4653
+ });
4654
+ return {
4655
+ activity,
4656
+ hasProof: true,
4657
+ proofCreated: true
4658
+ };
4659
+ };
4660
+ if (keys.length < 2 && !hasProof) return await sign(keys);
4661
+ if (!containsCompoundPortableObject(await activity.toJsonLd({
4662
+ format: "compact",
4663
+ contextLoader
4664
+ }))) return await sign(keys);
4665
+ const logger = getLogger([
4666
+ "fedify",
4667
+ "federation",
4668
+ "outbox"
4669
+ ]);
4670
+ const activityId = activity.id?.href;
4671
+ if (hasProof) {
4672
+ logger.debug("The activity {activityId} embeds portable objects and already carries a proof, so no further proof is added; the map-local compound-proof profile accepts exactly one direct proof per map.", { activityId });
4673
+ return {
4674
+ activity,
4675
+ hasProof,
4676
+ proofCreated: false
4677
+ };
4678
+ }
4679
+ if (activity.id == null || !isPortableUrl(activity.id)) throw new TypeError(`Cannot choose an Object Integrity Proof key for the activity ${activityId}: it embeds portable objects, so it falls under the map-local compound-proof profile, which accepts exactly one direct proof per map, but ${keys.length} Ed25519 keys were supplied (${formatKeyIds(keys)}). Send it with explicit sender keys that contain exactly one Ed25519 key (RSA keys for HTTP Signatures may stay), or sign it with signObject() before sending it.`);
4680
+ const activityDid = getFe34Origin(activity.id);
4681
+ const eligible = keys.filter((c) => c.verificationMethod.protocol === "did:" && haveSameFe34Origin(activity.id, c.verificationMethod));
4682
+ if (eligible.length !== 1) throw new TypeError(`Cannot choose an Object Integrity Proof key for the portable activity ${activityId}: ` + (eligible.length < 1 ? `none of its ${keys.length} Ed25519 keys (${formatKeyIds(keys)}) ` : `${eligible.length} of its Ed25519 keys (${formatKeyIds(eligible)}) `) + `${eligible.length < 1 ? "is" : "are"} a DID URL verification method for ${activityDid}. The map-local compound-proof profile accepts exactly one direct proof per map, and FEP-ef61 requires that proof's verification method to be a DID URL for the activity's DID. Supply exactly one Ed25519 key whose key ID is a DID URL for ${activityDid}, or sign the activity with signObject() before sending it.`);
4683
+ logger.debug("The portable activity {activityId} is signed only by {keyId}, the one Ed25519 key whose verification method matches its DID; the map-local compound-proof profile accepts exactly one direct proof per map.", {
4684
+ activityId,
4685
+ keyId: eligible[0].verificationMethod.href
4686
+ });
4687
+ return await sign(eligible);
4688
+ }
4689
+ /**
4690
+ * Rejects an outgoing activity whose proofs Fedify's own inbox would reject
4691
+ * as unsupported: a document with portable objects in which some map carries
4692
+ * a proof set or another value that is not a single proof map.
4693
+ *
4694
+ * @param jsonLd The compact JSON-LD document about to be delivered.
4695
+ * @param activityId The activity ID, for the error message.
4696
+ * @throws {TypeError} If the document has an unsupported proof shape.
4697
+ * @internal
4698
+ */
4699
+ function assertSupportedCompoundProofShape(jsonLd, activityId) {
4700
+ if (!containsCompoundPortableObject(jsonLd)) return;
4701
+ const path = findUnsupportedCompoundProofShape(jsonLd);
4702
+ if (path == null) return;
4703
+ throw new TypeError(`Cannot send the activity ${activityId}: it embeds portable objects, but its proof at the JSON Pointer ${JSON.stringify(path)} is not a single proof map. The map-local compound-proof profile accepts exactly one direct proof per map, so Fedify inboxes would reject the activity. Sign each object with exactly one key.`);
4704
+ }
4705
+ //#endregion
4538
4706
  //#region src/federation/retry.ts
4539
4707
  /**
4540
4708
  * Creates an exponential backoff retry policy. The delay between retries
@@ -6342,8 +6510,6 @@ var FederationImpl = class extends FederationBuilderImpl {
6342
6510
  else if (keys.length < 1) throw new TypeError("The keys must not be empty.");
6343
6511
  const contextLoader = this.contextLoaderFactory(this.#getLoaderOptions(ctx.origin));
6344
6512
  const activityId = activity.id.href;
6345
- let hasProof = false;
6346
- let proofCreated = false;
6347
6513
  let rsaKey = null;
6348
6514
  for (const { keyId, privateKey } of keys) {
6349
6515
  validateCryptoKey(privateKey, "private");
@@ -6352,25 +6518,22 @@ var FederationImpl = class extends FederationBuilderImpl {
6352
6518
  privateKey
6353
6519
  };
6354
6520
  }
6355
- for await (const _ of activity.getProofs({ contextLoader })) {
6356
- hasProof = true;
6357
- break;
6358
- }
6359
- if (!hasProof) {
6360
- for (const { keyId, privateKey } of keys) if (privateKey.algorithm.name === "Ed25519") {
6361
- activity = await signObject(activity, privateKey, keyId, {
6362
- contextLoader,
6363
- tracerProvider: this.tracerProvider
6364
- });
6365
- hasProof = true;
6366
- proofCreated = true;
6367
- }
6368
- }
6521
+ const signed = await signOutgoingActivity(activity, keys.map(({ keyId, privateKey }) => ({
6522
+ verificationMethod: keyId,
6523
+ privateKey
6524
+ })), {
6525
+ contextLoader,
6526
+ tracerProvider: this.tracerProvider,
6527
+ appendToExistingProofs: false
6528
+ });
6529
+ activity = signed.activity;
6530
+ const { hasProof, proofCreated } = signed;
6369
6531
  let jsonLd = !proofCreated && options.activityJsonLd != null ? options.activityJsonLd : await activity.toJsonLd({
6370
6532
  format: "compact",
6371
6533
  contextLoader
6372
6534
  });
6373
6535
  if (proofCreated || !hasProof || options.normalizeExistingProofs) jsonLd = await normalizeOutgoingActivityJsonLd(jsonLd, contextLoader, { preserveNestedSecuredDocuments: true });
6536
+ assertSupportedCompoundProofShape(jsonLd, activityId);
6374
6537
  if (rsaKey == null) logger.warn("No supported key found to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature. In order to create a Linked Data signature, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
6375
6538
  activityId,
6376
6539
  keys: keys.map((pair) => ({
@@ -7342,33 +7505,18 @@ var ContextImpl = class ContextImpl {
7342
7505
  });
7343
7506
  throw new TypeError("The activity to send must have at least one actor property.");
7344
7507
  }
7345
- let proofCreated = false;
7346
- if (actorKeyPairs != null) {
7347
- const contextLoader = this.contextLoader;
7348
- for (const kp of actorKeyPairs) {
7349
- if (kp.privateKey.algorithm.name !== "Ed25519" || kp.multikey.id == null) continue;
7350
- activity = await signObject(activity, kp.privateKey, kp.multikey.id, {
7351
- contextLoader,
7352
- tracerProvider: this.tracerProvider
7353
- });
7354
- proofCreated = true;
7355
- }
7356
- } else {
7357
- const contextLoader = this.contextLoader;
7358
- let hasProof = false;
7359
- for await (const _ of activity.getProofs({ contextLoader })) {
7360
- hasProof = true;
7361
- break;
7362
- }
7363
- if (!hasProof) for (const { keyId, privateKey } of keys) {
7364
- if (privateKey.algorithm.name !== "Ed25519") continue;
7365
- activity = await signObject(activity, privateKey, keyId, {
7366
- contextLoader,
7367
- tracerProvider: this.tracerProvider
7368
- });
7369
- proofCreated = true;
7370
- }
7371
- }
7508
+ const { activity: signedActivity, proofCreated } = await signOutgoingActivity(activity, actorKeyPairs == null ? keys.map(({ keyId, privateKey }) => ({
7509
+ verificationMethod: keyId,
7510
+ privateKey
7511
+ })) : actorKeyPairs.flatMap((kp) => kp.multikey.id == null ? [] : [{
7512
+ verificationMethod: kp.multikey.id,
7513
+ privateKey: kp.privateKey
7514
+ }]), {
7515
+ contextLoader: this.contextLoader,
7516
+ tracerProvider: this.tracerProvider,
7517
+ appendToExistingProofs: actorKeyPairs != null
7518
+ });
7519
+ activity = signedActivity;
7372
7520
  const inboxes = extractInboxes({
7373
7521
  recipients: expandedRecipients,
7374
7522
  preferSharedInbox: options.preferSharedInbox,
@@ -7393,6 +7541,11 @@ var ContextImpl = class ContextImpl {
7393
7541
  });
7394
7542
  return true;
7395
7543
  }
7544
+ const activityJsonLd = await activity.toJsonLd({
7545
+ format: "compact",
7546
+ contextLoader: this.contextLoader
7547
+ });
7548
+ assertSupportedCompoundProofShape(activityJsonLd, activity.id?.href);
7396
7549
  const keyJwkPairs = await Promise.all(keys.map(async ({ keyId, privateKey }) => ({
7397
7550
  keyId: keyId.href,
7398
7551
  privateKey: await exportJwk(privateKey)
@@ -7408,10 +7561,7 @@ var ContextImpl = class ContextImpl {
7408
7561
  actorIds: [...actorIds],
7409
7562
  sharedInbox
7410
7563
  }])),
7411
- activity: await activity.toJsonLd({
7412
- format: "compact",
7413
- contextLoader: this.contextLoader
7414
- }),
7564
+ activity: activityJsonLd,
7415
7565
  activityId: activity.id?.href,
7416
7566
  activityType: getTypeId(activity).href,
7417
7567
  collectionSync: opts.collectionSync,
package/dist/mod.cjs CHANGED
@@ -3,11 +3,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("./rolldown-runtime-Dmm3t92W.cjs");
4
4
  const require_transformers = require("./transformers-BalCrSsr.cjs");
5
5
  require("./compat/mod.cjs");
6
- const require_http = require("./http-CWXKwHPv.cjs");
7
- const require_federation = require("./federation-C0ijTwhx.cjs");
6
+ const require_http = require("./http-B5F1JMh0.cjs");
7
+ const require_federation = require("./federation-CTnaljmy.cjs");
8
8
  const require_types = require("./types-Be2zbyeG.cjs");
9
- const require_owner = require("./owner-DffLVeYC.cjs");
10
- const require_kv_cache = require("./kv-cache-Dos4tOWb.cjs");
9
+ const require_owner = require("./owner-WUYke16i.cjs");
10
+ const require_kv_cache = require("./kv-cache-8K70pjtX.cjs");
11
11
  require("./nodeinfo/mod.cjs");
12
12
  require("./runtime/mod.cjs");
13
13
  require("./sig/mod.cjs");
package/dist/mod.js CHANGED
@@ -3,11 +3,11 @@ import { URLPattern } from "urlpattern-polyfill";
3
3
  import "./rolldown-runtime-BC-Eo5Mj.js";
4
4
  import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-DAtXl_Kc.js";
5
5
  import "./compat/mod.js";
6
- import { F as validateAcceptSignature, M as formatAcceptSignature, N as fulfillAcceptSignature, P as parseAcceptSignature, a as verifyRequestDetailed, c as fetchKey, d as importJwk, i as verifyRequest, l as fetchKeyDetailed, o as exportJwk, r as signRequest, u as generateCryptoKeyPair } from "./http-KZWtR1H8.js";
7
- import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "./middleware-iffqYoTV.js";
6
+ import { F as validateAcceptSignature, M as formatAcceptSignature, N as fulfillAcceptSignature, P as parseAcceptSignature, a as verifyRequestDetailed, c as fetchKey, d as importJwk, i as verifyRequest, l as fetchKeyDetailed, o as exportJwk, r as signRequest, u as generateCryptoKeyPair } from "./http-By8tnmEr.js";
7
+ import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "./middleware-Cxto6Bq2.js";
8
8
  import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-C_cNlNVK.js";
9
- import { S as signJsonLd, T as verifySignature, a as signObject, c as verifyPortableObjectProof, g as detachSignature, h as createSignature, i as hasProofLike, n as getKeyOwner, p as attachSignature, r as createProof, s as verifyObject, t as doesActorOwnKey, u as verifyProof, w as verifyJsonLd, y as hasSignatureLike } from "./owner-B7lgRMdU.js";
10
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-HOO6BsuW.js";
9
+ import { S as signJsonLd, T as verifySignature, a as signObject, c as verifyPortableObjectProof, g as detachSignature, h as createSignature, i as hasProofLike, n as getKeyOwner, p as attachSignature, r as createProof, s as verifyObject, t as doesActorOwnKey, u as verifyProof, w as verifyJsonLd, y as hasSignatureLike } from "./owner-D-E0bT2O.js";
10
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BswMKQjC.js";
11
11
  import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue, Router, RouterError } from "./federation/mod.js";
12
12
  import "./nodeinfo/mod.js";
13
13
  import "./runtime/mod.js";
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-CbS35fLr.mjs";
5
5
  import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
7
7
  import "../std__assert-DvMDRPes.mjs";
8
- import { _ as handleNodeInfo, o as createFederation, v as handleNodeInfoJrd } from "../middleware-BsYD_ufs.mjs";
8
+ import { _ as handleNodeInfo, o as createFederation, v as handleNodeInfoJrd } from "../middleware-C7_hqDnl.mjs";
9
9
  import { test } from "@fedify/fixture";
10
10
  //#region src/nodeinfo/handler.test.ts
11
11
  test("handleNodeInfo()", async () => {
@@ -1,8 +1,8 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-BcZNXlJn.mjs";
5
- import { c as verifyKeyOwnership, n as fetchActorDocument, t as exportJwk } from "./key-Xb1hVVZO.mjs";
4
+ import { n as version, t as name } from "./deno-Vj_9wePq.mjs";
5
+ import { c as verifyKeyOwnership, n as fetchActorDocument, t as exportJwk } from "./key-B_Zc5Jbd.mjs";
6
6
  import { getLogger } from "@logtape/logtape";
7
7
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
8
8
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";