import assert from "node:assert/strict"; import { mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { test } from "node:test"; import { FILEDROP_CONTRACT_VERSION, FILEDROP_WEBHOOK_SIGNATURE_HEADER, FILEDROP_WEBHOOK_TIMESTAMP_HEADER, createLocalFileDropStorage, createSignedFileDropWebhook, developmentRecipientPublicKey, fileDropEventSchema, fileDropUploadCommitSchema, getActiveDropboxFromEnvironment, parseFileDropWebhook, receiveCiphertextIntakeFromFormData, verifyFileDropWebhookSignature, type FileDropStorage } from "../dist/index.js"; const fixture = JSON.parse(await readFile(new URL("./fixtures/filedrop-v1.json", import.meta.url), "utf8")) as { ciphertext: string; contactEmail: string; contactName: string; dropboxId: string; envelope: Record; languagePair: string; now: string; requestedDeadline: string; routingLabel: string; serviceType: string; uploadId: string; webhookId: string; }; test("discovery is generic and exposes key lifecycle state", async () => { const discovery = await getActiveDropboxFromEnvironment({ FILEDROP_DROPBOX_ID: fixture.dropboxId, FILEDROP_DROPBOX_LABEL: "Fixture secure drop", FILEDROP_RECIPIENT_KEY_ROTATED_AT: fixture.now, FILEDROP_RECIPIENT_KEY_STATUS: "rotating", FILEDROP_RECIPIENT_PUBLIC_KEY_JWK: JSON.stringify(developmentRecipientPublicKey) }); assert.equal(discovery.contractVersion, FILEDROP_CONTRACT_VERSION); assert.equal(discovery.dropboxId, fixture.dropboxId); assert.equal(discovery.label, "Fixture secure drop"); assert.equal(discovery.status, "rotating"); assert.equal(discovery.key.status, "rotating"); assert.equal(discovery.key.rotatedAt, fixture.now); assert.equal(discovery.source, "configured"); }); test("discovery defaults do not contain host-specific branding", async () => { const discovery = await getActiveDropboxFromEnvironment({}); assert.equal(discovery.label, "Secure file drop"); assert.equal(discovery.dropboxId, "default"); assert.equal(discovery.source, "development"); }); test("receiveCiphertextIntakeFromFormData validates filedrop.v1 and supports custom storage", async () => { const saved: Array<{ id: string; manifest: Record; text: string }> = []; const storage: FileDropStorage = { async saveCiphertextUpload(input) { saved.push({ id: input.id, manifest: input.manifest, text: Buffer.from(await input.ciphertext.arrayBuffer()).toString("utf8") }); return { driver: "memory", manifestKey: `memory/${input.id}.json`, storageKey: `memory/${input.id}.enc` }; } }; const received = await receiveCiphertextIntakeFromFormData(createFixtureFormData(), {}, { id: fixture.uploadId, now: new Date(fixture.now), storage }); assert.equal(received.id, fixture.uploadId); assert.equal(received.storageDriver, "memory"); assert.equal(received.storageKey, `memory/${fixture.uploadId}.enc`); assert.equal(received.commit.contractVersion, FILEDROP_CONTRACT_VERSION); assert.equal(received.commit.sender.contactEmail, fixture.contactEmail); assert.equal(received.commit.routing.dropboxId, fixture.dropboxId); assert.equal(received.event.eventType, "filedrop.upload.received"); assert.equal(received.event.storage.driver, "memory"); assert.equal(saved[0]?.text, fixture.ciphertext); assert.doesNotThrow(() => fileDropUploadCommitSchema.parse(received.commit)); assert.doesNotThrow(() => fileDropEventSchema.parse(received.event)); }); test("local storage adapter writes ciphertext and manifest", async () => { const storageDir = await mkdtemp(path.join(tmpdir(), "filedrop-core-")); try { const received = await receiveCiphertextIntakeFromFormData(createFixtureFormData(), {}, { id: fixture.uploadId, now: new Date(fixture.now), storage: createLocalFileDropStorage({ storageDir }) }); const ciphertext = await readFile(path.join(storageDir, received.storageKey), "utf8"); const manifest = JSON.parse(await readFile(path.join(storageDir, received.manifestKey), "utf8")) as { contractVersion: string; commit: { sender: { contactEmail: string } }; }; assert.equal(ciphertext, fixture.ciphertext); assert.equal(manifest.contractVersion, FILEDROP_CONTRACT_VERSION); assert.equal(manifest.commit.sender.contactEmail, fixture.contactEmail); } finally { await rm(storageDir, { force: true, recursive: true }); } }); test("webhook signatures verify and reject tampered payloads", async () => { const received = await receiveCiphertextIntakeFromFormData(createFixtureFormData(), {}, { id: fixture.uploadId, now: new Date(fixture.now), storage: memoryStorage() }); const signed = createSignedFileDropWebhook(received.event, "test-secret", { now: new Date(fixture.now), webhookId: fixture.webhookId }); assert.equal( verifyFileDropWebhookSignature({ body: signed.body, now: new Date(fixture.now), secret: "test-secret", signatureHeader: signed.headers[FILEDROP_WEBHOOK_SIGNATURE_HEADER], timestampHeader: signed.headers[FILEDROP_WEBHOOK_TIMESTAMP_HEADER] }), true ); assert.equal( verifyFileDropWebhookSignature({ body: `${signed.body} `, now: new Date(fixture.now), secret: "test-secret", signatureHeader: signed.headers[FILEDROP_WEBHOOK_SIGNATURE_HEADER], timestampHeader: signed.headers[FILEDROP_WEBHOOK_TIMESTAMP_HEADER] }), false ); const parsed = parseFileDropWebhook({ body: signed.body, now: new Date(fixture.now), secret: "test-secret", signatureHeader: signed.headers[FILEDROP_WEBHOOK_SIGNATURE_HEADER], timestampHeader: signed.headers[FILEDROP_WEBHOOK_TIMESTAMP_HEADER] }); assert.equal(parsed.webhookId, fixture.webhookId); assert.equal(parsed.event.upload.id, fixture.uploadId); }); function createFixtureFormData() { const formData = new FormData(); formData.append("ciphertext", new Blob([fixture.ciphertext], { type: "application/octet-stream" }), "payload.enc"); formData.append("contactEmail", fixture.contactEmail); formData.append("contactName", fixture.contactName); formData.append("dropboxId", fixture.dropboxId); formData.append("envelope", JSON.stringify(fixture.envelope)); formData.append("languagePair", fixture.languagePair); formData.append("requestedDeadline", fixture.requestedDeadline); formData.append("routingLabel", fixture.routingLabel); formData.append("serviceType", fixture.serviceType); return formData; } function memoryStorage(): FileDropStorage { return { async saveCiphertextUpload(input) { return { driver: "memory", manifestKey: `memory/${input.id}.json`, storageKey: `memory/${input.id}.enc` }; } }; }