Major changes: - Restructure plugin architecture: moved federation logic into a dedicated `federation` plugin with Better Auth integration, defining schemas for server registry, key rotation, and blacklist management - Extract encryption layer: new `oven` plugin handles end-to-end encryption (E2EE) with OLM client/server implementations - Reorganize social features: consolidated social endpoints (posts, follows, blocks, mutes) and removed legacy plugin patterns in favor of unified plugin structure - Decentralized key management: refactored `keytools` and `keygen` to support federation key rotation with challenge tokens and health checks Infrastructure updates: - Upgrade dependencies: bump Better Auth to 1.6.9, React to 19.2.5, Next.js to 16.2.3, Tailwind to 4.2.4 - Add cryptographic libraries: @scure/bip39, @signalapp/libsignal-client, @matrix-org/matrix-sdk-crypto-wasm for enhanced federation security - Add utilities: base58-js, uuid for federation identifier handling - Update database schema with new federation tables (serverRegistry, rotateChallengeTokens, blacklistedServers) Minor updates: test suite alignment, storage client cleanup, PostFederationSchema refinements Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
// tests/helpers/db.ts
|
|
import db from "@/lib/db";
|
|
import { blacklistedServers, rotateChallengeTokens, serverRegistry } from "@/lib/db/schema";
|
|
import { eq } from "drizzle-orm";
|
|
import nacl from "tweetnacl";
|
|
|
|
export function generateEnvKeyPair() {
|
|
const signing = nacl.sign.keyPair();
|
|
const encryption = nacl.box.keyPair();
|
|
return {
|
|
signingPublicKey: Buffer.from(signing.publicKey).toString("base64"),
|
|
signingSecretKey: Buffer.from(signing.secretKey).toString("base64"),
|
|
encryptionPublicKey: Buffer.from(encryption.publicKey).toString("base64"),
|
|
encryptionSecretKey: Buffer.from(encryption.secretKey).toString("base64"),
|
|
}
|
|
}
|
|
|
|
export async function seedServer(url: string, publicKey: string, encryptionPublicKey: string) {
|
|
await db.insert(serverRegistry).values({
|
|
id: crypto.randomUUID(),
|
|
url,
|
|
publicKey,
|
|
encryptionPublicKey,
|
|
lastSeen: new Date(),
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
isHealthy: true,
|
|
}).onConflictDoNothing()
|
|
}
|
|
|
|
export async function seedChallenge(overrides?: Partial<typeof rotateChallengeTokens.$inferInsert>) {
|
|
const keys = generateEnvKeyPair()
|
|
const defaults = {
|
|
id: crypto.randomUUID(),
|
|
serverUrl: "https://test-server.com",
|
|
signingOldToken: crypto.randomUUID(),
|
|
signingNewToken: crypto.randomUUID(),
|
|
encryptionOldToken: crypto.randomUUID(),
|
|
encryptionNewToken: crypto.randomUUID(),
|
|
newSigningPublicKey: keys.signingPublicKey,
|
|
newEncryptionPublicKey: keys.encryptionPublicKey,
|
|
attemptsLeft: 3,
|
|
createdAt: new Date(),
|
|
expiresAt: new Date(Date.now() + 1000 * 60 * 5),
|
|
}
|
|
const row = { ...defaults, ...overrides }
|
|
await db.insert(rotateChallengeTokens).values(row)
|
|
return row
|
|
}
|
|
|
|
export async function getServerByUrl(url: string) {
|
|
return (await db.select().from(serverRegistry).where(eq(serverRegistry.url, url)))[0]
|
|
}
|
|
|
|
export async function clearServerRegistry() {
|
|
return await db.delete(serverRegistry)
|
|
}
|
|
|
|
export async function clearRotateChallengeTokens() {
|
|
return await db.delete(rotateChallengeTokens)
|
|
}
|
|
|
|
export async function insertServerEcho(url: string, publicKey: string, encryptionPublicKey: string) {
|
|
await db.insert(serverRegistry).values({
|
|
id: crypto.randomUUID(),
|
|
url,
|
|
publicKey,
|
|
encryptionPublicKey,
|
|
lastSeen: new Date(),
|
|
createdAt: new Date(),
|
|
updatedAt: new Date(),
|
|
isHealthy: true,
|
|
}).onConflictDoNothing()
|
|
}
|
|
|
|
export async function getBlacklistedServer(serverUrl: string) {
|
|
return (await db.select().from(blacklistedServers).where(eq(blacklistedServers.serverUrl, serverUrl)))[0]
|
|
}
|
|
|
|
export async function getChallengesByServerUrl(serverUrl: string) {
|
|
return await db.select().from(rotateChallengeTokens).where(eq(rotateChallengeTokens.serverUrl, serverUrl))
|
|
}
|
|
|
|
export async function clearBlacklist() {
|
|
return await db.delete(blacklistedServers)
|
|
}
|
|
|
|
export async function clearTables() {
|
|
return await Promise.all([
|
|
clearRotateChallengeTokens(),
|
|
clearBlacklist(),
|
|
clearServerRegistry(),
|
|
])
|
|
}
|