@fedify/fedify 2.4.0-dev.2219 → 2.4.0-dev.2233
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-C5rYBZ16.mjs → builder-BmoDmjWk.mjs} +2 -2
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-D0xY7MBs.mjs → compound-proof-Pn8766TV.mjs} +2 -2
- package/dist/{deno-Dj1TFhf4.mjs → deno-62DcBMwc.mjs} +1 -1
- package/dist/{docloader-CzyJe90o.mjs → docloader-Be9TaKa_.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 +73 -6
- 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 +248 -6
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.mjs +3 -3
- package/dist/federation/portable-collection.test.mjs +4 -4
- package/dist/federation/portable-delivery.test.mjs +2 -2
- package/dist/federation/portable-gateway-keys.test.mjs +4 -4
- package/dist/federation/portable-inbox.test.mjs +4 -4
- package/dist/federation/portable-parse-uri.test.mjs +1 -1
- package/dist/federation/portable-route-activity.test.mjs +2 -2
- package/dist/federation/portable.test.mjs +80 -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-DC1yfb-8.cjs → federation-BVkPF8vF.cjs} +246 -31
- package/dist/{http-Cuk0w0rp.cjs → http-BbDZCEnR.cjs} +1 -1
- package/dist/{http-Dx7yMmfw.js → http-D4JQwy-3.js} +1 -1
- package/dist/{http-D-DpP4sd.mjs → http-SIEv_YGW.mjs} +4 -4
- package/dist/{key-Djyt1BFx.mjs → key-CtAhsSFI.mjs} +2 -2
- package/dist/{kv-cache-CUZOCSKZ.js → kv-cache-DXFAaMh2.js} +1 -1
- package/dist/{kv-cache-BmLTVLXc.cjs → kv-cache-DxLtK3Np.cjs} +1 -1
- package/dist/{kv-cache-ecUXfCqW.mjs → kv-cache-Fn7dxiMu.mjs} +1 -1
- package/dist/{ld-CNVWdooi.mjs → ld-BuI0RakW.mjs} +3 -3
- package/dist/{metrics-BnYleVpg.mjs → metrics-jr7IbGjd.mjs} +1 -1
- package/dist/{middleware-Bh592bk8.mjs → middleware-BWhRFmO0.mjs} +1 -1
- package/dist/{middleware-C2_LcbL3.mjs → middleware-BhtaUtlt.mjs} +243 -28
- package/dist/{middleware-BdzcazaN.js → middleware-D0t1NBIE.js} +246 -31
- package/dist/mod.cjs +4 -4
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-D_BDPwm2.mjs → owner-CoNYVTQp.mjs} +3 -3
- package/dist/{portable-collection-hcONGyUs.mjs → portable-collection-CxP30PWK.mjs} +2 -2
- package/dist/{portable-collection-DwJ8YJP2.cjs → portable-collection-FLEUNFj5.cjs} +1 -1
- package/dist/{portable-collection-C0c0rUN9.js → portable-collection-ZczKiIeK.js} +1 -1
- package/dist/{portable-key-B880yVlC.mjs → portable-key-90Ux6h7F.mjs} +1 -1
- package/dist/{proof-z6Prgi5I.mjs → proof-Bhsb_KYD.mjs} +4 -4
- package/dist/{send-Cw545L_2.mjs → send-CdRJj10a.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 +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +1 -1
- package/dist/sig/portable-key.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +5 -3
- package/dist/{temporal-Cy-8WCod.mjs → temporal-vBRC6bwu.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 +7 -7
|
@@ -3,28 +3,28 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { d as isPortableUri, f as isSameObjectId, i as getPortableDid, l as isPortableId, n as getCanonicalPortableId, o as hasPortableActor, r as getGatewayKeyBase, s as isCompatibleKeyId, t as getAuthenticationOrigin, u as isPortableKeyId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
5
5
|
import { n as isPubliclyAddressedNode, t as isInAudience } from "./audience-CHQ-FlLD.mjs";
|
|
6
|
-
import { n as version, t as name } from "./deno-
|
|
7
|
-
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-
|
|
6
|
+
import { n as version, t as name } from "./deno-62DcBMwc.mjs";
|
|
7
|
+
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-jr7IbGjd.mjs";
|
|
8
8
|
import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
9
|
-
import { c as validateCryptoKey, n as exportJwk, s as importJwk } from "./key-
|
|
9
|
+
import { c as validateCryptoKey, n as exportJwk, s as importJwk } from "./key-CtAhsSFI.mjs";
|
|
10
10
|
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
|
|
11
|
-
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-
|
|
12
|
-
import { a as signObject, c as verifyPortableObjectProof, i as hasProofLike, s as verifyObject, t as InvalidPortableObjectIdError, u as verifyPortableObjectProofWithRoot } from "./proof-
|
|
13
|
-
import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-
|
|
14
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
15
|
-
import { n as kvCache } from "./kv-cache-
|
|
11
|
+
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-BuI0RakW.mjs";
|
|
12
|
+
import { a as signObject, c as verifyPortableObjectProof, i as hasProofLike, s as verifyObject, t as InvalidPortableObjectIdError, u as verifyPortableObjectProofWithRoot } from "./proof-Bhsb_KYD.mjs";
|
|
13
|
+
import { a as listRequestSignatures, c as selectRequestSignature, d as validateMaxSignatures, f as verifyRequest, p as verifyRequestDetailed, s as parseRfc9421SignatureInput } from "./http-SIEv_YGW.mjs";
|
|
14
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-Be9TaKa_.mjs";
|
|
15
|
+
import { n as kvCache } from "./kv-cache-Fn7dxiMu.mjs";
|
|
16
16
|
import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-CEnNz8O7.mjs";
|
|
17
17
|
import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
|
|
18
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
19
|
-
import { t as verifyPortableObject } from "./portable-collection-
|
|
20
|
-
import { a as getOrderingDestination, i as sendActivityThroughGateways, n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-
|
|
21
|
-
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-
|
|
18
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-CoNYVTQp.mjs";
|
|
19
|
+
import { t as verifyPortableObject } from "./portable-collection-CxP30PWK.mjs";
|
|
20
|
+
import { a as getOrderingDestination, i as sendActivityThroughGateways, n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-CdRJj10a.mjs";
|
|
21
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BmoDmjWk.mjs";
|
|
22
22
|
import { t as CircuitBreaker } from "./circuit-breaker-XJ53md4S.mjs";
|
|
23
23
|
import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
|
|
24
|
-
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, s as verifyServedPortableObjects, t as containsCompoundPortableObject } from "./compound-proof-
|
|
24
|
+
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, s as verifyServedPortableObjects, t as containsCompoundPortableObject } from "./compound-proof-Pn8766TV.mjs";
|
|
25
25
|
import { t as KvKeyCache } from "./keycache-Da8A8mZa.mjs";
|
|
26
26
|
import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
|
|
27
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
27
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-vBRC6bwu.mjs";
|
|
28
28
|
import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
|
|
29
29
|
import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
|
|
30
30
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
@@ -359,6 +359,180 @@ function serializeDataPointType(dataPointType) {
|
|
|
359
359
|
}
|
|
360
360
|
}
|
|
361
361
|
//#endregion
|
|
362
|
+
//#region src/federation/compatible-id-warning.ts
|
|
363
|
+
/** Returns a verified first gateway, without dereferencing the actor. */
|
|
364
|
+
async function getLocalFirstGateway(context, ownerId, did) {
|
|
365
|
+
try {
|
|
366
|
+
const parsed = context.parseUri(ownerId, { portable: true });
|
|
367
|
+
if (parsed?.type !== "actor" || parsed.authority !== did) return null;
|
|
368
|
+
return firstGateway(await context.getActor(parsed.identifier), did);
|
|
369
|
+
} catch (error) {
|
|
370
|
+
getLogger([
|
|
371
|
+
"fedify",
|
|
372
|
+
"federation",
|
|
373
|
+
"object"
|
|
374
|
+
]).debug("Could not check the first gateway of {ownerId}: {error}", {
|
|
375
|
+
ownerId: ownerId.href,
|
|
376
|
+
error
|
|
377
|
+
});
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function firstGateway(actor, did) {
|
|
382
|
+
if (actor?.id == null || getPortableDid(actor.id) !== did) return null;
|
|
383
|
+
const gateway = actor.gateway;
|
|
384
|
+
return gateway != null && isGatewayUrl(gateway) ? gateway : null;
|
|
385
|
+
}
|
|
386
|
+
/** Looks for an actor already embedded in the document being published. */
|
|
387
|
+
function getEmbeddedFirstGateway(json, ownerId, did) {
|
|
388
|
+
const owner = getCanonicalPortableId(ownerId);
|
|
389
|
+
if (owner == null) return null;
|
|
390
|
+
return visitJsonMaps(json, (map) => {
|
|
391
|
+
const id = parseMapId(map, isJsonMap(json) ? json : null);
|
|
392
|
+
if (id == null || getCanonicalPortableId(id) !== owner) return;
|
|
393
|
+
const gateways = map.gateways ?? map["https://w3id.org/fep/ef61/gateways"];
|
|
394
|
+
const first = Array.isArray(gateways) ? gateways[0] : isJsonMap(gateways) && Array.isArray(gateways["@list"]) ? gateways["@list"][0] : null;
|
|
395
|
+
const address = typeof first === "string" ? first : isJsonMap(first) ? first.id ?? first["@id"] : null;
|
|
396
|
+
if (typeof address !== "string") return;
|
|
397
|
+
try {
|
|
398
|
+
const gateway = new URL(address);
|
|
399
|
+
if (getPortableDid(id) === did && isGatewayUrl(gateway)) return gateway;
|
|
400
|
+
} catch (error) {
|
|
401
|
+
if (!(error instanceof TypeError)) throw error;
|
|
402
|
+
}
|
|
403
|
+
}) ?? null;
|
|
404
|
+
}
|
|
405
|
+
function isJsonMap(value) {
|
|
406
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
407
|
+
}
|
|
408
|
+
/** Warns only when the publisher's actual first gateway is known. */
|
|
409
|
+
function warnCompatibleId(id, did, gateway, kind) {
|
|
410
|
+
if (!isCompatibleEf61Iri(id) || getPortableDid(id) !== did || id.origin === gateway.origin) return;
|
|
411
|
+
getLogger([
|
|
412
|
+
"fedify",
|
|
413
|
+
"federation",
|
|
414
|
+
kind === "activity" ? "outbox" : "object"
|
|
415
|
+
]).warn("The {kind} {id} has an FEP-ef61 compatible identifier on another gateway than its owner's first gateway, {gateway}. FEP-ef61 requires publishers to use the first gateway in the actor's gateways.", {
|
|
416
|
+
kind,
|
|
417
|
+
id: id.href,
|
|
418
|
+
gateway: gateway.origin
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
/** Reads the root ID without dereferencing or expanding the document. */
|
|
422
|
+
function getCompactRootId(json) {
|
|
423
|
+
return isJsonMap(json) ? parseMapId(json, json) : null;
|
|
424
|
+
}
|
|
425
|
+
/** Checks an activity and its embedded objects against each one's owner. */
|
|
426
|
+
async function warnCompatibleIdsInJson(json, context) {
|
|
427
|
+
const root = isJsonMap(json) ? json : null;
|
|
428
|
+
const rootOwners = root == null ? [] : ownerIds(root, "actor", root);
|
|
429
|
+
const gateways = /* @__PURE__ */ new Map();
|
|
430
|
+
const maps = [];
|
|
431
|
+
visitJsonMaps(json, (map, path) => {
|
|
432
|
+
maps.push({
|
|
433
|
+
map,
|
|
434
|
+
path
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
for (const { map, path } of maps) {
|
|
438
|
+
const id = parseMapId(map, root);
|
|
439
|
+
if (id == null || !isCompatibleEf61Iri(id)) continue;
|
|
440
|
+
const type = map.type ?? map["@type"];
|
|
441
|
+
if ((Array.isArray(type) ? type : [type]).some((t) => typeof t === "string" && /(?:^|[#/:])(CryptographicKey|Multikey|JsonWebKey|Key)$/.test(t))) continue;
|
|
442
|
+
const did = getPortableDid(id);
|
|
443
|
+
if (did == null) continue;
|
|
444
|
+
const owners = path === "" ? rootOwners : [
|
|
445
|
+
...ownerIds(map, "actor", root),
|
|
446
|
+
...ownerIds(map, "attributedTo", root),
|
|
447
|
+
...rootOwners
|
|
448
|
+
];
|
|
449
|
+
for (const ownerId of owners) {
|
|
450
|
+
if (getPortableDid(ownerId) !== did) continue;
|
|
451
|
+
const key = getCanonicalPortableId(ownerId);
|
|
452
|
+
if (key == null) continue;
|
|
453
|
+
let gateway = gateways.get(key);
|
|
454
|
+
if (gateway === void 0) {
|
|
455
|
+
gateway = getEmbeddedFirstGateway(json, ownerId, did) ?? (context == null ? null : await getLocalFirstGateway(context, ownerId, did));
|
|
456
|
+
gateways.set(key, gateway);
|
|
457
|
+
}
|
|
458
|
+
if (gateway != null) {
|
|
459
|
+
warnCompatibleId(id, did, gateway, path === "" ? "activity" : "object");
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function ownerIds(map, term, root) {
|
|
466
|
+
const iri = `https://www.w3.org/ns/activitystreams#${term}`;
|
|
467
|
+
const values = [map[term], map[iri]];
|
|
468
|
+
for (const context of [map["@context"], root?.["@context"]]) for (const [alias, definition] of localContextEntries(context)) {
|
|
469
|
+
const mapped = typeof definition === "string" ? definition : isJsonMap(definition) ? definition["@id"] : null;
|
|
470
|
+
if (mapped === iri || mapped === `as:${term}`) values.push(map[alias]);
|
|
471
|
+
}
|
|
472
|
+
return values.flatMap((value) => parseOwnerIds(value, root));
|
|
473
|
+
}
|
|
474
|
+
function localContextEntries(context) {
|
|
475
|
+
if (Array.isArray(context)) return context.flatMap(localContextEntries);
|
|
476
|
+
return isJsonMap(context) ? Object.entries(context) : [];
|
|
477
|
+
}
|
|
478
|
+
function parseOwnerIds(value, root) {
|
|
479
|
+
if (Array.isArray(value)) return value.flatMap((item) => parseOwnerIds(item, root));
|
|
480
|
+
if (isJsonMap(value)) {
|
|
481
|
+
const id = parseMapId(value, root);
|
|
482
|
+
return id == null ? [] : [id];
|
|
483
|
+
}
|
|
484
|
+
if (typeof value !== "string") return [];
|
|
485
|
+
try {
|
|
486
|
+
return [parseIri(value)];
|
|
487
|
+
} catch (error) {
|
|
488
|
+
if (error instanceof TypeError) return [];
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
function parseMapId(map, root) {
|
|
493
|
+
let raw = map["@id"] ?? map.id;
|
|
494
|
+
for (const context of [map["@context"], root?.["@context"]]) for (const [alias, definition] of localContextEntries(context)) if ((typeof definition === "string" ? definition : isJsonMap(definition) ? definition["@id"] : null) === "@id" && typeof map[alias] === "string") {
|
|
495
|
+
raw = map[alias];
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
if (typeof raw !== "string") return null;
|
|
499
|
+
try {
|
|
500
|
+
return parseIri(raw);
|
|
501
|
+
} catch (error) {
|
|
502
|
+
if (error instanceof TypeError) return null;
|
|
503
|
+
throw error;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
function visitJsonMaps(json, visit) {
|
|
507
|
+
const seen = /* @__PURE__ */ new Set();
|
|
508
|
+
const pending = [{
|
|
509
|
+
value: json,
|
|
510
|
+
path: ""
|
|
511
|
+
}];
|
|
512
|
+
while (pending.length > 0) {
|
|
513
|
+
const { value, path } = pending.pop();
|
|
514
|
+
if (value == null || typeof value !== "object" || seen.has(value)) continue;
|
|
515
|
+
seen.add(value);
|
|
516
|
+
if (Array.isArray(value)) {
|
|
517
|
+
for (let i = value.length - 1; i >= 0; i--) pending.push({
|
|
518
|
+
value: value[i],
|
|
519
|
+
path: `${path}/${i}`
|
|
520
|
+
});
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const map = value;
|
|
524
|
+
const result = visit(map, path);
|
|
525
|
+
if (result !== void 0) return result;
|
|
526
|
+
for (const key of Object.keys(map).reverse()) {
|
|
527
|
+
if (key === "proof" || key === "@context") continue;
|
|
528
|
+
pending.push({
|
|
529
|
+
value: map[key],
|
|
530
|
+
path: `${path}/${key}`
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
//#endregion
|
|
362
536
|
//#region src/federation/inbox.ts
|
|
363
537
|
async function routeActivity({ context: ctx, json, originalJson, normalizedActivity, ldSignatureVerified, activity, recipient, inboxListeners, inboxContextFactory, listenerInboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, meterProvider, tracerProvider, idempotencyStrategy }) {
|
|
364
538
|
const logger = getLogger([
|
|
@@ -1202,6 +1376,7 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
1202
1376
|
Vary: "Accept"
|
|
1203
1377
|
}
|
|
1204
1378
|
});
|
|
1379
|
+
await warnServedCompatibleObject(context, object, getCompactRootId(jsonLd));
|
|
1205
1380
|
return new Response(JSON.stringify(jsonLd), { headers: {
|
|
1206
1381
|
"Content-Type": "application/activity+json",
|
|
1207
1382
|
Vary: "Accept"
|
|
@@ -1305,6 +1480,7 @@ async function handlePortableObject(request, { values, context, objectDispatcher
|
|
|
1305
1480
|
return portableObjectInternalServerError(request);
|
|
1306
1481
|
}
|
|
1307
1482
|
}
|
|
1483
|
+
if (!tombstone) await warnServedCompatibleObject(context, object, servedId);
|
|
1308
1484
|
const headers = new Headers({
|
|
1309
1485
|
"Content-Type": PORTABLE_OBJECT_CONTENT_TYPE,
|
|
1310
1486
|
Vary: "Accept"
|
|
@@ -1315,6 +1491,32 @@ async function handlePortableObject(request, { values, context, objectDispatcher
|
|
|
1315
1491
|
headers
|
|
1316
1492
|
});
|
|
1317
1493
|
}
|
|
1494
|
+
async function warnServedCompatibleObject(context, object, serializedId) {
|
|
1495
|
+
try {
|
|
1496
|
+
if (isActor(object)) return;
|
|
1497
|
+
const id = typeof serializedId === "string" ? parseIri(serializedId) : serializedId ?? object.id;
|
|
1498
|
+
if (id == null || !isCompatibleEf61Iri(id)) return;
|
|
1499
|
+
const did = getPortableDid(id);
|
|
1500
|
+
if (did == null) return;
|
|
1501
|
+
const ownerIds = object instanceof Activity ? object.actorIds : object.attributionIds;
|
|
1502
|
+
for (const ownerId of ownerIds) {
|
|
1503
|
+
if (getPortableDid(ownerId) !== did) continue;
|
|
1504
|
+
const gateway = await getLocalFirstGateway(context, ownerId, did);
|
|
1505
|
+
if (gateway == null) continue;
|
|
1506
|
+
warnCompatibleId(id, did, gateway, object instanceof Activity ? "activity" : "object");
|
|
1507
|
+
break;
|
|
1508
|
+
}
|
|
1509
|
+
} catch (error) {
|
|
1510
|
+
getLogger([
|
|
1511
|
+
"fedify",
|
|
1512
|
+
"federation",
|
|
1513
|
+
"object"
|
|
1514
|
+
]).debug("Could not check the first gateway of {objectId}: {error}", {
|
|
1515
|
+
objectId: object.id?.href,
|
|
1516
|
+
error
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1318
1520
|
function isRequestedPortableObject(object, canonicalId) {
|
|
1319
1521
|
return object.id != null && getCanonicalPortableId(object.id) === canonicalId;
|
|
1320
1522
|
}
|
|
@@ -1418,13 +1620,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
1418
1620
|
* @param parameters The parameters for handling the collection.
|
|
1419
1621
|
* @returns A promise that resolves to an HTTP response.
|
|
1420
1622
|
*/
|
|
1421
|
-
async function handleCollection(request, { name: name$
|
|
1422
|
-
const spanName = name$
|
|
1623
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
1624
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
1423
1625
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
1424
1626
|
const tracer = tracerProvider.getTracer(name, version);
|
|
1425
1627
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
1426
1628
|
const metricBase = {
|
|
1427
|
-
kind: getCollectionMetricKind(name$
|
|
1629
|
+
kind: getCollectionMetricKind(name$1),
|
|
1428
1630
|
page: cursor != null,
|
|
1429
1631
|
dispatcher: "built_in"
|
|
1430
1632
|
};
|
|
@@ -1470,7 +1672,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1470
1672
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1471
1673
|
return await onNotFound(request);
|
|
1472
1674
|
}
|
|
1473
|
-
const items = filterCollectionItems(page.items, name$
|
|
1675
|
+
const items = filterCollectionItems(page.items, name$1, filterPredicate);
|
|
1474
1676
|
itemCount = items.length;
|
|
1475
1677
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
1476
1678
|
return items;
|
|
@@ -1512,7 +1714,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1512
1714
|
} else {
|
|
1513
1715
|
const uri = new URL(portable == null ? baseUri : pageBase);
|
|
1514
1716
|
uri.searchParams.set("cursor", cursor);
|
|
1515
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
1717
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
1516
1718
|
kind: SpanKind.SERVER,
|
|
1517
1719
|
attributes: {
|
|
1518
1720
|
"activitypub.collection.id": uri.href,
|
|
@@ -1528,7 +1730,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
1528
1730
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1529
1731
|
return await onNotFound(request);
|
|
1530
1732
|
}
|
|
1531
|
-
const items = filterCollectionItems(page.items, name$
|
|
1733
|
+
const items = filterCollectionItems(page.items, name$1, filterPredicate);
|
|
1532
1734
|
itemCount = items.length;
|
|
1533
1735
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
1534
1736
|
return {
|
|
@@ -1740,7 +1942,7 @@ async function handleOutbox(request, { identifier, context: ctx, outboxContextFa
|
|
|
1740
1942
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1741
1943
|
});
|
|
1742
1944
|
}
|
|
1743
|
-
if (!activity.actorIds.every((actorId) => actorId
|
|
1945
|
+
if (!activity.actorIds.every((actorId) => isSameObjectId(actorId, expectedActorId))) {
|
|
1744
1946
|
const error = /* @__PURE__ */ new Error("The activity actor does not match the outbox owner.");
|
|
1745
1947
|
logger.error("The posted activity actor does not match outbox owner {identifier}.", {
|
|
1746
1948
|
identifier,
|
|
@@ -2719,8 +2921,8 @@ var CustomCollectionHandler = class {
|
|
|
2719
2921
|
* @param CollectionPage The CollectionPage constructor.
|
|
2720
2922
|
* @param filterPredicate Optional filter predicate for items.
|
|
2721
2923
|
*/
|
|
2722
|
-
constructor(name$
|
|
2723
|
-
this.name = name$
|
|
2924
|
+
constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
|
|
2925
|
+
this.name = name$2;
|
|
2724
2926
|
this.values = values;
|
|
2725
2927
|
this.context = context;
|
|
2726
2928
|
this.callbacks = callbacks;
|
|
@@ -7144,17 +7346,26 @@ var ContextImpl = class ContextImpl {
|
|
|
7144
7346
|
activityId: activity.id?.href,
|
|
7145
7347
|
activity
|
|
7146
7348
|
});
|
|
7349
|
+
const activityJsonLd = await activity.toJsonLd({
|
|
7350
|
+
format: "compact",
|
|
7351
|
+
contextLoader: this.contextLoader
|
|
7352
|
+
});
|
|
7353
|
+
try {
|
|
7354
|
+
await warnCompatibleIdsInJson(activityJsonLd, this instanceof RequestContextImpl && !this.isInActorDispatcher() ? this : void 0);
|
|
7355
|
+
} catch (error) {
|
|
7356
|
+
logger.debug("Could not check the first gateway of activity {activityId}: {error}", {
|
|
7357
|
+
activityId: activity.id?.href,
|
|
7358
|
+
error
|
|
7359
|
+
});
|
|
7360
|
+
}
|
|
7147
7361
|
if (this.federation.fanoutQueue == null || options.immediate || options.fanout === "skip" || (options.fanout ?? "auto") === "auto" && globalThis.Object.keys(inboxes).length < FANOUT_THRESHOLD) {
|
|
7148
7362
|
await this.federation.sendActivity(keys, inboxes, activity, {
|
|
7149
7363
|
...opts,
|
|
7364
|
+
activityJsonLd,
|
|
7150
7365
|
normalizeExistingProofs: proofCreated || options.normalizeExistingProofs
|
|
7151
7366
|
});
|
|
7152
7367
|
return true;
|
|
7153
7368
|
}
|
|
7154
|
-
const activityJsonLd = await activity.toJsonLd({
|
|
7155
|
-
format: "compact",
|
|
7156
|
-
contextLoader: this.contextLoader
|
|
7157
|
-
});
|
|
7158
7369
|
assertSupportedCompoundProofShape(activityJsonLd, activity.id?.href);
|
|
7159
7370
|
const keyJwkPairs = await Promise.all(keys.map(async ({ keyId, privateKey }) => ({
|
|
7160
7371
|
keyId: keyId.href,
|
|
@@ -7337,6 +7548,10 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
7337
7548
|
#invokedFromActorDispatcher;
|
|
7338
7549
|
#invokedFromObjectDispatcher;
|
|
7339
7550
|
request;
|
|
7551
|
+
/** Whether a diagnostic actor lookup would re-enter the actor dispatcher. */
|
|
7552
|
+
isInActorDispatcher() {
|
|
7553
|
+
return this.#invokedFromActorDispatcher != null;
|
|
7554
|
+
}
|
|
7340
7555
|
url = void 0;
|
|
7341
7556
|
portableRequest;
|
|
7342
7557
|
constructor(options) {
|
|
@@ -7787,4 +8002,4 @@ function getRequestId(request) {
|
|
|
7787
8002
|
return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
7788
8003
|
}
|
|
7789
8004
|
//#endregion
|
|
7790
|
-
export {
|
|
8005
|
+
export { getEmbeddedFirstGateway as C, handleNodeInfoJrd as D, handleNodeInfo as E, actorDehydrator as O, getCompactRootId as S, handleBenchmarkTrigger as T, coversDelivery as _, OutboxContextImpl as a, PORTABLE_OBJECT_CONTENT_TYPE as b, assertPortableActorActivity as c, handleCustomCollection as d, handleInbox as f, respondWithObjectIfAcceptable as g, respondWithObject as h, KvSpecDeterminer as i, autoIdAssigner as k, handleActor as l, handleOutbox as m, FederationImpl as n, createFederation as o, handleObject as p, InboxContextImpl as r, handleWebFinger as s, ContextImpl as t, handleCollection as u, forwardPortableInboxActivity as v, warnCompatibleIdsInJson as w, parseHashlinkGatewayRequest as x, resolvePortableInboxForwardingOptions as y };
|