courtmitra / packages /domain /src /policies /__tests__ /consent-hash.test.ts
hetanshwaghela's picture
Day 1–2: monorepo scaffold + ingestion→intake→evidence loop
170b9b6
Raw
History Blame
2.14 kB
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);
});
});