@fedify/fedify 2.4.0-dev.2169 → 2.4.0-dev.2193
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-B2d_Pt0j.mjs → builder-0onlMY4u.mjs} +26 -6
- package/dist/{circuit-breaker-C5NqoLBJ.mjs → circuit-breaker-XJ53md4S.mjs} +16 -11
- 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-D28gMFqP.mjs → compound-proof-B-Fk6Slo.mjs} +3 -3
- package/dist/{context-BykNUf04.d.ts → context-9T--NSo4.d.ts} +55 -1
- package/dist/{context-L0Fnib9j.d.cts → context-CDcAgm4l.d.cts} +55 -1
- package/dist/{deno-DU8dvnWk.mjs → deno-DB_Sh0LK.mjs} +1 -1
- package/dist/{docloader-CghLH7Zi.mjs → docloader-DpWYYY6a.mjs} +25 -17
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/circuit-breaker.test.mjs +50 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +52 -3
- package/dist/federation/handler.test.mjs +5 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/keycache.test.mjs +1 -1
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +182 -13
- 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 +5 -5
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.mjs +3 -3
- package/dist/federation/portable-collection.test.mjs +4 -4
- package/dist/federation/portable-gateway-keys.test.mjs +6 -6
- package/dist/federation/portable-inbox.test.mjs +35 -5
- package/dist/federation/portable-parse-uri.test.mjs +1 -1
- package/dist/federation/portable-route-activity.test.d.mts +2 -0
- package/dist/federation/portable-route-activity.test.mjs +259 -0
- package/dist/federation/portable.test.mjs +49 -5
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{federation-DrNgkLfJ.cjs → federation-BsGo0EH2.cjs} +76 -35
- package/dist/{http-5CJBdU8n.cjs → http-BEivI0TS.cjs} +279 -87
- package/dist/{http-BGpexPO7.js → http-BGmxtpo2.js} +263 -89
- package/dist/{http-Cok5-vIC.d.ts → http-BrwKINQn.d.cts} +29 -1
- package/dist/{http-DC1cqAQ2.d.cts → http-DGx0KOws.d.ts} +29 -1
- package/dist/{http-Bd6rZlJX.mjs → http-DQf9Mw4V.mjs} +180 -92
- package/dist/{key-gIhVZO3p.mjs → key-DA3Yx8p2.mjs} +4 -4
- package/dist/{key-owner-evidence-Bo3yaeL5.mjs → key-owner-evidence-APB6NpSk.mjs} +1 -1
- package/dist/{keycache-PiOM9pM0.mjs → keycache-Da8A8mZa.mjs} +1 -1
- package/dist/{kv-cache-YRi_g8GB.cjs → kv-cache-1hafSoqH.cjs} +23 -15
- package/dist/{kv-cache-iR55fqlk.js → kv-cache-DduYhpee.js} +24 -16
- package/dist/{kv-cache-D0qjSeWY.mjs → kv-cache-OFBvrKh3.mjs} +1 -1
- package/dist/{ld-BsTkRrwF.mjs → ld-C15yzuY6.mjs} +3 -3
- package/dist/{metrics-jUDFfVgi.mjs → metrics-B1H23mlq.mjs} +1 -1
- package/dist/{middleware-Dq-OCmb6.mjs → middleware-BZQnf0nI.mjs} +1 -1
- package/dist/{middleware-Coqgp-K0.mjs → middleware-BqqycC0P.mjs} +52 -36
- package/dist/{middleware-DlxMxVp5.js → middleware-ClaUFaLb.js} +77 -36
- package/dist/{mod-DK0y9fd-.d.ts → mod-B3OBLj5g.d.ts} +1 -1
- package/dist/{mod-B5z_q9TH.d.ts → mod-C5Mwx5ty.d.ts} +5 -1
- package/dist/{mod-CPPqkyV_.d.cts → mod-Cy9VNHVw.d.ts} +14 -3
- package/dist/{mod-BLOXGs6m.d.cts → mod-D58KCqUg.d.cts} +1 -1
- package/dist/{mod--jv6vyrP.d.ts → mod-DoTWIc7F.d.cts} +14 -3
- package/dist/{mod-BA_F2x53.d.cts → mod-Dp3Ij7sw.d.cts} +5 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-D3GoetXS.mjs → owner-BVpZBM-V.mjs} +5 -5
- package/dist/{portable-collection-CnlCamup.cjs → portable-collection-BFSShzwh.cjs} +1 -1
- package/dist/{portable-collection-Bkdh_WpL.js → portable-collection-D535cSz_.js} +1 -1
- package/dist/{portable-collection-C60_acmx.mjs → portable-collection-Dn2GdZdI.mjs} +2 -2
- package/dist/{portable-key-DyF5AnZo.mjs → portable-key-Bmwmq7Y6.mjs} +2 -2
- package/dist/{portable-key-id-Bg259c4Z.mjs → portable-key-id-Ca30-hOa.mjs} +45 -1
- package/dist/{proof-CQAYqWdj.mjs → proof-DrJWKeOl.mjs} +49 -7
- package/dist/{send-DjkQrxt5.mjs → send-CT3a-0Vd.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 +495 -23
- package/dist/sig/key-owner-evidence.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +1 -1
- package/dist/sig/portable-key-id.test.d.mts +2 -0
- package/dist/sig/portable-key-id.test.mjs +67 -0
- package/dist/sig/portable-key.test.mjs +7 -7
- package/dist/sig/proof.test.mjs +141 -7
- package/dist/{temporal-oRKP803M.mjs → temporal-DNqluyEc.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +52 -0
- package/dist/utils/docloader.test.mjs +93 -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
|
@@ -1,8 +1,8 @@
|
|
|
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 {
|
|
4
|
+
import { n as version, t as name } from "./deno-DB_Sh0LK.mjs";
|
|
5
|
+
import { i as getPortableDid, l as isPortableId, n as getCanonicalPortableId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
6
6
|
import { t as ActivityListenerSet } from "./activity-listener-C-BSbKI7.mjs";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { Router, RouterError, assertPath } from "@fedify/uri-template";
|
|
@@ -89,7 +89,7 @@ var FederationBuilderImpl = class {
|
|
|
89
89
|
* specified.
|
|
90
90
|
*/
|
|
91
91
|
async build(options) {
|
|
92
|
-
const { FederationImpl } = await import("./middleware-
|
|
92
|
+
const { FederationImpl } = await import("./middleware-BZQnf0nI.mjs");
|
|
93
93
|
const f = new FederationImpl(options);
|
|
94
94
|
const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
|
|
95
95
|
f.router = this.router.clone();
|
|
@@ -165,6 +165,7 @@ var FederationBuilderImpl = class {
|
|
|
165
165
|
if (actor.id == null) logger.warn("Actor dispatcher returned an actor without an id property. Set the property with Context.getActorUri(identifier).");
|
|
166
166
|
else if (!portable && actor.id.href != context.getActorUri(identifier).href) logger.warn("Actor dispatcher returned an actor with an id property that does not match the actor URI. Set the property with Context.getActorUri(identifier).");
|
|
167
167
|
if (actor instanceof Tombstone) return actor;
|
|
168
|
+
if (portable && actor.id != null) warnPortableActorGateways(actor.id, actor.gateways);
|
|
168
169
|
if (actor.id != null && isCompatibleEf61Iri(actor.id)) warnCompatibleActorId(actor.id, actor.gateway);
|
|
169
170
|
if (portable) this.#warnPortableCollectionIds(context, identifier, actor);
|
|
170
171
|
if (this.followingCallbacks != null && this.followingCallbacks.dispatcher != null) {
|
|
@@ -768,9 +769,28 @@ function warnMismatchedTombstoneId(context, cls, values, tombstone) {
|
|
|
768
769
|
});
|
|
769
770
|
}
|
|
770
771
|
/**
|
|
772
|
+
* Warns about an FEP-ef61 portable actor whose `gateways` is empty or has
|
|
773
|
+
* an item that is not an HTTP(S) origin, which FEP-ef61 does not allow.
|
|
774
|
+
* Every item is checked, since the list and its URLs can be mutated after
|
|
775
|
+
* the actor is constructed.
|
|
776
|
+
*/
|
|
777
|
+
function warnPortableActorGateways(actorId, gateways) {
|
|
778
|
+
if (gateways.length > 0 && gateways.every(isGatewayUrl)) return;
|
|
779
|
+
getLogger([
|
|
780
|
+
"fedify",
|
|
781
|
+
"federation",
|
|
782
|
+
"actor"
|
|
783
|
+
]).warn("Actor dispatcher returned an FEP-ef61 portable actor, {actorId}, whose gateways property is empty or has an item that is not an HTTP(S) origin. FEP-ef61 requires a portable actor to have at least one gateway, and every gateway to be an HTTP(S) URI with an empty path, query, and fragment. Set the gateways property.", {
|
|
784
|
+
actorId: actorId.href,
|
|
785
|
+
gateways: gateways.map((g) => g.href)
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
771
789
|
* Warns about an FEP-ef61 portable actor identified by a compatible identifier
|
|
772
790
|
* that is malformed, or is not on the actor's first gateway, where FEP-ef61
|
|
773
|
-
* requires publishers to construct compatible identifiers.
|
|
791
|
+
* requires publishers to construct compatible identifiers. A missing or
|
|
792
|
+
* invalid first gateway is reported by {@link warnPortableActorGateways}
|
|
793
|
+
* instead.
|
|
774
794
|
*/
|
|
775
795
|
function warnCompatibleActorId(actorId, gateway) {
|
|
776
796
|
const logger = getLogger([
|
|
@@ -788,8 +808,8 @@ function warnCompatibleActorId(actorId, gateway) {
|
|
|
788
808
|
});
|
|
789
809
|
return;
|
|
790
810
|
}
|
|
791
|
-
if (gateway == null || !isGatewayUrl(gateway))
|
|
792
|
-
|
|
811
|
+
if (gateway == null || !isGatewayUrl(gateway)) return;
|
|
812
|
+
if (actorId.origin !== gateway.origin) logger.warn("Actor dispatcher returned an actor whose id property, {actorId}, is an FEP-ef61 compatible identifier on another gateway than its first gateway, {gateway}. FEP-ef61 requires publishers to construct compatible identifiers with the first gateway in the actor's gateways.", {
|
|
793
813
|
actorId: actorId.href,
|
|
794
814
|
gateway: gateway.origin
|
|
795
815
|
});
|
|
@@ -47,7 +47,7 @@ var CircuitBreaker = class {
|
|
|
47
47
|
};
|
|
48
48
|
let lastConflictingState;
|
|
49
49
|
for (let attempt = 0; attempt < 10; attempt++) {
|
|
50
|
-
const oldState = await this.#get(remoteHost);
|
|
50
|
+
const { state: oldState, raw: oldValue } = await this.#get(remoteHost);
|
|
51
51
|
if (oldState == null || oldState.state === "closed") return {
|
|
52
52
|
type: "send",
|
|
53
53
|
probe: false
|
|
@@ -73,7 +73,7 @@ var CircuitBreaker = class {
|
|
|
73
73
|
state: "half-open",
|
|
74
74
|
halfOpened: now.toString()
|
|
75
75
|
};
|
|
76
|
-
if (await this.#replace(remoteHost,
|
|
76
|
+
if (await this.#replace(remoteHost, oldValue, newState)) return {
|
|
77
77
|
type: "send",
|
|
78
78
|
probe: true
|
|
79
79
|
};
|
|
@@ -95,7 +95,7 @@ var CircuitBreaker = class {
|
|
|
95
95
|
state: "half-open",
|
|
96
96
|
halfOpened: now.toString()
|
|
97
97
|
};
|
|
98
|
-
if (await this.#replace(remoteHost,
|
|
98
|
+
if (await this.#replace(remoteHost, oldValue, newState)) {
|
|
99
99
|
await this.#notifyStateChange(remoteHost, "open", "half-open");
|
|
100
100
|
return {
|
|
101
101
|
type: "send",
|
|
@@ -122,9 +122,9 @@ var CircuitBreaker = class {
|
|
|
122
122
|
async recordSuccess(remoteHost) {
|
|
123
123
|
this.#sweepLegacyStates();
|
|
124
124
|
for (let attempt = 0; attempt < 10; attempt++) {
|
|
125
|
-
const oldState = await this.#get(remoteHost);
|
|
125
|
+
const { state: oldState, raw: oldValue } = await this.#get(remoteHost);
|
|
126
126
|
if (oldState == null) return void 0;
|
|
127
|
-
if (await this.#replace(remoteHost,
|
|
127
|
+
if (await this.#replace(remoteHost, oldValue, void 0)) {
|
|
128
128
|
if (oldState.state !== "closed") {
|
|
129
129
|
await this.#notifyStateChange(remoteHost, oldState.state, "closed");
|
|
130
130
|
return {
|
|
@@ -144,7 +144,7 @@ var CircuitBreaker = class {
|
|
|
144
144
|
this.#sweepLegacyStates();
|
|
145
145
|
const now = this.#now();
|
|
146
146
|
for (let attempt = 0; attempt < 10; attempt++) {
|
|
147
|
-
const oldState = await this.#get(remoteHost);
|
|
147
|
+
const { state: oldState, raw: oldValue } = await this.#get(remoteHost);
|
|
148
148
|
if (oldState?.state === "open") return void 0;
|
|
149
149
|
const oldFailures = oldState?.failures.map(Temporal.Instant.from) ?? [];
|
|
150
150
|
const failures = this.#options.pruneFailures([...oldFailures, now], now);
|
|
@@ -161,7 +161,7 @@ var CircuitBreaker = class {
|
|
|
161
161
|
state: "closed",
|
|
162
162
|
failures: failures.map((t) => t.toString())
|
|
163
163
|
};
|
|
164
|
-
if (await this.#replace(remoteHost,
|
|
164
|
+
if (await this.#replace(remoteHost, oldValue, newState)) {
|
|
165
165
|
if (transition != null) {
|
|
166
166
|
await this.#notifyStateChange(remoteHost, transition[0], transition[1]);
|
|
167
167
|
return {
|
|
@@ -190,7 +190,7 @@ var CircuitBreaker = class {
|
|
|
190
190
|
}
|
|
191
191
|
async getState(remoteHost) {
|
|
192
192
|
this.#sweepLegacyStates();
|
|
193
|
-
return stripStoredCircuitBreakerState(await this.#get(remoteHost));
|
|
193
|
+
return stripStoredCircuitBreakerState((await this.#get(remoteHost)).state);
|
|
194
194
|
}
|
|
195
195
|
/**
|
|
196
196
|
* The currently running background legacy sweep, if any.
|
|
@@ -310,9 +310,14 @@ var CircuitBreaker = class {
|
|
|
310
310
|
return Temporal.Instant.compare(expiresAt, retryAt) < 0 ? expiresAt : retryAt;
|
|
311
311
|
}
|
|
312
312
|
async #get(remoteHost) {
|
|
313
|
-
|
|
313
|
+
const value = await this.#kv.get(this.#key(remoteHost));
|
|
314
|
+
const state = parseStoredCircuitBreakerKvState(value);
|
|
315
|
+
return {
|
|
316
|
+
state,
|
|
317
|
+
raw: state == null ? void 0 : value
|
|
318
|
+
};
|
|
314
319
|
}
|
|
315
|
-
async #replace(remoteHost,
|
|
320
|
+
async #replace(remoteHost, oldValue, newState) {
|
|
316
321
|
const key = this.#key(remoteHost);
|
|
317
322
|
const storedState = newState == null ? void 0 : markCircuitBreakerState(newState);
|
|
318
323
|
if (this.#kv.cas == null) {
|
|
@@ -320,7 +325,7 @@ var CircuitBreaker = class {
|
|
|
320
325
|
else await this.#kv.set(key, storedState, this.#setOptions());
|
|
321
326
|
return true;
|
|
322
327
|
}
|
|
323
|
-
return await this.#kv.cas(key,
|
|
328
|
+
return await this.#kv.cas(key, oldValue, storedState, storedState == null ? void 0 : this.#setOptions());
|
|
324
329
|
}
|
|
325
330
|
#setOptions() {
|
|
326
331
|
return this.#options.stateTtl == null ? void 0 : { ttl: this.#options.stateTtl };
|
package/dist/compat/mod.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { $t as ActivityTransformer, n as Context } from "../context-
|
|
2
|
+
import { $t as ActivityTransformer, n as Context } from "../context-CDcAgm4l.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 { $t as ActivityTransformer, n as Context } from "../context-
|
|
2
|
+
import { $t as ActivityTransformer, n as Context } from "../context-9T--NSo4.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 { E as autoIdAssigner, T as actorDehydrator, n as FederationImpl } from "../middleware-
|
|
8
|
+
import { E as autoIdAssigner, T as actorDehydrator, n as FederationImpl } from "../middleware-BqqycC0P.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,10 +1,10 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import {
|
|
4
|
+
import { a as getRawCanonicalPortableId, l as isPortableId, n as getCanonicalPortableId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
5
5
|
import { n as preloadedOnlyDocumentLoader } from "./public-audience--klBIOk1.mjs";
|
|
6
|
-
import { c as getNormalizationContextLoader } from "./ld-
|
|
7
|
-
import { l as verifyPortableObjectProofPolicy, n as classifyFep2277CoreType, o as verifyMapLocalProof } from "./proof-
|
|
6
|
+
import { c as getNormalizationContextLoader } from "./ld-C15yzuY6.mjs";
|
|
7
|
+
import { l as verifyPortableObjectProofPolicy, n as classifyFep2277CoreType, o as verifyMapLocalProof } from "./proof-DrJWKeOl.mjs";
|
|
8
8
|
import { parseIri, preloadedContexts } from "@fedify/vocab-runtime";
|
|
9
9
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
10
10
|
//#region src/sig/compound-proof.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { o as JsonValue, s as NodeInfo, t as GetNodeInfoOptions } from "./client-D-XP_Ccb.js";
|
|
3
|
-
import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-
|
|
3
|
+
import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-DGx0KOws.js";
|
|
4
4
|
import { n as GetKeyOwnerOptions } from "./owner-BSzr5-I8.js";
|
|
5
5
|
import { n as KvStore, t as KvKey } from "./kv-BhNbN8Ed.js";
|
|
6
6
|
import { Router } from "@fedify/uri-template";
|
|
@@ -1485,6 +1485,8 @@ interface FederationOrigin {
|
|
|
1485
1485
|
* @returns A new {@link Federation} instance.
|
|
1486
1486
|
* @throws {TypeError} If benchmark mode and `meterProvider` are both
|
|
1487
1487
|
* specified.
|
|
1488
|
+
* @throws {RangeError} If {@link FederationOptions.maxHttpSignatures} is not
|
|
1489
|
+
* a positive integer or `Infinity`.
|
|
1488
1490
|
* @since 0.10.0
|
|
1489
1491
|
*/
|
|
1490
1492
|
declare function createFederation<TContextData>(options: FederationOptions<TContextData>): Federation<TContextData>;
|
|
@@ -2309,6 +2311,35 @@ interface FederationOptions<TContextData> {
|
|
|
2309
2311
|
*/
|
|
2310
2312
|
userAgent?: GetUserAgentOptions | string;
|
|
2311
2313
|
/**
|
|
2314
|
+
* The timeout for each call of the built-in document loader, context
|
|
2315
|
+
* loader, and authenticated document loader, e.g., when Fedify fetches
|
|
2316
|
+
* a key to verify a signature. The timeout is shared by all the steps of
|
|
2317
|
+
* a call, including every redirect it follows, retries, and reading the
|
|
2318
|
+
* response body. It does not cover the time spent reading from or
|
|
2319
|
+
* writing to the cache.
|
|
2320
|
+
*
|
|
2321
|
+
* A timed-out call throws a `FetchError` without a response, whose
|
|
2322
|
+
* `cause` is a `DOMException` named `"TimeoutError"`, so that, e.g.,
|
|
2323
|
+
* a key fetch that times out is reported as a `keyFetchError` and cached
|
|
2324
|
+
* like other failures to fetch a key.
|
|
2325
|
+
*
|
|
2326
|
+
* It does not affect loaders made by
|
|
2327
|
+
* {@link FederationOptions.documentLoaderFactory},
|
|
2328
|
+
* {@link FederationOptions.contextLoaderFactory}, or
|
|
2329
|
+
* {@link FederationOptions.authenticatedDocumentLoaderFactory}.
|
|
2330
|
+
* Note that if only {@link FederationOptions.documentLoaderFactory} is
|
|
2331
|
+
* set, it also makes context loaders.
|
|
2332
|
+
*
|
|
2333
|
+
* Set it to `null` to turn off the timeout.
|
|
2334
|
+
*
|
|
2335
|
+
* 10 seconds by default.
|
|
2336
|
+
* @throws {RangeError} If the duration is not positive, is longer than
|
|
2337
|
+
* about 24.8 days, or is given in calendar units
|
|
2338
|
+
* such as months.
|
|
2339
|
+
* @since 2.4.0
|
|
2340
|
+
*/
|
|
2341
|
+
documentLoaderTimeout?: Temporal.Duration | Temporal.DurationLike | null;
|
|
2342
|
+
/**
|
|
2312
2343
|
* A callback that handles errors during outbox processing. Note that this
|
|
2313
2344
|
* callback can be called multiple times for the same activity, because
|
|
2314
2345
|
* the delivery is retried according to the backoff schedule until it
|
|
@@ -2337,6 +2368,29 @@ interface FederationOptions<TContextData> {
|
|
|
2337
2368
|
*/
|
|
2338
2369
|
signatureTimeWindow?: Temporal.Duration | Temporal.DurationLike | false;
|
|
2339
2370
|
/**
|
|
2371
|
+
* The maximum number of [RFC 9421] signatures of an incoming request to
|
|
2372
|
+
* verify, e.g., in the inbox and in
|
|
2373
|
+
* {@link RequestContext.getSignedKey}. A request can carry several
|
|
2374
|
+
* signatures, each of which may make Fedify fetch the key that it names,
|
|
2375
|
+
* so only the first ones in the order of the `Signature-Input` header are
|
|
2376
|
+
* verified, and the rest are ignored as if they were absent. Every
|
|
2377
|
+
* signature among the first ones counts, even if it fails before its key
|
|
2378
|
+
* is fetched. See also the `maxSignatures` option of `verifyRequest()`.
|
|
2379
|
+
*
|
|
2380
|
+
* It has to be a positive integer, or `Infinity` to verify every
|
|
2381
|
+
* signature, which lets a single request make Fedify fetch any number of
|
|
2382
|
+
* keys. Draft-cavage HTTP Signatures carry a single signature, so this
|
|
2383
|
+
* option does not affect them.
|
|
2384
|
+
*
|
|
2385
|
+
* Three by default.
|
|
2386
|
+
*
|
|
2387
|
+
* [RFC 9421]: https://www.rfc-editor.org/rfc/rfc9421
|
|
2388
|
+
* @throws {RangeError} Thrown when the federation is created if the value
|
|
2389
|
+
* is not a positive integer or `Infinity`.
|
|
2390
|
+
* @since 2.4.0
|
|
2391
|
+
*/
|
|
2392
|
+
maxHttpSignatures?: number;
|
|
2393
|
+
/**
|
|
2340
2394
|
* Whether to skip HTTP Signatures verification for incoming activities.
|
|
2341
2395
|
* This is useful for testing purposes, but should not be used in production.
|
|
2342
2396
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { o as JsonValue, s as NodeInfo, t as GetNodeInfoOptions } from "./client-D-XP_Ccb.cjs";
|
|
3
|
-
import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-
|
|
3
|
+
import { o as VerifyRequestFailureReason, t as HttpMessageSignaturesSpec } from "./http-BrwKINQn.cjs";
|
|
4
4
|
import { n as GetKeyOwnerOptions } from "./owner-BF0L9cMt.cjs";
|
|
5
5
|
import { n as KvStore, t as KvKey } from "./kv-BhNbN8Ed.cjs";
|
|
6
6
|
import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
|
|
@@ -1483,6 +1483,8 @@ interface FederationOrigin {
|
|
|
1483
1483
|
* @returns A new {@link Federation} instance.
|
|
1484
1484
|
* @throws {TypeError} If benchmark mode and `meterProvider` are both
|
|
1485
1485
|
* specified.
|
|
1486
|
+
* @throws {RangeError} If {@link FederationOptions.maxHttpSignatures} is not
|
|
1487
|
+
* a positive integer or `Infinity`.
|
|
1486
1488
|
* @since 0.10.0
|
|
1487
1489
|
*/
|
|
1488
1490
|
declare function createFederation<TContextData>(options: FederationOptions<TContextData>): Federation<TContextData>;
|
|
@@ -2307,6 +2309,35 @@ interface FederationOptions<TContextData> {
|
|
|
2307
2309
|
*/
|
|
2308
2310
|
userAgent?: GetUserAgentOptions | string;
|
|
2309
2311
|
/**
|
|
2312
|
+
* The timeout for each call of the built-in document loader, context
|
|
2313
|
+
* loader, and authenticated document loader, e.g., when Fedify fetches
|
|
2314
|
+
* a key to verify a signature. The timeout is shared by all the steps of
|
|
2315
|
+
* a call, including every redirect it follows, retries, and reading the
|
|
2316
|
+
* response body. It does not cover the time spent reading from or
|
|
2317
|
+
* writing to the cache.
|
|
2318
|
+
*
|
|
2319
|
+
* A timed-out call throws a `FetchError` without a response, whose
|
|
2320
|
+
* `cause` is a `DOMException` named `"TimeoutError"`, so that, e.g.,
|
|
2321
|
+
* a key fetch that times out is reported as a `keyFetchError` and cached
|
|
2322
|
+
* like other failures to fetch a key.
|
|
2323
|
+
*
|
|
2324
|
+
* It does not affect loaders made by
|
|
2325
|
+
* {@link FederationOptions.documentLoaderFactory},
|
|
2326
|
+
* {@link FederationOptions.contextLoaderFactory}, or
|
|
2327
|
+
* {@link FederationOptions.authenticatedDocumentLoaderFactory}.
|
|
2328
|
+
* Note that if only {@link FederationOptions.documentLoaderFactory} is
|
|
2329
|
+
* set, it also makes context loaders.
|
|
2330
|
+
*
|
|
2331
|
+
* Set it to `null` to turn off the timeout.
|
|
2332
|
+
*
|
|
2333
|
+
* 10 seconds by default.
|
|
2334
|
+
* @throws {RangeError} If the duration is not positive, is longer than
|
|
2335
|
+
* about 24.8 days, or is given in calendar units
|
|
2336
|
+
* such as months.
|
|
2337
|
+
* @since 2.4.0
|
|
2338
|
+
*/
|
|
2339
|
+
documentLoaderTimeout?: Temporal.Duration | Temporal.DurationLike | null;
|
|
2340
|
+
/**
|
|
2310
2341
|
* A callback that handles errors during outbox processing. Note that this
|
|
2311
2342
|
* callback can be called multiple times for the same activity, because
|
|
2312
2343
|
* the delivery is retried according to the backoff schedule until it
|
|
@@ -2335,6 +2366,29 @@ interface FederationOptions<TContextData> {
|
|
|
2335
2366
|
*/
|
|
2336
2367
|
signatureTimeWindow?: Temporal.Duration | Temporal.DurationLike | false;
|
|
2337
2368
|
/**
|
|
2369
|
+
* The maximum number of [RFC 9421] signatures of an incoming request to
|
|
2370
|
+
* verify, e.g., in the inbox and in
|
|
2371
|
+
* {@link RequestContext.getSignedKey}. A request can carry several
|
|
2372
|
+
* signatures, each of which may make Fedify fetch the key that it names,
|
|
2373
|
+
* so only the first ones in the order of the `Signature-Input` header are
|
|
2374
|
+
* verified, and the rest are ignored as if they were absent. Every
|
|
2375
|
+
* signature among the first ones counts, even if it fails before its key
|
|
2376
|
+
* is fetched. See also the `maxSignatures` option of `verifyRequest()`.
|
|
2377
|
+
*
|
|
2378
|
+
* It has to be a positive integer, or `Infinity` to verify every
|
|
2379
|
+
* signature, which lets a single request make Fedify fetch any number of
|
|
2380
|
+
* keys. Draft-cavage HTTP Signatures carry a single signature, so this
|
|
2381
|
+
* option does not affect them.
|
|
2382
|
+
*
|
|
2383
|
+
* Three by default.
|
|
2384
|
+
*
|
|
2385
|
+
* [RFC 9421]: https://www.rfc-editor.org/rfc/rfc9421
|
|
2386
|
+
* @throws {RangeError} Thrown when the federation is created if the value
|
|
2387
|
+
* is not a positive integer or `Infinity`.
|
|
2388
|
+
* @since 2.4.0
|
|
2389
|
+
*/
|
|
2390
|
+
maxHttpSignatures?: number;
|
|
2391
|
+
/**
|
|
2338
2392
|
* Whether to skip HTTP Signatures verification for incoming activities.
|
|
2339
2393
|
* This is useful for testing purposes, but should not be used in production.
|
|
2340
2394
|
*
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { c as validateCryptoKey } from "./key-
|
|
5
|
-
import { n as doubleKnock } from "./http-
|
|
4
|
+
import { c as validateCryptoKey } from "./key-DA3Yx8p2.mjs";
|
|
5
|
+
import { n as doubleKnock } from "./http-DQf9Mw4V.mjs";
|
|
6
6
|
import { getLogger } from "@logtape/logtape";
|
|
7
7
|
import { curry } from "es-toolkit";
|
|
8
|
-
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, validatePublicUrl } from "@fedify/vocab-runtime";
|
|
8
|
+
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, resolveDocumentLoaderTimeout, validatePublicUrl, withDocumentLoaderTimeout } from "@fedify/vocab-runtime";
|
|
9
9
|
//#region src/utils/docloader.ts
|
|
10
10
|
const logger = getLogger([
|
|
11
11
|
"fedify",
|
|
@@ -19,15 +19,19 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
19
19
|
* the fetched documents.
|
|
20
20
|
* At most 20 HTTP redirects and alternate document links are followed in total
|
|
21
21
|
* per call. Revisiting a URL within that chain throws a {@link FetchError}.
|
|
22
|
+
* Each call, including its double-knocking retries, times out after
|
|
23
|
+
* 10 seconds by default; see {@link DocumentLoaderFactoryOptions.timeout}.
|
|
22
24
|
* @param identity The identity to get the document loader for.
|
|
23
25
|
* The actor's key pair.
|
|
24
26
|
* @param options The options for the document loader.
|
|
25
27
|
* @returns The authenticated document loader.
|
|
26
28
|
* @throws {TypeError} If the key is invalid or unsupported.
|
|
29
|
+
* @throws {RangeError} If the `timeout` option is invalid.
|
|
27
30
|
* @since 0.4.0
|
|
28
31
|
*/
|
|
29
|
-
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, tracerProvider } = {}) {
|
|
32
|
+
function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, timeout, tracerProvider } = {}) {
|
|
30
33
|
validateCryptoKey(identity.privateKey);
|
|
34
|
+
const resolvedTimeout = resolveDocumentLoaderTimeout(timeout);
|
|
31
35
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
32
36
|
options?.signal?.throwIfAborted();
|
|
33
37
|
let currentUrl = new URL(url).href;
|
|
@@ -53,27 +57,31 @@ function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedi
|
|
|
53
57
|
currentUrl = nextUrl;
|
|
54
58
|
}
|
|
55
59
|
});
|
|
60
|
+
options?.signal?.throwIfAborted();
|
|
56
61
|
return getRemoteDocument(currentUrl, response, (alternateUrl) => {
|
|
57
62
|
follow(alternateUrl);
|
|
58
63
|
return load(alternateUrl, options, redirected, visited);
|
|
59
64
|
}, options);
|
|
60
65
|
}
|
|
61
66
|
async function validateUrl(url, options) {
|
|
62
|
-
if (!allowPrivateAddress)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
url,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
url,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
if (!allowPrivateAddress) {
|
|
68
|
+
try {
|
|
69
|
+
await validatePublicUrl(url);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (error instanceof UrlError) if (error.reason === "dns") logger.debug("DNS lookup failed for {url}", {
|
|
72
|
+
url,
|
|
73
|
+
error
|
|
74
|
+
});
|
|
75
|
+
else logger[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
76
|
+
url,
|
|
77
|
+
error
|
|
78
|
+
});
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
options?.signal?.throwIfAborted();
|
|
74
82
|
}
|
|
75
83
|
}
|
|
76
|
-
return (url, options) => load(url, options);
|
|
84
|
+
return withDocumentLoaderTimeout((url, options) => load(url, options), resolvedTimeout);
|
|
77
85
|
}
|
|
78
86
|
//#endregion
|
|
79
87
|
export { getAuthenticatedDocumentLoader as t };
|
|
@@ -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-0onlMY4u.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";
|
|
@@ -5,7 +5,8 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
6
6
|
import { t as assertThrows } from "../assert_throws-BYITOvPO.mjs";
|
|
7
7
|
import "../std__assert-DvMDRPes.mjs";
|
|
8
|
-
import {
|
|
8
|
+
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
9
|
+
import { n as normalizeCircuitBreakerOptions, r as parseCircuitBreakerKvState, t as CircuitBreaker } from "../circuit-breaker-XJ53md4S.mjs";
|
|
9
10
|
import { t as markCircuitBreakerLegacySweepDone } from "../circuit-breaker-test-utils-DW6YC_Pe.mjs";
|
|
10
11
|
import { test } from "@fedify/fixture";
|
|
11
12
|
//#region src/federation/circuit-breaker.test.ts
|
|
@@ -26,6 +27,54 @@ var CountingCasKvStore = class extends MemoryKvStore {
|
|
|
26
27
|
return super.cas(key, expectedValue, newValue, options);
|
|
27
28
|
}
|
|
28
29
|
};
|
|
30
|
+
var EncodedCasKvStore = class extends MemoryKvStore {
|
|
31
|
+
async cas(key, expectedValue, newValue, options) {
|
|
32
|
+
const current = await this.get(key);
|
|
33
|
+
if (JSON.stringify(current) !== JSON.stringify(expectedValue)) return false;
|
|
34
|
+
if (newValue === void 0) await this.delete(key);
|
|
35
|
+
else await this.set(key, newValue, options);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
test("CircuitBreaker uses raw encoded CAS expectations", async () => {
|
|
40
|
+
const kv = new EncodedCasKvStore();
|
|
41
|
+
await markCircuitBreakerLegacySweepDone(kv);
|
|
42
|
+
let now = Temporal.Instant.from("2026-05-25T00:00:00Z");
|
|
43
|
+
const circuit = new CircuitBreaker({
|
|
44
|
+
kv,
|
|
45
|
+
prefix: ["_fedify", "circuit"],
|
|
46
|
+
now: () => now,
|
|
47
|
+
options: {
|
|
48
|
+
failureThreshold: 1,
|
|
49
|
+
recoveryDelay: { seconds: 30 }
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const key = [
|
|
53
|
+
"_fedify",
|
|
54
|
+
"circuit",
|
|
55
|
+
"remote.example"
|
|
56
|
+
];
|
|
57
|
+
await circuit.recordFailure("remote.example");
|
|
58
|
+
now = now.add({ seconds: 30 });
|
|
59
|
+
assertEquals((await circuit.beforeSend("remote.example", {})).type, "send");
|
|
60
|
+
assertEquals((await circuit.recordSuccess("remote.example"))?.newState, "closed");
|
|
61
|
+
const oldOrder = {
|
|
62
|
+
state: "half-open",
|
|
63
|
+
failures: ["2026-05-25T00:00:00Z"],
|
|
64
|
+
opened: "2026-05-25T00:00:00Z",
|
|
65
|
+
__fedifyCircuitBreakerStateVersion: 1,
|
|
66
|
+
halfOpened: "2026-05-25T00:00:00Z"
|
|
67
|
+
};
|
|
68
|
+
await kv.set(key, oldOrder);
|
|
69
|
+
assertEquals((await circuit.recordFailure("remote.example"))?.newState, "open");
|
|
70
|
+
await kv.set(key, oldOrder);
|
|
71
|
+
assertEquals((await circuit.recordSuccess("remote.example"))?.newState, "closed");
|
|
72
|
+
await kv.set(key, oldOrder);
|
|
73
|
+
assertEquals((await circuit.beforeSend("remote.example", {})).type, "send");
|
|
74
|
+
await kv.set(key, { __fedifyDeletingCircuitBreakerLegacyState: true });
|
|
75
|
+
await assertRejects(() => circuit.recordFailure("remote.example"));
|
|
76
|
+
assertEquals(await kv.get(key), { __fedifyDeletingCircuitBreakerLegacyState: true });
|
|
77
|
+
});
|
|
29
78
|
var CountingSetKvStore = class {
|
|
30
79
|
#store = new MemoryKvStore();
|
|
31
80
|
keys = [];
|
|
@@ -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 { n as exportJwk } from "../key-
|
|
9
|
+
import { n as exportJwk } from "../key-DA3Yx8p2.mjs";
|
|
10
10
|
import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
|
|
11
|
-
import { a as signObject, d as verifyProof } from "../proof-
|
|
11
|
+
import { a as signObject, d as verifyProof } from "../proof-DrJWKeOl.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-BqqycC0P.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";
|
|
@@ -5,10 +5,10 @@ import { r as createRequestContext, t as createInboxContext } from "../context-B
|
|
|
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 { a as compactJsonLd, m as verifyCompactJsonLd, p as signJsonLd } from "../ld-
|
|
9
|
-
import { l as signRequest } from "../http-
|
|
8
|
+
import { a as compactJsonLd, m as verifyCompactJsonLd, p as signJsonLd } from "../ld-C15yzuY6.mjs";
|
|
9
|
+
import { l as signRequest } from "../http-DQf9Mw4V.mjs";
|
|
10
10
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
11
|
-
import { f as handleInbox, o as createFederation } from "../middleware-
|
|
11
|
+
import { f as handleInbox, o as createFederation } from "../middleware-BqqycC0P.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, CryptographicKey, Multikey, Person, Update } from "@fedify/vocab";
|
|
@@ -331,5 +331,54 @@ test("handleInbox() accepts portable actors with keys at ap: URIs", async () =>
|
|
|
331
331
|
const dispatched = { count: 0 };
|
|
332
332
|
assertEquals([(await handle(await update("ap://did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK/actor"), dispatched)).status, dispatched.count], [401, 0]);
|
|
333
333
|
});
|
|
334
|
+
test("handleInbox() rejects embedded portable actors without valid gateways", async () => {
|
|
335
|
+
const did = await exportDidKey(ed25519PublicKey.publicKey);
|
|
336
|
+
const verificationMethod = `${did}#${did.slice(8)}`;
|
|
337
|
+
const privateJwk = await crypto.subtle.exportKey("jwk", ed25519PrivateKey);
|
|
338
|
+
const actorId = `ap://${did}/actor`;
|
|
339
|
+
const update = async (gateways) => await secureDocument({
|
|
340
|
+
"@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"],
|
|
341
|
+
id: `ap://${did}/activities/update`,
|
|
342
|
+
type: "Update",
|
|
343
|
+
actor: actorId,
|
|
344
|
+
object: await secureDocument({
|
|
345
|
+
"@context": [
|
|
346
|
+
"https://www.w3.org/ns/activitystreams",
|
|
347
|
+
"https://w3id.org/security/data-integrity/v1",
|
|
348
|
+
"https://w3id.org/fep/ef61"
|
|
349
|
+
],
|
|
350
|
+
id: actorId,
|
|
351
|
+
type: "Person",
|
|
352
|
+
inbox: `${actorId}/inbox`,
|
|
353
|
+
outbox: `${actorId}/outbox`,
|
|
354
|
+
...gateways
|
|
355
|
+
}, privateJwk, verificationMethod)
|
|
356
|
+
}, privateJwk, verificationMethod);
|
|
357
|
+
for (const [gateways, status, count] of [
|
|
358
|
+
[
|
|
359
|
+
{ gateways: ["https://gw.example"] },
|
|
360
|
+
202,
|
|
361
|
+
1
|
|
362
|
+
],
|
|
363
|
+
[
|
|
364
|
+
{},
|
|
365
|
+
401,
|
|
366
|
+
0
|
|
367
|
+
],
|
|
368
|
+
[
|
|
369
|
+
{ gateways: [] },
|
|
370
|
+
401,
|
|
371
|
+
0
|
|
372
|
+
],
|
|
373
|
+
[
|
|
374
|
+
{ gateways: ["https://gw.example/path"] },
|
|
375
|
+
400,
|
|
376
|
+
0
|
|
377
|
+
]
|
|
378
|
+
]) {
|
|
379
|
+
const dispatched = { count: 0 };
|
|
380
|
+
assertEquals([(await handle(await update(gateways), dispatched)).status, dispatched.count], [status, count], JSON.stringify(gateways));
|
|
381
|
+
}
|
|
382
|
+
});
|
|
334
383
|
//#endregion
|
|
335
384
|
export {};
|
|
@@ -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 { o as generateCryptoKeyPair } from "../key-
|
|
14
|
-
import { a as compactJsonLd, p as signJsonLd } from "../ld-
|
|
15
|
-
import { a as signObject } from "../proof-
|
|
16
|
-
import { l as signRequest } from "../http-
|
|
13
|
+
import { o as generateCryptoKeyPair } from "../key-DA3Yx8p2.mjs";
|
|
14
|
+
import { a as compactJsonLd, p as signJsonLd } from "../ld-C15yzuY6.mjs";
|
|
15
|
+
import { a as signObject } from "../proof-DrJWKeOl.mjs";
|
|
16
|
+
import { l as signRequest } from "../http-DQf9Mw4V.mjs";
|
|
17
17
|
import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
18
|
-
import { d as handleCustomCollection, f as handleInbox, g as respondWithObjectIfAcceptable, h as respondWithObject, l as handleActor, m as handleOutbox, o as createFederation, p as handleObject, u as handleCollection } from "../middleware-
|
|
18
|
+
import { d as handleCustomCollection, f as handleInbox, g as respondWithObjectIfAcceptable, h as respondWithObject, l as handleActor, m as handleOutbox, o as createFederation, p as handleObject, u as handleCollection } from "../middleware-BqqycC0P.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";
|
|
@@ -10,8 +10,8 @@ import "../std__assert-DvMDRPes.mjs";
|
|
|
10
10
|
import { t as assertStrictEquals } from "../assert_strict_equals-CYvBmkpC.mjs";
|
|
11
11
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
12
12
|
import { r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
|
|
13
|
-
import { o as createFederation, x as parseHashlinkGatewayRequest } from "../middleware-
|
|
14
|
-
import { r as createFederationBuilder } from "../builder-
|
|
13
|
+
import { o as createFederation, x as parseHashlinkGatewayRequest } from "../middleware-BqqycC0P.mjs";
|
|
14
|
+
import { r as createFederationBuilder } from "../builder-0onlMY4u.mjs";
|
|
15
15
|
import { n as RouterError } from "../router-u5O5KCQr.mjs";
|
|
16
16
|
import { Note } from "@fedify/vocab";
|
|
17
17
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|