@fedify/fedify 2.4.0-dev.2077 → 2.4.0-dev.2084
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/dist/{builder-i3jxVe9m.mjs → builder-BGlpUocK.mjs} +2 -2
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-Cayy-ECj.mjs → compound-proof-B6Aj2kGY.mjs} +1 -1
- package/dist/{deno-Djkzd-G_.mjs → deno-Dn-py9Zy.mjs} +1 -1
- package/dist/{docloader-dA0RswUV.mjs → docloader-BUq5bYJr.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +5 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +7 -7
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- package/dist/federation/portable-gateway-keys.test.mjs +3 -3
- package/dist/federation/portable-inbox.test.mjs +401 -6
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{federation-CFd0Jhhv.cjs → federation-BLGx8JUH.cjs} +115 -12
- package/dist/{http-aqh3yFdM.js → http-4PCCvhsU.js} +1 -1
- package/dist/{http-CCJ97Jql.mjs → http-B0VRNipE.mjs} +4 -4
- package/dist/{http-Dvy_IwRa.cjs → http-B5q1CHtL.cjs} +1 -1
- package/dist/{key-IxTTC8Yf.mjs → key-BJrp524f.mjs} +2 -2
- package/dist/{kv-cache-Y6SDRSX6.js → kv-cache-1KUmAPH7.js} +1 -1
- package/dist/{kv-cache-Bwwbh-xR.mjs → kv-cache-C4C3LyYW.mjs} +1 -1
- package/dist/{kv-cache-BP69NV0P.cjs → kv-cache-Dhhhrryv.cjs} +1 -1
- package/dist/{ld-l0B9nREb.mjs → ld-BmFz5NLA.mjs} +3 -3
- package/dist/{metrics-D1p6hv4z.mjs → metrics-Beod6tzO.mjs} +1 -1
- package/dist/{middleware-BDjCUHMS.mjs → middleware-B7CNsyqt.mjs} +1 -1
- package/dist/{middleware-BMgzqBtr.mjs → middleware-BKeQYPm0.mjs} +125 -22
- package/dist/{middleware-SSfryVzY.js → middleware-D_9pNYe9.js} +115 -12
- package/dist/mod.cjs +5 -5
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-BpOxL5PG.cjs → owner-BQFZtFV4.cjs} +1 -1
- package/dist/{owner-DGbYmXqU.mjs → owner-CsKVgMzk.mjs} +3 -3
- package/dist/{owner-jH1z_YfD.js → owner-_pbbgLJK.js} +1 -1
- package/dist/{portable-key-CCwJGSsU.mjs → portable-key-B4R-CiIV.mjs} +2 -2
- package/dist/{proof-CVL7JnZd.mjs → proof-ozG4HfcQ.mjs} +4 -4
- package/dist/{send-Ejy1jOz9.mjs → send-ClPt8nYu.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +3 -3
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +2 -2
- package/dist/sig/portable-key.test.mjs +3 -3
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{sig-Dpy1B1Ad.js → sig-DhdomAN0.js} +2 -2
- package/dist/{sig-xoqy3ATq.cjs → sig-k3C8sF7g.cjs} +2 -2
- package/dist/{temporal-DNJ1cNpr.mjs → temporal-Ba0EAZAI.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
2
|
const require_rolldown_runtime = require("./rolldown-runtime-Dmm3t92W.cjs");
|
|
3
3
|
const require_transformers = require("./transformers-BalCrSsr.cjs");
|
|
4
|
-
const require_http = require("./http-
|
|
4
|
+
const require_http = require("./http-B5q1CHtL.cjs");
|
|
5
5
|
const require_types = require("./types-Be2zbyeG.cjs");
|
|
6
|
-
const require_owner = require("./owner-
|
|
7
|
-
const require_kv_cache = require("./kv-cache-
|
|
6
|
+
const require_owner = require("./owner-BQFZtFV4.cjs");
|
|
7
|
+
const require_kv_cache = require("./kv-cache-Dhhhrryv.cjs");
|
|
8
8
|
let _logtape_logtape = require("@logtape/logtape");
|
|
9
9
|
let _fedify_uri_template = require("@fedify/uri-template");
|
|
10
10
|
let _fedify_vocab = require("@fedify/vocab");
|
|
@@ -5059,6 +5059,7 @@ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, loc
|
|
|
5059
5059
|
return {
|
|
5060
5060
|
status: "accepted",
|
|
5061
5061
|
recipient: {
|
|
5062
|
+
actorId: id,
|
|
5062
5063
|
inboxId,
|
|
5063
5064
|
canonicalInboxId,
|
|
5064
5065
|
gateways
|
|
@@ -5092,8 +5093,11 @@ function canonicalize(iri) {
|
|
|
5092
5093
|
* Forwarding is therefore best effort. Without {@link KvStore.cas}, nothing is
|
|
5093
5094
|
* forwarded.
|
|
5094
5095
|
*
|
|
5095
|
-
* Forwarded requests are
|
|
5096
|
-
*
|
|
5096
|
+
* Forwarded requests are signed with HTTP Signatures by the RSA key among
|
|
5097
|
+
* {@link ForwardPortableInboxActivityParameters.getKeys}, if any, so that
|
|
5098
|
+
* servers requiring HTTP Signatures accept them, and are sent unsigned
|
|
5099
|
+
* otherwise. Either way, the receiving gateways authenticate the activity by
|
|
5100
|
+
* its own proof.
|
|
5097
5101
|
* @param parameters The parameters.
|
|
5098
5102
|
* @returns The target inbox URLs that the activity was handed off to.
|
|
5099
5103
|
*/
|
|
@@ -5165,20 +5169,59 @@ function getForwardingTargets(recipient, excludedOrigins) {
|
|
|
5165
5169
|
}
|
|
5166
5170
|
return targets;
|
|
5167
5171
|
}
|
|
5168
|
-
|
|
5172
|
+
/**
|
|
5173
|
+
* Resolves the key that signs forwarded requests: the first RSASSA-PKCS1-v1_5
|
|
5174
|
+
* key, as {@link sendActivity} signs requests only with such a key. Since
|
|
5175
|
+
* the targets have already been claimed, the activity is forwarded unsigned
|
|
5176
|
+
* rather than not at all if the key cannot be resolved or used.
|
|
5177
|
+
*/
|
|
5178
|
+
async function resolveForwardingKey({ getKeys, activityId }) {
|
|
5179
|
+
if (getKeys == null) return null;
|
|
5180
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
5181
|
+
"fedify",
|
|
5182
|
+
"federation",
|
|
5183
|
+
"inbox"
|
|
5184
|
+
]);
|
|
5185
|
+
let key;
|
|
5186
|
+
try {
|
|
5187
|
+
key = (await getKeys()).find((k) => k.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5");
|
|
5188
|
+
} catch (error) {
|
|
5189
|
+
logger.error("Failed to get the gateway keys to sign forwarded requests with; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
|
|
5190
|
+
activityId: activityId.href,
|
|
5191
|
+
error
|
|
5192
|
+
});
|
|
5193
|
+
return null;
|
|
5194
|
+
}
|
|
5195
|
+
if (key == null) return null;
|
|
5196
|
+
try {
|
|
5197
|
+
require_http.validateCryptoKey(key.privateKey, "private");
|
|
5198
|
+
} catch (error) {
|
|
5199
|
+
if (!(error instanceof TypeError)) throw error;
|
|
5200
|
+
logger.warn("The gateway key {keyId} cannot sign forwarded requests; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
|
|
5201
|
+
keyId: key.keyId.href,
|
|
5202
|
+
activityId: activityId.href,
|
|
5203
|
+
error
|
|
5204
|
+
});
|
|
5205
|
+
return null;
|
|
5206
|
+
}
|
|
5207
|
+
return key;
|
|
5208
|
+
}
|
|
5209
|
+
async function forwardImmediately(parameters, inboxes) {
|
|
5210
|
+
const { activity, activityId, activityType, allowPrivateAddress, specDeterminer, options, meterProvider, tracerProvider } = parameters;
|
|
5169
5211
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
5170
5212
|
"fedify",
|
|
5171
5213
|
"federation",
|
|
5172
5214
|
"inbox"
|
|
5173
5215
|
]);
|
|
5174
5216
|
const deadline = (options ?? resolvePortableInboxForwardingOptions()).deadline.total("millisecond");
|
|
5175
|
-
const
|
|
5217
|
+
const forwarding = resolveForwardingKey(parameters).then((key) => Promise.all(inboxes.map((inbox) => sendActivity({
|
|
5176
5218
|
activity,
|
|
5177
5219
|
activityId: activityId.href,
|
|
5178
5220
|
activityType,
|
|
5179
|
-
keys: [],
|
|
5221
|
+
keys: key == null ? [] : [key],
|
|
5180
5222
|
inbox,
|
|
5181
5223
|
allowPrivateAddress,
|
|
5224
|
+
specDeterminer,
|
|
5182
5225
|
meterProvider,
|
|
5183
5226
|
tracerProvider
|
|
5184
5227
|
}).catch((error) => {
|
|
@@ -5187,9 +5230,9 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
|
|
|
5187
5230
|
inbox: inbox.href,
|
|
5188
5231
|
error
|
|
5189
5232
|
});
|
|
5190
|
-
}));
|
|
5233
|
+
}))));
|
|
5191
5234
|
let timer;
|
|
5192
|
-
const timedOut = await Promise.race([
|
|
5235
|
+
const timedOut = await Promise.race([forwarding.then(() => false), new Promise((resolve) => {
|
|
5193
5236
|
timer = setTimeout(() => resolve(true), deadline);
|
|
5194
5237
|
})]);
|
|
5195
5238
|
clearTimeout(timer);
|
|
@@ -5198,12 +5241,27 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
|
|
|
5198
5241
|
deadline
|
|
5199
5242
|
});
|
|
5200
5243
|
}
|
|
5201
|
-
async function enqueueForwarding(
|
|
5244
|
+
async function enqueueForwarding(parameters, outboxQueue, inboxes) {
|
|
5245
|
+
const { activity, activityId, activityType, baseUrl, startQueue, meterProvider } = parameters;
|
|
5202
5246
|
const logger = (0, _logtape_logtape.getLogger)([
|
|
5203
5247
|
"fedify",
|
|
5204
5248
|
"federation",
|
|
5205
5249
|
"inbox"
|
|
5206
5250
|
]);
|
|
5251
|
+
const key = await resolveForwardingKey(parameters);
|
|
5252
|
+
const keys = [];
|
|
5253
|
+
if (key != null) try {
|
|
5254
|
+
keys.push({
|
|
5255
|
+
keyId: key.keyId.href,
|
|
5256
|
+
privateKey: await require_http.exportJwk(key.privateKey)
|
|
5257
|
+
});
|
|
5258
|
+
} catch (error) {
|
|
5259
|
+
logger.error("Failed to export the gateway key {keyId}; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
|
|
5260
|
+
keyId: key.keyId.href,
|
|
5261
|
+
activityId: activityId.href,
|
|
5262
|
+
error
|
|
5263
|
+
});
|
|
5264
|
+
}
|
|
5207
5265
|
startQueue?.();
|
|
5208
5266
|
const started = (/* @__PURE__ */ new Date()).toISOString();
|
|
5209
5267
|
const traceContext = {};
|
|
@@ -5213,7 +5271,7 @@ async function enqueueForwarding({ activity, activityId, activityType, baseUrl,
|
|
|
5213
5271
|
type: "outbox",
|
|
5214
5272
|
id: crypto.randomUUID(),
|
|
5215
5273
|
baseUrl,
|
|
5216
|
-
keys
|
|
5274
|
+
keys,
|
|
5217
5275
|
activity,
|
|
5218
5276
|
activityId: activityId.href,
|
|
5219
5277
|
activityType,
|
|
@@ -7896,6 +7954,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
7896
7954
|
outboxQueue: this.outboxQueue,
|
|
7897
7955
|
startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
|
|
7898
7956
|
allowPrivateAddress: this.allowPrivateAddress,
|
|
7957
|
+
getKeys: () => this.#getPortableGatewayKeyPairs(context, identifier, recipient),
|
|
7958
|
+
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, this.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
|
|
7899
7959
|
options: this.portableInboxForwarding,
|
|
7900
7960
|
meterProvider: this.meterProvider,
|
|
7901
7961
|
tracerProvider: this.tracerProvider
|
|
@@ -7904,6 +7964,49 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
7904
7964
|
}
|
|
7905
7965
|
});
|
|
7906
7966
|
}
|
|
7967
|
+
/**
|
|
7968
|
+
* Gets this server's gateway key pairs for the portable actor that owns
|
|
7969
|
+
* a portable inbox, which sign the activities forwarded from the inbox.
|
|
7970
|
+
* @param context The context.
|
|
7971
|
+
* @param identifier The identifier of the portable actor.
|
|
7972
|
+
* @param recipient The portable inbox.
|
|
7973
|
+
* @returns The key pairs, or an empty array if the actor has no gateway
|
|
7974
|
+
* keys on this server.
|
|
7975
|
+
*/
|
|
7976
|
+
async #getPortableGatewayKeyPairs(context, identifier, recipient) {
|
|
7977
|
+
const logger = (0, _logtape_logtape.getLogger)([
|
|
7978
|
+
"fedify",
|
|
7979
|
+
"federation",
|
|
7980
|
+
"inbox"
|
|
7981
|
+
]);
|
|
7982
|
+
if (this.actorCallbacks?.keyPairsDispatcher == null || this.actorCallbacks.portableActorIdMapper == null) {
|
|
7983
|
+
logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as gateway keys need both a key pairs dispatcher and a portable actor ID mapper.", { inbox: recipient.canonicalInboxId });
|
|
7984
|
+
return [];
|
|
7985
|
+
}
|
|
7986
|
+
const actorId = require_http.getCanonicalPortableId(recipient.actorId);
|
|
7987
|
+
if (actorId == null) return [];
|
|
7988
|
+
const keyPairs = await context.getActorKeyPairs(identifier);
|
|
7989
|
+
for (const { cryptographicKey } of keyPairs) {
|
|
7990
|
+
const owner = cryptographicKey.ownerId;
|
|
7991
|
+
const canonicalOwner = owner == null ? null : require_http.getCanonicalPortableId(owner);
|
|
7992
|
+
if (canonicalOwner === actorId) continue;
|
|
7993
|
+
if (canonicalOwner == null) logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are not the gateway keys of a portable actor.", {
|
|
7994
|
+
inbox: recipient.canonicalInboxId,
|
|
7995
|
+
identifier
|
|
7996
|
+
});
|
|
7997
|
+
else logger.warn("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are the gateway keys of {owner}, not of the recipient {actorId}.", {
|
|
7998
|
+
inbox: recipient.canonicalInboxId,
|
|
7999
|
+
identifier,
|
|
8000
|
+
owner: canonicalOwner,
|
|
8001
|
+
actorId
|
|
8002
|
+
});
|
|
8003
|
+
return [];
|
|
8004
|
+
}
|
|
8005
|
+
return keyPairs.map(({ keyId, privateKey }) => ({
|
|
8006
|
+
keyId,
|
|
8007
|
+
privateKey
|
|
8008
|
+
}));
|
|
8009
|
+
}
|
|
7907
8010
|
async #fetchHashlinkMedia(request, media, { onNotFound, contextData, span, metricState }) {
|
|
7908
8011
|
metricState.endpoint = "hashlink_media";
|
|
7909
8012
|
metricState.routeTemplate = HASHLINK_MEDIA_ROUTE_TEMPLATE;
|
|
@@ -13,7 +13,7 @@ import { decodeBase64, encodeBase64 } from "byte-encodings/base64";
|
|
|
13
13
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
14
14
|
//#region deno.json
|
|
15
15
|
var name = "@fedify/fedify";
|
|
16
|
-
var version = "2.4.0-dev.
|
|
16
|
+
var version = "2.4.0-dev.2084+4b8bd325";
|
|
17
17
|
//#endregion
|
|
18
18
|
//#region src/sig/accept.ts
|
|
19
19
|
/**
|
|
@@ -1,11 +1,11 @@
|
|
|
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-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-Dn-py9Zy.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-Beod6tzO.mjs";
|
|
6
6
|
import { i as validateAcceptSignature, n as fulfillAcceptSignature, r as parseAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
7
|
-
import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-
|
|
8
|
-
import { n as verifyPortableGatewayKeyDocument } from "./portable-key-
|
|
7
|
+
import { i as fetchKeyDetailed, s as validateCryptoKey } from "./key-BJrp524f.mjs";
|
|
8
|
+
import { n as verifyPortableGatewayKeyDocument } from "./portable-key-B4R-CiIV.mjs";
|
|
9
9
|
import { getLogger } from "@logtape/logtape";
|
|
10
10
|
import { CryptographicKey } from "@fedify/vocab";
|
|
11
11
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -15,7 +15,7 @@ let byte_encodings_base64 = require("byte-encodings/base64");
|
|
|
15
15
|
let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
16
16
|
//#region deno.json
|
|
17
17
|
var name = "@fedify/fedify";
|
|
18
|
-
var version = "2.4.0-dev.
|
|
18
|
+
var version = "2.4.0-dev.2084+4b8bd325";
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region ../../node_modules/.pnpm/temporal-polyfill@1.0.1/node_modules/temporal-polyfill/chunks/root.js
|
|
21
21
|
const NativeTemporal = globalThis.Temporal;
|
|
@@ -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-
|
|
5
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-Dn-py9Zy.mjs";
|
|
5
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-Beod6tzO.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
8
8
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { R as validateCryptoKey, nt as recordDocumentCache, t as doubleKnock } from "./http-
|
|
3
|
+
import { R as validateCryptoKey, nt as recordDocumentCache, t as doubleKnock } from "./http-4PCCvhsU.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { p as recordDocumentCache } from "./metrics-
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-Beod6tzO.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
2
|
+
const require_http = require("./http-B5q1CHtL.cjs");
|
|
3
3
|
let _logtape_logtape = require("@logtape/logtape");
|
|
4
4
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
5
5
|
let es_toolkit = require("es-toolkit");
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { r as fetchKey, s as validateCryptoKey } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-Dn-py9Zy.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-Beod6tzO.mjs";
|
|
6
|
+
import { r as fetchKey, s as validateCryptoKey } from "./key-BJrp524f.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
9
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-Dn-py9Zy.mjs";
|
|
5
5
|
import { metrics } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/federation/metrics.ts
|
|
@@ -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-
|
|
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-
|
|
4
|
+
import { n as version, t as name } from "./deno-Dn-py9Zy.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-Beod6tzO.mjs";
|
|
6
6
|
import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
7
|
-
import { d as hasPortableActor, f as isCompatibleKeyId, m as isPortableUri, o as importJwk, s as validateCryptoKey, t as exportJwk, u as getGatewayKeyBase } from "./key-
|
|
7
|
+
import { d as hasPortableActor, f as isCompatibleKeyId, l as getCanonicalPortableId, m as isPortableUri, o as importJwk, s as validateCryptoKey, t as exportJwk, u as getGatewayKeyBase } from "./key-BJrp524f.mjs";
|
|
8
8
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
|
|
9
|
-
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-
|
|
10
|
-
import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-
|
|
11
|
-
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-
|
|
12
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
13
|
-
import { n as kvCache } from "./kv-cache-
|
|
9
|
+
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-BmFz5NLA.mjs";
|
|
10
|
+
import { a as verifyObject, n as hasProofLike, o as verifyPortableObjectProof, r as signObject } from "./proof-ozG4HfcQ.mjs";
|
|
11
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-B0VRNipE.mjs";
|
|
12
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-BUq5bYJr.mjs";
|
|
13
|
+
import { n as kvCache } from "./kv-cache-C4C3LyYW.mjs";
|
|
14
14
|
import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-DpnpgjyX.mjs";
|
|
15
15
|
import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
|
|
16
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
17
|
-
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-
|
|
18
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
16
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CsKVgMzk.mjs";
|
|
17
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-ClPt8nYu.mjs";
|
|
18
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BGlpUocK.mjs";
|
|
19
19
|
import { t as CircuitBreaker } from "./circuit-breaker-C5NqoLBJ.mjs";
|
|
20
20
|
import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
|
|
21
|
-
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-
|
|
21
|
+
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-B6Aj2kGY.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-
|
|
24
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-Ba0EAZAI.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";
|
|
@@ -2670,6 +2670,7 @@ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, loc
|
|
|
2670
2670
|
return {
|
|
2671
2671
|
status: "accepted",
|
|
2672
2672
|
recipient: {
|
|
2673
|
+
actorId: id,
|
|
2673
2674
|
inboxId,
|
|
2674
2675
|
canonicalInboxId,
|
|
2675
2676
|
gateways
|
|
@@ -2703,8 +2704,11 @@ function canonicalize(iri) {
|
|
|
2703
2704
|
* Forwarding is therefore best effort. Without {@link KvStore.cas}, nothing is
|
|
2704
2705
|
* forwarded.
|
|
2705
2706
|
*
|
|
2706
|
-
* Forwarded requests are
|
|
2707
|
-
*
|
|
2707
|
+
* Forwarded requests are signed with HTTP Signatures by the RSA key among
|
|
2708
|
+
* {@link ForwardPortableInboxActivityParameters.getKeys}, if any, so that
|
|
2709
|
+
* servers requiring HTTP Signatures accept them, and are sent unsigned
|
|
2710
|
+
* otherwise. Either way, the receiving gateways authenticate the activity by
|
|
2711
|
+
* its own proof.
|
|
2708
2712
|
* @param parameters The parameters.
|
|
2709
2713
|
* @returns The target inbox URLs that the activity was handed off to.
|
|
2710
2714
|
*/
|
|
@@ -2776,20 +2780,59 @@ function getForwardingTargets(recipient, excludedOrigins) {
|
|
|
2776
2780
|
}
|
|
2777
2781
|
return targets;
|
|
2778
2782
|
}
|
|
2779
|
-
|
|
2783
|
+
/**
|
|
2784
|
+
* Resolves the key that signs forwarded requests: the first RSASSA-PKCS1-v1_5
|
|
2785
|
+
* key, as {@link sendActivity} signs requests only with such a key. Since
|
|
2786
|
+
* the targets have already been claimed, the activity is forwarded unsigned
|
|
2787
|
+
* rather than not at all if the key cannot be resolved or used.
|
|
2788
|
+
*/
|
|
2789
|
+
async function resolveForwardingKey({ getKeys, activityId }) {
|
|
2790
|
+
if (getKeys == null) return null;
|
|
2791
|
+
const logger = getLogger([
|
|
2792
|
+
"fedify",
|
|
2793
|
+
"federation",
|
|
2794
|
+
"inbox"
|
|
2795
|
+
]);
|
|
2796
|
+
let key;
|
|
2797
|
+
try {
|
|
2798
|
+
key = (await getKeys()).find((k) => k.privateKey.algorithm.name === "RSASSA-PKCS1-v1_5");
|
|
2799
|
+
} catch (error) {
|
|
2800
|
+
logger.error("Failed to get the gateway keys to sign forwarded requests with; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
|
|
2801
|
+
activityId: activityId.href,
|
|
2802
|
+
error
|
|
2803
|
+
});
|
|
2804
|
+
return null;
|
|
2805
|
+
}
|
|
2806
|
+
if (key == null) return null;
|
|
2807
|
+
try {
|
|
2808
|
+
validateCryptoKey(key.privateKey, "private");
|
|
2809
|
+
} catch (error) {
|
|
2810
|
+
if (!(error instanceof TypeError)) throw error;
|
|
2811
|
+
logger.warn("The gateway key {keyId} cannot sign forwarded requests; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
|
|
2812
|
+
keyId: key.keyId.href,
|
|
2813
|
+
activityId: activityId.href,
|
|
2814
|
+
error
|
|
2815
|
+
});
|
|
2816
|
+
return null;
|
|
2817
|
+
}
|
|
2818
|
+
return key;
|
|
2819
|
+
}
|
|
2820
|
+
async function forwardImmediately(parameters, inboxes) {
|
|
2821
|
+
const { activity, activityId, activityType, allowPrivateAddress, specDeterminer, options, meterProvider, tracerProvider } = parameters;
|
|
2780
2822
|
const logger = getLogger([
|
|
2781
2823
|
"fedify",
|
|
2782
2824
|
"federation",
|
|
2783
2825
|
"inbox"
|
|
2784
2826
|
]);
|
|
2785
2827
|
const deadline = (options ?? resolvePortableInboxForwardingOptions()).deadline.total("millisecond");
|
|
2786
|
-
const
|
|
2828
|
+
const forwarding = resolveForwardingKey(parameters).then((key) => Promise.all(inboxes.map((inbox) => sendActivity({
|
|
2787
2829
|
activity,
|
|
2788
2830
|
activityId: activityId.href,
|
|
2789
2831
|
activityType,
|
|
2790
|
-
keys: [],
|
|
2832
|
+
keys: key == null ? [] : [key],
|
|
2791
2833
|
inbox,
|
|
2792
2834
|
allowPrivateAddress,
|
|
2835
|
+
specDeterminer,
|
|
2793
2836
|
meterProvider,
|
|
2794
2837
|
tracerProvider
|
|
2795
2838
|
}).catch((error) => {
|
|
@@ -2798,9 +2841,9 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
|
|
|
2798
2841
|
inbox: inbox.href,
|
|
2799
2842
|
error
|
|
2800
2843
|
});
|
|
2801
|
-
}));
|
|
2844
|
+
}))));
|
|
2802
2845
|
let timer;
|
|
2803
|
-
const timedOut = await Promise.race([
|
|
2846
|
+
const timedOut = await Promise.race([forwarding.then(() => false), new Promise((resolve) => {
|
|
2804
2847
|
timer = setTimeout(() => resolve(true), deadline);
|
|
2805
2848
|
})]);
|
|
2806
2849
|
clearTimeout(timer);
|
|
@@ -2809,12 +2852,27 @@ async function forwardImmediately({ activity, activityId, activityType, allowPri
|
|
|
2809
2852
|
deadline
|
|
2810
2853
|
});
|
|
2811
2854
|
}
|
|
2812
|
-
async function enqueueForwarding(
|
|
2855
|
+
async function enqueueForwarding(parameters, outboxQueue, inboxes) {
|
|
2856
|
+
const { activity, activityId, activityType, baseUrl, startQueue, meterProvider } = parameters;
|
|
2813
2857
|
const logger = getLogger([
|
|
2814
2858
|
"fedify",
|
|
2815
2859
|
"federation",
|
|
2816
2860
|
"inbox"
|
|
2817
2861
|
]);
|
|
2862
|
+
const key = await resolveForwardingKey(parameters);
|
|
2863
|
+
const keys = [];
|
|
2864
|
+
if (key != null) try {
|
|
2865
|
+
keys.push({
|
|
2866
|
+
keyId: key.keyId.href,
|
|
2867
|
+
privateKey: await exportJwk(key.privateKey)
|
|
2868
|
+
});
|
|
2869
|
+
} catch (error) {
|
|
2870
|
+
logger.error("Failed to export the gateway key {keyId}; forwarding activity {activityId} without HTTP Signatures:\n{error}", {
|
|
2871
|
+
keyId: key.keyId.href,
|
|
2872
|
+
activityId: activityId.href,
|
|
2873
|
+
error
|
|
2874
|
+
});
|
|
2875
|
+
}
|
|
2818
2876
|
startQueue?.();
|
|
2819
2877
|
const started = (/* @__PURE__ */ new Date()).toISOString();
|
|
2820
2878
|
const traceContext = {};
|
|
@@ -2824,7 +2882,7 @@ async function enqueueForwarding({ activity, activityId, activityType, baseUrl,
|
|
|
2824
2882
|
type: "outbox",
|
|
2825
2883
|
id: crypto.randomUUID(),
|
|
2826
2884
|
baseUrl,
|
|
2827
|
-
keys
|
|
2885
|
+
keys,
|
|
2828
2886
|
activity,
|
|
2829
2887
|
activityId: activityId.href,
|
|
2830
2888
|
activityType,
|
|
@@ -5325,6 +5383,8 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5325
5383
|
outboxQueue: this.outboxQueue,
|
|
5326
5384
|
startQueue: this.manuallyStartQueue ? void 0 : () => this._startQueueInternal(contextData),
|
|
5327
5385
|
allowPrivateAddress: this.allowPrivateAddress,
|
|
5386
|
+
getKeys: () => this.#getPortableGatewayKeyPairs(context, identifier, recipient),
|
|
5387
|
+
specDeterminer: new KvSpecDeterminer(this.kv, this.kvPrefixes.httpMessageSignaturesSpec, this.firstKnock, { specTtl: this.httpMessageSignaturesSpecTtl }),
|
|
5328
5388
|
options: this.portableInboxForwarding,
|
|
5329
5389
|
meterProvider: this.meterProvider,
|
|
5330
5390
|
tracerProvider: this.tracerProvider
|
|
@@ -5333,6 +5393,49 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5333
5393
|
}
|
|
5334
5394
|
});
|
|
5335
5395
|
}
|
|
5396
|
+
/**
|
|
5397
|
+
* Gets this server's gateway key pairs for the portable actor that owns
|
|
5398
|
+
* a portable inbox, which sign the activities forwarded from the inbox.
|
|
5399
|
+
* @param context The context.
|
|
5400
|
+
* @param identifier The identifier of the portable actor.
|
|
5401
|
+
* @param recipient The portable inbox.
|
|
5402
|
+
* @returns The key pairs, or an empty array if the actor has no gateway
|
|
5403
|
+
* keys on this server.
|
|
5404
|
+
*/
|
|
5405
|
+
async #getPortableGatewayKeyPairs(context, identifier, recipient) {
|
|
5406
|
+
const logger = getLogger([
|
|
5407
|
+
"fedify",
|
|
5408
|
+
"federation",
|
|
5409
|
+
"inbox"
|
|
5410
|
+
]);
|
|
5411
|
+
if (this.actorCallbacks?.keyPairsDispatcher == null || this.actorCallbacks.portableActorIdMapper == null) {
|
|
5412
|
+
logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as gateway keys need both a key pairs dispatcher and a portable actor ID mapper.", { inbox: recipient.canonicalInboxId });
|
|
5413
|
+
return [];
|
|
5414
|
+
}
|
|
5415
|
+
const actorId = getCanonicalPortableId(recipient.actorId);
|
|
5416
|
+
if (actorId == null) return [];
|
|
5417
|
+
const keyPairs = await context.getActorKeyPairs(identifier);
|
|
5418
|
+
for (const { cryptographicKey } of keyPairs) {
|
|
5419
|
+
const owner = cryptographicKey.ownerId;
|
|
5420
|
+
const canonicalOwner = owner == null ? null : getCanonicalPortableId(owner);
|
|
5421
|
+
if (canonicalOwner === actorId) continue;
|
|
5422
|
+
if (canonicalOwner == null) logger.debug("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are not the gateway keys of a portable actor.", {
|
|
5423
|
+
inbox: recipient.canonicalInboxId,
|
|
5424
|
+
identifier
|
|
5425
|
+
});
|
|
5426
|
+
else logger.warn("Forwarding activities from the portable inbox {inbox} without HTTP Signatures, as the key pairs of the actor {identifier} are the gateway keys of {owner}, not of the recipient {actorId}.", {
|
|
5427
|
+
inbox: recipient.canonicalInboxId,
|
|
5428
|
+
identifier,
|
|
5429
|
+
owner: canonicalOwner,
|
|
5430
|
+
actorId
|
|
5431
|
+
});
|
|
5432
|
+
return [];
|
|
5433
|
+
}
|
|
5434
|
+
return keyPairs.map(({ keyId, privateKey }) => ({
|
|
5435
|
+
keyId,
|
|
5436
|
+
privateKey
|
|
5437
|
+
}));
|
|
5438
|
+
}
|
|
5336
5439
|
async #fetchHashlinkMedia(request, media, { onNotFound, contextData, span, metricState }) {
|
|
5337
5440
|
metricState.endpoint = "hashlink_media";
|
|
5338
5441
|
metricState.routeTemplate = HASHLINK_MEDIA_ROUTE_TEMPLATE;
|