@fedify/fedify 2.1.27 → 2.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{assert_rejects-B-qJtC9Z.mjs → assert_rejects-WyYSTDDX.mjs} +2 -20
- package/dist/{assert_throws-4NwKEy2q.mjs → assert_throws-D4DNWrux.mjs} +19 -1
- package/dist/{builder-CKQkP3a2.mjs → builder-Mg2G3qj8.mjs} +3 -3
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{deno-BR2CGENT.mjs → deno-BiYv5RT5.mjs} +1 -1
- package/dist/{docloader-BDHKVMoV.mjs → docloader-DrxXBFL8.mjs} +4 -2
- package/dist/federation/builder.test.mjs +3 -3
- package/dist/federation/collection.test.mjs +1 -1
- package/dist/federation/handler.test.mjs +262 -9
- package/dist/federation/idempotency.test.mjs +3 -3
- package/dist/federation/inbox.test.mjs +25 -2
- package/dist/federation/kv.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +128 -10
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +2 -2
- package/dist/federation/negotiation.test.mjs +2 -2
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/router.test.mjs +2 -3
- package/dist/federation/send.test.mjs +7 -6
- package/dist/federation/temporal.test.mjs +3 -3
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{http-DQVY5EMT.js → http-B3rSb2GQ.js} +104 -10
- package/dist/{http-QzHm1vsW.mjs → http-C1ga9WQu.mjs} +2 -2
- package/dist/{http-CsQRvInz.cjs → http-Cginz7L0.cjs} +103 -9
- package/dist/{inbox-DEXoNgGa.mjs → inbox-BWzL0xMU.mjs} +23 -10
- package/dist/{key-CDIMbgsc.mjs → key-O-ATwIGS.mjs} +104 -10
- package/dist/{kv-cache-cTsPZ49Z.js → kv-cache-8Kg2CHiD.js} +3 -1
- package/dist/{kv-cache-FfmHQljR.cjs → kv-cache-BdylAE9w.cjs} +3 -1
- package/dist/{ld-BpkaBh2H.mjs → ld-C-fCGM-z.mjs} +2 -2
- package/dist/{middleware-DwEVn3gK.js → middleware-41MkquTV.js} +95 -25
- package/dist/{middleware-DVaturw-.mjs → middleware-C9UCWOqw.mjs} +82 -25
- package/dist/{middleware-Bla8jBXk.cjs → middleware-CVRFS7PZ.cjs} +96 -26
- package/dist/{middleware-C9vVE-6R.mjs → middleware-CxgFiKI3.mjs} +1 -1
- package/dist/{middleware-Ddrg18eD.cjs → middleware-VvrqPwHL.cjs} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/client.test.mjs +1 -1
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/nodeinfo/types.test.mjs +2 -2
- package/dist/otel/exporter.test.mjs +1 -1
- package/dist/{owner-DnOwKsK6.mjs → owner-C8IVASD3.mjs} +2 -2
- package/dist/{proof-JfqNWc2E.cjs → proof-BbHMAkPG.cjs} +1 -1
- package/dist/{proof-CShmVLWt.mjs → proof-CUdcBgvg.mjs} +2 -2
- package/dist/{proof-uEay4EIq.js → proof-cGfRPTiV.js} +1 -1
- package/dist/{send-DCg0WblG.mjs → send-BoV4dyVO.mjs} +2 -2
- package/dist/sig/http.test.mjs +5 -5
- package/dist/sig/key.test.mjs +200 -6
- package/dist/sig/ld.test.mjs +4 -4
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +3 -3
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{std__assert-BUOJXi-Z.mjs → std__assert-DflMZha5.mjs} +2 -2
- package/dist/{temporal-C96jXvaM.mjs → temporal-BJlnku_d.mjs} +1 -1
- package/dist/utils/docloader.test.mjs +114 -39
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
- /package/dist/{assert_not_equals--wG9hV7u.mjs → assert_not_equals-BkxW5QJI.mjs} +0 -0
package/dist/sig/proof.test.mjs
CHANGED
|
@@ -2,11 +2,11 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
5
|
-
import "../std__assert-
|
|
6
|
-
import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
|
|
5
|
+
import "../std__assert-DflMZha5.mjs";
|
|
7
6
|
import { n as assertInstanceOf } from "../assert-BhQd8QHP.mjs";
|
|
7
|
+
import { t as assertRejects } from "../assert_rejects-WyYSTDDX.mjs";
|
|
8
8
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-CtZLJq76.mjs";
|
|
9
|
-
import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof-
|
|
9
|
+
import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof-CUdcBgvg.mjs";
|
|
10
10
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
11
11
|
import { Create, DataIntegrityProof, Multikey, Note, Place } from "@fedify/vocab";
|
|
12
12
|
import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
|
|
@@ -2,8 +2,8 @@ import "@js-temporal/polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { a as red, i as buildMessage, l as AssertionError, n as diffStr, r as diff, s as format } from "./assert_equals-Ew3jOFa3.mjs";
|
|
5
|
-
import "./
|
|
6
|
-
import "./
|
|
5
|
+
import "./assert_throws-D4DNWrux.mjs";
|
|
6
|
+
import "./assert_rejects-WyYSTDDX.mjs";
|
|
7
7
|
//#region ../../node_modules/.pnpm/@jsr+std__assert@0.226.0/node_modules/@jsr/std__assert/assert_exists.js
|
|
8
8
|
/**
|
|
9
9
|
* Make an assertion that actual is not null or undefined.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { c as getNormalizationContextLoader } from "./ld-
|
|
4
|
+
import { c as getNormalizationContextLoader } from "./ld-C-fCGM-z.mjs";
|
|
5
5
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
6
6
|
//#region src/federation/temporal.ts
|
|
7
7
|
function isPlainObject(value) {
|
|
@@ -3,11 +3,11 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as esm_default } from "../esm-DVILvP5e.mjs";
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
6
|
-
import "../std__assert-
|
|
7
|
-
import { t as assertRejects } from "../assert_rejects-
|
|
8
|
-
import { l as verifyRequest } from "../http-
|
|
6
|
+
import "../std__assert-DflMZha5.mjs";
|
|
7
|
+
import { t as assertRejects } from "../assert_rejects-WyYSTDDX.mjs";
|
|
8
|
+
import { l as verifyRequest } from "../http-C1ga9WQu.mjs";
|
|
9
9
|
import { i as rsaPrivateKey2 } from "../keys-CtZLJq76.mjs";
|
|
10
|
-
import { t as getAuthenticatedDocumentLoader } from "../docloader-
|
|
10
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-DrxXBFL8.mjs";
|
|
11
11
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
12
|
import { FetchError, UrlError } from "@fedify/vocab-runtime";
|
|
13
13
|
import { configure, reset } from "@logtape/logtape";
|
|
@@ -83,45 +83,50 @@ test("getAuthenticatedDocumentLoader() validates redirects", async (t) => {
|
|
|
83
83
|
});
|
|
84
84
|
esm_default.hardReset();
|
|
85
85
|
});
|
|
86
|
-
test("getAuthenticatedDocumentLoader() cancellation", {
|
|
87
|
-
sanitizeResources: false,
|
|
88
|
-
sanitizeOps: false
|
|
89
|
-
}, async (t) => {
|
|
86
|
+
test("getAuthenticatedDocumentLoader() cancellation", async (t) => {
|
|
90
87
|
esm_default.spyGlobal();
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
try {
|
|
89
|
+
await t.step("document loader cancellation", async () => {
|
|
90
|
+
let responseTimer;
|
|
91
|
+
try {
|
|
92
|
+
esm_default.get("https://example.com/slow-object", () => new Promise((resolve) => {
|
|
93
|
+
responseTimer = setTimeout(() => {
|
|
94
|
+
resolve({
|
|
95
|
+
status: 200,
|
|
96
|
+
headers: { "Content-Type": "application/activity+json" },
|
|
97
|
+
body: {
|
|
98
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
99
|
+
type: "Note",
|
|
100
|
+
content: "Slow response"
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}, 1e3);
|
|
104
|
+
}));
|
|
105
|
+
const loader = getAuthenticatedDocumentLoader({
|
|
106
|
+
keyId: new URL("https://example.com/key2"),
|
|
107
|
+
privateKey: rsaPrivateKey2
|
|
102
108
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
const controller = new AbortController();
|
|
110
|
+
const promise = loader("https://example.com/slow-object", { signal: controller.signal });
|
|
111
|
+
controller.abort();
|
|
112
|
+
await assertRejects(() => promise, Error);
|
|
113
|
+
await assertRejects(() => loader("https://example.com/object", { signal: controller.signal }), Error);
|
|
114
|
+
} finally {
|
|
115
|
+
clearTimeout(responseTimer);
|
|
116
|
+
}
|
|
108
117
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
keyId: new URL("https://example.com/key2"),
|
|
118
|
-
privateKey: rsaPrivateKey2
|
|
118
|
+
await t.step("immediate cancellation", async () => {
|
|
119
|
+
const loader = getAuthenticatedDocumentLoader({
|
|
120
|
+
keyId: new URL("https://example.com/key2"),
|
|
121
|
+
privateKey: rsaPrivateKey2
|
|
122
|
+
});
|
|
123
|
+
const controller = new AbortController();
|
|
124
|
+
controller.abort();
|
|
125
|
+
await assertRejects(() => loader("https://example.com/object", { signal: controller.signal }), Error);
|
|
119
126
|
});
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
124
|
-
esm_default.hardReset();
|
|
127
|
+
} finally {
|
|
128
|
+
esm_default.hardReset();
|
|
129
|
+
}
|
|
125
130
|
});
|
|
126
131
|
test("getAuthenticatedDocumentLoader() bounds JSON after redirects", async () => {
|
|
127
132
|
esm_default.mockGlobal();
|
|
@@ -440,5 +445,75 @@ test("getAuthenticatedDocumentLoader() rejects cancellation before fetching", as
|
|
|
440
445
|
esm_default.hardReset();
|
|
441
446
|
}
|
|
442
447
|
});
|
|
448
|
+
const unsupportedUrls = [
|
|
449
|
+
"ftp://example.com/collection",
|
|
450
|
+
"file:///collection",
|
|
451
|
+
`data:application/ld+json,${encodeURIComponent(JSON.stringify({ id: "https://example.com/data" }))}`
|
|
452
|
+
];
|
|
453
|
+
function isUnsupportedProtocolError(error, url) {
|
|
454
|
+
return error instanceof UrlError && error.message === `Unsupported protocol: ${new URL(url).protocol}` && error.reason === "disallowed";
|
|
455
|
+
}
|
|
456
|
+
async function withFetchStub(respond, callback) {
|
|
457
|
+
const fetched = [];
|
|
458
|
+
const originalFetch = globalThis.fetch;
|
|
459
|
+
globalThis.fetch = ((input, init) => {
|
|
460
|
+
const request = input instanceof Request && init == null ? input : new Request(input, init);
|
|
461
|
+
fetched.push(request);
|
|
462
|
+
return Promise.resolve(respond(request));
|
|
463
|
+
});
|
|
464
|
+
try {
|
|
465
|
+
await callback(fetched);
|
|
466
|
+
} finally {
|
|
467
|
+
globalThis.fetch = originalFetch;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
for (const url of unsupportedUrls) {
|
|
471
|
+
const scheme = new URL(url).protocol;
|
|
472
|
+
const loader = getAuthenticatedDocumentLoader({
|
|
473
|
+
keyId: new URL("https://example.com/key2"),
|
|
474
|
+
privateKey: rsaPrivateKey2
|
|
475
|
+
}, { allowPrivateAddress: true });
|
|
476
|
+
test(`getAuthenticatedDocumentLoader() rejects ${scheme} URLs with private addresses allowed before fetching`, async () => {
|
|
477
|
+
await withFetchStub(() => Response.json({}), async (fetched) => {
|
|
478
|
+
await rejects(loader(url), (e) => isUnsupportedProtocolError(e, url));
|
|
479
|
+
deepStrictEqual(fetched, []);
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
test(`getAuthenticatedDocumentLoader() rejects redirects to ${scheme} URLs with private addresses allowed`, async () => {
|
|
483
|
+
const start = "https://example.com/redirect-to-unsupported";
|
|
484
|
+
await withFetchStub(() => Response.redirect(url, 302), async (fetched) => {
|
|
485
|
+
await rejects(loader(start), (e) => isUnsupportedProtocolError(e, url));
|
|
486
|
+
deepStrictEqual(fetched.map((r) => r.url), [start]);
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
for (const firstSpec of ["rfc9421", "draft-cavage-http-signatures-12"]) test(`getAuthenticatedDocumentLoader() rejects redirects to ${scheme} URLs after signature fallback from ${firstSpec}`, async () => {
|
|
490
|
+
const start = "https://example.com/fallback-redirect-to-unsupported";
|
|
491
|
+
const fallbackLoader = getAuthenticatedDocumentLoader({
|
|
492
|
+
keyId: new URL("https://example.com/key2"),
|
|
493
|
+
privateKey: rsaPrivateKey2
|
|
494
|
+
}, {
|
|
495
|
+
allowPrivateAddress: true,
|
|
496
|
+
specDeterminer: {
|
|
497
|
+
determineSpec: () => firstSpec,
|
|
498
|
+
rememberSpec: () => {}
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
await withFetchStub((request) => request.headers.has("Signature-Input") === (firstSpec === "rfc9421") ? new Response("Unauthorized", { status: 401 }) : Response.redirect(url, 302), async (fetched) => {
|
|
502
|
+
await rejects(fallbackLoader(start), (e) => isUnsupportedProtocolError(e, url));
|
|
503
|
+
deepStrictEqual(fetched.map((r) => r.url), [start, start]);
|
|
504
|
+
deepStrictEqual(fetched.map((r) => r.headers.has("Signature-Input")), [firstSpec === "rfc9421", firstSpec !== "rfc9421"]);
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
for (const html of [false, true]) test(`getAuthenticatedDocumentLoader() rejects ${html ? "HTML" : "Link header"} alternates to ${scheme} URLs with private addresses allowed`, async () => {
|
|
508
|
+
const start = "https://example.com/alternate-to-unsupported";
|
|
509
|
+
await withFetchStub(() => html ? new Response(`<link rel="alternate" type="application/activity+json" href="${url}">`, { headers: { "Content-Type": "text/html" } }) : new Response("", { headers: {
|
|
510
|
+
"Content-Type": "text/plain",
|
|
511
|
+
Link: `<${url}>; rel="alternate"; type="application/activity+json"`
|
|
512
|
+
} }), async (fetched) => {
|
|
513
|
+
await rejects(loader(start), (e) => isUnsupportedProtocolError(e, url));
|
|
514
|
+
deepStrictEqual(fetched.map((r) => r.url), [start]);
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
}
|
|
443
518
|
//#endregion
|
|
444
519
|
export {};
|
package/dist/utils/mod.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
-
const require_kv_cache = require("../kv-cache-
|
|
4
|
+
const require_kv_cache = require("../kv-cache-BdylAE9w.cjs");
|
|
5
5
|
exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
|
|
6
6
|
exports.kvCache = require_kv_cache.kvCache;
|
package/dist/utils/mod.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-
|
|
3
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-8Kg2CHiD.js";
|
|
4
4
|
export { getAuthenticatedDocumentLoader, kvCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/fedify",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.29",
|
|
4
4
|
"description": "An ActivityPub server framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ActivityPub",
|
|
@@ -144,9 +144,9 @@
|
|
|
144
144
|
"uri-template-router": "^1.0.0",
|
|
145
145
|
"url-template": "^3.1.1",
|
|
146
146
|
"urlpattern-polyfill": "^10.1.0",
|
|
147
|
-
"@fedify/vocab": "2.1.
|
|
148
|
-
"@fedify/vocab-runtime": "2.1.
|
|
149
|
-
"@fedify/webfinger": "2.1.
|
|
147
|
+
"@fedify/vocab": "2.1.29",
|
|
148
|
+
"@fedify/vocab-runtime": "2.1.29",
|
|
149
|
+
"@fedify/webfinger": "2.1.29"
|
|
150
150
|
},
|
|
151
151
|
"devDependencies": {
|
|
152
152
|
"@std/assert": "npm:@jsr/std__assert@^0.226.0",
|
|
@@ -158,8 +158,8 @@
|
|
|
158
158
|
"tsx": "^4.19.4",
|
|
159
159
|
"typescript": "^6.0.0",
|
|
160
160
|
"wrangler": "^4.17.0",
|
|
161
|
-
"@fedify/
|
|
162
|
-
"@fedify/
|
|
161
|
+
"@fedify/vocab-tools": "^2.1.29",
|
|
162
|
+
"@fedify/fixture": "2.0.0"
|
|
163
163
|
},
|
|
164
164
|
"scripts": {
|
|
165
165
|
"build:self": "tsdown",
|
|
File without changes
|