diff --git a/deno.json b/deno.json
index 316c65b5..75ea3332 100644
--- a/deno.json
+++ b/deno.json
@@ -36,7 +36,8 @@
"@std/media-types": "jsr:@std/media-types@^0.224.1",
"@std/streams": "jsr:@std/streams@^0.223.0",
"comlink": "npm:comlink@^4.4.1",
- "deno-safe-fetch": "https://gitlab.com/soapbox-pub/deno-safe-fetch/-/raw/v1.0.0/load.ts",
+ "deno-safe-fetch/load": "https://gitlab.com/soapbox-pub/deno-safe-fetch/-/raw/v1.0.0/load.ts",
+ "deno-sqlite": "https://raw.githubusercontent.com/alexgleason/deno-sqlite/325f66d8c395e7f6f5ee78ebfa42a0eeea4a942b/mod.ts",
"entities": "npm:entities@^4.5.0",
"fast-stable-stringify": "npm:fast-stable-stringify@^1.0.0",
"formdata-helper": "npm:formdata-helper@^0.3.0",
diff --git a/src/app.ts b/src/app.ts
index 5300b485..be2ce840 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -7,7 +7,6 @@ import { Conf } from '@/config.ts';
import { startFirehose } from '@/firehose.ts';
import { Time } from '@/utils.ts';
-import { actorController } from '@/controllers/activitypub/actor.ts';
import {
accountController,
accountLookupController,
@@ -77,10 +76,8 @@ import {
} from '@/controllers/api/timelines.ts';
import { trendingTagsController } from '@/controllers/api/trends.ts';
import { indexController } from '@/controllers/site.ts';
-import { hostMetaController } from '@/controllers/well-known/host-meta.ts';
import { nodeInfoController, nodeInfoSchemaController } from '@/controllers/well-known/nodeinfo.ts';
import { nostrController } from '@/controllers/well-known/nostr.ts';
-import { webfingerController } from '@/controllers/well-known/webfinger.ts';
import { auth98Middleware, requireProof, requireRole } from '@/middleware/auth98Middleware.ts';
import { cacheMiddleware } from '@/middleware/cacheMiddleware.ts';
import { cspMiddleware } from '@/middleware/cspMiddleware.ts';
@@ -137,13 +134,9 @@ app.use(
storeMiddleware,
);
-app.get('/.well-known/webfinger', webfingerController);
-app.get('/.well-known/host-meta', hostMetaController);
app.get('/.well-known/nodeinfo', nodeInfoController);
app.get('/.well-known/nostr.json', nostrController);
-app.get('/users/:username', actorController);
-
app.get('/nodeinfo/:version', nodeInfoSchemaController);
app.get('/api/v1/instance', cacheMiddleware({ cacheName: 'web', expires: Time.minutes(5) }), instanceController);
diff --git a/src/controllers/activitypub/actor.ts b/src/controllers/activitypub/actor.ts
deleted file mode 100644
index 19f5f100..00000000
--- a/src/controllers/activitypub/actor.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { getAuthor } from '@/queries.ts';
-import { activityJson } from '@/utils/api.ts';
-import { renderActor } from '@/views/activitypub/actor.ts';
-import { localNip05Lookup } from '@/utils/nip05.ts';
-
-import type { AppContext, AppController } from '@/app.ts';
-
-const actorController: AppController = async (c) => {
- const username = c.req.param('username');
- const { signal } = c.req.raw;
-
- const pointer = await localNip05Lookup(c.get('store'), username);
- if (!pointer) return notFound(c);
-
- const event = await getAuthor(pointer.pubkey, { signal });
- if (!event) return notFound(c);
-
- const actor = await renderActor(event, username);
- if (!actor) return notFound(c);
-
- return activityJson(c, actor);
-};
-
-function notFound(c: AppContext) {
- return c.json({ error: 'Not found' }, 404);
-}
-
-export { actorController };
diff --git a/src/controllers/well-known/host-meta.ts b/src/controllers/well-known/host-meta.ts
deleted file mode 100644
index 85da11bf..00000000
--- a/src/controllers/well-known/host-meta.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Conf } from '@/config.ts';
-
-import type { AppController } from '@/app.ts';
-
-/** https://datatracker.ietf.org/doc/html/rfc6415 */
-const hostMetaController: AppController = (c) => {
- const template = Conf.local('/.well-known/webfinger?resource={uri}');
-
- c.header('content-type', 'application/xrd+xml');
-
- return c.body(
- `
-
-
-
-`,
- );
-};
-
-export { hostMetaController };
diff --git a/src/controllers/well-known/webfinger.ts b/src/controllers/well-known/webfinger.ts
deleted file mode 100644
index c1c8b815..00000000
--- a/src/controllers/well-known/webfinger.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import { nip19 } from 'nostr-tools';
-import { z } from 'zod';
-
-import { Conf } from '@/config.ts';
-import { localNip05Lookup } from '@/utils/nip05.ts';
-
-import type { AppContext, AppController } from '@/app.ts';
-import type { Webfinger } from '@/schemas/webfinger.ts';
-
-const webfingerQuerySchema = z.object({
- resource: z.string().url(),
-});
-
-const webfingerController: AppController = (c) => {
- const query = webfingerQuerySchema.safeParse(c.req.query());
- if (!query.success) {
- return c.json({ error: 'Bad request', schema: query.error }, 400);
- }
-
- const resource = new URL(query.data.resource);
-
- switch (resource.protocol) {
- case 'acct:': {
- return handleAcct(c, resource);
- }
- default:
- return c.json({ error: 'Unsupported URI scheme' }, 400);
- }
-};
-
-/** Transforms the resource URI into a `[username, domain]` tuple. */
-const acctSchema = z.custom((value) => value instanceof URL)
- .transform((uri) => uri.pathname)
- .pipe(z.string().email('Invalid acct'))
- .transform((acct) => acct.split('@') as [username: string, host: string])
- .refine(([_username, host]) => host === Conf.url.hostname, {
- message: 'Host must be local',
- path: ['resource', 'acct'],
- });
-
-async function handleAcct(c: AppContext, resource: URL): Promise {
- const result = acctSchema.safeParse(resource);
- if (!result.success) {
- return c.json({ error: 'Invalid acct URI', schema: result.error }, 400);
- }
-
- const [username, host] = result.data;
- const pointer = await localNip05Lookup(c.get('store'), username);
-
- if (!pointer) {
- return c.json({ error: 'Not found' }, 404);
- }
-
- const json = renderWebfinger({
- pubkey: pointer.pubkey,
- username,
- subject: `acct:${username}@${host}`,
- });
-
- c.header('content-type', 'application/jrd+json');
- return c.body(JSON.stringify(json));
-}
-
-interface RenderWebfingerOpts {
- pubkey: string;
- username: string;
- subject: string;
-}
-
-/** Present Nostr user on Webfinger. */
-function renderWebfinger({ pubkey, username, subject }: RenderWebfingerOpts): Webfinger {
- const apId = Conf.local(`/users/${username}`);
-
- return {
- subject,
- aliases: [apId],
- links: [
- {
- rel: 'self',
- type: 'application/activity+json',
- href: apId,
- },
- {
- rel: 'self',
- type: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
- href: apId,
- },
- {
- rel: 'self',
- type: 'application/nostr+json',
- href: `nostr:${nip19.npubEncode(pubkey)}`,
- },
- ],
- };
-}
-
-export { webfingerController };
diff --git a/src/deps.ts b/src/deps.ts
deleted file mode 100644
index ae960349..00000000
--- a/src/deps.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'deno-safe-fetch';
-export {
- type ParsedSignature,
- pemToPublicKey,
- publicKeyToPem,
- signRequest,
- verifyRequest,
-} from 'https://gitlab.com/soapbox-pub/fedisign/-/raw/v0.2.1/mod.ts';
-export { generateSeededRsa } from 'https://gitlab.com/soapbox-pub/seeded-rsa/-/raw/v1.0.0/mod.ts';
-export {
- DB as Sqlite,
-} from 'https://raw.githubusercontent.com/alexgleason/deno-sqlite/325f66d8c395e7f6f5ee78ebfa42a0eeea4a942b/mod.ts';
diff --git a/src/schemas/webfinger.ts b/src/schemas/webfinger.ts
deleted file mode 100644
index 8c9cf576..00000000
--- a/src/schemas/webfinger.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { z } from 'zod';
-
-const linkSchema = z.object({
- rel: z.string().optional(),
- type: z.string().optional(),
- href: z.string().optional(),
- template: z.string().optional(),
-});
-
-const webfingerSchema = z.object({
- subject: z.string(),
- aliases: z.array(z.string()).catch([]),
- links: z.array(linkSchema),
-});
-
-type Webfinger = z.infer;
-
-export { webfingerSchema };
-export type { Webfinger };
diff --git a/src/server.ts b/src/server.ts
index 4825e99d..f7a33dc0 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -1,3 +1,5 @@
+import 'deno-safe-fetch/load';
+
import '@/precheck.ts';
import '@/sentry.ts';
import '@/nostr-wasm.ts';
diff --git a/src/utils/rsa.ts b/src/utils/rsa.ts
deleted file mode 100644
index 6942c435..00000000
--- a/src/utils/rsa.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import * as secp from '@noble/secp256k1';
-import { LRUCache } from 'lru-cache';
-
-import { Conf } from '@/config.ts';
-import { generateSeededRsa, publicKeyToPem } from '@/deps.ts';
-
-const opts = {
- bits: 2048,
-};
-
-const rsaCache = new LRUCache>({ max: 1000 });
-
-async function buildSeed(pubkey: string): Promise {
- const key = await Conf.cryptoKey;
- const data = new TextEncoder().encode(pubkey);
- const signature = await window.crypto.subtle.sign('HMAC', key, data);
- return secp.etc.bytesToHex(new Uint8Array(signature));
-}
-
-async function getPublicKeyPem(pubkey: string): Promise {
- const cached = await rsaCache.get(pubkey);
- if (cached) return cached;
-
- const seed = await buildSeed(pubkey);
- const { publicKey } = await generateSeededRsa(seed, opts);
- const promise = publicKeyToPem(publicKey);
-
- rsaCache.set(pubkey, promise);
- return promise;
-}
-
-export { getPublicKeyPem };
diff --git a/src/views/activitypub/actor.ts b/src/views/activitypub/actor.ts
deleted file mode 100644
index cfd40ba1..00000000
--- a/src/views/activitypub/actor.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { NSchema as n } from '@nostrify/nostrify';
-
-import { Conf } from '@/config.ts';
-import { getPublicKeyPem } from '@/utils/rsa.ts';
-
-import type { NostrEvent } from '@nostrify/nostrify';
-import type { Actor } from '@/schemas/activitypub.ts';
-
-/** Nostr metadata event to ActivityPub actor. */
-async function renderActor(event: NostrEvent, username: string): Promise {
- const content = n.json().pipe(n.metadata()).catch({}).parse(event.content);
-
- return {
- type: 'Person',
- id: Conf.local(`/users/${username}`),
- name: content?.name || '',
- preferredUsername: username,
- inbox: Conf.local(`/users/${username}/inbox`),
- followers: Conf.local(`/users/${username}/followers`),
- following: Conf.local(`/users/${username}/following`),
- outbox: Conf.local(`/users/${username}/outbox`),
- icon: content.picture
- ? {
- type: 'Image',
- url: content.picture,
- }
- : undefined,
- image: content.banner
- ? {
- type: 'Image',
- url: content.banner,
- }
- : undefined,
- summary: content.about ?? '',
- attachment: [],
- tag: [],
- publicKey: {
- id: Conf.local(`/users/${username}#main-key`),
- owner: Conf.local(`/users/${username}`),
- publicKeyPem: await getPublicKeyPem(event.pubkey),
- },
- endpoints: {
- sharedInbox: Conf.local('/inbox'),
- },
- };
-}
-
-export { renderActor };
diff --git a/src/workers/policy.worker.ts b/src/workers/policy.worker.ts
index 4e4bcae6..d1368bce 100644
--- a/src/workers/policy.worker.ts
+++ b/src/workers/policy.worker.ts
@@ -1,4 +1,4 @@
-import 'deno-safe-fetch';
+import 'deno-safe-fetch/load';
import { NostrEvent, NostrRelayOK, NPolicy } from '@nostrify/nostrify';
import { ReadOnlyPolicy } from '@nostrify/nostrify/policies';
import * as Comlink from 'comlink';
diff --git a/src/workers/trends.worker.ts b/src/workers/trends.worker.ts
index 33fd1a12..74a256b9 100644
--- a/src/workers/trends.worker.ts
+++ b/src/workers/trends.worker.ts
@@ -1,7 +1,7 @@
import { NSchema } from '@nostrify/nostrify';
import * as Comlink from 'comlink';
+import { DB as Sqlite } from 'deno-sqlite';
-import { Sqlite } from '@/deps.ts';
import { hashtagSchema } from '@/schema.ts';
import { generateDateRange, Time } from '@/utils/time.ts';