@fedify/fedify 2.4.0-dev.2122 → 2.4.0-dev.2129
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-BCXywsZF.mjs → builder-C0bxZDL0.mjs} +3 -3
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-Fxd45Oy5.mjs → compound-proof-D9Kljk_7.mjs} +3 -3
- package/dist/{context-tOiJfBoD.d.ts → context-Cz1w5Krc.d.ts} +31 -5
- package/dist/{context-CoNRxGYp.mjs → context-DfSVPcJ8.mjs} +6 -3
- package/dist/{context-SMNOiiY6.d.cts → context-Dvec_D_h.d.cts} +31 -5
- package/dist/{deno-BZrnW0Qz.mjs → deno-_o3lkDlG.mjs} +1 -1
- package/dist/{docloader-3BHaS20Z.mjs → docloader-BbS0rO-Y.mjs} +7 -7
- 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 +4 -4
- package/dist/federation/handler.test.mjs +6 -6
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +8 -8
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +6 -6
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.d.mts +2 -0
- package/dist/federation/portable-chain.test.mjs +358 -0
- package/dist/federation/portable-gateway-keys.test.mjs +77 -6
- package/dist/federation/portable-inbox.test.mjs +9 -4
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +2 -2
- package/dist/federation/tasks/tasks.test.mjs +3 -3
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{federation-Ml6NrgRV.cjs → federation-DRY8KrkB.cjs} +46 -22
- package/dist/{http-4bmgw-mA.cjs → http-B1J6E-bT.cjs} +384 -33
- package/dist/{http-B9BQDNIy.mjs → http-BpOiZE09.mjs} +18 -12
- package/dist/{http-D76Py0M4.d.cts → http-C-x_OLSp.d.ts} +57 -14
- package/dist/{http-BETASGl0.js → http-C2M6wcs8.js} +374 -35
- package/dist/{http-BrQgkJay.d.ts → http-CjezPjFX.d.cts} +57 -14
- package/dist/{key-PyYvun0F.mjs → key-DolJjJab.mjs} +103 -16
- package/dist/{kv-cache-CPqUxRL3.mjs → kv-cache-Bq2cah0c.mjs} +1 -1
- package/dist/{kv-cache-C4mv2ZFQ.js → kv-cache-D7TiyMxv.js} +6 -6
- package/dist/{kv-cache-D2Bz6t_c.cjs → kv-cache-D9nRbG2Q.cjs} +6 -6
- package/dist/{ld-u4JOD4iO.mjs → ld-Dwc176V4.mjs} +3 -3
- package/dist/{metrics-DCLoLvLz.mjs → metrics-CDaHfBXY.mjs} +1 -1
- package/dist/{middleware-B7bmtONC.mjs → middleware-CmB1FD8A.mjs} +1 -1
- package/dist/{middleware-DWlAGlyP.js → middleware-CylX-pvI.js} +52 -28
- package/dist/{middleware-CgOqRkK-.mjs → middleware-DN3MdTDg.mjs} +64 -39
- package/dist/{mod-CTh7ijx5.d.ts → mod-Bz9tFXI2.d.ts} +14 -3
- package/dist/{mod-Cwdt_CWU.d.ts → mod-CZetqT5h.d.ts} +1 -1
- package/dist/{mod-Cr79cQlc.d.cts → mod-D4g9ffEn.d.cts} +1 -1
- package/dist/{mod-DnElMslb.d.cts → mod-DGOIxEfb.d.cts} +1 -1
- package/dist/{mod-DMdGFMEl.d.cts → mod-S--JxYjo.d.cts} +14 -3
- package/dist/{mod-COWgSo2v.d.ts → mod-owwElvpw.d.ts} +1 -1
- package/dist/mod.cjs +8 -8
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/{owner-CPFM-sqo.mjs → owner-BNHhwjNu.mjs} +37 -4
- package/dist/{sig-C1xOA4ml.js → portable-collection-CRpTUHCY.mjs} +5 -4
- package/dist/portable-collection-CgglAI9B.js +656 -0
- package/dist/{sig-Cb9VSeiF.cjs → portable-collection-PTGD0q70.cjs} +253 -2
- package/dist/portable-key-DqX2emHQ.mjs +395 -0
- package/dist/{portable-key-id-T7lecIbt.mjs → portable-key-id-Bg259c4Z.mjs} +69 -2
- package/dist/{proof-BCOg7Njv.mjs → proof-B4_0E-KU.mjs} +5 -5
- package/dist/{send-C8eOPat3.mjs → send-Dpu5qbP5.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +5 -6
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +2 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +20 -431
- package/dist/sig/portable-key.test.mjs +479 -5
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{temporal-vjHOhBpy.mjs → temporal-78JVR3GK.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +30 -4
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-BWq1dCzx.mjs → testing-otQhu4aD.mjs} +1 -1
- package/dist/utils/docloader.test.mjs +81 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +7 -7
- package/dist/owner-DkA0Lz7v.cjs +0 -225
- package/dist/owner-wNinn7RK.js +0 -215
- package/dist/portable-key-DyylakVV.mjs +0 -214
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { Actor, CryptographicKey, Multikey } from "@fedify/vocab";
|
|
3
|
-
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
4
3
|
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
4
|
+
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
5
5
|
|
|
6
6
|
//#region src/sig/portable-key.d.ts
|
|
7
7
|
/**
|
|
@@ -29,6 +29,28 @@ type PortableGatewayKeyResolution = {
|
|
|
29
29
|
*/
|
|
30
30
|
readonly expires?: Temporal.Instant;
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* The result of resolving a key of a portable actor at an `ap:` or
|
|
34
|
+
* `ap+ef61:` key ID.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
type PortableActorKeyResolution = Exclude<PortableGatewayKeyResolution, {
|
|
38
|
+
readonly type: "legacy";
|
|
39
|
+
}> | {
|
|
40
|
+
/**
|
|
41
|
+
* Whether the actor's document vouches for the key could not be
|
|
42
|
+
* determined, e.g., because no gateway could be reached.
|
|
43
|
+
*/
|
|
44
|
+
readonly type: "unavailable";
|
|
45
|
+
readonly error: unknown;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the failure can be cached as a failure to fetch the key, i.e.,
|
|
48
|
+
* every gateway failed to serve the actor's document at all. A failure
|
|
49
|
+
* that is not cacheable comes with an error that has no HTTP status,
|
|
50
|
+
* since none of the statuses describes the lookup as a whole.
|
|
51
|
+
*/
|
|
52
|
+
readonly cacheable: boolean;
|
|
53
|
+
};
|
|
32
54
|
//#endregion
|
|
33
55
|
//#region src/sig/key.d.ts
|
|
34
56
|
/**
|
|
@@ -119,17 +141,34 @@ interface FetchKeyOptions {
|
|
|
119
141
|
*/
|
|
120
142
|
keyIdBoundByCaller?: boolean;
|
|
121
143
|
/**
|
|
122
|
-
* Resolves
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* which passes it, accepts gateway keys. Object Integrity Proofs and
|
|
127
|
-
* Linked Data Signatures never do.
|
|
144
|
+
* Resolves keys of [FEP-ef61] portable actors, which only HTTP Signature
|
|
145
|
+
* verification passes, so that only it accepts them. Object Integrity
|
|
146
|
+
* Proofs and Linked Data Signatures never do: such a key is rejected if
|
|
147
|
+
* this is omitted.
|
|
128
148
|
*
|
|
129
149
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
130
150
|
* @internal
|
|
131
151
|
*/
|
|
132
|
-
|
|
152
|
+
portableKeyResolvers?: PortableKeyResolvers;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Resolves keys of [FEP-ef61] portable actors for HTTP Signature
|
|
156
|
+
* verification. See {@link FetchKeyOptions.portableKeyResolvers}.
|
|
157
|
+
*
|
|
158
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
159
|
+
* @internal
|
|
160
|
+
*/
|
|
161
|
+
interface PortableKeyResolvers {
|
|
162
|
+
/**
|
|
163
|
+
* Resolves a gateway key, i.e., a key whose ID is a compatible identifier
|
|
164
|
+
* and dereferences to a portable actor's document.
|
|
165
|
+
*/
|
|
166
|
+
gatewayKey(document: unknown, actor: Actor, keyId: URL): Promise<PortableGatewayKeyResolution>;
|
|
167
|
+
/**
|
|
168
|
+
* Resolves a key of a portable actor itself, i.e., a key whose ID is an
|
|
169
|
+
* `ap:` or `ap+ef61:` URI.
|
|
170
|
+
*/
|
|
171
|
+
actorKey(keyId: URL): Promise<PortableActorKeyResolution>;
|
|
133
172
|
}
|
|
134
173
|
/**
|
|
135
174
|
* The result of {@link fetchKey}.
|
|
@@ -182,9 +221,11 @@ type FetchableKeyClass<T extends CryptographicKey | Multikey> = (new (...args: a
|
|
|
182
221
|
* Gateway keys of [FEP-ef61] portable actors, i.e., keys whose IDs are
|
|
183
222
|
* compatible identifiers that dereference to portable actor documents, are
|
|
184
223
|
* not resolved by this function, as they only authenticate HTTP requests;
|
|
185
|
-
* use `verifyRequest()` or `getKeyOwner()` for them instead.
|
|
186
|
-
*
|
|
187
|
-
*
|
|
224
|
+
* use `verifyRequest()` or `getKeyOwner()` for them instead. Nor are keys
|
|
225
|
+
* of portable actors whose IDs are `ap:` or `ap+ef61:` URIs, for the same
|
|
226
|
+
* reason. Keys whose IDs are compatible identifiers or `ap:` or `ap+ef61:`
|
|
227
|
+
* URIs are never read from or written to the key cache under their IDs,
|
|
228
|
+
* except for failures to fetch them.
|
|
188
229
|
*
|
|
189
230
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
190
231
|
* @template T The type of the key to fetch. Either {@link CryptographicKey}
|
|
@@ -204,9 +245,11 @@ declare function fetchKey<T extends CryptographicKey | Multikey>(keyId: URL | st
|
|
|
204
245
|
* Gateway keys of [FEP-ef61] portable actors, i.e., keys whose IDs are
|
|
205
246
|
* compatible identifiers that dereference to portable actor documents, are
|
|
206
247
|
* not resolved by this function, as they only authenticate HTTP requests;
|
|
207
|
-
* use `verifyRequest()` or `getKeyOwner()` for them instead.
|
|
208
|
-
*
|
|
209
|
-
*
|
|
248
|
+
* use `verifyRequest()` or `getKeyOwner()` for them instead. Nor are keys
|
|
249
|
+
* of portable actors whose IDs are `ap:` or `ap+ef61:` URIs, for the same
|
|
250
|
+
* reason. Keys whose IDs are compatible identifiers or `ap:` or `ap+ef61:`
|
|
251
|
+
* URIs are never read from or written to the key cache under their IDs,
|
|
252
|
+
* except for failures to fetch them.
|
|
210
253
|
*
|
|
211
254
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
212
255
|
*
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-
|
|
6
|
-
import {
|
|
4
|
+
import { n as version, t as name } from "./deno-_o3lkDlG.mjs";
|
|
5
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-CDaHfBXY.mjs";
|
|
6
|
+
import { c as isPortableId, f as parseKeyIdString, o as isCompatibleKeyId, s as isPortableActorDocument, u as isPortableUri } from "./portable-key-id-Bg259c4Z.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
9
9
|
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -236,6 +236,17 @@ function bypassKeyCacheReads(keyCache) {
|
|
|
236
236
|
};
|
|
237
237
|
return bypassed;
|
|
238
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Parses a key ID given as a string. Unlike `new URL()`, it accepts `ap:`
|
|
241
|
+
* and `ap+ef61:` URIs, and refuses a portable or compatible key ID whose
|
|
242
|
+
* identity URL parsing would change, e.g., by resolving dot segments.
|
|
243
|
+
* @throws {TypeError} If the key ID is invalid.
|
|
244
|
+
*/
|
|
245
|
+
function parseKeyIdOrThrow(keyId) {
|
|
246
|
+
const parsed = parseKeyIdString(keyId);
|
|
247
|
+
if (parsed == null) throw new TypeError(`Invalid key ID: ${keyId}`);
|
|
248
|
+
return parsed;
|
|
249
|
+
}
|
|
239
250
|
async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
240
251
|
tracerProvider ??= trace.getTracerProvider();
|
|
241
252
|
return await tracerProvider.getTracer(name, version).startActiveSpan("activitypub.fetch_key", {
|
|
@@ -272,9 +283,11 @@ async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
|
272
283
|
* Gateway keys of [FEP-ef61] portable actors, i.e., keys whose IDs are
|
|
273
284
|
* compatible identifiers that dereference to portable actor documents, are
|
|
274
285
|
* not resolved by this function, as they only authenticate HTTP requests;
|
|
275
|
-
* use `verifyRequest()` or `getKeyOwner()` for them instead.
|
|
276
|
-
*
|
|
277
|
-
*
|
|
286
|
+
* use `verifyRequest()` or `getKeyOwner()` for them instead. Nor are keys
|
|
287
|
+
* of portable actors whose IDs are `ap:` or `ap+ef61:` URIs, for the same
|
|
288
|
+
* reason. Keys whose IDs are compatible identifiers or `ap:` or `ap+ef61:`
|
|
289
|
+
* URIs are never read from or written to the key cache under their IDs,
|
|
290
|
+
* except for failures to fetch them.
|
|
278
291
|
*
|
|
279
292
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
280
293
|
* @template T The type of the key to fetch. Either {@link CryptographicKey}
|
|
@@ -287,7 +300,7 @@ async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
|
287
300
|
* @since 1.3.0
|
|
288
301
|
*/
|
|
289
302
|
function fetchKey(keyId, cls, options = {}) {
|
|
290
|
-
keyId = typeof keyId === "string" ?
|
|
303
|
+
keyId = typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId;
|
|
291
304
|
return withFetchKeySpan(keyId, options.tracerProvider, () => fetchKeyInternal(keyId, cls, options));
|
|
292
305
|
}
|
|
293
306
|
/**
|
|
@@ -297,9 +310,11 @@ function fetchKey(keyId, cls, options = {}) {
|
|
|
297
310
|
* Gateway keys of [FEP-ef61] portable actors, i.e., keys whose IDs are
|
|
298
311
|
* compatible identifiers that dereference to portable actor documents, are
|
|
299
312
|
* not resolved by this function, as they only authenticate HTTP requests;
|
|
300
|
-
* use `verifyRequest()` or `getKeyOwner()` for them instead.
|
|
301
|
-
*
|
|
302
|
-
*
|
|
313
|
+
* use `verifyRequest()` or `getKeyOwner()` for them instead. Nor are keys
|
|
314
|
+
* of portable actors whose IDs are `ap:` or `ap+ef61:` URIs, for the same
|
|
315
|
+
* reason. Keys whose IDs are compatible identifiers or `ap:` or `ap+ef61:`
|
|
316
|
+
* URIs are never read from or written to the key cache under their IDs,
|
|
317
|
+
* except for failures to fetch them.
|
|
303
318
|
*
|
|
304
319
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
305
320
|
*
|
|
@@ -313,7 +328,7 @@ function fetchKey(keyId, cls, options = {}) {
|
|
|
313
328
|
* @since 2.1.0
|
|
314
329
|
*/
|
|
315
330
|
async function fetchKeyDetailed(keyId, cls, options = {}) {
|
|
316
|
-
const cacheKey = typeof keyId === "string" ?
|
|
331
|
+
const cacheKey = typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId;
|
|
317
332
|
return await withFetchKeySpan(cacheKey, options.tracerProvider, async () => {
|
|
318
333
|
return await fetchKeyWithResult(cacheKey, cls, options, async (cacheKey, keyId, keyCache, logger) => {
|
|
319
334
|
const fetchError = await keyCache?.getFetchError?.(cacheKey);
|
|
@@ -452,7 +467,7 @@ async function resolveDidKey(cacheKey, cls, keyCache, logger) {
|
|
|
452
467
|
cached: false
|
|
453
468
|
};
|
|
454
469
|
}
|
|
455
|
-
async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider, keyIdBoundByCaller,
|
|
470
|
+
async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider, keyIdBoundByCaller, portableKeyResolvers }, logger) {
|
|
456
471
|
let object;
|
|
457
472
|
try {
|
|
458
473
|
object = await Object$1.fromJsonLd(document, {
|
|
@@ -483,7 +498,7 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
|
|
|
483
498
|
}
|
|
484
499
|
if (isCompatibleKeyId(cacheKey) && isPortableActorDocument(object)) {
|
|
485
500
|
const scopedCache = keyCache;
|
|
486
|
-
if (
|
|
501
|
+
if (portableKeyResolvers == null || cls !== CryptographicKey) {
|
|
487
502
|
logger.debug("Failed to verify; key {keyId} is a gateway key of the portable actor {actorId}, which is only accepted for HTTP Signatures.", {
|
|
488
503
|
keyId,
|
|
489
504
|
actorId: object.id?.href
|
|
@@ -494,7 +509,7 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
|
|
|
494
509
|
cached: false
|
|
495
510
|
};
|
|
496
511
|
}
|
|
497
|
-
const resolution = await
|
|
512
|
+
const resolution = await portableKeyResolvers.gatewayKey(document, object, cacheKey);
|
|
498
513
|
if (resolution.type !== "verified") {
|
|
499
514
|
logger.debug("Failed to verify; the portable actor {actorId} does not vouch for its gateway key {keyId}.", {
|
|
500
515
|
keyId,
|
|
@@ -654,6 +669,11 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
|
|
|
654
669
|
]);
|
|
655
670
|
const keyId = cacheKey.href;
|
|
656
671
|
const keyCache = options.keyCache;
|
|
672
|
+
if (isPortableUri(cacheKey)) {
|
|
673
|
+
const result = await fetchPortableActorKey(cacheKey, cls, options, onCachedUnavailable, onFetchError, logger);
|
|
674
|
+
outcome = result.outcome;
|
|
675
|
+
return result.result;
|
|
676
|
+
}
|
|
657
677
|
if (isCompatibleKeyId(cacheKey)) {
|
|
658
678
|
const result = await fetchCompatibleKey(cacheKey, cls, options, onCachedUnavailable, onFetchError, logger);
|
|
659
679
|
outcome = result.outcome;
|
|
@@ -705,7 +725,7 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
|
|
|
705
725
|
*/
|
|
706
726
|
function getCompatibleKeyScope(cls, options) {
|
|
707
727
|
if (cls !== CryptographicKey) return "multikey";
|
|
708
|
-
return options.
|
|
728
|
+
return options.portableKeyResolvers == null ? "cryptographicKey" : "httpSignature";
|
|
709
729
|
}
|
|
710
730
|
/**
|
|
711
731
|
* Looks up a key at an [FEP-ef61] compatible identifier. Such a key may be
|
|
@@ -759,8 +779,75 @@ async function fetchCompatibleKey(cacheKey, cls, options, onCachedUnavailable, o
|
|
|
759
779
|
outcome: { result: resolved.key != null ? "fetched" : "invalid" }
|
|
760
780
|
};
|
|
761
781
|
}
|
|
782
|
+
/**
|
|
783
|
+
* Looks up a key of an [FEP-ef61] portable actor at an `ap:` or `ap+ef61:`
|
|
784
|
+
* key ID. Such a key is accepted only for HTTP Signatures, and is rejected
|
|
785
|
+
* for any other purpose without being fetched. Like keys at compatible
|
|
786
|
+
* identifiers, what it resolves to is cached in the namespace of the lookup's
|
|
787
|
+
* purpose, and a failure to fetch the actor's document from every gateway is
|
|
788
|
+
* cached in the shared namespace. A failure that is neither, e.g., one
|
|
789
|
+
* gateway being unreachable while another served an invalid document, is not
|
|
790
|
+
* cached at all.
|
|
791
|
+
*
|
|
792
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
793
|
+
*/
|
|
794
|
+
async function fetchPortableActorKey(cacheKey, cls, options, onCachedUnavailable, onFetchError, logger) {
|
|
795
|
+
const keyId = cacheKey.href;
|
|
796
|
+
const resolvers = options.portableKeyResolvers;
|
|
797
|
+
if (resolvers == null || cls !== CryptographicKey) {
|
|
798
|
+
logger.debug("Failed to verify; key {keyId} is a key of a portable actor, which is only accepted for HTTP Signatures.", { keyId });
|
|
799
|
+
return {
|
|
800
|
+
result: {
|
|
801
|
+
key: null,
|
|
802
|
+
cached: false
|
|
803
|
+
},
|
|
804
|
+
outcome: { result: "invalid" }
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
const sharedCache = options.keyCache;
|
|
808
|
+
const scopedCache = sharedCache?.compatibleKeyScope?.("httpSignature");
|
|
809
|
+
const cached = await getCachedFetchKey(cacheKey, keyId, cls, scopedCache, logger);
|
|
810
|
+
if (cached != null) return {
|
|
811
|
+
result: cached,
|
|
812
|
+
outcome: { result: "hit" }
|
|
813
|
+
};
|
|
814
|
+
if (await sharedCache?.get(cacheKey) === null) {
|
|
815
|
+
logger.debug("Entry {keyId} found in cache, but it could not be fetched.", { keyId });
|
|
816
|
+
return {
|
|
817
|
+
result: await onCachedUnavailable(cacheKey, keyId, sharedCache, logger),
|
|
818
|
+
outcome: { result: "hit" }
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
logger.debug("Resolving key {keyId} to verify signature...", { keyId });
|
|
822
|
+
const resolution = await resolvers.actorKey(cacheKey);
|
|
823
|
+
if (resolution.type === "verified") {
|
|
824
|
+
await scopedCache?.set(cacheKey, resolution.key, { expires: resolution.expires });
|
|
825
|
+
return {
|
|
826
|
+
result: {
|
|
827
|
+
key: resolution.key,
|
|
828
|
+
cached: false
|
|
829
|
+
},
|
|
830
|
+
outcome: { result: "fetched" }
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
if (resolution.type === "rejected") {
|
|
834
|
+
await scopedCache?.set(cacheKey, null);
|
|
835
|
+
return {
|
|
836
|
+
result: {
|
|
837
|
+
key: null,
|
|
838
|
+
cached: false
|
|
839
|
+
},
|
|
840
|
+
outcome: { result: "invalid" }
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
await scopedCache?.delete(cacheKey);
|
|
844
|
+
return {
|
|
845
|
+
result: await onFetchError(resolution.error, cacheKey, keyId, resolution.cacheable ? sharedCache : void 0, logger),
|
|
846
|
+
outcome: resolution.cacheable ? classifyFetchError(resolution.error) : { result: "error" }
|
|
847
|
+
};
|
|
848
|
+
}
|
|
762
849
|
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
763
|
-
return await fetchKeyWithResult(typeof keyId === "string" ?
|
|
850
|
+
return await fetchKeyWithResult(typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
764
851
|
return {
|
|
765
852
|
key: null,
|
|
766
853
|
cached: true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { p as recordDocumentCache } from "./metrics-
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-CDaHfBXY.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import {
|
|
3
|
+
import { U as validateCryptoKey, t as doubleKnock, tt as recordDocumentCache } from "./http-C2M6wcs8.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
@@ -24,21 +24,21 @@ const logger$1 = getLogger([
|
|
|
24
24
|
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
25
25
|
validateCryptoKey(identity.privateKey);
|
|
26
26
|
async function load(url, options) {
|
|
27
|
-
await validateUrl(url);
|
|
27
|
+
await validateUrl(url, options);
|
|
28
28
|
return getRemoteDocument(url, await doubleKnock(createActivityPubRequest(url, { userAgent }), identity, {
|
|
29
29
|
maxRedirection,
|
|
30
30
|
specDeterminer,
|
|
31
31
|
log: curry(logRequest)(logger$1),
|
|
32
32
|
tracerProvider,
|
|
33
33
|
signal: options?.signal,
|
|
34
|
-
validateRedirect: validateUrl
|
|
35
|
-
}), load);
|
|
34
|
+
validateRedirect: (url) => validateUrl(url, options)
|
|
35
|
+
}), load, options);
|
|
36
36
|
}
|
|
37
|
-
async function validateUrl(url) {
|
|
37
|
+
async function validateUrl(url, options) {
|
|
38
38
|
if (!allowPrivateAddress) try {
|
|
39
39
|
await validatePublicUrl(url);
|
|
40
40
|
} catch (error) {
|
|
41
|
-
if (error instanceof UrlError) logger$1
|
|
41
|
+
if (error instanceof UrlError) logger$1[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
42
42
|
url,
|
|
43
43
|
error
|
|
44
44
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
2
|
+
const require_http = require("./http-B1J6E-bT.cjs");
|
|
3
3
|
let _logtape_logtape = require("@logtape/logtape");
|
|
4
4
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
5
5
|
let es_toolkit = require("es-toolkit");
|
|
@@ -23,21 +23,21 @@ const logger$1 = (0, _logtape_logtape.getLogger)([
|
|
|
23
23
|
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
24
24
|
require_http.validateCryptoKey(identity.privateKey);
|
|
25
25
|
async function load(url, options) {
|
|
26
|
-
await validateUrl(url);
|
|
26
|
+
await validateUrl(url, options);
|
|
27
27
|
return (0, _fedify_vocab_runtime.getRemoteDocument)(url, await require_http.doubleKnock((0, _fedify_vocab_runtime.createActivityPubRequest)(url, { userAgent }), identity, {
|
|
28
28
|
maxRedirection,
|
|
29
29
|
specDeterminer,
|
|
30
30
|
log: (0, es_toolkit.curry)(_fedify_vocab_runtime.logRequest)(logger$1),
|
|
31
31
|
tracerProvider,
|
|
32
32
|
signal: options?.signal,
|
|
33
|
-
validateRedirect: validateUrl
|
|
34
|
-
}), load);
|
|
33
|
+
validateRedirect: (url) => validateUrl(url, options)
|
|
34
|
+
}), load, options);
|
|
35
35
|
}
|
|
36
|
-
async function validateUrl(url) {
|
|
36
|
+
async function validateUrl(url, options) {
|
|
37
37
|
if (!allowPrivateAddress) try {
|
|
38
38
|
await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
|
|
39
39
|
} catch (error) {
|
|
40
|
-
if (error instanceof _fedify_vocab_runtime.UrlError) logger$1
|
|
40
|
+
if (error instanceof _fedify_vocab_runtime.UrlError) logger$1[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
41
41
|
url,
|
|
42
42
|
error
|
|
43
43
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
5
|
-
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-
|
|
6
|
-
import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-
|
|
4
|
+
import { n as version, t as name } from "./deno-_o3lkDlG.mjs";
|
|
5
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-CDaHfBXY.mjs";
|
|
6
|
+
import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-DolJjJab.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
9
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-_o3lkDlG.mjs";
|
|
5
5
|
import { metrics } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/federation/metrics.ts
|
|
@@ -2,10 +2,10 @@ import { Temporal } from "temporal-polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { t as __exportAll } from "./rolldown-runtime-BC-Eo5Mj.js";
|
|
4
4
|
import { r as getDefaultActivityTransformers } from "./transformers-DAtXl_Kc.js";
|
|
5
|
-
import { $ as
|
|
5
|
+
import { $ as recordCollectionRequest, A as isClearlyMalformedContextReference, Ct as version, D as getNormalizationContextLoader, E as detachSignature, G as getDurationMs, H as importJwk, I as wrapContextLoaderForJsonLd, J as instrumentDocumentLoader, K as getFederationMetrics, L as exportJwk, M as signJsonLd, N as verifyCompactJsonLd, O as hasSignature, Q as recordCollectionPageItems, S as assertSafeJsonLd, St as name, U as validateCryptoKey, X as recordCircuitBreakerStateChange, Y as isAbortError, Z as recordCollectionDispatchDuration, _ as verifyPortableObjectProofPolicy, _t as isCompatibleKeyId, at as recordOutboxEnqueue, b as normalizeOutgoingActivityJsonLd, bt as isPortableUri, ct as preloadedOnlyDocumentLoader, et as recordCollectionTotalItems, f as hasProofLike, g as verifyPortableObjectProof, gt as hasPortableActor, h as verifyObject, ht as getPortableDid, i as selectRequestSignature, it as recordOutboxActivity, j as isInvalidUrlTypeError, k as hasSignatureLike, lt as formatAcceptSignature, m as verifyMapLocalProof, mt as getGatewayKeyBase, n as listRequestSignatures, nt as recordFanoutRecipients, o as verifyRequest, ot as recordWebFingerHandle, p as signObject, pt as getCanonicalPortableId, q as getRemoteHost, r as parseRfc9421SignatureInput, rt as recordInboxActivity, s as verifyRequestDetailed, st as registerQueueDepthGauge, t as doubleKnock, u as InvalidPortableObjectIdError, v as verifyPortableObjectProofWithRoot, vt as isPortableId, w as compactJsonLd, x as InvalidContextReferenceError, yt as isPortableKeyId } from "./http-C2M6wcs8.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 { n as getKeyOwner, t as
|
|
8
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-
|
|
7
|
+
import { n as doesActorOwnKey, r as getKeyOwner, t as verifyPortableObject } from "./portable-collection-CgglAI9B.js";
|
|
8
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "./kv-cache-D7TiyMxv.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";
|
|
@@ -3668,13 +3668,13 @@ function recordCollectionMetrics(meterProvider, base, result, options = {}) {
|
|
|
3668
3668
|
* @param parameters The parameters for handling the collection.
|
|
3669
3669
|
* @returns A promise that resolves to an HTTP response.
|
|
3670
3670
|
*/
|
|
3671
|
-
async function handleCollection(request, { name: name$
|
|
3672
|
-
const spanName = name$
|
|
3671
|
+
async function handleCollection(request, { name: name$2, identifier, uriGetter, filter, filterPredicate, context, collectionCallbacks, tracerProvider, meterProvider, onUnauthorized, onNotFound }) {
|
|
3672
|
+
const spanName = name$2.trim().replace(/\s+/g, "_");
|
|
3673
3673
|
tracerProvider = tracerProvider ?? trace.getTracerProvider();
|
|
3674
3674
|
const tracer = tracerProvider.getTracer(name, version);
|
|
3675
3675
|
const cursor = new URL(request.url).searchParams.get("cursor");
|
|
3676
3676
|
const metricBase = {
|
|
3677
|
-
kind: getCollectionMetricKind(name$
|
|
3677
|
+
kind: getCollectionMetricKind(name$2),
|
|
3678
3678
|
page: cursor != null,
|
|
3679
3679
|
dispatcher: "built_in"
|
|
3680
3680
|
};
|
|
@@ -3715,7 +3715,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
3715
3715
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
3716
3716
|
return await onNotFound(request);
|
|
3717
3717
|
}
|
|
3718
|
-
const items = filterCollectionItems(page.items, name$
|
|
3718
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
3719
3719
|
itemCount = items.length;
|
|
3720
3720
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
3721
3721
|
return items;
|
|
@@ -3755,7 +3755,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
3755
3755
|
} else {
|
|
3756
3756
|
const uri = new URL(baseUri);
|
|
3757
3757
|
uri.searchParams.set("cursor", cursor);
|
|
3758
|
-
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$
|
|
3758
|
+
const pageOrResponse = await tracer.startActiveSpan(`activitypub.dispatch_collection_page ${name$2}`, {
|
|
3759
3759
|
kind: SpanKind.SERVER,
|
|
3760
3760
|
attributes: {
|
|
3761
3761
|
"activitypub.collection.id": uri.href,
|
|
@@ -3771,7 +3771,7 @@ async function handleCollection(request, { name: name$1, identifier, uriGetter,
|
|
|
3771
3771
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
3772
3772
|
return await onNotFound(request);
|
|
3773
3773
|
}
|
|
3774
|
-
const items = filterCollectionItems(page.items, name$
|
|
3774
|
+
const items = filterCollectionItems(page.items, name$2, filterPredicate);
|
|
3775
3775
|
itemCount = items.length;
|
|
3776
3776
|
span.setAttribute("fedify.collection.items", itemCount);
|
|
3777
3777
|
return {
|
|
@@ -4506,7 +4506,8 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
4506
4506
|
documentLoader: ctx.documentLoader,
|
|
4507
4507
|
keyCache,
|
|
4508
4508
|
meterProvider,
|
|
4509
|
-
tracerProvider
|
|
4509
|
+
tracerProvider,
|
|
4510
|
+
verifyPortableObject: ctx.verifyPortableObject
|
|
4510
4511
|
});
|
|
4511
4512
|
} catch (error) {
|
|
4512
4513
|
if (error instanceof RangeError && await hasMalformedKnownTemporalLiteral(jsonWithoutSig, ctx.contextLoader)) return await respondInvalidActivity(error);
|
|
@@ -4664,7 +4665,7 @@ async function handleInboxInternal(request, parameters, span) {
|
|
|
4664
4665
|
"http_signatures.verified": httpSigKey != null,
|
|
4665
4666
|
"http_signatures.key_id": httpSigKey?.id?.href ?? ""
|
|
4666
4667
|
});
|
|
4667
|
-
if (!skipSignatureVerification && !proofVerified && (isPortableActivity(activity) ||
|
|
4668
|
+
if (!skipSignatureVerification && !proofVerified && (isPortableActivity(activity) || isPortableActorKey(httpSigKey))) {
|
|
4668
4669
|
if (deferredLdSignatureError != null) throw deferredLdSignatureError;
|
|
4669
4670
|
logger.error("The activity {activityId} of the portable actor {actorId} is not authenticated by a valid Object Integrity Proof.", {
|
|
4670
4671
|
activity: json,
|
|
@@ -4959,8 +4960,8 @@ var CustomCollectionHandler = class {
|
|
|
4959
4960
|
* @param CollectionPage The CollectionPage constructor.
|
|
4960
4961
|
* @param filterPredicate Optional filter predicate for items.
|
|
4961
4962
|
*/
|
|
4962
|
-
constructor(name$
|
|
4963
|
-
this.name = name$
|
|
4963
|
+
constructor(name$1, values, context, callbacks, tracerProvider = trace.getTracerProvider(), meterProvider, Collection, CollectionPage, filterPredicate) {
|
|
4964
|
+
this.name = name$1;
|
|
4964
4965
|
this.values = values;
|
|
4965
4966
|
this.context = context;
|
|
4966
4967
|
this.callbacks = callbacks;
|
|
@@ -5445,13 +5446,13 @@ const MIN_COMPONENTS = [
|
|
|
5445
5446
|
"@authority"
|
|
5446
5447
|
];
|
|
5447
5448
|
/**
|
|
5448
|
-
* Checks whether an HTTP Signature key is a
|
|
5449
|
-
*
|
|
5450
|
-
* a portable actor, which only the portable actor's
|
|
5451
|
-
* establish.
|
|
5449
|
+
* Checks whether an HTTP Signature key is a key of an FEP-ef61 portable
|
|
5450
|
+
* actor, i.e., its ID is a compatible identifier or an `ap:` or `ap+ef61:`
|
|
5451
|
+
* URI, and it is owned by a portable actor, which only the portable actor's
|
|
5452
|
+
* signed document can establish.
|
|
5452
5453
|
*/
|
|
5453
|
-
function
|
|
5454
|
-
return key?.id != null &&
|
|
5454
|
+
function isPortableActorKey(key) {
|
|
5455
|
+
return key?.id != null && isPortableKeyId(key.id) && key.ownerId != null && isPortableId(key.ownerId);
|
|
5455
5456
|
}
|
|
5456
5457
|
/**
|
|
5457
5458
|
* Checks whether an activity needs an Object Integrity Proof by its DID:
|
|
@@ -5800,7 +5801,7 @@ async function signOutgoingActivity(activity, candidates, options) {
|
|
|
5800
5801
|
hasProof = true;
|
|
5801
5802
|
break;
|
|
5802
5803
|
}
|
|
5803
|
-
const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519" && !
|
|
5804
|
+
const keys = candidates.filter((c) => c.privateKey.algorithm.name === "Ed25519" && !isPortableKeyId(c.verificationMethod));
|
|
5804
5805
|
if (!hasProof && activity.id != null && isPortableId(activity.id)) return await sign(selectPortableActivityKey(activity, activity.id, keys));
|
|
5805
5806
|
if (keys.length < 1 || hasProof && !options.appendToExistingProofs) return {
|
|
5806
5807
|
activity,
|
|
@@ -7114,11 +7115,16 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
7114
7115
|
});
|
|
7115
7116
|
return parsedActorIds;
|
|
7116
7117
|
};
|
|
7117
|
-
const parseActivity = () =>
|
|
7118
|
-
contextLoader
|
|
7119
|
-
documentLoader
|
|
7120
|
-
|
|
7121
|
-
|
|
7118
|
+
const parseActivity = () => {
|
|
7119
|
+
const contextLoader = this.contextLoaderFactory(loaderOptions);
|
|
7120
|
+
const documentLoader = rsaKeyPair == null ? this.documentLoaderFactory(loaderOptions) : this.authenticatedDocumentLoaderFactory(rsaKeyPair, loaderOptions);
|
|
7121
|
+
return Activity.fromJsonLd(message.activity, {
|
|
7122
|
+
contextLoader,
|
|
7123
|
+
documentLoader,
|
|
7124
|
+
tracerProvider: this.tracerProvider,
|
|
7125
|
+
verifyPortableObject: createPortableObjectVerifier(documentLoader, contextLoader, this)
|
|
7126
|
+
});
|
|
7127
|
+
};
|
|
7122
7128
|
const enqueueHeldOutboxMessage = async (delay, heldSince) => {
|
|
7123
7129
|
const { outboxQueue } = this;
|
|
7124
7130
|
if (outboxQueue == null) return;
|
|
@@ -7760,7 +7766,7 @@ var FederationImpl = class extends FederationBuilderImpl {
|
|
|
7760
7766
|
const ldSignable = !hasPortableActor(activity);
|
|
7761
7767
|
for (const { keyId, privateKey } of keys) {
|
|
7762
7768
|
validateCryptoKey(privateKey, "private");
|
|
7763
|
-
if (ldSignable && rsaKey == null && privateKey.algorithm.name === "RSASSA-PKCS1-v1_5" && !
|
|
7769
|
+
if (ldSignable && rsaKey == null && privateKey.algorithm.name === "RSASSA-PKCS1-v1_5" && !isPortableKeyId(keyId)) rsaKey = {
|
|
7764
7770
|
keyId,
|
|
7765
7771
|
privateKey
|
|
7766
7772
|
};
|
|
@@ -8594,12 +8600,28 @@ function getCollectionMetricRoute(routeName) {
|
|
|
8594
8600
|
}
|
|
8595
8601
|
}
|
|
8596
8602
|
const FANOUT_THRESHOLD = 5;
|
|
8603
|
+
/**
|
|
8604
|
+
* Creates the FEP-ef61 portable object verifier that a context applies to
|
|
8605
|
+
* portable objects it dereferences: `verifyPortableObject()` with the given
|
|
8606
|
+
* loaders and the federation's tracer provider as defaults. Other options,
|
|
8607
|
+
* such as the document URL, gateways, and referrer, are passed through as
|
|
8608
|
+
* they are.
|
|
8609
|
+
*/
|
|
8610
|
+
function createPortableObjectVerifier(documentLoader, contextLoader, federation) {
|
|
8611
|
+
return (document, options = {}) => verifyPortableObject(document, {
|
|
8612
|
+
...options,
|
|
8613
|
+
documentLoader: options.documentLoader ?? documentLoader,
|
|
8614
|
+
contextLoader: options.contextLoader ?? contextLoader,
|
|
8615
|
+
tracerProvider: options.tracerProvider ?? federation.tracerProvider
|
|
8616
|
+
});
|
|
8617
|
+
}
|
|
8597
8618
|
var ContextImpl = class ContextImpl {
|
|
8598
8619
|
url;
|
|
8599
8620
|
federation;
|
|
8600
8621
|
data;
|
|
8601
8622
|
documentLoader;
|
|
8602
8623
|
contextLoader;
|
|
8624
|
+
verifyPortableObject;
|
|
8603
8625
|
invokedFromActorKeyPairsDispatcher;
|
|
8604
8626
|
#codec;
|
|
8605
8627
|
constructor({ url, federation, data, documentLoader, contextLoader, invokedFromActorKeyPairsDispatcher }) {
|
|
@@ -8608,6 +8630,7 @@ var ContextImpl = class ContextImpl {
|
|
|
8608
8630
|
this.data = data;
|
|
8609
8631
|
this.documentLoader = documentLoader;
|
|
8610
8632
|
this.contextLoader = contextLoader;
|
|
8633
|
+
this.verifyPortableObject = createPortableObjectVerifier(documentLoader, contextLoader, federation);
|
|
8611
8634
|
this.invokedFromActorKeyPairsDispatcher = invokedFromActorKeyPairsDispatcher;
|
|
8612
8635
|
}
|
|
8613
8636
|
/**
|
|
@@ -8959,7 +8982,7 @@ var ContextImpl = class ContextImpl {
|
|
|
8959
8982
|
userAgent: options.userAgent ?? this.federation.userAgent,
|
|
8960
8983
|
tracerProvider: options.tracerProvider ?? this.tracerProvider,
|
|
8961
8984
|
meterProvider: options.meterProvider ?? this.meterProvider,
|
|
8962
|
-
verifyPortableObject: options.verifyPortableObject ??
|
|
8985
|
+
verifyPortableObject: options.verifyPortableObject ?? this.verifyPortableObject,
|
|
8963
8986
|
allowPrivateAddress: this.federation.allowPrivateAddress
|
|
8964
8987
|
});
|
|
8965
8988
|
}
|
|
@@ -8967,7 +8990,8 @@ var ContextImpl = class ContextImpl {
|
|
|
8967
8990
|
return traverseCollection(collection, {
|
|
8968
8991
|
...options,
|
|
8969
8992
|
documentLoader: options.documentLoader ?? this.documentLoader,
|
|
8970
|
-
contextLoader: options.contextLoader ?? this.contextLoader
|
|
8993
|
+
contextLoader: options.contextLoader ?? this.contextLoader,
|
|
8994
|
+
verifyPortableObject: options.verifyPortableObject ?? this.verifyPortableObject
|
|
8971
8995
|
});
|
|
8972
8996
|
}
|
|
8973
8997
|
lookupNodeInfo(url, options = {}) {
|