@fedify/fedify 2.4.0-dev.2071 → 2.4.0-dev.2077
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-DVQ0yhKJ.mjs → builder-i3jxVe9m.mjs} +2 -2
- 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-KmXDfWFp.mjs → compound-proof-Cayy-ECj.mjs} +1 -1
- package/dist/{context-DsB9kF6q.d.ts → context-BSywYspi.d.ts} +109 -1
- package/dist/{context-DijrgHDe.d.cts → context-CZjZYXFC.d.cts} +109 -1
- package/dist/{context-DG5QeQ8W.mjs → context-DlZhxdFT.mjs} +2 -1
- package/dist/{deno-B-NtYZVW.mjs → deno-Djkzd-G_.mjs} +1 -1
- package/dist/{docloader-C6yOVoaF.mjs → docloader-dA0RswUV.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 +138 -11
- 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 +3 -3
- package/dist/federation/mod.d.ts +3 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- package/dist/federation/portable-gateway-keys.test.mjs +4 -4
- package/dist/federation/portable-inbox.test.d.mts +2 -0
- package/dist/federation/portable-inbox.test.mjs +546 -0
- 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-CUiHc7dP.cjs → federation-CFd0Jhhv.cjs} +463 -82
- package/dist/{http-DKWi8RjI.mjs → http-CCJ97Jql.mjs} +4 -4
- package/dist/{http-CuLWIJdf.cjs → http-Dvy_IwRa.cjs} +1 -1
- package/dist/{http-BoWBwC0g.js → http-aqh3yFdM.js} +1 -1
- package/dist/{key-lfcx_NaE.mjs → key-IxTTC8Yf.mjs} +2 -2
- package/dist/{kv-cache-DE8kSNQU.cjs → kv-cache-BP69NV0P.cjs} +1 -1
- package/dist/{kv-cache-d8EjO29d.mjs → kv-cache-Bwwbh-xR.mjs} +1 -1
- package/dist/{kv-cache-BdnmnAVc.js → kv-cache-Y6SDRSX6.js} +1 -1
- package/dist/{ld-jyjdrWjG.mjs → ld-l0B9nREb.mjs} +3 -3
- package/dist/{metrics-B5Rei-HC.mjs → metrics-D1p6hv4z.mjs} +1 -1
- package/dist/{middleware-CdVnCDXD.mjs → middleware-BDjCUHMS.mjs} +1 -1
- package/dist/{middleware-CPx4ZWwt.mjs → middleware-BMgzqBtr.mjs} +418 -42
- package/dist/{middleware-CAObohey.js → middleware-SSfryVzY.js} +412 -32
- package/dist/{mod-DMkflQdF.d.ts → mod-B2h2KY0q.d.ts} +1 -1
- package/dist/{mod-DTAaBwiY.d.cts → mod-JzkaEXsi.d.cts} +1 -1
- package/dist/mod.cjs +5 -5
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/{owner-BXufwAzm.cjs → owner-BpOxL5PG.cjs} +1 -1
- package/dist/{owner-ByqNQVaa.mjs → owner-DGbYmXqU.mjs} +3 -3
- package/dist/{owner-1TFakcTF.js → owner-jH1z_YfD.js} +1 -1
- package/dist/{portable-key-Cw_ow5vn.mjs → portable-key-CCwJGSsU.mjs} +2 -2
- package/dist/{proof-B6gwdhN5.mjs → proof-CVL7JnZd.mjs} +4 -4
- package/dist/{send-DsK7xevO.mjs → send-Ejy1jOz9.mjs} +8 -4
- 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 +3 -3
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +2 -2
- package/dist/sig/portable-key.test.mjs +3 -3
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{sig-BR_Z6mpY.js → sig-Dpy1B1Ad.js} +2 -2
- package/dist/{sig-TTn9wYrE.cjs → sig-xoqy3ATq.cjs} +2 -2
- package/dist/{temporal-Bw5jtrBY.mjs → temporal-DNJ1cNpr.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +108 -0
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-By1YYsIK.mjs → testing-CO_cEvQc.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,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-Djkzd-G_.mjs";
|
|
5
5
|
import { t as ActivityListenerSet } from "./activity-listener-C-BSbKI7.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { Router, RouterError, assertPath } from "@fedify/uri-template";
|
|
@@ -86,7 +86,7 @@ var FederationBuilderImpl = class {
|
|
|
86
86
|
* specified.
|
|
87
87
|
*/
|
|
88
88
|
async build(options) {
|
|
89
|
-
const { FederationImpl } = await import("./middleware-
|
|
89
|
+
const { FederationImpl } = await import("./middleware-BDjCUHMS.mjs");
|
|
90
90
|
const f = new FederationImpl(options);
|
|
91
91
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
92
92
|
f.router = this.router.clone();
|
package/dist/compat/mod.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import {
|
|
2
|
+
import { Xt as ActivityTransformer, n as Context } from "../context-CZjZYXFC.cjs";
|
|
3
3
|
import { Activity } from "@fedify/vocab";
|
|
4
4
|
|
|
5
5
|
//#region src/compat/transformers.d.ts
|
package/dist/compat/mod.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import {
|
|
2
|
+
import { Xt as ActivityTransformer, n as Context } from "../context-BSywYspi.js";
|
|
3
3
|
import { Activity } from "@fedify/vocab";
|
|
4
4
|
|
|
5
5
|
//#region src/compat/transformers.d.ts
|
|
@@ -5,7 +5,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
|
|
7
7
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
8
|
-
import {
|
|
8
|
+
import { C as actorDehydrator, n as FederationImpl, w as autoIdAssigner } from "../middleware-BMgzqBtr.mjs";
|
|
9
9
|
import { Follow, Person } from "@fedify/vocab";
|
|
10
10
|
import { test } from "@fedify/fixture";
|
|
11
11
|
//#region src/compat/transformers.test.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { i as verifyMapLocalProof, s as verifyPortableObjectProofPolicy } from "./proof-
|
|
4
|
+
import { i as verifyMapLocalProof, s as verifyPortableObjectProofPolicy } from "./proof-CVL7JnZd.mjs";
|
|
5
5
|
//#region src/sig/compound-proof.ts
|
|
6
6
|
const textEncoder = new TextEncoder();
|
|
7
7
|
const PORTABLE_OBJECT_ID_PATTERN = /^ap(?:\+ef61)?:\/\//i;
|
|
@@ -1424,6 +1424,16 @@ interface FederationKvPrefixes {
|
|
|
1424
1424
|
* @since 2.4.0
|
|
1425
1425
|
*/
|
|
1426
1426
|
readonly taskDeduplication: KvKey;
|
|
1427
|
+
/**
|
|
1428
|
+
* The key prefix used for remembering which activities received in
|
|
1429
|
+
* [FEP-ef61] portable inboxes have been forwarded to which gateways, so that
|
|
1430
|
+
* each activity is forwarded at most once.
|
|
1431
|
+
*
|
|
1432
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
1433
|
+
* @default `["_fedify", "portableInboxForwarding"]`
|
|
1434
|
+
* @since 2.4.0
|
|
1435
|
+
*/
|
|
1436
|
+
readonly portableInboxForwarding: KvKey;
|
|
1427
1437
|
}
|
|
1428
1438
|
/**
|
|
1429
1439
|
* Options for {@link FederationOptions.origin} when it is not a string.
|
|
@@ -2030,6 +2040,44 @@ interface FederationBuilder<TContextData> extends Federatable<TContextData> {
|
|
|
2030
2040
|
build(options: FederationOptions<TContextData>): Promise<Federation<TContextData>>;
|
|
2031
2041
|
}
|
|
2032
2042
|
/**
|
|
2043
|
+
* Options for forwarding activities received in [FEP-ef61] portable inboxes to
|
|
2044
|
+
* the other gateways of their actors. See
|
|
2045
|
+
* {@link FederationOptions.portableInboxForwarding}.
|
|
2046
|
+
*
|
|
2047
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2048
|
+
* @since 2.4.0
|
|
2049
|
+
*/
|
|
2050
|
+
interface PortableInboxForwardingOptions {
|
|
2051
|
+
/**
|
|
2052
|
+
* The maximum number of other gateways that a single delivery is forwarded
|
|
2053
|
+
* to. Gateways beyond it are skipped with a warning. `0` turns off
|
|
2054
|
+
* forwarding.
|
|
2055
|
+
* @default `10`
|
|
2056
|
+
*/
|
|
2057
|
+
maxTargets?: number;
|
|
2058
|
+
/**
|
|
2059
|
+
* How long Fedify remembers that it has forwarded an activity from
|
|
2060
|
+
* a portable inbox to a gateway, under
|
|
2061
|
+
* {@link FederationKvPrefixes.portableInboxForwarding}. Within it, the same
|
|
2062
|
+
* activity is never forwarded to the same gateway again; once it expires,
|
|
2063
|
+
* a redelivery of the activity may be forwarded again. It cannot have
|
|
2064
|
+
* calendar units, i.e., weeks, months, or years.
|
|
2065
|
+
* @default `{ days: 30 }`
|
|
2066
|
+
*/
|
|
2067
|
+
ttl?: Temporal.DurationLike;
|
|
2068
|
+
/**
|
|
2069
|
+
* How long a delivery waits for forwarding requests made immediately, i.e.,
|
|
2070
|
+
* when no outbox queue is configured, before Fedify responds to it.
|
|
2071
|
+
* Requests still running afterwards continue in the background. It does
|
|
2072
|
+
* not apply when forwarding is queued. It cannot have calendar units,
|
|
2073
|
+
* i.e., weeks, months, or years, and cannot be longer than
|
|
2074
|
+
* 2,147,483,647 milliseconds (about 24.8 days), the longest delay timers
|
|
2075
|
+
* support.
|
|
2076
|
+
* @default `{ seconds: 10 }`
|
|
2077
|
+
*/
|
|
2078
|
+
deadline?: Temporal.DurationLike;
|
|
2079
|
+
}
|
|
2080
|
+
/**
|
|
2033
2081
|
* Policy for emitting `Accept-Signature` challenges on inbox `401`
|
|
2034
2082
|
* responses, as defined in
|
|
2035
2083
|
* [RFC 9421 §5](https://www.rfc-editor.org/rfc/rfc9421#section-5).
|
|
@@ -2124,6 +2172,14 @@ interface FederationOptions<TContextData> {
|
|
|
2124
2172
|
*/
|
|
2125
2173
|
httpMessageSignaturesSpecTtl?: Temporal.DurationLike;
|
|
2126
2174
|
/**
|
|
2175
|
+
* Options for forwarding activities received in [FEP-ef61] portable inboxes
|
|
2176
|
+
* to the other gateways of their actors.
|
|
2177
|
+
*
|
|
2178
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2179
|
+
* @since 2.4.0
|
|
2180
|
+
*/
|
|
2181
|
+
portableInboxForwarding?: PortableInboxForwardingOptions;
|
|
2182
|
+
/**
|
|
2127
2183
|
* The message queue for sending and receiving activities. If not provided,
|
|
2128
2184
|
* activities will not be queued and will be processed immediately.
|
|
2129
2185
|
*
|
|
@@ -2907,6 +2963,35 @@ interface Context<TContextData> {
|
|
|
2907
2963
|
*/
|
|
2908
2964
|
getPortableObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>, authority: string): URL;
|
|
2909
2965
|
/**
|
|
2966
|
+
* Builds the [FEP-ef61] portable ID of an actor's inbox with the given
|
|
2967
|
+
* identifier under the given DID authority.
|
|
2968
|
+
*
|
|
2969
|
+
* The path is the same as the one {@link Context.getInboxUri} builds from
|
|
2970
|
+
* the inbox path, but the result is an `ap+ef61:` URI whose authority is
|
|
2971
|
+
* the DID, e.g., `ap+ef61://did:key:z6Mk.../users/alice/inbox`. If
|
|
2972
|
+
* a portable actor has it as its `inbox` and lists this server in its
|
|
2973
|
+
* `gateways`, this server accepts deliveries to the inbox through
|
|
2974
|
+
* the FEP-ef61 gateway endpoint, e.g.,
|
|
2975
|
+
* `POST /.well-known/apgateway/did:key:z6Mk.../users/alice/inbox`, and
|
|
2976
|
+
* dispatches them to the inbox listeners.
|
|
2977
|
+
*
|
|
2978
|
+
* The returned `URL` keeps the DID authority percent-encoded, because
|
|
2979
|
+
* the `URL` class cannot represent the canonical form. Use `formatIri()`
|
|
2980
|
+
* from `@fedify/vocab-runtime` to get the canonical string.
|
|
2981
|
+
*
|
|
2982
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2983
|
+
*
|
|
2984
|
+
* @param identifier The actor's identifier.
|
|
2985
|
+
* @param authority The DID that controls the actor, e.g.,
|
|
2986
|
+
* `did:key:z6Mk...`. It must be a bare DID, without
|
|
2987
|
+
* a path, query, or fragment.
|
|
2988
|
+
* @returns The inbox's portable ID.
|
|
2989
|
+
* @throws {RouterError} If no inbox path is registered.
|
|
2990
|
+
* @throws {TypeError} If the authority is not a DID.
|
|
2991
|
+
* @since 2.4.0
|
|
2992
|
+
*/
|
|
2993
|
+
getPortableInboxUri(identifier: string, authority: string): URL;
|
|
2994
|
+
/**
|
|
2910
2995
|
* Builds the URI of an actor's outbox with the given identifier.
|
|
2911
2996
|
* @param identifier The actor's identifier.
|
|
2912
2997
|
* @returns The actor's outbox URI.
|
|
@@ -3321,6 +3406,29 @@ interface RequestContext<TContextData> extends Context<TContextData> {
|
|
|
3321
3406
|
*/
|
|
3322
3407
|
getPortableObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>, authority?: string): URL;
|
|
3323
3408
|
/**
|
|
3409
|
+
* Builds the [FEP-ef61] portable ID of an actor's inbox with the given
|
|
3410
|
+
* identifier. It works the same as {@link Context.getPortableInboxUri},
|
|
3411
|
+
* except that the authority can be omitted while handling a portable object
|
|
3412
|
+
* request, i.e., when {@link RequestContext.portableRequest} is set. In
|
|
3413
|
+
* that case, its DID is used. Deliveries to portable inboxes do not set
|
|
3414
|
+
* {@link RequestContext.portableRequest}, so pass the authority explicitly
|
|
3415
|
+
* while handling them.
|
|
3416
|
+
*
|
|
3417
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
3418
|
+
*
|
|
3419
|
+
* @param identifier The actor's identifier.
|
|
3420
|
+
* @param authority The DID that controls the actor, e.g.,
|
|
3421
|
+
* `did:key:z6Mk...`. It must be a bare DID, without
|
|
3422
|
+
* a path, query, or fragment. Defaults to the DID of
|
|
3423
|
+
* the requested portable object, if any.
|
|
3424
|
+
* @returns The inbox's portable ID.
|
|
3425
|
+
* @throws {RouterError} If no inbox path is registered.
|
|
3426
|
+
* @throws {TypeError} If the authority is not a DID, or the authority is
|
|
3427
|
+
* omitted outside a portable gateway request.
|
|
3428
|
+
* @since 2.4.0
|
|
3429
|
+
*/
|
|
3430
|
+
getPortableInboxUri(identifier: string, authority?: string): URL;
|
|
3431
|
+
/**
|
|
3324
3432
|
* Creates a new context with the same properties as this one,
|
|
3325
3433
|
* but with the given data.
|
|
3326
3434
|
* @param data The new data to associate with the context.
|
|
@@ -3795,4 +3903,4 @@ interface ActorKeyPair extends CryptoKeyPair {
|
|
|
3795
3903
|
readonly multikey: Multikey;
|
|
3796
3904
|
}
|
|
3797
3905
|
//#endregion
|
|
3798
|
-
export {
|
|
3906
|
+
export { InProcessMessageQueueOptions as $, ObjectCallbackSetters as A, InboxErrorHandler as At, TaskDefinition as B, PortableActorIdMapper as Bt, FederationOptions as C, CollectionCursor as Ct, InboxChallengePolicy as D, CustomCollectionDispatcher as Dt, IdempotencyStrategy as E, CustomCollectionCursor as Et, FederationOrigin as F, ObjectDispatcher as Ft, CreateExponentialBackoffPolicyOptions as G, SendActivityError as Gt, TaskEnqueueOptions as H, UnverifiedActivityHandler as Ht, FederationQueueOptions as I, OutboxErrorHandler as It, createExponentialBackoffPolicy as J, buildCollectionSynchronizationHeader as Jt, RetryContext as K, SenderKeyPair as Kt, createFederation as L, OutboxListener as Lt, PortableInboxForwardingOptions as M, MediaUploaderCallback as Mt, Rfc6570Expression as N, NodeInfoDispatcher as Nt, InboxListenerSetters as O, HashlinkMediaDispatcher as Ot, FederationKvPrefixes as P, ObjectAuthorizePredicate as Pt, InProcessMessageQueue as Q, Message as R, OutboxListenerErrorHandler as Rt, FederationFetchOptions as S, CollectionCounter as St, IdempotencyKeyCallback as T, CustomCollectionCounter as Tt, TaskHandler as U, UnverifiedActivityReason as Ut, TaskDefinitionOptions as V, SharedInboxKeyDispatcher as Vt, TaskRegistry as W, WebFingerLinksDispatcher as Wt, respondWithObject as X, ActivityTransformer as Xt, RespondWithObjectOptions as Y, digest as Yt, respondWithObjectIfAcceptable as Z, CustomCollectionCallbackSetters as _, ActorAliasMapper as _t, GetSignedKeyOptions as a, CircuitBreaker as at, FederationBenchmarkOptions as b, ActorKeyPairsDispatcher as bt, ParseUriResult as c, CircuitBreakerCreateOptions as ct, RouteActivityOptions as d, CircuitBreakerOptions as dt, MessageQueue as et, SendActivityOptions as f, CircuitBreakerState as ft, ConstructorWithTypeId as g, parseCircuitBreakerKvState as gt, CollectionCallbackSetters as h, normalizeCircuitBreakerOptions as ht, GetActorOptions as i, ParallelMessageQueue as it, OutboxListenerSetters as j, InboxListener as jt, MediaUploaderSetters as k, HashlinkMediaRequest as kt, PortableRequest as l, CircuitBreakerFailurePolicy as lt, ActorCallbackSetters as m, NormalizedCircuitBreakerOptions as mt, Context as n, MessageQueueEnqueueOptions as nt, InboxContext as o, CircuitBreakerActivityDrop as ot, SendActivityOptionsForCollection as p, CircuitBreakerStateChange as pt, RetryPolicy as q, PageItems as qt, ForwardActivityOptions as r, MessageQueueListenOptions as rt, OutboxContext as s, CircuitBreakerBeforeSendDecision as st, ActorKeyPair as t, MessageQueueDepth as tt, RequestContext as u, CircuitBreakerKvState as ut, Federatable as v, ActorDispatcher as vt, FederationStartQueueOptions as w, CollectionDispatcher as wt, FederationBuilder as x, AuthorizePredicate as xt, Federation as y, ActorHandleMapper as yt, createFederationBuilder as z, OutboxPermanentFailureHandler as zt };
|
|
@@ -1422,6 +1422,16 @@ interface FederationKvPrefixes {
|
|
|
1422
1422
|
* @since 2.4.0
|
|
1423
1423
|
*/
|
|
1424
1424
|
readonly taskDeduplication: KvKey;
|
|
1425
|
+
/**
|
|
1426
|
+
* The key prefix used for remembering which activities received in
|
|
1427
|
+
* [FEP-ef61] portable inboxes have been forwarded to which gateways, so that
|
|
1428
|
+
* each activity is forwarded at most once.
|
|
1429
|
+
*
|
|
1430
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
1431
|
+
* @default `["_fedify", "portableInboxForwarding"]`
|
|
1432
|
+
* @since 2.4.0
|
|
1433
|
+
*/
|
|
1434
|
+
readonly portableInboxForwarding: KvKey;
|
|
1425
1435
|
}
|
|
1426
1436
|
/**
|
|
1427
1437
|
* Options for {@link FederationOptions.origin} when it is not a string.
|
|
@@ -2028,6 +2038,44 @@ interface FederationBuilder<TContextData> extends Federatable<TContextData> {
|
|
|
2028
2038
|
build(options: FederationOptions<TContextData>): Promise<Federation<TContextData>>;
|
|
2029
2039
|
}
|
|
2030
2040
|
/**
|
|
2041
|
+
* Options for forwarding activities received in [FEP-ef61] portable inboxes to
|
|
2042
|
+
* the other gateways of their actors. See
|
|
2043
|
+
* {@link FederationOptions.portableInboxForwarding}.
|
|
2044
|
+
*
|
|
2045
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2046
|
+
* @since 2.4.0
|
|
2047
|
+
*/
|
|
2048
|
+
interface PortableInboxForwardingOptions {
|
|
2049
|
+
/**
|
|
2050
|
+
* The maximum number of other gateways that a single delivery is forwarded
|
|
2051
|
+
* to. Gateways beyond it are skipped with a warning. `0` turns off
|
|
2052
|
+
* forwarding.
|
|
2053
|
+
* @default `10`
|
|
2054
|
+
*/
|
|
2055
|
+
maxTargets?: number;
|
|
2056
|
+
/**
|
|
2057
|
+
* How long Fedify remembers that it has forwarded an activity from
|
|
2058
|
+
* a portable inbox to a gateway, under
|
|
2059
|
+
* {@link FederationKvPrefixes.portableInboxForwarding}. Within it, the same
|
|
2060
|
+
* activity is never forwarded to the same gateway again; once it expires,
|
|
2061
|
+
* a redelivery of the activity may be forwarded again. It cannot have
|
|
2062
|
+
* calendar units, i.e., weeks, months, or years.
|
|
2063
|
+
* @default `{ days: 30 }`
|
|
2064
|
+
*/
|
|
2065
|
+
ttl?: Temporal.DurationLike;
|
|
2066
|
+
/**
|
|
2067
|
+
* How long a delivery waits for forwarding requests made immediately, i.e.,
|
|
2068
|
+
* when no outbox queue is configured, before Fedify responds to it.
|
|
2069
|
+
* Requests still running afterwards continue in the background. It does
|
|
2070
|
+
* not apply when forwarding is queued. It cannot have calendar units,
|
|
2071
|
+
* i.e., weeks, months, or years, and cannot be longer than
|
|
2072
|
+
* 2,147,483,647 milliseconds (about 24.8 days), the longest delay timers
|
|
2073
|
+
* support.
|
|
2074
|
+
* @default `{ seconds: 10 }`
|
|
2075
|
+
*/
|
|
2076
|
+
deadline?: Temporal.DurationLike;
|
|
2077
|
+
}
|
|
2078
|
+
/**
|
|
2031
2079
|
* Policy for emitting `Accept-Signature` challenges on inbox `401`
|
|
2032
2080
|
* responses, as defined in
|
|
2033
2081
|
* [RFC 9421 §5](https://www.rfc-editor.org/rfc/rfc9421#section-5).
|
|
@@ -2122,6 +2170,14 @@ interface FederationOptions<TContextData> {
|
|
|
2122
2170
|
*/
|
|
2123
2171
|
httpMessageSignaturesSpecTtl?: Temporal.DurationLike;
|
|
2124
2172
|
/**
|
|
2173
|
+
* Options for forwarding activities received in [FEP-ef61] portable inboxes
|
|
2174
|
+
* to the other gateways of their actors.
|
|
2175
|
+
*
|
|
2176
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2177
|
+
* @since 2.4.0
|
|
2178
|
+
*/
|
|
2179
|
+
portableInboxForwarding?: PortableInboxForwardingOptions;
|
|
2180
|
+
/**
|
|
2125
2181
|
* The message queue for sending and receiving activities. If not provided,
|
|
2126
2182
|
* activities will not be queued and will be processed immediately.
|
|
2127
2183
|
*
|
|
@@ -2905,6 +2961,35 @@ interface Context<TContextData> {
|
|
|
2905
2961
|
*/
|
|
2906
2962
|
getPortableObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>, authority: string): URL;
|
|
2907
2963
|
/**
|
|
2964
|
+
* Builds the [FEP-ef61] portable ID of an actor's inbox with the given
|
|
2965
|
+
* identifier under the given DID authority.
|
|
2966
|
+
*
|
|
2967
|
+
* The path is the same as the one {@link Context.getInboxUri} builds from
|
|
2968
|
+
* the inbox path, but the result is an `ap+ef61:` URI whose authority is
|
|
2969
|
+
* the DID, e.g., `ap+ef61://did:key:z6Mk.../users/alice/inbox`. If
|
|
2970
|
+
* a portable actor has it as its `inbox` and lists this server in its
|
|
2971
|
+
* `gateways`, this server accepts deliveries to the inbox through
|
|
2972
|
+
* the FEP-ef61 gateway endpoint, e.g.,
|
|
2973
|
+
* `POST /.well-known/apgateway/did:key:z6Mk.../users/alice/inbox`, and
|
|
2974
|
+
* dispatches them to the inbox listeners.
|
|
2975
|
+
*
|
|
2976
|
+
* The returned `URL` keeps the DID authority percent-encoded, because
|
|
2977
|
+
* the `URL` class cannot represent the canonical form. Use `formatIri()`
|
|
2978
|
+
* from `@fedify/vocab-runtime` to get the canonical string.
|
|
2979
|
+
*
|
|
2980
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2981
|
+
*
|
|
2982
|
+
* @param identifier The actor's identifier.
|
|
2983
|
+
* @param authority The DID that controls the actor, e.g.,
|
|
2984
|
+
* `did:key:z6Mk...`. It must be a bare DID, without
|
|
2985
|
+
* a path, query, or fragment.
|
|
2986
|
+
* @returns The inbox's portable ID.
|
|
2987
|
+
* @throws {RouterError} If no inbox path is registered.
|
|
2988
|
+
* @throws {TypeError} If the authority is not a DID.
|
|
2989
|
+
* @since 2.4.0
|
|
2990
|
+
*/
|
|
2991
|
+
getPortableInboxUri(identifier: string, authority: string): URL;
|
|
2992
|
+
/**
|
|
2908
2993
|
* Builds the URI of an actor's outbox with the given identifier.
|
|
2909
2994
|
* @param identifier The actor's identifier.
|
|
2910
2995
|
* @returns The actor's outbox URI.
|
|
@@ -3319,6 +3404,29 @@ interface RequestContext<TContextData> extends Context<TContextData> {
|
|
|
3319
3404
|
*/
|
|
3320
3405
|
getPortableObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>, authority?: string): URL;
|
|
3321
3406
|
/**
|
|
3407
|
+
* Builds the [FEP-ef61] portable ID of an actor's inbox with the given
|
|
3408
|
+
* identifier. It works the same as {@link Context.getPortableInboxUri},
|
|
3409
|
+
* except that the authority can be omitted while handling a portable object
|
|
3410
|
+
* request, i.e., when {@link RequestContext.portableRequest} is set. In
|
|
3411
|
+
* that case, its DID is used. Deliveries to portable inboxes do not set
|
|
3412
|
+
* {@link RequestContext.portableRequest}, so pass the authority explicitly
|
|
3413
|
+
* while handling them.
|
|
3414
|
+
*
|
|
3415
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
3416
|
+
*
|
|
3417
|
+
* @param identifier The actor's identifier.
|
|
3418
|
+
* @param authority The DID that controls the actor, e.g.,
|
|
3419
|
+
* `did:key:z6Mk...`. It must be a bare DID, without
|
|
3420
|
+
* a path, query, or fragment. Defaults to the DID of
|
|
3421
|
+
* the requested portable object, if any.
|
|
3422
|
+
* @returns The inbox's portable ID.
|
|
3423
|
+
* @throws {RouterError} If no inbox path is registered.
|
|
3424
|
+
* @throws {TypeError} If the authority is not a DID, or the authority is
|
|
3425
|
+
* omitted outside a portable gateway request.
|
|
3426
|
+
* @since 2.4.0
|
|
3427
|
+
*/
|
|
3428
|
+
getPortableInboxUri(identifier: string, authority?: string): URL;
|
|
3429
|
+
/**
|
|
3322
3430
|
* Creates a new context with the same properties as this one,
|
|
3323
3431
|
* but with the given data.
|
|
3324
3432
|
* @param data The new data to associate with the context.
|
|
@@ -3793,4 +3901,4 @@ interface ActorKeyPair extends CryptoKeyPair {
|
|
|
3793
3901
|
readonly multikey: Multikey;
|
|
3794
3902
|
}
|
|
3795
3903
|
//#endregion
|
|
3796
|
-
export {
|
|
3904
|
+
export { InProcessMessageQueueOptions as $, ObjectCallbackSetters as A, InboxErrorHandler as At, TaskDefinition as B, PortableActorIdMapper as Bt, FederationOptions as C, CollectionCursor as Ct, InboxChallengePolicy as D, CustomCollectionDispatcher as Dt, IdempotencyStrategy as E, CustomCollectionCursor as Et, FederationOrigin as F, ObjectDispatcher as Ft, CreateExponentialBackoffPolicyOptions as G, SendActivityError as Gt, TaskEnqueueOptions as H, UnverifiedActivityHandler as Ht, FederationQueueOptions as I, OutboxErrorHandler as It, createExponentialBackoffPolicy as J, buildCollectionSynchronizationHeader as Jt, RetryContext as K, SenderKeyPair as Kt, createFederation as L, OutboxListener as Lt, PortableInboxForwardingOptions as M, MediaUploaderCallback as Mt, Rfc6570Expression as N, NodeInfoDispatcher as Nt, InboxListenerSetters as O, HashlinkMediaDispatcher as Ot, FederationKvPrefixes as P, ObjectAuthorizePredicate as Pt, InProcessMessageQueue as Q, Message as R, OutboxListenerErrorHandler as Rt, FederationFetchOptions as S, CollectionCounter as St, IdempotencyKeyCallback as T, CustomCollectionCounter as Tt, TaskHandler as U, UnverifiedActivityReason as Ut, TaskDefinitionOptions as V, SharedInboxKeyDispatcher as Vt, TaskRegistry as W, WebFingerLinksDispatcher as Wt, respondWithObject as X, ActivityTransformer as Xt, RespondWithObjectOptions as Y, digest as Yt, respondWithObjectIfAcceptable as Z, CustomCollectionCallbackSetters as _, ActorAliasMapper as _t, GetSignedKeyOptions as a, CircuitBreaker as at, FederationBenchmarkOptions as b, ActorKeyPairsDispatcher as bt, ParseUriResult as c, CircuitBreakerCreateOptions as ct, RouteActivityOptions as d, CircuitBreakerOptions as dt, MessageQueue as et, SendActivityOptions as f, CircuitBreakerState as ft, ConstructorWithTypeId as g, parseCircuitBreakerKvState as gt, CollectionCallbackSetters as h, normalizeCircuitBreakerOptions as ht, GetActorOptions as i, ParallelMessageQueue as it, OutboxListenerSetters as j, InboxListener as jt, MediaUploaderSetters as k, HashlinkMediaRequest as kt, PortableRequest as l, CircuitBreakerFailurePolicy as lt, ActorCallbackSetters as m, NormalizedCircuitBreakerOptions as mt, Context as n, MessageQueueEnqueueOptions as nt, InboxContext as o, CircuitBreakerActivityDrop as ot, SendActivityOptionsForCollection as p, CircuitBreakerStateChange as pt, RetryPolicy as q, PageItems as qt, ForwardActivityOptions as r, MessageQueueListenOptions as rt, OutboxContext as s, CircuitBreakerBeforeSendDecision as st, ActorKeyPair as t, MessageQueueDepth as tt, RequestContext as u, CircuitBreakerKvState as ut, Federatable as v, ActorDispatcher as vt, FederationStartQueueOptions as w, CollectionDispatcher as wt, FederationBuilder as x, AuthorizePredicate as xt, Federation as y, ActorHandleMapper as yt, createFederationBuilder as z, OutboxPermanentFailureHandler as zt };
|
|
@@ -8,7 +8,7 @@ import { lookupWebFinger } from "@fedify/webfinger";
|
|
|
8
8
|
import { metrics, trace } from "@opentelemetry/api";
|
|
9
9
|
//#region src/testing/context.ts
|
|
10
10
|
function createContext(values) {
|
|
11
|
-
const { federation, url = new URL("http://example.com/"), canonicalOrigin, data, documentLoader, contextLoader, meterProvider, tracerProvider, clone, getNodeInfoUri, getActorUri, getObjectUri, getPortableObjectUri, getCollectionUri, getOutboxUri, getMediaUploaderUri, getInboxUri, getFollowingUri, getFollowersUri, getLikedUri, getFeaturedUri, getFeaturedTagsUri, parseUri, getActorKeyPairs, getDocumentLoader, lookupObject: lookupObject$1, traverseCollection: traverseCollection$1, lookupNodeInfo, lookupWebFinger: lookupWebFinger$1, sendActivity, routeActivity, enqueueTask, enqueueTaskMany } = values;
|
|
11
|
+
const { federation, url = new URL("http://example.com/"), canonicalOrigin, data, documentLoader, contextLoader, meterProvider, tracerProvider, clone, getNodeInfoUri, getActorUri, getObjectUri, getPortableObjectUri, getPortableInboxUri, getCollectionUri, getOutboxUri, getMediaUploaderUri, getInboxUri, getFollowingUri, getFollowersUri, getLikedUri, getFeaturedUri, getFeaturedTagsUri, parseUri, getActorKeyPairs, getDocumentLoader, lookupObject: lookupObject$1, traverseCollection: traverseCollection$1, lookupNodeInfo, lookupWebFinger: lookupWebFinger$1, sendActivity, routeActivity, enqueueTask, enqueueTaskMany } = values;
|
|
12
12
|
function throwRouterError() {
|
|
13
13
|
throw new RouterError("Not implemented");
|
|
14
14
|
}
|
|
@@ -31,6 +31,7 @@ function createContext(values) {
|
|
|
31
31
|
getActorUri: getActorUri ?? throwRouterError,
|
|
32
32
|
getObjectUri: getObjectUri ?? throwRouterError,
|
|
33
33
|
getPortableObjectUri: getPortableObjectUri ?? throwRouterError,
|
|
34
|
+
getPortableInboxUri: getPortableInboxUri ?? throwRouterError,
|
|
34
35
|
getCollectionUri: getCollectionUri ?? throwRouterError,
|
|
35
36
|
getOutboxUri: getOutboxUri ?? throwRouterError,
|
|
36
37
|
getMediaUploaderUri: getMediaUploaderUri ?? throwRouterError,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { s as validateCryptoKey } from "./key-
|
|
5
|
-
import { n as doubleKnock } from "./http-
|
|
4
|
+
import { s as validateCryptoKey } from "./key-IxTTC8Yf.mjs";
|
|
5
|
+
import { n as doubleKnock } from "./http-CCJ97Jql.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { curry } from "es-toolkit";
|
|
8
8
|
import { UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
@@ -6,7 +6,7 @@ import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
|
6
6
|
import { t as assertExists } from "../assert_exists-cffSpJ7X.mjs";
|
|
7
7
|
import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
8
8
|
import "../std__assert-DvMDRPes.mjs";
|
|
9
|
-
import { r as createFederationBuilder } from "../builder-
|
|
9
|
+
import { r as createFederationBuilder } from "../builder-i3jxVe9m.mjs";
|
|
10
10
|
import { DisallowedOperatorError, DisallowedVarSpecModifierError, DuplicateRouteVariableError, RouteTemplateOptionsNotMatchedError, RouterError } from "@fedify/uri-template";
|
|
11
11
|
import { Activity, Note, Person } from "@fedify/vocab";
|
|
12
12
|
import { test } from "@fedify/fixture";
|
|
@@ -6,11 +6,11 @@ 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
8
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
9
|
-
import { t as exportJwk } from "../key-
|
|
9
|
+
import { t as exportJwk } from "../key-IxTTC8Yf.mjs";
|
|
10
10
|
import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
|
|
11
|
-
import { l as verifyProof, r as signObject } from "../proof-
|
|
11
|
+
import { l as verifyProof, r as signObject } from "../proof-CVL7JnZd.mjs";
|
|
12
12
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
13
|
-
import { n as FederationImpl } from "../middleware-
|
|
13
|
+
import { n as FederationImpl } from "../middleware-BMgzqBtr.mjs";
|
|
14
14
|
import { Create, DataIntegrityProof, Note } from "@fedify/vocab";
|
|
15
15
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
16
16
|
import { exportDidKey, parseIri } from "@fedify/vocab-runtime";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { r as createRequestContext, t as createInboxContext } from "../context-
|
|
4
|
+
import { r as createRequestContext, t as createInboxContext } 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 { p as signJsonLd } from "../ld-
|
|
9
|
-
import { s as signRequest } from "../http-
|
|
10
|
-
import { a as rsaPrivateKey3, c as rsaPublicKey3 } from "../keys-DIJNHW-Y.mjs";
|
|
11
|
-
import {
|
|
8
|
+
import { a as compactJsonLd, m as verifyCompactJsonLd, p as signJsonLd } from "../ld-l0B9nREb.mjs";
|
|
9
|
+
import { s as signRequest } from "../http-CCJ97Jql.mjs";
|
|
10
|
+
import { a as rsaPrivateKey3, c as rsaPublicKey3, n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
|
|
11
|
+
import { o as createFederation, p as handleInbox } from "../middleware-BMgzqBtr.mjs";
|
|
12
12
|
import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
|
|
13
13
|
import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
|
|
14
14
|
import { Create } from "@fedify/vocab";
|
|
@@ -100,12 +100,7 @@ test("handleInbox() enforces portable compound proofs atomically", async () => {
|
|
|
100
100
|
tamperedInner.object.content = "Tampered";
|
|
101
101
|
assertEquals((await handle(await secureDocument(tamperedInner, map_local_create_note_default.keys.outer.testPrivateKeyJwk, map_local_create_note_default.keys.outer.verificationMethod))).status, 401);
|
|
102
102
|
const changedAfterSigning = structuredClone(valid);
|
|
103
|
-
changedAfterSigning.
|
|
104
|
-
type: "RsaSignature2017",
|
|
105
|
-
creator: "https://example.com/keys/1",
|
|
106
|
-
created: "2023-02-24T23:36:38Z",
|
|
107
|
-
signatureValue: "not-a-signature"
|
|
108
|
-
};
|
|
103
|
+
changedAfterSigning.summary = "Added after signing";
|
|
109
104
|
assertEquals((await handle(changedAfterSigning)).status, 401);
|
|
110
105
|
});
|
|
111
106
|
test("handleInbox() enforces compounds after alternate outer auth", async () => {
|
|
@@ -148,5 +143,137 @@ test("handleInbox() preserves ordinary top-level proof behavior", async () => {
|
|
|
148
143
|
}
|
|
149
144
|
}, map_local_create_note_default.keys.outer.testPrivateKeyJwk, map_local_create_note_default.keys.outer.verificationMethod))).status, 202);
|
|
150
145
|
});
|
|
146
|
+
async function signLd(document) {
|
|
147
|
+
return await signJsonLd(document, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader });
|
|
148
|
+
}
|
|
149
|
+
async function isLdSignatureVerified(document) {
|
|
150
|
+
return await verifyCompactJsonLd(await compactJsonLd(document, mockDocumentLoader), {
|
|
151
|
+
contextLoader: mockDocumentLoader,
|
|
152
|
+
documentLoader: mockDocumentLoader
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async function handleDispatched(body) {
|
|
156
|
+
const dispatched = { count: 0 };
|
|
157
|
+
const response = await handle(body, dispatched);
|
|
158
|
+
return [
|
|
159
|
+
response.status,
|
|
160
|
+
await response.text(),
|
|
161
|
+
dispatched.count
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
const COMPOUND_FAILURE = "Failed to verify compound portable Object Integrity Proofs.";
|
|
165
|
+
test("handleInbox() ignores a portable activity's Linked Data Signature", async () => {
|
|
166
|
+
const signed = await signLd(structuredClone(map_local_create_note_default.documents.finalSecuredCompound));
|
|
167
|
+
assertEquals(await isLdSignatureVerified(signed), false);
|
|
168
|
+
assertEquals(await handleDispatched(signed), [
|
|
169
|
+
202,
|
|
170
|
+
"",
|
|
171
|
+
1
|
|
172
|
+
]);
|
|
173
|
+
const bogus = structuredClone(map_local_create_note_default.documents.finalSecuredCompound);
|
|
174
|
+
bogus.signature = {
|
|
175
|
+
type: "RsaSignature2017",
|
|
176
|
+
creator: "https://example.com/keys/1",
|
|
177
|
+
created: "2023-02-24T23:36:38Z",
|
|
178
|
+
signatureValue: "not-a-signature"
|
|
179
|
+
};
|
|
180
|
+
assertEquals(await handleDispatched(bogus), [
|
|
181
|
+
202,
|
|
182
|
+
"",
|
|
183
|
+
1
|
|
184
|
+
]);
|
|
185
|
+
const tampered = structuredClone(map_local_create_note_default.documents.finalSecuredCompound);
|
|
186
|
+
tampered.object = {
|
|
187
|
+
...tampered.object,
|
|
188
|
+
content: "Tampered"
|
|
189
|
+
};
|
|
190
|
+
assertEquals((await handleDispatched(await signLd(tampered)))[0], 401);
|
|
191
|
+
const invalidInner = structuredClone(map_local_create_note_default.documents.outerUnsecuredDocument);
|
|
192
|
+
invalidInner.object.content = "Tampered";
|
|
193
|
+
assertEquals(await handleDispatched(await signLd(await secureDocument(invalidInner, map_local_create_note_default.keys.outer.testPrivateKeyJwk, map_local_create_note_default.keys.outer.verificationMethod))), [
|
|
194
|
+
401,
|
|
195
|
+
COMPOUND_FAILURE,
|
|
196
|
+
0
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
test("handleInbox() verifies compounds with verified Linked Data Signatures", async () => {
|
|
200
|
+
const createBody = (object) => ({
|
|
201
|
+
"@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"],
|
|
202
|
+
id: "https://example.com/activities/compound-ld",
|
|
203
|
+
type: "Create",
|
|
204
|
+
actor: rsaPublicKey3.ownerId.href,
|
|
205
|
+
object
|
|
206
|
+
});
|
|
207
|
+
const privateJwk = await crypto.subtle.exportKey("jwk", ed25519PrivateKey);
|
|
208
|
+
const sign = async (object) => await signLd(await secureDocument(createBody(object), privateJwk, ed25519PublicKey.id.href));
|
|
209
|
+
const valid = await sign(structuredClone(map_local_create_note_default.documents.securedInner));
|
|
210
|
+
assertEquals(await isLdSignatureVerified(valid), true);
|
|
211
|
+
assertEquals(await handleDispatched(valid), [
|
|
212
|
+
202,
|
|
213
|
+
"",
|
|
214
|
+
1
|
|
215
|
+
]);
|
|
216
|
+
const invalidInner = structuredClone(map_local_create_note_default.documents.securedInner);
|
|
217
|
+
invalidInner.content = "Tampered";
|
|
218
|
+
const invalid = await sign(invalidInner);
|
|
219
|
+
assertEquals(await isLdSignatureVerified(invalid), true);
|
|
220
|
+
assertEquals(await handleDispatched(invalid), [
|
|
221
|
+
401,
|
|
222
|
+
COMPOUND_FAILURE,
|
|
223
|
+
0
|
|
224
|
+
]);
|
|
225
|
+
});
|
|
226
|
+
test("handleInbox() keeps embedded signature properties in proof inputs", async () => {
|
|
227
|
+
const innerWithSignature = await secureDocument({
|
|
228
|
+
...map_local_create_note_default.documents.innerUnsecuredDocument,
|
|
229
|
+
"@context": ["https://w3id.org/security/v1", ...map_local_create_note_default.documents.innerUnsecuredDocument["@context"]],
|
|
230
|
+
signature: {
|
|
231
|
+
type: "https://example.com/ns#ExampleSignature",
|
|
232
|
+
signatureValue: "covered by the inner proof"
|
|
233
|
+
}
|
|
234
|
+
}, map_local_create_note_default.keys.inner.testPrivateKeyJwk, map_local_create_note_default.keys.inner.verificationMethod);
|
|
235
|
+
const sign = async (object) => await signLd(await secureDocument({
|
|
236
|
+
...map_local_create_note_default.documents.outerUnsecuredDocument,
|
|
237
|
+
object
|
|
238
|
+
}, map_local_create_note_default.keys.outer.testPrivateKeyJwk, map_local_create_note_default.keys.outer.verificationMethod));
|
|
239
|
+
assertEquals(await handleDispatched(await sign(structuredClone(innerWithSignature))), [
|
|
240
|
+
202,
|
|
241
|
+
"",
|
|
242
|
+
1
|
|
243
|
+
]);
|
|
244
|
+
const innerWithoutSignature = structuredClone(innerWithSignature);
|
|
245
|
+
delete innerWithoutSignature.signature;
|
|
246
|
+
assertEquals(await handleDispatched(await sign(innerWithoutSignature)), [
|
|
247
|
+
401,
|
|
248
|
+
COMPOUND_FAILURE,
|
|
249
|
+
0
|
|
250
|
+
]);
|
|
251
|
+
});
|
|
252
|
+
test("handleInbox() inspects compounds without the Linked Data Signature", async () => {
|
|
253
|
+
const activity = await secureDocument({
|
|
254
|
+
"@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"],
|
|
255
|
+
id: "https://example.com/activities/ordinary-ld",
|
|
256
|
+
type: "Create",
|
|
257
|
+
actor: map_local_create_note_default.keys.outer.controller,
|
|
258
|
+
object: {
|
|
259
|
+
id: "https://example.com/notes/ordinary-ld",
|
|
260
|
+
type: "Note",
|
|
261
|
+
attributedTo: map_local_create_note_default.keys.outer.controller,
|
|
262
|
+
content: "An ordinary note"
|
|
263
|
+
}
|
|
264
|
+
}, map_local_create_note_default.keys.outer.testPrivateKeyJwk, map_local_create_note_default.keys.outer.verificationMethod);
|
|
265
|
+
activity.signature = {
|
|
266
|
+
id: map_local_create_note_default.documents.innerUnsecuredDocument.id,
|
|
267
|
+
type: "RsaSignature2017",
|
|
268
|
+
creator: "https://example.com/keys/1",
|
|
269
|
+
created: "2023-02-24T23:36:38Z",
|
|
270
|
+
signatureValue: "not-a-signature"
|
|
271
|
+
};
|
|
272
|
+
assertEquals(await handleDispatched(activity), [
|
|
273
|
+
202,
|
|
274
|
+
"",
|
|
275
|
+
1
|
|
276
|
+
]);
|
|
277
|
+
});
|
|
151
278
|
//#endregion
|
|
152
279
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-
|
|
4
|
+
import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } 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 { t as assertGreaterOrEqual } from "../assert_greater_or_equal-BlafOF4-.mjs";
|
|
@@ -10,12 +10,12 @@ import "../std__assert-DvMDRPes.mjs";
|
|
|
10
10
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
11
11
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
12
12
|
import { r as parseAcceptSignature } from "../accept-CPVqki78.mjs";
|
|
13
|
-
import { a as generateCryptoKeyPair } from "../key-
|
|
14
|
-
import { a as compactJsonLd, p as signJsonLd } from "../ld-
|
|
15
|
-
import { r as signObject } from "../proof-
|
|
16
|
-
import { s as signRequest } from "../http-
|
|
13
|
+
import { a as generateCryptoKeyPair } from "../key-IxTTC8Yf.mjs";
|
|
14
|
+
import { a as compactJsonLd, p as signJsonLd } from "../ld-l0B9nREb.mjs";
|
|
15
|
+
import { r as signObject } from "../proof-CVL7JnZd.mjs";
|
|
16
|
+
import { s as signRequest } from "../http-CCJ97Jql.mjs";
|
|
17
17
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
18
|
-
import {
|
|
18
|
+
import { _ as respondWithObjectIfAcceptable, d as handleCollection, f as handleCustomCollection, g as respondWithObject, h as handleOutbox, m as handleObject, o as createFederation, p as handleInbox, u as handleActor } from "../middleware-BMgzqBtr.mjs";
|
|
19
19
|
import { t as ActivityListenerSet } from "../activity-listener-C-BSbKI7.mjs";
|
|
20
20
|
import { Activity, Create, CryptographicKey, Multikey, Note, Person, Tombstone } from "@fedify/vocab";
|
|
21
21
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|