@disclos/sdk-web 0.1.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.
Files changed (84) hide show
  1. package/dist/batch-GICDMFCN.mjs +63 -0
  2. package/dist/batch-GICDMFCN.mjs.map +1 -0
  3. package/dist/batch-UBSRBBS5.cjs +65 -0
  4. package/dist/batch-UBSRBBS5.cjs.map +1 -0
  5. package/dist/cdn/sdk.min.global.js +122 -0
  6. package/dist/chatbot-banner-DGXTYL6P.cjs +15 -0
  7. package/dist/chatbot-banner-DGXTYL6P.cjs.map +1 -0
  8. package/dist/chatbot-banner-TN4LWAYQ.mjs +6 -0
  9. package/dist/chatbot-banner-TN4LWAYQ.mjs.map +1 -0
  10. package/dist/chunk-32Z4Q6ZD.cjs +68 -0
  11. package/dist/chunk-32Z4Q6ZD.cjs.map +1 -0
  12. package/dist/chunk-4JEHEDQP.mjs +56 -0
  13. package/dist/chunk-4JEHEDQP.mjs.map +1 -0
  14. package/dist/chunk-4KTDVK7J.cjs +53 -0
  15. package/dist/chunk-4KTDVK7J.cjs.map +1 -0
  16. package/dist/chunk-4QR2B5RG.cjs +46 -0
  17. package/dist/chunk-4QR2B5RG.cjs.map +1 -0
  18. package/dist/chunk-BHR3367P.mjs +48 -0
  19. package/dist/chunk-BHR3367P.mjs.map +1 -0
  20. package/dist/chunk-CZLDE2OZ.cjs +28 -0
  21. package/dist/chunk-CZLDE2OZ.cjs.map +1 -0
  22. package/dist/chunk-DG3Z3IAG.mjs +57 -0
  23. package/dist/chunk-DG3Z3IAG.mjs.map +1 -0
  24. package/dist/chunk-ESP33I43.mjs +67 -0
  25. package/dist/chunk-ESP33I43.mjs.map +1 -0
  26. package/dist/chunk-GFU3F3ZX.mjs +66 -0
  27. package/dist/chunk-GFU3F3ZX.mjs.map +1 -0
  28. package/dist/chunk-GYNG67I6.cjs +64 -0
  29. package/dist/chunk-GYNG67I6.cjs.map +1 -0
  30. package/dist/chunk-H724IVG6.cjs +119 -0
  31. package/dist/chunk-H724IVG6.cjs.map +1 -0
  32. package/dist/chunk-I7K3XSEO.cjs +71 -0
  33. package/dist/chunk-I7K3XSEO.cjs.map +1 -0
  34. package/dist/chunk-LNXULTZ5.mjs +62 -0
  35. package/dist/chunk-LNXULTZ5.mjs.map +1 -0
  36. package/dist/chunk-NFEGQTCC.mjs +24 -0
  37. package/dist/chunk-NFEGQTCC.mjs.map +1 -0
  38. package/dist/chunk-PZM26IE6.mjs +44 -0
  39. package/dist/chunk-PZM26IE6.mjs.map +1 -0
  40. package/dist/chunk-Q3245KZ2.cjs +58 -0
  41. package/dist/chunk-Q3245KZ2.cjs.map +1 -0
  42. package/dist/chunk-QOGWEWJP.cjs +62 -0
  43. package/dist/chunk-QOGWEWJP.cjs.map +1 -0
  44. package/dist/chunk-TTJMXFXE.cjs +186 -0
  45. package/dist/chunk-TTJMXFXE.cjs.map +1 -0
  46. package/dist/chunk-UU6VG7CJ.mjs +117 -0
  47. package/dist/chunk-UU6VG7CJ.mjs.map +1 -0
  48. package/dist/chunk-YJEYWPLR.mjs +182 -0
  49. package/dist/chunk-YJEYWPLR.mjs.map +1 -0
  50. package/dist/content-label-ITJPDODX.mjs +6 -0
  51. package/dist/content-label-ITJPDODX.mjs.map +1 -0
  52. package/dist/content-label-JFRT3OGU.cjs +15 -0
  53. package/dist/content-label-JFRT3OGU.cjs.map +1 -0
  54. package/dist/deepfake-marker-5FNO7W5J.cjs +15 -0
  55. package/dist/deepfake-marker-5FNO7W5J.cjs.map +1 -0
  56. package/dist/deepfake-marker-ILF66NVN.mjs +6 -0
  57. package/dist/deepfake-marker-ILF66NVN.mjs.map +1 -0
  58. package/dist/index.cjs +51 -0
  59. package/dist/index.cjs.map +1 -0
  60. package/dist/index.d.cts +157 -0
  61. package/dist/index.d.ts +157 -0
  62. package/dist/index.mjs +10 -0
  63. package/dist/index.mjs.map +1 -0
  64. package/dist/logger-IEU35PCN.cjs +14 -0
  65. package/dist/logger-IEU35PCN.cjs.map +1 -0
  66. package/dist/logger-X67CWRL4.mjs +5 -0
  67. package/dist/logger-X67CWRL4.mjs.map +1 -0
  68. package/dist/queue-CHODSJ4I.mjs +4 -0
  69. package/dist/queue-CHODSJ4I.mjs.map +1 -0
  70. package/dist/queue-LF4IPDT3.cjs +25 -0
  71. package/dist/queue-LF4IPDT3.cjs.map +1 -0
  72. package/dist/register-BA3KW4AJ.cjs +15 -0
  73. package/dist/register-BA3KW4AJ.cjs.map +1 -0
  74. package/dist/register-BBBSBMAF.mjs +13 -0
  75. package/dist/register-BBBSBMAF.mjs.map +1 -0
  76. package/dist/sender-EXBUUDTU.cjs +15 -0
  77. package/dist/sender-EXBUUDTU.cjs.map +1 -0
  78. package/dist/sender-RUX2MZKR.mjs +6 -0
  79. package/dist/sender-RUX2MZKR.mjs.map +1 -0
  80. package/dist/trust-page-HALUJVZU.cjs +15 -0
  81. package/dist/trust-page-HALUJVZU.cjs.map +1 -0
  82. package/dist/trust-page-NLFTM3WT.mjs +6 -0
  83. package/dist/trust-page-NLFTM3WT.mjs.map +1 -0
  84. package/package.json +60 -0
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __esm = (fn, res) => function __init() {
8
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
23
+
24
+ exports.__esm = __esm;
25
+ exports.__export = __export;
26
+ exports.__toCommonJS = __toCommonJS;
27
+ //# sourceMappingURL=chunk-CZLDE2OZ.cjs.map
28
+ //# sourceMappingURL=chunk-CZLDE2OZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-CZLDE2OZ.cjs"}
@@ -0,0 +1,57 @@
1
+ // src/log/queue.ts
2
+ var QUEUE_KEY = "disclos_event_queue";
3
+ var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
4
+ function isStorageAvailable() {
5
+ try {
6
+ const k = "__disclos_test__";
7
+ localStorage.setItem(k, "1");
8
+ localStorage.removeItem(k);
9
+ return true;
10
+ } catch {
11
+ return false;
12
+ }
13
+ }
14
+ function persistFailedBatch(events) {
15
+ if (!isStorageAvailable()) return;
16
+ try {
17
+ const queue = loadRawQueue();
18
+ const fresh = queue.filter((e) => Date.now() - e.savedAt < MAX_AGE_MS);
19
+ fresh.push({ events, savedAt: Date.now() });
20
+ localStorage.setItem(QUEUE_KEY, JSON.stringify(fresh));
21
+ } catch {
22
+ }
23
+ }
24
+ function loadQueue() {
25
+ return loadRawQueue().filter((e) => Date.now() - e.savedAt < MAX_AGE_MS);
26
+ }
27
+ function clearQueue() {
28
+ try {
29
+ localStorage.removeItem(QUEUE_KEY);
30
+ } catch {
31
+ }
32
+ }
33
+ function loadRawQueue() {
34
+ try {
35
+ const raw = localStorage.getItem(QUEUE_KEY);
36
+ if (!raw) return [];
37
+ return JSON.parse(raw);
38
+ } catch {
39
+ return [];
40
+ }
41
+ }
42
+ async function drainQueue() {
43
+ const entries = loadQueue();
44
+ if (entries.length === 0) return;
45
+ clearQueue();
46
+ const { sendBatch } = await import('./sender-RUX2MZKR.mjs');
47
+ for (const entry of entries) {
48
+ try {
49
+ await sendBatch(entry.events);
50
+ } catch {
51
+ }
52
+ }
53
+ }
54
+
55
+ export { clearQueue, drainQueue, loadQueue, persistFailedBatch };
56
+ //# sourceMappingURL=chunk-DG3Z3IAG.mjs.map
57
+ //# sourceMappingURL=chunk-DG3Z3IAG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/log/queue.ts"],"names":[],"mappings":";AAIA,IAAM,SAAA,GAAY,qBAAA;AAClB,IAAM,UAAA,GAAa,CAAA,GAAI,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAOtC,SAAS,kBAAA,GAA8B;AACrC,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,kBAAA;AACV,IAAA,YAAA,CAAa,OAAA,CAAQ,GAAG,GAAG,CAAA;AAC3B,IAAA,YAAA,CAAa,WAAW,CAAC,CAAA;AACzB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,mBAAmB,MAAA,EAA+B;AAChE,EAAA,IAAI,CAAC,oBAAmB,EAAG;AAC3B,EAAA,IAAI;AACF,IAAA,MAAM,QAAQ,YAAA,EAAa;AAE3B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,KAAK,GAAA,EAAI,GAAI,CAAA,CAAE,OAAA,GAAU,UAAU,CAAA;AACrE,IAAA,KAAA,CAAM,KAAK,EAAE,MAAA,EAAQ,SAAS,IAAA,CAAK,GAAA,IAAO,CAAA;AAC1C,IAAA,YAAA,CAAa,OAAA,CAAQ,SAAA,EAAW,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EACvD,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEO,SAAS,SAAA,GAA0B;AACxC,EAAA,OAAO,YAAA,EAAa,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,KAAK,GAAA,EAAI,GAAI,CAAA,CAAE,OAAA,GAAU,UAAU,CAAA;AACzE;AAEO,SAAS,UAAA,GAAmB;AACjC,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,WAAW,SAAS,CAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,SAAS,YAAA,GAA6B;AACpC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,SAAS,CAAA;AAC1C,IAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAC;AAClB,IAAA,OAAO,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAOA,eAAsB,UAAA,GAA4B;AAChD,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC1B,EAAA,UAAA,EAAW;AAGX,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,OAAO,uBAAU,CAAA;AAC7C,EAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,CAAU,MAAM,MAAM,CAAA;AAAA,IAC9B,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF","file":"chunk-DG3Z3IAG.mjs","sourcesContent":["// localStorage persistence queue — events survive page unload / transient network errors.\n// Drained on next init(). No network calls here; purely storage operations.\nimport type { InternalEvent } from '../core/types';\n\nconst QUEUE_KEY = 'disclos_event_queue';\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1_000; // 7 days\n\ninterface QueueEntry {\n events: InternalEvent[];\n savedAt: number;\n}\n\nfunction isStorageAvailable(): boolean {\n try {\n const k = '__disclos_test__';\n localStorage.setItem(k, '1');\n localStorage.removeItem(k);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function persistFailedBatch(events: InternalEvent[]): void {\n if (!isStorageAvailable()) return;\n try {\n const queue = loadRawQueue();\n // Prune expired entries and append the new one\n const fresh = queue.filter((e) => Date.now() - e.savedAt < MAX_AGE_MS);\n fresh.push({ events, savedAt: Date.now() });\n localStorage.setItem(QUEUE_KEY, JSON.stringify(fresh));\n } catch {\n /* storage quota exceeded */\n }\n}\n\nexport function loadQueue(): QueueEntry[] {\n return loadRawQueue().filter((e) => Date.now() - e.savedAt < MAX_AGE_MS);\n}\n\nexport function clearQueue(): void {\n try {\n localStorage.removeItem(QUEUE_KEY);\n } catch {\n /* noop */\n }\n}\n\nfunction loadRawQueue(): QueueEntry[] {\n try {\n const raw = localStorage.getItem(QUEUE_KEY);\n if (!raw) return [];\n return JSON.parse(raw) as QueueEntry[];\n } catch {\n return [];\n }\n}\n\n/**\n * Drains stored events from previous page sessions.\n * Called by init() after the batcher is ready.\n * Clears the queue before re-sending (prevents growth on persistent failure).\n */\nexport async function drainQueue(): Promise<void> {\n const entries = loadQueue();\n if (entries.length === 0) return;\n clearQueue();\n\n // Lazy-import sender to avoid circular deps\n const { sendBatch } = await import('./sender');\n for (const entry of entries) {\n try {\n await sendBatch(entry.events);\n } catch {\n /* best-effort — give up on entries that fail again */\n }\n }\n}\n"]}
@@ -0,0 +1,67 @@
1
+ import { init_state, getState } from './chunk-BHR3367P.mjs';
2
+
3
+ // src/log/logger.ts
4
+ init_state();
5
+
6
+ // src/log/anon.ts
7
+ async function hashSessionId(rawId, apiKeySalt) {
8
+ if (typeof crypto !== "undefined" && crypto.subtle) {
9
+ const data = new TextEncoder().encode(`${rawId}:${apiKeySalt}`);
10
+ const buf = await crypto.subtle.digest("SHA-256", data);
11
+ return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
12
+ }
13
+ return hashSessionIdSync(rawId, apiKeySalt);
14
+ }
15
+ function hashSessionIdSync(rawId, apiKeySalt) {
16
+ const input = `${rawId}:${apiKeySalt}`;
17
+ let h = 2166136261;
18
+ for (let i = 0; i < input.length; i++) {
19
+ h ^= input.charCodeAt(i);
20
+ h = Math.imul(h, 16777619) >>> 0;
21
+ }
22
+ const hex = h.toString(16).padStart(8, "0");
23
+ return hex + hex;
24
+ }
25
+
26
+ // src/log/logger.ts
27
+ function log(event) {
28
+ const state = getState();
29
+ if (!state.initialized) {
30
+ if (state.debug) {
31
+ console.warn("[Disclos] log() called before init() \u2014 event dropped. Call Disclos.init() first.");
32
+ }
33
+ return;
34
+ }
35
+ if (!state.batcher) return;
36
+ const rate = state.config?.samplingRate ?? 1;
37
+ if (rate < 1 && Math.random() > rate) return;
38
+ const sessionId = event.sessionId ? hashSessionIdSync(event.sessionId, state.apiKey) : void 0;
39
+ let metadata = event.metadata ?? {};
40
+ if (!state.logContent) {
41
+ const { content: _c, prompt: _p, response: _r, output: _o, ...safe } = metadata;
42
+ metadata = safe;
43
+ }
44
+ const internal = {
45
+ id: uid(),
46
+ api_key: state.apiKey,
47
+ ai_system_id: event.aiSystemId ?? state.aiSystemId,
48
+ event_type: event.type,
49
+ timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
50
+ session_id: sessionId,
51
+ payload: metadata
52
+ };
53
+ state.batcher.add(internal);
54
+ }
55
+ function uid() {
56
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
57
+ return crypto.randomUUID();
58
+ }
59
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
60
+ const r = Math.random() * 16 | 0;
61
+ return (c === "x" ? r : r & 3 | 8).toString(16);
62
+ });
63
+ }
64
+
65
+ export { hashSessionId, hashSessionIdSync, log };
66
+ //# sourceMappingURL=chunk-ESP33I43.mjs.map
67
+ //# sourceMappingURL=chunk-ESP33I43.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/log/logger.ts","../src/log/anon.ts"],"names":[],"mappings":";;;AACA,UAAA,EAAA;;;ACUA,eAAsB,aAAA,CAAc,OAAe,UAAA,EAAqC;AACtF,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,MAAA,EAAQ;AAClD,IAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY,CAAE,OAAO,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,UAAU,CAAA,CAAE,CAAA;AAC9D,IAAA,MAAM,MAAM,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,CAAA;AACtD,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,UAAA,CAAW,GAAG,CAAC,CAAA,CAClC,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA,CACP,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,iBAAA,CAAkB,OAAO,UAAU,CAAA;AAC5C;AAOO,SAAS,iBAAA,CAAkB,OAAe,UAAA,EAA4B;AAC3E,EAAA,MAAM,KAAA,GAAQ,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AACpC,EAAA,IAAI,CAAA,GAAI,UAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,CAAA,IAAK,KAAA,CAAM,WAAW,CAAC,CAAA;AACvB,IAAA,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,CAAA,EAAG,QAAU,CAAA,KAAM,CAAA;AAAA,EACnC;AAEA,EAAA,MAAM,MAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAC1C,EAAA,OAAO,GAAA,GAAM,GAAA;AACf;;;ADrBO,SAAS,IAAI,KAAA,EAAuB;AACzC,EAAA,MAAM,QAAQ,QAAA,EAAS;AAEvB,EAAA,IAAI,CAAC,MAAM,WAAA,EAAa;AACtB,IAAA,IAAI,MAAM,KAAA,EAAO;AACf,MAAA,OAAA,CAAQ,KAAK,uFAAkF,CAAA;AAAA,IACjG;AACA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAGpB,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,MAAA,EAAQ,YAAA,IAAgB,CAAA;AAC3C,EAAA,IAAI,IAAA,GAAO,CAAA,IAAO,IAAA,CAAK,MAAA,KAAW,IAAA,EAAM;AAGxC,EAAA,MAAM,SAAA,GAAY,MAAM,SAAA,GACpB,iBAAA,CAAkB,MAAM,SAAA,EAAW,KAAA,CAAM,MAAM,CAAA,GAC/C,MAAA;AAGJ,EAAA,IAAI,QAAA,GAAW,KAAA,CAAM,QAAA,IAAY,EAAC;AAClC,EAAA,IAAI,CAAC,MAAM,UAAA,EAAY;AACrB,IAAA,MAAM,EAAE,OAAA,EAAS,EAAA,EAAI,MAAA,EAAQ,EAAA,EAAI,QAAA,EAAU,EAAA,EAAI,MAAA,EAAQ,EAAA,EAAI,GAAG,IAAA,EAAK,GAAI,QAAA;AACvE,IAAA,QAAA,GAAW,IAAA;AAAA,EACb;AAEA,EAAA,MAAM,QAAA,GAA0B;AAAA,IAC9B,IAAI,GAAA,EAAI;AAAA,IACR,SAAS,KAAA,CAAM,MAAA;AAAA,IACf,YAAA,EAAc,KAAA,CAAM,UAAA,IAAc,KAAA,CAAM,UAAA;AAAA,IACxC,YAAY,KAAA,CAAM,IAAA;AAAA,IAClB,WAAW,KAAA,CAAM,SAAA,IAAA,iBAAa,IAAI,IAAA,IAAO,WAAA,EAAY;AAAA,IACrD,UAAA,EAAY,SAAA;AAAA,IACZ,OAAA,EAAS;AAAA,GACX;AAEA,EAAA,KAAA,CAAM,OAAA,CAAQ,IAAI,QAAQ,CAAA;AAC5B;AAGA,SAAS,GAAA,GAAc;AACrB,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,MAAA,CAAO,eAAe,UAAA,EAAY;AAC5E,IAAA,OAAO,OAAO,UAAA,EAAW;AAAA,EAC3B;AACA,EAAA,OAAO,sCAAA,CAAuC,OAAA,CAAQ,OAAA,EAAS,CAAC,CAAA,KAAM;AACpE,IAAA,MAAM,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAA,GAAM,CAAA;AACjC,IAAA,OAAA,CAAQ,MAAM,GAAA,GAAM,CAAA,GAAK,IAAI,CAAA,GAAO,CAAA,EAAK,SAAS,EAAE,CAAA;AAAA,EACtD,CAAC,CAAA;AACH","file":"chunk-ESP33I43.mjs","sourcesContent":["// Public logging primitive — the only API most SDK consumers will ever call\nimport { getState } from '../core/state';\nimport { hashSessionIdSync } from './anon';\nimport type { LogEvent, InternalEvent } from '../core/types';\n\n/**\n * Enqueues a compliance event for batched delivery to the Disclos ingestion plane.\n *\n * - Synchronous and non-blocking: event is added to the in-memory batcher\n * - Session ID is one-way hashed before it leaves the browser\n * - Content (prompts, responses) is stripped unless `logContent: true` was set in init()\n * - Safe to call before init() — emits a console warning and no-ops\n * - Respects the `samplingRate` from the remote config\n *\n * @example\n * Disclos.log({ type: 'ai_interaction', metadata: { model: 'gpt-4o', latency_ms: 312 } });\n */\nexport function log(event: LogEvent): void {\n const state = getState();\n\n if (!state.initialized) {\n if (state.debug) {\n console.warn('[Disclos] log() called before init() — event dropped. Call Disclos.init() first.');\n }\n return;\n }\n\n if (!state.batcher) return;\n\n // Sampling — respects remote config; default 1.0 (100%)\n const rate = state.config?.samplingRate ?? 1.0;\n if (rate < 1.0 && Math.random() > rate) return;\n\n // Anonymize session ID — one-way hash, never raw\n const sessionId = event.sessionId\n ? hashSessionIdSync(event.sessionId, state.apiKey)\n : undefined;\n\n // Strip content unless customer opted in\n let metadata = event.metadata ?? {};\n if (!state.logContent) {\n const { content: _c, prompt: _p, response: _r, output: _o, ...safe } = metadata as Record<string, unknown>;\n metadata = safe;\n }\n\n const internal: InternalEvent = {\n id: uid(),\n api_key: state.apiKey,\n ai_system_id: event.aiSystemId ?? state.aiSystemId,\n event_type: event.type,\n timestamp: event.timestamp ?? new Date().toISOString(),\n session_id: sessionId,\n payload: metadata,\n };\n\n state.batcher.add(internal);\n}\n\n/** Compact UUID v4 without external deps */\nfunction uid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n","// Session ID anonymization — one-way hash, never re-identifiable\n// Uses Web Crypto API (available in all target browsers + Workers)\n\n/**\n * Returns a 16-character hex one-way hash of the raw session ID.\n * Salted with the API key so the same session produces different\n * hashes across different Disclos customers — prevents cross-customer linkage.\n *\n * Async (uses SubtleCrypto). Falls back to synchronous FNV-1a if\n * SubtleCrypto is unavailable (rare edge case).\n */\nexport async function hashSessionId(rawId: string, apiKeySalt: string): Promise<string> {\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const data = new TextEncoder().encode(`${rawId}:${apiKeySalt}`);\n const buf = await crypto.subtle.digest('SHA-256', data);\n return Array.from(new Uint8Array(buf))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, 16);\n }\n return hashSessionIdSync(rawId, apiKeySalt);\n}\n\n/**\n * Synchronous fallback using FNV-1a 32-bit hash.\n * Only used when SubtleCrypto is unavailable (pre-Safari 14 legacy).\n * Deterministic and collision-resistant for our purposes.\n */\nexport function hashSessionIdSync(rawId: string, apiKeySalt: string): string {\n const input = `${rawId}:${apiKeySalt}`;\n let h = 2_166_136_261;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 16_777_619) >>> 0;\n }\n // Repeat to get 16 hex chars\n const hex = h.toString(16).padStart(8, '0');\n return hex + hex;\n}\n"]}
@@ -0,0 +1,66 @@
1
+ import { DisclosElement } from './chunk-YJEYWPLR.mjs';
2
+
3
+ // src/components/content-label.ts
4
+ var STYLES = `
5
+ :host {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: 4px;
9
+ font-family: var(--disclos-font, system-ui, sans-serif);
10
+ font-size: var(--disclos-label-size, 0.7rem);
11
+ font-weight: 500;
12
+ line-height: 1;
13
+ color: var(--disclos-label-text, #6b7280);
14
+ background: var(--disclos-label-bg, #f3f4f6);
15
+ border: 1px solid var(--disclos-label-border, #e5e7eb);
16
+ border-radius: var(--disclos-label-radius, 4px);
17
+ padding: var(--disclos-label-padding, 3px 7px);
18
+ white-space: nowrap;
19
+ cursor: default;
20
+ }
21
+ .icon { font-size: 0.85em; }
22
+ `;
23
+ var KIND_ICONS = {
24
+ text: "\u2726",
25
+ image: "\u{1F5BC}",
26
+ audio: "\u{1F50A}",
27
+ video: "\u{1F3AC}"
28
+ };
29
+ var ContentLabel = class extends DisclosElement {
30
+ static get observedAttributes() {
31
+ return ["kind"];
32
+ }
33
+ _html(config) {
34
+ const kind = this.getAttribute("kind") ?? "text";
35
+ const labels = config?.disclosures.contentLabel ?? {
36
+ text: "AI-generated text",
37
+ image: "AI-generated image",
38
+ audio: "AI-generated audio",
39
+ video: "AI-generated video"
40
+ };
41
+ const label = labels[kind] ?? labels.text;
42
+ const icon = KIND_ICONS[kind] ?? KIND_ICONS.text;
43
+ return `<style>${STYLES}</style>
44
+ <span class="icon" aria-hidden="true">${icon}</span>
45
+ <span>${label}</span>`;
46
+ }
47
+ _onVisible() {
48
+ void import('./logger-X67CWRL4.mjs').then(({ log }) => {
49
+ log({
50
+ type: "content_labeled",
51
+ metadata: {
52
+ component: "content-label",
53
+ content_type: this.getAttribute("kind") ?? "text",
54
+ label_method: "overlay"
55
+ }
56
+ });
57
+ });
58
+ }
59
+ };
60
+ if (!customElements.get("disclos-content-label")) {
61
+ customElements.define("disclos-content-label", ContentLabel);
62
+ }
63
+
64
+ export { ContentLabel };
65
+ //# sourceMappingURL=chunk-GFU3F3ZX.mjs.map
66
+ //# sourceMappingURL=chunk-GFU3F3ZX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/content-label.ts"],"names":[],"mappings":";;;AAOA,IAAM,MAAA,GAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAoBf,IAAM,UAAA,GAA0C;AAAA,EAC9C,IAAA,EAAM,QAAA;AAAA,EACN,KAAA,EAAO,WAAA;AAAA,EACP,KAAA,EAAO,WAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAA;AAEO,IAAM,YAAA,GAAN,cAA2B,cAAA,CAAe;AAAA,EAC/C,WAAW,kBAAA,GAA+B;AACxC,IAAA,OAAO,CAAC,MAAM,CAAA;AAAA,EAChB;AAAA,EAEU,MAAM,MAAA,EAAqC;AACnD,IAAA,MAAM,IAAA,GAAQ,IAAA,CAAK,YAAA,CAAa,MAAM,CAAA,IAAK,MAAA;AAC3C,IAAA,MAAM,MAAA,GAAS,MAAA,EAAQ,WAAA,CAAY,YAAA,IAAgB;AAAA,MACjD,IAAA,EAAM,mBAAA;AAAA,MACN,KAAA,EAAO,oBAAA;AAAA,MACP,KAAA,EAAO,oBAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AACA,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAI,CAAA,IAAK,MAAA,CAAO,IAAA;AACrC,IAAA,MAAM,IAAA,GAAO,UAAA,CAAW,IAAI,CAAA,IAAK,UAAA,CAAW,IAAA;AAE5C,IAAA,OAAO,UAAU,MAAM,CAAA;AAAA,sCAAA,EACa,IAAI,CAAA;AAAA,MAAA,EACpC,KAAK,CAAA,OAAA,CAAA;AAAA,EACX;AAAA,EAEU,UAAA,GAAmB;AAC3B,IAAA,KAAK,OAAO,uBAAe,CAAA,CAAE,KAAK,CAAC,EAAE,KAAI,KAAM;AAC7C,MAAA,GAAA,CAAI;AAAA,QACF,IAAA,EAAM,iBAAA;AAAA,QACN,QAAA,EAAU;AAAA,UACR,SAAA,EAAW,eAAA;AAAA,UACX,YAAA,EAAc,IAAA,CAAK,YAAA,CAAa,MAAM,CAAA,IAAK,MAAA;AAAA,UAC3C,YAAA,EAAc;AAAA;AAChB,OACD,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AACF;AAEA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,uBAAuB,CAAA,EAAG;AAChD,EAAA,cAAA,CAAe,MAAA,CAAO,yBAAyB,YAAY,CAAA;AAC7D","file":"chunk-GFU3F3ZX.mjs","sourcesContent":["// <disclos-content-label> — Article 50(2) AI-generated content badge\n// Inline badge; kind attribute controls the label text.\nimport { DisclosElement } from './base';\nimport type { RemoteConfig } from '../core/types';\n\ntype ContentKind = 'text' | 'image' | 'audio' | 'video';\n\nconst STYLES = `\n:host {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-family: var(--disclos-font, system-ui, sans-serif);\n font-size: var(--disclos-label-size, 0.7rem);\n font-weight: 500;\n line-height: 1;\n color: var(--disclos-label-text, #6b7280);\n background: var(--disclos-label-bg, #f3f4f6);\n border: 1px solid var(--disclos-label-border, #e5e7eb);\n border-radius: var(--disclos-label-radius, 4px);\n padding: var(--disclos-label-padding, 3px 7px);\n white-space: nowrap;\n cursor: default;\n}\n.icon { font-size: 0.85em; }\n`;\n\nconst KIND_ICONS: Record<ContentKind, string> = {\n text: '✦',\n image: '🖼',\n audio: '🔊',\n video: '🎬',\n};\n\nexport class ContentLabel extends DisclosElement {\n static get observedAttributes(): string[] {\n return ['kind'];\n }\n\n protected _html(config: RemoteConfig | null): string {\n const kind = (this.getAttribute('kind') ?? 'text') as ContentKind;\n const labels = config?.disclosures.contentLabel ?? {\n text: 'AI-generated text',\n image: 'AI-generated image',\n audio: 'AI-generated audio',\n video: 'AI-generated video',\n };\n const label = labels[kind] ?? labels.text;\n const icon = KIND_ICONS[kind] ?? KIND_ICONS.text;\n\n return `<style>${STYLES}</style>\n<span class=\"icon\" aria-hidden=\"true\">${icon}</span>\n<span>${label}</span>`;\n }\n\n protected _onVisible(): void {\n void import('../log/logger').then(({ log }) => {\n log({\n type: 'content_labeled',\n metadata: {\n component: 'content-label',\n content_type: this.getAttribute('kind') ?? 'text',\n label_method: 'overlay',\n },\n });\n });\n }\n}\n\nif (!customElements.get('disclos-content-label')) {\n customElements.define('disclos-content-label', ContentLabel);\n}\n"]}
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+
3
+ var chunkTTJMXFXE_cjs = require('./chunk-TTJMXFXE.cjs');
4
+
5
+ // src/components/deepfake-marker.ts
6
+ var STYLES = `
7
+ :host {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: 8px;
11
+ font-family: var(--disclos-font, system-ui, sans-serif);
12
+ font-size: var(--disclos-font-size, 0.8rem);
13
+ color: var(--disclos-deepfake-text, #92400e);
14
+ background: var(--disclos-deepfake-bg, #fffbeb);
15
+ border: 1px solid var(--disclos-deepfake-border, #fde68a);
16
+ border-radius: var(--disclos-radius, 6px);
17
+ padding: var(--disclos-padding, 8px 12px);
18
+ box-sizing: border-box;
19
+ }
20
+ .c2pa-badge {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ gap: 4px;
24
+ font-size: 0.7rem;
25
+ font-weight: 600;
26
+ color: var(--disclos-c2pa-text, #065f46);
27
+ background: var(--disclos-c2pa-bg, #d1fae5);
28
+ border-radius: 4px;
29
+ padding: 2px 6px;
30
+ margin-left: auto;
31
+ }
32
+ `;
33
+ var DeepfakeMarker = class extends chunkTTJMXFXE_cjs.DisclosElement {
34
+ static get observedAttributes() {
35
+ return ["c2pa-manifest"];
36
+ }
37
+ _html(config) {
38
+ const text = config?.disclosures.deepfake ?? "This content has been artificially generated or manipulated using AI.";
39
+ const hasManifest = !!this.getAttribute("c2pa-manifest");
40
+ const c2paBadge = hasManifest ? '<span class="c2pa-badge" title="C2PA provenance metadata present">\u2713 C2PA</span>' : "";
41
+ return `<style>${STYLES}</style>
42
+ <span aria-hidden="true">\u26A0\uFE0F</span>
43
+ <span role="note">${text}</span>
44
+ ${c2paBadge}`;
45
+ }
46
+ _onVisible() {
47
+ void import('./logger-IEU35PCN.cjs').then(({ log }) => {
48
+ log({
49
+ type: "disclosure_shown",
50
+ metadata: {
51
+ component: "deepfake-marker",
52
+ has_c2pa: !!this.getAttribute("c2pa-manifest")
53
+ }
54
+ });
55
+ });
56
+ }
57
+ };
58
+ if (!customElements.get("disclos-deepfake-marker")) {
59
+ customElements.define("disclos-deepfake-marker", DeepfakeMarker);
60
+ }
61
+
62
+ exports.DeepfakeMarker = DeepfakeMarker;
63
+ //# sourceMappingURL=chunk-GYNG67I6.cjs.map
64
+ //# sourceMappingURL=chunk-GYNG67I6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/deepfake-marker.ts"],"names":["DisclosElement"],"mappings":";;;;;AAKA,IAAM,MAAA,GAAS;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,CAAA;AA4BR,IAAM,cAAA,GAAN,cAA6BA,gCAAA,CAAe;AAAA,EACjD,WAAW,kBAAA,GAA+B;AACxC,IAAA,OAAO,CAAC,eAAe,CAAA;AAAA,EACzB;AAAA,EAEU,MAAM,MAAA,EAAqC;AACnD,IAAA,MAAM,IAAA,GAAO,MAAA,EAAQ,WAAA,CAAY,QAAA,IAC/B,uEAAA;AACF,IAAA,MAAM,WAAA,GAAc,CAAC,CAAC,IAAA,CAAK,aAAa,eAAe,CAAA;AAEvD,IAAA,MAAM,SAAA,GAAY,cACd,sFAAA,GACA,EAAA;AAEJ,IAAA,OAAO,UAAU,MAAM,CAAA;AAAA;AAAA,kBAAA,EAEP,IAAI,CAAA;AAAA,EACtB,SAAS,CAAA,CAAA;AAAA,EACT;AAAA,EAEU,UAAA,GAAmB;AAC3B,IAAA,KAAK,OAAO,uBAAe,CAAA,CAAE,KAAK,CAAC,EAAE,KAAI,KAAM;AAC7C,MAAA,GAAA,CAAI;AAAA,QACF,IAAA,EAAM,kBAAA;AAAA,QACN,QAAA,EAAU;AAAA,UACR,SAAA,EAAW,iBAAA;AAAA,UACX,QAAA,EAAU,CAAC,CAAC,IAAA,CAAK,aAAa,eAAe;AAAA;AAC/C,OACD,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AACF;AAEA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,yBAAyB,CAAA,EAAG;AAClD,EAAA,cAAA,CAAe,MAAA,CAAO,2BAA2B,cAAc,CAAA;AACjE","file":"chunk-GYNG67I6.cjs","sourcesContent":["// <disclos-deepfake-marker> — Article 50(3) synthetic media disclosure\n// Optional c2pa-manifest attribute for C2PA provenance verification (stub).\nimport { DisclosElement } from './base';\nimport type { RemoteConfig } from '../core/types';\n\nconst STYLES = `\n:host {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--disclos-font, system-ui, sans-serif);\n font-size: var(--disclos-font-size, 0.8rem);\n color: var(--disclos-deepfake-text, #92400e);\n background: var(--disclos-deepfake-bg, #fffbeb);\n border: 1px solid var(--disclos-deepfake-border, #fde68a);\n border-radius: var(--disclos-radius, 6px);\n padding: var(--disclos-padding, 8px 12px);\n box-sizing: border-box;\n}\n.c2pa-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 0.7rem;\n font-weight: 600;\n color: var(--disclos-c2pa-text, #065f46);\n background: var(--disclos-c2pa-bg, #d1fae5);\n border-radius: 4px;\n padding: 2px 6px;\n margin-left: auto;\n}\n`;\n\nexport class DeepfakeMarker extends DisclosElement {\n static get observedAttributes(): string[] {\n return ['c2pa-manifest'];\n }\n\n protected _html(config: RemoteConfig | null): string {\n const text = config?.disclosures.deepfake ??\n 'This content has been artificially generated or manipulated using AI.';\n const hasManifest = !!this.getAttribute('c2pa-manifest');\n\n const c2paBadge = hasManifest\n ? '<span class=\"c2pa-badge\" title=\"C2PA provenance metadata present\">✓ C2PA</span>'\n : '';\n\n return `<style>${STYLES}</style>\n<span aria-hidden=\"true\">⚠️</span>\n<span role=\"note\">${text}</span>\n${c2paBadge}`;\n }\n\n protected _onVisible(): void {\n void import('../log/logger').then(({ log }) => {\n log({\n type: 'disclosure_shown',\n metadata: {\n component: 'deepfake-marker',\n has_c2pa: !!this.getAttribute('c2pa-manifest'),\n },\n });\n });\n }\n}\n\nif (!customElements.get('disclos-deepfake-marker')) {\n customElements.define('disclos-deepfake-marker', DeepfakeMarker);\n}\n"]}
@@ -0,0 +1,119 @@
1
+ 'use strict';
2
+
3
+ var chunkTTJMXFXE_cjs = require('./chunk-TTJMXFXE.cjs');
4
+ var chunk4KTDVK7J_cjs = require('./chunk-4KTDVK7J.cjs');
5
+
6
+ // src/components/trust-page.ts
7
+ chunk4KTDVK7J_cjs.init_state();
8
+ var STYLES = `
9
+ :host {
10
+ display: block;
11
+ font-family: var(--disclos-font, system-ui, -apple-system, sans-serif);
12
+ color: var(--disclos-text, #111827);
13
+ max-width: var(--disclos-max-width, 860px);
14
+ margin: 0 auto;
15
+ padding: var(--disclos-padding, 2rem 1rem);
16
+ box-sizing: border-box;
17
+ }
18
+ .header { border-bottom: 2px solid #e5e7eb; padding-bottom: 1.5rem; margin-bottom: 2rem; }
19
+ .title { font-size: 1.75rem; font-weight: 700; margin: 0 0 0.5rem; }
20
+ .subtitle { color: #6b7280; margin: 0; font-size: 0.95rem; }
21
+ .system-grid { display: grid; gap: 1rem; }
22
+ .system-card {
23
+ border: 1px solid #e5e7eb; border-radius: 10px; padding: 1.25rem;
24
+ background: #fafafa;
25
+ }
26
+ .system-name { font-weight: 600; font-size: 1.05rem; margin: 0 0 0.5rem; }
27
+ .system-meta { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 0.75rem; }
28
+ .badge {
29
+ font-size: 0.72rem; font-weight: 500; padding: 2px 8px; border-radius: 99px;
30
+ background: #e0e7ff; color: #3730a3;
31
+ }
32
+ .badge.risk-high { background: #fee2e2; color: #991b1b; }
33
+ .badge.risk-limited { background: #fef3c7; color: #92400e; }
34
+ .badge.risk-minimal { background: #d1fae5; color: #065f46; }
35
+ .purpose { font-size: 0.875rem; color: #4b5563; }
36
+ .loading { text-align: center; padding: 3rem; color: #9ca3af; }
37
+ .error { text-align: center; padding: 2rem; color: #ef4444; font-size: 0.9rem; }
38
+ .footer { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #e5e7eb;
39
+ font-size: 0.75rem; color: #9ca3af; text-align: center; }
40
+ a { color: #2563eb; }
41
+ `;
42
+ var TrustPage = class extends chunkTTJMXFXE_cjs.DisclosElement {
43
+ constructor() {
44
+ super(...arguments);
45
+ this._data = null;
46
+ this._error = false;
47
+ this._loading = true;
48
+ }
49
+ static get observedAttributes() {
50
+ return ["ai-system-id"];
51
+ }
52
+ connectedCallback() {
53
+ super.connectedCallback();
54
+ void this._load();
55
+ }
56
+ _html(_config) {
57
+ if (this._loading) {
58
+ return `<style>${STYLES}</style><div class="loading">Loading AI transparency information\u2026</div>`;
59
+ }
60
+ if (this._error || !this._data) {
61
+ return `<style>${STYLES}</style><div class="error">Unable to load transparency information. Please try again later.</div>`;
62
+ }
63
+ const { org, systems } = this._data;
64
+ const systemCards = systems.map(renderSystemCard).join("");
65
+ return `<style>${STYLES}</style>
66
+ <div class="header">
67
+ <h1 class="title">${esc(org.name)} \u2014 AI Transparency</h1>
68
+ <p class="subtitle">Published AI System Inventory under the EU AI Act (Article 50)</p>
69
+ </div>
70
+ <div class="system-grid">${systemCards}</div>
71
+ <div class="footer">
72
+ Transparency information powered by <a href="https://disclos.dev" target="_blank" rel="noopener">Disclos</a>
73
+ \xB7 Last updated ${(/* @__PURE__ */ new Date()).toLocaleDateString()}
74
+ </div>`;
75
+ }
76
+ async _load() {
77
+ const state = chunk4KTDVK7J_cjs.getState();
78
+ const aiSystemId = this.getAttribute("ai-system-id") ?? state.aiSystemId;
79
+ try {
80
+ const url = new URL("https://cdn.disclos.dev/v1/trust-page");
81
+ url.searchParams.set("key", state.apiKey);
82
+ if (aiSystemId) url.searchParams.set("aiSystemId", aiSystemId);
83
+ const res = await fetch(url.toString(), { signal: AbortSignal.timeout(5e3) });
84
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
85
+ this._data = await res.json();
86
+ } catch {
87
+ this._error = true;
88
+ } finally {
89
+ this._loading = false;
90
+ if (this.shadowRoot) this.shadowRoot.innerHTML = this._html(this.getConfig());
91
+ }
92
+ }
93
+ };
94
+ function renderSystemCard(s) {
95
+ const riskClass = s.riskClassification.includes("high") ? "risk-high" : s.riskClassification.includes("limited") ? "risk-limited" : "risk-minimal";
96
+ const techniques = s.aiTechniques.map((t) => `<span class="badge">${esc(t)}</span>`).join("");
97
+ const euBadge = s.euUserExposure ? '<span class="badge">\u{1F1EA}\u{1F1FA} EU users</span>' : "";
98
+ return `
99
+ <div class="system-card" role="article">
100
+ <p class="system-name">${esc(s.name)}</p>
101
+ <div class="system-meta">
102
+ <span class="badge ${riskClass}">${esc(s.riskClassification.replace(/_/g, " "))}</span>
103
+ <span class="badge">${esc(s.role)}</span>
104
+ ${techniques}
105
+ ${euBadge}
106
+ </div>
107
+ ${s.purpose ? `<p class="purpose">${esc(s.purpose)}</p>` : ""}
108
+ </div>`;
109
+ }
110
+ function esc(s) {
111
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
112
+ }
113
+ if (!customElements.get("disclos-trust-page")) {
114
+ customElements.define("disclos-trust-page", TrustPage);
115
+ }
116
+
117
+ exports.TrustPage = TrustPage;
118
+ //# sourceMappingURL=chunk-H724IVG6.cjs.map
119
+ //# sourceMappingURL=chunk-H724IVG6.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/trust-page.ts"],"names":["init_state","DisclosElement","getState"],"mappings":"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","file":"chunk-H724IVG6.cjs","sourcesContent":["// <disclos-trust-page> — drop-in AI transparency page component\n// Lazy-fetches the customer's published AI System Inventory from the CDN.\n// Renders a polished, responsive, accessible page — no framework required.\nimport { DisclosElement } from './base';\nimport { getState } from '../core/state';\nimport type { RemoteConfig } from '../core/types';\n\nconst STYLES = `\n:host {\n display: block;\n font-family: var(--disclos-font, system-ui, -apple-system, sans-serif);\n color: var(--disclos-text, #111827);\n max-width: var(--disclos-max-width, 860px);\n margin: 0 auto;\n padding: var(--disclos-padding, 2rem 1rem);\n box-sizing: border-box;\n}\n.header { border-bottom: 2px solid #e5e7eb; padding-bottom: 1.5rem; margin-bottom: 2rem; }\n.title { font-size: 1.75rem; font-weight: 700; margin: 0 0 0.5rem; }\n.subtitle { color: #6b7280; margin: 0; font-size: 0.95rem; }\n.system-grid { display: grid; gap: 1rem; }\n.system-card {\n border: 1px solid #e5e7eb; border-radius: 10px; padding: 1.25rem;\n background: #fafafa;\n}\n.system-name { font-weight: 600; font-size: 1.05rem; margin: 0 0 0.5rem; }\n.system-meta { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 0.75rem; }\n.badge {\n font-size: 0.72rem; font-weight: 500; padding: 2px 8px; border-radius: 99px;\n background: #e0e7ff; color: #3730a3;\n}\n.badge.risk-high { background: #fee2e2; color: #991b1b; }\n.badge.risk-limited { background: #fef3c7; color: #92400e; }\n.badge.risk-minimal { background: #d1fae5; color: #065f46; }\n.purpose { font-size: 0.875rem; color: #4b5563; }\n.loading { text-align: center; padding: 3rem; color: #9ca3af; }\n.error { text-align: center; padding: 2rem; color: #ef4444; font-size: 0.9rem; }\n.footer { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #e5e7eb;\n font-size: 0.75rem; color: #9ca3af; text-align: center; }\na { color: #2563eb; }\n`;\n\nexport class TrustPage extends DisclosElement {\n private _data: TrustPageData | null = null;\n private _error = false;\n private _loading = true;\n\n static get observedAttributes(): string[] {\n return ['ai-system-id'];\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n void this._load();\n }\n\n protected _html(_config: RemoteConfig | null): string {\n if (this._loading) {\n return `<style>${STYLES}</style><div class=\"loading\">Loading AI transparency information…</div>`;\n }\n if (this._error || !this._data) {\n return `<style>${STYLES}</style><div class=\"error\">Unable to load transparency information. Please try again later.</div>`;\n }\n\n const { org, systems } = this._data;\n const systemCards = systems.map(renderSystemCard).join('');\n\n return `<style>${STYLES}</style>\n<div class=\"header\">\n <h1 class=\"title\">${esc(org.name)} — AI Transparency</h1>\n <p class=\"subtitle\">Published AI System Inventory under the EU AI Act (Article 50)</p>\n</div>\n<div class=\"system-grid\">${systemCards}</div>\n<div class=\"footer\">\n Transparency information powered by <a href=\"https://disclos.dev\" target=\"_blank\" rel=\"noopener\">Disclos</a>\n · Last updated ${new Date().toLocaleDateString()}\n</div>`;\n }\n\n private async _load(): Promise<void> {\n const state = getState();\n const aiSystemId = this.getAttribute('ai-system-id') ?? state.aiSystemId;\n\n try {\n const url = new URL('https://cdn.disclos.dev/v1/trust-page');\n url.searchParams.set('key', state.apiKey);\n if (aiSystemId) url.searchParams.set('aiSystemId', aiSystemId);\n\n const res = await fetch(url.toString(), { signal: AbortSignal.timeout(5_000) });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n this._data = (await res.json()) as TrustPageData;\n } catch {\n this._error = true;\n } finally {\n this._loading = false;\n // Trigger re-render\n if (this.shadowRoot) this.shadowRoot.innerHTML = this._html(this.getConfig());\n }\n }\n}\n\n// ── Data types ────────────────────────────────────────────────────────────────\n\ninterface TrustPageData {\n org: { name: string };\n systems: Array<{\n name: string;\n purpose: string;\n riskClassification: string;\n role: string;\n aiTechniques: string[];\n euUserExposure: boolean;\n }>;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction renderSystemCard(s: TrustPageData['systems'][number]): string {\n const riskClass = s.riskClassification.includes('high')\n ? 'risk-high'\n : s.riskClassification.includes('limited')\n ? 'risk-limited'\n : 'risk-minimal';\n const techniques = s.aiTechniques.map((t) => `<span class=\"badge\">${esc(t)}</span>`).join('');\n const euBadge = s.euUserExposure ? '<span class=\"badge\">🇪🇺 EU users</span>' : '';\n\n return `\n<div class=\"system-card\" role=\"article\">\n <p class=\"system-name\">${esc(s.name)}</p>\n <div class=\"system-meta\">\n <span class=\"badge ${riskClass}\">${esc(s.riskClassification.replace(/_/g, ' '))}</span>\n <span class=\"badge\">${esc(s.role)}</span>\n ${techniques}\n ${euBadge}\n </div>\n ${s.purpose ? `<p class=\"purpose\">${esc(s.purpose)}</p>` : ''}\n</div>`;\n}\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nif (!customElements.get('disclos-trust-page')) {\n customElements.define('disclos-trust-page', TrustPage);\n}\n"]}
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ var chunk4KTDVK7J_cjs = require('./chunk-4KTDVK7J.cjs');
4
+
5
+ // src/log/logger.ts
6
+ chunk4KTDVK7J_cjs.init_state();
7
+
8
+ // src/log/anon.ts
9
+ async function hashSessionId(rawId, apiKeySalt) {
10
+ if (typeof crypto !== "undefined" && crypto.subtle) {
11
+ const data = new TextEncoder().encode(`${rawId}:${apiKeySalt}`);
12
+ const buf = await crypto.subtle.digest("SHA-256", data);
13
+ return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
14
+ }
15
+ return hashSessionIdSync(rawId, apiKeySalt);
16
+ }
17
+ function hashSessionIdSync(rawId, apiKeySalt) {
18
+ const input = `${rawId}:${apiKeySalt}`;
19
+ let h = 2166136261;
20
+ for (let i = 0; i < input.length; i++) {
21
+ h ^= input.charCodeAt(i);
22
+ h = Math.imul(h, 16777619) >>> 0;
23
+ }
24
+ const hex = h.toString(16).padStart(8, "0");
25
+ return hex + hex;
26
+ }
27
+
28
+ // src/log/logger.ts
29
+ function log(event) {
30
+ const state = chunk4KTDVK7J_cjs.getState();
31
+ if (!state.initialized) {
32
+ if (state.debug) {
33
+ console.warn("[Disclos] log() called before init() \u2014 event dropped. Call Disclos.init() first.");
34
+ }
35
+ return;
36
+ }
37
+ if (!state.batcher) return;
38
+ const rate = state.config?.samplingRate ?? 1;
39
+ if (rate < 1 && Math.random() > rate) return;
40
+ const sessionId = event.sessionId ? hashSessionIdSync(event.sessionId, state.apiKey) : void 0;
41
+ let metadata = event.metadata ?? {};
42
+ if (!state.logContent) {
43
+ const { content: _c, prompt: _p, response: _r, output: _o, ...safe } = metadata;
44
+ metadata = safe;
45
+ }
46
+ const internal = {
47
+ id: uid(),
48
+ api_key: state.apiKey,
49
+ ai_system_id: event.aiSystemId ?? state.aiSystemId,
50
+ event_type: event.type,
51
+ timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
52
+ session_id: sessionId,
53
+ payload: metadata
54
+ };
55
+ state.batcher.add(internal);
56
+ }
57
+ function uid() {
58
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
59
+ return crypto.randomUUID();
60
+ }
61
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
62
+ const r = Math.random() * 16 | 0;
63
+ return (c === "x" ? r : r & 3 | 8).toString(16);
64
+ });
65
+ }
66
+
67
+ exports.hashSessionId = hashSessionId;
68
+ exports.hashSessionIdSync = hashSessionIdSync;
69
+ exports.log = log;
70
+ //# sourceMappingURL=chunk-I7K3XSEO.cjs.map
71
+ //# sourceMappingURL=chunk-I7K3XSEO.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/log/logger.ts","../src/log/anon.ts"],"names":["init_state","getState"],"mappings":"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","file":"chunk-I7K3XSEO.cjs","sourcesContent":["// Public logging primitive — the only API most SDK consumers will ever call\nimport { getState } from '../core/state';\nimport { hashSessionIdSync } from './anon';\nimport type { LogEvent, InternalEvent } from '../core/types';\n\n/**\n * Enqueues a compliance event for batched delivery to the Disclos ingestion plane.\n *\n * - Synchronous and non-blocking: event is added to the in-memory batcher\n * - Session ID is one-way hashed before it leaves the browser\n * - Content (prompts, responses) is stripped unless `logContent: true` was set in init()\n * - Safe to call before init() — emits a console warning and no-ops\n * - Respects the `samplingRate` from the remote config\n *\n * @example\n * Disclos.log({ type: 'ai_interaction', metadata: { model: 'gpt-4o', latency_ms: 312 } });\n */\nexport function log(event: LogEvent): void {\n const state = getState();\n\n if (!state.initialized) {\n if (state.debug) {\n console.warn('[Disclos] log() called before init() — event dropped. Call Disclos.init() first.');\n }\n return;\n }\n\n if (!state.batcher) return;\n\n // Sampling — respects remote config; default 1.0 (100%)\n const rate = state.config?.samplingRate ?? 1.0;\n if (rate < 1.0 && Math.random() > rate) return;\n\n // Anonymize session ID — one-way hash, never raw\n const sessionId = event.sessionId\n ? hashSessionIdSync(event.sessionId, state.apiKey)\n : undefined;\n\n // Strip content unless customer opted in\n let metadata = event.metadata ?? {};\n if (!state.logContent) {\n const { content: _c, prompt: _p, response: _r, output: _o, ...safe } = metadata as Record<string, unknown>;\n metadata = safe;\n }\n\n const internal: InternalEvent = {\n id: uid(),\n api_key: state.apiKey,\n ai_system_id: event.aiSystemId ?? state.aiSystemId,\n event_type: event.type,\n timestamp: event.timestamp ?? new Date().toISOString(),\n session_id: sessionId,\n payload: metadata,\n };\n\n state.batcher.add(internal);\n}\n\n/** Compact UUID v4 without external deps */\nfunction uid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n","// Session ID anonymization — one-way hash, never re-identifiable\n// Uses Web Crypto API (available in all target browsers + Workers)\n\n/**\n * Returns a 16-character hex one-way hash of the raw session ID.\n * Salted with the API key so the same session produces different\n * hashes across different Disclos customers — prevents cross-customer linkage.\n *\n * Async (uses SubtleCrypto). Falls back to synchronous FNV-1a if\n * SubtleCrypto is unavailable (rare edge case).\n */\nexport async function hashSessionId(rawId: string, apiKeySalt: string): Promise<string> {\n if (typeof crypto !== 'undefined' && crypto.subtle) {\n const data = new TextEncoder().encode(`${rawId}:${apiKeySalt}`);\n const buf = await crypto.subtle.digest('SHA-256', data);\n return Array.from(new Uint8Array(buf))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, 16);\n }\n return hashSessionIdSync(rawId, apiKeySalt);\n}\n\n/**\n * Synchronous fallback using FNV-1a 32-bit hash.\n * Only used when SubtleCrypto is unavailable (pre-Safari 14 legacy).\n * Deterministic and collision-resistant for our purposes.\n */\nexport function hashSessionIdSync(rawId: string, apiKeySalt: string): string {\n const input = `${rawId}:${apiKeySalt}`;\n let h = 2_166_136_261;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 16_777_619) >>> 0;\n }\n // Repeat to get 16 hex chars\n const hex = h.toString(16).padStart(8, '0');\n return hex + hex;\n}\n"]}
@@ -0,0 +1,62 @@
1
+ import { DisclosElement } from './chunk-YJEYWPLR.mjs';
2
+
3
+ // src/components/deepfake-marker.ts
4
+ var STYLES = `
5
+ :host {
6
+ display: flex;
7
+ align-items: center;
8
+ gap: 8px;
9
+ font-family: var(--disclos-font, system-ui, sans-serif);
10
+ font-size: var(--disclos-font-size, 0.8rem);
11
+ color: var(--disclos-deepfake-text, #92400e);
12
+ background: var(--disclos-deepfake-bg, #fffbeb);
13
+ border: 1px solid var(--disclos-deepfake-border, #fde68a);
14
+ border-radius: var(--disclos-radius, 6px);
15
+ padding: var(--disclos-padding, 8px 12px);
16
+ box-sizing: border-box;
17
+ }
18
+ .c2pa-badge {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ gap: 4px;
22
+ font-size: 0.7rem;
23
+ font-weight: 600;
24
+ color: var(--disclos-c2pa-text, #065f46);
25
+ background: var(--disclos-c2pa-bg, #d1fae5);
26
+ border-radius: 4px;
27
+ padding: 2px 6px;
28
+ margin-left: auto;
29
+ }
30
+ `;
31
+ var DeepfakeMarker = class extends DisclosElement {
32
+ static get observedAttributes() {
33
+ return ["c2pa-manifest"];
34
+ }
35
+ _html(config) {
36
+ const text = config?.disclosures.deepfake ?? "This content has been artificially generated or manipulated using AI.";
37
+ const hasManifest = !!this.getAttribute("c2pa-manifest");
38
+ const c2paBadge = hasManifest ? '<span class="c2pa-badge" title="C2PA provenance metadata present">\u2713 C2PA</span>' : "";
39
+ return `<style>${STYLES}</style>
40
+ <span aria-hidden="true">\u26A0\uFE0F</span>
41
+ <span role="note">${text}</span>
42
+ ${c2paBadge}`;
43
+ }
44
+ _onVisible() {
45
+ void import('./logger-X67CWRL4.mjs').then(({ log }) => {
46
+ log({
47
+ type: "disclosure_shown",
48
+ metadata: {
49
+ component: "deepfake-marker",
50
+ has_c2pa: !!this.getAttribute("c2pa-manifest")
51
+ }
52
+ });
53
+ });
54
+ }
55
+ };
56
+ if (!customElements.get("disclos-deepfake-marker")) {
57
+ customElements.define("disclos-deepfake-marker", DeepfakeMarker);
58
+ }
59
+
60
+ export { DeepfakeMarker };
61
+ //# sourceMappingURL=chunk-LNXULTZ5.mjs.map
62
+ //# sourceMappingURL=chunk-LNXULTZ5.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/deepfake-marker.ts"],"names":[],"mappings":";;;AAKA,IAAM,MAAA,GAAS;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,CAAA;AA4BR,IAAM,cAAA,GAAN,cAA6B,cAAA,CAAe;AAAA,EACjD,WAAW,kBAAA,GAA+B;AACxC,IAAA,OAAO,CAAC,eAAe,CAAA;AAAA,EACzB;AAAA,EAEU,MAAM,MAAA,EAAqC;AACnD,IAAA,MAAM,IAAA,GAAO,MAAA,EAAQ,WAAA,CAAY,QAAA,IAC/B,uEAAA;AACF,IAAA,MAAM,WAAA,GAAc,CAAC,CAAC,IAAA,CAAK,aAAa,eAAe,CAAA;AAEvD,IAAA,MAAM,SAAA,GAAY,cACd,sFAAA,GACA,EAAA;AAEJ,IAAA,OAAO,UAAU,MAAM,CAAA;AAAA;AAAA,kBAAA,EAEP,IAAI,CAAA;AAAA,EACtB,SAAS,CAAA,CAAA;AAAA,EACT;AAAA,EAEU,UAAA,GAAmB;AAC3B,IAAA,KAAK,OAAO,uBAAe,CAAA,CAAE,KAAK,CAAC,EAAE,KAAI,KAAM;AAC7C,MAAA,GAAA,CAAI;AAAA,QACF,IAAA,EAAM,kBAAA;AAAA,QACN,QAAA,EAAU;AAAA,UACR,SAAA,EAAW,iBAAA;AAAA,UACX,QAAA,EAAU,CAAC,CAAC,IAAA,CAAK,aAAa,eAAe;AAAA;AAC/C,OACD,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AACF;AAEA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,yBAAyB,CAAA,EAAG;AAClD,EAAA,cAAA,CAAe,MAAA,CAAO,2BAA2B,cAAc,CAAA;AACjE","file":"chunk-LNXULTZ5.mjs","sourcesContent":["// <disclos-deepfake-marker> — Article 50(3) synthetic media disclosure\n// Optional c2pa-manifest attribute for C2PA provenance verification (stub).\nimport { DisclosElement } from './base';\nimport type { RemoteConfig } from '../core/types';\n\nconst STYLES = `\n:host {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--disclos-font, system-ui, sans-serif);\n font-size: var(--disclos-font-size, 0.8rem);\n color: var(--disclos-deepfake-text, #92400e);\n background: var(--disclos-deepfake-bg, #fffbeb);\n border: 1px solid var(--disclos-deepfake-border, #fde68a);\n border-radius: var(--disclos-radius, 6px);\n padding: var(--disclos-padding, 8px 12px);\n box-sizing: border-box;\n}\n.c2pa-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 0.7rem;\n font-weight: 600;\n color: var(--disclos-c2pa-text, #065f46);\n background: var(--disclos-c2pa-bg, #d1fae5);\n border-radius: 4px;\n padding: 2px 6px;\n margin-left: auto;\n}\n`;\n\nexport class DeepfakeMarker extends DisclosElement {\n static get observedAttributes(): string[] {\n return ['c2pa-manifest'];\n }\n\n protected _html(config: RemoteConfig | null): string {\n const text = config?.disclosures.deepfake ??\n 'This content has been artificially generated or manipulated using AI.';\n const hasManifest = !!this.getAttribute('c2pa-manifest');\n\n const c2paBadge = hasManifest\n ? '<span class=\"c2pa-badge\" title=\"C2PA provenance metadata present\">✓ C2PA</span>'\n : '';\n\n return `<style>${STYLES}</style>\n<span aria-hidden=\"true\">⚠️</span>\n<span role=\"note\">${text}</span>\n${c2paBadge}`;\n }\n\n protected _onVisible(): void {\n void import('../log/logger').then(({ log }) => {\n log({\n type: 'disclosure_shown',\n metadata: {\n component: 'deepfake-marker',\n has_c2pa: !!this.getAttribute('c2pa-manifest'),\n },\n });\n });\n }\n}\n\nif (!customElements.get('disclos-deepfake-marker')) {\n customElements.define('disclos-deepfake-marker', DeepfakeMarker);\n}\n"]}