Initial reliable release of consent engine

This commit is contained in:
Deyson Thomé
2026-09-02 14:19:05 -03:00
commit 9e1082d47b
22 changed files with 3377 additions and 0 deletions
+525
View File
@@ -0,0 +1,525 @@
import assert from "node:assert/strict";
import { createConsentEngine } from "../../core/consent.js";
import {
isStoragePayload
} from "../../core/storage.js";
import {
isValidCategoriesObject
} from "../../core/categories.js";
let jar = new Map();
let blockWrites = false;
globalThis.location = { protocol: "http:" };
globalThis.document = {};
Object.defineProperty(globalThis.document, "cookie", {
configurable: true,
get() {
return [...jar.entries()]
.map(([key, value]) => `${key}=${value}`)
.join("; ");
},
set(value) {
if (blockWrites) {
return;
}
const parts = value.split(";").map((item) => item.trim());
const [name, raw = ""] = parts[0].split("=");
const maxAge = parts.find((item) => /^Max-Age=/i.test(item));
if (maxAge && maxAge.toLowerCase() === "max-age=0") {
jar.delete(name);
return;
}
jar.set(name, raw);
}
});
function clearEnvironment() {
jar.clear();
blockWrites = false;
}
function make(options = {}) {
return createConsentEngine({
policyVersion: "2026-01",
jurisdiction: "global",
storage: {
name: "cc_reliability",
duration: 180,
path: "/",
sameSite: "Lax"
},
...options
});
}
let passed = 0;
function test(name, fn) {
clearEnvironment();
try {
fn();
passed += 1;
console.log(`PASS ${name}`);
} catch (error) {
console.error(`FAIL ${name}`);
throw error;
}
}
/* -------------------------------------------------------------------------- */
/* Input contract */
/* -------------------------------------------------------------------------- */
test("engine accepts omitted configuration and applies defaults", () => {
const consent = createConsentEngine();
consent.initialize();
const state = consent.getState();
assert.equal(state.hasDecision, false);
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
test("rejects invalid consent category value", () => {
const consent = make();
consent.initialize();
assert.throws(
() => consent.setConsent({
analytics: "invalid"
}),
TypeError
);
});
test("rejects denial of necessary category", () => {
const consent = make();
consent.initialize();
assert.throws(
() => consent.setConsent({
necessary: "denied"
}),
TypeError
);
});
/* -------------------------------------------------------------------------- */
/* State isolation */
/* -------------------------------------------------------------------------- */
test("separate engines do not share state", () => {
const first = make();
const second = make();
first.initialize();
second.initialize();
first.acceptAll();
assert.equal(first.getState().hasDecision, true);
assert.equal(second.getState().hasDecision, false);
});
test("returned state mutation cannot alter internal categories", () => {
const consent = make();
consent.initialize();
const state = consent.getState();
state.categories.analytics = "granted";
state.categories.marketing = "granted";
const current = consent.getState();
assert.equal(current.categories.analytics, "unknown");
assert.equal(current.categories.marketing, "unknown");
});
test("returned state mutation cannot alter jurisdiction", () => {
const consent = make({
jurisdiction: "us-ma"
});
consent.initialize();
const state = consent.getState();
state.jurisdiction = "eu";
assert.equal(
consent.getState().jurisdiction,
"us-ma"
);
});
/* -------------------------------------------------------------------------- */
/* Consent transitions */
/* -------------------------------------------------------------------------- */
test("partial consent does not become a complete decision", () => {
const consent = make();
consent.initialize();
const state = consent.setConsent({
analytics: "granted"
});
assert.equal(state.categories.analytics, "granted");
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.marketing, "unknown");
assert.equal(state.hasDecision, false);
});
test("complete selective consent creates a decision", () => {
const consent = make();
consent.initialize();
const state = consent.setConsent({
preferences: "denied",
analytics: "granted",
marketing: "denied"
});
assert.equal(state.hasDecision, true);
assert.equal(state.categories.necessary, "granted");
});
test("acceptAll is idempotent", () => {
const consent = make();
consent.initialize();
let changed = 0;
let accepted = 0;
consent.on("consent:changed", () => changed++);
consent.on("consent:accepted", () => accepted++);
const first = consent.acceptAll();
const second = consent.acceptAll();
assert.equal(first.hasDecision, true);
assert.equal(second.hasDecision, true);
assert.equal(changed, 1);
assert.equal(accepted, 1);
assert.equal(second.timestamp, first.timestamp);
});
test("rejectAll is idempotent", () => {
const consent = make();
consent.initialize();
let changed = 0;
let rejected = 0;
consent.on("consent:changed", () => changed++);
consent.on("consent:rejected", () => rejected++);
const first = consent.rejectAll();
const second = consent.rejectAll();
assert.equal(first.hasDecision, true);
assert.equal(second.hasDecision, true);
assert.equal(changed, 1);
assert.equal(rejected, 1);
});
test("revoke after acceptance creates the Core-defined denied state", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
let revoked = 0;
consent.on("consent:revoked", () => revoked++);
const first = consent.revoke();
const second = consent.revoke();
assert.equal(first.categories.necessary, "granted");
assert.equal(first.categories.preferences, "denied");
assert.equal(first.categories.analytics, "denied");
assert.equal(first.categories.marketing, "denied");
assert.equal(second.categories.analytics, "denied");
assert.equal(revoked, 1);
});
test("reset returns the engine to undecided state", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
const state = consent.reset();
assert.equal(state.hasDecision, false);
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
test("reset is idempotent", () => {
const consent = make();
consent.initialize();
let reset = 0;
consent.on("consent:reset", () => reset++);
const first = consent.reset();
const second = consent.reset();
assert.equal(first.hasDecision, false);
assert.equal(second.hasDecision, false);
assert.equal(reset, 2);
});
/* -------------------------------------------------------------------------- */
/* GPC */
/* -------------------------------------------------------------------------- */
test("GPC never grants optional consent", () => {
const consent = make();
consent.initialize();
const state = consent.setGpc(true);
assert.equal(state.gpc, true);
assert.equal(state.hasDecision, false);
assert.equal(state.categories.preferences, "unknown");
assert.equal(state.categories.analytics, "unknown");
assert.equal(state.categories.marketing, "unknown");
});
test("GPC can coexist with explicit consent without changing categories", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
const state = consent.setGpc(true);
assert.equal(state.gpc, true);
assert.equal(state.categories.analytics, "granted");
assert.equal(state.categories.marketing, "granted");
});
/* -------------------------------------------------------------------------- */
/* Persistence */
/* -------------------------------------------------------------------------- */
test("accepted consent survives a fresh engine instance", () => {
const first = make();
first.initialize();
first.acceptAll();
const second = make();
second.initialize();
const state = second.getState();
assert.equal(state.source, "storage");
assert.equal(state.hasDecision, true);
assert.equal(state.categories.analytics, "granted");
});
test("rejected consent survives a fresh engine instance", () => {
const first = make();
first.initialize();
first.rejectAll();
const second = make();
second.initialize();
assert.equal(
second.getState().categories.analytics,
"denied"
);
});
test("policy mismatch invalidates persisted consent", () => {
const first = make();
first.initialize();
first.acceptAll();
const second = make({
policyVersion: "2027-01"
});
second.initialize();
assert.equal(second.isComplete(), false);
assert.equal(document.cookie, "");
});
test("invalid persisted payload is ignored and removed", () => {
const bad = {
engineVersion: "invalid",
policyVersion: "2026-01",
timestamp: Date.now(),
categories: {
necessary: "granted",
preferences: "banana",
analytics: "granted",
marketing: "denied"
},
jurisdiction: "global",
gpc: false
};
document.cookie =
`cc_reliability=${encodeURIComponent(JSON.stringify(bad))}; Path=/; SameSite=Lax`;
const consent = make();
consent.initialize();
assert.equal(consent.isComplete(), false);
assert.equal(document.cookie, "");
});
test("storage removal failure does not falsely report reset", () => {
const consent = make();
consent.initialize();
consent.acceptAll();
blockWrites = true;
let resetEvents = 0;
let storageErrors = 0;
consent.on("consent:reset", () => resetEvents++);
consent.on("storage:error", () => storageErrors++);
consent.reset();
assert.equal(resetEvents, 0);
assert.equal(storageErrors, 1);
assert.equal(consent.getState().hasDecision, true);
});
/* -------------------------------------------------------------------------- */
/* Data contracts */
/* -------------------------------------------------------------------------- */
test("valid categories object satisfies its contract", () => {
assert.equal(
isValidCategoriesObject({
necessary: "granted",
preferences: "unknown",
analytics: "granted",
marketing: "denied"
}),
true
);
});
test("invalid categories object fails its contract", () => {
assert.equal(
isValidCategoriesObject({
necessary: "granted",
preferences: "invalid",
analytics: "granted",
marketing: "denied"
}),
false
);
});
test("valid stored envelope satisfies its contract", () => {
assert.equal(
isStoragePayload({
engineVersion: "1.0.0",
policyVersion: "2026-01",
timestamp: Date.now(),
categories: {
necessary: "granted",
preferences: "unknown",
analytics: "granted",
marketing: "denied"
},
jurisdiction: "global",
gpc: false
}),
true
);
});
test("empty stored envelope fails its contract", () => {
assert.equal(
isStoragePayload({}),
false
);
});
/* -------------------------------------------------------------------------- */
/* Lifecycle */
/* -------------------------------------------------------------------------- */
test("initialize is idempotent", () => {
const consent = make();
let initialized = 0;
consent.on("initialized", () => initialized++);
consent.initialize();
consent.initialize();
consent.initialize();
assert.equal(initialized, 1);
});
test("initialize without stored consent starts undecided", () => {
const consent = make();
consent.initialize();
const state = consent.getState();
assert.equal(state.hasDecision, false);
assert.equal(state.source, "default");
assert.equal(state.categories.necessary, "granted");
assert.equal(state.categories.analytics, "unknown");
});
console.log(`\n${passed} reliability tests passed.`);