import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { handleRequest } from "../src/index.js"; import { type SensitiveAction, recentDeviceActionProofBytes, recentDeviceActionRequestHash, } from "../src/recent_device_action_proof.js"; import { ACCESS_TOKEN, PUBLIC_KEY, signDeviceMessage, testD1Database, testEnv, } from "./devices_test_support.js"; const NOW = 1_780_001_000; interface ActionCase { action: SensitiveAction; path: string; confirmation: string; idempotencyKey: string; forbiddenError: string; failedError: string; existingEvent: Record; } const ACTIONS: ActionCase[] = [ { action: "sync.reset", path: "/api/sync/reset", confirmation: "delete-cloud-sync-data", idempotencyKey: "sync-reset-security-0001", forbiddenError: "sync_reset_forbidden", failedError: "sync_reset_failed", existingEvent: { actor_device_id: "device-01", outcome: "success", created_at: NOW, }, }, { action: "account.delete", path: "/api/account/delete", confirmation: "delete-elydora-account", idempotencyKey: "account-delete-security-0001", forbiddenError: "account_deletion_forbidden", failedError: "account_deletion_failed", existingEvent: { actor_device_id: "device-01", outcome: "success", subject_id: "2fb6b7445391dae3bf4fb63927132e773d8d00e5963b5270dddecc84e99811fa", created_at: NOW, }, }, ]; describe("destructive action proofs", () => { it("blocks a stolen bearer without the device private key", async () => { for (const action of ACTIONS) { const body = await actionBody(action, NOW); body.action_proof = "0".repeat(128); const response = await actionRequest(action, body, newActionRows(action)); assert.equal(response.status, 403); assert.deepEqual(await response.json(), { error: action.forbiddenError }); } }); it("binds the action, session, and idempotency key", async () => { for (const action of ACTIONS) { for (const changed of ["action", "session", "idempotency"] as const) { const signedAction = changed === "action" ? action.action === "sync.reset" ? "account.delete" : "sync.reset" : action.action; const body = await actionBody( action, NOW, signedAction, changed === "session" ? "session-02" : "session-01", ); if (changed === "idempotency") { body.idempotency_key = `${action.idempotencyKey}-changed`; } const response = await actionRequest(action, body, newActionRows(action)); assert.equal(response.status, 403); assert.deepEqual(await response.json(), { error: action.forbiddenError }); } } }); it("requires freshness for a new destructive action", async () => { for (const action of ACTIONS) { const response = await actionRequest( action, await actionBody(action, NOW - 301), newActionRows(action, true), ); assert.equal(response.status, 403); assert.deepEqual(await response.json(), { error: action.forbiddenError }); } }); it("verifies old proofs for exact idempotent replays without requiring freshness", async () => { for (const action of ACTIONS) { const body = await actionBody(action, NOW - 301); const event = { ...action.existingEvent, ...(action.action === "account.delete" ? { metadata_hash: await requestHash(action, body) } : {}), }; const response = await actionRequest(action, body, replayRows(action, event)); assert.equal(response.status, 200); } }); it("maps a malformed stored signing key to a persistence failure", async () => { for (const action of ACTIONS) { const rows = newActionRows(action); rows[rows.length - 1] = { signing_public_key: "invalid" }; const response = await actionRequest(action, await actionBody(action, NOW), rows); assert.equal(response.status, 500); assert.deepEqual(await response.json(), { error: action.failedError }); } }); it("opens a fresh primary session after a concurrent replay abort", async () => { const action = ACTIONS[0]; assert.ok(action !== undefined); const proofCreatedAt = Math.floor(Date.now() / 1000); const d1 = testD1Database({ firstRows: [ { device_id: "device-01" }, { signing_public_key: PUBLIC_KEY }, null, { objects: 0, changes: 0, snapshots: 0, tombstones: 0 }, action.existingEvent, ], allRows: [], batchError: new Error("UNIQUE constraint failed: audit_events.event_id"), }); const response = await handleRequest( new Request(`https://elydora.test${action.path}`, { method: "POST", headers: { authorization: `Bearer ${ACCESS_TOKEN}`, "content-type": "application/json", }, body: JSON.stringify(await actionBody(action, proofCreatedAt)), }), testEnv({ d1 }), ); assert.equal(response.status, 200); assert.deepEqual(d1.sessionConstraints, ["first-primary", "first-primary"]); }); it("requires the exact timestamp and session for an account deletion replay", async () => { const action = ACTIONS[1]; assert.ok(action !== undefined); const body = await actionBody(action, NOW - 301); const event = { ...action.existingEvent, metadata_hash: await requestHash(action, body), }; const changedTimestamp = { ...body, proof_created_at: NOW - 300 }; const timestampResponse = await actionRequest(action, changedTimestamp, [event]); assert.equal(timestampResponse.status, 400); const d1 = testD1Database({ firstRows: [event], sessionRow: { id: "session-02", userId: "user-01", expiresAt: "2099-01-01T00:00:00.000Z", createdAt: "2026-01-01T00:00:00.000Z", deviceId: "device-01", }, }); const sessionResponse = await handleRequest( new Request(`https://elydora.test${action.path}`, { method: "POST", headers: { authorization: `Bearer ${ACCESS_TOKEN}`, "content-type": "application/json", }, body: JSON.stringify(body), }), testEnv({ d1 }), ); assert.equal(sessionResponse.status, 400); }); }); async function actionRequest( action: ActionCase, body: Record, firstRows: unknown[], ): Promise { return handleRequest( new Request(`https://elydora.test${action.path}`, { method: "POST", headers: { authorization: `Bearer ${ACCESS_TOKEN}`, "content-type": "application/json", }, body: JSON.stringify(body), }), testEnv({ d1: testD1Database({ firstRows }) }), ); } function newActionRows(action: ActionCase, includeEventMiss = false): unknown[] { if (action.action === "account.delete") { return [null, { signing_public_key: PUBLIC_KEY }]; } return [ { device_id: "device-01" }, { signing_public_key: PUBLIC_KEY }, ...(includeEventMiss ? [null] : []), ]; } function replayRows(action: ActionCase, event: Record): unknown[] { return action.action === "account.delete" ? [event] : [{ device_id: "device-01" }, { signing_public_key: PUBLIC_KEY }, event]; } async function actionBody( action: ActionCase, proofCreatedAt: number, signedAction = action.action, signedSessionId = "session-01", ): Promise> { const body = { version: 2, confirmation: action.confirmation, idempotency_key: action.idempotencyKey, proof_created_at: proofCreatedAt, action_proof: "", }; body.action_proof = await signDeviceMessage(recentDeviceActionProofBytes({ action: signedAction, userId: "user-01", sessionId: signedSessionId, deviceId: "device-01", confirmation: body.confirmation, idempotencyKey: body.idempotency_key, proofCreatedAt, })); return body; } function requestHash( action: ActionCase, body: Record, ): Promise { return recentDeviceActionRequestHash({ action: action.action, userId: "user-01", sessionId: "session-01", deviceId: "device-01", confirmation: String(body.confirmation), idempotencyKey: String(body.idempotency_key), proofCreatedAt: Number(body.proof_created_at), actionProof: String(body.action_proof), }); }