@fedify/fedify 2.4.0-dev.2010 → 2.4.0-dev.2030
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{assert-CebeUf0C.mjs → assert-D1Eafmd_.mjs} +1 -1
- package/dist/{assert_equals-CBlRfA-_.mjs → assert_equals-Z6IcEbWU.mjs} +2 -28
- package/dist/{assert_exists-DtzkXC47.mjs → assert_exists-cffSpJ7X.mjs} +1 -1
- package/dist/{assert_false-3pLLLsO4.mjs → assert_false-CPdRnc3E.mjs} +1 -1
- package/dist/{assert_greater_or_equal-BApOTh1h.mjs → assert_greater_or_equal-BlafOF4-.mjs} +2 -1
- package/dist/{assert_instance_of-g3WcyYNR.mjs → assert_instance_of-mrXWWNY-.mjs} +1 -1
- package/dist/{assert_not_equals-BN7yDMWe.mjs → assert_not_equals-CpPK2t89.mjs} +2 -1
- package/dist/{assert_rejects-wFbSPn1O.mjs → assert_rejects-CTptdYck.mjs} +2 -2
- package/dist/{assert_strict_equals-Bpjl4Psw.mjs → assert_strict_equals-CYvBmkpC.mjs} +2 -1
- package/dist/{assert_throws-BJ5wuvR2.mjs → assert_throws-BYITOvPO.mjs} +2 -1
- package/dist/assertion_error-B-cx0fFA.mjs +31 -0
- package/dist/{builder-asm96yV1.mjs → builder-BYJ5otJa.mjs} +2 -2
- package/dist/compat/outgoing-jsonld.test.mjs +71 -3
- package/dist/compat/public-audience.test.mjs +3 -3
- package/dist/compat/secured-document.test.d.mts +2 -0
- package/dist/compat/secured-document.test.mjs +58 -0
- package/dist/compat/transformers.test.mjs +4 -4
- package/dist/{compound-proof-7UIAueLV.mjs → compound-proof-BIvUoJxm.mjs} +74 -2
- package/dist/{deno-Ckq9TwCv.mjs → deno-Vj_9wePq.mjs} +1 -1
- package/dist/{docloader-DUKEPG-O.mjs → docloader-qUudHZVH.mjs} +2 -2
- package/dist/federation/builder.test.mjs +5 -5
- package/dist/federation/circuit-breaker.test.mjs +3 -3
- package/dist/federation/collection.test.mjs +2 -2
- package/dist/federation/compound-fanout.test.d.mts +2 -0
- package/dist/federation/compound-fanout.test.mjs +228 -0
- package/dist/federation/handler-compound-proof.test.mjs +5 -5
- package/dist/federation/handler.test.mjs +11 -11
- package/dist/federation/idempotency.test.mjs +4 -4
- package/dist/federation/inbox.test.mjs +2 -2
- package/dist/federation/keycache.test.mjs +3 -3
- package/dist/federation/kv.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +4 -4
- package/dist/federation/middleware.test.mjs +17 -17
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +7 -6
- package/dist/federation/negotiation.test.mjs +3 -3
- package/dist/federation/outgoing-proof.test.d.mts +2 -0
- package/dist/federation/outgoing-proof.test.mjs +396 -0
- package/dist/federation/retry.test.mjs +3 -2
- package/dist/federation/router.test.mjs +5 -5
- package/dist/federation/send.test.mjs +11 -11
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +4 -4
- package/dist/federation/webfinger.test.mjs +4 -4
- package/dist/{federation-CgbvMauV.cjs → federation-CTnaljmy.cjs} +203 -37
- package/dist/{http-DQBfmkrS.cjs → http-B5F1JMh0.cjs} +1 -1
- package/dist/{http-DQA2JOEJ.js → http-By8tnmEr.js} +1 -1
- package/dist/{http-DZaAutqg.mjs → http-D4WPcJUe.mjs} +3 -3
- package/dist/{key-zxzx01Ec.mjs → key-B_Zc5Jbd.mjs} +2 -2
- package/dist/{kv-cache-sy8OMNT8.cjs → kv-cache-8K70pjtX.cjs} +1 -1
- package/dist/{kv-cache-CbrUX90H.mjs → kv-cache-BXdT7pJQ.mjs} +1 -1
- package/dist/{kv-cache-BBoePTOJ.js → kv-cache-BswMKQjC.js} +1 -1
- package/dist/{ld-CD_TN0e8.mjs → ld-B16KUSIQ.mjs} +3 -3
- package/dist/{metrics-B47Cm5gK.mjs → metrics-DpQqUAmh.mjs} +1 -1
- package/dist/{middleware-U_Gannqi.mjs → middleware-BL5HFFVU.mjs} +1 -1
- package/dist/{middleware-pHwDTAnq.mjs → middleware-C7_hqDnl.mjs} +143 -49
- package/dist/{middleware-U0OIuqwD.js → middleware-Cxto6Bq2.js} +204 -38
- package/dist/{mod-UDwMjuHM.d.ts → mod-CNRAxXEb.d.ts} +1 -5
- package/dist/{mod-CbKDOnCt.d.cts → mod-CVQFWefn.d.cts} +1 -5
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/client.test.mjs +2 -2
- package/dist/nodeinfo/handler.test.mjs +3 -3
- package/dist/nodeinfo/types.test.mjs +3 -3
- package/dist/otel/exporter.test.mjs +2 -2
- package/dist/{outgoing-jsonld-B5Ne7JoL.mjs → outgoing-jsonld-4IJqPYos.mjs} +11 -9
- package/dist/{owner-u3IJRhVx.mjs → owner-BIOIhZoM.mjs} +2 -2
- package/dist/{owner-BNKC3s6G.js → owner-D-E0bT2O.js} +127 -35
- package/dist/{owner--mNatWct.cjs → owner-WUYke16i.cjs} +126 -34
- package/dist/{proof-D3te0SP-.mjs → proof-BVxJu5vv.mjs} +80 -23
- package/dist/{public-audience-Cc2YJ3ip.mjs → public-audience--klBIOk1.mjs} +13 -9
- package/dist/secured-document-CxzZZ9nL.mjs +35 -0
- package/dist/{send-CDr0Zivk.mjs → send-Cr5FJ7iu.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +3 -3
- package/dist/sig/compound-proof-producer.test.d.mts +2 -0
- package/dist/sig/compound-proof-producer.test.mjs +107 -0
- package/dist/sig/compound-proof-verification.test.mjs +5 -5
- package/dist/sig/compound-proof.test.mjs +145 -58
- package/dist/sig/http.test.mjs +11 -10
- package/dist/sig/key.test.mjs +6 -6
- package/dist/sig/ld.test.mjs +9 -9
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +1 -1
- package/dist/sig/mod.d.ts +1 -1
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +5 -5
- package/dist/sig/proof.test.mjs +9 -9
- package/dist/std__assert-DvMDRPes.mjs +8 -0
- package/dist/{temporal-DKhVF_Uk.mjs → temporal-CCf0lZV3.mjs} +1 -1
- package/dist/testing/kv.test.mjs +2 -2
- package/dist/utils/docloader.test.mjs +5 -5
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
- package/dist/std__assert-CxFT0MNt.mjs +0 -8
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-
|
|
4
|
+
import { n as version, t as name } from "./deno-Vj_9wePq.mjs";
|
|
5
|
+
import { a as instrumentDocumentLoader, b as recordWebFingerHandle, c as recordCircuitBreakerStateChange, d as recordCollectionRequest, f as recordCollectionTotalItems, g as recordInboxActivity, h as recordFanoutRecipients, i as getRemoteHost, l as recordCollectionDispatchDuration, n as getDurationMs, o as isAbortError, r as getFederationMetrics, u as recordCollectionPageItems, v as recordOutboxActivity, x as registerQueueDepthGauge, y as recordOutboxEnqueue } from "./metrics-DpQqUAmh.mjs";
|
|
6
6
|
import { t as formatAcceptSignature } from "./accept-CPVqki78.mjs";
|
|
7
|
-
import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-
|
|
8
|
-
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-
|
|
9
|
-
import { t as getAuthenticatedDocumentLoader } from "./docloader-
|
|
10
|
-
import { n as kvCache } from "./kv-cache-
|
|
11
|
-
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-
|
|
7
|
+
import { o as importJwk, s as validateCryptoKey, t as exportJwk } from "./key-B_Zc5Jbd.mjs";
|
|
8
|
+
import { l as verifyRequest, o as parseRfc9421SignatureInput, u as verifyRequestDetailed } from "./http-D4WPcJUe.mjs";
|
|
9
|
+
import { t as getAuthenticatedDocumentLoader } from "./docloader-qUudHZVH.mjs";
|
|
10
|
+
import { n as kvCache } from "./kv-cache-BXdT7pJQ.mjs";
|
|
11
|
+
import { r as normalizeOutgoingActivityJsonLd } from "./outgoing-jsonld-4IJqPYos.mjs";
|
|
12
12
|
import { d as readBoundedText, l as BodyTooLargeError, t as getNodeInfo, u as MAX_BODY_SIZE } from "./client-DpnpgjyX.mjs";
|
|
13
13
|
import { t as nodeInfoToJson } from "./types-DE_LV1JB.mjs";
|
|
14
|
-
import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-
|
|
15
|
-
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-
|
|
16
|
-
import { a as verifyObject, n as hasProofLike, r as signObject } from "./proof-
|
|
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-
|
|
14
|
+
import { _ as wrapContextLoaderForJsonLd, a as compactJsonLd, c as getNormalizationContextLoader, d as isClearlyMalformedContextReference, f as isInvalidUrlTypeError, l as hasSignature, m as verifyCompactJsonLd, p as signJsonLd, r as assertSafeJsonLd, s as detachSignature, t as InvalidContextReferenceError, u as hasSignatureLike } from "./ld-B16KUSIQ.mjs";
|
|
15
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "./owner-BIOIhZoM.mjs";
|
|
16
|
+
import { a as verifyObject, n as hasProofLike, r as signObject } from "./proof-BVxJu5vv.mjs";
|
|
17
|
+
import { n as extractInboxes, r as sendActivity, t as SendActivityError } from "./send-Cr5FJ7iu.mjs";
|
|
18
|
+
import { n as FederationBuilderImpl, t as ACTOR_ALIAS_PREFIX } from "./builder-BYJ5otJa.mjs";
|
|
19
19
|
import { t as CircuitBreaker } from "./circuit-breaker-C5NqoLBJ.mjs";
|
|
20
20
|
import { t as buildCollectionSynchronizationHeader } from "./collection-CnnP1UAv.mjs";
|
|
21
|
-
import {
|
|
21
|
+
import { a as verifyCompoundPortableObjectProofs, i as inspectCompoundPortableObjectApplicability, r as findUnsupportedCompoundProofShape, t as containsCompoundPortableObject } from "./compound-proof-BIvUoJxm.mjs";
|
|
22
22
|
import { t as KvKeyCache } from "./keycache-BUDHB5rY.mjs";
|
|
23
23
|
import { t as acceptsJsonLd } from "./negotiation-CCocWT_N.mjs";
|
|
24
|
-
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-
|
|
24
|
+
import { t as hasMalformedKnownTemporalLiteral } from "./temporal-CCf0lZV3.mjs";
|
|
25
25
|
import { t as createExponentialBackoffPolicy } from "./retry-zX5xw5e0.mjs";
|
|
26
26
|
import { t as TaskCodec } from "./codec-C6rTrpIp.mjs";
|
|
27
27
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
@@ -30,7 +30,7 @@ import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey,
|
|
|
30
30
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
31
31
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
32
32
|
import { uniq } from "es-toolkit";
|
|
33
|
-
import { FetchError, getDocumentLoader } from "@fedify/vocab-runtime";
|
|
33
|
+
import { FetchError, getDocumentLoader, getFe34Origin, haveSameFe34Origin } from "@fedify/vocab-runtime";
|
|
34
34
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
35
35
|
import { DataPointType, MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
|
|
36
36
|
import { domainToASCII } from "node:url";
|
|
@@ -2326,6 +2326,102 @@ const MIN_COMPONENTS = [
|
|
|
2326
2326
|
"@authority"
|
|
2327
2327
|
];
|
|
2328
2328
|
//#endregion
|
|
2329
|
+
//#region src/federation/outgoing-proof.ts
|
|
2330
|
+
function isPortableUrl(url) {
|
|
2331
|
+
return url.protocol === "ap:" || url.protocol === "ap+ef61:";
|
|
2332
|
+
}
|
|
2333
|
+
function formatKeyIds(candidates) {
|
|
2334
|
+
return candidates.map((c) => c.verificationMethod.href).join(", ");
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* Creates the Object Integrity Proofs Fedify attaches to an outgoing activity.
|
|
2338
|
+
*
|
|
2339
|
+
* Outside the map-local compound-proof profile, i.e., when the activity
|
|
2340
|
+
* embeds no portable object, every Ed25519 key signs the activity, as it
|
|
2341
|
+
* always has. Inside the profile, which accepts exactly one direct proof per
|
|
2342
|
+
* map, Fedify creates at most one proof:
|
|
2343
|
+
*
|
|
2344
|
+
* - An activity that already carries a proof is kept as is.
|
|
2345
|
+
* - A single Ed25519 key signs the activity.
|
|
2346
|
+
* - With several Ed25519 keys, a portable activity is signed by the one key
|
|
2347
|
+
* whose verification method is a DID URL for the activity's DID, the only
|
|
2348
|
+
* proof the FEP-ef61 policy can accept. If no key or more than one key
|
|
2349
|
+
* qualifies, or the activity is not portable itself, the choice is
|
|
2350
|
+
* ambiguous and this function throws.
|
|
2351
|
+
*
|
|
2352
|
+
* @throws {TypeError} If a single proof key cannot be chosen.
|
|
2353
|
+
* @internal
|
|
2354
|
+
*/
|
|
2355
|
+
async function signOutgoingActivity(activity, candidates, options) {
|
|
2356
|
+
const { contextLoader, tracerProvider } = options;
|
|
2357
|
+
let hasProof = false;
|
|
2358
|
+
for await (const _ of activity.getProofs({ contextLoader })) {
|
|
2359
|
+
hasProof = true;
|
|
2360
|
+
break;
|
|
2361
|
+
}
|
|
2362
|
+
const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519");
|
|
2363
|
+
if (keys.length < 1 || hasProof && !options.appendToExistingProofs) return {
|
|
2364
|
+
activity,
|
|
2365
|
+
hasProof,
|
|
2366
|
+
proofCreated: false
|
|
2367
|
+
};
|
|
2368
|
+
const sign = async (selected) => {
|
|
2369
|
+
for (const { verificationMethod, privateKey } of selected) activity = await signObject(activity, privateKey, verificationMethod, {
|
|
2370
|
+
contextLoader,
|
|
2371
|
+
tracerProvider
|
|
2372
|
+
});
|
|
2373
|
+
return {
|
|
2374
|
+
activity,
|
|
2375
|
+
hasProof: true,
|
|
2376
|
+
proofCreated: true
|
|
2377
|
+
};
|
|
2378
|
+
};
|
|
2379
|
+
if (keys.length < 2 && !hasProof) return await sign(keys);
|
|
2380
|
+
if (!containsCompoundPortableObject(await activity.toJsonLd({
|
|
2381
|
+
format: "compact",
|
|
2382
|
+
contextLoader
|
|
2383
|
+
}))) return await sign(keys);
|
|
2384
|
+
const logger = getLogger([
|
|
2385
|
+
"fedify",
|
|
2386
|
+
"federation",
|
|
2387
|
+
"outbox"
|
|
2388
|
+
]);
|
|
2389
|
+
const activityId = activity.id?.href;
|
|
2390
|
+
if (hasProof) {
|
|
2391
|
+
logger.debug("The activity {activityId} embeds portable objects and already carries a proof, so no further proof is added; the map-local compound-proof profile accepts exactly one direct proof per map.", { activityId });
|
|
2392
|
+
return {
|
|
2393
|
+
activity,
|
|
2394
|
+
hasProof,
|
|
2395
|
+
proofCreated: false
|
|
2396
|
+
};
|
|
2397
|
+
}
|
|
2398
|
+
if (activity.id == null || !isPortableUrl(activity.id)) throw new TypeError(`Cannot choose an Object Integrity Proof key for the activity ${activityId}: it embeds portable objects, so it falls under the map-local compound-proof profile, which accepts exactly one direct proof per map, but ${keys.length} Ed25519 keys were supplied (${formatKeyIds(keys)}). Send it with explicit sender keys that contain exactly one Ed25519 key (RSA keys for HTTP Signatures may stay), or sign it with signObject() before sending it.`);
|
|
2399
|
+
const activityDid = getFe34Origin(activity.id);
|
|
2400
|
+
const eligible = keys.filter((c) => c.verificationMethod.protocol === "did:" && haveSameFe34Origin(activity.id, c.verificationMethod));
|
|
2401
|
+
if (eligible.length !== 1) throw new TypeError(`Cannot choose an Object Integrity Proof key for the portable activity ${activityId}: ` + (eligible.length < 1 ? `none of its ${keys.length} Ed25519 keys (${formatKeyIds(keys)}) ` : `${eligible.length} of its Ed25519 keys (${formatKeyIds(eligible)}) `) + `${eligible.length < 1 ? "is" : "are"} a DID URL verification method for ${activityDid}. The map-local compound-proof profile accepts exactly one direct proof per map, and FEP-ef61 requires that proof's verification method to be a DID URL for the activity's DID. Supply exactly one Ed25519 key whose key ID is a DID URL for ${activityDid}, or sign the activity with signObject() before sending it.`);
|
|
2402
|
+
logger.debug("The portable activity {activityId} is signed only by {keyId}, the one Ed25519 key whose verification method matches its DID; the map-local compound-proof profile accepts exactly one direct proof per map.", {
|
|
2403
|
+
activityId,
|
|
2404
|
+
keyId: eligible[0].verificationMethod.href
|
|
2405
|
+
});
|
|
2406
|
+
return await sign(eligible);
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Rejects an outgoing activity whose proofs Fedify's own inbox would reject
|
|
2410
|
+
* as unsupported: a document with portable objects in which some map carries
|
|
2411
|
+
* a proof set or another value that is not a single proof map.
|
|
2412
|
+
*
|
|
2413
|
+
* @param jsonLd The compact JSON-LD document about to be delivered.
|
|
2414
|
+
* @param activityId The activity ID, for the error message.
|
|
2415
|
+
* @throws {TypeError} If the document has an unsupported proof shape.
|
|
2416
|
+
* @internal
|
|
2417
|
+
*/
|
|
2418
|
+
function assertSupportedCompoundProofShape(jsonLd, activityId) {
|
|
2419
|
+
if (!containsCompoundPortableObject(jsonLd)) return;
|
|
2420
|
+
const path = findUnsupportedCompoundProofShape(jsonLd);
|
|
2421
|
+
if (path == null) return;
|
|
2422
|
+
throw new TypeError(`Cannot send the activity ${activityId}: it embeds portable objects, but its proof at the JSON Pointer ${JSON.stringify(path)} is not a single proof map. The map-local compound-proof profile accepts exactly one direct proof per map, so Fedify inboxes would reject the activity. Sign each object with exactly one key.`);
|
|
2423
|
+
}
|
|
2424
|
+
//#endregion
|
|
2329
2425
|
//#region src/federation/tasks/enqueue.ts
|
|
2330
2426
|
/**
|
|
2331
2427
|
* The enqueue pipeline for custom background tasks. `ContextImpl.enqueueTask`
|
|
@@ -3272,6 +3368,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3272
3368
|
collectionSync: message.collectionSync,
|
|
3273
3369
|
orderingKey: message.orderingKey,
|
|
3274
3370
|
normalizeExistingProofs: message.normalizeExistingProofs,
|
|
3371
|
+
activityJsonLd: message.activity,
|
|
3275
3372
|
context
|
|
3276
3373
|
});
|
|
3277
3374
|
}
|
|
@@ -3953,8 +4050,6 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3953
4050
|
else if (keys.length < 1) throw new TypeError("The keys must not be empty.");
|
|
3954
4051
|
const contextLoader = this.contextLoaderFactory(this.#getLoaderOptions(ctx.origin));
|
|
3955
4052
|
const activityId = activity.id.href;
|
|
3956
|
-
let hasProof = false;
|
|
3957
|
-
let proofCreated = false;
|
|
3958
4053
|
let rsaKey = null;
|
|
3959
4054
|
for (const { keyId, privateKey } of keys) {
|
|
3960
4055
|
validateCryptoKey(privateKey, "private");
|
|
@@ -3963,25 +4058,22 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
3963
4058
|
privateKey
|
|
3964
4059
|
};
|
|
3965
4060
|
}
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
}
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
proofCreated = true;
|
|
3978
|
-
}
|
|
3979
|
-
}
|
|
3980
|
-
let jsonLd = await activity.toJsonLd({
|
|
4061
|
+
const signed = await signOutgoingActivity(activity, keys.map(({ keyId, privateKey }) => ({
|
|
4062
|
+
verificationMethod: keyId,
|
|
4063
|
+
privateKey
|
|
4064
|
+
})), {
|
|
4065
|
+
contextLoader,
|
|
4066
|
+
tracerProvider: this.tracerProvider,
|
|
4067
|
+
appendToExistingProofs: false
|
|
4068
|
+
});
|
|
4069
|
+
activity = signed.activity;
|
|
4070
|
+
const { hasProof, proofCreated } = signed;
|
|
4071
|
+
let jsonLd = !proofCreated && options.activityJsonLd != null ? options.activityJsonLd : await activity.toJsonLd({
|
|
3981
4072
|
format: "compact",
|
|
3982
4073
|
contextLoader
|
|
3983
4074
|
});
|
|
3984
|
-
if (proofCreated || !hasProof || options.normalizeExistingProofs) jsonLd = await normalizeOutgoingActivityJsonLd(jsonLd, contextLoader);
|
|
4075
|
+
if (proofCreated || !hasProof || options.normalizeExistingProofs) jsonLd = await normalizeOutgoingActivityJsonLd(jsonLd, contextLoader, { preserveNestedSecuredDocuments: true });
|
|
4076
|
+
assertSupportedCompoundProofShape(jsonLd, activityId);
|
|
3985
4077
|
if (rsaKey == null) logger.warn("No supported key found to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature. In order to create a Linked Data signature, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
|
|
3986
4078
|
activityId,
|
|
3987
4079
|
keys: keys.map((pair) => ({
|
|
@@ -4953,18 +5045,18 @@ var ContextImpl = class ContextImpl {
|
|
|
4953
5045
|
});
|
|
4954
5046
|
throw new TypeError("The activity to send must have at least one actor property.");
|
|
4955
5047
|
}
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
5048
|
+
const { activity: signedActivity, proofCreated } = await signOutgoingActivity(activity, actorKeyPairs == null ? keys.map(({ keyId, privateKey }) => ({
|
|
5049
|
+
verificationMethod: keyId,
|
|
5050
|
+
privateKey
|
|
5051
|
+
})) : actorKeyPairs.flatMap((kp) => kp.multikey.id == null ? [] : [{
|
|
5052
|
+
verificationMethod: kp.multikey.id,
|
|
5053
|
+
privateKey: kp.privateKey
|
|
5054
|
+
}]), {
|
|
5055
|
+
contextLoader: this.contextLoader,
|
|
5056
|
+
tracerProvider: this.tracerProvider,
|
|
5057
|
+
appendToExistingProofs: actorKeyPairs != null
|
|
5058
|
+
});
|
|
5059
|
+
activity = signedActivity;
|
|
4968
5060
|
const inboxes = extractInboxes({
|
|
4969
5061
|
recipients: expandedRecipients,
|
|
4970
5062
|
preferSharedInbox: options.preferSharedInbox,
|
|
@@ -4989,6 +5081,11 @@ var ContextImpl = class ContextImpl {
|
|
|
4989
5081
|
});
|
|
4990
5082
|
return true;
|
|
4991
5083
|
}
|
|
5084
|
+
const activityJsonLd = await activity.toJsonLd({
|
|
5085
|
+
format: "compact",
|
|
5086
|
+
contextLoader: this.contextLoader
|
|
5087
|
+
});
|
|
5088
|
+
assertSupportedCompoundProofShape(activityJsonLd, activity.id?.href);
|
|
4992
5089
|
const keyJwkPairs = await Promise.all(keys.map(async ({ keyId, privateKey }) => ({
|
|
4993
5090
|
keyId: keyId.href,
|
|
4994
5091
|
privateKey: await exportJwk(privateKey)
|
|
@@ -5004,10 +5101,7 @@ var ContextImpl = class ContextImpl {
|
|
|
5004
5101
|
actorIds: [...actorIds],
|
|
5005
5102
|
sharedInbox
|
|
5006
5103
|
}])),
|
|
5007
|
-
activity:
|
|
5008
|
-
format: "compact",
|
|
5009
|
-
contextLoader: this.contextLoader
|
|
5010
|
-
}),
|
|
5104
|
+
activity: activityJsonLd,
|
|
5011
5105
|
activityId: activity.id?.href,
|
|
5012
5106
|
activityType: getTypeId(activity).href,
|
|
5013
5107
|
collectionSync: opts.collectionSync,
|
|
@@ -2,16 +2,16 @@ import { Temporal } from "temporal-polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./rolldown-runtime-BC-Eo5Mj.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-DAtXl_Kc.js";
|
|
5
|
-
import { A as recordWebFingerHandle, C as recordCollectionRequest, D as recordInboxActivity, E as recordFanoutRecipients, I as name, L as version, M as formatAcceptSignature, O as recordOutboxActivity, S as recordCollectionPageItems, _ as instrumentDocumentLoader, a as verifyRequestDetailed, b as recordCircuitBreakerStateChange, d as importJwk, f as validateCryptoKey, g as getRemoteHost, h as getFederationMetrics, i as verifyRequest, j as registerQueueDepthGauge, k as recordOutboxEnqueue, m as getDurationMs, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as isAbortError, w as recordCollectionTotalItems, x as recordCollectionDispatchDuration } from "./http-
|
|
5
|
+
import { A as recordWebFingerHandle, C as recordCollectionRequest, D as recordInboxActivity, E as recordFanoutRecipients, I as name, L as version, M as formatAcceptSignature, O as recordOutboxActivity, S as recordCollectionPageItems, _ as instrumentDocumentLoader, a as verifyRequestDetailed, b as recordCircuitBreakerStateChange, d as importJwk, f as validateCryptoKey, g as getRemoteHost, h as getFederationMetrics, i as verifyRequest, j as registerQueueDepthGauge, k as recordOutboxEnqueue, m as getDurationMs, n as parseRfc9421SignatureInput, o as exportJwk, t as doubleKnock, v as isAbortError, w as recordCollectionTotalItems, x as recordCollectionDispatchDuration } from "./http-By8tnmEr.js";
|
|
6
6
|
import { a as MAX_BODY_SIZE, i as BodyTooLargeError, n as getNodeInfo, o as readBoundedText, t as nodeInfoToJson } from "./types-C_cNlNVK.js";
|
|
7
|
-
import { C as verifyCompactJsonLd, D as normalizeOutgoingActivityJsonLd, E as wrapContextLoaderForJsonLd, S as signJsonLd, _ as getNormalizationContextLoader, a as signObject, b as isClearlyMalformedContextReference, d as InvalidContextReferenceError, f as assertSafeJsonLd, g as detachSignature, i as hasProofLike, l as verifyPortableObjectProofPolicy, m as compactJsonLd, n as getKeyOwner, o as verifyMapLocalProof, s as verifyObject, t as doesActorOwnKey, v as hasSignature, x as isInvalidUrlTypeError, y as hasSignatureLike } from "./owner-
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
7
|
+
import { C as verifyCompactJsonLd, D as normalizeOutgoingActivityJsonLd, E as wrapContextLoaderForJsonLd, S as signJsonLd, _ as getNormalizationContextLoader, a as signObject, b as isClearlyMalformedContextReference, d as InvalidContextReferenceError, f as assertSafeJsonLd, g as detachSignature, i as hasProofLike, l as verifyPortableObjectProofPolicy, m as compactJsonLd, n as getKeyOwner, o as verifyMapLocalProof, s as verifyObject, t as doesActorOwnKey, v as hasSignature, x as isInvalidUrlTypeError, y as hasSignatureLike } from "./owner-D-E0bT2O.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-BswMKQjC.js";
|
|
9
9
|
import { getLogger, withContext } from "@logtape/logtape";
|
|
10
10
|
import { Router, RouterError, assertPath } from "@fedify/uri-template";
|
|
11
11
|
import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, Tombstone, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
12
12
|
import { SpanKind, SpanStatusCode, context, metrics, propagation, trace } from "@opentelemetry/api";
|
|
13
13
|
import { encodeHex } from "byte-encodings/hex";
|
|
14
|
-
import { FetchError, UrlError, getDocumentLoader, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
14
|
+
import { FetchError, UrlError, getDocumentLoader, getFe34Origin, haveSameFe34Origin, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
15
15
|
import { uniq } from "es-toolkit";
|
|
16
16
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
17
17
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_HEADER, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
@@ -1643,6 +1643,78 @@ function inspectCompoundPortableObjectApplicability(json, limits) {
|
|
|
1643
1643
|
return "absent";
|
|
1644
1644
|
}
|
|
1645
1645
|
/**
|
|
1646
|
+
* Walks every JSON map in a finite, already-materialized JSON tree, depth
|
|
1647
|
+
* first in insertion order, skipping the values of `proof` and `@context`
|
|
1648
|
+
* members. A map reached a second time through a repeated reference is not
|
|
1649
|
+
* visited again, so a cyclic input terminates. The walk stops as soon as
|
|
1650
|
+
* the visitor returns a value other than `undefined`.
|
|
1651
|
+
*/
|
|
1652
|
+
function findInJsonMaps(json, visit) {
|
|
1653
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1654
|
+
const pending = [{
|
|
1655
|
+
value: json,
|
|
1656
|
+
path: ""
|
|
1657
|
+
}];
|
|
1658
|
+
while (pending.length > 0) {
|
|
1659
|
+
const { value, path } = pending.pop();
|
|
1660
|
+
if (typeof value !== "object" || value == null || seen.has(value)) continue;
|
|
1661
|
+
seen.add(value);
|
|
1662
|
+
if (Array.isArray(value)) {
|
|
1663
|
+
for (let index = value.length - 1; index >= 0; index--) pending.push({
|
|
1664
|
+
value: value[index],
|
|
1665
|
+
path: childPath(path, String(index))
|
|
1666
|
+
});
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
const map = value;
|
|
1670
|
+
const result = visit(map, path);
|
|
1671
|
+
if (result !== void 0) return result;
|
|
1672
|
+
const keys = Object.keys(map);
|
|
1673
|
+
for (let index = keys.length - 1; index >= 0; index--) {
|
|
1674
|
+
const key = keys[index];
|
|
1675
|
+
if (key === "proof" || key === "@context") continue;
|
|
1676
|
+
pending.push({
|
|
1677
|
+
value: map[key],
|
|
1678
|
+
path: childPath(path, key)
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
/**
|
|
1684
|
+
* Determines whether an outgoing JSON tree contains portable content that
|
|
1685
|
+
* requires producer-side proof-shape checks: a map, outside proof and context
|
|
1686
|
+
* values, whose direct `id` or `@id` is a portable ActivityPub URI.
|
|
1687
|
+
*
|
|
1688
|
+
* This deliberately differs from
|
|
1689
|
+
* {@link inspectCompoundPortableObjectApplicability}: it applies no resource
|
|
1690
|
+
* limits, so a portable map or an unsupported proof beyond the inbox limits
|
|
1691
|
+
* is still found, and a large document without portable maps stays outside
|
|
1692
|
+
* the compound-proof profile. The input must be a finite JSON tree that has
|
|
1693
|
+
* already been materialized, such as a compact JSON-LD document about to be
|
|
1694
|
+
* sent.
|
|
1695
|
+
*
|
|
1696
|
+
* @internal
|
|
1697
|
+
*/
|
|
1698
|
+
function containsCompoundPortableObject(json) {
|
|
1699
|
+
return findInJsonMaps(json, (map) => [map.id, map["@id"]].some((id) => typeof id === "string" && PORTABLE_OBJECT_ID_PATTERN.test(id)) ? true : void 0) ?? false;
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Finds the first direct `proof` member whose value the map-local
|
|
1703
|
+
* compound-proof profile does not accept, i.e., anything other than a single
|
|
1704
|
+
* JSON map: a proof set, `null`, or a scalar. Like the inbox discovery, it
|
|
1705
|
+
* does not look inside proof or context values.
|
|
1706
|
+
*
|
|
1707
|
+
* The input must be a finite, already-materialized JSON tree; see
|
|
1708
|
+
* {@link containsCompoundPortableObject}.
|
|
1709
|
+
*
|
|
1710
|
+
* @returns The RFC 6901 JSON Pointer to the unsupported `proof` member, or
|
|
1711
|
+
* `null` if every direct proof is a single JSON map.
|
|
1712
|
+
* @internal
|
|
1713
|
+
*/
|
|
1714
|
+
function findUnsupportedCompoundProofShape(json) {
|
|
1715
|
+
return findInJsonMaps(json, (map, path) => Object.hasOwn(map, "proof") && !isJsonMap(map.proof) ? childPath(path, "proof") : void 0) ?? null;
|
|
1716
|
+
}
|
|
1717
|
+
/**
|
|
1646
1718
|
* Discovers direct literal proof-bearing maps in an immutable JSON snapshot.
|
|
1647
1719
|
*
|
|
1648
1720
|
* Discovery is bounded and atomic. Unsupported proof shapes, non-JSON input,
|
|
@@ -4535,6 +4607,102 @@ function serializeDataPointType(dataPointType) {
|
|
|
4535
4607
|
}
|
|
4536
4608
|
}
|
|
4537
4609
|
//#endregion
|
|
4610
|
+
//#region src/federation/outgoing-proof.ts
|
|
4611
|
+
function isPortableUrl(url) {
|
|
4612
|
+
return url.protocol === "ap:" || url.protocol === "ap+ef61:";
|
|
4613
|
+
}
|
|
4614
|
+
function formatKeyIds(candidates) {
|
|
4615
|
+
return candidates.map((c) => c.verificationMethod.href).join(", ");
|
|
4616
|
+
}
|
|
4617
|
+
/**
|
|
4618
|
+
* Creates the Object Integrity Proofs Fedify attaches to an outgoing activity.
|
|
4619
|
+
*
|
|
4620
|
+
* Outside the map-local compound-proof profile, i.e., when the activity
|
|
4621
|
+
* embeds no portable object, every Ed25519 key signs the activity, as it
|
|
4622
|
+
* always has. Inside the profile, which accepts exactly one direct proof per
|
|
4623
|
+
* map, Fedify creates at most one proof:
|
|
4624
|
+
*
|
|
4625
|
+
* - An activity that already carries a proof is kept as is.
|
|
4626
|
+
* - A single Ed25519 key signs the activity.
|
|
4627
|
+
* - With several Ed25519 keys, a portable activity is signed by the one key
|
|
4628
|
+
* whose verification method is a DID URL for the activity's DID, the only
|
|
4629
|
+
* proof the FEP-ef61 policy can accept. If no key or more than one key
|
|
4630
|
+
* qualifies, or the activity is not portable itself, the choice is
|
|
4631
|
+
* ambiguous and this function throws.
|
|
4632
|
+
*
|
|
4633
|
+
* @throws {TypeError} If a single proof key cannot be chosen.
|
|
4634
|
+
* @internal
|
|
4635
|
+
*/
|
|
4636
|
+
async function signOutgoingActivity(activity, candidates, options) {
|
|
4637
|
+
const { contextLoader, tracerProvider } = options;
|
|
4638
|
+
let hasProof = false;
|
|
4639
|
+
for await (const _ of activity.getProofs({ contextLoader })) {
|
|
4640
|
+
hasProof = true;
|
|
4641
|
+
break;
|
|
4642
|
+
}
|
|
4643
|
+
const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519");
|
|
4644
|
+
if (keys.length < 1 || hasProof && !options.appendToExistingProofs) return {
|
|
4645
|
+
activity,
|
|
4646
|
+
hasProof,
|
|
4647
|
+
proofCreated: false
|
|
4648
|
+
};
|
|
4649
|
+
const sign = async (selected) => {
|
|
4650
|
+
for (const { verificationMethod, privateKey } of selected) activity = await signObject(activity, privateKey, verificationMethod, {
|
|
4651
|
+
contextLoader,
|
|
4652
|
+
tracerProvider
|
|
4653
|
+
});
|
|
4654
|
+
return {
|
|
4655
|
+
activity,
|
|
4656
|
+
hasProof: true,
|
|
4657
|
+
proofCreated: true
|
|
4658
|
+
};
|
|
4659
|
+
};
|
|
4660
|
+
if (keys.length < 2 && !hasProof) return await sign(keys);
|
|
4661
|
+
if (!containsCompoundPortableObject(await activity.toJsonLd({
|
|
4662
|
+
format: "compact",
|
|
4663
|
+
contextLoader
|
|
4664
|
+
}))) return await sign(keys);
|
|
4665
|
+
const logger = getLogger([
|
|
4666
|
+
"fedify",
|
|
4667
|
+
"federation",
|
|
4668
|
+
"outbox"
|
|
4669
|
+
]);
|
|
4670
|
+
const activityId = activity.id?.href;
|
|
4671
|
+
if (hasProof) {
|
|
4672
|
+
logger.debug("The activity {activityId} embeds portable objects and already carries a proof, so no further proof is added; the map-local compound-proof profile accepts exactly one direct proof per map.", { activityId });
|
|
4673
|
+
return {
|
|
4674
|
+
activity,
|
|
4675
|
+
hasProof,
|
|
4676
|
+
proofCreated: false
|
|
4677
|
+
};
|
|
4678
|
+
}
|
|
4679
|
+
if (activity.id == null || !isPortableUrl(activity.id)) throw new TypeError(`Cannot choose an Object Integrity Proof key for the activity ${activityId}: it embeds portable objects, so it falls under the map-local compound-proof profile, which accepts exactly one direct proof per map, but ${keys.length} Ed25519 keys were supplied (${formatKeyIds(keys)}). Send it with explicit sender keys that contain exactly one Ed25519 key (RSA keys for HTTP Signatures may stay), or sign it with signObject() before sending it.`);
|
|
4680
|
+
const activityDid = getFe34Origin(activity.id);
|
|
4681
|
+
const eligible = keys.filter((c) => c.verificationMethod.protocol === "did:" && haveSameFe34Origin(activity.id, c.verificationMethod));
|
|
4682
|
+
if (eligible.length !== 1) throw new TypeError(`Cannot choose an Object Integrity Proof key for the portable activity ${activityId}: ` + (eligible.length < 1 ? `none of its ${keys.length} Ed25519 keys (${formatKeyIds(keys)}) ` : `${eligible.length} of its Ed25519 keys (${formatKeyIds(eligible)}) `) + `${eligible.length < 1 ? "is" : "are"} a DID URL verification method for ${activityDid}. The map-local compound-proof profile accepts exactly one direct proof per map, and FEP-ef61 requires that proof's verification method to be a DID URL for the activity's DID. Supply exactly one Ed25519 key whose key ID is a DID URL for ${activityDid}, or sign the activity with signObject() before sending it.`);
|
|
4683
|
+
logger.debug("The portable activity {activityId} is signed only by {keyId}, the one Ed25519 key whose verification method matches its DID; the map-local compound-proof profile accepts exactly one direct proof per map.", {
|
|
4684
|
+
activityId,
|
|
4685
|
+
keyId: eligible[0].verificationMethod.href
|
|
4686
|
+
});
|
|
4687
|
+
return await sign(eligible);
|
|
4688
|
+
}
|
|
4689
|
+
/**
|
|
4690
|
+
* Rejects an outgoing activity whose proofs Fedify's own inbox would reject
|
|
4691
|
+
* as unsupported: a document with portable objects in which some map carries
|
|
4692
|
+
* a proof set or another value that is not a single proof map.
|
|
4693
|
+
*
|
|
4694
|
+
* @param jsonLd The compact JSON-LD document about to be delivered.
|
|
4695
|
+
* @param activityId The activity ID, for the error message.
|
|
4696
|
+
* @throws {TypeError} If the document has an unsupported proof shape.
|
|
4697
|
+
* @internal
|
|
4698
|
+
*/
|
|
4699
|
+
function assertSupportedCompoundProofShape(jsonLd, activityId) {
|
|
4700
|
+
if (!containsCompoundPortableObject(jsonLd)) return;
|
|
4701
|
+
const path = findUnsupportedCompoundProofShape(jsonLd);
|
|
4702
|
+
if (path == null) return;
|
|
4703
|
+
throw new TypeError(`Cannot send the activity ${activityId}: it embeds portable objects, but its proof at the JSON Pointer ${JSON.stringify(path)} is not a single proof map. The map-local compound-proof profile accepts exactly one direct proof per map, so Fedify inboxes would reject the activity. Sign each object with exactly one key.`);
|
|
4704
|
+
}
|
|
4705
|
+
//#endregion
|
|
4538
4706
|
//#region src/federation/retry.ts
|
|
4539
4707
|
/**
|
|
4540
4708
|
* Creates an exponential backoff retry policy. The delay between retries
|
|
@@ -5660,6 +5828,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
5660
5828
|
collectionSync: message.collectionSync,
|
|
5661
5829
|
orderingKey: message.orderingKey,
|
|
5662
5830
|
normalizeExistingProofs: message.normalizeExistingProofs,
|
|
5831
|
+
activityJsonLd: message.activity,
|
|
5663
5832
|
context
|
|
5664
5833
|
});
|
|
5665
5834
|
}
|
|
@@ -6341,8 +6510,6 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
6341
6510
|
else if (keys.length < 1) throw new TypeError("The keys must not be empty.");
|
|
6342
6511
|
const contextLoader = this.contextLoaderFactory(this.#getLoaderOptions(ctx.origin));
|
|
6343
6512
|
const activityId = activity.id.href;
|
|
6344
|
-
let hasProof = false;
|
|
6345
|
-
let proofCreated = false;
|
|
6346
6513
|
let rsaKey = null;
|
|
6347
6514
|
for (const { keyId, privateKey } of keys) {
|
|
6348
6515
|
validateCryptoKey(privateKey, "private");
|
|
@@ -6351,25 +6518,22 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
6351
6518
|
privateKey
|
|
6352
6519
|
};
|
|
6353
6520
|
}
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
}
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
proofCreated = true;
|
|
6366
|
-
}
|
|
6367
|
-
}
|
|
6368
|
-
let jsonLd = await activity.toJsonLd({
|
|
6521
|
+
const signed = await signOutgoingActivity(activity, keys.map(({ keyId, privateKey }) => ({
|
|
6522
|
+
verificationMethod: keyId,
|
|
6523
|
+
privateKey
|
|
6524
|
+
})), {
|
|
6525
|
+
contextLoader,
|
|
6526
|
+
tracerProvider: this.tracerProvider,
|
|
6527
|
+
appendToExistingProofs: false
|
|
6528
|
+
});
|
|
6529
|
+
activity = signed.activity;
|
|
6530
|
+
const { hasProof, proofCreated } = signed;
|
|
6531
|
+
let jsonLd = !proofCreated && options.activityJsonLd != null ? options.activityJsonLd : await activity.toJsonLd({
|
|
6369
6532
|
format: "compact",
|
|
6370
6533
|
contextLoader
|
|
6371
6534
|
});
|
|
6372
|
-
if (proofCreated || !hasProof || options.normalizeExistingProofs) jsonLd = await normalizeOutgoingActivityJsonLd(jsonLd, contextLoader);
|
|
6535
|
+
if (proofCreated || !hasProof || options.normalizeExistingProofs) jsonLd = await normalizeOutgoingActivityJsonLd(jsonLd, contextLoader, { preserveNestedSecuredDocuments: true });
|
|
6536
|
+
assertSupportedCompoundProofShape(jsonLd, activityId);
|
|
6373
6537
|
if (rsaKey == null) logger.warn("No supported key found to create a Linked Data signature for the activity {activityId}. The activity will be sent without a Linked Data signature. In order to create a Linked Data signature, at least one RSASSA-PKCS1-v1_5 key must be provided.", {
|
|
6374
6538
|
activityId,
|
|
6375
6539
|
keys: keys.map((pair) => ({
|
|
@@ -7341,18 +7505,18 @@ var ContextImpl = class ContextImpl {
|
|
|
7341
7505
|
});
|
|
7342
7506
|
throw new TypeError("The activity to send must have at least one actor property.");
|
|
7343
7507
|
}
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7508
|
+
const { activity: signedActivity, proofCreated } = await signOutgoingActivity(activity, actorKeyPairs == null ? keys.map(({ keyId, privateKey }) => ({
|
|
7509
|
+
verificationMethod: keyId,
|
|
7510
|
+
privateKey
|
|
7511
|
+
})) : actorKeyPairs.flatMap((kp) => kp.multikey.id == null ? [] : [{
|
|
7512
|
+
verificationMethod: kp.multikey.id,
|
|
7513
|
+
privateKey: kp.privateKey
|
|
7514
|
+
}]), {
|
|
7515
|
+
contextLoader: this.contextLoader,
|
|
7516
|
+
tracerProvider: this.tracerProvider,
|
|
7517
|
+
appendToExistingProofs: actorKeyPairs != null
|
|
7518
|
+
});
|
|
7519
|
+
activity = signedActivity;
|
|
7356
7520
|
const inboxes = extractInboxes({
|
|
7357
7521
|
recipients: expandedRecipients,
|
|
7358
7522
|
preferSharedInbox: options.preferSharedInbox,
|
|
@@ -7377,6 +7541,11 @@ var ContextImpl = class ContextImpl {
|
|
|
7377
7541
|
});
|
|
7378
7542
|
return true;
|
|
7379
7543
|
}
|
|
7544
|
+
const activityJsonLd = await activity.toJsonLd({
|
|
7545
|
+
format: "compact",
|
|
7546
|
+
contextLoader: this.contextLoader
|
|
7547
|
+
});
|
|
7548
|
+
assertSupportedCompoundProofShape(activityJsonLd, activity.id?.href);
|
|
7380
7549
|
const keyJwkPairs = await Promise.all(keys.map(async ({ keyId, privateKey }) => ({
|
|
7381
7550
|
keyId: keyId.href,
|
|
7382
7551
|
privateKey: await exportJwk(privateKey)
|
|
@@ -7392,10 +7561,7 @@ var ContextImpl = class ContextImpl {
|
|
|
7392
7561
|
actorIds: [...actorIds],
|
|
7393
7562
|
sharedInbox
|
|
7394
7563
|
}])),
|
|
7395
|
-
activity:
|
|
7396
|
-
format: "compact",
|
|
7397
|
-
contextLoader: this.contextLoader
|
|
7398
|
-
}),
|
|
7564
|
+
activity: activityJsonLd,
|
|
7399
7565
|
activityId: activity.id?.href,
|
|
7400
7566
|
activityType: getTypeId(activity).href,
|
|
7401
7567
|
collectionSync: opts.collectionSync,
|
|
@@ -207,11 +207,7 @@ interface CreateProofOptions {
|
|
|
207
207
|
* @throws {TypeError} If the private key is invalid or unsupported.
|
|
208
208
|
* @since 0.10.0
|
|
209
209
|
*/
|
|
210
|
-
declare function createProof(object: Object$1, privateKey: CryptoKey, keyId: URL,
|
|
211
|
-
contextLoader,
|
|
212
|
-
context,
|
|
213
|
-
created
|
|
214
|
-
}?: CreateProofOptions): Promise<DataIntegrityProof>;
|
|
210
|
+
declare function createProof(object: Object$1, privateKey: CryptoKey, keyId: URL, options?: CreateProofOptions): Promise<DataIntegrityProof>;
|
|
215
211
|
/**
|
|
216
212
|
* Options for {@link signObject}.
|
|
217
213
|
* @since 0.10.0
|
|
@@ -207,11 +207,7 @@ interface CreateProofOptions {
|
|
|
207
207
|
* @throws {TypeError} If the private key is invalid or unsupported.
|
|
208
208
|
* @since 0.10.0
|
|
209
209
|
*/
|
|
210
|
-
declare function createProof(object: Object$1, privateKey: CryptoKey, keyId: URL,
|
|
211
|
-
contextLoader,
|
|
212
|
-
context,
|
|
213
|
-
created
|
|
214
|
-
}?: CreateProofOptions): Promise<DataIntegrityProof>;
|
|
210
|
+
declare function createProof(object: Object$1, privateKey: CryptoKey, keyId: URL, options?: CreateProofOptions): Promise<DataIntegrityProof>;
|
|
215
211
|
/**
|
|
216
212
|
* Options for {@link signObject}.
|
|
217
213
|
* @since 0.10.0
|
package/dist/mod.cjs
CHANGED
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
require("./rolldown-runtime-Dmm3t92W.cjs");
|
|
4
4
|
const require_transformers = require("./transformers-BalCrSsr.cjs");
|
|
5
5
|
require("./compat/mod.cjs");
|
|
6
|
-
const require_http = require("./http-
|
|
7
|
-
const require_federation = require("./federation-
|
|
6
|
+
const require_http = require("./http-B5F1JMh0.cjs");
|
|
7
|
+
const require_federation = require("./federation-CTnaljmy.cjs");
|
|
8
8
|
const require_types = require("./types-Be2zbyeG.cjs");
|
|
9
|
-
const require_owner = require("./owner
|
|
10
|
-
const require_kv_cache = require("./kv-cache-
|
|
9
|
+
const require_owner = require("./owner-WUYke16i.cjs");
|
|
10
|
+
const require_kv_cache = require("./kv-cache-8K70pjtX.cjs");
|
|
11
11
|
require("./nodeinfo/mod.cjs");
|
|
12
12
|
require("./runtime/mod.cjs");
|
|
13
13
|
require("./sig/mod.cjs");
|
package/dist/mod.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthori
|
|
|
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-x9W0d0Pk.cjs";
|
|
9
|
-
import { C as verifyJsonLd, S as signJsonLd, _ as VerifySignatureOptions, a as VerifyPortableObjectProofOptions, b as detachSignature, c as createProof, d as verifyObject, f as verifyPortableObjectProof, g as VerifyJsonLdOptions, h as SignJsonLdOptions, i as VerifyPortableObjectProofFailureReason, l as hasProofLike, m as CreateSignatureOptions, n as SignObjectOptions, o as VerifyPortableObjectProofResult, p as verifyProof, r as VerifyObjectOptions, s as VerifyProofOptions, t as CreateProofOptions, u as signObject, v as attachSignature, w as verifySignature, x as hasSignatureLike, y as createSignature } from "./mod-
|
|
9
|
+
import { C as verifyJsonLd, S as signJsonLd, _ as VerifySignatureOptions, a as VerifyPortableObjectProofOptions, b as detachSignature, c as createProof, d as verifyObject, f as verifyPortableObjectProof, g as VerifyJsonLdOptions, h as SignJsonLdOptions, i as VerifyPortableObjectProofFailureReason, l as hasProofLike, m as CreateSignatureOptions, n as SignObjectOptions, o as VerifyPortableObjectProofResult, p as verifyProof, r as VerifyObjectOptions, s as VerifyProofOptions, t as CreateProofOptions, u as signObject, v as attachSignature, w as verifySignature, x as hasSignatureLike, y as createSignature } from "./mod-CVQFWefn.cjs";
|
|
10
10
|
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-CyiSjRkk.cjs";
|
|
11
11
|
export * from "@fedify/vocab-runtime";
|
|
12
12
|
|
package/dist/mod.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { $ as MessageQueueDepth, A as OutboxListenerSetters, At as ObjectAuthori
|
|
|
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-D882_Xsg.js";
|
|
9
|
-
import { C as verifyJsonLd, S as signJsonLd, _ as VerifySignatureOptions, a as VerifyPortableObjectProofOptions, b as detachSignature, c as createProof, d as verifyObject, f as verifyPortableObjectProof, g as VerifyJsonLdOptions, h as SignJsonLdOptions, i as VerifyPortableObjectProofFailureReason, l as hasProofLike, m as CreateSignatureOptions, n as SignObjectOptions, o as VerifyPortableObjectProofResult, p as verifyProof, r as VerifyObjectOptions, s as VerifyProofOptions, t as CreateProofOptions, u as signObject, v as attachSignature, w as verifySignature, x as hasSignatureLike, y as createSignature } from "./mod-
|
|
9
|
+
import { C as verifyJsonLd, S as signJsonLd, _ as VerifySignatureOptions, a as VerifyPortableObjectProofOptions, b as detachSignature, c as createProof, d as verifyObject, f as verifyPortableObjectProof, g as VerifyJsonLdOptions, h as SignJsonLdOptions, i as VerifyPortableObjectProofFailureReason, l as hasProofLike, m as CreateSignatureOptions, n as SignObjectOptions, o as VerifyPortableObjectProofResult, p as verifyProof, r as VerifyObjectOptions, s as VerifyProofOptions, t as CreateProofOptions, u as signObject, v as attachSignature, w as verifySignature, x as hasSignatureLike, y as createSignature } from "./mod-CNRAxXEb.js";
|
|
10
10
|
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./mod-C0BYc0OU.js";
|
|
11
11
|
export * from "@fedify/vocab-runtime";
|
|
12
12
|
|