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
+38
View File
@@ -0,0 +1,38 @@
/**
* Universal Cookie Consent
* jurisdiction/constants.js
*
* Pure constants for jurisdiction resolution. No DOM, network, storage,
* geolocation, GTM, or legal enforcement logic belongs here.
*/
export const JURISDICTION_MODES = Object.freeze([
"fixed",
"auto",
"global"
]);
export const RESOLUTION_SOURCES = Object.freeze([
"site-config",
"server",
"application",
"browser",
"fallback"
]);
export const CONFIDENCE_LEVELS = Object.freeze([
"explicit",
"high",
"medium",
"low",
"default"
]);
export const RESOLUTION_STATUSES = Object.freeze([
"resolved",
"fallback"
]);
export const DEFAULT_JURISDICTION_ID = "global";
export const DEFAULT_POLICY_ID = "global-baseline";
export const DEFAULT_MODE = "auto";
+35
View File
@@ -0,0 +1,35 @@
/**
* Universal Cookie Consent
* jurisdiction/index.js
*
* Public API for the Jurisdiction Engine.
*/
export {
JURISDICTION_MODES,
RESOLUTION_SOURCES,
CONFIDENCE_LEVELS,
RESOLUTION_STATUSES,
DEFAULT_JURISDICTION_ID,
DEFAULT_POLICY_ID,
DEFAULT_MODE
} from "./constants.js";
export {
JURISDICTION_CATALOG,
getJurisdiction,
hasJurisdiction
} from "./jurisdiction.js";
export {
POLICIES,
getPolicy,
hasPolicy
} from "./policies.js";
export {
resolveJurisdiction,
getResolutionPriority,
getSourceConfidence,
isValidResolution
} from "./resolver.js";
+73
View File
@@ -0,0 +1,73 @@
/**
* Universal Cookie Consent
* jurisdiction/jurisdiction.js
*
* Declarative jurisdiction catalog. This file maps jurisdiction identifiers
* to policy identifiers. It does not detect visitors or enforce consent.
*/
import { hasPolicy } from "./policies.js";
const JURISDICTIONS = {
global: {
id: "global",
country: null,
region: null,
policy: "global-baseline"
},
us: {
id: "us",
country: "US",
region: null,
policy: "us-state-privacy"
},
"us-ma": {
id: "us-ma",
country: "US",
region: "MA",
policy: "us-state-privacy"
},
"us-ca": {
id: "us-ca",
country: "US",
region: "CA",
policy: "us-california-privacy"
},
eu: {
id: "eu",
country: "EU",
region: null,
policy: "eu-privacy"
}
};
for (const entry of Object.values(JURISDICTIONS)) {
if (!hasPolicy(entry.policy)) {
throw new Error(`Jurisdiction references unknown policy: ${entry.policy}`);
}
}
export const JURISDICTION_CATALOG = Object.freeze(
Object.fromEntries(
Object.entries(JURISDICTIONS).map(([id, value]) => [
id,
Object.freeze({ ...value })
])
)
);
export function getJurisdiction(id) {
if (typeof id !== "string") {
return null;
}
return JURISDICTION_CATALOG[id] || null;
}
export function hasJurisdiction(id) {
return Boolean(getJurisdiction(id));
}
+55
View File
@@ -0,0 +1,55 @@
/**
* Universal Cookie Consent
* jurisdiction/policies.js
*
* Declarative policy catalog.
*
* IMPORTANT:
* These entries identify policy families only. They are NOT legal advice and
* deliberately do not encode detailed legal requirements yet. Those rules
* will be added after current-source legal research and policy review.
*/
const freeze = (value) => Object.freeze(value);
export const POLICIES = Object.freeze({
"global-baseline": freeze({
id: "global-baseline",
family: "global",
version: "1.0",
description: "Conservative global baseline pending jurisdiction-specific policy."
}),
"us-state-privacy": freeze({
id: "us-state-privacy",
family: "us-state",
version: "1.0",
description: "Policy family for U.S. state privacy regimes."
}),
"us-california-privacy": freeze({
id: "us-california-privacy",
family: "us-state",
version: "1.0",
description: "Policy family reserved for California-specific requirements."
}),
"eu-privacy": freeze({
id: "eu-privacy",
family: "eu",
version: "1.0",
description: "Policy family reserved for applicable European privacy requirements."
})
});
export function getPolicy(policyId) {
if (typeof policyId !== "string") {
return null;
}
return POLICIES[policyId] || null;
}
export function hasPolicy(policyId) {
return Boolean(getPolicy(policyId));
}
+215
View File
@@ -0,0 +1,215 @@
/**
* Universal Cookie Consent
* jurisdiction/resolver.js
*
* Pure deterministic jurisdiction resolver.
*
* It consumes explicitly supplied signals. It never performs network calls,
* reads IP addresses, accesses browser location, or guesses silently.
*/
import {
JURISDICTION_MODES,
RESOLUTION_SOURCES,
CONFIDENCE_LEVELS,
DEFAULT_JURISDICTION_ID,
DEFAULT_POLICY_ID,
DEFAULT_MODE
} from "./constants.js";
import { getJurisdiction, hasJurisdiction } from "./jurisdiction.js";
import { getPolicy, hasPolicy } from "./policies.js";
const SOURCE_CONFIDENCE = Object.freeze({
"site-config": "explicit",
server: "high",
application: "medium",
browser: "low",
fallback: "default"
});
const SOURCE_PRIORITY = Object.freeze({
"site-config": 500,
server: 400,
application: 300,
browser: 200,
fallback: 100
});
function isPlainObject(value) {
return Boolean(
value &&
typeof value === "object" &&
!Array.isArray(value)
);
}
function normalizeString(value) {
return typeof value === "string" ? value.trim() : "";
}
function assertMode(mode) {
if (!JURISDICTION_MODES.includes(mode)) {
throw new TypeError(
`Invalid jurisdiction mode. Expected: ${JURISDICTION_MODES.join(", ")}.`
);
}
}
function resolveEntry(id, source, status = "resolved") {
const entry = getJurisdiction(id);
if (!entry) {
throw new Error(`Unknown jurisdiction: ${id}`);
}
const policy = getPolicy(entry.policy);
if (!policy) {
throw new Error(`Unknown policy: ${entry.policy}`);
}
return Object.freeze({
status,
jurisdiction: Object.freeze({
id: entry.id,
country: entry.country,
region: entry.region
}),
policy: Object.freeze({
id: policy.id,
family: policy.family,
version: policy.version
}),
source,
confidence: SOURCE_CONFIDENCE[source]
});
}
function normalizeSignal(signal, fallbackSource) {
if (!isPlainObject(signal)) {
return null;
}
const id = normalizeString(signal.jurisdiction || signal.id);
if (!id || !hasJurisdiction(id)) {
return null;
}
const source = normalizeString(signal.source) || fallbackSource;
if (!RESOLUTION_SOURCES.includes(source)) {
return null;
}
return {
id,
source,
priority: SOURCE_PRIORITY[source]
};
}
function chooseBestSignal(signals) {
const candidates = [];
for (const signal of signals) {
const normalized = normalizeSignal(signal, "browser");
if (normalized) {
candidates.push(normalized);
}
}
if (!candidates.length) {
return null;
}
candidates.sort((a, b) => b.priority - a.priority);
return candidates[0];
}
function resolveAuto(input) {
const site = isPlainObject(input.site) ? input.site : {};
const request = isPlainObject(input.request) ? input.request : {};
const visitor = isPlainObject(input.visitor) ? input.visitor : {};
const signal = chooseBestSignal([
{ jurisdiction: request.jurisdiction, source: request.source || "server" },
{ jurisdiction: request.regionJurisdiction, source: request.regionSource || "server" },
{ jurisdiction: visitor.jurisdiction, source: visitor.source || "browser" },
{ jurisdiction: visitor.regionJurisdiction, source: visitor.regionSource || "browser" },
{ jurisdiction: site.jurisdiction, source: site.source || "application" }
]);
if (signal) {
return resolveEntry(signal.id, signal.source);
}
return resolveEntry(DEFAULT_JURISDICTION_ID, "fallback", "fallback");
}
export function resolveJurisdiction(input = {}) {
if (!isPlainObject(input)) {
throw new TypeError("Jurisdiction input must be an object.");
}
const site = isPlainObject(input.site) ? input.site : {};
const mode = normalizeString(input.mode || site.mode || DEFAULT_MODE) || DEFAULT_MODE;
assertMode(mode);
if (mode === "global") {
return resolveEntry(DEFAULT_JURISDICTION_ID, "site-config");
}
if (mode === "fixed") {
const id = normalizeString(input.jurisdiction || site.jurisdiction);
if (!id) {
throw new TypeError(
"A jurisdiction is required when mode is \"fixed\"."
);
}
if (!hasJurisdiction(id)) {
throw new RangeError(`Unknown jurisdiction: ${id}`);
}
return resolveEntry(id, "site-config");
}
return resolveAuto(input);
}
export function getResolutionPriority(source) {
return SOURCE_PRIORITY[source] || 0;
}
export function getSourceConfidence(source) {
return SOURCE_CONFIDENCE[source] || null;
}
export function isValidResolution(result) {
if (!isPlainObject(result)) {
return false;
}
if (!Object.prototype.hasOwnProperty.call(result, "status")) {
return false;
}
if (!Object.prototype.hasOwnProperty.call(result, "jurisdiction")) {
return false;
}
if (!Object.prototype.hasOwnProperty.call(result, "policy")) {
return false;
}
return (
(result.status === "resolved" || result.status === "fallback") &&
typeof result.jurisdiction.id === "string" &&
typeof result.policy.id === "string" &&
RESOLUTION_SOURCES.includes(result.source) &&
CONFIDENCE_LEVELS.includes(result.confidence) &&
hasJurisdiction(result.jurisdiction.id) &&
hasPolicy(result.policy.id)
);
}