/** * DTP-02 / DTP-09 / DTP-26 — schema-version pinning + per-file * consistency invariants + structured error context. */ import { describe, expect, it } from "@suaveplan/testing/runner"; import type { DriveTemplate, FileTemplate, FolderTemplate, } from "../src/index.js"; import { assertFile, assertFolderFileInvariants, type DriveTemplateError, DTP_CODES, TemplateNonceLru, validateTemplate, } from "../src/index.js"; import { DEFAULT_POLICY, makeKeys, signed } from "./_helpers.js"; const baseFile: FileTemplate = { name: "x.bin", fileLocId: "loc-1", fileId: "f".repeat(64), size: 100, totalChunks: 1, chunkSize: 1024, checksum: "blake3:abcd", flags: DEFAULT_POLICY, manifestKey: "manifest:f", manifestSig: new Uint8Array(64).fill(1), }; describe("DTP-02 — schema version pinned to 1", () => { it("schemaVersion ≠ 1 rejected with TEMPLATE_VERSION_UNSUPPORTED", { timeout: 5000, }, () => { const keys = makeKeys(); const tpl = signed({ issuer: keys.publicHex }, keys); // Cast through unknown to bypass the literal-1 type guard. const broken = { ...tpl, schemaVersion: 2 } as unknown as DriveTemplate; try { validateTemplate(broken, { clock: () => Date.now(), nonceLru: new TemplateNonceLru(), }); throw new Error("expected VERSION_UNSUPPORTED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_VERSION_UNSUPPORTED ); } }); }); describe("DTP-09 — per-file consistency invariants", () => { it("chunkSize 164 rejected", { timeout: 5000 }, () => { try { assertFile({ ...baseFile, chunkSize: 164 }, "/x.bin"); throw new Error("expected MALFORMED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_MALFORMED ); expect((err as DriveTemplateError).context).toMatchObject({ file: "/x.bin", }); } }); it("totalChunks insufficient for size rejected", { timeout: 5000 }, () => { try { assertFile( { ...baseFile, totalChunks: 1, chunkSize: 1024, size: 4096 }, "/x.bin" ); throw new Error("expected MALFORMED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_MALFORMED ); } }); it("valid file passes through assertFile (positive path)", { timeout: 5000, }, () => { expect(() => assertFile(baseFile, "/x.bin")).not.toThrow(); }); it("empty manifestKey rejected", { timeout: 5000 }, () => { try { assertFile({ ...baseFile, manifestKey: "" }, "/x.bin"); throw new Error("expected MALFORMED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_MALFORMED ); } }); it("malformed checksum rejected", { timeout: 5000 }, () => { try { assertFile({ ...baseFile, checksum: "md5:abc" }, "/x.bin"); throw new Error("expected MALFORMED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_MALFORMED ); } }); it("empty manifestSig rejected", { timeout: 5000 }, () => { try { assertFile( { ...baseFile, manifestSig: new Uint8Array(0) }, "/x.bin" ); throw new Error("expected MALFORMED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_MALFORMED ); } }); it("nested folder: deepest file's failure surfaces with full path", { timeout: 5000, }, () => { const tree: FolderTemplate = { name: "/", children: [ { name: "photos", children: [ { name: "wedding", children: [{ ...baseFile, chunkSize: 164 }], }, ], }, ], }; try { assertFolderFileInvariants(tree); throw new Error("expected MALFORMED"); } catch (err) { expect((err as DriveTemplateError).code).toBe( DTP_CODES.TEMPLATE_MALFORMED ); const ctx = (err as DriveTemplateError).context as { file: string }; expect(ctx.file).toContain("photos"); expect(ctx.file).toContain("wedding"); } }); });