@solvenza/cookies-compliance 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Solvenza IA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -263,8 +263,8 @@ var CookieStorageProvider = class {
263
263
  set(key, value, options) {
264
264
  CookieStore.set(key, value, options);
265
265
  }
266
- remove(key, path = "/") {
267
- CookieStore.remove(key, path);
266
+ remove(key, path = "/", domain) {
267
+ CookieStore.remove(key, path, domain);
268
268
  }
269
269
  };
270
270
  var CookieStore = class {
@@ -291,14 +291,34 @@ var CookieStore = class {
291
291
  const isHttps = typeof window !== "undefined" && window.location.protocol === "https:";
292
292
  const secure = (_b = options.secure) != null ? _b : isHttps;
293
293
  let cookieStr = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; Path=${path}; Max-Age=${maxAgeSeconds}; SameSite=${sameSite}`;
294
+ if (options.domain) {
295
+ cookieStr += `; Domain=${options.domain}`;
296
+ }
294
297
  if (secure) {
295
298
  cookieStr += "; Secure";
296
299
  }
297
300
  document.cookie = cookieStr;
298
301
  }
299
- static remove(name, path = "/") {
302
+ static remove(name, path = "/", domain) {
300
303
  if (typeof document === "undefined") return;
301
- document.cookie = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=Lax`;
304
+ let cookieStr = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=Lax`;
305
+ if (domain) {
306
+ cookieStr += `; Domain=${domain}`;
307
+ }
308
+ document.cookie = cookieStr;
309
+ }
310
+ static clearServiceCookies(config, revokedCategory) {
311
+ var _a, _b;
312
+ if (typeof document === "undefined" || !config.services) return;
313
+ const path = ((_a = config.storage) == null ? void 0 : _a.path) || "/";
314
+ const domain = (_b = config.storage) == null ? void 0 : _b.domain;
315
+ for (const service of Object.values(config.services)) {
316
+ if (service.category === revokedCategory && service.cookies) {
317
+ for (const cookieItem of service.cookies) {
318
+ this.remove(cookieItem.name, path, domain || cookieItem.domain);
319
+ }
320
+ }
321
+ }
302
322
  }
303
323
  };
304
324
 
@@ -1628,6 +1648,7 @@ var ConsentEngine = class {
1628
1648
  GoogleConsentAdapter.initDefault();
1629
1649
  if (evalResult.isValid) {
1630
1650
  GoogleConsentAdapter.update(evalResult.choices);
1651
+ this.dispatchDomEvent("solvenza:restored", { state: this.getConsent() });
1631
1652
  }
1632
1653
  this.blockerRegistry.init(
1633
1654
  (cat) => this.has(cat),
@@ -1714,7 +1735,7 @@ var ConsentEngine = class {
1714
1735
  this.preferencesModal.close();
1715
1736
  }
1716
1737
  withdraw() {
1717
- var _a, _b;
1738
+ var _a, _b, _c, _d;
1718
1739
  const previousChoices = this.stateManager.getChoices();
1719
1740
  const config = this.stateManager.getConfig();
1720
1741
  if (!config) return;
@@ -1722,11 +1743,17 @@ var ConsentEngine = class {
1722
1743
  if (((_b = config.storage) == null ? void 0 : _b.type) === "memory") {
1723
1744
  MemoryStore.remove(cookieName);
1724
1745
  } else {
1725
- CookieStore.remove(cookieName);
1746
+ CookieStore.remove(cookieName, ((_c = config.storage) == null ? void 0 : _c.path) || "/", (_d = config.storage) == null ? void 0 : _d.domain);
1747
+ }
1748
+ for (const catId of Object.keys(config.categories)) {
1749
+ if (catId !== "necessary") {
1750
+ CookieStore.clearServiceCookies(config, catId);
1751
+ }
1726
1752
  }
1727
1753
  this.stateManager.clearChoices();
1728
1754
  GoogleConsentAdapter.update(this.stateManager.getChoices());
1729
1755
  this.eventBus.emit("consent:withdrawn", { previousChoices });
1756
+ this.dispatchDomEvent("solvenza:updated", { choices: this.stateManager.getChoices() });
1730
1757
  this.showBanner();
1731
1758
  }
1732
1759
  when(categoryOrService, callback) {
@@ -1761,7 +1788,7 @@ var ConsentEngine = class {
1761
1788
  }
1762
1789
  }
1763
1790
  saveChoices(choices, source) {
1764
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1791
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1765
1792
  const config = this.stateManager.getConfig();
1766
1793
  if (!config) return;
1767
1794
  const receipt = createReceipt(
@@ -1772,6 +1799,11 @@ var ConsentEngine = class {
1772
1799
  (_a = config.security) == null ? void 0 : _a.secretKey
1773
1800
  );
1774
1801
  this.stateManager.updateChoices(receipt);
1802
+ for (const [catId, isAllowed] of Object.entries(choices)) {
1803
+ if (!isAllowed) {
1804
+ CookieStore.clearServiceCookies(config, catId);
1805
+ }
1806
+ }
1775
1807
  const cookieName = ((_b = config.storage) == null ? void 0 : _b.name) || "site_consent";
1776
1808
  const receiptJson = JSON.stringify(receipt);
1777
1809
  if (((_c = config.storage) == null ? void 0 : _c.type) === "memory") {
@@ -1781,7 +1813,8 @@ var ConsentEngine = class {
1781
1813
  path: ((_d = config.storage) == null ? void 0 : _d.path) || "/",
1782
1814
  maxAgeDays: (_f = (_e = config.consent) == null ? void 0 : _e.maxAgeDays) != null ? _f : 365,
1783
1815
  sameSite: ((_g = config.storage) == null ? void 0 : _g.sameSite) || "Lax",
1784
- secure: (_h = config.storage) == null ? void 0 : _h.secure
1816
+ secure: (_h = config.storage) == null ? void 0 : _h.secure,
1817
+ domain: (_i = config.storage) == null ? void 0 : _i.domain
1785
1818
  });
1786
1819
  }
1787
1820
  GoogleConsentAdapter.update(choices);
@@ -1789,7 +1822,7 @@ var ConsentEngine = class {
1789
1822
  (cat) => this.has(cat),
1790
1823
  (srv) => this.hasService(srv)
1791
1824
  );
1792
- if (((_i = config.logging) == null ? void 0 : _i.enabled) && config.logging.endpoint) {
1825
+ if (((_j = config.logging) == null ? void 0 : _j.enabled) && config.logging.endpoint) {
1793
1826
  try {
1794
1827
  fetch(config.logging.endpoint, {
1795
1828
  method: "POST",
@@ -1802,6 +1835,7 @@ var ConsentEngine = class {
1802
1835
  }
1803
1836
  this.banner.remove();
1804
1837
  this.eventBus.emit("consent:changed", { choices, receipt });
1838
+ this.dispatchDomEvent("solvenza:updated", { choices, receipt });
1805
1839
  }
1806
1840
  showBanner() {
1807
1841
  const config = this.stateManager.getConfig();
@@ -1812,6 +1846,7 @@ var ConsentEngine = class {
1812
1846
  onConfigure: () => this.openPreferences()
1813
1847
  });
1814
1848
  this.eventBus.emit("banner:shown", void 0);
1849
+ this.dispatchDomEvent("solvenza:show", void 0);
1815
1850
  }
1816
1851
  setupGlobalRevocationTrigger() {
1817
1852
  if (typeof document === "undefined") return;
@@ -1822,6 +1857,20 @@ var ConsentEngine = class {
1822
1857
  this.openPreferences();
1823
1858
  }
1824
1859
  });
1860
+ document.addEventListener("solvenza:show", () => {
1861
+ this.showBanner();
1862
+ });
1863
+ document.addEventListener("solvenza:preferences", () => {
1864
+ this.openPreferences();
1865
+ });
1866
+ }
1867
+ dispatchDomEvent(name, detail) {
1868
+ if (typeof document === "undefined") return;
1869
+ try {
1870
+ const customEvent = new CustomEvent(name, { detail, bubbles: true });
1871
+ document.dispatchEvent(customEvent);
1872
+ } catch (e) {
1873
+ }
1825
1874
  }
1826
1875
  };
1827
1876
  var globalScope = typeof window !== "undefined" ? window : globalThis;
@@ -1855,4 +1904,4 @@ export {
1855
1904
  ConsentEngine,
1856
1905
  Consent
1857
1906
  };
1858
- //# sourceMappingURL=chunk-LIWFUVWY.js.map
1907
+ //# sourceMappingURL=chunk-FBRP4MSA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/config-validator.ts","../src/core/security.ts","../src/core/receipt.ts","../src/storage/cookie-store.ts","../src/storage/memory-store.ts","../src/blocker/script-gate.ts","../src/blocker/iframe-gate.ts","../src/blocker/resource-gate.ts","../src/services/google.ts","../src/diagnostics/resource-scanner.ts","../src/ui/policy-generator.ts","../src/core/state.ts","../src/core/events.ts","../src/core/policy-engine.ts","../src/blocker/registry.ts","../src/services/custom.ts","../src/ui/styles.ts","../src/ui/banner.ts","../src/ui/preferences.ts","../src/core/consent-engine.ts"],"sourcesContent":["import type { ConsentConfig } from \"./types.js\";\n\nexport class ConfigValidationError extends Error {\n constructor(message: string) {\n super(`[ConsentSDK Config Error] ${message}`);\n this.name = \"ConfigValidationError\";\n }\n}\n\nexport function validateConfig(config: ConsentConfig): void {\n if (!config) {\n throw new ConfigValidationError(\"Configuration object is null or undefined.\");\n }\n\n if (typeof config.schemaVersion !== \"number\" || config.schemaVersion < 1) {\n throw new ConfigValidationError(\"Invalid or missing 'schemaVersion'. Expected integer >= 1.\");\n }\n\n if (!config.policyVersion || typeof config.policyVersion !== \"string\") {\n throw new ConfigValidationError(\"Invalid or missing 'policyVersion'. String required.\");\n }\n\n if (!config.categories || typeof config.categories !== \"object\") {\n throw new ConfigValidationError(\"Missing 'categories' map in configuration.\");\n }\n\n const categoryKeys = Object.keys(config.categories);\n if (categoryKeys.length === 0) {\n throw new ConfigValidationError(\"At least one category must be defined in 'categories'.\");\n }\n\n // Ensure necessary category exists and is required\n const necessaryCategory = config.categories[\"necessary\"];\n if (!necessaryCategory) {\n throw new ConfigValidationError(\"Category 'necessary' must be defined.\");\n }\n if (necessaryCategory.required !== true) {\n throw new ConfigValidationError(\"Category 'necessary' must have 'required: true'.\");\n }\n\n // Legal guardrail (AEPD): Optional categories MUST NOT be pre-selected (default = true)\n for (const [catId, catConfig] of Object.entries(config.categories)) {\n if (catId !== \"necessary\" && !catConfig.required) {\n if (catConfig.default === true) {\n throw new ConfigValidationError(\n `Legal violation (AEPD): Optional category '${catId}' cannot have default: true. All optional categories must be opt-in (default: false).`\n );\n }\n }\n }\n\n // Validate services if present\n if (config.services && typeof config.services === \"object\") {\n for (const [serviceId, serviceConfig] of Object.entries(config.services)) {\n if (!serviceConfig.category) {\n throw new ConfigValidationError(\n `Service '${serviceId}' missing 'category' reference.`\n );\n }\n if (!config.categories[serviceConfig.category]) {\n throw new ConfigValidationError(\n `Service '${serviceId}' references non-existent category '${serviceConfig.category}'.`\n );\n }\n }\n }\n}\n","/**\n * Security & Anti-Tampering Utilities\n * Solvenza Cookies Compliance\n */\n\n// Pure JS SHA-256 implementation (Zero-dependency, works in Node, Browser, Web Workers)\nfunction sha256Sync(ascii: string): string {\n let i, j;\n let result = \"\";\n\n const asciiLength = ascii.length * 8;\n let hash = [\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,\n 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n ];\n\n const k = [\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n ];\n\n const blocks: number[] = [];\n for (i = 0; i < ascii.length; i++) {\n blocks[i >> 2] |= ascii.charCodeAt(i) << (24 - (i % 4) * 8);\n }\n blocks[asciiLength >> 5] |= 0x80 << (24 - (asciiLength % 32));\n blocks[(((asciiLength + 64) >> 9) << 4) + 15] = asciiLength;\n\n for (i = 0; i < blocks.length; i += 16) {\n const w = blocks.slice(i, i + 16);\n const oldHash = [...hash];\n\n for (j = 0; j < 64; j++) {\n const w15 = w[j - 15], w2 = w[j - 2];\n\n const s0 = ((w15 >>> 7) | (w15 << 25)) ^ ((w15 >>> 18) | (w15 << 14)) ^ (w15 >>> 3);\n const s1 = ((w2 >>> 17) | (w2 << 15)) ^ ((w2 >>> 19) | (w2 << 13)) ^ (w2 >>> 10);\n\n w[j] = j < 16 ? (w[j] || 0) : (w[j - 16] + s0 + w[j - 7] + s1) | 0;\n\n const ch = (hash[4] & hash[5]) ^ (~hash[4] & hash[6]);\n const maj = (hash[0] & hash[1]) ^ (hash[0] & hash[2]) ^ (hash[1] & hash[2]);\n\n const sig0 = ((hash[0] >>> 2) | (hash[0] << 30)) ^ ((hash[0] >>> 13) | (hash[0] << 19)) ^ ((hash[0] >>> 22) | (hash[0] << 10));\n const sig1 = ((hash[4] >>> 6) | (hash[4] << 26)) ^ ((hash[4] >>> 11) | (hash[4] << 21)) ^ ((hash[4] >>> 25) | (hash[4] << 7));\n\n const t1 = hash[7] + sig1 + ch + k[j] + (w[j] | 0);\n const t2 = sig0 + maj;\n\n hash[7] = hash[6];\n hash[6] = hash[5];\n hash[5] = hash[4];\n hash[4] = (hash[3] + t1) | 0;\n hash[3] = hash[2];\n hash[2] = hash[1];\n hash[1] = hash[0];\n hash[0] = (t1 + t2) | 0;\n }\n\n for (j = 0; j < 8; j++) {\n hash[j] = (hash[j] + oldHash[j]) | 0;\n }\n }\n\n for (i = 0; i < 8; i++) {\n for (j = 3; j >= 0; j--) {\n const b = (hash[i] >> (j * 8)) & 255;\n result += (b < 16 ? \"0\" : \"\") + b.toString(16);\n }\n }\n\n return result;\n}\n\nexport function computeReceiptSignature(payload: string, secretKey?: string): string {\n if (secretKey) {\n return sha256Sync(`${secretKey}:${payload}:${secretKey}`);\n }\n // Fallback FNV-1a hash if no secret key provided\n let hash = 2166136261;\n for (let i = 0; i < payload.length; i++) {\n hash ^= payload.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0).toString(16);\n}\n\nexport function verifyReceiptIntegrity(payload: string, expectedSignature: string, secretKey?: string): boolean {\n if (!expectedSignature) return false;\n return computeReceiptSignature(payload, secretKey) === expectedSignature;\n}\n\nexport function sanitizeHtml(str: string): string {\n if (!str) return \"\";\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#039;\");\n}\n\nexport function sanitizeUrl(url: string): string {\n if (!url) return \"#\";\n const trimmed = url.trim().toLowerCase();\n if (trimmed.startsWith(\"javascript:\") || trimmed.startsWith(\"data:\") || trimmed.startsWith(\"vbscript:\")) {\n return \"#\";\n }\n return url;\n}\n","import type { ConsentChoices, ConsentReceipt } from \"./types.js\";\nimport { computeReceiptSignature } from \"./security.js\";\n\nfunction generateUUID(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n // Fallback for environments lacking crypto.randomUUID\n return \"xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function createReceipt(\n policyVersion: string,\n choices: ConsentChoices,\n source: ConsentReceipt[\"source\"],\n existingReceipt?: ConsentReceipt | null,\n secretKey?: string,\n): ConsentReceipt {\n const now = new Date().toISOString();\n const receiptId = existingReceipt?.receiptId || generateUUID();\n const decidedAt = existingReceipt?.decidedAt || now;\n\n const payloadToSign = `${receiptId}:${policyVersion}:${JSON.stringify(choices)}`;\n const signature = computeReceiptSignature(payloadToSign, secretKey);\n\n return {\n schema: 1,\n receiptId,\n policyVersion,\n decidedAt,\n updatedAt: now,\n source,\n choices,\n signature,\n };\n}\n\nexport function parseReceipt(jsonStr: string): ConsentReceipt | null {\n try {\n const data = JSON.parse(jsonStr);\n if (\n typeof data === \"object\" &&\n data !== null &&\n typeof data.receiptId === \"string\" &&\n typeof data.policyVersion === \"string\" &&\n typeof data.choices === \"object\"\n ) {\n return data as ConsentReceipt;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function isReceiptExpired(\n receipt: ConsentReceipt,\n maxAgeDays = 365,\n): boolean {\n if (!receipt.updatedAt) return true;\n const updated = new Date(receipt.updatedAt).getTime();\n const now = Date.now();\n const maxAgeMs = maxAgeDays * 86400 * 1000;\n return now - updated > maxAgeMs;\n}\n","import type { ConsentConfig } from \"../core/types.js\";\nimport type { CookieOptions, IStorageProvider } from \"../core/contracts/storage.interface.js\";\n\nexport type { CookieOptions };\n\nexport class CookieStorageProvider implements IStorageProvider {\n get(key: string): string | null {\n return CookieStore.get(key);\n }\n\n set(key: string, value: string, options?: CookieOptions): void {\n CookieStore.set(key, value, options);\n }\n\n remove(key: string, path = \"/\", domain?: string): void {\n CookieStore.remove(key, path, domain);\n }\n}\n\nexport class CookieStore {\n static get(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const nameEQ = encodeURIComponent(name) + \"=\";\n const ca = document.cookie.split(\";\");\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === \" \") c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) === 0) {\n return decodeURIComponent(c.substring(nameEQ.length, c.length));\n }\n }\n return null;\n }\n\n static set(name: string, value: string, options: CookieOptions = {}): void {\n if (typeof document === \"undefined\") return;\n\n const path = options.path || \"/\";\n const maxAgeDays = options.maxAgeDays ?? 365;\n const maxAgeSeconds = Math.floor(maxAgeDays * 86400);\n const sameSite = options.sameSite || \"Lax\";\n\n const isHttps =\n typeof window !== \"undefined\" && window.location.protocol === \"https:\";\n const secure = options.secure ?? isHttps;\n\n let cookieStr = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; Path=${path}; Max-Age=${maxAgeSeconds}; SameSite=${sameSite}`;\n\n if (options.domain) {\n cookieStr += `; Domain=${options.domain}`;\n }\n\n if (secure) {\n cookieStr += \"; Secure\";\n }\n\n document.cookie = cookieStr;\n }\n\n static remove(name: string, path = \"/\", domain?: string): void {\n if (typeof document === \"undefined\") return;\n let cookieStr = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=Lax`;\n if (domain) {\n cookieStr += `; Domain=${domain}`;\n }\n document.cookie = cookieStr;\n }\n\n static clearServiceCookies(config: ConsentConfig, revokedCategory: string): void {\n if (typeof document === \"undefined\" || !config.services) return;\n\n const path = config.storage?.path || \"/\";\n const domain = config.storage?.domain;\n\n for (const service of Object.values(config.services)) {\n if (service.category === revokedCategory && service.cookies) {\n for (const cookieItem of service.cookies) {\n this.remove(cookieItem.name, path, domain || cookieItem.domain);\n }\n }\n }\n }\n}\n","import type { IStorageProvider } from \"../core/contracts/storage.interface.js\";\n\nexport class MemoryStorageProvider implements IStorageProvider {\n private static store = new Map<string, string>();\n\n get(key: string): string | null {\n return MemoryStorageProvider.store.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n MemoryStorageProvider.store.set(key, value);\n }\n\n remove(key: string): void {\n MemoryStorageProvider.store.delete(key);\n }\n\n clear(): void {\n MemoryStorageProvider.store.clear();\n }\n}\n\nexport const MemoryStore = {\n get: (name: string) => new MemoryStorageProvider().get(name),\n set: (name: string, val: string) => new MemoryStorageProvider().set(name, val),\n remove: (name: string) => new MemoryStorageProvider().remove(name),\n clear: () => new MemoryStorageProvider().clear(),\n};\n","import type { IResourceBlocker } from \"../core/contracts/blocker.interface.js\";\n\nexport class ScriptResourceBlocker implements IResourceBlocker {\n type: \"script\" = \"script\";\n\n process(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean\n ): void {\n ScriptGate.scanAndActivate(isCategoryAllowed, isServiceAllowed);\n }\n}\n\nexport class ScriptGate {\n private static executedScripts = new Set<Element>();\n\n static scanAndActivate(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean,\n onServiceLoaded?: (serviceId: string, category: string) => void,\n ): void {\n if (typeof document === \"undefined\") return;\n\n const blockedScripts = Array.from(\n document.querySelectorAll<HTMLScriptElement>(\n 'script[type=\"text/plain\"][data-consent], script[type=\"text/plain\"][data-service]',\n ),\n );\n\n for (const oldScript of blockedScripts) {\n if (this.executedScripts.has(oldScript)) continue;\n\n const category = oldScript.getAttribute(\"data-consent\");\n const serviceId = oldScript.getAttribute(\"data-service\");\n\n let isAllowed = false;\n if (serviceId) {\n isAllowed = isServiceAllowed(serviceId);\n } else if (category) {\n isAllowed = isCategoryAllowed(category);\n }\n\n if (!isAllowed) continue;\n\n this.executedScripts.add(oldScript);\n const newScript = document.createElement(\"script\");\n\n for (let i = 0; i < oldScript.attributes.length; i++) {\n const attr = oldScript.attributes[i];\n if (attr.name === \"type\") continue;\n if (attr.name === \"data-src\") {\n newScript.src = attr.value;\n continue;\n }\n newScript.setAttribute(attr.name, attr.value);\n }\n\n newScript.type = \"text/javascript\";\n if (!newScript.src && oldScript.textContent) {\n newScript.textContent = oldScript.textContent;\n }\n\n oldScript.parentNode?.replaceChild(newScript, oldScript);\n\n if (serviceId || category) {\n onServiceLoaded?.(serviceId || category!, category || \"custom\");\n }\n }\n }\n}\n","import type { IResourceBlocker } from \"../core/contracts/blocker.interface.js\";\n\nexport interface IframeGateOptions {\n onAllowClick?: (category: string, serviceId?: string) => void;\n}\n\nexport class IframeResourceBlocker implements IResourceBlocker {\n type: \"iframe\" = \"iframe\";\n\n process(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean\n ): void {\n IframeGate.processIframes(isCategoryAllowed, isServiceAllowed);\n }\n}\n\nexport class IframeGate {\n private static placeholders = new Map<HTMLIFrameElement, HTMLElement>();\n\n static processIframes(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean,\n options: IframeGateOptions = {},\n ): void {\n if (typeof document === \"undefined\") return;\n\n const iframes = Array.from(\n document.querySelectorAll<HTMLIFrameElement>(\n \"iframe[data-consent], iframe[data-service]\",\n ),\n );\n\n for (const iframe of iframes) {\n const category = iframe.getAttribute(\"data-consent\");\n const serviceId = iframe.getAttribute(\"data-service\");\n\n let isAllowed = false;\n if (serviceId) {\n isAllowed = isServiceAllowed(serviceId);\n } else if (category) {\n isAllowed = isCategoryAllowed(category);\n }\n\n const originalSrc =\n iframe.getAttribute(\"data-src\") || iframe.getAttribute(\"src\");\n\n if (!originalSrc) continue;\n\n if (!iframe.getAttribute(\"data-src\")) {\n iframe.setAttribute(\"data-src\", originalSrc);\n }\n\n if (isAllowed) {\n this.unlockIframe(iframe, originalSrc);\n } else {\n this.lockIframe(\n iframe,\n category || \"marketing\",\n serviceId || undefined,\n options,\n );\n }\n }\n }\n\n private static lockIframe(\n iframe: HTMLIFrameElement,\n category: string,\n serviceId: string | undefined,\n options: IframeGateOptions,\n ): void {\n if (iframe.hasAttribute(\"src\")) {\n iframe.removeAttribute(\"src\");\n }\n\n if (this.placeholders.has(iframe)) return;\n\n const container = document.createElement(\"div\");\n container.className = \"consent-iframe-placeholder\";\n container.style.cssText = `\n width: ${iframe.width ? (iframe.width.endsWith(\"%\") || iframe.width.endsWith(\"px\") ? iframe.width : iframe.width + \"px\") : \"100%\"};\n height: ${iframe.height ? (iframe.height.endsWith(\"%\") || iframe.height.endsWith(\"px\") ? iframe.height : iframe.height + \"px\") : \"315px\"};\n min-height: 200px;\n background: #0f172a;\n color: #f8fafc;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 1.5rem;\n border-radius: 8px;\n box-sizing: border-box;\n font-family: system-ui, -apple-system, sans-serif;\n `;\n\n const titleText = serviceId\n ? `Contenido de ${serviceId} bloqueado`\n : \"Contenido externo bloqueado\";\n const bodyText =\n \"Este contenido está bloqueado hasta que autorices esta finalidad de privacidad.\";\n\n container.innerHTML = `\n <div style=\"font-weight: 600; font-size: 1.1rem; margin-bottom: 0.5rem; color: #f8fafc;\">\n ${titleText}\n </div>\n <p style=\"font-size: 0.9rem; color: #94a3b8; margin: 0 0 1rem 0; max-width: 400px;\">\n ${bodyText}\n </p>\n <button type=\"button\" class=\"consent-placeholder-allow-btn\" style=\"\n background: #2563eb;\n color: #ffffff;\n border: none;\n padding: 0.6rem 1.2rem;\n border-radius: 6px;\n font-weight: 500;\n cursor: pointer;\n font-size: 0.9rem;\n transition: background 0.2s ease;\n \">\n Permitir y mostrar contenido\n </button>\n `;\n\n const button = container.querySelector<HTMLButtonElement>(\n \".consent-placeholder-allow-btn\",\n );\n button?.addEventListener(\"click\", () => {\n options.onAllowClick?.(category, serviceId);\n });\n\n iframe.style.display = \"none\";\n iframe.parentNode?.insertBefore(container, iframe);\n this.placeholders.set(iframe, container);\n }\n\n private static unlockIframe(iframe: HTMLIFrameElement, src: string): void {\n if (iframe.getAttribute(\"src\") !== src) {\n iframe.setAttribute(\"src\", src);\n }\n iframe.style.display = \"\";\n\n const placeholder = this.placeholders.get(iframe);\n if (placeholder) {\n placeholder.parentNode?.removeChild(placeholder);\n this.placeholders.delete(iframe);\n }\n }\n}\n","import type { IResourceBlocker } from \"../core/contracts/blocker.interface.js\";\n\nexport class ImageResourceBlocker implements IResourceBlocker {\n type: \"image\" = \"image\";\n\n process(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean\n ): void {\n ResourceGate.processImages(isCategoryAllowed, isServiceAllowed);\n }\n}\n\nexport class ResourceGate {\n static processImages(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean,\n ): void {\n if (typeof document === \"undefined\") return;\n\n const images = Array.from(\n document.querySelectorAll<HTMLImageElement>(\n \"img[data-consent], img[data-service]\",\n ),\n );\n\n for (const img of images) {\n const category = img.getAttribute(\"data-consent\");\n const serviceId = img.getAttribute(\"data-service\");\n\n let isAllowed = false;\n if (serviceId) {\n isAllowed = isServiceAllowed(serviceId);\n } else if (category) {\n isAllowed = isCategoryAllowed(category);\n }\n\n const originalSrc =\n img.getAttribute(\"data-src\") || img.getAttribute(\"src\");\n\n if (!originalSrc) continue;\n\n if (!img.getAttribute(\"data-src\")) {\n img.setAttribute(\"data-src\", originalSrc);\n }\n\n if (isAllowed) {\n if (img.getAttribute(\"src\") !== originalSrc) {\n img.setAttribute(\"src\", originalSrc);\n }\n } else {\n if (img.hasAttribute(\"src\")) {\n img.removeAttribute(\"src\");\n }\n }\n }\n }\n}\n","import type { ConsentChoices } from \"../core/types.js\";\n\ndeclare global {\n interface Window {\n dataLayer?: any[];\n gtag?: (...args: any[]) => void;\n }\n}\n\nexport interface GoogleConsentModeConfig {\n analytics_storage?: string; // category id e.g. \"analytics\"\n ad_storage?: string; // category id e.g. \"marketing\"\n ad_user_data?: string; // category id e.g. \"marketing\"\n ad_personalization?: string; // category id e.g. \"marketing\"\n}\n\nexport class GoogleConsentAdapter {\n private static initialized = false;\n\n static initDefault(_configMap?: GoogleConsentModeConfig): void {\n if (typeof window === \"undefined\") return;\n\n window.dataLayer = window.dataLayer || [];\n if (!window.gtag) {\n window.gtag = function () {\n window.dataLayer?.push(arguments);\n };\n }\n\n if (!this.initialized) {\n window.gtag(\"consent\", \"default\", {\n analytics_storage: \"denied\",\n ad_storage: \"denied\",\n ad_user_data: \"denied\",\n ad_personalization: \"denied\",\n wait_for_update: 500,\n });\n this.initialized = true;\n }\n }\n\n static update(choices: ConsentChoices, configMap?: GoogleConsentModeConfig): void {\n if (typeof window === \"undefined\") return;\n\n this.initDefault(configMap);\n\n const analyticsCategory = configMap?.analytics_storage || \"analytics\";\n const marketingCategory = configMap?.ad_storage || \"marketing\";\n\n const isAnalyticsAllowed = choices[analyticsCategory] === true;\n const isMarketingAllowed = choices[marketingCategory] === true;\n\n window.gtag!(\"consent\", \"update\", {\n analytics_storage: isAnalyticsAllowed ? \"granted\" : \"denied\",\n ad_storage: isMarketingAllowed ? \"granted\" : \"denied\",\n ad_user_data: isMarketingAllowed ? \"granted\" : \"denied\",\n ad_personalization: isMarketingAllowed ? \"granted\" : \"denied\",\n });\n }\n}\n","import type { ConsentConfig, DiagnosticReport } from \"../core/types.js\";\n\nexport class ResourceScanner {\n static runDiagnostic(_config: ConsentConfig, isConsentGiven: boolean): DiagnosticReport {\n const thirdPartyScripts: string[] = [];\n if (typeof document !== \"undefined\") {\n const scripts = document.querySelectorAll(\"script[src]\");\n scripts.forEach((script) => {\n const src = script.getAttribute(\"src\");\n if (src && (src.startsWith(\"http://\") || src.startsWith(\"https://\"))) {\n thirdPartyScripts.push(src);\n }\n });\n }\n\n return {\n timestamp: new Date().toISOString(),\n unblockedThirdPartyScripts: isConsentGiven ? [] : thirdPartyScripts,\n compliant: isConsentGiven || thirdPartyScripts.length === 0,\n };\n }\n\n scanThirdPartyResources(): string[] {\n return ResourceScanner.runDiagnostic({} as any, true).unblockedThirdPartyScripts;\n }\n}\n","import type { ConsentConfig } from \"../core/types.js\";\nimport { sanitizeHtml } from \"../core/security.js\";\n\nexport class PolicyGenerator {\n static renderTable(config: ConsentConfig): string {\n let html = `\n <div class=\"consent-policy-table-wrapper\" style=\"margin: 1.5rem 0; font-family: system-ui, sans-serif;\">\n <table style=\"width: 100%; border-collapse: collapse; text-align: left; border: 1px solid #e2e8f0;\">\n <thead>\n <tr style=\"background: #f8fafc; border-bottom: 2px solid #cbd5e1;\">\n <th style=\"padding: 0.75rem; border: 1px solid #e2e8f0;\">Categoría / Servicio</th>\n <th style=\"padding: 0.75rem; border: 1px solid #e2e8f0;\">Proveedor</th>\n <th style=\"padding: 0.75rem; border: 1px solid #e2e8f0;\">Finalidad</th>\n <th style=\"padding: 0.75rem; border: 1px solid #e2e8f0;\">Requerida</th>\n </tr>\n </thead>\n <tbody>\n `;\n\n for (const [catId, cat] of Object.entries(config.categories)) {\n const isReq = cat.required ? \"Sí (Técnica)\" : \"No (Opcional)\";\n html += `\n <tr style=\"background: #ffffff; font-weight: 600;\">\n <td style=\"padding: 0.75rem; border: 1px solid #e2e8f0;\" colspan=\"3\">${sanitizeHtml(cat.label)}</td>\n <td style=\"padding: 0.75rem; border: 1px solid #e2e8f0;\">${isReq}</td>\n </tr>\n `;\n\n if (config.services) {\n for (const [srvId, srv] of Object.entries(config.services)) {\n if (srv.category === catId) {\n html += `\n <tr style=\"background: #f8fafc; font-size: 0.9rem;\">\n <td style=\"padding: 0.5rem 0.75rem 0.5rem 1.5rem; border: 1px solid #e2e8f0;\">↳ ${sanitizeHtml(srv.label || srvId)}</td>\n <td style=\"padding: 0.5rem 0.75rem; border: 1px solid #e2e8f0;\">${sanitizeHtml(srv.provider || \"-\")}</td>\n <td style=\"padding: 0.5rem 0.75rem; border: 1px solid #e2e8f0;\">${sanitizeHtml(cat.description || \"-\")}</td>\n <td style=\"padding: 0.5rem 0.75rem; border: 1px solid #e2e8f0;\">${isReq}</td>\n </tr>\n `;\n }\n }\n }\n }\n\n html += `\n </tbody>\n </table>\n </div>\n `;\n\n return html;\n }\n}\n","import type {\n ConsentChoices,\n ConsentConfig,\n ConsentReceipt,\n ConsentState,\n} from \"./types.js\";\n\nexport class StateManager {\n private state: ConsentState = {\n initialized: false,\n policyVersion: \"\",\n locale: \"es\",\n receipt: null,\n choices: {},\n };\n\n private config: ConsentConfig | null = null;\n\n init(\n config: ConsentConfig,\n choices: ConsentChoices,\n receipt: ConsentReceipt | null,\n ): void {\n this.config = config;\n this.state = {\n initialized: true,\n policyVersion: config.policyVersion,\n locale: config.locale?.default || \"es\",\n receipt,\n choices,\n };\n }\n\n getConfig(): ConsentConfig | null {\n return this.config;\n }\n\n getState(): ConsentState {\n return { ...this.state };\n }\n\n getChoices(): ConsentChoices {\n return { ...this.state.choices };\n }\n\n getReceipt(): ConsentReceipt | null {\n return this.state.receipt;\n }\n\n hasCategory(category: string): boolean {\n return this.state.choices[category] === true;\n }\n\n hasService(serviceId: string): boolean {\n if (!this.config || !this.config.services) return false;\n const service = this.config.services[serviceId];\n if (!service) return false;\n\n return this.hasCategory(service.category);\n }\n\n updateChoices(receipt: ConsentReceipt): void {\n this.state.receipt = receipt;\n this.state.choices = { ...receipt.choices };\n }\n\n clearChoices(): void {\n if (!this.config) return;\n const resetChoices: ConsentChoices = {};\n for (const [catId, catConfig] of Object.entries(this.config.categories)) {\n resetChoices[catId] = catConfig.required === true;\n }\n this.state.choices = resetChoices;\n this.state.receipt = null;\n }\n}\n","import type {\n ConsentEvent,\n ConsentEventDetailMap,\n ConsentEventHandler,\n} from \"./types.js\";\n\nexport class EventBus {\n private handlers = new Map<ConsentEvent, Set<ConsentEventHandler<any>>>();\n\n on<E extends ConsentEvent>(\n event: E,\n handler: ConsentEventHandler<E>\n ): () => void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n const set = this.handlers.get(event)!;\n set.add(handler);\n\n return () => {\n set.delete(handler);\n };\n }\n\n emit<E extends ConsentEvent>(event: E, detail: ConsentEventDetailMap[E]): void {\n const set = this.handlers.get(event);\n if (!set) return;\n\n for (const handler of set) {\n try {\n handler(detail);\n } catch (err) {\n console.error(`[ConsentSDK Event Error] Handler for '${event}' failed:`, err);\n }\n }\n }\n\n clear(): void {\n this.handlers.clear();\n }\n}\n","import type { ConsentChoices, ConsentConfig, ConsentReceipt } from \"./types.js\";\nimport { isReceiptExpired } from \"./receipt.js\";\nimport { computeReceiptSignature } from \"./security.js\";\n\nexport interface PolicyEvaluationResult {\n isValid: boolean;\n reason?: \"missing\" | \"policy_version_changed\" | \"expired\" | \"tampered\" | \"valid\";\n choices: ConsentChoices;\n}\n\nexport function evaluatePolicy(\n config: ConsentConfig,\n receipt: ConsentReceipt | null\n): PolicyEvaluationResult {\n // Build default deny choices (necessary = true, all optionals = false)\n const defaultChoices: ConsentChoices = {};\n for (const [catId, catConfig] of Object.entries(config.categories)) {\n defaultChoices[catId] = catConfig.required === true;\n }\n\n if (!receipt) {\n return {\n isValid: false,\n reason: \"missing\",\n choices: defaultChoices,\n };\n }\n\n if (receipt.policyVersion !== config.policyVersion) {\n return {\n isValid: false,\n reason: \"policy_version_changed\",\n choices: defaultChoices,\n };\n }\n\n const maxAgeDays = config.consent?.maxAgeDays ?? 365;\n if (isReceiptExpired(receipt, maxAgeDays)) {\n return {\n isValid: false,\n reason: \"expired\",\n choices: defaultChoices,\n };\n }\n\n // Anti-tampering signature verification\n if (receipt.signature) {\n const payloadToSign = `${receipt.receiptId}:${receipt.policyVersion}:${JSON.stringify(receipt.choices)}`;\n const expectedSignature = computeReceiptSignature(payloadToSign, config.security?.secretKey);\n if (receipt.signature !== expectedSignature) {\n return {\n isValid: false,\n reason: \"tampered\",\n choices: defaultChoices,\n };\n }\n }\n\n // Merge receipt choices ensuring necessary remains true and any missing category defaults to false\n const activeChoices: ConsentChoices = { ...defaultChoices };\n for (const catId of Object.keys(config.categories)) {\n if (catId === \"necessary\") {\n activeChoices[catId] = true;\n } else if (typeof receipt.choices[catId] === \"boolean\") {\n activeChoices[catId] = receipt.choices[catId];\n }\n }\n\n return {\n isValid: true,\n reason: \"valid\",\n choices: activeChoices,\n };\n}\n","import { ScriptGate } from \"./script-gate.js\";\nimport { IframeGate, type IframeGateOptions } from \"./iframe-gate.js\";\nimport { ResourceGate } from \"./resource-gate.js\";\n\nexport class BlockerRegistry {\n private observer: MutationObserver | null = null;\n\n init(\n isCategoryAllowed: (category: string) => boolean,\n isServiceAllowed: (serviceId: string) => boolean,\n iframeOptions?: IframeGateOptions,\n onServiceLoaded?: (serviceId: string, category: string) => void,\n ): void {\n const runBlockers = () => {\n ScriptGate.scanAndActivate(\n isCategoryAllowed,\n isServiceAllowed,\n onServiceLoaded,\n );\n IframeGate.processIframes(\n isCategoryAllowed,\n isServiceAllowed,\n iframeOptions,\n );\n ResourceGate.processImages(isCategoryAllowed, isServiceAllowed);\n };\n\n // Initial pass\n runBlockers();\n\n // Set up MutationObserver Level B defense for dynamically injected scripts/iframes\n if (\n typeof MutationObserver !== \"undefined\" &&\n typeof document !== \"undefined\"\n ) {\n this.observer = new MutationObserver(() => {\n runBlockers();\n });\n\n this.observer.observe(document.documentElement || document.body, {\n childList: true,\n subtree: true,\n });\n }\n }\n\n destroy(): void {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n }\n}\n","import type { EventBus } from \"../core/events.js\";\n\nexport class CustomServiceAdapter {\n static createWhen(\n eventBus: EventBus,\n isCategoryAllowed: (cat: string) => boolean,\n isServiceAllowed: (srv: string) => boolean\n ) {\n return function when(\n categoryOrService: string,\n callback: () => void\n ): () => void {\n // Execute immediately if already granted\n if (isCategoryAllowed(categoryOrService) || isServiceAllowed(categoryOrService)) {\n try {\n callback();\n } catch (err) {\n console.error(`[ConsentSDK when()] Callback execution failed:`, err);\n }\n }\n\n // Listen for future consent changes\n return eventBus.on(\"consent:changed\", ({ choices }) => {\n if (choices[categoryOrService] === true || isServiceAllowed(categoryOrService)) {\n try {\n callback();\n } catch (err) {\n console.error(`[ConsentSDK when()] Callback execution failed:`, err);\n }\n }\n });\n };\n }\n}\n","export function injectStyles(nonce?: string): void {\n if (typeof document === \"undefined\") return;\n\n const existing = document.getElementById(\"consent-sdk-styles\");\n if (existing) {\n existing.remove(); // Re-inject updated styles\n }\n\n const styleEl = document.createElement(\"style\");\n styleEl.id = \"consent-sdk-styles\";\n if (nonce) {\n styleEl.setAttribute(\"nonce\", nonce);\n }\n\n styleEl.textContent = `\n :root {\n --consent-bg: #ffffff;\n --consent-fg: #0f172a;\n --consent-muted: #64748b;\n --consent-divider: #f1f5f9;\n --consent-border: #e2e8f0;\n --consent-hover-bg: #f8fafc;\n --consent-primary: #0f172a;\n --consent-primary-hover: #1e293b;\n --consent-primary-fg: #ffffff;\n --consent-secondary: #f8fafc;\n --consent-secondary-hover: #f1f5f9;\n --consent-secondary-fg: #0f172a;\n --consent-accent: #2563eb;\n --consent-focus-ring: rgba(37, 99, 235, 0.3);\n --consent-font: system-ui, -apple-system, BlinkMacSystemFont, \"SF Pro Display\", \"SF Pro Text\", \"Segoe UI\", Roboto, sans-serif;\n --consent-modal-shadow: 0 32px 64px -16px rgba(15, 23, 42, 0.2), 0 0 1px rgba(15, 23, 42, 0.12);\n }\n\n @media (prefers-color-scheme: dark) {\n :root {\n --consent-bg: #0f172a;\n --consent-fg: #f8fafc;\n --consent-muted: #94a3b8;\n --consent-divider: #1e293b;\n --consent-border: #334155;\n --consent-hover-bg: #1e293b;\n --consent-primary: #f8fafc;\n --consent-primary-hover: #ffffff;\n --consent-primary-fg: #0f172a;\n --consent-secondary: #1e293b;\n --consent-secondary-hover: #334155;\n --consent-secondary-fg: #f8fafc;\n --consent-modal-shadow: 0 32px 64px -16px rgba(0, 0, 0, 0.6), 0 0 1px rgba(255, 255, 255, 0.12);\n }\n }\n\n @keyframes consentSlideUp {\n from {\n opacity: 0;\n transform: translateY(16px) scale(0.985);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n @keyframes consentFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n /* 1st Layer Banner - Clean & Seamless */\n .consent-banner-wrapper {\n position: fixed;\n bottom: 1.25rem;\n left: 1.25rem;\n right: 1.25rem;\n max-width: 1060px;\n margin: 0 auto;\n z-index: 2147483645;\n background: var(--consent-bg);\n color: var(--consent-fg);\n border: 1px solid var(--consent-border);\n border-radius: 20px;\n box-shadow: var(--consent-modal-shadow);\n padding: 1.5rem 1.75rem;\n font-family: var(--consent-font);\n font-size: 0.92rem;\n line-height: 1.5;\n animation: consentSlideUp 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n box-sizing: border-box;\n }\n\n .consent-banner-container {\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n }\n\n @media (min-width: 860px) {\n .consent-banner-container {\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n }\n }\n\n .consent-banner-text {\n flex: 1;\n }\n\n .consent-banner-title {\n font-size: 1.1rem;\n font-weight: 700;\n letter-spacing: -0.015em;\n margin: 0 0 0.35rem 0;\n color: var(--consent-fg);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .consent-banner-title-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 6px;\n background: rgba(37, 99, 235, 0.1);\n color: var(--consent-accent);\n }\n\n .consent-banner-desc {\n margin: 0;\n color: var(--consent-muted);\n font-size: 0.88rem;\n max-width: 720px;\n }\n\n .consent-banner-links {\n margin-top: 0.4rem;\n }\n\n .consent-banner-links a {\n color: var(--consent-muted);\n font-size: 0.83rem;\n text-decoration: underline;\n text-underline-offset: 3px;\n font-weight: 500;\n margin-right: 1.2rem;\n transition: color 0.15s ease;\n }\n\n .consent-banner-links a:hover {\n color: var(--consent-fg);\n }\n\n /* Equal Visual Prominence CTAs */\n .consent-banner-actions {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n width: 100%;\n }\n\n @media (min-width: 640px) {\n .consent-banner-actions {\n flex-direction: row;\n width: auto;\n align-items: center;\n }\n }\n\n .consent-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0.6rem 1.2rem;\n font-size: 0.88rem;\n font-weight: 600;\n border-radius: 10px;\n border: 1px solid var(--consent-border);\n cursor: pointer;\n font-family: inherit;\n transition: all 0.18s cubic-bezier(0.16, 1, 0.3, 1);\n min-height: 42px;\n min-width: 110px;\n box-sizing: border-box;\n user-select: none;\n }\n\n .consent-btn:hover {\n transform: translateY(-1px);\n }\n\n .consent-btn:active {\n transform: translateY(0) scale(0.98);\n }\n\n .consent-btn:focus-visible {\n outline: 3px solid var(--consent-focus-ring);\n outline-offset: 2px;\n }\n\n .consent-btn-reject {\n background: var(--consent-secondary);\n color: var(--consent-secondary-fg);\n border-color: var(--consent-border);\n }\n\n .consent-btn-reject:hover {\n background: var(--consent-secondary-hover);\n }\n\n .consent-btn-configure {\n background: transparent;\n color: var(--consent-muted);\n border-color: transparent;\n }\n\n .consent-btn-configure:hover {\n color: var(--consent-fg);\n background: var(--consent-secondary);\n }\n\n .consent-btn-accept {\n background: var(--consent-primary);\n color: var(--consent-primary-fg);\n border-color: var(--consent-primary);\n }\n\n .consent-btn-accept:hover {\n background: var(--consent-primary-hover);\n }\n\n /* 2nd Layer Preference Modal - Ultra Clean Linear List Style */\n .consent-dialog-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(15, 23, 42, 0.45);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n z-index: 2147483646;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.25rem;\n box-sizing: border-box;\n animation: consentFadeIn 0.2s ease forwards;\n }\n\n .consent-dialog {\n background: var(--consent-bg);\n color: var(--consent-fg);\n border: 1px solid var(--consent-border);\n border-radius: 20px;\n width: 100%;\n max-width: 600px;\n max-height: 85vh;\n display: flex;\n flex-direction: column;\n box-shadow: var(--consent-modal-shadow);\n font-family: var(--consent-font);\n overflow: hidden;\n animation: consentSlideUp 0.25s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n }\n\n .consent-dialog-header {\n padding: 1.5rem 1.75rem 1.25rem 1.75rem;\n border-bottom: 1px solid var(--consent-divider);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n }\n\n .consent-dialog-title {\n font-size: 1.15rem;\n font-weight: 700;\n letter-spacing: -0.015em;\n margin: 0;\n }\n\n .consent-dialog-close {\n background: transparent;\n border: none;\n color: var(--consent-muted);\n cursor: pointer;\n padding: 0.35rem;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s ease, color 0.15s ease;\n margin: -0.35rem -0.35rem 0 0;\n }\n\n .consent-dialog-close:hover {\n background: var(--consent-secondary);\n color: var(--consent-fg);\n }\n\n /* Seamless Category List Body (NO individual boxed divs) */\n .consent-dialog-body {\n padding: 0;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n }\n\n .consent-category-row {\n padding: 1.25rem 1.75rem;\n border-bottom: 1px solid var(--consent-divider);\n transition: background 0.15s ease;\n }\n\n .consent-category-row:last-child {\n border-bottom: none;\n }\n\n .consent-category-row:hover {\n background: var(--consent-hover-bg);\n }\n\n .consent-category-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 1rem;\n }\n\n .consent-category-name {\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--consent-fg);\n }\n\n .consent-category-desc {\n margin: 0.3rem 0 0 0;\n font-size: 0.85rem;\n color: var(--consent-muted);\n line-height: 1.45;\n }\n\n /* Minimalist Badges */\n .consent-badge {\n display: inline-flex;\n align-items: center;\n padding: 0.15rem 0.5rem;\n border-radius: 6px;\n font-size: 0.7rem;\n font-weight: 600;\n letter-spacing: 0.01em;\n }\n\n .consent-badge-required {\n background: rgba(16, 185, 129, 0.1);\n color: #059669;\n }\n\n .consent-badge-optional {\n background: rgba(100, 116, 139, 0.08);\n color: var(--consent-muted);\n }\n\n /* Inline Service Disclosure Button */\n .consent-toggle-services-btn {\n border: none;\n background: transparent;\n color: var(--consent-accent);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n padding: 0.35rem 0 0 0;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n font-family: inherit;\n }\n\n .consent-toggle-services-btn:hover {\n opacity: 0.85;\n }\n\n /* Minimalist Toggle Switch */\n .consent-toggle {\n position: relative;\n display: inline-block;\n width: 40px;\n height: 22px;\n flex-shrink: 0;\n margin-top: 0.15rem;\n }\n\n .consent-toggle input {\n opacity: 0;\n width: 0;\n height: 0;\n }\n\n .consent-toggle-slider {\n position: absolute;\n cursor: pointer;\n top: 0; left: 0; right: 0; bottom: 0;\n background-color: #cbd5e1;\n transition: background-color 0.2s ease;\n border-radius: 22px;\n }\n\n .consent-toggle-slider:before {\n position: absolute;\n content: \"\";\n height: 16px;\n width: 16px;\n left: 3px;\n bottom: 3px;\n background-color: white;\n transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n border-radius: 50%;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);\n }\n\n .consent-toggle input:checked + .consent-toggle-slider {\n background-color: var(--consent-accent);\n }\n\n .consent-toggle input:checked + .consent-toggle-slider:before {\n transform: translateX(18px);\n }\n\n .consent-toggle input:disabled + .consent-toggle-slider {\n opacity: 0.45;\n cursor: not-allowed;\n }\n\n /* Footer */\n .consent-dialog-footer {\n padding: 1.25rem 1.75rem;\n border-top: 1px solid var(--consent-divider);\n background: var(--consent-bg);\n display: flex;\n flex-direction: column;\n gap: 0.6rem;\n justify-content: space-between;\n align-items: center;\n }\n\n @media (min-width: 520px) {\n .consent-dialog-footer {\n flex-direction: row;\n }\n }\n `;\n document.head.appendChild(styleEl);\n}\n","import type { ConsentConfig } from \"../core/types.js\";\nimport { injectStyles } from \"./styles.js\";\nimport { sanitizeHtml, sanitizeUrl } from \"../core/security.js\";\n\nexport interface BannerHandlers {\n onAcceptAll: () => void;\n onRejectAll: () => void;\n onConfigure: () => void;\n}\n\nexport class ConsentBanner {\n private element: HTMLElement | null = null;\n\n render(config: ConsentConfig, handlers: BannerHandlers): void {\n if (typeof document === \"undefined\") return;\n this.remove();\n injectStyles(config.csp?.nonce);\n\n const bannerConfig = config.ui?.banner || {};\n const titleText = sanitizeHtml(bannerConfig.title || \"Tu privacidad, bajo tu control\");\n const descText = sanitizeHtml(\n bannerConfig.description ||\n \"Usamos tecnologías necesarias para el funcionamiento del sitio. Con tu permiso, también podemos utilizar analítica y marketing.\"\n );\n const acceptText = sanitizeHtml(bannerConfig.accept || \"Aceptar todas\");\n const rejectText = sanitizeHtml(bannerConfig.reject || \"Rechazar todas\");\n const configureText = sanitizeHtml(bannerConfig.configure || \"Configurar\");\n\n const privacyUrl = sanitizeUrl(config.policy?.privacyUrl || \"/politica-privacidad\");\n const cookiesUrl = sanitizeUrl(config.policy?.cookiesUrl || \"/politica-cookies\");\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"consent-banner-wrapper\";\n wrapper.setAttribute(\"role\", \"region\");\n wrapper.setAttribute(\n \"aria-label\",\n \"Gestión de consentimiento de privacidad\",\n );\n\n wrapper.innerHTML = `\n <div class=\"consent-banner-container\">\n <div class=\"consent-banner-text\">\n <h2 class=\"consent-banner-title\">\n <span class=\"consent-banner-title-icon\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\">\n <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"/>\n </svg>\n </span>\n ${titleText}\n </h2>\n <p class=\"consent-banner-desc\">${descText}</p>\n <div class=\"consent-banner-links\">\n <a href=\"${cookiesUrl}\" target=\"_blank\" rel=\"noopener\">Política de cookies</a>\n <a href=\"${privacyUrl}\" target=\"_blank\" rel=\"noopener\">Política de privacidad</a>\n </div>\n </div>\n <div class=\"consent-banner-actions\">\n <button type=\"button\" class=\"consent-btn consent-btn-reject\" id=\"consent-btn-reject\">\n ${rejectText}\n </button>\n <button type=\"button\" class=\"consent-btn consent-btn-configure\" id=\"consent-btn-configure\">\n ${configureText}\n </button>\n <button type=\"button\" class=\"consent-btn consent-btn-accept\" id=\"consent-btn-accept\">\n ${acceptText}\n </button>\n </div>\n </div>\n `;\n\n wrapper\n .querySelector(\"#consent-btn-reject\")\n ?.addEventListener(\"click\", () => {\n handlers.onRejectAll();\n this.remove();\n });\n\n wrapper\n .querySelector(\"#consent-btn-configure\")\n ?.addEventListener(\"click\", () => {\n handlers.onConfigure();\n });\n\n wrapper\n .querySelector(\"#consent-btn-accept\")\n ?.addEventListener(\"click\", () => {\n handlers.onAcceptAll();\n this.remove();\n });\n\n document.body.appendChild(wrapper);\n this.element = wrapper;\n }\n\n remove(): void {\n if (this.element && this.element.parentNode) {\n this.element.parentNode.removeChild(this.element);\n this.element = null;\n }\n }\n}\n","import type { ConsentChoices, ConsentConfig } from \"../core/types.js\";\nimport { injectStyles } from \"./styles.js\";\nimport { sanitizeHtml } from \"../core/security.js\";\n\nexport interface PreferencesHandlers {\n onSave: (choices: ConsentChoices) => void;\n onAcceptAll: () => void;\n onRejectAll: () => void;\n onClose: () => void;\n}\n\nexport class PreferencesModal {\n private backdrop: HTMLElement | null = null;\n private lastFocusedElement: HTMLElement | null = null;\n\n render(\n config: ConsentConfig,\n currentChoices: ConsentChoices,\n handlers: PreferencesHandlers,\n ): void {\n if (typeof document === \"undefined\") return;\n this.close();\n injectStyles(config.csp?.nonce);\n\n this.lastFocusedElement = document.activeElement as HTMLElement;\n\n const prefConfig = config.ui?.preferences || {};\n const modalTitle = sanitizeHtml(prefConfig.title || \"Preferencias de privacidad\");\n const saveText = sanitizeHtml(prefConfig.save || \"Guardar selección\");\n const acceptAllText = sanitizeHtml(prefConfig.acceptAll || \"Permitir todas\");\n const rejectAllText = sanitizeHtml(prefConfig.rejectAll || \"Rechazar opcionales\");\n\n const backdrop = document.createElement(\"div\");\n backdrop.className = \"consent-dialog-backdrop\";\n\n const dialog = document.createElement(\"div\");\n dialog.className = \"consent-dialog\";\n dialog.setAttribute(\"role\", \"dialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", \"consent-dialog-title-id\");\n\n // Header\n const header = document.createElement(\"div\");\n header.className = \"consent-dialog-header\";\n header.innerHTML = `\n <div>\n <h2 class=\"consent-dialog-title\" id=\"consent-dialog-title-id\">${modalTitle}</h2>\n <p style=\"margin: 0.2rem 0 0 0; font-size: 0.84rem; color: var(--consent-muted); font-weight: 400;\">\n Gestiona tus permisos de almacenamiento por finalidad (LSSI art. 22.2 &amp; RGPD).\n </p>\n </div>\n <button type=\"button\" class=\"consent-dialog-close\" aria-label=\"Cerrar ventana\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n `;\n\n // Body (Seamless List Rows)\n const body = document.createElement(\"div\");\n body.className = \"consent-dialog-body\";\n\n const categoryChoices: ConsentChoices = { ...currentChoices };\n\n for (const [catId, catConfig] of Object.entries(config.categories)) {\n const catRow = document.createElement(\"div\");\n catRow.className = \"consent-category-row\";\n\n const isRequired = catConfig.required === true;\n const isChecked = isRequired ? true : (categoryChoices[catId] ?? false);\n\n const associatedServices = config.services\n ? Object.entries(config.services).filter(([_, srv]) => srv.category === catId)\n : [];\n\n let servicesHtml = \"\";\n if (associatedServices.length > 0) {\n servicesHtml = `\n <div class=\"consent-category-services\" id=\"cat-services-${catId}\" style=\"display: none; margin-top: 0.75rem; padding-top: 0.6rem; border-top: 1px dashed var(--consent-divider); font-size: 0.82rem;\">\n <div style=\"font-weight: 600; color: var(--consent-muted); margin-bottom: 0.4rem; font-size: 0.75rem; letter-spacing: 0.02em;\">\n Servicios incluidos (${associatedServices.length})\n </div>\n <div style=\"display: flex; flex-direction: column; gap: 0.3rem;\">\n ${associatedServices\n .map(\n ([srvId, srv]) => `\n <div style=\"display: flex; justify-content: space-between; align-items: center; padding: 0.2rem 0;\">\n <span style=\"font-weight: 500;\">${sanitizeHtml(srv.label || srvId)}</span>\n <span style=\"color: var(--consent-muted); font-size: 0.78rem;\">${sanitizeHtml(srv.provider || \"Terceros\")}</span>\n </div>\n `,\n )\n .join(\"\")}\n </div>\n </div>\n `;\n }\n\n catRow.innerHTML = `\n <div class=\"consent-category-header\">\n <div style=\"flex: 1; padding-right: 1rem;\">\n <div style=\"display: flex; align-items: center; gap: 0.4rem;\">\n <span class=\"consent-category-name\">${sanitizeHtml(catConfig.label)}</span>\n ${\n isRequired\n ? '<span class=\"consent-badge consent-badge-required\">Requerida</span>'\n : '<span class=\"consent-badge consent-badge-optional\">Opcional</span>'\n }\n </div>\n <p class=\"consent-category-desc\">${sanitizeHtml(catConfig.description)}</p>\n ${\n associatedServices.length > 0\n ? `<button type=\"button\" class=\"consent-toggle-services-btn\" data-target=\"cat-services-${catId}\">\n Ver servicios (${associatedServices.length}) ▾\n </button>`\n : \"\"\n }\n </div>\n <label class=\"consent-toggle\">\n <input type=\"checkbox\" id=\"cat-toggle-${catId}\" ${isChecked ? \"checked\" : \"\"} ${isRequired ? \"disabled\" : \"\"}>\n <span class=\"consent-toggle-slider\"></span>\n </label>\n </div>\n ${servicesHtml}\n `;\n\n if (!isRequired) {\n const checkbox = catRow.querySelector<HTMLInputElement>(\n `#cat-toggle-${catId}`,\n );\n checkbox?.addEventListener(\"change\", (e) => {\n categoryChoices[catId] = (e.target as HTMLInputElement).checked;\n });\n }\n\n const toggleServicesBtn = catRow.querySelector<HTMLButtonElement>(\n \".consent-toggle-services-btn\",\n );\n if (toggleServicesBtn) {\n toggleServicesBtn.addEventListener(\"click\", () => {\n const targetId = toggleServicesBtn.getAttribute(\"data-target\");\n if (targetId) {\n const targetEl = catRow.querySelector<HTMLElement>(`#${targetId}`);\n if (targetEl) {\n const isHidden = targetEl.style.display === \"none\";\n targetEl.style.display = isHidden ? \"block\" : \"none\";\n toggleServicesBtn.textContent = isHidden\n ? `Ocultar servicios (${associatedServices.length}) ▴`\n : `Ver servicios (${associatedServices.length}) ▾`;\n }\n }\n });\n }\n\n body.appendChild(catRow);\n }\n\n // Footer\n const footer = document.createElement(\"div\");\n footer.className = \"consent-dialog-footer\";\n footer.innerHTML = `\n <button type=\"button\" class=\"consent-btn consent-btn-reject\" id=\"consent-pref-reject\">\n ${rejectAllText}\n </button>\n <div style=\"display: flex; gap: 0.5rem; flex-wrap: wrap;\">\n <button type=\"button\" class=\"consent-btn consent-btn-configure\" id=\"consent-pref-accept\">\n ${acceptAllText}\n </button>\n <button type=\"button\" class=\"consent-btn consent-btn-accept\" id=\"consent-pref-save\">\n ${saveText}\n </button>\n </div>\n `;\n\n dialog.appendChild(header);\n dialog.appendChild(body);\n dialog.appendChild(footer);\n backdrop.appendChild(dialog);\n\n // Event listeners\n header\n .querySelector(\".consent-dialog-close\")\n ?.addEventListener(\"click\", () => {\n handlers.onClose();\n this.close();\n });\n\n footer\n .querySelector(\"#consent-pref-reject\")\n ?.addEventListener(\"click\", () => {\n handlers.onRejectAll();\n this.close();\n });\n\n footer\n .querySelector(\"#consent-pref-accept\")\n ?.addEventListener(\"click\", () => {\n handlers.onAcceptAll();\n this.close();\n });\n\n footer\n .querySelector(\"#consent-pref-save\")\n ?.addEventListener(\"click\", () => {\n handlers.onSave(categoryChoices);\n this.close();\n });\n\n // Keyboard navigation (Escape & Focus Trap)\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n handlers.onClose();\n this.close();\n return;\n }\n\n if (e.key === \"Tab\") {\n const focusableElements = dialog.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (e.shiftKey) {\n if (document.activeElement === firstElement) {\n lastElement?.focus();\n e.preventDefault();\n }\n } else {\n if (document.activeElement === lastElement) {\n firstElement?.focus();\n e.preventDefault();\n }\n }\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n (this as any)._keyListener = handleKeyDown;\n\n document.body.appendChild(backdrop);\n this.backdrop = backdrop;\n\n // Focus first element\n const firstFocusable = dialog.querySelector<HTMLElement>(\"button\");\n firstFocusable?.focus();\n }\n\n close(): void {\n if ((this as any)._keyListener) {\n document.removeEventListener(\"keydown\", (this as any)._keyListener);\n delete (this as any)._keyListener;\n }\n\n if (this.backdrop && this.backdrop.parentNode) {\n this.backdrop.parentNode.removeChild(this.backdrop);\n this.backdrop = null;\n }\n\n if (\n this.lastFocusedElement &&\n typeof this.lastFocusedElement.focus === \"function\"\n ) {\n this.lastFocusedElement.focus();\n this.lastFocusedElement = null;\n }\n }\n}\n","import type {\n ConsentChoices,\n ConsentConfig,\n ConsentEvent,\n ConsentEventHandler,\n ConsentReceipt,\n ConsentSDKInterface,\n ConsentState,\n DiagnosticReport,\n} from \"./types.js\";\nimport { validateConfig } from \"./config-validator.js\";\nimport { StateManager } from \"./state.js\";\nimport { EventBus } from \"./events.js\";\nimport { createReceipt, parseReceipt } from \"./receipt.js\";\nimport { evaluatePolicy } from \"./policy-engine.js\";\nimport { CookieStore } from \"../storage/cookie-store.js\";\nimport { MemoryStore } from \"../storage/memory-store.js\";\nimport { BlockerRegistry } from \"../blocker/registry.js\";\nimport { GoogleConsentAdapter } from \"../services/google.js\";\nimport { CustomServiceAdapter } from \"../services/custom.js\";\nimport { ConsentBanner } from \"../ui/banner.js\";\nimport { PreferencesModal } from \"../ui/preferences.js\";\nimport { ResourceScanner } from \"../diagnostics/resource-scanner.js\";\nimport { PolicyGenerator } from \"../ui/policy-generator.js\";\n\nexport class ConsentEngine implements ConsentSDKInterface {\n private stateManager = new StateManager();\n private eventBus = new EventBus();\n private blockerRegistry = new BlockerRegistry();\n private banner = new ConsentBanner();\n private preferencesModal = new PreferencesModal();\n\n private initPromise: Promise<void> | null = null;\n private resolveReady: (() => void) | null = null;\n private readyPromise = new Promise<void>((resolve) => {\n this.resolveReady = resolve;\n });\n\n async init(configInput: ConsentConfig | string): Promise<void> {\n if (this.initPromise) return this.initPromise;\n\n this.initPromise = (async () => {\n let config: ConsentConfig;\n\n if (typeof configInput === \"string\") {\n const response = await fetch(configInput);\n if (!response.ok) {\n throw new Error(\n `[ConsentSDK] Failed to fetch consent configuration from '${configInput}' (HTTP ${response.status})`,\n );\n }\n config = await response.json();\n } else {\n config = configInput;\n }\n\n validateConfig(config);\n\n // Load saved receipt from cookie or memory\n const cookieName = config.storage?.name || \"site_consent\";\n const rawReceipt =\n config.storage?.type === \"memory\"\n ? MemoryStore.get(cookieName)\n : CookieStore.get(cookieName);\n\n const savedReceipt = rawReceipt ? parseReceipt(rawReceipt) : null;\n const evalResult = evaluatePolicy(config, savedReceipt);\n\n const activeReceipt = evalResult.isValid ? savedReceipt : null;\n this.stateManager.init(config, evalResult.choices, activeReceipt);\n\n // Initialize Google Consent Mode defaults\n GoogleConsentAdapter.initDefault();\n if (evalResult.isValid) {\n GoogleConsentAdapter.update(evalResult.choices);\n this.dispatchDomEvent(\"solvenza:restored\", { state: this.getConsent() });\n }\n\n // Initialize Blocker System\n this.blockerRegistry.init(\n (cat) => this.has(cat),\n (srv) => this.hasService(srv),\n {\n onAllowClick: (category) => {\n const current = this.stateManager.getChoices();\n current[category] = true;\n this.setPreferences(current);\n },\n },\n (serviceId, category) => {\n this.eventBus.emit(\"service:loaded\", { serviceId, category });\n },\n );\n\n // Attach global listeners for permanent revocation trigger [data-consent-open] and CustomEvents\n this.setupGlobalRevocationTrigger();\n\n this.resolveReady?.();\n this.eventBus.emit(\"ready\", { state: this.getConsent() });\n\n // If missing receipt or policy version changed, display 1st layer banner\n if (!evalResult.isValid) {\n this.showBanner();\n }\n })();\n\n return this.initPromise;\n }\n\n async ready(): Promise<void> {\n return this.readyPromise;\n }\n\n getConsent(): ConsentState {\n return this.stateManager.getState();\n }\n\n has(category: string): boolean {\n return this.stateManager.hasCategory(category);\n }\n\n hasService(serviceId: string): boolean {\n return this.stateManager.hasService(serviceId);\n }\n\n acceptAll(): void {\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n const choices: ConsentChoices = {};\n for (const catId of Object.keys(config.categories)) {\n choices[catId] = true;\n }\n\n this.saveChoices(choices, \"banner\");\n this.eventBus.emit(\"consent:accepted\", {\n choices,\n receipt: this.getReceipt()!,\n });\n }\n\n rejectAll(): void {\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n const choices: ConsentChoices = {};\n for (const [catId, catConfig] of Object.entries(config.categories)) {\n choices[catId] = catConfig.required === true;\n }\n\n this.saveChoices(choices, \"banner\");\n this.eventBus.emit(\"consent:rejected\", {\n choices,\n receipt: this.getReceipt()!,\n });\n }\n\n setPreferences(choices: ConsentChoices): void {\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n // Enforce necessary = true\n const sanitizedChoices: ConsentChoices = { ...choices };\n sanitizedChoices[\"necessary\"] = true;\n\n this.saveChoices(sanitizedChoices, \"preferences\");\n }\n\n openPreferences(): void {\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n this.preferencesModal.render(config, this.stateManager.getChoices(), {\n onSave: (choices) => this.setPreferences(choices),\n onAcceptAll: () => this.acceptAll(),\n onRejectAll: () => this.rejectAll(),\n onClose: () => {\n this.eventBus.emit(\"preferences:closed\", undefined);\n },\n });\n\n this.eventBus.emit(\"preferences:opened\", undefined);\n }\n\n closePreferences(): void {\n this.preferencesModal.close();\n }\n\n withdraw(): void {\n const previousChoices = this.stateManager.getChoices();\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n const cookieName = config.storage?.name || \"site_consent\";\n if (config.storage?.type === \"memory\") {\n MemoryStore.remove(cookieName);\n } else {\n CookieStore.remove(cookieName, config.storage?.path || \"/\", config.storage?.domain);\n }\n\n // Auto-clear all service cookies for optional categories\n for (const catId of Object.keys(config.categories)) {\n if (catId !== \"necessary\") {\n CookieStore.clearServiceCookies(config, catId);\n }\n }\n\n this.stateManager.clearChoices();\n GoogleConsentAdapter.update(this.stateManager.getChoices());\n this.eventBus.emit(\"consent:withdrawn\", { previousChoices });\n this.dispatchDomEvent(\"solvenza:updated\", { choices: this.stateManager.getChoices() });\n\n this.showBanner();\n }\n\n when(categoryOrService: string, callback: () => void): () => void {\n return CustomServiceAdapter.createWhen(\n this.eventBus,\n (cat) => this.has(cat),\n (srv) => this.hasService(srv),\n )(categoryOrService, callback);\n }\n\n on<E extends ConsentEvent>(\n event: E,\n handler: ConsentEventHandler<E>,\n ): () => void {\n return this.eventBus.on(event, handler);\n }\n\n getReceipt(): ConsentReceipt | null {\n return this.stateManager.getReceipt();\n }\n\n rescan(): DiagnosticReport {\n const config = this.stateManager.getConfig();\n if (!config) {\n throw new Error(\"[ConsentSDK] SDK not initialized.\");\n }\n const isGiven = !!this.getReceipt();\n return ResourceScanner.runDiagnostic(config, isGiven);\n }\n\n mountPolicy(targetContainer: HTMLElement | string): void {\n const config = this.stateManager.getConfig();\n if (!config) {\n throw new Error(\"[ConsentSDK] SDK not initialized.\");\n }\n const container =\n typeof targetContainer === \"string\"\n ? document.querySelector<HTMLElement>(targetContainer)\n : targetContainer;\n if (container) {\n container.innerHTML = PolicyGenerator.renderTable(config);\n }\n }\n\n private saveChoices(\n choices: ConsentChoices,\n source: ConsentReceipt[\"source\"],\n ): void {\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n const receipt = createReceipt(\n config.policyVersion,\n choices,\n source,\n this.stateManager.getReceipt(),\n config.security?.secretKey,\n );\n\n this.stateManager.updateChoices(receipt);\n\n // Auto-clear cookies for revoked categories\n for (const [catId, isAllowed] of Object.entries(choices)) {\n if (!isAllowed) {\n CookieStore.clearServiceCookies(config, catId);\n }\n }\n\n // Persist receipt\n const cookieName = config.storage?.name || \"site_consent\";\n const receiptJson = JSON.stringify(receipt);\n\n if (config.storage?.type === \"memory\") {\n MemoryStore.set(cookieName, receiptJson);\n } else {\n CookieStore.set(cookieName, receiptJson, {\n path: config.storage?.path || \"/\",\n maxAgeDays: config.consent?.maxAgeDays ?? 365,\n sameSite: config.storage?.sameSite || \"Lax\",\n secure: config.storage?.secure,\n domain: config.storage?.domain,\n });\n }\n\n // Update Google Consent Mode\n GoogleConsentAdapter.update(choices);\n\n // Trigger blocker scan for newly permitted resources\n this.blockerRegistry.init(\n (cat) => this.has(cat),\n (srv) => this.hasService(srv),\n );\n\n // Optional receipt log endpoint\n if (config.logging?.enabled && config.logging.endpoint) {\n try {\n fetch(config.logging.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: receiptJson,\n }).catch(() => {});\n } catch {}\n }\n\n this.banner.remove();\n this.eventBus.emit(\"consent:changed\", { choices, receipt });\n this.dispatchDomEvent(\"solvenza:updated\", { choices, receipt });\n }\n\n private showBanner(): void {\n const config = this.stateManager.getConfig();\n if (!config) return;\n\n this.banner.render(config, {\n onAcceptAll: () => this.acceptAll(),\n onRejectAll: () => this.rejectAll(),\n onConfigure: () => this.openPreferences(),\n });\n this.eventBus.emit(\"banner:shown\", undefined);\n this.dispatchDomEvent(\"solvenza:show\", undefined);\n }\n\n private setupGlobalRevocationTrigger(): void {\n if (typeof document === \"undefined\") return;\n\n document.addEventListener(\"click\", (e) => {\n const target = e.target as HTMLElement | null;\n if (target?.closest(\"[data-consent-open]\")) {\n e.preventDefault();\n this.openPreferences();\n }\n });\n\n // Support zero-code DOM CustomEvents dispatching (e.g. document.dispatchEvent(new Event('solvenza:show')))\n document.addEventListener(\"solvenza:show\", () => {\n this.showBanner();\n });\n\n document.addEventListener(\"solvenza:preferences\", () => {\n this.openPreferences();\n });\n }\n\n private dispatchDomEvent(name: string, detail: unknown): void {\n if (typeof document === \"undefined\") return;\n try {\n const customEvent = new CustomEvent(name, { detail, bubbles: true });\n document.dispatchEvent(customEvent);\n } catch {}\n }\n}\n\n// Ensure global singleton instance across bundler chunks, wrappers, and HMR\nconst globalScope = typeof window !== \"undefined\" ? (window as any) : globalThis;\nif (!globalScope.__ConsentSDK_Instance__) {\n globalScope.__ConsentSDK_Instance__ = new ConsentEngine();\n}\n\nexport const Consent: ConsentEngine = globalScope.__ConsentSDK_Instance__;\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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","names":["_a"]}
@@ -37,6 +37,7 @@ interface ConsentConfig {
37
37
  sameSite?: "Strict" | "Lax" | "None";
38
38
  secure?: boolean;
39
39
  path?: string;
40
+ domain?: string;
40
41
  };
41
42
  consent?: {
42
43
  maxAgeDays?: number;
@@ -185,6 +186,7 @@ declare class ConsentEngine implements ConsentSDKInterface {
185
186
  private saveChoices;
186
187
  private showBanner;
187
188
  private setupGlobalRevocationTrigger;
189
+ private dispatchDomEvent;
188
190
  }
189
191
  declare const Consent: ConsentEngine;
190
192
 
@@ -37,6 +37,7 @@ interface ConsentConfig {
37
37
  sameSite?: "Strict" | "Lax" | "None";
38
38
  secure?: boolean;
39
39
  path?: string;
40
+ domain?: string;
40
41
  };
41
42
  consent?: {
42
43
  maxAgeDays?: number;
@@ -185,6 +186,7 @@ declare class ConsentEngine implements ConsentSDKInterface {
185
186
  private saveChoices;
186
187
  private showBanner;
187
188
  private setupGlobalRevocationTrigger;
189
+ private dispatchDomEvent;
188
190
  }
189
191
  declare const Consent: ConsentEngine;
190
192
 
@@ -472,8 +472,8 @@ var CookieStorageProvider = class {
472
472
  set(key, value, options) {
473
473
  CookieStore.set(key, value, options);
474
474
  }
475
- remove(key, path = "/") {
476
- CookieStore.remove(key, path);
475
+ remove(key, path = "/", domain) {
476
+ CookieStore.remove(key, path, domain);
477
477
  }
478
478
  };
479
479
  var CookieStore = class {
@@ -500,14 +500,34 @@ var CookieStore = class {
500
500
  const isHttps = typeof window !== "undefined" && window.location.protocol === "https:";
501
501
  const secure = (_b = options.secure) != null ? _b : isHttps;
502
502
  let cookieStr = `${encodeURIComponent(name)}=${encodeURIComponent(value)}; Path=${path}; Max-Age=${maxAgeSeconds}; SameSite=${sameSite}`;
503
+ if (options.domain) {
504
+ cookieStr += `; Domain=${options.domain}`;
505
+ }
503
506
  if (secure) {
504
507
  cookieStr += "; Secure";
505
508
  }
506
509
  document.cookie = cookieStr;
507
510
  }
508
- static remove(name, path = "/") {
511
+ static remove(name, path = "/", domain) {
509
512
  if (typeof document === "undefined") return;
510
- document.cookie = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=Lax`;
513
+ let cookieStr = `${encodeURIComponent(name)}=; Path=${path}; Max-Age=0; SameSite=Lax`;
514
+ if (domain) {
515
+ cookieStr += `; Domain=${domain}`;
516
+ }
517
+ document.cookie = cookieStr;
518
+ }
519
+ static clearServiceCookies(config, revokedCategory) {
520
+ var _a, _b;
521
+ if (typeof document === "undefined" || !config.services) return;
522
+ const path = ((_a = config.storage) == null ? void 0 : _a.path) || "/";
523
+ const domain = (_b = config.storage) == null ? void 0 : _b.domain;
524
+ for (const service of Object.values(config.services)) {
525
+ if (service.category === revokedCategory && service.cookies) {
526
+ for (const cookieItem of service.cookies) {
527
+ this.remove(cookieItem.name, path, domain || cookieItem.domain);
528
+ }
529
+ }
530
+ }
511
531
  }
512
532
  };
513
533
 
@@ -1692,6 +1712,7 @@ var ConsentEngine = class {
1692
1712
  GoogleConsentAdapter.initDefault();
1693
1713
  if (evalResult.isValid) {
1694
1714
  GoogleConsentAdapter.update(evalResult.choices);
1715
+ this.dispatchDomEvent("solvenza:restored", { state: this.getConsent() });
1695
1716
  }
1696
1717
  this.blockerRegistry.init(
1697
1718
  (cat) => this.has(cat),
@@ -1778,7 +1799,7 @@ var ConsentEngine = class {
1778
1799
  this.preferencesModal.close();
1779
1800
  }
1780
1801
  withdraw() {
1781
- var _a, _b;
1802
+ var _a, _b, _c, _d;
1782
1803
  const previousChoices = this.stateManager.getChoices();
1783
1804
  const config = this.stateManager.getConfig();
1784
1805
  if (!config) return;
@@ -1786,11 +1807,17 @@ var ConsentEngine = class {
1786
1807
  if (((_b = config.storage) == null ? void 0 : _b.type) === "memory") {
1787
1808
  MemoryStore.remove(cookieName);
1788
1809
  } else {
1789
- CookieStore.remove(cookieName);
1810
+ CookieStore.remove(cookieName, ((_c = config.storage) == null ? void 0 : _c.path) || "/", (_d = config.storage) == null ? void 0 : _d.domain);
1811
+ }
1812
+ for (const catId of Object.keys(config.categories)) {
1813
+ if (catId !== "necessary") {
1814
+ CookieStore.clearServiceCookies(config, catId);
1815
+ }
1790
1816
  }
1791
1817
  this.stateManager.clearChoices();
1792
1818
  GoogleConsentAdapter.update(this.stateManager.getChoices());
1793
1819
  this.eventBus.emit("consent:withdrawn", { previousChoices });
1820
+ this.dispatchDomEvent("solvenza:updated", { choices: this.stateManager.getChoices() });
1794
1821
  this.showBanner();
1795
1822
  }
1796
1823
  when(categoryOrService, callback) {
@@ -1825,7 +1852,7 @@ var ConsentEngine = class {
1825
1852
  }
1826
1853
  }
1827
1854
  saveChoices(choices, source) {
1828
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1855
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1829
1856
  const config = this.stateManager.getConfig();
1830
1857
  if (!config) return;
1831
1858
  const receipt = createReceipt(
@@ -1836,6 +1863,11 @@ var ConsentEngine = class {
1836
1863
  (_a = config.security) == null ? void 0 : _a.secretKey
1837
1864
  );
1838
1865
  this.stateManager.updateChoices(receipt);
1866
+ for (const [catId, isAllowed] of Object.entries(choices)) {
1867
+ if (!isAllowed) {
1868
+ CookieStore.clearServiceCookies(config, catId);
1869
+ }
1870
+ }
1839
1871
  const cookieName = ((_b = config.storage) == null ? void 0 : _b.name) || "site_consent";
1840
1872
  const receiptJson = JSON.stringify(receipt);
1841
1873
  if (((_c = config.storage) == null ? void 0 : _c.type) === "memory") {
@@ -1845,7 +1877,8 @@ var ConsentEngine = class {
1845
1877
  path: ((_d = config.storage) == null ? void 0 : _d.path) || "/",
1846
1878
  maxAgeDays: (_f = (_e = config.consent) == null ? void 0 : _e.maxAgeDays) != null ? _f : 365,
1847
1879
  sameSite: ((_g = config.storage) == null ? void 0 : _g.sameSite) || "Lax",
1848
- secure: (_h = config.storage) == null ? void 0 : _h.secure
1880
+ secure: (_h = config.storage) == null ? void 0 : _h.secure,
1881
+ domain: (_i = config.storage) == null ? void 0 : _i.domain
1849
1882
  });
1850
1883
  }
1851
1884
  GoogleConsentAdapter.update(choices);
@@ -1853,7 +1886,7 @@ var ConsentEngine = class {
1853
1886
  (cat) => this.has(cat),
1854
1887
  (srv) => this.hasService(srv)
1855
1888
  );
1856
- if (((_i = config.logging) == null ? void 0 : _i.enabled) && config.logging.endpoint) {
1889
+ if (((_j = config.logging) == null ? void 0 : _j.enabled) && config.logging.endpoint) {
1857
1890
  try {
1858
1891
  fetch(config.logging.endpoint, {
1859
1892
  method: "POST",
@@ -1866,6 +1899,7 @@ var ConsentEngine = class {
1866
1899
  }
1867
1900
  this.banner.remove();
1868
1901
  this.eventBus.emit("consent:changed", { choices, receipt });
1902
+ this.dispatchDomEvent("solvenza:updated", { choices, receipt });
1869
1903
  }
1870
1904
  showBanner() {
1871
1905
  const config = this.stateManager.getConfig();
@@ -1876,6 +1910,7 @@ var ConsentEngine = class {
1876
1910
  onConfigure: () => this.openPreferences()
1877
1911
  });
1878
1912
  this.eventBus.emit("banner:shown", void 0);
1913
+ this.dispatchDomEvent("solvenza:show", void 0);
1879
1914
  }
1880
1915
  setupGlobalRevocationTrigger() {
1881
1916
  if (typeof document === "undefined") return;
@@ -1886,6 +1921,20 @@ var ConsentEngine = class {
1886
1921
  this.openPreferences();
1887
1922
  }
1888
1923
  });
1924
+ document.addEventListener("solvenza:show", () => {
1925
+ this.showBanner();
1926
+ });
1927
+ document.addEventListener("solvenza:preferences", () => {
1928
+ this.openPreferences();
1929
+ });
1930
+ }
1931
+ dispatchDomEvent(name, detail) {
1932
+ if (typeof document === "undefined") return;
1933
+ try {
1934
+ const customEvent = new CustomEvent(name, { detail, bubbles: true });
1935
+ document.dispatchEvent(customEvent);
1936
+ } catch (e) {
1937
+ }
1889
1938
  }
1890
1939
  };
1891
1940
  var globalScope = typeof window !== "undefined" ? window : globalThis;