import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { deviceApprovalProofBytes } from "../src/device_approval_proof.js"; import { handleRequest } from "../src/index.js"; import { ACCESS_TOKEN, PUBLIC_KEY, WRAPPING_PUBLIC_KEY, signDeviceMessage, testD1Database, testEnv, } from "./devices_test_support.js"; const KEY_ID = "a".repeat(64); const IDEMPOTENCY_KEY = "device-approval-0001"; const SUITE = "HPKE-BASE-X25519-HKDF-SHA256-CHACHA20POLY1305" as const; describe("device approval stored state", () => { it("reports a malformed requester key as a persistence failure", async () => { await assertPersistenceFailure([{ device_id: "device-01", signing_public_key: "invalid" }]); }); it("reports malformed approval metadata as a persistence failure", async () => { await assertPersistenceFailure([ deviceRow(), approvalRow({ device_id: 2 }), ]); }); it("reports an invalid approval status as a persistence failure", async () => { await assertPersistenceFailure([ deviceRow(), approvalRow({ status: "corrupt" }), ]); }); it("treats a valid pending row as an idempotency mismatch", async () => { const d1 = testD1Database({ firstRows: [deviceRow(), approvalRow({ status: "pending", decided_at: null })], }); const response = await approvalRequest(d1); assert.equal(response.status, 403); assert.deepEqual(await response.json(), { error: "device_approval_forbidden" }); assert.deepEqual(d1.batches, []); }); it("reports malformed device state as a persistence failure", async () => { await assertPersistenceFailure([ deviceRow(), null, deviceRow({ device_id: "device-02", approval_status: "pending", created_at: "invalid" }), ]); }); it("reports a missing approved-device key row as a persistence failure", async () => { await assertPersistenceFailure([ deviceRow(), approvalRow(), deviceRow({ device_id: "device-02", wrapping_public_key: null }), ]); }); it("reports malformed envelope state as a persistence failure", async () => { await assertPersistenceFailure([ deviceRow(), approvalRow(), deviceRow({ device_id: "device-02" }), approvalEnvelopeRow({ generation: "1" }), ]); }); }); async function assertPersistenceFailure(firstRows: unknown[]): Promise { const d1 = testD1Database({ firstRows }); const response = await approvalRequest(d1); assert.equal(response.status, 500); assert.deepEqual(await response.json(), { error: "device_approval_failed" }); assert.deepEqual(d1.batches, []); } async function approvalRequest(d1: ReturnType): Promise { return handleRequest( new Request("https://elydora.test/api/devices/approve", { method: "POST", headers: { authorization: `Bearer ${ACCESS_TOKEN}`, "content-type": "application/json", }, body: JSON.stringify(await approvalBody()), }), testEnv({ d1 }), ); } async function approvalBody(): Promise> { const proofCreatedAt = Math.floor(Date.now() / 1000); const envelope = { version: 1 as const, suite: SUITE, encapped_key: "A".repeat(43), ciphertext: "B".repeat(64), }; const action = { deviceId: "device-02", keyId: KEY_ID, generation: 1, envelope, idempotencyKey: IDEMPOTENCY_KEY, proofCreatedAt, }; return { version: 2, device_id: action.deviceId, key_id: action.keyId, generation: action.generation, envelope, idempotency_key: action.idempotencyKey, proof_created_at: proofCreatedAt, approval_proof: await signDeviceMessage( deviceApprovalProofBytes("user-01", "device-01", action), ), }; } function approvalRow(overrides: Record = {}): Record { return { device_id: "device-02", requester_device_id: "device-01", status: "approved", decided_at: 1_780_000_300, ...overrides, }; } function deviceRow(overrides: Record = {}): Record { return { device_id: "device-01", public_key: PUBLIC_KEY, signing_public_key: PUBLIC_KEY, wrapping_public_key: WRAPPING_PUBLIC_KEY, device_name: "MacBook Pro", platform: "macOS", approval_status: "approved", created_at: 1_780_000_000, approved_at: 1_780_000_010, last_active_at: 1_780_000_020, revoked_at: null, ...overrides, }; } function approvalEnvelopeRow(overrides: Record): Record { return { key_id: KEY_ID, generation: 1, recipient_device_id: "device-02", approver_device_id: "device-01", envelope_version: 1, suite: SUITE, encapped_key: "A".repeat(43), ciphertext: "B".repeat(64), idempotency_key: IDEMPOTENCY_KEY, ...overrides, }; }