Spaces:
Running
Running
File size: 2,136 Bytes
170b9b6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import { describe, it, expect } from "vitest";
import type { ConsentPreview } from "@courtmitra/contracts";
import { computeConsentHash, consentHashMatches } from "../consent-hash.js";
const base: ConsentPreview = {
actionType: "send_email",
destination: "grievance@acme.example",
public: false,
body: "Dear Acme,\nPlease refund my order.\nRegards",
attachments: [
{ id: "ev_2", sha256: "bbb", redacted: true },
{ id: "ev_1", sha256: "aaa", redacted: true },
],
piiDisclosed: ["order_id", "name"],
risks: ["company may not reply"],
createdAt: "2026-05-27T10:00:00+05:30",
};
describe("consent hash", () => {
it("is stable regardless of attachment / array ordering and createdAt", () => {
const reordered: ConsentPreview = {
...base,
attachments: [
{ id: "ev_1", sha256: "aaa", redacted: true },
{ id: "ev_2", sha256: "bbb", redacted: true },
],
piiDisclosed: ["name", "order_id"],
createdAt: "2099-01-01T00:00:00+05:30", // volatile — must not affect hash
};
expect(computeConsentHash(base)).toBe(computeConsentHash(reordered));
});
it("normalizes CRLF line endings in the body", () => {
const crlf: ConsentPreview = { ...base, body: base.body.replace(/\n/g, "\r\n") };
expect(computeConsentHash(crlf)).toBe(computeConsentHash(base));
});
it("changes when the body text changes (bait-and-switch guard)", () => {
const harsher: ConsentPreview = { ...base, body: base.body + "\nYou are a SCAM." };
expect(computeConsentHash(harsher)).not.toBe(computeConsentHash(base));
expect(consentHashMatches(computeConsentHash(base), harsher)).toBe(false);
});
it("changes when an attachment hash changes", () => {
const tampered: ConsentPreview = {
...base,
attachments: [
{ id: "ev_1", sha256: "DIFFERENT", redacted: true },
{ id: "ev_2", sha256: "bbb", redacted: true },
],
};
expect(consentHashMatches(computeConsentHash(base), tampered)).toBe(false);
});
it("matches itself", () => {
expect(consentHashMatches(computeConsentHash(base), base)).toBe(true);
});
});
|