import { createHash, randomUUID } from "node:crypto"; import { existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from "node:fs"; import { createRequire } from "node:module"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { Readable } from "node:stream"; import type BetterSqlite3 from "better-sqlite3"; import { afterEach, describe, expect, it } from "vitest"; import { HARD_LIMIT_BYTES, ManagedStorage, StorageCapacityError, StorageUnavailableError } from "../../apps/api/src/managed-storage.js"; import { StickerReleaseService } from "../../apps/api/src/sticker-releases.js"; const now = Date.parse("2026-08-03T12:00:00.000Z"); const require = createRequire(resolve("apps/api/package.json")); const Database = require("better-sqlite3") as typeof BetterSqlite3; const png = Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAEklEQVQImWO4E6XxHxkzEBQAANIxHF3ECQOzAAAAAElFTkSuQmCC", "base64"); const webp = Buffer.from("UklGRjoAAABXRUJQVlA4IC4AAADQAQCdASoGAAUAAUAmJaACdLoB+AADsAD+9IiH/pNnibPE2fJI/+Uq8Fjc3wAA", "base64"); const roots: string[] = []; const closeables: Array<{ close(): void }> = []; function filesBelow(path: string): string[] { if (!existsSync(path)) return []; return readdirSync(path, { withFileTypes: true }).flatMap((entry) => { const child = join(path, entry.name); return entry.isDirectory() ? filesBelow(child) : [child]; }); } function evidence(name: string, value: unknown) { const directory = process.env.DADA_EVIDENCE_DIR_WP5_UPL; if (!directory) return; mkdirSync(directory, { recursive: true }); writeFileSync(resolve(directory, name), `${JSON.stringify(value, null, 2)}\n`); } function fixture() { const dataRoot = mkdtempSync(join(tmpdir(), "dada-wp5-05-integration-")); roots.push(dataRoot); mkdirSync(join(dataRoot, "db"), { recursive: true }); const databasePath = join(dataRoot, "db", "dada.sqlite3"); const storage = new ManagedStorage({ dataRoot, databasePath }); const stickers = new StickerReleaseService({ clock: () => now, databasePath, storage }); closeables.push(stickers, storage); return { dataRoot, databasePath, stickers, storage }; } async function upload(stickers: StickerReleaseService, stableId: string, order: number, bytes = png, mimeType: "image/png" | "image/webp" = "image/png") { return stickers.upload({ actorId: randomUUID(), content: Readable.from(bytes), enabled: true, expectedByteSize: bytes.byteLength, expectedMimeType: mimeType, expectedSha256: createHash("sha256").update(bytes).digest("hex"), fileName: mimeType === "image/png" ? `${stableId}.png` : `${stableId}.webp`, idempotencyKey: `upload-${randomUUID()}-${randomUUID()}`, order, part: 25, stableId, }); } afterEach(() => { for (const value of closeables.splice(0).reverse()) value.close(); for (const root of roots.splice(0)) rmSync(root, { force: true, recursive: true }); }); describe("TDD-WP5-UPL-001 upload metering", () => { it("decodes PNG, publishes an immutable release, meters original and thumbnail, and preserves old release reads", async () => { const test = fixture(); const before = { files: filesBelow(join(test.dataRoot, "managed-assets")), state: test.storage.getState() }; const published = await upload(test.stickers, "STK1408", 184); const afterUpload = test.storage.getState(); expect(published.release_version).toBe("asset-20260803.1"); expect(published.item).toMatchObject({ enabled: true, height: 3, mime_type: "image/png", origin: "admin_uploaded", stable_id: "STK1408", width: 4 }); expect(afterUpload.managed_content_bytes).toBe(published.original.byte_size + published.thumbnail.byte_size); expect(test.storage.inspectCounts()).toMatchObject({ active_reservations: 0, managed_files: 2, pending_cleanup: 0 }); expect(filesBelow(join(test.dataRoot, "managed-assets"))).toHaveLength(2); expect(test.stickers.listPublic()).toMatchObject({ count: 1, items: [{ stable_id: "STK1408" }] }); const disabled = test.stickers.update({ actorId: randomUUID(), enabled: false, stableId: "STK1408" }); expect(disabled.release_version).toBe("asset-20260803.2"); expect(test.stickers.listPublic().items).toEqual([]); expect(test.stickers.listPublic(published.release_version).items).toHaveLength(1); expect(test.stickers.readPublicAsset(published.release_version, "STK1408", "original")?.bytes).toEqual(png); expect(test.stickers.readPublicAsset(disabled.release_version, "STK1408", "original")).toBeUndefined(); const audit = new Database(test.databasePath, { readonly: true }); expect(audit.prepare(` SELECT operation_type, target_ref, result FROM admin_operation_logs WHERE operation_type IN ('sticker_release_publish', 'sticker_release_update') ORDER BY occurred_at `).all()).toEqual([ { operation_type: "sticker_release_publish", result: "succeeded", target_ref: published.release_version }, { operation_type: "sticker_release_update", result: "succeeded", target_ref: disabled.release_version }, ]); audit.close(); const auditFailure = new Database(test.databasePath); auditFailure.exec(` CREATE TRIGGER force_sticker_release_audit_failure BEFORE INSERT ON admin_operation_logs WHEN NEW.operation_type = 'sticker_release_update' BEGIN SELECT RAISE(ABORT, 'forced_audit_failure'); END; `); expect(() => test.stickers.update({ actorId: randomUUID(), enabled: true, stableId: "STK1408" })) .toThrow("forced_audit_failure"); expect(test.stickers.adminView()).toMatchObject({ release_version: disabled.release_version, items: [{ enabled: false }] }); auditFailure.close(); evidence("fs-before.json", before); evidence("fs-after.json", { files: filesBelow(join(test.dataRoot, "managed-assets")), state: test.storage.getState() }); evidence("db-diff.json", { releases: test.stickers.inspectCounts(), storage: test.storage.inspectCounts() }); }); it("allows exact equality then blocks full and unavailable storage without partial files or rows", async () => { const sizing = fixture(); const measured = await upload(sizing.stickers, "STK1408", 184); const writeBytes = measured.original.byte_size + measured.thumbnail.byte_size; const exact = fixture(); exact.storage.applyControlledMeasurement(HARD_LIMIT_BYTES - writeBytes); const exactResult = await upload(exact.stickers, "STK1408", 184); expect(exactResult.original.byte_size + exactResult.thumbnail.byte_size).toBe(writeBytes); expect(exact.storage.getState().storage_status).toBe("full"); const filesAtFull = filesBelow(join(exact.dataRoot, "managed-assets")); const countsAtFull = exact.stickers.inspectCounts(); await expect(upload(exact.stickers, "STK1409", 185)).rejects.toBeInstanceOf(StorageCapacityError); expect(filesBelow(join(exact.dataRoot, "managed-assets"))).toEqual(filesAtFull); expect(exact.stickers.inspectCounts()).toEqual(countsAtFull); const unavailable = fixture(); unavailable.storage.setAvailability({ dataRootWritable: false, diskSpaceAvailable: true, sqliteWritable: true }); await expect(upload(unavailable.stickers, "STK1408", 184)).rejects.toBeInstanceOf(StorageUnavailableError); expect(filesBelow(join(unavailable.dataRoot, "managed-assets"))).toEqual([]); expect(unavailable.stickers.inspectCounts()).toEqual({ items: 0, releases: 0, upload_receipts: 0 }); }); it("rejects a forged PNG before release or managed-file commit", async () => { const test = fixture(); const forged = Buffer.concat([png.subarray(0, 8), Buffer.from("not-a-decodable-png")]); await expect(upload(test.stickers, "STK1408", 184, forged)).rejects.toThrow("content_decode_invalid"); expect(test.storage.inspectCounts()).toMatchObject({ active_reservations: 0, managed_files: 0 }); expect(test.stickers.inspectCounts()).toEqual({ items: 0, releases: 0, upload_receipts: 0 }); expect(filesBelow(join(test.dataRoot, "managed-assets"))).toEqual([]); }); it("decodes WebP and rejects stable-ID or part-order conflicts without extra writes", async () => { const test = fixture(); const published = await upload(test.stickers, "STK1408", 184, webp, "image/webp"); expect(published.item).toMatchObject({ height: 5, mime_type: "image/webp", width: 6 }); expect(test.stickers.readPublicAsset(published.release_version, "STK1408", "original")?.bytes).toEqual(webp); const files = filesBelow(join(test.dataRoot, "managed-assets")); const counts = test.stickers.inspectCounts(); await expect(upload(test.stickers, "STK1408", 185)).rejects.toMatchObject({ httpStatus: 409, reason: "sticker_stable_id_conflict" }); await expect(upload(test.stickers, "STK1409", 184)).rejects.toMatchObject({ httpStatus: 409, reason: "sticker_order_conflict" }); expect(filesBelow(join(test.dataRoot, "managed-assets"))).toEqual(files); expect(test.stickers.inspectCounts()).toEqual(counts); }); });