@fedify/fedify 2.4.0-dev.2084 → 2.4.0-dev.2093
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-BGlpUocK.mjs → builder-Ld4Y9ymR.mjs} +34 -3
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-B6Aj2kGY.mjs → compound-proof-CTx_lewQ.mjs} +191 -13
- package/dist/{deno-Dn-py9Zy.mjs → deno-8t8k_6Yv.mjs} +1 -1
- package/dist/{docloader-BUq5bYJr.mjs → docloader-DJKcsAiF.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 +254 -5
- package/dist/federation/portable-gateway-keys.test.mjs +72 -11
- package/dist/federation/portable-inbox.test.mjs +116 -4
- package/dist/federation/portable.test.mjs +182 -4
- 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 +89 -1
- package/dist/{federation-BLGx8JUH.cjs → federation-aSHO04ob.cjs} +360 -65
- package/dist/{http-B0VRNipE.mjs → http-B2ftY0Ha.mjs} +4 -4
- package/dist/{http-B5q1CHtL.cjs → http-DSaSAN7X.cjs} +1609 -1457
- package/dist/{http-4PCCvhsU.js → http-DyT7DP1Y.js} +1518 -1390
- package/dist/{key-BJrp524f.mjs → key-Dwm4VswT.mjs} +39 -99
- package/dist/{kv-cache-Dhhhrryv.cjs → kv-cache-BSJAlP4C.cjs} +1 -1
- package/dist/{kv-cache-C4C3LyYW.mjs → kv-cache-D0yYukqk.mjs} +1 -1
- package/dist/{kv-cache-1KUmAPH7.js → kv-cache-DmroAz3M.js} +1 -1
- package/dist/{ld-BmFz5NLA.mjs → ld-BYZOoDzZ.mjs} +3 -3
- package/dist/{metrics-Beod6tzO.mjs → metrics-B7YwKTFr.mjs} +1 -1
- package/dist/{middleware-B7CNsyqt.mjs → middleware-BNeqKSsL.mjs} +1 -1
- package/dist/{middleware-D_9pNYe9.js → middleware-Blq0882d.js} +368 -73
- package/dist/{middleware-BKeQYPm0.mjs → middleware-E_0IH72m.mjs} +166 -71
- package/dist/{mod-HDSvS-ww.d.cts → mod-C8LieBzF.d.cts} +16 -3
- package/dist/{mod-C9WSpZWm.d.ts → mod-Coacostr.d.ts} +16 -3
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-CsKVgMzk.mjs → owner-Cgx2Dc7I.mjs} +5 -4
- package/dist/{owner-_pbbgLJK.js → owner-DAGSC5gX.js} +2 -2
- package/dist/{owner-BQFZtFV4.cjs → owner-szIZl4qI.cjs} +2 -2
- package/dist/{portable-key-B4R-CiIV.mjs → portable-key-Cn1WJSN1.mjs} +60 -41
- package/dist/portable-key-id-Bva5iT3W.mjs +136 -0
- package/dist/{proof-ozG4HfcQ.mjs → proof-DVXC6nYz.mjs} +59 -18
- package/dist/{send-ClPt8nYu.mjs → send-D-hOvYKy.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 +160 -3
- 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.d.cts +1 -1
- package/dist/sig/mod.d.ts +1 -1
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +69 -5
- package/dist/sig/portable-key.test.mjs +176 -10
- package/dist/sig/proof.test.mjs +107 -4
- package/dist/{sig-DhdomAN0.js → sig-B5Ell7pO.js} +19 -3
- package/dist/{sig-k3C8sF7g.cjs → sig-CXOKN4Br.cjs} +19 -3
- package/dist/{temporal-Ba0EAZAI.mjs → temporal-CqpKGEPk.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
|
@@ -1,27 +1,28 @@
|
|
|
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-8t8k_6Yv.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-B7YwKTFr.mjs";
|
|
6
6
|
import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { a as isCompatibleKeyId, c as isPortableUri, i as hasPortableActor, n as getGatewayKeyBase, r as getPortableDid, s as isPortableId, t as getCanonicalPortableId } from "./portable-key-id-Bva5iT3W.mjs";
|
|
8
|
+
import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-Dwm4VswT.mjs";
|
|
8
9
|
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 {
|
|
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-
|
|
10
|
+
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-BYZOoDzZ.mjs";
|
|
11
|
+
import { i as signObject, l as verifyPortableObjectProofWithRoot, o as verifyObject, r as hasProofLike, s as verifyPortableObjectProof, t as InvalidPortableObjectIdError } from "./proof-DVXC6nYz.mjs";
|
|
12
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-B2ftY0Ha.mjs";
|
|
13
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-DJKcsAiF.mjs";
|
|
14
|
+
import { n as kvCache } from "./kv-cache-D0yYukqk.mjs";
|
|
14
15
|
import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-DpnpgjyX.mjs";
|
|
15
16
|
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-
|
|
17
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-Cgx2Dc7I.mjs";
|
|
18
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-D-hOvYKy.mjs";
|
|
19
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-Ld4Y9ymR.mjs";
|
|
19
20
|
import { t as CircuitBreaker } from "./circuit-breaker-C5NqoLBJ.mjs";
|
|
20
21
|
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-
|
|
22
|
+
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-CTx_lewQ.mjs";
|
|
22
23
|
import { t as KvKeyCache } from "./keycache-BUDHB5rY.mjs";
|
|
23
24
|
import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
|
|
24
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
25
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-CqpKGEPk.mjs";
|
|
25
26
|
import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
|
|
26
27
|
import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
|
|
27
28
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
@@ -30,8 +31,9 @@ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey,
|
|
|
30
31
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
31
32
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
32
33
|
import { uniq } from "es-toolkit";
|
|
33
|
-
import { FetchError, canonicalizePortableUri, decodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin,
|
|
34
|
+
import { FetchError, canonicalizePortableUri, decodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDigestMultibase, parseHashlink, parseIri, toCompatibleEf61Id } from "@fedify/vocab-runtime";
|
|
34
35
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
36
|
+
import { isCompatibleEf61Iri } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
35
37
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
36
38
|
import { DataPointType, MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
|
|
37
39
|
import { domainToASCII } from "node:url";
|
|
@@ -789,14 +791,7 @@ async function handlePortableObject(request, { values, context, objectDispatcher
|
|
|
789
791
|
} });
|
|
790
792
|
}
|
|
791
793
|
function isRequestedPortableObject(object, canonicalId) {
|
|
792
|
-
|
|
793
|
-
if (object.id.protocol !== "ap:" && object.id.protocol !== "ap+ef61:") return false;
|
|
794
|
-
try {
|
|
795
|
-
return canonicalizePortableUri(formatIri(object.id)) === canonicalId;
|
|
796
|
-
} catch (error) {
|
|
797
|
-
if (error instanceof TypeError) return false;
|
|
798
|
-
throw error;
|
|
799
|
-
}
|
|
794
|
+
return object.id != null && getCanonicalPortableId(object.id) === canonicalId;
|
|
800
795
|
}
|
|
801
796
|
async function getJsonLdRootId(jsonLd, contextLoader) {
|
|
802
797
|
const expanded = await jsonld.expand(jsonLd, {
|
|
@@ -808,6 +803,7 @@ async function getJsonLdRootId(jsonLd, contextLoader) {
|
|
|
808
803
|
return typeof id === "string" ? id : null;
|
|
809
804
|
}
|
|
810
805
|
function isRequestedPortableId(id, canonicalId) {
|
|
806
|
+
if (!/^ap(?:\+ef61)?:\/\//i.test(id)) return URL.canParse(id) && getCanonicalPortableId(new URL(id)) === canonicalId;
|
|
811
807
|
try {
|
|
812
808
|
return canonicalizePortableUri(id) === canonicalId;
|
|
813
809
|
} catch (error) {
|
|
@@ -858,13 +854,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
858
854
|
* @param parameters The parameters for handling the collection.
|
|
859
855
|
* @returns A promise that resolves to an HTTP response.
|
|
860
856
|
*/
|
|
861
|
-
async function handleCollection(request, { name: name$
|
|
862
|
-
const spanName = name$
|
|
857
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
858
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
863
859
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
864
860
|
const tracer = tracerProvider.getTracer(name, version);
|
|
865
861
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
866
862
|
const metricBase = {
|
|
867
|
-
kind: getCollectionMetricKind(name$
|
|
863
|
+
kind: getCollectionMetricKind(name$2),
|
|
868
864
|
page: cursor != null,
|
|
869
865
|
dispatcher: "built_in"
|
|
870
866
|
};
|
|
@@ -905,7 +901,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
905
901
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
906
902
|
return await onNotFound(request);
|
|
907
903
|
}
|
|
908
|
-
const items = filterCollectionItems(page.items, name$
|
|
904
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
909
905
|
itemCount = items.length;
|
|
910
906
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
911
907
|
return items;
|
|
@@ -945,7 +941,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
945
941
|
} else {
|
|
946
942
|
const uri = new URL(baseUri);
|
|
947
943
|
uri.searchParams.set("cursor", cursor);
|
|
948
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
944
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
949
945
|
kind: SpanKind.SERVER,
|
|
950
946
|
attributes: {
|
|
951
947
|
"activitypub.collection.id": uri.href,
|
|
@@ -961,7 +957,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
961
957
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
962
958
|
return await onNotFound(request);
|
|
963
959
|
}
|
|
964
|
-
const items = filterCollectionItems(page.items, name$
|
|
960
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
965
961
|
itemCount = items.length;
|
|
966
962
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
967
963
|
return {
|
|
@@ -1670,7 +1666,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1670
1666
|
return await respondInvalidActivity(error);
|
|
1671
1667
|
}
|
|
1672
1668
|
activityVerified = true;
|
|
1673
|
-
if (!skipSignatureVerification &&
|
|
1669
|
+
if (!skipSignatureVerification && isPortableActivity(activity)) try {
|
|
1674
1670
|
proofVerified = await verifyObject(Activity, jsonWithoutSig, {
|
|
1675
1671
|
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1676
1672
|
documentLoader: ctx.documentLoader,
|
|
@@ -1854,7 +1850,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1854
1850
|
"http_signatures.verified": httpSigKey != null,
|
|
1855
1851
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
1856
1852
|
});
|
|
1857
|
-
if (!skipSignatureVerification && !proofVerified && (
|
|
1853
|
+
if (!skipSignatureVerification && !proofVerified && (isPortableActivity(activity) || isPortableGatewayKey(httpSigKey))) {
|
|
1858
1854
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1859
1855
|
logger.error("The activity {activityId} of the portable actor {actorId} is not authenticated by a valid Object Integrity Proof.", {
|
|
1860
1856
|
activity: json,
|
|
@@ -1872,6 +1868,32 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
1872
1868
|
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1873
1869
|
});
|
|
1874
1870
|
}
|
|
1871
|
+
if (!skipSignatureVerification && activity.id != null && isPortableId(activity.id)) {
|
|
1872
|
+
const rejection = await verifyPortableActivityId(activity.id, jsonWithoutSig, {
|
|
1873
|
+
contextLoader: wrapContextLoaderForJsonLd(ctx.contextLoader),
|
|
1874
|
+
documentLoader: ctx.documentLoader,
|
|
1875
|
+
keyCache,
|
|
1876
|
+
meterProvider,
|
|
1877
|
+
tracerProvider
|
|
1878
|
+
});
|
|
1879
|
+
if (rejection != null) {
|
|
1880
|
+
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1881
|
+
logger.error("The portable activity {activityId} is not authenticated by an Object Integrity Proof of its own DID: {reason}", {
|
|
1882
|
+
activity: json,
|
|
1883
|
+
recipient,
|
|
1884
|
+
activityId: activity.id.href,
|
|
1885
|
+
reason: rejection
|
|
1886
|
+
});
|
|
1887
|
+
span.setStatus({
|
|
1888
|
+
code: SpanStatusCode.ERROR,
|
|
1889
|
+
message: `The portable activity (${activity.id.href}) is not authenticated by an Object Integrity Proof of its own DID.`
|
|
1890
|
+
});
|
|
1891
|
+
return new Response("Portable activities must have valid Object Integrity Proofs made by their own DIDs.", {
|
|
1892
|
+
status: 401,
|
|
1893
|
+
headers: { "Content-Type": "text/plain; charset=utf-8" }
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1875
1897
|
if (httpSigKey != null && !await doesActorOwnKey(activity, httpSigKey, ctx)) {
|
|
1876
1898
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
1877
1899
|
getFederationMetrics(parameters.meterProvider).recordSignatureVerificationFailure("actorKeyMismatch", httpSigKey.id == null ? void 0 : getRemoteHost(httpSigKey.id));
|
|
@@ -2109,8 +2131,8 @@ var CustomCollectionHandler = class {
|
|
|
2109
2131
|
* @param CollectionPage The CollectionPage constructor.
|
|
2110
2132
|
* @param filterPredicate Optional filter predicate for items.
|
|
2111
2133
|
*/
|
|
2112
|
-
constructor(name$
|
|
2113
|
-
this.name = name$
|
|
2134
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
|
|
2135
|
+
this.name = name$1;
|
|
2114
2136
|
this.values = values;
|
|
2115
2137
|
this.context = context;
|
|
2116
2138
|
this.callbacks = callbacks;
|
|
@@ -2601,7 +2623,41 @@ const MIN_COMPONENTS = [
|
|
|
2601
2623
|
* establish.
|
|
2602
2624
|
*/
|
|
2603
2625
|
function isPortableGatewayKey(key) {
|
|
2604
|
-
return key?.id != null && isCompatibleKeyId(key.id) && key.ownerId != null &&
|
|
2626
|
+
return key?.id != null && isCompatibleKeyId(key.id) && key.ownerId != null && isPortableId(key.ownerId);
|
|
2627
|
+
}
|
|
2628
|
+
/**
|
|
2629
|
+
* Checks whether an activity needs an Object Integrity Proof by its DID:
|
|
2630
|
+
* either it is performed by an [FEP-ef61] portable actor, or its own ID is
|
|
2631
|
+
* portable. Both `ap:` URIs and compatible identifiers count as portable.
|
|
2632
|
+
*
|
|
2633
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2634
|
+
*/
|
|
2635
|
+
function isPortableActivity(activity) {
|
|
2636
|
+
return hasPortableActor(activity) || activity.id != null && isPortableId(activity.id);
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* Verifies that a portable activity's own ID belongs to the DID that signed
|
|
2640
|
+
* it, on the JSON-LD document received. The ID the proof policy checks has
|
|
2641
|
+
* to be the parsed activity's ID, so that a remote context that changes
|
|
2642
|
+
* between loads cannot make the two name different objects.
|
|
2643
|
+
* @returns `null` if the ID is verified, or the reason why it is not.
|
|
2644
|
+
*/
|
|
2645
|
+
async function verifyPortableActivityId(activityId, jsonLd, options) {
|
|
2646
|
+
const expectedId = getCanonicalPortableId(activityId);
|
|
2647
|
+
if (expectedId == null) return "malformed portable ID";
|
|
2648
|
+
let verification;
|
|
2649
|
+
try {
|
|
2650
|
+
verification = await verifyPortableObjectProofWithRoot(jsonLd, options);
|
|
2651
|
+
} catch (error) {
|
|
2652
|
+
if (error instanceof InvalidPortableObjectIdError) return "malformed portable ID";
|
|
2653
|
+
if (!isPermanentActivityParseError(error)) throw error;
|
|
2654
|
+
return "malformed document";
|
|
2655
|
+
}
|
|
2656
|
+
const { result, root } = verification;
|
|
2657
|
+
if (!result.verified) return result.reason.type;
|
|
2658
|
+
const rootId = root?.["@id"];
|
|
2659
|
+
if (typeof rootId !== "string" || getCanonicalPortableId(parseIri(rootId)) !== expectedId) return "the verified document has another ID";
|
|
2660
|
+
return null;
|
|
2605
2661
|
}
|
|
2606
2662
|
//#endregion
|
|
2607
2663
|
//#region src/federation/portable-inbox.ts
|
|
@@ -2649,16 +2705,17 @@ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, loc
|
|
|
2649
2705
|
reason: "notFound"
|
|
2650
2706
|
};
|
|
2651
2707
|
const id = actor.id;
|
|
2652
|
-
|
|
2708
|
+
const did = id == null || !isPortableId(id) ? null : getPortableDid(id);
|
|
2709
|
+
if (id == null || did == null) return {
|
|
2653
2710
|
status: "rejected",
|
|
2654
2711
|
reason: "notPortable"
|
|
2655
2712
|
};
|
|
2656
|
-
if (
|
|
2713
|
+
if (did !== authority) return {
|
|
2657
2714
|
status: "rejected",
|
|
2658
2715
|
reason: "authorityMismatch"
|
|
2659
2716
|
};
|
|
2660
|
-
const inboxId = actor.inboxId;
|
|
2661
|
-
if (inboxId == null ||
|
|
2717
|
+
const inboxId = actor.inboxId == null ? null : toPortableUri(actor.inboxId);
|
|
2718
|
+
if (inboxId == null || getCanonicalPortableId(inboxId) !== canonicalInboxId) return {
|
|
2662
2719
|
status: "rejected",
|
|
2663
2720
|
reason: "inboxMismatch"
|
|
2664
2721
|
};
|
|
@@ -2677,17 +2734,15 @@ function resolvePortableInboxRecipient(actor, { authority, canonicalInboxId, loc
|
|
|
2677
2734
|
}
|
|
2678
2735
|
};
|
|
2679
2736
|
}
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
}
|
|
2688
|
-
function canonicalize(iri) {
|
|
2737
|
+
/**
|
|
2738
|
+
* Gets the portable form of an `ap:` or `ap+ef61:` URI or a compatible
|
|
2739
|
+
* identifier, keeping its query.
|
|
2740
|
+
* @returns The portable URI, or `null` if the ID is neither, or is malformed.
|
|
2741
|
+
*/
|
|
2742
|
+
function toPortableUri(id) {
|
|
2743
|
+
if (isPortableUri(id)) return id;
|
|
2689
2744
|
try {
|
|
2690
|
-
return
|
|
2745
|
+
return fromCompatibleEf61Id(id);
|
|
2691
2746
|
} catch (error) {
|
|
2692
2747
|
if (error instanceof TypeError) return null;
|
|
2693
2748
|
throw error;
|
|
@@ -2721,7 +2776,7 @@ async function forwardPortableInboxActivity(parameters) {
|
|
|
2721
2776
|
const { recipient, activityId, excludedOrigins, kv, kvPrefix, outboxQueue } = parameters;
|
|
2722
2777
|
const { maxTargets, ttl } = parameters.options ?? resolvePortableInboxForwardingOptions();
|
|
2723
2778
|
if (kv.cas == null || maxTargets < 1) return [];
|
|
2724
|
-
const canonicalActivityId =
|
|
2779
|
+
const canonicalActivityId = getCanonicalPortableId(activityId) ?? activityId.href;
|
|
2725
2780
|
const targets = getForwardingTargets(recipient, excludedOrigins);
|
|
2726
2781
|
if (targets.length > maxTargets) {
|
|
2727
2782
|
logger.warn("The portable actor that owns the inbox {inbox} has more than {max} other gateways; the activity {activityId} is forwarded only to the first {max} of them.", {
|
|
@@ -2908,34 +2963,50 @@ async function enqueueForwarding(parameters, outboxQueue, inboxes) {
|
|
|
2908
2963
|
}
|
|
2909
2964
|
//#endregion
|
|
2910
2965
|
//#region src/federation/outgoing-proof.ts
|
|
2911
|
-
function isPortableUrl(url) {
|
|
2912
|
-
return url.protocol === "ap:" || url.protocol === "ap+ef61:";
|
|
2913
|
-
}
|
|
2914
2966
|
function formatKeyIds(candidates) {
|
|
2915
2967
|
return candidates.map((c) => c.verificationMethod.href).join(", ");
|
|
2916
2968
|
}
|
|
2917
2969
|
/**
|
|
2918
2970
|
* Rejects an activity of a portable actor whose ID cannot be authenticated by
|
|
2919
2971
|
* the actor's DID: FEP-ef61 requires the activity to be a portable object
|
|
2920
|
-
* signed by that DID, so its ID has to be a portable ID
|
|
2972
|
+
* signed by that DID, so its ID has to be a portable ID, i.e., an `ap:` or
|
|
2973
|
+
* `ap+ef61:` URI or a compatible identifier, with the same DID. A portable
|
|
2974
|
+
* actor is one whose ID is such an ID as well.
|
|
2921
2975
|
* @throws {TypeError} If the activity is performed by a portable actor, but
|
|
2922
|
-
* its ID is not a portable ID of the actor's DID,
|
|
2923
|
-
* portable actors do not share a DID
|
|
2976
|
+
* its ID is not a portable ID of the actor's DID, its
|
|
2977
|
+
* portable actors do not share a DID, or the ID of one of
|
|
2978
|
+
* them is a malformed compatible identifier.
|
|
2924
2979
|
* @internal
|
|
2925
2980
|
*/
|
|
2926
2981
|
function assertPortableActorActivity(activity) {
|
|
2927
|
-
const portableActors = activity.actorIds.filter(
|
|
2982
|
+
const portableActors = activity.actorIds.filter((id) => isPortableId(id));
|
|
2928
2983
|
if (portableActors.length < 1) return;
|
|
2929
|
-
const
|
|
2930
|
-
|
|
2931
|
-
|
|
2984
|
+
const dids = portableActors.map((actorId) => {
|
|
2985
|
+
const did = getPortableDid(actorId);
|
|
2986
|
+
if (did == null) throw new TypeError(`The activity ${activity.id?.href} is performed by the actor ${actorId.href}, whose ID is a malformed FEP-ef61 portable ID. A compatible identifier must have a valid DID and an object path, and must not have credentials or @gateway location hints.`);
|
|
2987
|
+
return did;
|
|
2988
|
+
});
|
|
2989
|
+
const did = dids[0];
|
|
2990
|
+
if (dids.some((d) => d !== did)) throw new TypeError(`The activity ${activity.id?.href} has portable actors with different DIDs (${portableActors.map((a) => a.href).join(", ")}); a portable activity is signed by a single DID.`);
|
|
2991
|
+
if (activity.id == null || !isPortableId(activity.id) || getPortableDid(activity.id) !== did) throw new TypeError(`The activity ${activity.id?.href} is performed by the portable actor ${portableActors[0].href}, so its ID has to be an ap: or ap+ef61: URI, or an FEP-ef61 compatible identifier, with the same DID (${did}), as FEP-ef61 requires it to carry an Object Integrity Proof made by that DID.`);
|
|
2992
|
+
if (!isCompatibleEf61Iri(activity.id)) return;
|
|
2993
|
+
const mismatched = portableActors.find((actorId) => isCompatibleEf61Iri(actorId) && actorId.origin !== activity.id?.origin);
|
|
2994
|
+
if (mismatched == null) return;
|
|
2995
|
+
getLogger([
|
|
2996
|
+
"fedify",
|
|
2997
|
+
"federation",
|
|
2998
|
+
"outbox"
|
|
2999
|
+
]).warn("The activity {activityId} and its actor {actorId} are identified by FEP-ef61 compatible identifiers on different gateways. FEP-ef61 requires publishers to use the first gateway in the actor's gateways when constructing compatible identifiers.", {
|
|
3000
|
+
activityId: activity.id.href,
|
|
3001
|
+
actorId: mismatched.href
|
|
3002
|
+
});
|
|
2932
3003
|
}
|
|
2933
3004
|
/**
|
|
2934
3005
|
* Creates the Object Integrity Proofs Fedify attaches to an outgoing activity.
|
|
2935
3006
|
*
|
|
2936
3007
|
* Keys whose IDs are FEP-ef61 compatible identifiers are gateway keys, which
|
|
2937
3008
|
* never sign proofs. A portable activity, i.e., one with an `ap:` or
|
|
2938
|
-
* `ap+ef61:` ID, that carries no proof is signed only by the one Ed25519 key
|
|
3009
|
+
* `ap+ef61:` ID or a compatible identifier, that carries no proof is signed only by the one Ed25519 key
|
|
2939
3010
|
* whose verification method is a DID URL for its DID, even if it is the only
|
|
2940
3011
|
* key; if no key or more than one key qualifies, this function throws.
|
|
2941
3012
|
*
|
|
@@ -2974,7 +3045,7 @@ async function signOutgoingActivity(activity, candidates, options) {
|
|
|
2974
3045
|
break;
|
|
2975
3046
|
}
|
|
2976
3047
|
const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519" && !isCompatibleKeyId(c.verificationMethod));
|
|
2977
|
-
if (!hasProof && activity.id != null &&
|
|
3048
|
+
if (!hasProof && activity.id != null && isPortableId(activity.id)) return await sign(selectPortableActivityKey(activity, activity.id, keys));
|
|
2978
3049
|
if (keys.length < 1 || hasProof && !options.appendToExistingProofs) return {
|
|
2979
3050
|
activity,
|
|
2980
3051
|
hasProof,
|
|
@@ -3007,8 +3078,9 @@ async function signOutgoingActivity(activity, candidates, options) {
|
|
|
3007
3078
|
* @throws {TypeError} If no key or more than one key qualifies.
|
|
3008
3079
|
*/
|
|
3009
3080
|
function selectPortableActivityKey(activity, activityId, keys) {
|
|
3010
|
-
const activityDid =
|
|
3011
|
-
|
|
3081
|
+
const activityDid = getPortableDid(activityId);
|
|
3082
|
+
if (activityDid == null) throw new TypeError(`Cannot sign the portable activity ${activityId.href}, as its ID is a malformed FEP-ef61 portable ID. A compatible identifier must have a valid DID and an object path, and must not have credentials or @gateway location hints.`);
|
|
3083
|
+
const eligible = keys.filter((c) => c.verificationMethod.protocol === "did:" && getPortableDid(c.verificationMethod) === activityDid);
|
|
3012
3084
|
if (eligible.length !== 1) throw new TypeError(`Cannot choose an Object Integrity Proof key for the portable activity ${activityId.href}: ` + (eligible.length < 1 ? `none of its ${keys.length} Ed25519 keys (${formatKeyIds(keys)}) ` : `${eligible.length} of its Ed25519 keys (${formatKeyIds(eligible)}) `) + `${eligible.length < 1 ? "is" : "are"} a DID URL verification method for ${activityDid}. FEP-ef61 requires a portable activity's proof to be made by its DID, and the map-local compound-proof profile accepts exactly one direct proof per map. Gateway keys, whose IDs are compatible identifiers, never sign proofs. Supply exactly one Ed25519 key whose key ID is a DID URL for ${activityDid}, or sign the activity with signObject() before sending it.`);
|
|
3013
3085
|
getLogger([
|
|
3014
3086
|
"fedify",
|
|
@@ -3255,6 +3327,27 @@ function getWebFingerSubjectAndAliases({ resourceUrl, actorUri, preferredUsernam
|
|
|
3255
3327
|
};
|
|
3256
3328
|
}
|
|
3257
3329
|
/**
|
|
3330
|
+
* Gets the compatible identifier that a WebFinger response links to for
|
|
3331
|
+
* an FEP-ef61 portable actor. An actor identified by an `ap:` or `ap+ef61:`
|
|
3332
|
+
* URI is linked through its compatible identifier on the given gateway, while
|
|
3333
|
+
* an actor identified by a compatible identifier is linked through its ID as
|
|
3334
|
+
* is, so that software without FEP-ef61 support finds the same ID in the actor
|
|
3335
|
+
* document.
|
|
3336
|
+
* @param actorId The portable actor's ID.
|
|
3337
|
+
* @param gateway The actor's first gateway.
|
|
3338
|
+
* @returns The compatible identifier, or `null` if the actor ID is malformed
|
|
3339
|
+
* or cannot be represented as a compatible identifier.
|
|
3340
|
+
*/
|
|
3341
|
+
function getCompatibleActorId(actorId, gateway) {
|
|
3342
|
+
try {
|
|
3343
|
+
if (isPortableUri(actorId)) return toCompatibleEf61Id(actorId, gateway);
|
|
3344
|
+
return fromCompatibleEf61Id(actorId) == null ? null : actorId;
|
|
3345
|
+
} catch (error) {
|
|
3346
|
+
if (error instanceof TypeError) return null;
|
|
3347
|
+
throw error;
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
/**
|
|
3258
3351
|
* Computes the subject and aliases for an FEP-ef61 portable actor, whose
|
|
3259
3352
|
* WebFinger address takes its domain from the first gateway of the actor
|
|
3260
3353
|
* rather than from the actor ID. The canonical `ap:` ID is not emitted,
|
|
@@ -3418,21 +3511,23 @@ async function handleWebFingerInternal(request, { context, host, actorDispatcher
|
|
|
3418
3511
|
});
|
|
3419
3512
|
let actorUri = context.getActorUri(identifier);
|
|
3420
3513
|
let portable;
|
|
3421
|
-
if (actor.id != null && (actor.id
|
|
3514
|
+
if (actor.id != null && isPortableId(actor.id)) {
|
|
3422
3515
|
const gateway = actor.gateway;
|
|
3423
|
-
|
|
3424
|
-
if (gateway != null && isGatewayUrl(gateway)) try {
|
|
3425
|
-
compatibleId = toCompatibleEf61Id(actor.id, gateway);
|
|
3426
|
-
} catch (error) {
|
|
3427
|
-
if (!(error instanceof TypeError)) throw error;
|
|
3428
|
-
}
|
|
3429
|
-
if (gateway == null || compatibleId == null) {
|
|
3516
|
+
if (gateway == null || !isGatewayUrl(gateway)) {
|
|
3430
3517
|
logger.error("The portable actor {actorId} (identifier: {identifier}) needs an HTTP(S) origin as the first item of its gateways property to be discovered through WebFinger.", {
|
|
3431
3518
|
actorId: formatIri(actor.id),
|
|
3432
3519
|
identifier
|
|
3433
3520
|
});
|
|
3434
3521
|
return await onNotFound(request);
|
|
3435
3522
|
}
|
|
3523
|
+
const compatibleId = getCompatibleActorId(actor.id, gateway);
|
|
3524
|
+
if (compatibleId == null) {
|
|
3525
|
+
logger.error("The portable actor {actorId} (identifier: {identifier}) cannot be discovered through WebFinger, as its ID is malformed or cannot be represented as an FEP-ef61 compatible identifier.", {
|
|
3526
|
+
actorId: formatIri(actor.id),
|
|
3527
|
+
identifier
|
|
3528
|
+
});
|
|
3529
|
+
return await onNotFound(request);
|
|
3530
|
+
}
|
|
3436
3531
|
actorUri = compatibleId;
|
|
3437
3532
|
portable = {
|
|
3438
3533
|
compatibleId,
|
|
@@ -6667,4 +6762,4 @@ function getRequestId(request) {
|
|
|
6667
6762
|
return `req_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
6668
6763
|
}
|
|
6669
6764
|
//#endregion
|
|
6670
|
-
export {
|
|
6765
|
+
export { handleNodeInfoJrd as C, handleNodeInfo as S, autoIdAssigner as T, respondWithObject as _, OutboxContextImpl as a, parseHashlinkGatewayRequest as b, assertPortableActorActivity as c, handleActor as d, handleCollection as f, handleOutbox as g, handleObject as h, KvSpecDeterminer as i, forwardPortableInboxActivity as l, handleInbox as m, FederationImpl as n, createFederation as o, handleCustomCollection as p, InboxContextImpl as r, handleWebFinger as s, ContextImpl as t, resolvePortableInboxForwardingOptions as u, respondWithObjectIfAcceptable as v, actorDehydrator as w, handleBenchmarkTrigger as x, PORTABLE_OBJECT_CONTENT_TYPE as y };
|
|
@@ -289,7 +289,11 @@ interface VerifyPortableObjectProofOptions extends VerifyProofOptions {}
|
|
|
289
289
|
* @since 2.4.0
|
|
290
290
|
*/
|
|
291
291
|
type VerifyPortableObjectProofFailureReason = {
|
|
292
|
-
/**
|
|
292
|
+
/**
|
|
293
|
+
* The document has neither a portable `ap:` or `ap+ef61:` ID nor an
|
|
294
|
+
* FEP-ef61 compatible identifier.
|
|
295
|
+
*/
|
|
296
|
+
readonly type: "notPortableObject";
|
|
293
297
|
} | {
|
|
294
298
|
/**
|
|
295
299
|
* The document is a portable collection without an Object Integrity
|
|
@@ -347,15 +351,24 @@ declare function verifyProof(jsonLd: unknown, proof: DataIntegrityProof, options
|
|
|
347
351
|
* collection without a proof is reported separately so a caller can apply a
|
|
348
352
|
* gateway trust policy. Embedded portable objects are not traversed.
|
|
349
353
|
*
|
|
354
|
+
* A portable object is a document whose ID is an `ap:` or `ap+ef61:` URI, or
|
|
355
|
+
* an [FEP-ef61] compatible identifier such as
|
|
356
|
+
* `https://gw.example/.well-known/apgateway/did:key:z6Mk…/actor`, which
|
|
357
|
+
* stands for the portable ID `ap+ef61://did:key:z6Mk…/actor`.
|
|
358
|
+
*
|
|
350
359
|
* Every proof must use a DID URL whose DID matches the portable object's
|
|
351
|
-
* authority, and every proof must
|
|
360
|
+
* authority, i.e., the DID of its canonical portable ID, and every proof must
|
|
361
|
+
* pass {@link verifyProof}. The proofs are verified over the document as
|
|
362
|
+
* given; a compatible identifier is never rewritten into a portable ID.
|
|
363
|
+
*
|
|
364
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
352
365
|
*
|
|
353
366
|
* @param jsonLd The JSON-LD document to verify.
|
|
354
367
|
* @param options Additional options. See also
|
|
355
368
|
* {@link VerifyPortableObjectProofOptions}.
|
|
356
369
|
* @returns The detailed portable proof-policy result.
|
|
357
370
|
* @throws {TypeError} If the input is not a single JSON-LD object or has a
|
|
358
|
-
* malformed portable ID.
|
|
371
|
+
* malformed portable ID or compatible identifier.
|
|
359
372
|
* @since 2.4.0
|
|
360
373
|
*/
|
|
361
374
|
declare function verifyPortableObjectProof(jsonLd: unknown, options?: VerifyPortableObjectProofOptions): Promise<VerifyPortableObjectProofResult>;
|
|
@@ -289,7 +289,11 @@ interface VerifyPortableObjectProofOptions extends VerifyProofOptions {}
|
|
|
289
289
|
* @since 2.4.0
|
|
290
290
|
*/
|
|
291
291
|
type VerifyPortableObjectProofFailureReason = {
|
|
292
|
-
/**
|
|
292
|
+
/**
|
|
293
|
+
* The document has neither a portable `ap:` or `ap+ef61:` ID nor an
|
|
294
|
+
* FEP-ef61 compatible identifier.
|
|
295
|
+
*/
|
|
296
|
+
readonly type: "notPortableObject";
|
|
293
297
|
} | {
|
|
294
298
|
/**
|
|
295
299
|
* The document is a portable collection without an Object Integrity
|
|
@@ -347,15 +351,24 @@ declare function verifyProof(jsonLd: unknown, proof: DataIntegrityProof, options
|
|
|
347
351
|
* collection without a proof is reported separately so a caller can apply a
|
|
348
352
|
* gateway trust policy. Embedded portable objects are not traversed.
|
|
349
353
|
*
|
|
354
|
+
* A portable object is a document whose ID is an `ap:` or `ap+ef61:` URI, or
|
|
355
|
+
* an [FEP-ef61] compatible identifier such as
|
|
356
|
+
* `https://gw.example/.well-known/apgateway/did:key:z6Mk…/actor`, which
|
|
357
|
+
* stands for the portable ID `ap+ef61://did:key:z6Mk…/actor`.
|
|
358
|
+
*
|
|
350
359
|
* Every proof must use a DID URL whose DID matches the portable object's
|
|
351
|
-
* authority, and every proof must
|
|
360
|
+
* authority, i.e., the DID of its canonical portable ID, and every proof must
|
|
361
|
+
* pass {@link verifyProof}. The proofs are verified over the document as
|
|
362
|
+
* given; a compatible identifier is never rewritten into a portable ID.
|
|
363
|
+
*
|
|
364
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
352
365
|
*
|
|
353
366
|
* @param jsonLd The JSON-LD document to verify.
|
|
354
367
|
* @param options Additional options. See also
|
|
355
368
|
* {@link VerifyPortableObjectProofOptions}.
|
|
356
369
|
* @returns The detailed portable proof-policy result.
|
|
357
370
|
* @throws {TypeError} If the input is not a single JSON-LD object or has a
|
|
358
|
-
* malformed portable ID.
|
|
371
|
+
* malformed portable ID or compatible identifier.
|
|
359
372
|
* @since 2.4.0
|
|
360
373
|
*/
|
|
361
374
|
declare function verifyPortableObjectProof(jsonLd: unknown, options?: VerifyPortableObjectProofOptions): Promise<VerifyPortableObjectProofResult>;
|
package/dist/mod.cjs
CHANGED
|
@@ -3,14 +3,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
require("./rolldown-runtime-Dmm3t92W.cjs");
|
|
4
4
|
const require_transformers = require("./transformers-BalCrSsr.cjs");
|
|
5
5
|
require("./compat/mod.cjs");
|
|
6
|
-
const require_http = require("./http-
|
|
7
|
-
const require_federation = require("./federation-
|
|
6
|
+
const require_http = require("./http-DSaSAN7X.cjs");
|
|
7
|
+
const require_federation = require("./federation-aSHO04ob.cjs");
|
|
8
8
|
const require_types = require("./types-Be2zbyeG.cjs");
|
|
9
|
-
const require_owner = require("./owner-
|
|
10
|
-
const require_kv_cache = require("./kv-cache-
|
|
9
|
+
const require_owner = require("./owner-szIZl4qI.cjs");
|
|
10
|
+
const require_kv_cache = require("./kv-cache-BSJAlP4C.cjs");
|
|
11
11
|
require("./nodeinfo/mod.cjs");
|
|
12
12
|
require("./runtime/mod.cjs");
|
|
13
|
-
const require_sig = require("./sig-
|
|
13
|
+
const require_sig = require("./sig-CXOKN4Br.cjs");
|
|
14
14
|
require("./utils/mod.cjs");
|
|
15
15
|
//#endregion
|
|
16
16
|
exports.CircuitBreaker = require_federation.CircuitBreaker;
|
package/dist/mod.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ import { $ as InProcessMessageQueueOptions, A as ObjectCallbackSetters, At as In
|
|
|
6
6
|
import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "./kv-BhNbN8Ed.cjs";
|
|
7
7
|
import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "./compat/mod.cjs";
|
|
8
8
|
import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "./mod-JzkaEXsi.cjs";
|
|
9
|
-
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "./mod-
|
|
9
|
+
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "./mod-C8LieBzF.cjs";
|
|
10
10
|
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-xGFCHqq_.cjs";
|
|
11
11
|
export * from "@fedify/vocab-runtime";
|
|
12
12
|
|
package/dist/mod.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { $ as InProcessMessageQueueOptions, A as ObjectCallbackSetters, At as In
|
|
|
6
6
|
import { a as MemoryKvStore, i as KvStoreSetOptions, n as KvStore, r as KvStoreListEntry, t as KvKey } from "./kv-BhNbN8Ed.js";
|
|
7
7
|
import { actorDehydrator, autoIdAssigner, getDefaultActivityTransformers } from "./compat/mod.js";
|
|
8
8
|
import { a as RouterOptions, i as RouterError, n as handleWebFinger, o as RouterRouteResult, r as Router, t as WebFingerHandlerParameters } from "./mod-B2h2KY0q.js";
|
|
9
|
-
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "./mod-
|
|
9
|
+
import { C as createSignature, D as verifyJsonLd, E as signJsonLd, O as verifySignature, S as attachSignature, T as hasSignatureLike, _ as verifyProof, a as CreateProofOptions, b as VerifyJsonLdOptions, c as VerifyPortableObjectProofFailureReason, d as VerifyProofOptions, f as createProof, g as verifyPortableObjectProof, h as verifyObject, i as verifyPortableObject, l as VerifyPortableObjectProofOptions, m as signObject, n as VerifyPortableObjectOptions, o as SignObjectOptions, p as hasProofLike, r as VerifyPortableObjectResult, s as VerifyObjectOptions, t as VerifyPortableObjectFailureReason, u as VerifyPortableObjectProofResult, v as CreateSignatureOptions, w as detachSignature, x as VerifySignatureOptions, y as SignJsonLdOptions } from "./mod-Coacostr.js";
|
|
10
10
|
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-CVZrXSdm.js";
|
|
11
11
|
export * from "@fedify/vocab-runtime";
|
|
12
12
|
|
package/dist/mod.js
CHANGED
|
@@ -3,15 +3,15 @@ import { URLPattern } from "urlpattern-polyfill";
|
|
|
3
3
|
import "./rolldown-runtime-BC-Eo5Mj.js";
|
|
4
4
|
import { n as autoIdAssigner, r as getDefaultActivityTransformers, t as actorDehydrator } from "./transformers-DAtXl_Kc.js";
|
|
5
5
|
import "./compat/mod.js";
|
|
6
|
-
import {
|
|
7
|
-
import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "./middleware-
|
|
6
|
+
import { C as detachSignature, E as hasSignatureLike, I as fetchKey, L as fetchKeyDetailed, M as verifySignature, P as exportJwk, R as generateCryptoKeyPair, S as createSignature, a as verifyRequestDetailed, b as attachSignature, c as createProof, ct as parseAcceptSignature, f as verifyObject, g as verifyProof, i as verifyRequest, j as verifyJsonLd, k as signJsonLd, l as hasProofLike, lt as validateAcceptSignature, ot as formatAcceptSignature, p as verifyPortableObjectProof, r as signRequest, st as fulfillAcceptSignature, u as signObject, z as importJwk } from "./http-DyT7DP1Y.js";
|
|
7
|
+
import { a as respondWithObject, c as digest, d as parseCircuitBreakerKvState, f as createFederationBuilder, i as SendActivityError, l as CircuitBreaker, n as handleWebFinger, o as respondWithObjectIfAcceptable, r as createExponentialBackoffPolicy, s as buildCollectionSynchronizationHeader, t as createFederation, u as normalizeCircuitBreakerOptions } from "./middleware-Blq0882d.js";
|
|
8
8
|
import { n as getNodeInfo, r as parseNodeInfo, t as nodeInfoToJson } from "./types-C_cNlNVK.js";
|
|
9
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
10
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
9
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-DAGSC5gX.js";
|
|
10
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-DmroAz3M.js";
|
|
11
11
|
import { InProcessMessageQueue, MemoryKvStore, ParallelMessageQueue, Router, RouterError } from "./federation/mod.js";
|
|
12
12
|
import "./nodeinfo/mod.js";
|
|
13
13
|
import "./runtime/mod.js";
|
|
14
|
-
import { t as verifyPortableObject } from "./sig-
|
|
14
|
+
import { t as verifyPortableObject } from "./sig-B5Ell7pO.js";
|
|
15
15
|
import "./utils/mod.js";
|
|
16
16
|
export * from "@fedify/vocab-runtime";
|
|
17
17
|
//#endregion
|
|
@@ -5,7 +5,7 @@ import { r as createRequestContext } from "../context-DlZhxdFT.mjs";
|
|
|
5
5
|
import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
6
6
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
7
7
|
import "../std__assert-DvMDRPes.mjs";
|
|
8
|
-
import {
|
|
8
|
+
import { C as handleNodeInfoJrd, S as handleNodeInfo, o as createFederation } from "../middleware-E_0IH72m.mjs";
|
|
9
9
|
import { test } from "@fedify/fixture";
|
|
10
10
|
//#region src/nodeinfo/handler.test.ts
|
|
11
11
|
test("handleNodeInfo()", async () => {
|
|
@@ -1,9 +1,10 @@
|
|
|
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 {
|
|
6
|
-
import { t as
|
|
4
|
+
import { n as version, t as name } from "./deno-8t8k_6Yv.mjs";
|
|
5
|
+
import { a as isCompatibleKeyId, l as isSamePublicKey$1, s as isPortableId, t as getCanonicalPortableId } from "./portable-key-id-Bva5iT3W.mjs";
|
|
6
|
+
import { c as verifyKeyOwnership, n as fetchActorDocument, t as exportJwk } from "./key-Dwm4VswT.mjs";
|
|
7
|
+
import { t as fetchPortableGatewayKey } from "./portable-key-Cn1WJSN1.mjs";
|
|
7
8
|
import { getLogger } from "@logtape/logtape";
|
|
8
9
|
import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
9
10
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -176,7 +177,7 @@ async function getKeyOwner(keyId, options) {
|
|
|
176
177
|
return await verifyKeyOwnership(object.id == null ? object.clone({ id: keyId }) : object, fetchOptions);
|
|
177
178
|
}
|
|
178
179
|
if (!isActor(object)) return null;
|
|
179
|
-
if (object.id == null || object.id.origin !== documentUrl.origin) {
|
|
180
|
+
if (object.id == null || isPortableId(object.id) || object.id.origin !== documentUrl.origin) {
|
|
180
181
|
logger.debug("The document served at {documentUrl} claims to be the actor {actorId}, which belongs to another origin; refusing to treat it as the owner of key {keyId}.", {
|
|
181
182
|
documentUrl: documentUrl.href,
|
|
182
183
|
actorId: object.id?.href,
|