import "@js-temporal/polyfill";
import "urlpattern-polyfill";
globalThis.addEventListener = () => {};
import { C as Person, _ as Note, o as Create } from "../vocab-C5EUmVTj.mjs";
import { a as mockDocumentLoader, i as createRequestContext, r as createInboxContext, t as test } from "../testing-BQeTO4ss.mjs";
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
import "../std__assert-2v7gYiZp.mjs";
import { n as assertFalse, t as assertRejects } from "../assert_rejects-CJC9ThS-.mjs";
import { t as assert } from "../assert-DikXweDx.mjs";
import { t as MemoryKvStore } from "../kv-OuT2IU64.mjs";
import { a as createFederation, c as handleCollection, d as handleObject, f as respondWithObject, l as handleCustomCollection, o as acceptsJsonLd, p as respondWithObjectIfAcceptable, s as handleActor, u as handleInbox } from "../middleware-C26Vj2UM.mjs";
import { s as signRequest } from "../http-B7ppDy7F.mjs";
import { a as compactJsonLd, f as signJsonLd } from "../ld-BJtgkkBN.mjs";
import { t as InboxListenerSet } from "../inbox-BtX2yRj2.mjs";
import { t as createTestTracerProvider } from "../otel-D00WjYJ1.mjs";
import { a as rsaPrivateKey3, c as rsaPublicKey3, s as rsaPublicKey2 } from "../keys-BkXWqCAE.mjs";
//#region src/federation/handler.test.ts
test("acceptsJsonLd()", () => {
	assert(acceptsJsonLd(new Request("https://example.com/", { headers: { Accept: "application/activity+json" } })));
	assert(acceptsJsonLd(new Request("https://example.com/", { headers: { Accept: "application/ld+json" } })));
	assert(acceptsJsonLd(new Request("https://example.com/", { headers: { Accept: "application/json" } })));
	assertFalse(acceptsJsonLd(new Request("https://example.com/", { headers: { Accept: "application/ld+json; q=0.5, text/html; q=0.8" } })));
	assertFalse(acceptsJsonLd(new Request("https://example.com/", { headers: { Accept: "application/ld+json; q=0.4, application/xhtml+xml; q=0.9" } })));
});
test("handleActor()", async () => {
	let context = createRequestContext({
		federation: createFederation({ kv: new MemoryKvStore() }),
		data: void 0,
		url: new URL("https://example.com/"),
		getActorUri(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		}
	});
	const actorDispatcher = (ctx, handle) => {
		if (handle !== "someone") return null;
		return new Person({
			id: ctx.getActorUri(handle),
			name: "Someone"
		});
	};
	let onNotFoundCalled = null;
	const onNotFound = (request) => {
		onNotFoundCalled = request;
		return new Response("Not found", { status: 404 });
	};
	let onNotAcceptableCalled = null;
	const onNotAcceptable = (request) => {
		onNotAcceptableCalled = request;
		return new Response("Not acceptable", { status: 406 });
	};
	let onUnauthorizedCalled = null;
	const onUnauthorized = (request) => {
		onUnauthorizedCalled = request;
		return new Response("Unauthorized", { status: 401 });
	};
	let response = await handleActor(context.request, {
		context,
		identifier: "someone",
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	context = createRequestContext({
		...context,
		getActor(handle) {
			return Promise.resolve(actorDispatcher(context, handle));
		}
	});
	response = await handleActor(context.request, {
		context,
		identifier: "someone",
		actorDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 406);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, context.request);
	assertEquals(onUnauthorizedCalled, null);
	onNotAcceptableCalled = null;
	response = await handleActor(context.request, {
		context,
		identifier: "no-one",
		actorDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	context = createRequestContext({
		...context,
		request: new Request(context.url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleActor(context.request, {
		context,
		identifier: "someone",
		actorDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/v1",
			"https://w3id.org/security/data-integrity/v1",
			"https://www.w3.org/ns/did/v1",
			"https://w3id.org/security/multikey/v1",
			{
				alsoKnownAs: {
					"@id": "as:alsoKnownAs",
					"@type": "@id"
				},
				manuallyApprovesFollowers: "as:manuallyApprovesFollowers",
				movedTo: {
					"@id": "as:movedTo",
					"@type": "@id"
				},
				featured: {
					"@id": "toot:featured",
					"@type": "@id"
				},
				featuredTags: {
					"@id": "toot:featuredTags",
					"@type": "@id"
				},
				discoverable: "toot:discoverable",
				indexable: "toot:indexable",
				memorial: "toot:memorial",
				suspended: "toot:suspended",
				toot: "http://joinmastodon.org/ns#",
				schema: "http://schema.org#",
				PropertyValue: "schema:PropertyValue",
				value: "schema:value",
				misskey: "https://misskey-hub.net/ns#",
				_misskey_followedMessage: "misskey:_misskey_followedMessage",
				isCat: "misskey:isCat",
				Emoji: "toot:Emoji"
			}
		],
		id: "https://example.com/users/someone",
		type: "Person",
		name: "Someone"
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	response = await handleActor(context.request, {
		context,
		identifier: "no-one",
		actorDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleActor(context.request, {
		context,
		identifier: "someone",
		actorDispatcher,
		authorizePredicate: (_ctx, _handle, signedKey, signedKeyOwner) => signedKey != null && signedKeyOwner != null,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 401);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, context.request);
	onUnauthorizedCalled = null;
	context = createRequestContext({
		...context,
		getSignedKey: () => Promise.resolve(rsaPublicKey2),
		getSignedKeyOwner: () => Promise.resolve(new Person({}))
	});
	response = await handleActor(context.request, {
		context,
		identifier: "someone",
		actorDispatcher,
		authorizePredicate: (_ctx, _handle, signedKey, signedKeyOwner) => signedKey != null && signedKeyOwner != null,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/v1",
			"https://w3id.org/security/data-integrity/v1",
			"https://www.w3.org/ns/did/v1",
			"https://w3id.org/security/multikey/v1",
			{
				alsoKnownAs: {
					"@id": "as:alsoKnownAs",
					"@type": "@id"
				},
				manuallyApprovesFollowers: "as:manuallyApprovesFollowers",
				movedTo: {
					"@id": "as:movedTo",
					"@type": "@id"
				},
				featured: {
					"@id": "toot:featured",
					"@type": "@id"
				},
				featuredTags: {
					"@id": "toot:featuredTags",
					"@type": "@id"
				},
				discoverable: "toot:discoverable",
				indexable: "toot:indexable",
				memorial: "toot:memorial",
				suspended: "toot:suspended",
				toot: "http://joinmastodon.org/ns#",
				schema: "http://schema.org#",
				PropertyValue: "schema:PropertyValue",
				value: "schema:value",
				misskey: "https://misskey-hub.net/ns#",
				_misskey_followedMessage: "misskey:_misskey_followedMessage",
				isCat: "misskey:isCat",
				Emoji: "toot:Emoji"
			}
		],
		id: "https://example.com/users/someone",
		type: "Person",
		name: "Someone"
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
});
test("handleObject()", async () => {
	let context = createRequestContext({
		federation: createFederation({ kv: new MemoryKvStore() }),
		data: void 0,
		url: new URL("https://example.com/"),
		getObjectUri(_cls, values) {
			return new URL(`https://example.com/users/${values.handle}/notes/${values.id}`);
		}
	});
	const objectDispatcher = (ctx, values) => {
		if (values.handle !== "someone" || values.id !== "123") return null;
		return new Note({
			id: ctx.getObjectUri(Note, values),
			summary: "Hello, world!"
		});
	};
	let onNotFoundCalled = null;
	const onNotFound = (request) => {
		onNotFoundCalled = request;
		return new Response("Not found", { status: 404 });
	};
	let onNotAcceptableCalled = null;
	const onNotAcceptable = (request) => {
		onNotAcceptableCalled = request;
		return new Response("Not acceptable", { status: 406 });
	};
	let onUnauthorizedCalled = null;
	const onUnauthorized = (request) => {
		onUnauthorizedCalled = request;
		return new Response("Unauthorized", { status: 401 });
	};
	let response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "123"
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "123"
		},
		objectDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 406);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, context.request);
	assertEquals(onUnauthorizedCalled, null);
	onNotAcceptableCalled = null;
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "no-one",
			id: "123"
		},
		objectDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "not-exist"
		},
		objectDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	context = createRequestContext({
		...context,
		request: new Request(context.url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "123"
		},
		objectDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				toot: "http://joinmastodon.org/ns#",
				_misskey_quote: "misskey:_misskey_quote",
				fedibird: "http://fedibird.com/ns#",
				misskey: "https://misskey-hub.net/ns#",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone/notes/123",
		summary: "Hello, world!",
		type: "Note"
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "no-one",
			id: "123"
		},
		objectDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "not-exist"
		},
		objectDispatcher,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "123"
		},
		objectDispatcher,
		authorizePredicate: (_ctx, _values, signedKey, signedKeyOwner) => signedKey != null && signedKeyOwner != null,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 401);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, context.request);
	onUnauthorizedCalled = null;
	context = createRequestContext({
		...context,
		getSignedKey: () => Promise.resolve(rsaPublicKey2),
		getSignedKeyOwner: () => Promise.resolve(new Person({}))
	});
	response = await handleObject(context.request, {
		context,
		values: {
			handle: "someone",
			id: "123"
		},
		objectDispatcher,
		authorizePredicate: (_ctx, _values, signedKey, signedKeyOwner) => signedKey != null && signedKeyOwner != null,
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				toot: "http://joinmastodon.org/ns#",
				_misskey_quote: "misskey:_misskey_quote",
				fedibird: "http://fedibird.com/ns#",
				misskey: "https://misskey-hub.net/ns#",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone/notes/123",
		summary: "Hello, world!",
		type: "Note"
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
});
test("handleCollection()", async () => {
	let context = createRequestContext({
		federation: createFederation({ kv: new MemoryKvStore() }),
		data: void 0,
		url: new URL("https://example.com/"),
		getActorUri(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		}
	});
	const dispatcher = (_ctx, handle, cursor) => {
		if (handle !== "someone") return null;
		const items = [
			new Create({ id: new URL("https://example.com/activities/1") }),
			new Create({ id: new URL("https://example.com/activities/2") }),
			new Create({ id: new URL("https://example.com/activities/3") })
		];
		if (cursor != null) {
			const idx = parseInt(cursor);
			return {
				items: [items[idx]],
				nextCursor: idx < items.length - 1 ? (idx + 1).toString() : null,
				prevCursor: idx > 0 ? (idx - 1).toString() : null
			};
		}
		return { items };
	};
	const counter = (_ctx, handle) => handle === "someone" ? 3 : null;
	const firstCursor = (_ctx, handle) => handle === "someone" ? "0" : null;
	const lastCursor = (_ctx, handle) => handle === "someone" ? "2" : null;
	let onNotFoundCalled = null;
	const onNotFound = (request) => {
		onNotFoundCalled = request;
		return new Response("Not found", { status: 404 });
	};
	let onNotAcceptableCalled = null;
	const onNotAcceptable = (request) => {
		onNotAcceptableCalled = request;
		return new Response("Not acceptable", { status: 406 });
	};
	let onUnauthorizedCalled = null;
	const onUnauthorized = (request) => {
		onUnauthorizedCalled = request;
		return new Response("Unauthorized", { status: 401 });
	};
	let response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: { dispatcher },
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 406);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, context.request);
	assertEquals(onUnauthorizedCalled, null);
	onNotAcceptableCalled = null;
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "no-one",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: { dispatcher },
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	context = createRequestContext({
		...context,
		request: new Request(context.url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "no-one",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: { dispatcher },
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: { dispatcher },
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	const createCtx = [
		"https://w3id.org/identity/v1",
		"https://www.w3.org/ns/activitystreams",
		"https://w3id.org/security/data-integrity/v1",
		{
			toot: "http://joinmastodon.org/ns#",
			misskey: "https://misskey-hub.net/ns#",
			fedibird: "http://fedibird.com/ns#",
			ChatMessage: "http://litepub.social/ns#ChatMessage",
			Emoji: "toot:Emoji",
			Hashtag: "as:Hashtag",
			sensitive: "as:sensitive",
			votersCount: {
				"@id": "toot:votersCount",
				"@type": "http://www.w3.org/2001/XMLSchema#nonNegativeInteger"
			},
			_misskey_quote: "misskey:_misskey_quote",
			quoteUri: "fedibird:quoteUri",
			quoteUrl: "as:quoteUrl",
			emojiReactions: {
				"@id": "fedibird:emojiReactions",
				"@type": "@id"
			}
		}
	];
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				toot: "http://joinmastodon.org/ns#",
				misskey: "https://misskey-hub.net/ns#",
				fedibird: "http://fedibird.com/ns#",
				ChatMessage: "http://litepub.social/ns#ChatMessage",
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				votersCount: "toot:votersCount",
				_misskey_quote: "misskey:_misskey_quote",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone",
		type: "OrderedCollection",
		orderedItems: [
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/1"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/2"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/3"
			}
		]
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: {
			dispatcher,
			authorizePredicate: (_ctx, _handle, key, keyOwner) => key != null && keyOwner != null
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 401);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, context.request);
	onUnauthorizedCalled = null;
	context = createRequestContext({
		...context,
		getSignedKey: () => Promise.resolve(rsaPublicKey2),
		getSignedKeyOwner: () => Promise.resolve(new Person({}))
	});
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: {
			dispatcher,
			authorizePredicate: (_ctx, _handle, key, keyOwner) => key != null && keyOwner != null
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				toot: "http://joinmastodon.org/ns#",
				misskey: "https://misskey-hub.net/ns#",
				fedibird: "http://fedibird.com/ns#",
				ChatMessage: "http://litepub.social/ns#ChatMessage",
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				votersCount: "toot:votersCount",
				_misskey_quote: "misskey:_misskey_quote",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone",
		type: "OrderedCollection",
		orderedItems: [
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/1"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/2"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/3"
			}
		]
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: {
			dispatcher,
			counter,
			firstCursor,
			lastCursor
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				toot: "http://joinmastodon.org/ns#",
				misskey: "https://misskey-hub.net/ns#",
				fedibird: "http://fedibird.com/ns#",
				ChatMessage: "http://litepub.social/ns#ChatMessage",
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				votersCount: "toot:votersCount",
				_misskey_quote: "misskey:_misskey_quote",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone",
		type: "OrderedCollection",
		totalItems: 3,
		first: "https://example.com/?cursor=0",
		last: "https://example.com/?cursor=2"
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	let url = new URL("https://example.com/?cursor=0");
	context = createRequestContext({
		...context,
		url,
		request: new Request(url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: {
			dispatcher,
			counter,
			firstCursor,
			lastCursor
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				toot: "http://joinmastodon.org/ns#",
				misskey: "https://misskey-hub.net/ns#",
				fedibird: "http://fedibird.com/ns#",
				ChatMessage: "http://litepub.social/ns#ChatMessage",
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				votersCount: "toot:votersCount",
				_misskey_quote: "misskey:_misskey_quote",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone?cursor=0",
		type: "OrderedCollectionPage",
		partOf: "https://example.com/",
		next: "https://example.com/?cursor=1",
		orderedItems: [{
			"@context": createCtx,
			id: "https://example.com/activities/1",
			type: "Create"
		}]
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	url = new URL("https://example.com/?cursor=2");
	context = createRequestContext({
		...context,
		url,
		request: new Request(url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleCollection(context.request, {
		context,
		name: "collection",
		identifier: "someone",
		uriGetter(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		},
		collectionCallbacks: {
			dispatcher,
			counter,
			firstCursor,
			lastCursor
		},
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				toot: "http://joinmastodon.org/ns#",
				misskey: "https://misskey-hub.net/ns#",
				fedibird: "http://fedibird.com/ns#",
				ChatMessage: "http://litepub.social/ns#ChatMessage",
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				votersCount: "toot:votersCount",
				_misskey_quote: "misskey:_misskey_quote",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/users/someone?cursor=2",
		type: "OrderedCollectionPage",
		partOf: "https://example.com/",
		prev: "https://example.com/?cursor=1",
		orderedItems: [{
			"@context": createCtx,
			id: "https://example.com/activities/3",
			type: "Create"
		}]
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
});
test("handleInbox()", async () => {
	const activity = new Create({
		id: new URL("https://example.com/activities/1"),
		actor: new URL("https://example.com/person2"),
		object: new Note({
			id: new URL("https://example.com/notes/1"),
			attribution: new URL("https://example.com/person2"),
			content: "Hello, world!"
		})
	});
	const unsignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(await activity.toJsonLd())
	});
	const federation = createFederation({ kv: new MemoryKvStore() });
	const unsignedContext = createRequestContext({
		federation,
		request: unsignedRequest,
		url: new URL(unsignedRequest.url),
		data: void 0
	});
	let onNotFoundCalled = null;
	const onNotFound = (request) => {
		onNotFoundCalled = request;
		return new Response("Not found", { status: 404 });
	};
	const actorDispatcher = (_ctx, identifier) => {
		if (identifier !== "someone") return null;
		return new Person({ name: "Someone" });
	};
	const restrictiveContextLoader = async (resource) => {
		const url = new URL(resource).href;
		if (url === "https://www.w3.org/ns/activitystreams" || url === "https://w3id.org/identity/v1") return await mockDocumentLoader(url);
		throw new Error(`Unexpected context: ${url}`);
	};
	const inboxOptions = {
		kv: new MemoryKvStore(),
		kvPrefixes: {
			activityIdempotence: ["_fedify", "activityIdempotence"],
			publicKey: ["_fedify", "publicKey"]
		},
		actorDispatcher,
		onNotFound,
		signatureTimeWindow: { minutes: 5 },
		skipSignatureVerification: false
	};
	let response = await handleInbox(unsignedRequest, {
		recipient: null,
		context: unsignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0
			});
		},
		...inboxOptions,
		actorDispatcher: void 0
	});
	assertEquals(onNotFoundCalled, unsignedRequest);
	assertEquals(response.status, 404);
	onNotFoundCalled = null;
	response = await handleInbox(unsignedRequest, {
		recipient: "nobody",
		context: unsignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0,
				recipient: "nobody"
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, unsignedRequest);
	assertEquals(response.status, 404);
	onNotFoundCalled = null;
	response = await handleInbox(unsignedRequest, {
		recipient: null,
		context: unsignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(response.status, 401);
	response = await handleInbox(unsignedRequest, {
		recipient: "someone",
		context: unsignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0,
				recipient: "someone"
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(response.status, 401);
	const malformedProofCreatedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"],
			id: "https://example.com/activities/invalid-proof-created",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/invalid-proof-created",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			},
			proof: {
				type: "DataIntegrityProof",
				cryptosuite: "eddsa-jcs-2022",
				verificationMethod: "https://example.com/person2#main-key",
				proofPurpose: "assertionMethod",
				created: { "@value": "not-a-date" },
				proofValue: "zLaewdp4H9kqtwyrLatK4cjY5oRHwVcw4gibPSUDYDMhi4M49v8pcYk3ZB6D69dNpAPbUmY8ocuJ3m9KhKJEEg7z"
			}
		})
	});
	const malformedProofCreatedContext = createRequestContext({
		federation,
		request: malformedProofCreatedRequest,
		url: new URL(malformedProofCreatedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: mockDocumentLoader
	});
	response = await handleInbox(malformedProofCreatedRequest, {
		recipient: null,
		context: malformedProofCreatedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedProofCreatedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [400, "Invalid activity."]);
	onNotFoundCalled = null;
	const signedRequest = await signRequest(unsignedRequest.clone(), rsaPrivateKey3, rsaPublicKey3.id);
	const signedContext = createRequestContext({
		federation,
		request: signedRequest,
		url: new URL(signedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader
	});
	response = await handleInbox(signedRequest, {
		recipient: null,
		context: signedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals([response.status, await response.text()], [202, ""]);
	const ldSignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(await signJsonLd({
			"@context": [
				"https://www.w3.org/ns/activitystreams",
				"https://w3id.org/identity/v1",
				"https://w3id.org/security/v1",
				"https://w3id.org/security/data-integrity/v1"
			],
			id: "https://example.com/activities/ld-signed",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/ld-signed",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader }))
	});
	const ldSignedContext = createRequestContext({
		federation,
		request: ldSignedRequest,
		url: new URL(ldSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: restrictiveContextLoader
	});
	response = await handleInbox(ldSignedRequest, {
		recipient: null,
		context: ldSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...ldSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals([response.status, await response.text()], [202, ""]);
	const remoteContextUrl = "https://remote.example/contexts/ext";
	let failRemoteContextOnce = true;
	const flakyContextLoader = async (resource) => {
		const url = new URL(resource).href;
		if (url === remoteContextUrl) {
			if (failRemoteContextOnce) {
				failRemoteContextOnce = false;
				throw new Error(`Unexpected context: ${url}`);
			}
			return {
				contextUrl: null,
				documentUrl: url,
				document: { "@context": { ext: "https://example.com/ext" } }
			};
		}
		return await mockDocumentLoader(url);
	};
	const httpSignedLdBody = {
		"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
		id: "https://example.com/activities/http-signed-ld",
		type: "Create",
		actor: "https://example.com/person2",
		ext: "preserve-me",
		object: {
			id: "https://example.com/notes/http-signed-ld",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		},
		signature: {
			type: "RsaSignature2017",
			creator: rsaPublicKey3.id.href,
			created: "2024-01-01T00:00:00Z",
			signatureValue: "bogus"
		}
	};
	const httpSignedLdRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(httpSignedLdBody)
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const httpSignedLdContext = createRequestContext({
		federation,
		request: httpSignedLdRequest,
		url: new URL(httpSignedLdRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: flakyContextLoader
	});
	response = await handleInbox(httpSignedLdRequest, {
		recipient: null,
		context: httpSignedLdContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...httpSignedLdContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals([response.status, await response.text()], [202, ""]);
	const ldSignedOnlyBody = await signJsonLd({
		"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
		id: "https://example.com/activities/ld-only-transient",
		type: "Create",
		actor: "https://example.com/person2",
		ext: "preserve-me",
		object: {
			id: "https://example.com/notes/ld-only-transient",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		}
	}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: async (resource) => {
		const url = new URL(resource).href;
		if (url === remoteContextUrl) return {
			contextUrl: null,
			documentUrl: url,
			document: { "@context": { ext: "https://example.com/ext" } }
		};
		return await mockDocumentLoader(url);
	} });
	const malformedTemporalLdSignedBody = await signJsonLd({
		"@context": "https://www.w3.org/ns/activitystreams",
		id: "https://example.com/activities/ld-only-invalid-published",
		type: "Create",
		actor: "https://example.com/person2",
		published: { "@value": "not-a-date" },
		object: {
			id: "https://example.com/notes/ld-only-invalid-published",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		}
	}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader });
	const malformedTemporalLdSignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(malformedTemporalLdSignedBody)
	});
	const malformedTemporalLdSignedContext = createRequestContext({
		federation,
		request: malformedTemporalLdSignedRequest,
		url: new URL(malformedTemporalLdSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: mockDocumentLoader
	});
	response = await handleInbox(malformedTemporalLdSignedRequest, {
		recipient: null,
		context: malformedTemporalLdSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedTemporalLdSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [400, "Invalid activity."]);
	const malformedClosedLdSignedBody = await signJsonLd({
		"@context": "https://www.w3.org/ns/activitystreams",
		id: "https://example.com/questions/ld-only-invalid-closed",
		type: "Question",
		closed: "2024-02-31T00:00:00Z"
	}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader });
	const malformedClosedLdSignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(malformedClosedLdSignedBody)
	});
	const malformedClosedLdSignedContext = createRequestContext({
		federation,
		request: malformedClosedLdSignedRequest,
		url: new URL(malformedClosedLdSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: mockDocumentLoader
	});
	response = await handleInbox(malformedClosedLdSignedRequest, {
		recipient: null,
		context: malformedClosedLdSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedClosedLdSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [400, "Invalid activity."]);
	const malformedIriHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": "https://www.w3.org/ns/activitystreams",
			id: "http://[",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-invalid-iri",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const malformedIriHttpSignedContext = createRequestContext({
		federation,
		request: malformedIriHttpSignedRequest,
		url: new URL(malformedIriHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: mockDocumentLoader
	});
	response = await handleInbox(malformedIriHttpSignedRequest, {
		recipient: null,
		context: malformedIriHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedIriHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [400, "Invalid activity."]);
	const ldSignedOnlyRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(ldSignedOnlyBody)
	});
	const ldSignedOnlyContext = createRequestContext({
		federation,
		request: ldSignedOnlyRequest,
		url: new URL(ldSignedOnlyRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) throw new Error(`Unexpected context: ${url}`);
			return await mockDocumentLoader(url);
		}
	});
	await assertRejects(() => handleInbox(ldSignedOnlyRequest, {
		recipient: null,
		context: ldSignedOnlyContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...ldSignedOnlyContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	failRemoteContextOnce = true;
	const invalidHttpFallbackRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(ldSignedOnlyBody),
		headers: { Signature: "bogus" }
	});
	const invalidHttpFallbackContext = createRequestContext({
		federation,
		request: invalidHttpFallbackRequest,
		url: new URL(invalidHttpFallbackRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: flakyContextLoader
	});
	await assertRejects(() => handleInbox(invalidHttpFallbackRequest, {
		recipient: null,
		context: invalidHttpFallbackContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...invalidHttpFallbackContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const transientKeyContextUrl = "https://remote.example/contexts/key";
	const transientCreatorUrl = "https://remote.example/keys/transient#main-key";
	const verificationFailureLdSignedBody = await signJsonLd({
		"@context": "https://www.w3.org/ns/activitystreams",
		id: "https://example.com/activities/ld-key-fetch-transient",
		type: "Create",
		actor: "https://example.com/person2",
		object: {
			id: "https://example.com/notes/ld-key-fetch-transient",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		}
	}, rsaPrivateKey3, new URL(transientCreatorUrl), { contextLoader: mockDocumentLoader });
	const verificationFailureLdSignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(verificationFailureLdSignedBody),
		headers: { Signature: "bogus" }
	});
	const verificationFailureLdSignedContext = createRequestContext({
		federation,
		request: verificationFailureLdSignedRequest,
		url: new URL(verificationFailureLdSignedRequest.url),
		data: void 0,
		documentLoader: async (resource) => {
			if (resource === transientCreatorUrl) return {
				contextUrl: null,
				documentUrl: resource,
				document: {
					"@context": [transientKeyContextUrl],
					id: resource
				}
			};
			return await mockDocumentLoader(new URL(resource).href);
		},
		contextLoader: async (resource) => {
			if (resource === transientKeyContextUrl) throw new Error(`Transient key context failure: ${resource}`);
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	response = await handleInbox(verificationFailureLdSignedRequest, {
		recipient: null,
		context: verificationFailureLdSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...verificationFailureLdSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [401, "Failed to verify the request signature."]);
	failRemoteContextOnce = true;
	const deferredMalformedTemporalLdSignedBody = await signJsonLd({
		"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
		id: "https://example.com/activities/deferred-invalid-published",
		type: "Create",
		actor: "https://example.com/person2",
		ext: "preserve-me",
		published: { "@value": "not-a-date" },
		object: {
			id: "https://example.com/notes/deferred-invalid-published",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		}
	}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: async (resource) => {
		const url = new URL(resource).href;
		if (url === remoteContextUrl) return {
			contextUrl: null,
			documentUrl: url,
			document: { "@context": { ext: "https://example.com/ext" } }
		};
		return await mockDocumentLoader(url);
	} });
	const deferredMalformedTemporalLdSignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(deferredMalformedTemporalLdSignedBody),
		headers: { Signature: "bogus" }
	});
	const deferredMalformedTemporalLdSignedContext = createRequestContext({
		federation,
		request: deferredMalformedTemporalLdSignedRequest,
		url: new URL(deferredMalformedTemporalLdSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: flakyContextLoader
	});
	response = await handleInbox(deferredMalformedTemporalLdSignedRequest, {
		recipient: null,
		context: deferredMalformedTemporalLdSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...deferredMalformedTemporalLdSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [400, "Invalid activity."]);
	const malformedLdSignedRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			...ldSignedOnlyBody,
			"@context": ["not a url", "https://www.w3.org/ns/activitystreams"]
		})
	});
	const malformedLdSignedContext = createRequestContext({
		federation,
		request: malformedLdSignedRequest,
		url: new URL(malformedLdSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: mockDocumentLoader
	});
	response = await handleInbox(malformedLdSignedRequest, {
		recipient: null,
		context: malformedLdSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedLdSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals([response.status, await response.text()], [400, "Invalid JSON-LD."]);
	const dualSignedInvalidCreatorRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			...httpSignedLdBody,
			signature: {
				...httpSignedLdBody.signature,
				creator: "not a url"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const dualSignedInvalidCreatorContext = createRequestContext({
		federation,
		request: dualSignedInvalidCreatorRequest,
		url: new URL(dualSignedInvalidCreatorRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: flakyContextLoader
	});
	response = await handleInbox(dualSignedInvalidCreatorRequest, {
		recipient: null,
		context: dualSignedInvalidCreatorContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...dualSignedInvalidCreatorContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals([response.status, await response.text()], [202, ""]);
	const invalidUrlHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-invalid-context",
			type: "Create",
			actor: "https://example.com/person2",
			ext: "preserve-me",
			object: {
				id: "https://example.com/notes/http-signed-invalid-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const invalidUrlHttpSignedContext = createRequestContext({
		federation,
		request: invalidUrlHttpSignedRequest,
		url: new URL(invalidUrlHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) {
				const error = /* @__PURE__ */ new Error(`Transient remote context failure: ${url}`);
				error.name = "jsonld.InvalidUrl";
				error.details = {
					code: "loading remote context failed",
					url
				};
				throw error;
			}
			return await mockDocumentLoader(url);
		}
	});
	await assertRejects(() => handleInbox(invalidUrlHttpSignedRequest, {
		recipient: null,
		context: invalidUrlHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...invalidUrlHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const opaqueContextIdHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["app-context", "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-opaque-context",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-opaque-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const opaqueContextIdHttpSignedContext = createRequestContext({
		federation,
		request: opaqueContextIdHttpSignedRequest,
		url: new URL(opaqueContextIdHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			if (resource === "app-context") {
				const error = /* @__PURE__ */ new Error(`Opaque context backend is unavailable: ${resource}`);
				error.name = "jsonld.InvalidUrl";
				error.details = {
					code: "loading remote context failed",
					url: resource
				};
				throw error;
			}
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	await assertRejects(() => handleInbox(opaqueContextIdHttpSignedRequest, {
		recipient: null,
		context: opaqueContextIdHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...opaqueContextIdHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const opaqueContextTypeErrorHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["app:context", "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-opaque-typeerror",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-opaque-typeerror",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const opaqueContextTypeErrorHttpSignedContext = createRequestContext({
		federation,
		request: opaqueContextTypeErrorHttpSignedRequest,
		url: new URL(opaqueContextTypeErrorHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			if (resource === "app:context") throw new TypeError(`Invalid URL: ${resource}`);
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	await assertRejects(() => handleInbox(opaqueContextTypeErrorHttpSignedRequest, {
		recipient: null,
		context: opaqueContextTypeErrorHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...opaqueContextTypeErrorHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const networkPathContextHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["//cdn.example/ctx", "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-network-path-context",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-network-path-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const networkPathContextHttpSignedContext = createRequestContext({
		federation,
		request: networkPathContextHttpSignedRequest,
		url: new URL(networkPathContextHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			if (resource === "//cdn.example/ctx") {
				const error = /* @__PURE__ */ new Error(`Network-path context backend is unavailable: ${resource}`);
				error.name = "jsonld.InvalidUrl";
				error.details = {
					code: "loading remote context failed",
					url: resource
				};
				throw error;
			}
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	await assertRejects(() => handleInbox(networkPathContextHttpSignedRequest, {
		recipient: null,
		context: networkPathContextHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...networkPathContextHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const malformedNetworkPathContextHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["//[", "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-malformed-network-path-context",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-malformed-network-path-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const malformedNetworkPathContextHttpSignedContext = createRequestContext({
		federation,
		request: malformedNetworkPathContextHttpSignedRequest,
		url: new URL(malformedNetworkPathContextHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			if (resource === "//[") {
				const error = /* @__PURE__ */ new Error(`Malformed network-path context: ${resource}`);
				error.name = "jsonld.InvalidUrl";
				error.details = {
					code: "loading remote context failed",
					url: resource
				};
				throw error;
			}
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	response = await handleInbox(malformedNetworkPathContextHttpSignedRequest, {
		recipient: null,
		context: malformedNetworkPathContextHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedNetworkPathContextHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(response.status, 400);
	const malformedUrlLikeContextHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["http://[", "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-malformed-url-like-context",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-malformed-url-like-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const malformedUrlLikeContextHttpSignedContext = createRequestContext({
		federation,
		request: malformedUrlLikeContextHttpSignedRequest,
		url: new URL(malformedUrlLikeContextHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			if (resource === "http://[") {
				const error = /* @__PURE__ */ new Error(`Invalid remote context URL: ${resource}`);
				error.name = "jsonld.InvalidUrl";
				error.details = {
					code: "loading remote context failed",
					url: resource
				};
				throw error;
			}
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	response = await handleInbox(malformedUrlLikeContextHttpSignedRequest, {
		recipient: null,
		context: malformedUrlLikeContextHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedUrlLikeContextHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(response.status, 400);
	const malformedContextUrlHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": ["not a url", "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-malformed-context",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-malformed-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const malformedContextUrlHttpSignedContext = createRequestContext({
		federation,
		request: malformedContextUrlHttpSignedRequest,
		url: new URL(malformedContextUrlHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			if (resource === "not a url") {
				const error = /* @__PURE__ */ new Error(`Invalid remote context URL: ${resource}`);
				error.name = "jsonld.InvalidUrl";
				error.details = {
					code: "loading remote context failed",
					url: resource
				};
				throw error;
			}
			return await mockDocumentLoader(new URL(resource).href);
		}
	});
	response = await handleInbox(malformedContextUrlHttpSignedRequest, {
		recipient: null,
		context: malformedContextUrlHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...malformedContextUrlHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(response.status, 400);
	const invalidRemoteContextHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-invalid-remote-context",
			type: "Create",
			actor: "https://example.com/person2",
			object: {
				id: "https://example.com/notes/http-signed-invalid-remote-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const invalidRemoteContextHttpSignedContext = createRequestContext({
		federation,
		request: invalidRemoteContextHttpSignedRequest,
		url: new URL(invalidRemoteContextHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) return {
				contextUrl: null,
				documentUrl: url,
				document: [
					"not",
					"an",
					"object"
				]
			};
			return await mockDocumentLoader(url);
		}
	});
	response = await handleInbox(invalidRemoteContextHttpSignedRequest, {
		recipient: null,
		context: invalidRemoteContextHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...invalidRemoteContextHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(response.status, 400);
	const invalidUrlAbsoluteContextHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-invalid-url-context",
			type: "Create",
			actor: "https://example.com/person2",
			ext: "preserve-me",
			object: {
				id: "https://example.com/notes/http-signed-invalid-url-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const invalidUrlAbsoluteContextHttpSignedContext = createRequestContext({
		federation,
		request: invalidUrlAbsoluteContextHttpSignedRequest,
		url: new URL(invalidUrlAbsoluteContextHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) throw new TypeError(`Invalid URL: ${url}`);
			return await mockDocumentLoader(url);
		}
	});
	await assertRejects(() => handleInbox(invalidUrlAbsoluteContextHttpSignedRequest, {
		recipient: null,
		context: invalidUrlAbsoluteContextHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...invalidUrlAbsoluteContextHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const typeErrorHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-typeerror-context",
			type: "Create",
			actor: "https://example.com/person2",
			ext: "preserve-me",
			object: {
				id: "https://example.com/notes/http-signed-typeerror-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const typeErrorHttpSignedContext = createRequestContext({
		federation,
		request: typeErrorHttpSignedRequest,
		url: new URL(typeErrorHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) throw new TypeError(`The remote context host timed out: ${url}`);
			return await mockDocumentLoader(url);
		}
	});
	await assertRejects(() => handleInbox(typeErrorHttpSignedRequest, {
		recipient: null,
		context: typeErrorHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...typeErrorHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const rangeErrorHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-rangeerror-context",
			type: "Create",
			actor: "https://example.com/person2",
			ext: "preserve-me",
			object: {
				id: "https://example.com/notes/http-signed-rangeerror-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const rangeErrorHttpSignedContext = createRequestContext({
		federation,
		request: rangeErrorHttpSignedRequest,
		url: new URL(rangeErrorHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) throw new RangeError(`Temporary remote context cache window exceeded: ${url}`);
			return await mockDocumentLoader(url);
		}
	});
	await assertRejects(() => handleInbox(rangeErrorHttpSignedRequest, {
		recipient: null,
		context: rangeErrorHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...rangeErrorHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	const syntaxErrorHttpSignedRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
			id: "https://example.com/activities/http-signed-syntax-context",
			type: "Create",
			actor: "https://example.com/person2",
			ext: "preserve-me",
			object: {
				id: "https://example.com/notes/http-signed-syntax-context",
				type: "Note",
				attributedTo: "https://example.com/person2",
				content: "Hello, world!"
			}
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const syntaxErrorHttpSignedContext = createRequestContext({
		federation,
		request: syntaxErrorHttpSignedRequest,
		url: new URL(syntaxErrorHttpSignedRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: async (resource) => {
			const url = new URL(resource).href;
			if (url === remoteContextUrl) {
				const error = /* @__PURE__ */ new Error(`Transient syntax failure: ${url}`);
				error.name = "jsonld.SyntaxError";
				error.details = { code: "loading remote context failed" };
				throw error;
			}
			return await mockDocumentLoader(url);
		}
	});
	await assertRejects(() => handleInbox(syntaxErrorHttpSignedRequest, {
		recipient: null,
		context: syntaxErrorHttpSignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...syntaxErrorHttpSignedContext,
				clone: void 0
			});
		},
		...inboxOptions
	}), Error);
	response = await handleInbox(signedRequest, {
		recipient: "someone",
		context: signedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0,
				recipient: "someone"
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals([response.status, await response.text()], [202, ""]);
	response = await handleInbox(unsignedRequest, {
		recipient: null,
		context: unsignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0
			});
		},
		...inboxOptions,
		skipSignatureVerification: true
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(response.status, 202);
	response = await handleInbox(unsignedRequest, {
		recipient: "someone",
		context: unsignedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsignedContext,
				clone: void 0,
				recipient: "someone"
			});
		},
		...inboxOptions,
		skipSignatureVerification: true
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(response.status, 202);
	const unsafeJson = {
		"@context": ["https://www.w3.org/ns/activitystreams", { rev: "@reverse" }],
		id: "https://example.com/activities/unsafe",
		type: "Announce",
		actor: "https://example.com/person2",
		object: "https://example.com/notes/1",
		rev: { object: {
			id: "https://example.com/activities/undo",
			type: "Undo",
			actor: "https://example.com/person2"
		} }
	};
	const unsafeRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(unsafeJson)
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const unsafeContext = createRequestContext({
		federation,
		request: unsafeRequest,
		url: new URL(unsafeRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader
	});
	response = await handleInbox(unsafeRequest, {
		recipient: null,
		context: unsafeContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsafeContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(response.status, 202);
	const unsafeLdRequest = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(await signJsonLd(unsafeJson, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader }))
	});
	const unsafeLdContext = createRequestContext({
		federation,
		request: unsafeLdRequest,
		url: new URL(unsafeLdRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader
	});
	response = await handleInbox(unsafeLdRequest, {
		recipient: null,
		context: unsafeLdContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...unsafeLdContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(response.status, 400);
	const signedInvalidRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify({
			"@context": [
				"https://www.w3.org/ns/activitystreams",
				true,
				23
			],
			type: "Create",
			object: {
				type: "Note",
				content: "Hello, world!"
			},
			actor: "https://example.com/users/alice"
		})
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const signedInvalidContext = createRequestContext({
		federation,
		request: signedInvalidRequest,
		url: new URL(signedInvalidRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader
	});
	response = await handleInbox(signedInvalidRequest, {
		recipient: null,
		context: signedContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...signedInvalidContext,
				clone: void 0
			});
		},
		...inboxOptions
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(response.status, 400);
});
test("handleInbox() preserves the raw signed payload for inboxContextFactory", async () => {
	const federation = createFederation({ kv: new MemoryKvStore() });
	const remoteContextUrl = "https://remote.example/contexts/ext";
	const sourceContextLoader = async (resource) => {
		const url = new URL(resource).href;
		if (url === remoteContextUrl) return {
			contextUrl: null,
			documentUrl: url,
			document: { "@context": { ext: "https://example.com/ext" } }
		};
		return await mockDocumentLoader(url);
	};
	const signed = await signJsonLd({
		"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
		id: "https://example.com/activities/preserve-raw",
		type: "Create",
		actor: "https://example.com/person2",
		ext: "preserve-me",
		object: {
			id: "https://example.com/notes/preserve-raw",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		}
	}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: sourceContextLoader });
	const request = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(signed)
	});
	const context = createRequestContext({
		federation,
		request,
		url: new URL(request.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: sourceContextLoader
	});
	let receivedRaw = null;
	let receivedTyped = null;
	const inboxListeners = new InboxListenerSet();
	inboxListeners.add(Create, (ctx, activity) => {
		receivedRaw = ctx.activity;
		receivedTyped = activity;
	});
	const response = await handleInbox(request, {
		recipient: "someone",
		context,
		inboxContextFactory(recipient, activity, activityId, activityType) {
			return {
				...createInboxContext({
					...context,
					clone: void 0,
					recipient
				}),
				activity,
				activityId,
				activityType
			};
		},
		kv: new MemoryKvStore(),
		kvPrefixes: {
			activityIdempotence: ["_fedify", "activityIdempotence"],
			publicKey: ["_fedify", "publicKey"]
		},
		actorDispatcher: (_ctx, identifier) => identifier === "someone" ? new Person({ name: "Someone" }) : null,
		inboxListeners,
		onNotFound: () => new Response("Not found", { status: 404 }),
		signatureTimeWindow: { minutes: 5 },
		skipSignatureVerification: false
	});
	assertEquals([response.status, await response.text()], [202, ""]);
	assertEquals(receivedRaw, signed);
	const delivered = receivedTyped;
	assert(delivered != null);
	assertEquals(delivered.id?.href, "https://example.com/activities/preserve-raw");
});
test("handleInbox() enqueues normalizedActivity for LD-signed inbox work", async () => {
	const remoteContextUrl = "https://remote.example/contexts/ext";
	const sourceContextLoader = async (resource) => {
		const url = new URL(resource).href;
		if (url === remoteContextUrl) return {
			contextUrl: null,
			documentUrl: url,
			document: { "@context": { ext: "https://example.com/ext" } }
		};
		return await mockDocumentLoader(url);
	};
	let queuedMessage = null;
	const queue = {
		enqueue(message) {
			queuedMessage = message;
			return Promise.resolve();
		},
		async listen() {}
	};
	const federation = createFederation({
		kv: new MemoryKvStore(),
		queue
	});
	const signed = await signJsonLd({
		"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
		id: "https://example.com/activities/enqueued-normalized",
		type: "Create",
		actor: "https://example.com/person2",
		ext: "preserve-me",
		object: {
			id: "https://example.com/notes/enqueued-normalized",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		}
	}, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: sourceContextLoader });
	const request = new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(signed)
	});
	const context = createRequestContext({
		federation,
		request,
		url: new URL(request.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: sourceContextLoader
	});
	const response = await handleInbox(request, {
		recipient: "someone",
		context,
		inboxContextFactory(recipient, activity, activityId, activityType) {
			return {
				...createInboxContext({
					...context,
					clone: void 0,
					recipient
				}),
				activity,
				activityId,
				activityType
			};
		},
		kv: new MemoryKvStore(),
		kvPrefixes: {
			activityIdempotence: ["_fedify", "activityIdempotence"],
			publicKey: ["_fedify", "publicKey"]
		},
		queue,
		actorDispatcher: (_ctx, identifier) => identifier === "someone" ? new Person({ name: "Someone" }) : null,
		onNotFound: () => new Response("Not found", { status: 404 }),
		signatureTimeWindow: { minutes: 5 },
		skipSignatureVerification: false
	});
	assertEquals([response.status, await response.text()], [202, "Activity is enqueued."]);
	const enqueued = queuedMessage;
	assert(enqueued != null);
	const inboxMessage = enqueued;
	assertEquals(inboxMessage.activity, signed);
	assertEquals(inboxMessage.normalizedActivity, await compactJsonLd(signed, sourceContextLoader));
	assertEquals(inboxMessage.ldSignatureVerified, true);
});
test("handleInbox() caches normalizedActivity for queued signature-bearing fallback traffic", async () => {
	const remoteContextUrl = "https://remote.example/contexts/ext";
	let queuedMessage = null;
	const queue = {
		enqueue(message) {
			queuedMessage = message;
			return Promise.resolve();
		},
		async listen() {}
	};
	const federation = createFederation({
		kv: new MemoryKvStore(),
		queue
	});
	const sourceContextLoader = async (resource) => {
		const url = new URL(resource).href;
		if (url === remoteContextUrl) return {
			contextUrl: null,
			documentUrl: url,
			document: { "@context": { ext: "https://example.com/ext" } }
		};
		return await mockDocumentLoader(url);
	};
	const unsignedBody = {
		"@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
		id: "https://example.com/activities/non-lds-queued-signature",
		type: "Create",
		actor: "https://example.com/person2",
		ext: "preserve-me",
		object: {
			id: "https://example.com/notes/non-lds-queued-signature",
			type: "Note",
			attributedTo: "https://example.com/person2",
			content: "Hello, world!"
		},
		signature: {
			type: "RsaSignature2017",
			creator: "not a url",
			created: "2024-09-12T16:50:46Z",
			signatureValue: "Zm9v"
		}
	};
	const request = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(unsignedBody)
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const context = createRequestContext({
		federation,
		request,
		url: new URL(request.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: sourceContextLoader
	});
	const response = await handleInbox(request, {
		recipient: "someone",
		context,
		inboxContextFactory(recipient, activity, activityId, activityType) {
			return {
				...createInboxContext({
					...context,
					clone: void 0,
					recipient
				}),
				activity,
				activityId,
				activityType
			};
		},
		kv: new MemoryKvStore(),
		kvPrefixes: {
			activityIdempotence: ["_fedify", "activityIdempotence"],
			publicKey: ["_fedify", "publicKey"]
		},
		queue,
		actorDispatcher: (_ctx, identifier) => identifier === "someone" ? new Person({ name: "Someone" }) : null,
		onNotFound: () => new Response("Not found", { status: 404 }),
		signatureTimeWindow: { minutes: 5 },
		skipSignatureVerification: false
	});
	assertEquals([response.status, await response.text()], [202, "Activity is enqueued."]);
	if (queuedMessage == null) throw new Error("Inbox message not queued.");
	const inboxMessage = queuedMessage;
	assertEquals(inboxMessage, {
		type: "inbox",
		id: inboxMessage.id,
		baseUrl: "https://example.com",
		activity: unsignedBody,
		normalizedActivity: await compactJsonLd(unsignedBody, sourceContextLoader),
		ldSignatureVerified: false,
		started: inboxMessage.started,
		attempt: 0,
		identifier: "someone",
		traceContext: inboxMessage.traceContext
	});
});
test("respondWithObject()", async () => {
	const response = await respondWithObject(new Note({
		id: new URL("https://example.com/notes/1"),
		content: "Hello, world!"
	}), { contextLoader: mockDocumentLoader });
	assert(response.ok);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				toot: "http://joinmastodon.org/ns#",
				_misskey_quote: "misskey:_misskey_quote",
				fedibird: "http://fedibird.com/ns#",
				misskey: "https://misskey-hub.net/ns#",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/notes/1",
		type: "Note",
		content: "Hello, world!"
	});
});
test("handleInbox() - authentication bypass vulnerability", async () => {
	const federation = createFederation({ kv: new MemoryKvStore() });
	let processedActivity;
	const inboxListeners = new InboxListenerSet();
	inboxListeners.add(Create, (_ctx, activity) => {
		processedActivity = activity;
	});
	const maliciousActivity = new Create({
		id: new URL("https://attacker.example.com/activities/malicious"),
		actor: new URL("https://victim.example.com/users/alice"),
		object: new Note({
			id: new URL("https://attacker.example.com/notes/forged"),
			attribution: new URL("https://victim.example.com/users/alice"),
			content: "This is a forged message from the victim!"
		})
	});
	const maliciousRequest = await signRequest(new Request("https://example.com/", {
		method: "POST",
		body: JSON.stringify(await maliciousActivity.toJsonLd())
	}), rsaPrivateKey3, rsaPublicKey3.id);
	const maliciousContext = createRequestContext({
		request: maliciousRequest,
		url: new URL(maliciousRequest.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		federation
	});
	const actorDispatcher = (_ctx, identifier) => {
		if (identifier !== "someone") return null;
		return new Person({ name: "Someone" });
	};
	const response = await handleInbox(maliciousRequest, {
		recipient: "someone",
		context: maliciousContext,
		inboxContextFactory(_activity) {
			return createInboxContext({
				url: new URL(maliciousRequest.url),
				data: void 0,
				documentLoader: mockDocumentLoader,
				federation,
				recipient: "someone"
			});
		},
		kv: new MemoryKvStore(),
		kvPrefixes: {
			activityIdempotence: ["_fedify", "activityIdempotence"],
			publicKey: ["_fedify", "publicKey"]
		},
		actorDispatcher,
		inboxListeners,
		onNotFound: () => new Response("Not found", { status: 404 }),
		signatureTimeWindow: { minutes: 5 },
		skipSignatureVerification: false
	});
	assertEquals(response.status, 401);
	assertEquals(await response.text(), "The signer and the actor do not match.");
	assertEquals(processedActivity, void 0, `SECURITY VULNERABILITY: Malicious activity with mismatched signature was processed! Activity ID: ${processedActivity?.id?.href}, Claimed actor: ${processedActivity?.actorId?.href}`);
});
test("respondWithObjectIfAcceptable", async () => {
	let request = new Request("https://example.com/", { headers: { Accept: "application/activity+json" } });
	let response = await respondWithObjectIfAcceptable(new Note({
		id: new URL("https://example.com/notes/1"),
		content: "Hello, world!"
	}), request, { contextLoader: mockDocumentLoader });
	assert(response != null);
	assert(response.ok);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": [
			"https://www.w3.org/ns/activitystreams",
			"https://w3id.org/security/data-integrity/v1",
			{
				Emoji: "toot:Emoji",
				Hashtag: "as:Hashtag",
				sensitive: "as:sensitive",
				toot: "http://joinmastodon.org/ns#",
				_misskey_quote: "misskey:_misskey_quote",
				fedibird: "http://fedibird.com/ns#",
				misskey: "https://misskey-hub.net/ns#",
				quoteUri: "fedibird:quoteUri",
				quoteUrl: "as:quoteUrl",
				emojiReactions: {
					"@id": "fedibird:emojiReactions",
					"@type": "@id"
				}
			}
		],
		id: "https://example.com/notes/1",
		type: "Note",
		content: "Hello, world!"
	});
	request = new Request("https://example.com/", { headers: { Accept: "text/html" } });
	response = await respondWithObjectIfAcceptable(new Note({
		id: new URL("https://example.com/notes/1"),
		content: "Hello, world!"
	}), request, { contextLoader: mockDocumentLoader });
	assertEquals(response, null);
});
test("handleCustomCollection()", async () => {
	let context = createRequestContext({
		federation: createFederation({ kv: new MemoryKvStore() }),
		data: void 0,
		url: new URL("https://example.com/")
	});
	const dispatcher = (_ctx, values, cursor) => {
		if (values.handle !== "someone") return null;
		const items = [
			new Create({ id: new URL("https://example.com/activities/1") }),
			new Create({ id: new URL("https://example.com/activities/2") }),
			new Create({ id: new URL("https://example.com/activities/3") })
		];
		if (cursor != null) {
			const idx = parseInt(cursor);
			return {
				items: [items[idx]],
				nextCursor: idx < items.length - 1 ? (idx + 1).toString() : null,
				prevCursor: idx > 0 ? (idx - 1).toString() : null
			};
		}
		return { items };
	};
	const counter = (_ctx, values) => values.handle === "someone" ? 3 : null;
	const firstCursor = (_ctx, values) => values.handle === "someone" ? "0" : null;
	const lastCursor = (_ctx, values) => values.handle === "someone" ? "2" : null;
	const callbacks = {
		dispatcher,
		counter,
		firstCursor,
		lastCursor
	};
	let onNotFoundCalled = null;
	const onNotFound = (request) => {
		onNotFoundCalled = request;
		return new Response("Not found", { status: 404 });
	};
	let onNotAcceptableCalled = null;
	const onNotAcceptable = (request) => {
		onNotAcceptableCalled = request;
		return new Response("Not acceptable", { status: 406 });
	};
	let onUnauthorizedCalled = null;
	const onUnauthorized = (request) => {
		onUnauthorizedCalled = request;
		return new Response("Unauthorized", { status: 401 });
	};
	const errorHandlers = {
		onNotFound,
		onNotAcceptable,
		onUnauthorized
	};
	let response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		...errorHandlers
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: { dispatcher },
		...errorHandlers
	});
	assertEquals(response.status, 406);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, context.request);
	assertEquals(onUnauthorizedCalled, null);
	onNotAcceptableCalled = null;
	context = createRequestContext({
		...context,
		request: new Request(context.url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "no-one" },
		collectionCallbacks: { dispatcher },
		...errorHandlers
	});
	assertEquals(response.status, 404);
	assertEquals(onNotFoundCalled, context.request);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	onNotFoundCalled = null;
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: { dispatcher },
		...errorHandlers
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	const createCtx = [
		"https://w3id.org/identity/v1",
		"https://www.w3.org/ns/activitystreams",
		"https://w3id.org/security/data-integrity/v1",
		{
			toot: "http://joinmastodon.org/ns#",
			misskey: "https://misskey-hub.net/ns#",
			fedibird: "http://fedibird.com/ns#",
			ChatMessage: "http://litepub.social/ns#ChatMessage",
			Emoji: "toot:Emoji",
			Hashtag: "as:Hashtag",
			sensitive: "as:sensitive",
			votersCount: {
				"@id": "toot:votersCount",
				"@type": "http://www.w3.org/2001/XMLSchema#nonNegativeInteger"
			},
			_misskey_quote: "misskey:_misskey_quote",
			quoteUri: "fedibird:quoteUri",
			quoteUrl: "as:quoteUrl",
			emojiReactions: {
				"@id": "fedibird:emojiReactions",
				"@type": "@id"
			}
		}
	];
	const CONTEXT = [
		"https://www.w3.org/ns/activitystreams",
		"https://w3id.org/security/data-integrity/v1",
		{
			toot: "http://joinmastodon.org/ns#",
			misskey: "https://misskey-hub.net/ns#",
			fedibird: "http://fedibird.com/ns#",
			ChatMessage: "http://litepub.social/ns#ChatMessage",
			Emoji: "toot:Emoji",
			Hashtag: "as:Hashtag",
			sensitive: "as:sensitive",
			votersCount: "toot:votersCount",
			_misskey_quote: "misskey:_misskey_quote",
			quoteUri: "fedibird:quoteUri",
			quoteUrl: "as:quoteUrl",
			emojiReactions: {
				"@id": "fedibird:emojiReactions",
				"@type": "@id"
			}
		}
	];
	assertEquals(await response.json(), {
		"@context": CONTEXT,
		id: "https://example.com/",
		type: "Collection",
		items: [
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/1"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/2"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/3"
			}
		]
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: {
			dispatcher,
			authorizePredicate: (_ctx, _values, key, keyOwner) => key != null && keyOwner != null
		},
		...errorHandlers
	});
	assertEquals(response.status, 401);
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, context.request);
	onUnauthorizedCalled = null;
	context = createRequestContext({
		...context,
		getSignedKey: () => Promise.resolve(rsaPublicKey2),
		getSignedKeyOwner: () => Promise.resolve(new Person({}))
	});
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: {
			dispatcher,
			authorizePredicate: (_ctx, _values, key, keyOwner) => key != null && keyOwner != null
		},
		...errorHandlers
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": CONTEXT,
		id: "https://example.com/",
		type: "Collection",
		items: [
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/1"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/2"
			},
			{
				"@context": createCtx,
				type: "Create",
				id: "https://example.com/activities/3"
			}
		]
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: callbacks,
		...errorHandlers
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": CONTEXT,
		id: "https://example.com/",
		type: "Collection",
		totalItems: 3,
		first: "https://example.com/?cursor=0",
		last: "https://example.com/?cursor=2"
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	let url = new URL("https://example.com/?cursor=0");
	context = createRequestContext({
		...context,
		url,
		request: new Request(url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: callbacks,
		...errorHandlers
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": CONTEXT,
		id: "https://example.com/?cursor=0",
		type: "CollectionPage",
		partOf: "https://example.com/",
		next: "https://example.com/?cursor=1",
		items: {
			"@context": createCtx,
			id: "https://example.com/activities/1",
			type: "Create"
		}
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
	url = new URL("https://example.com/?cursor=2");
	context = createRequestContext({
		...context,
		url,
		request: new Request(url, { headers: { Accept: "application/activity+json" } })
	});
	response = await handleCustomCollection(context.request, {
		context,
		name: "custom collection",
		values: { handle: "someone" },
		collectionCallbacks: callbacks,
		...errorHandlers
	});
	assertEquals(response.status, 200);
	assertEquals(response.headers.get("Content-Type"), "application/activity+json");
	assertEquals(await response.json(), {
		"@context": CONTEXT,
		id: "https://example.com/?cursor=2",
		type: "CollectionPage",
		partOf: "https://example.com/",
		prev: "https://example.com/?cursor=1",
		items: {
			"@context": createCtx,
			id: "https://example.com/activities/3",
			type: "Create"
		}
	});
	assertEquals(onNotFoundCalled, null);
	assertEquals(onNotAcceptableCalled, null);
	assertEquals(onUnauthorizedCalled, null);
});
test("handleInbox() records OpenTelemetry span events", async () => {
	const [tracerProvider, exporter] = createTestTracerProvider();
	const kv = new MemoryKvStore();
	const federation = createFederation({
		kv,
		tracerProvider
	});
	const activity = new Create({
		id: new URL("https://example.com/activity"),
		actor: new URL("https://example.com/users/someone"),
		object: new Note({
			id: new URL("https://example.com/note"),
			content: "Hello, world!"
		})
	});
	const signed = await signRequest(new Request("https://example.com/users/someone/inbox", {
		method: "POST",
		headers: { "Content-Type": "application/activity+json" },
		body: JSON.stringify(await activity.toJsonLd())
	}), rsaPrivateKey3, new URL("https://example.com/users/someone#main-key"));
	const context = createRequestContext({
		federation,
		request: signed,
		url: new URL(signed.url),
		data: void 0,
		documentLoader: mockDocumentLoader,
		contextLoader: mockDocumentLoader,
		getActorUri(identifier) {
			return new URL(`https://example.com/users/${identifier}`);
		}
	});
	const actorDispatcher = (ctx, handle) => {
		if (handle !== "someone") return null;
		return new Person({
			id: ctx.getActorUri(handle),
			name: "Someone",
			inbox: new URL("https://example.com/users/someone/inbox"),
			publicKey: rsaPublicKey2
		});
	};
	const listeners = new InboxListenerSet();
	let receivedActivity = null;
	listeners.add(Create, (_ctx, activity) => {
		receivedActivity = activity;
	});
	assertEquals((await handleInbox(signed, {
		recipient: "someone",
		context,
		inboxContextFactory(_activity) {
			return createInboxContext({
				...context,
				clone: void 0
			});
		},
		kv,
		kvPrefixes: {
			activityIdempotence: ["activityIdempotence"],
			publicKey: ["publicKey"]
		},
		actorDispatcher,
		inboxListeners: listeners,
		inboxErrorHandler: void 0,
		onNotFound: (_request) => new Response("Not found", { status: 404 }),
		signatureTimeWindow: false,
		skipSignatureVerification: true,
		tracerProvider
	})).status, 202);
	assert(receivedActivity != null);
	const spans = exporter.getSpans("activitypub.inbox");
	assertEquals(spans.length, 1);
	const span = spans[0];
	assertEquals(span.attributes["fedify.inbox.recipient"], "someone");
	assertEquals(span.attributes["activitypub.activity.id"], "https://example.com/activity");
	const events = exporter.getEvents("activitypub.inbox", "activitypub.activity.received");
	assertEquals(events.length, 1);
	const event = events[0];
	assert(event.attributes != null);
	assertEquals(event.attributes["activitypub.activity.verified"], true);
	assertEquals(event.attributes["http_signatures.verified"], false);
	assert(typeof event.attributes["activitypub.activity.json"] === "string");
	const recordedActivity = JSON.parse(event.attributes["activitypub.activity.json"]);
	assertEquals(recordedActivity.id, "https://example.com/activity");
	assertEquals(recordedActivity.type, "Create");
});
//#endregion
export {};
