@fedify/fedify 2.4.0-dev.2219 → 2.4.0-dev.2228
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-Wx64uCV2.mjs} +2 -2
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-D0xY7MBs.mjs → compound-proof-B647GUyL.mjs} +2 -2
- package/dist/{deno-Dj1TFhf4.mjs → deno-9flirCWb.mjs} +1 -1
- package/dist/{docloader-CzyJe90o.mjs → docloader-pjAbs1lc.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 +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-DiycMKQx.cjs} +245 -30
- package/dist/{http-Dx7yMmfw.js → http-CHqz_Jp6.js} +1 -1
- package/dist/{http-Cuk0w0rp.cjs → http-DC5DyShJ.cjs} +1 -1
- package/dist/{http-D-DpP4sd.mjs → http-DysQjjJe.mjs} +4 -4
- package/dist/{key-Djyt1BFx.mjs → key-TtgqklZ1.mjs} +2 -2
- package/dist/{kv-cache-ecUXfCqW.mjs → kv-cache-B7g5Tvl0.mjs} +1 -1
- package/dist/{kv-cache-CUZOCSKZ.js → kv-cache-CgYK8siN.js} +1 -1
- package/dist/{kv-cache-BmLTVLXc.cjs → kv-cache-CsNDrjVT.cjs} +1 -1
- package/dist/{ld-CNVWdooi.mjs → ld-CHYUee-s.mjs} +3 -3
- package/dist/{metrics-BnYleVpg.mjs → metrics-X1lpKWRK.mjs} +1 -1
- package/dist/{middleware-BdzcazaN.js → middleware-D2scpP9Q.js} +245 -30
- package/dist/{middleware-C2_LcbL3.mjs → middleware-DoAk0Q3s.mjs} +242 -27
- package/dist/{middleware-Bh592bk8.mjs → middleware-ndPtgYYI.mjs} +1 -1
- 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-BP_ouAvi.mjs} +3 -3
- package/dist/{portable-collection-C0c0rUN9.js → portable-collection-4SnmDcTc.js} +1 -1
- package/dist/{portable-collection-DwJ8YJP2.cjs → portable-collection-Cz9K1Tas.cjs} +1 -1
- package/dist/{portable-collection-hcONGyUs.mjs → portable-collection-SqxusPj7.mjs} +2 -2
- package/dist/{portable-key-B880yVlC.mjs → portable-key-DYr6MZUl.mjs} +1 -1
- package/dist/{proof-z6Prgi5I.mjs → proof-B-iLzyva.mjs} +4 -4
- package/dist/{send-Cw545L_2.mjs → send-D0nNms3Q.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-39Ixir8d.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
|
@@ -2,8 +2,8 @@ import { Temporal } from "temporal-polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { c as isPortableActorDocument, d as isPortableUri, l as isPortableId, m as parseKeyIdString, s as isCompatibleKeyId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
5
|
-
import { n as version, t as name } from "./deno-
|
|
6
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-
|
|
5
|
+
import { n as version, t as name } from "./deno-9flirCWb.mjs";
|
|
6
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-X1lpKWRK.mjs";
|
|
7
7
|
import { n as attachKeyOwnerEvidence, t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
9
|
import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
@@ -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-X1lpKWRK.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,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-
|
|
3
|
+
import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-CHqz_Jp6.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, resolveDocumentLoaderTimeout, validatePublicUrl, withDocumentLoaderTimeout } from "@fedify/vocab-runtime";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
2
|
+
const require_http = require("./http-DC5DyShJ.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 { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-9flirCWb.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-X1lpKWRK.mjs";
|
|
6
|
+
import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-TtgqklZ1.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-9flirCWb.mjs";
|
|
5
5
|
import { metrics } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/federation/metrics.ts
|
|
@@ -2,10 +2,10 @@ 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 { $ as instrumentDocumentLoader, A as hasSignature, At as name, C as InvalidContextReferenceError, Ct as hasPortableActor, Dt as isPortableUri, E as compactJsonLd, Et as isPortableKeyId, F as verifyCompactJsonLd, G as validateCryptoKey, M as isClearlyMalformedContextReference, N as isInvalidUrlTypeError, O as detachSignature, Ot as isSameObjectId, P as signJsonLd, Q as getRemoteHost, R as wrapContextLoaderForJsonLd, S as normalizeOutgoingActivityJsonLd, St as getRawCanonicalPortableId, Tt as isPortableId, W as importJwk, X as getDurationMs, Z as getFederationMetrics, _ as verifyObject, at as recordCollectionTotalItems, b as verifyPortableObjectProofWithRoot, bt as getGatewayKeyBase, c as verifyRequestDetailed, ct as recordInboxActivity, d as InvalidPortableObjectIdError, dt as recordWebFingerHandle, et as isAbortError, f as classifyFep2277CoreType, ft as registerQueueDepthGauge, g as verifyMapLocalProof, h as signObject, i as selectRequestSignature, it as recordCollectionRequest, j as hasSignatureLike, jt as version, k as getNormalizationContextLoader, lt as recordOutboxActivity, m as hasProofLike, mt as formatAcceptSignature, n as listRequestSignatures, nt as recordCollectionDispatchDuration, o as validateMaxSignatures, pt as preloadedOnlyDocumentLoader, q as MAX_PORTABLE_KEY_TTL, r as parseRfc9421SignatureInput, rt as recordCollectionPageItems, s as verifyRequest, st as recordFanoutRecipients, t as doubleKnock, tt as recordCircuitBreakerStateChange, ut as recordOutboxEnqueue, v as verifyPortableObjectProof, vt as getAuthenticationOrigin, w as assertSafeJsonLd, wt as isCompatibleKeyId, xt as getPortableDid, y as verifyPortableObjectProofPolicy, yt as getCanonicalPortableId, z as exportJwk } from "./http-
|
|
5
|
+
import { $ as instrumentDocumentLoader, A as hasSignature, At as name, C as InvalidContextReferenceError, Ct as hasPortableActor, Dt as isPortableUri, E as compactJsonLd, Et as isPortableKeyId, F as verifyCompactJsonLd, G as validateCryptoKey, M as isClearlyMalformedContextReference, N as isInvalidUrlTypeError, O as detachSignature, Ot as isSameObjectId, P as signJsonLd, Q as getRemoteHost, R as wrapContextLoaderForJsonLd, S as normalizeOutgoingActivityJsonLd, St as getRawCanonicalPortableId, Tt as isPortableId, W as importJwk, X as getDurationMs, Z as getFederationMetrics, _ as verifyObject, at as recordCollectionTotalItems, b as verifyPortableObjectProofWithRoot, bt as getGatewayKeyBase, c as verifyRequestDetailed, ct as recordInboxActivity, d as InvalidPortableObjectIdError, dt as recordWebFingerHandle, et as isAbortError, f as classifyFep2277CoreType, ft as registerQueueDepthGauge, g as verifyMapLocalProof, h as signObject, i as selectRequestSignature, it as recordCollectionRequest, j as hasSignatureLike, jt as version, k as getNormalizationContextLoader, lt as recordOutboxActivity, m as hasProofLike, mt as formatAcceptSignature, n as listRequestSignatures, nt as recordCollectionDispatchDuration, o as validateMaxSignatures, pt as preloadedOnlyDocumentLoader, q as MAX_PORTABLE_KEY_TTL, r as parseRfc9421SignatureInput, rt as recordCollectionPageItems, s as verifyRequest, st as recordFanoutRecipients, t as doubleKnock, tt as recordCircuitBreakerStateChange, ut as recordOutboxEnqueue, v as verifyPortableObjectProof, vt as getAuthenticationOrigin, w as assertSafeJsonLd, wt as isCompatibleKeyId, xt as getPortableDid, y as verifyPortableObjectProofPolicy, yt as getCanonicalPortableId, z as exportJwk } from "./http-CHqz_Jp6.js";
|
|
6
6
|
import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-_S2_MeLF.js";
|
|
7
|
-
import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "./portable-collection-
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
7
|
+
import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "./portable-collection-4SnmDcTc.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-CgYK8siN.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, PUBLIC_COLLECTION, Tombstone, getTypeId, isActor, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
@@ -1456,7 +1456,7 @@ const textEncoder = new TextEncoder();
|
|
|
1456
1456
|
function isPortableIdValue(value) {
|
|
1457
1457
|
return typeof value === "string" && isPortableId(value);
|
|
1458
1458
|
}
|
|
1459
|
-
function isJsonMap(value) {
|
|
1459
|
+
function isJsonMap$1(value) {
|
|
1460
1460
|
return typeof value === "object" && value != null && !Array.isArray(value);
|
|
1461
1461
|
}
|
|
1462
1462
|
function isCompoundProofJsonObject(value) {
|
|
@@ -1522,7 +1522,7 @@ function addBytes(statistics, bytes, limits, path) {
|
|
|
1522
1522
|
if (statistics.byteLength > limits.maxBytes) return limitExceeded("bytes", limits.maxBytes, statistics.byteLength, path);
|
|
1523
1523
|
}
|
|
1524
1524
|
function inspectJsonTree(root, limits) {
|
|
1525
|
-
if (!isJsonMap(root)) return {
|
|
1525
|
+
if (!isJsonMap$1(root)) return {
|
|
1526
1526
|
status: "unsupported",
|
|
1527
1527
|
reason: {
|
|
1528
1528
|
type: "invalidJsonTree",
|
|
@@ -1585,7 +1585,7 @@ function inspectJsonTree(root, limits) {
|
|
|
1585
1585
|
insideProof: current.insideProof,
|
|
1586
1586
|
insideContext: current.insideContext
|
|
1587
1587
|
});
|
|
1588
|
-
} else if (isJsonMap(value)) {
|
|
1588
|
+
} else if (isJsonMap$1(value)) {
|
|
1589
1589
|
const prototype = Object.getPrototypeOf(value);
|
|
1590
1590
|
if (seen.has(value) || !hasOnlyDataProperties(value) || prototype !== Object.prototype && prototype !== null) return {
|
|
1591
1591
|
status: "unsupported",
|
|
@@ -1606,7 +1606,7 @@ function inspectJsonTree(root, limits) {
|
|
|
1606
1606
|
if (hasDirectProof) {
|
|
1607
1607
|
statistics.proofCount++;
|
|
1608
1608
|
if (statistics.proofCount > limits.maxProofs) return limitExceeded("proofs", limits.maxProofs, statistics.proofCount, childPath(current.path, "proof"));
|
|
1609
|
-
if (!isJsonMap(value.proof)) return {
|
|
1609
|
+
if (!isJsonMap$1(value.proof)) return {
|
|
1610
1610
|
status: "unsupported",
|
|
1611
1611
|
reason: {
|
|
1612
1612
|
type: "unsupportedProofShape",
|
|
@@ -1781,7 +1781,7 @@ function inspectCompoundPortableObjectApplicability(json, limits) {
|
|
|
1781
1781
|
iterator: value.values(),
|
|
1782
1782
|
depth: frame.depth + 1
|
|
1783
1783
|
});
|
|
1784
|
-
} else if (isJsonMap(value)) {
|
|
1784
|
+
} else if (isJsonMap$1(value)) {
|
|
1785
1785
|
mapCount++;
|
|
1786
1786
|
if (mapCount > limits.maxMaps) return "indeterminate";
|
|
1787
1787
|
if ([value.id, value["@id"]].some(isPortableIdValue)) return "present";
|
|
@@ -1877,7 +1877,7 @@ function containsCompoundPortableObject(json) {
|
|
|
1877
1877
|
* @internal
|
|
1878
1878
|
*/
|
|
1879
1879
|
function findUnsupportedCompoundProofShape(json) {
|
|
1880
|
-
return findInJsonMaps(json, (map, path) => Object.hasOwn(map, "proof") && !isJsonMap(map.proof) ? childPath(path, "proof") : void 0) ?? null;
|
|
1880
|
+
return findInJsonMaps(json, (map, path) => Object.hasOwn(map, "proof") && !isJsonMap$1(map.proof) ? childPath(path, "proof") : void 0) ?? null;
|
|
1881
1881
|
}
|
|
1882
1882
|
/**
|
|
1883
1883
|
* Discovers direct literal proof-bearing maps in an immutable JSON snapshot.
|
|
@@ -2079,13 +2079,13 @@ async function isEmbeddedPortableKey(parent, member, key, parentId) {
|
|
|
2079
2079
|
}
|
|
2080
2080
|
if (expanded.length !== 1 || hasGraphKeyword(expanded)) return false;
|
|
2081
2081
|
const node = expanded[0];
|
|
2082
|
-
if (!isJsonMap(node) || typeof node["@id"] !== "string" || getCanonicalPortableIdOf(node["@id"]) !== parentPortableId) return false;
|
|
2082
|
+
if (!isJsonMap$1(node) || typeof node["@id"] !== "string" || getCanonicalPortableIdOf(node["@id"]) !== parentPortableId) return false;
|
|
2083
2083
|
const properties = Object.keys(node).filter((property) => property !== "@id" && property !== "@type");
|
|
2084
2084
|
if (properties.length !== 1 || properties[0] !== `${SECURITY}${member}`) return false;
|
|
2085
2085
|
const values = node[properties[0]];
|
|
2086
2086
|
if (!Array.isArray(values) || values.length !== 1) return false;
|
|
2087
2087
|
const expandedKey = values[0];
|
|
2088
|
-
if (!isJsonMap(expandedKey) || expandedKey["@id"] !== literalIds[0] || Object.keys(expandedKey).some((property) => !KEY_PROPERTIES.has(property))) return false;
|
|
2088
|
+
if (!isJsonMap$1(expandedKey) || expandedKey["@id"] !== literalIds[0] || Object.keys(expandedKey).some((property) => !KEY_PROPERTIES.has(property))) return false;
|
|
2089
2089
|
const types = expandedKey["@type"];
|
|
2090
2090
|
if (types !== void 0 && (!Array.isArray(types) || types.some((type) => typeof type !== "string" || !KEY_TYPES.has(type)))) return false;
|
|
2091
2091
|
const pem = expandedKey[`${SECURITY}publicKeyPem`];
|
|
@@ -2096,7 +2096,7 @@ async function isEmbeddedPortableKey(parent, member, key, parentId) {
|
|
|
2096
2096
|
for (const property of [`${SECURITY}owner`, `${SECURITY}controller`]) {
|
|
2097
2097
|
const owners = expandedKey[property];
|
|
2098
2098
|
if (owners === void 0) continue;
|
|
2099
|
-
if (!Array.isArray(owners) || owners.length !== 1 || !isJsonMap(owners[0]) || Object.keys(owners[0]).length !== 1 || typeof owners[0]["@id"] !== "string" || getCanonicalPortableIdOf(owners[0]["@id"]) !== parentPortableId) return false;
|
|
2099
|
+
if (!Array.isArray(owners) || owners.length !== 1 || !isJsonMap$1(owners[0]) || Object.keys(owners[0]).length !== 1 || typeof owners[0]["@id"] !== "string" || getCanonicalPortableIdOf(owners[0]["@id"]) !== parentPortableId) return false;
|
|
2100
2100
|
}
|
|
2101
2101
|
return true;
|
|
2102
2102
|
}
|
|
@@ -2139,7 +2139,7 @@ function isSimpleContext(context) {
|
|
|
2139
2139
|
}
|
|
2140
2140
|
function hasGraphKeyword(value) {
|
|
2141
2141
|
if (Array.isArray(value)) return value.some(hasGraphKeyword);
|
|
2142
|
-
if (!isJsonMap(value)) return false;
|
|
2142
|
+
if (!isJsonMap$1(value)) return false;
|
|
2143
2143
|
return Object.entries(value).some(([key, child]) => key === "@graph" || key === "@included" || key === "@reverse" || hasGraphKeyword(child));
|
|
2144
2144
|
}
|
|
2145
2145
|
/**
|
|
@@ -2149,7 +2149,7 @@ function hasGraphKeyword(value) {
|
|
|
2149
2149
|
function isSingleStringValue(values, datatype) {
|
|
2150
2150
|
if (!Array.isArray(values) || values.length !== 1) return false;
|
|
2151
2151
|
const value = values[0];
|
|
2152
|
-
if (!isJsonMap(value) || typeof value["@value"] !== "string") return false;
|
|
2152
|
+
if (!isJsonMap$1(value) || typeof value["@value"] !== "string") return false;
|
|
2153
2153
|
const keys = Object.keys(value);
|
|
2154
2154
|
return keys.length === 1 || datatype != null && keys.length === 2 && value["@type"] === datatype;
|
|
2155
2155
|
}
|
|
@@ -2204,7 +2204,7 @@ async function verifyServedPortableObjects(json, options = {}) {
|
|
|
2204
2204
|
const maps = collected.maps;
|
|
2205
2205
|
const discovered = /* @__PURE__ */ new Map();
|
|
2206
2206
|
const ids = maps.map((candidate) => candidate.id);
|
|
2207
|
-
const rootId = isJsonMap(json) ? [json.id, json["@id"]].find(isPortableIdValue) : void 0;
|
|
2207
|
+
const rootId = isJsonMap$1(json) ? [json.id, json["@id"]].find(isPortableIdValue) : void 0;
|
|
2208
2208
|
if (rootId != null) ids.push(rootId);
|
|
2209
2209
|
for (const id of ids) discovered.set(id, (discovered.get(id) ?? 0) + 1);
|
|
2210
2210
|
let hidden;
|
|
@@ -2249,7 +2249,7 @@ function findHiddenPortableObject(expanded, discovered) {
|
|
|
2249
2249
|
pending.push(...value);
|
|
2250
2250
|
continue;
|
|
2251
2251
|
}
|
|
2252
|
-
if (!isJsonMap(value)) continue;
|
|
2252
|
+
if (!isJsonMap$1(value)) continue;
|
|
2253
2253
|
const id = value["@id"];
|
|
2254
2254
|
if (isPortableIdValue(id) && Object.keys(value).some((key) => key !== "@id")) {
|
|
2255
2255
|
const count = remaining.get(id) ?? 0;
|
|
@@ -2340,7 +2340,7 @@ function collectServedPortableMaps(json) {
|
|
|
2340
2340
|
}
|
|
2341
2341
|
async function checkServedPortableMap({ map, contexts }, options) {
|
|
2342
2342
|
if (Object.hasOwn(map, "proof")) {
|
|
2343
|
-
if (!isJsonMap(map.proof)) return "unsupportedProofShape";
|
|
2343
|
+
if (!isJsonMap$1(map.proof)) return "unsupportedProofShape";
|
|
2344
2344
|
if (!Object.hasOwn(map, "@context")) return "missingContext";
|
|
2345
2345
|
try {
|
|
2346
2346
|
const policy = await verifyPortableObjectProofPolicy(map, await verifyMapLocalProof(map, options), options);
|
|
@@ -2361,11 +2361,185 @@ async function checkServedPortableMap({ map, contexts }, options) {
|
|
|
2361
2361
|
} catch {
|
|
2362
2362
|
return "unsupportedContext";
|
|
2363
2363
|
}
|
|
2364
|
-
if (expanded.length !== 1 || !isJsonMap(expanded[0])) return "invalidPortableObject";
|
|
2364
|
+
if (expanded.length !== 1 || !isJsonMap$1(expanded[0])) return "invalidPortableObject";
|
|
2365
2365
|
const type = classifyFep2277CoreType(expanded[0]);
|
|
2366
2366
|
return UNSECURED_CORE_TYPES.has(type) ? null : "missingProof";
|
|
2367
2367
|
}
|
|
2368
2368
|
//#endregion
|
|
2369
|
+
//#region src/federation/compatible-id-warning.ts
|
|
2370
|
+
/** Returns a verified first gateway, without dereferencing the actor. */
|
|
2371
|
+
async function getLocalFirstGateway(context, ownerId, did) {
|
|
2372
|
+
try {
|
|
2373
|
+
const parsed = context.parseUri(ownerId, { portable: true });
|
|
2374
|
+
if (parsed?.type !== "actor" || parsed.authority !== did) return null;
|
|
2375
|
+
return firstGateway(await context.getActor(parsed.identifier), did);
|
|
2376
|
+
} catch (error) {
|
|
2377
|
+
getLogger([
|
|
2378
|
+
"fedify",
|
|
2379
|
+
"federation",
|
|
2380
|
+
"object"
|
|
2381
|
+
]).debug("Could not check the first gateway of {ownerId}: {error}", {
|
|
2382
|
+
ownerId: ownerId.href,
|
|
2383
|
+
error
|
|
2384
|
+
});
|
|
2385
|
+
return null;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
function firstGateway(actor, did) {
|
|
2389
|
+
if (actor?.id == null || getPortableDid(actor.id) !== did) return null;
|
|
2390
|
+
const gateway = actor.gateway;
|
|
2391
|
+
return gateway != null && isGatewayUrl(gateway) ? gateway : null;
|
|
2392
|
+
}
|
|
2393
|
+
/** Looks for an actor already embedded in the document being published. */
|
|
2394
|
+
function getEmbeddedFirstGateway(json, ownerId, did) {
|
|
2395
|
+
const owner = getCanonicalPortableId(ownerId);
|
|
2396
|
+
if (owner == null) return null;
|
|
2397
|
+
return visitJsonMaps(json, (map) => {
|
|
2398
|
+
const id = parseMapId(map, isJsonMap(json) ? json : null);
|
|
2399
|
+
if (id == null || getCanonicalPortableId(id) !== owner) return;
|
|
2400
|
+
const gateways = map.gateways ?? map["https://w3id.org/fep/ef61/gateways"];
|
|
2401
|
+
const first = Array.isArray(gateways) ? gateways[0] : isJsonMap(gateways) && Array.isArray(gateways["@list"]) ? gateways["@list"][0] : null;
|
|
2402
|
+
const address = typeof first === "string" ? first : isJsonMap(first) ? first.id ?? first["@id"] : null;
|
|
2403
|
+
if (typeof address !== "string") return;
|
|
2404
|
+
try {
|
|
2405
|
+
const gateway = new URL(address);
|
|
2406
|
+
if (getPortableDid(id) === did && isGatewayUrl(gateway)) return gateway;
|
|
2407
|
+
} catch (error) {
|
|
2408
|
+
if (!(error instanceof TypeError)) throw error;
|
|
2409
|
+
}
|
|
2410
|
+
}) ?? null;
|
|
2411
|
+
}
|
|
2412
|
+
function isJsonMap(value) {
|
|
2413
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
2414
|
+
}
|
|
2415
|
+
/** Warns only when the publisher's actual first gateway is known. */
|
|
2416
|
+
function warnCompatibleId(id, did, gateway, kind) {
|
|
2417
|
+
if (!isCompatibleEf61Iri(id) || getPortableDid(id) !== did || id.origin === gateway.origin) return;
|
|
2418
|
+
getLogger([
|
|
2419
|
+
"fedify",
|
|
2420
|
+
"federation",
|
|
2421
|
+
kind === "activity" ? "outbox" : "object"
|
|
2422
|
+
]).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.", {
|
|
2423
|
+
kind,
|
|
2424
|
+
id: id.href,
|
|
2425
|
+
gateway: gateway.origin
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
/** Reads the root ID without dereferencing or expanding the document. */
|
|
2429
|
+
function getCompactRootId(json) {
|
|
2430
|
+
return isJsonMap(json) ? parseMapId(json, json) : null;
|
|
2431
|
+
}
|
|
2432
|
+
/** Checks an activity and its embedded objects against each one's owner. */
|
|
2433
|
+
async function warnCompatibleIdsInJson(json, context) {
|
|
2434
|
+
const root = isJsonMap(json) ? json : null;
|
|
2435
|
+
const rootOwners = root == null ? [] : ownerIds(root, "actor", root);
|
|
2436
|
+
const gateways = /* @__PURE__ */ new Map();
|
|
2437
|
+
const maps = [];
|
|
2438
|
+
visitJsonMaps(json, (map, path) => {
|
|
2439
|
+
maps.push({
|
|
2440
|
+
map,
|
|
2441
|
+
path
|
|
2442
|
+
});
|
|
2443
|
+
});
|
|
2444
|
+
for (const { map, path } of maps) {
|
|
2445
|
+
const id = parseMapId(map, root);
|
|
2446
|
+
if (id == null || !isCompatibleEf61Iri(id)) continue;
|
|
2447
|
+
const type = map.type ?? map["@type"];
|
|
2448
|
+
if ((Array.isArray(type) ? type : [type]).some((t) => typeof t === "string" && /(?:^|[#/:])(CryptographicKey|Multikey|JsonWebKey|Key)$/.test(t))) continue;
|
|
2449
|
+
const did = getPortableDid(id);
|
|
2450
|
+
if (did == null) continue;
|
|
2451
|
+
const owners = path === "" ? rootOwners : [
|
|
2452
|
+
...ownerIds(map, "actor", root),
|
|
2453
|
+
...ownerIds(map, "attributedTo", root),
|
|
2454
|
+
...rootOwners
|
|
2455
|
+
];
|
|
2456
|
+
for (const ownerId of owners) {
|
|
2457
|
+
if (getPortableDid(ownerId) !== did) continue;
|
|
2458
|
+
const key = getCanonicalPortableId(ownerId);
|
|
2459
|
+
if (key == null) continue;
|
|
2460
|
+
let gateway = gateways.get(key);
|
|
2461
|
+
if (gateway === void 0) {
|
|
2462
|
+
gateway = getEmbeddedFirstGateway(json, ownerId, did) ?? (context == null ? null : await getLocalFirstGateway(context, ownerId, did));
|
|
2463
|
+
gateways.set(key, gateway);
|
|
2464
|
+
}
|
|
2465
|
+
if (gateway != null) {
|
|
2466
|
+
warnCompatibleId(id, did, gateway, path === "" ? "activity" : "object");
|
|
2467
|
+
break;
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
function ownerIds(map, term, root) {
|
|
2473
|
+
const iri = `https://www.w3.org/ns/activitystreams#${term}`;
|
|
2474
|
+
const values = [map[term], map[iri]];
|
|
2475
|
+
for (const context of [map["@context"], root?.["@context"]]) for (const [alias, definition] of localContextEntries(context)) {
|
|
2476
|
+
const mapped = typeof definition === "string" ? definition : isJsonMap(definition) ? definition["@id"] : null;
|
|
2477
|
+
if (mapped === iri || mapped === `as:${term}`) values.push(map[alias]);
|
|
2478
|
+
}
|
|
2479
|
+
return values.flatMap((value) => parseOwnerIds(value, root));
|
|
2480
|
+
}
|
|
2481
|
+
function localContextEntries(context) {
|
|
2482
|
+
if (Array.isArray(context)) return context.flatMap(localContextEntries);
|
|
2483
|
+
return isJsonMap(context) ? Object.entries(context) : [];
|
|
2484
|
+
}
|
|
2485
|
+
function parseOwnerIds(value, root) {
|
|
2486
|
+
if (Array.isArray(value)) return value.flatMap((item) => parseOwnerIds(item, root));
|
|
2487
|
+
if (isJsonMap(value)) {
|
|
2488
|
+
const id = parseMapId(value, root);
|
|
2489
|
+
return id == null ? [] : [id];
|
|
2490
|
+
}
|
|
2491
|
+
if (typeof value !== "string") return [];
|
|
2492
|
+
try {
|
|
2493
|
+
return [parseIri(value)];
|
|
2494
|
+
} catch (error) {
|
|
2495
|
+
if (error instanceof TypeError) return [];
|
|
2496
|
+
throw error;
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
function parseMapId(map, root) {
|
|
2500
|
+
let raw = map["@id"] ?? map.id;
|
|
2501
|
+
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") {
|
|
2502
|
+
raw = map[alias];
|
|
2503
|
+
break;
|
|
2504
|
+
}
|
|
2505
|
+
if (typeof raw !== "string") return null;
|
|
2506
|
+
try {
|
|
2507
|
+
return parseIri(raw);
|
|
2508
|
+
} catch (error) {
|
|
2509
|
+
if (error instanceof TypeError) return null;
|
|
2510
|
+
throw error;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
function visitJsonMaps(json, visit) {
|
|
2514
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2515
|
+
const pending = [{
|
|
2516
|
+
value: json,
|
|
2517
|
+
path: ""
|
|
2518
|
+
}];
|
|
2519
|
+
while (pending.length > 0) {
|
|
2520
|
+
const { value, path } = pending.pop();
|
|
2521
|
+
if (value == null || typeof value !== "object" || seen.has(value)) continue;
|
|
2522
|
+
seen.add(value);
|
|
2523
|
+
if (Array.isArray(value)) {
|
|
2524
|
+
for (let i = value.length - 1; i >= 0; i--) pending.push({
|
|
2525
|
+
value: value[i],
|
|
2526
|
+
path: `${path}/${i}`
|
|
2527
|
+
});
|
|
2528
|
+
continue;
|
|
2529
|
+
}
|
|
2530
|
+
const map = value;
|
|
2531
|
+
const result = visit(map, path);
|
|
2532
|
+
if (result !== void 0) return result;
|
|
2533
|
+
for (const key of Object.keys(map).reverse()) {
|
|
2534
|
+
if (key === "proof" || key === "@context") continue;
|
|
2535
|
+
pending.push({
|
|
2536
|
+
value: map[key],
|
|
2537
|
+
path: `${path}/${key}`
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
//#endregion
|
|
2369
2543
|
//#region src/federation/audience.ts
|
|
2370
2544
|
const AS_NAMESPACE = "https://www.w3.org/ns/activitystreams#";
|
|
2371
2545
|
/**
|
|
@@ -4155,6 +4329,7 @@ async function handleObject(request, { values, context, objectDispatcher, author
|
|
|
4155
4329
|
Vary: "Accept"
|
|
4156
4330
|
}
|
|
4157
4331
|
});
|
|
4332
|
+
await warnServedCompatibleObject(context, object, getCompactRootId(jsonLd));
|
|
4158
4333
|
return new Response(JSON.stringify(jsonLd), { headers: {
|
|
4159
4334
|
"Content-Type": "application/activity+json",
|
|
4160
4335
|
Vary: "Accept"
|
|
@@ -4258,6 +4433,7 @@ async function handlePortableObject(request, { values, context, objectDispatcher
|
|
|
4258
4433
|
return portableObjectInternalServerError(request);
|
|
4259
4434
|
}
|
|
4260
4435
|
}
|
|
4436
|
+
if (!tombstone) await warnServedCompatibleObject(context, object, servedId);
|
|
4261
4437
|
const headers = new Headers({
|
|
4262
4438
|
"Content-Type": PORTABLE_OBJECT_CONTENT_TYPE,
|
|
4263
4439
|
Vary: "Accept"
|
|
@@ -4268,6 +4444,32 @@ async function handlePortableObject(request, { values, context, objectDispatcher
|
|
|
4268
4444
|
headers
|
|
4269
4445
|
});
|
|
4270
4446
|
}
|
|
4447
|
+
async function warnServedCompatibleObject(context, object, serializedId) {
|
|
4448
|
+
try {
|
|
4449
|
+
if (isActor(object)) return;
|
|
4450
|
+
const id = typeof serializedId === "string" ? parseIri(serializedId) : serializedId ?? object.id;
|
|
4451
|
+
if (id == null || !isCompatibleEf61Iri(id)) return;
|
|
4452
|
+
const did = getPortableDid(id);
|
|
4453
|
+
if (did == null) return;
|
|
4454
|
+
const ownerIds = object instanceof Activity ? object.actorIds : object.attributionIds;
|
|
4455
|
+
for (const ownerId of ownerIds) {
|
|
4456
|
+
if (getPortableDid(ownerId) !== did) continue;
|
|
4457
|
+
const gateway = await getLocalFirstGateway(context, ownerId, did);
|
|
4458
|
+
if (gateway == null) continue;
|
|
4459
|
+
warnCompatibleId(id, did, gateway, object instanceof Activity ? "activity" : "object");
|
|
4460
|
+
break;
|
|
4461
|
+
}
|
|
4462
|
+
} catch (error) {
|
|
4463
|
+
getLogger([
|
|
4464
|
+
"fedify",
|
|
4465
|
+
"federation",
|
|
4466
|
+
"object"
|
|
4467
|
+
]).debug("Could not check the first gateway of {objectId}: {error}", {
|
|
4468
|
+
objectId: object.id?.href,
|
|
4469
|
+
error
|
|
4470
|
+
});
|
|
4471
|
+
}
|
|
4472
|
+
}
|
|
4271
4473
|
function isRequestedPortableObject(object, canonicalId) {
|
|
4272
4474
|
return object.id != null && getCanonicalPortableId(object.id) === canonicalId;
|
|
4273
4475
|
}
|
|
@@ -4371,13 +4573,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
4371
4573
|
* @param parameters The parameters for handling the collection.
|
|
4372
4574
|
* @returns A promise that resolves to an HTTP response.
|
|
4373
4575
|
*/
|
|
4374
|
-
async function handleCollection(request, { name: name$
|
|
4375
|
-
const spanName = name$
|
|
4576
|
+
async function handleCollection(request, { name: name$1, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, portable, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
4577
|
+
const spanName = name$1.trim().replace(/\s+/g, "_");
|
|
4376
4578
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
4377
4579
|
const tracer = tracerProvider.getTracer(name, version);
|
|
4378
4580
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
4379
4581
|
const metricBase = {
|
|
4380
|
-
kind: getCollectionMetricKind(name$
|
|
4582
|
+
kind: getCollectionMetricKind(name$1),
|
|
4381
4583
|
page: cursor != null,
|
|
4382
4584
|
dispatcher: "built_in"
|
|
4383
4585
|
};
|
|
@@ -4423,7 +4625,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
4423
4625
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
4424
4626
|
return await onNotFound(request);
|
|
4425
4627
|
}
|
|
4426
|
-
const items = filterCollectionItems(page.items, name$
|
|
4628
|
+
const items = filterCollectionItems(page.items, name$1, filterPredicate);
|
|
4427
4629
|
itemCount = items.length;
|
|
4428
4630
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
4429
4631
|
return items;
|
|
@@ -4465,7 +4667,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
4465
4667
|
} else {
|
|
4466
4668
|
const uri = new URL(portable == null ? baseUri : pageBase);
|
|
4467
4669
|
uri.searchParams.set("cursor", cursor);
|
|
4468
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
4670
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$1}`, {
|
|
4469
4671
|
kind: SpanKind.SERVER,
|
|
4470
4672
|
attributes: {
|
|
4471
4673
|
"activitypub.collection.id": uri.href,
|
|
@@ -4481,7 +4683,7 @@ async function handleCollection(request, { name: name$2, identifier, uriGetter,
|
|
|
4481
4683
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
4482
4684
|
return await onNotFound(request);
|
|
4483
4685
|
}
|
|
4484
|
-
const items = filterCollectionItems(page.items, name$
|
|
4686
|
+
const items = filterCollectionItems(page.items, name$1, filterPredicate);
|
|
4485
4687
|
itemCount = items.length;
|
|
4486
4688
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
4487
4689
|
return {
|
|
@@ -5672,8 +5874,8 @@ var CustomCollectionHandler = class {
|
|
|
5672
5874
|
* @param CollectionPage The CollectionPage constructor.
|
|
5673
5875
|
* @param filterPredicate Optional filter predicate for items.
|
|
5674
5876
|
*/
|
|
5675
|
-
constructor(name$
|
|
5676
|
-
this.name = name$
|
|
5877
|
+
constructor(name$2, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate, portable) {
|
|
5878
|
+
this.name = name$2;
|
|
5677
5879
|
this.values = values;
|
|
5678
5880
|
this.context = context;
|
|
5679
5881
|
this.callbacks = callbacks;
|
|
@@ -10506,17 +10708,26 @@ var ContextImpl = class ContextImpl {
|
|
|
10506
10708
|
activityId: activity.id?.href,
|
|
10507
10709
|
activity
|
|
10508
10710
|
});
|
|
10711
|
+
const activityJsonLd = await activity.toJsonLd({
|
|
10712
|
+
format: "compact",
|
|
10713
|
+
contextLoader: this.contextLoader
|
|
10714
|
+
});
|
|
10715
|
+
try {
|
|
10716
|
+
await warnCompatibleIdsInJson(activityJsonLd, this instanceof RequestContextImpl && !this.isInActorDispatcher() ? this : void 0);
|
|
10717
|
+
} catch (error) {
|
|
10718
|
+
logger.debug("Could not check the first gateway of activity {activityId}: {error}", {
|
|
10719
|
+
activityId: activity.id?.href,
|
|
10720
|
+
error
|
|
10721
|
+
});
|
|
10722
|
+
}
|
|
10509
10723
|
if (this.federation.fanoutQueue == null || options.immediate || options.fanout === "skip" || (options.fanout ?? "auto") === "auto" && globalThis.Object.keys(inboxes).length < FANOUT_THRESHOLD) {
|
|
10510
10724
|
await this.federation.sendActivity(keys, inboxes, activity, {
|
|
10511
10725
|
...opts,
|
|
10726
|
+
activityJsonLd,
|
|
10512
10727
|
normalizeExistingProofs: proofCreated || options.normalizeExistingProofs
|
|
10513
10728
|
});
|
|
10514
10729
|
return true;
|
|
10515
10730
|
}
|
|
10516
|
-
const activityJsonLd = await activity.toJsonLd({
|
|
10517
|
-
format: "compact",
|
|
10518
|
-
contextLoader: this.contextLoader
|
|
10519
|
-
});
|
|
10520
10731
|
assertSupportedCompoundProofShape(activityJsonLd, activity.id?.href);
|
|
10521
10732
|
const keyJwkPairs = await Promise.all(keys.map(async ({ keyId, privateKey }) => ({
|
|
10522
10733
|
keyId: keyId.href,
|
|
@@ -10699,6 +10910,10 @@ var RequestContextImpl = class RequestContextImpl extends ContextImpl {
|
|
|
10699
10910
|
#invokedFromActorDispatcher;
|
|
10700
10911
|
#invokedFromObjectDispatcher;
|
|
10701
10912
|
request;
|
|
10913
|
+
/** Whether a diagnostic actor lookup would re-enter the actor dispatcher. */
|
|
10914
|
+
isInActorDispatcher() {
|
|
10915
|
+
return this.#invokedFromActorDispatcher != null;
|
|
10916
|
+
}
|
|
10702
10917
|
url = void 0;
|
|
10703
10918
|
portableRequest;
|
|
10704
10919
|
constructor(options) {
|