@nice2dev/ui-security 1.0.10

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/dist/index.mjs ADDED
@@ -0,0 +1,3997 @@
1
+ import { jsx as c, jsxs as R, Fragment as Re } from "react/jsx-runtime";
2
+ import { useContext as Ce, createContext as Pe, useRef as V, useState as j, useCallback as G, useEffect as te, useMemo as se } from "react";
3
+ const Ee = {
4
+ low: 0.7,
5
+ medium: 0.8,
6
+ high: 0.85,
7
+ critical: 0.95
8
+ }, Fe = {
9
+ matchThreshold: 0.85,
10
+ timeout: 3e4,
11
+ maxRetries: 3,
12
+ livenessDetection: !0,
13
+ verifyEndpoint: "",
14
+ authToken: "",
15
+ showFeedback: !0,
16
+ hapticFeedback: !0,
17
+ locale: "en",
18
+ securityLevel: "high",
19
+ antiSpoofing: !0
20
+ };
21
+ function de(e) {
22
+ const t = { ...Fe, ...e };
23
+ return e != null && e.matchThreshold || (t.matchThreshold = Ee[t.securityLevel]), t;
24
+ }
25
+ async function ce(e) {
26
+ const t = new TextEncoder().encode(e), r = await crypto.subtle.digest("SHA-256", t);
27
+ return Array.from(new Uint8Array(r)).map((n) => n.toString(16).padStart(2, "0")).join("");
28
+ }
29
+ function he(e = 8) {
30
+ const t = new Uint8Array(e);
31
+ return crypto.getRandomValues(t), Array.from(t).map((r) => r.toString(36).padStart(2, "0")).join("").slice(0, e);
32
+ }
33
+ function ze(e) {
34
+ const t = new Uint32Array(1);
35
+ return crypto.getRandomValues(t), t[0] % e;
36
+ }
37
+ function Ne(e, t) {
38
+ return Math.sqrt((e.x - t.x) ** 2 + (e.y - t.y) ** 2);
39
+ }
40
+ async function fe(e = "user") {
41
+ return navigator.mediaDevices.getUserMedia({
42
+ video: { facingMode: e, width: { ideal: 1280 }, height: { ideal: 720 } },
43
+ audio: !1
44
+ });
45
+ }
46
+ function ae(e, t, r) {
47
+ const n = t ?? e.videoWidth, i = r ?? e.videoHeight, s = document.createElement("canvas");
48
+ s.width = n, s.height = i;
49
+ const o = s.getContext("2d");
50
+ o.drawImage(e, 0, 0, n, i);
51
+ const a = o.getImageData(0, 0, n, i);
52
+ return { canvas: s, ctx: o, imageData: a };
53
+ }
54
+ function oe(e) {
55
+ const t = new Uint8Array(e.width * e.height), r = e.data;
56
+ for (let n = 0; n < t.length; n++) {
57
+ const i = n * 4;
58
+ t[n] = Math.round(0.299 * r[i] + 0.587 * r[i + 1] + 0.114 * r[i + 2]);
59
+ }
60
+ return t;
61
+ }
62
+ function Se(e, t, r) {
63
+ const n = new Uint8Array(t * r), i = [1, 2, 1, 2, 4, 2, 1, 2, 1], s = 16;
64
+ for (let o = 1; o < r - 1; o++)
65
+ for (let a = 1; a < t - 1; a++) {
66
+ let g = 0, v = 0;
67
+ for (let f = -1; f <= 1; f++)
68
+ for (let m = -1; m <= 1; m++)
69
+ g += e[(o + f) * t + (a + m)] * i[v++];
70
+ n[o * t + a] = Math.round(g / s);
71
+ }
72
+ return n;
73
+ }
74
+ function Le(e, t, r) {
75
+ const n = new Uint8Array(t * r);
76
+ for (let i = 1; i < r - 1; i++)
77
+ for (let s = 1; s < t - 1; s++) {
78
+ const o = -e[(i - 1) * t + (s - 1)] + e[(i - 1) * t + (s + 1)] + -2 * e[i * t + (s - 1)] + 2 * e[i * t + (s + 1)] + -e[(i + 1) * t + (s - 1)] + e[(i + 1) * t + (s + 1)], a = -e[(i - 1) * t + (s - 1)] - 2 * e[(i - 1) * t + s] - e[(i - 1) * t + (s + 1)] + e[(i + 1) * t + (s - 1)] + 2 * e[(i + 1) * t + s] + e[(i + 1) * t + (s + 1)];
79
+ n[i * t + s] = Math.min(255, Math.round(Math.sqrt(o * o + a * a)));
80
+ }
81
+ return n;
82
+ }
83
+ function $e(e) {
84
+ const t = new Array(256).fill(0);
85
+ for (const v of e)
86
+ t[v]++;
87
+ const r = e.length;
88
+ let n = 0;
89
+ for (let v = 0; v < 256; v++)
90
+ n += v * t[v];
91
+ let i = 0, s = 0, o = 0, a = 0;
92
+ for (let v = 0; v < 256; v++) {
93
+ if (s += t[v], s === 0)
94
+ continue;
95
+ const f = r - s;
96
+ if (f === 0)
97
+ break;
98
+ i += v * t[v];
99
+ const m = i / s, k = (n - i) / f, p = s * f * (m - k) ** 2;
100
+ p > o && (o = p, a = v);
101
+ }
102
+ const g = new Uint8Array(e.length);
103
+ for (let v = 0; v < e.length; v++)
104
+ g[v] = e[v] > a ? 255 : 0;
105
+ return { threshold: a, binary: g };
106
+ }
107
+ function je(e, t = 0.3) {
108
+ var y;
109
+ const r = e.width, n = e.height, i = oe(e), s = Se(i, r, n), o = Le(s, r, n), { binary: a } = $e(o), g = [], v = [], f = [];
110
+ for (let S = 2; S < n - 2; S++)
111
+ for (let u = 2; u < r - 2; u++) {
112
+ if (a[S * r + u] === 0)
113
+ continue;
114
+ const x = [
115
+ a[(S - 1) * r + u],
116
+ a[(S - 1) * r + (u + 1)],
117
+ a[S * r + (u + 1)],
118
+ a[(S + 1) * r + (u + 1)],
119
+ a[(S + 1) * r + u],
120
+ a[(S + 1) * r + (u - 1)],
121
+ a[S * r + (u - 1)],
122
+ a[(S - 1) * r + (u - 1)]
123
+ ];
124
+ let l = 0;
125
+ for (let W = 0; W < 8; W++) {
126
+ const H = x[W] > 0 ? 1 : 0, Z = x[(W + 1) % 8] > 0 ? 1 : 0;
127
+ l += Math.abs(H - Z);
128
+ }
129
+ l /= 2;
130
+ let h = 0, L = 0;
131
+ for (let W = -2; W <= 2; W++)
132
+ for (let H = -2; H <= 2; H++)
133
+ h += o[(S + W) * r + (u + H)], L++;
134
+ const q = h / L / 255;
135
+ if (q < t)
136
+ continue;
137
+ const Y = Math.atan2(
138
+ i[(S + 1) * r + u] - i[(S - 1) * r + u],
139
+ i[S * r + (u + 1)] - i[S * r + (u - 1)]
140
+ );
141
+ l === 1 ? g.push({ x: u / r, y: S / n, angle: Y, type: "ending", quality: q }) : l === 3 && g.push({ x: u / r, y: S / n, angle: Y, type: "bifurcation", quality: q });
142
+ }
143
+ g.sort((S, u) => u.quality - S.quality);
144
+ const m = g.slice(0, 120);
145
+ if (m.length > 5) {
146
+ const S = m.reduce((x, l) => x + l.x, 0) / m.length, u = m.reduce((x, l) => x + l.y, 0) / m.length;
147
+ v.push({ x: S, y: u });
148
+ }
149
+ const k = m.length, p = m.filter((S) => S.type === "ending").length, C = m.filter((S) => S.type === "bifurcation").length / (p + 1);
150
+ let b = "loop-right";
151
+ C > 1.5 ? b = "whorl" : C < 0.5 ? b = "arch" : ((y = v[0]) == null ? void 0 : y.x) < 0.45 && (b = "loop-left");
152
+ const T = m.length > 20 ? m.reduce((S, u) => S + u.quality, 0) / m.length : 0;
153
+ return {
154
+ minutiae: m,
155
+ corePoints: v,
156
+ deltaPoints: f,
157
+ ridgeCount: k,
158
+ patternType: b,
159
+ quality: T
160
+ };
161
+ }
162
+ function Be(e, t) {
163
+ if (e.minutiae.length < 5 || t.minutiae.length < 5)
164
+ return 0;
165
+ let r = 0;
166
+ const n = 0.05, i = 0.5, s = /* @__PURE__ */ new Set();
167
+ for (const a of e.minutiae) {
168
+ let g = 1 / 0, v = -1;
169
+ for (let f = 0; f < t.minutiae.length; f++) {
170
+ if (s.has(f))
171
+ continue;
172
+ const m = t.minutiae[f];
173
+ if (a.type !== m.type)
174
+ continue;
175
+ const k = Ne(a, m), p = Math.abs(a.angle - m.angle);
176
+ k < n && p < i && k < g && (g = k, v = f);
177
+ }
178
+ v >= 0 && (r++, s.add(v));
179
+ }
180
+ const o = Math.min(e.minutiae.length, t.minutiae.length);
181
+ return o > 0 ? r / o : 0;
182
+ }
183
+ async function We(e, t) {
184
+ const r = JSON.stringify(e), n = await ce(r);
185
+ return {
186
+ id: `fp_${Date.now()}_${he()}`,
187
+ method: "fingerprint",
188
+ templateData: btoa(r),
189
+ enrolled: Date.now(),
190
+ label: t,
191
+ hash: n
192
+ };
193
+ }
194
+ function _e(e) {
195
+ return JSON.parse(atob(e.templateData));
196
+ }
197
+ function Ue(e, t = "left") {
198
+ const r = e.width, n = e.height, i = oe(e), s = Se(i, r, n);
199
+ let o = { cx: r / 2, cy: n / 2, r: Math.min(r, n) * 0.08, score: 1 / 0 };
200
+ for (let D = Math.round(n * 0.3); D < Math.round(n * 0.7); D += 2)
201
+ for (let C = Math.round(r * 0.3); C < Math.round(r * 0.7); C += 2)
202
+ for (let b = Math.round(Math.min(r, n) * 0.04); b < Math.round(Math.min(r, n) * 0.15); b += 2) {
203
+ let T = 0, y = 0;
204
+ for (let l = 0; l < Math.PI * 2; l += 0.3) {
205
+ const h = Math.round(C + b * Math.cos(l)), L = Math.round(D + b * Math.sin(l));
206
+ h >= 0 && h < r && L >= 0 && L < n && (T += s[L * r + h], y++);
207
+ }
208
+ const S = y > 0 ? T / y : 255, u = s[D * r + C], x = S * 0.5 + u * 0.5;
209
+ x < o.score && (o = { cx: C, cy: D, r: b, score: x });
210
+ }
211
+ const a = o.r * 3, g = {
212
+ cx: o.cx,
213
+ cy: o.cy,
214
+ r: Math.min(a, Math.min(r, n) * 0.4)
215
+ }, v = 256, f = [];
216
+ for (let D = 0; D < v; D++) {
217
+ const C = D / v * Math.PI * 2, b = o.r + (g.r - o.r) * 0.5, T = Math.round(o.cx + b * Math.cos(C)), y = Math.round(o.cy + b * Math.sin(C));
218
+ if (T >= 0 && T < r && y >= 0 && y < n) {
219
+ const S = Math.round(o.cx + b * Math.cos(C + 0.1)), u = Math.round(o.cy + b * Math.sin(C + 0.1)), x = s[y * r + T], l = S >= 0 && S < r && u >= 0 && u < n ? s[u * r + S] : x;
220
+ f.push(x > l ? 1 : 0);
221
+ } else
222
+ f.push(0);
223
+ }
224
+ const m = f.join(""), k = Math.PI * o.r ** 2, p = Math.min(1, Math.max(0, k / (r * n) * 100));
225
+ return {
226
+ irisCode: m,
227
+ pupil: o,
228
+ iris: g,
229
+ quality: p,
230
+ eye: t
231
+ };
232
+ }
233
+ function He(e, t) {
234
+ if (!e.irisCode || !t.irisCode)
235
+ return 0;
236
+ const r = Math.min(e.irisCode.length, t.irisCode.length);
237
+ if (r === 0)
238
+ return 0;
239
+ let n = 0, i = r;
240
+ for (let o = -8; o <= 8; o++) {
241
+ let a = 0;
242
+ for (let g = 0; g < r; g++) {
243
+ const v = (g + o + r) % r;
244
+ e.irisCode[g] !== t.irisCode[v] && a++;
245
+ }
246
+ a < i && (i = a);
247
+ }
248
+ n = i;
249
+ const s = n / r;
250
+ return Math.max(0, 1 - s * 2.5);
251
+ }
252
+ async function Oe(e, t) {
253
+ const r = JSON.stringify(e), n = await ce(r);
254
+ return {
255
+ id: `iris_${Date.now()}_${he()}`,
256
+ method: "iris",
257
+ templateData: btoa(r),
258
+ enrolled: Date.now(),
259
+ label: t,
260
+ hash: n
261
+ };
262
+ }
263
+ function qe(e) {
264
+ return JSON.parse(atob(e.templateData));
265
+ }
266
+ function ue(e) {
267
+ const t = e.width, r = e.height, n = e.data, i = new Uint8Array(t * r);
268
+ for (let u = 0; u < t * r; u++) {
269
+ const x = u * 4, l = n[x], h = n[x + 1], L = n[x + 2], q = 0.299 * l + 0.587 * h + 0.114 * L, Y = 128 - 0.169 * l - 0.331 * h + 0.5 * L, W = 128 + 0.5 * l - 0.419 * h - 0.081 * L;
270
+ Y >= 77 && Y <= 127 && W >= 133 && W <= 173 && q > 80 && (i[u] = 1);
271
+ }
272
+ let s = t, o = r, a = 0, g = 0, v = 0;
273
+ for (let u = 0; u < r; u++)
274
+ for (let x = 0; x < t; x++)
275
+ i[u * t + x] && (v++, x < s && (s = x), x > a && (a = x), u < o && (o = u), u > g && (g = u));
276
+ const f = a - s, m = g - o;
277
+ if (f < t * 0.1 || m < r * 0.1)
278
+ return null;
279
+ const k = { x: s, y: o, width: f, height: m }, p = [], D = oe(e), C = Math.max(1, Math.floor(f / 8)), b = Math.max(1, Math.floor(m / 16));
280
+ for (let u = 0; u < 16; u++)
281
+ for (let x = 0; x < 8; x++) {
282
+ const l = s + x * C + Math.floor(C / 2), h = o + u * b + Math.floor(b / 2);
283
+ l < t && h < r ? p.push(D[h * t + l] / 255) : p.push(0);
284
+ }
285
+ const T = [], y = { x: s + f / 2, y: o + m / 2 };
286
+ for (let u = 0; u < 68; u++) {
287
+ const x = u / 68 * Math.PI * 2, l = f * 0.4 * Math.cos(x), h = m * 0.45 * Math.sin(x);
288
+ T.push({
289
+ x: (y.x + l) / t,
290
+ y: (y.y + h) / r
291
+ });
292
+ }
293
+ const S = Math.min(1, v / (f * m) * 2);
294
+ return {
295
+ embedding: p,
296
+ boundingBox: k,
297
+ landmarks: T,
298
+ headPose: { yaw: 0, pitch: 0, roll: 0 },
299
+ quality: S
300
+ };
301
+ }
302
+ function ke(e, t) {
303
+ if (e.embedding.length !== t.embedding.length)
304
+ return 0;
305
+ let r = 0, n = 0, i = 0;
306
+ for (let o = 0; o < e.embedding.length; o++)
307
+ r += e.embedding[o] * t.embedding[o], n += e.embedding[o] ** 2, i += t.embedding[o] ** 2;
308
+ const s = Math.sqrt(n) * Math.sqrt(i);
309
+ return s > 0 ? (r / s + 1) / 2 : 0;
310
+ }
311
+ function Ke(e, t) {
312
+ const r = ue(e), n = ue(t);
313
+ return !r || !n ? { similarity: 0, cameraFeatures: r, refFeatures: n } : { similarity: ke(r, n), cameraFeatures: r, refFeatures: n };
314
+ }
315
+ async function Ge(e, t) {
316
+ const r = JSON.stringify(e), n = await ce(r);
317
+ return {
318
+ id: `face_${Date.now()}_${he()}`,
319
+ method: "face",
320
+ templateData: btoa(r),
321
+ enrolled: Date.now(),
322
+ label: t,
323
+ hash: n
324
+ };
325
+ }
326
+ function Je(e) {
327
+ return JSON.parse(atob(e.templateData));
328
+ }
329
+ function It() {
330
+ const e = [
331
+ "blink",
332
+ "smile",
333
+ "turn-left",
334
+ "turn-right",
335
+ "nod",
336
+ "raise-eyebrows"
337
+ ], t = e[ze(e.length)];
338
+ return { type: t, instruction: {
339
+ blink: "Please blink your eyes",
340
+ smile: "Please smile",
341
+ "turn-left": "Please turn your head left",
342
+ "turn-right": "Please turn your head right",
343
+ nod: "Please nod your head",
344
+ "raise-eyebrows": "Please raise your eyebrows"
345
+ }[t], completed: !1, confidence: 0 };
346
+ }
347
+ function Ae(e, t = 0.02) {
348
+ if (e.length < 2)
349
+ return { isLive: !1, confidence: 0, motionScore: 0 };
350
+ let r = 0;
351
+ for (let o = 1; o < e.length; o++) {
352
+ const a = oe(e[o - 1]), g = oe(e[o]);
353
+ let v = 0;
354
+ for (let f = 0; f < a.length; f++)
355
+ v += Math.abs(a[f] - g[f]);
356
+ r += v / (a.length * 255);
357
+ }
358
+ const n = r / (e.length - 1), i = n > t, s = Math.min(1, n / (t * 3));
359
+ return { isLive: i, confidence: s, motionScore: n };
360
+ }
361
+ function Te() {
362
+ return {
363
+ userAgent: navigator.userAgent,
364
+ platform: navigator.platform,
365
+ language: navigator.language,
366
+ screenResolution: [screen.width, screen.height],
367
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
368
+ touchSupport: "ontouchstart" in window || navigator.maxTouchPoints > 0,
369
+ hardwareConcurrency: navigator.hardwareConcurrency ?? 0
370
+ };
371
+ }
372
+ async function le() {
373
+ const e = Te(), t = JSON.stringify(e);
374
+ return ce(t);
375
+ }
376
+ function Ie() {
377
+ return typeof window < "u" && !!window.PublicKeyCredential;
378
+ }
379
+ async function Ze() {
380
+ if (!Ie())
381
+ return !1;
382
+ try {
383
+ return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
384
+ } catch {
385
+ return !1;
386
+ }
387
+ }
388
+ async function Ye(e) {
389
+ const t = {
390
+ rp: { name: e.rpName, id: e.rpId },
391
+ user: {
392
+ id: new TextEncoder().encode(e.userId),
393
+ name: e.userName,
394
+ displayName: e.userDisplayName
395
+ },
396
+ challenge: e.challenge,
397
+ pubKeyCredParams: [
398
+ { alg: -7, type: "public-key" },
399
+ // ES256
400
+ { alg: -257, type: "public-key" }
401
+ // RS256
402
+ ],
403
+ authenticatorSelection: {
404
+ authenticatorAttachment: "platform",
405
+ userVerification: "required",
406
+ residentKey: "preferred"
407
+ },
408
+ timeout: e.timeout ?? 6e4,
409
+ attestation: "none"
410
+ };
411
+ return await navigator.credentials.create({ publicKey: t });
412
+ }
413
+ async function Xe(e) {
414
+ const t = {
415
+ rpId: e.rpId,
416
+ challenge: e.challenge,
417
+ allowCredentials: e.allowCredentials,
418
+ userVerification: "required",
419
+ timeout: e.timeout ?? 6e4
420
+ };
421
+ return await navigator.credentials.get({ publicKey: t });
422
+ }
423
+ async function ye(e, t, r) {
424
+ const n = { "Content-Type": "application/json" };
425
+ r && (n.Authorization = `Bearer ${r}`);
426
+ const i = await fetch(e, {
427
+ method: "POST",
428
+ headers: n,
429
+ body: JSON.stringify(t)
430
+ });
431
+ return i.ok ? i.json() : { verified: !1, message: `Server error: ${i.status}` };
432
+ }
433
+ const Qe = (e, t) => t, De = Pe(Qe), Dt = ({ t: e, children: t }) => /* @__PURE__ */ c(De.Provider, { value: e, children: t });
434
+ function ee() {
435
+ return { t: Ce(De) };
436
+ }
437
+ const Ve = { sm: 200, md: 280, lg: 380 }, Mt = (e) => {
438
+ const {
439
+ mode: t,
440
+ enrolledTemplates: r = [],
441
+ fingerPosition: n = "right-index",
442
+ onEnroll: i,
443
+ onVerify: s,
444
+ onStatusChange: o,
445
+ onError: a,
446
+ className: g,
447
+ size: v = "md",
448
+ label: f,
449
+ showQuality: m = !0,
450
+ showMinutiae: k = !1,
451
+ instructionText: p,
452
+ cameraFacing: D = "environment",
453
+ ...C
454
+ } = e, { t: b } = ee(), T = de(C), y = Ve[v], S = V(null), u = V(null), x = V(null), [l, h] = j("idle"), [L, q] = j(0), [Y, W] = j(null), [H, Z] = j(0), [_, $] = j(""), B = G(
455
+ (E) => {
456
+ h(E), o == null || o(E);
457
+ },
458
+ [o]
459
+ ), F = G(async () => {
460
+ try {
461
+ const E = await fe(D);
462
+ x.current = E, S.current && (S.current.srcObject = E, await S.current.play()), B("idle"), $(b("security.fingerprint.placeFingerPrompt", "Place your finger on the scanner"));
463
+ } catch (E) {
464
+ a == null || a(E instanceof Error ? E : new Error(String(E))), $(b("security.fingerprint.cameraError", "Camera access denied")), B("error");
465
+ }
466
+ }, [D, b, B, a]), K = G(() => {
467
+ var E;
468
+ (E = x.current) == null || E.getTracks().forEach((I) => I.stop()), x.current = null;
469
+ }, []);
470
+ te(() => (F(), K), [F, K]);
471
+ const U = G(async () => {
472
+ if (!(!S.current || l === "processing" || l === "success")) {
473
+ B("scanning"), $(b("security.fingerprint.scanning", "Scanning…"));
474
+ try {
475
+ const { imageData: E } = ae(S.current);
476
+ B("processing"), $(b("security.fingerprint.processing", "Processing fingerprint…"));
477
+ const I = je(E);
478
+ if (W(I), q(I.quality), I.quality < 0.2) {
479
+ $(b("security.fingerprint.lowQuality", "Low quality — try again")), B("idle");
480
+ return;
481
+ }
482
+ if (t === "enroll") {
483
+ const z = await We(I, f ?? n);
484
+ i == null || i(z, I), $(b("security.fingerprint.enrolled", "Fingerprint enrolled successfully")), B("success");
485
+ } else {
486
+ let z = 0;
487
+ for (const d of r) {
488
+ const A = _e(d), N = Be(I, A);
489
+ N > z && (z = N);
490
+ }
491
+ const M = z >= T.matchThreshold, w = {
492
+ success: M,
493
+ confidence: z,
494
+ method: "fingerprint",
495
+ timestamp: Date.now(),
496
+ duration: 0,
497
+ payload: btoa(JSON.stringify(I))
498
+ };
499
+ if (M && T.verifyEndpoint) {
500
+ const d = await le(), A = await ye(
501
+ T.verifyEndpoint,
502
+ {
503
+ method: "fingerprint",
504
+ templateData: w.payload,
505
+ matchScore: z,
506
+ deviceFingerprint: d
507
+ },
508
+ T.authToken
509
+ );
510
+ w.success = A.verified;
511
+ }
512
+ w.success ? ($(b("security.fingerprint.verified", "Fingerprint verified")), B("success")) : (Z((d) => d + 1), H + 1 >= T.maxRetries ? ($(b("security.fingerprint.maxAttempts", "Maximum attempts reached")), B("failure")) : ($(b("security.fingerprint.noMatch", "No match — try again")), B("idle"))), s == null || s(w);
513
+ }
514
+ } catch (E) {
515
+ a == null || a(E instanceof Error ? E : new Error(String(E))), $(b("security.fingerprint.error", "Scan error — try again")), B("error");
516
+ }
517
+ }
518
+ }, [
519
+ l,
520
+ t,
521
+ r,
522
+ T,
523
+ b,
524
+ B,
525
+ i,
526
+ s,
527
+ a,
528
+ f,
529
+ n,
530
+ H
531
+ ]);
532
+ te(() => {
533
+ if (!k || !Y || !u.current)
534
+ return;
535
+ const E = u.current.getContext("2d");
536
+ E && (E.clearRect(0, 0, y, y), Y.minutiae.forEach((I) => {
537
+ E.beginPath(), E.arc(I.x * y, I.y * y, 2, 0, Math.PI * 2), E.fillStyle = I.type === "ending" ? "#10b981" : "#f59e0b", E.fill(), E.beginPath(), E.moveTo(I.x * y, I.y * y), E.lineTo(I.x * y + Math.cos(I.angle) * 8, I.y * y + Math.sin(I.angle) * 8), E.strokeStyle = E.fillStyle, E.lineWidth = 1, E.stroke();
538
+ }));
539
+ }, [Y, k, y]);
540
+ const X = l === "success" ? "var(--security-success)" : l === "failure" || l === "error" ? "var(--security-error)" : l === "scanning" || l === "processing" ? "var(--security-biometric)" : "var(--security-border)";
541
+ return /* @__PURE__ */ R(
542
+ "div",
543
+ {
544
+ className: g,
545
+ style: { display: "inline-flex", flexDirection: "column", alignItems: "center", gap: 12 },
546
+ children: [
547
+ f && /* @__PURE__ */ c("div", { style: { fontSize: 14, fontWeight: 600, color: "var(--security-text)" }, children: f }),
548
+ /* @__PURE__ */ R(
549
+ "div",
550
+ {
551
+ style: {
552
+ width: y,
553
+ height: y,
554
+ position: "relative",
555
+ borderRadius: "var(--security-radius-lg)",
556
+ overflow: "hidden",
557
+ border: `3px solid ${X}`,
558
+ boxShadow: l === "scanning" ? `0 0 20px ${X}` : "var(--security-shadow)",
559
+ transition: "border-color 0.3s, box-shadow 0.3s"
560
+ },
561
+ children: [
562
+ /* @__PURE__ */ c(
563
+ "video",
564
+ {
565
+ ref: S,
566
+ style: { width: "100%", height: "100%", objectFit: "cover" },
567
+ playsInline: !0,
568
+ muted: !0
569
+ }
570
+ ),
571
+ k && /* @__PURE__ */ c(
572
+ "canvas",
573
+ {
574
+ ref: u,
575
+ width: y,
576
+ height: y,
577
+ style: { position: "absolute", inset: 0, pointerEvents: "none" }
578
+ }
579
+ ),
580
+ /* @__PURE__ */ R(
581
+ "svg",
582
+ {
583
+ viewBox: "0 0 100 100",
584
+ style: {
585
+ position: "absolute",
586
+ inset: 0,
587
+ width: "100%",
588
+ height: "100%",
589
+ pointerEvents: "none",
590
+ opacity: 0.3
591
+ },
592
+ children: [
593
+ /* @__PURE__ */ c(
594
+ "ellipse",
595
+ {
596
+ cx: "50",
597
+ cy: "50",
598
+ rx: "28",
599
+ ry: "38",
600
+ fill: "none",
601
+ stroke: "white",
602
+ strokeWidth: "1",
603
+ strokeDasharray: "4 3"
604
+ }
605
+ ),
606
+ /* @__PURE__ */ c(
607
+ "ellipse",
608
+ {
609
+ cx: "50",
610
+ cy: "50",
611
+ rx: "20",
612
+ ry: "28",
613
+ fill: "none",
614
+ stroke: "white",
615
+ strokeWidth: "0.5",
616
+ strokeDasharray: "2 3"
617
+ }
618
+ )
619
+ ]
620
+ }
621
+ ),
622
+ (l === "scanning" || l === "processing") && /* @__PURE__ */ c(
623
+ "div",
624
+ {
625
+ style: {
626
+ position: "absolute",
627
+ inset: 0,
628
+ display: "flex",
629
+ alignItems: "center",
630
+ justifyContent: "center",
631
+ background: "rgba(0,0,0,0.3)"
632
+ },
633
+ children: /* @__PURE__ */ c(
634
+ "div",
635
+ {
636
+ style: {
637
+ width: 60,
638
+ height: 60,
639
+ borderRadius: "50%",
640
+ border: "3px solid transparent",
641
+ borderTopColor: X,
642
+ animation: "spin 0.8s linear infinite"
643
+ }
644
+ }
645
+ )
646
+ }
647
+ )
648
+ ]
649
+ }
650
+ ),
651
+ m && L > 0 && /* @__PURE__ */ c(
652
+ "div",
653
+ {
654
+ style: {
655
+ width: y,
656
+ height: 4,
657
+ background: "var(--security-bg-panel)",
658
+ borderRadius: 2,
659
+ overflow: "hidden"
660
+ },
661
+ children: /* @__PURE__ */ c(
662
+ "div",
663
+ {
664
+ style: {
665
+ width: `${L * 100}%`,
666
+ height: "100%",
667
+ background: L > 0.6 ? "var(--security-success)" : L > 0.3 ? "var(--security-warning)" : "var(--security-error)",
668
+ transition: "width 0.3s"
669
+ }
670
+ }
671
+ )
672
+ }
673
+ ),
674
+ /* @__PURE__ */ c(
675
+ "div",
676
+ {
677
+ style: {
678
+ fontSize: 13,
679
+ color: "var(--security-text-secondary)",
680
+ textAlign: "center",
681
+ minHeight: 20
682
+ },
683
+ children: p ?? _
684
+ }
685
+ ),
686
+ l !== "success" && l !== "failure" && /* @__PURE__ */ c(
687
+ "button",
688
+ {
689
+ onClick: U,
690
+ disabled: l === "scanning" || l === "processing",
691
+ style: {
692
+ padding: "10px 24px",
693
+ fontSize: 14,
694
+ fontWeight: 600,
695
+ background: "var(--security-biometric)",
696
+ color: "#fff",
697
+ border: "none",
698
+ borderRadius: "var(--security-radius)",
699
+ cursor: "pointer",
700
+ opacity: l === "scanning" || l === "processing" ? 0.6 : 1
701
+ },
702
+ children: t === "enroll" ? b("security.fingerprint.captureBtn", "🖐️ Capture Fingerprint") : b("security.fingerprint.verifyBtn", "🖐️ Verify Fingerprint")
703
+ }
704
+ ),
705
+ (l === "failure" || l === "error") && /* @__PURE__ */ c(
706
+ "button",
707
+ {
708
+ onClick: () => {
709
+ Z(0), B("idle"), $("");
710
+ },
711
+ style: {
712
+ padding: "8px 20px",
713
+ fontSize: 13,
714
+ background: "var(--security-bg-panel)",
715
+ color: "var(--security-text)",
716
+ border: "1px solid var(--security-border)",
717
+ borderRadius: "var(--security-radius)",
718
+ cursor: "pointer"
719
+ },
720
+ children: b("security.common.retry", "Try Again")
721
+ }
722
+ ),
723
+ /* @__PURE__ */ c("style", { children: "@keyframes spin { to { transform: rotate(360deg); } }" })
724
+ ]
725
+ }
726
+ );
727
+ }, et = { sm: 220, md: 300, lg: 400 }, Rt = (e) => {
728
+ const {
729
+ mode: t,
730
+ enrolledTemplates: r = [],
731
+ eye: n = "right",
732
+ onEnroll: i,
733
+ onVerify: s,
734
+ onStatusChange: o,
735
+ onError: a,
736
+ className: g,
737
+ size: v = "md",
738
+ label: f,
739
+ showQuality: m = !0,
740
+ showSegmentation: k = !0,
741
+ showGuide: p = !0,
742
+ instructionText: D,
743
+ ...C
744
+ } = e, { t: b } = ee(), T = de(C), y = et[v], S = V(null), u = V(null), x = V(null), l = V([]), [h, L] = j("idle"), [q, Y] = j(0), [W, H] = j(null), [Z, _] = j(0), [$, B] = j(""), F = G(
745
+ (I) => {
746
+ L(I), o == null || o(I);
747
+ },
748
+ [o]
749
+ ), K = G(async () => {
750
+ try {
751
+ const I = await fe("user");
752
+ x.current = I, S.current && (S.current.srcObject = I, await S.current.play()), F("idle"), B(b("security.iris.alignEyePrompt", "Align your eye with the circle"));
753
+ } catch (I) {
754
+ a == null || a(I instanceof Error ? I : new Error(String(I))), B(b("security.iris.cameraError", "Camera access denied")), F("error");
755
+ }
756
+ }, [b, F, a]), U = G(() => {
757
+ var I;
758
+ (I = x.current) == null || I.getTracks().forEach((z) => z.stop()), x.current = null;
759
+ }, []);
760
+ te(() => (K(), U), [K, U]);
761
+ const X = G(async () => {
762
+ if (!(!S.current || h === "processing" || h === "success")) {
763
+ F("scanning"), B(b("security.iris.scanning", "Scanning iris…"));
764
+ try {
765
+ const I = [];
766
+ for (let w = 0; w < 5; w++) {
767
+ const { imageData: d } = ae(S.current);
768
+ I.push(d), await new Promise((A) => setTimeout(A, 200));
769
+ }
770
+ if (l.current = I, T.livenessDetection && !Ae(I).isLive) {
771
+ B(
772
+ b("security.iris.notLive", "Liveness check failed — please blink or move slightly")
773
+ ), F("idle");
774
+ return;
775
+ }
776
+ F("processing"), B(b("security.iris.processing", "Processing iris pattern…"));
777
+ const z = I[I.length - 1], M = Ue(z, n === "both" ? "left" : n);
778
+ if (!M) {
779
+ B(b("security.iris.noIrisDetected", "No iris detected — adjust position")), F("idle");
780
+ return;
781
+ }
782
+ if (H(M), Y(M.quality), M.quality < 0.1) {
783
+ B(b("security.iris.lowQuality", "Low quality — move closer")), F("idle");
784
+ return;
785
+ }
786
+ if (k && u.current) {
787
+ const w = u.current.getContext("2d");
788
+ if (w) {
789
+ w.clearRect(0, 0, y, y);
790
+ const d = y / z.width, A = y / z.height;
791
+ w.beginPath(), w.arc(
792
+ M.pupil.cx * d,
793
+ M.pupil.cy * A,
794
+ M.pupil.r * d,
795
+ 0,
796
+ Math.PI * 2
797
+ ), w.strokeStyle = "#ef4444", w.lineWidth = 2, w.stroke(), w.beginPath(), w.arc(
798
+ M.iris.cx * d,
799
+ M.iris.cy * A,
800
+ M.iris.r * d,
801
+ 0,
802
+ Math.PI * 2
803
+ ), w.strokeStyle = "#3b82f6", w.lineWidth = 2, w.stroke();
804
+ }
805
+ }
806
+ if (t === "enroll") {
807
+ const w = await Oe(M, f ?? `${n} eye`);
808
+ i == null || i(w, M), B(b("security.iris.enrolled", "Iris enrolled successfully")), F("success");
809
+ } else {
810
+ let w = 0;
811
+ for (const N of r) {
812
+ const P = qe(N), O = He(M, P);
813
+ O > w && (w = O);
814
+ }
815
+ const d = w >= T.matchThreshold, A = {
816
+ success: d,
817
+ confidence: w,
818
+ method: "iris",
819
+ timestamp: Date.now(),
820
+ duration: 0,
821
+ livenessPassed: T.livenessDetection ? !0 : void 0,
822
+ payload: btoa(JSON.stringify(M))
823
+ };
824
+ if (d && T.verifyEndpoint) {
825
+ const N = await le(), P = await ye(
826
+ T.verifyEndpoint,
827
+ {
828
+ method: "iris",
829
+ templateData: A.payload,
830
+ matchScore: w,
831
+ deviceFingerprint: N
832
+ },
833
+ T.authToken
834
+ );
835
+ A.success = P.verified;
836
+ }
837
+ A.success ? (B(b("security.iris.verified", "Iris verified")), F("success")) : (_((N) => N + 1), Z + 1 >= T.maxRetries ? (B(b("security.iris.maxAttempts", "Maximum attempts reached")), F("failure")) : (B(b("security.iris.noMatch", "No match — try again")), F("idle"))), s == null || s(A);
838
+ }
839
+ } catch (I) {
840
+ a == null || a(I instanceof Error ? I : new Error(String(I))), B(b("security.iris.error", "Scan error")), F("error");
841
+ }
842
+ }
843
+ }, [
844
+ h,
845
+ t,
846
+ r,
847
+ T,
848
+ b,
849
+ F,
850
+ i,
851
+ s,
852
+ a,
853
+ f,
854
+ n,
855
+ Z,
856
+ k,
857
+ y
858
+ ]), E = h === "success" ? "var(--security-success)" : h === "failure" || h === "error" ? "var(--security-error)" : h === "scanning" || h === "processing" ? "var(--security-biometric)" : "var(--security-border)";
859
+ return /* @__PURE__ */ R(
860
+ "div",
861
+ {
862
+ className: g,
863
+ style: { display: "inline-flex", flexDirection: "column", alignItems: "center", gap: 12 },
864
+ children: [
865
+ f && /* @__PURE__ */ c("div", { style: { fontSize: 14, fontWeight: 600, color: "var(--security-text)" }, children: f }),
866
+ /* @__PURE__ */ R(
867
+ "div",
868
+ {
869
+ style: {
870
+ width: y,
871
+ height: y,
872
+ position: "relative",
873
+ borderRadius: "50%",
874
+ overflow: "hidden",
875
+ border: `3px solid ${E}`,
876
+ boxShadow: h === "scanning" ? `0 0 30px ${E}` : "var(--security-shadow)",
877
+ transition: "border-color 0.3s, box-shadow 0.3s"
878
+ },
879
+ children: [
880
+ /* @__PURE__ */ c(
881
+ "video",
882
+ {
883
+ ref: S,
884
+ style: { width: "100%", height: "100%", objectFit: "cover" },
885
+ playsInline: !0,
886
+ muted: !0
887
+ }
888
+ ),
889
+ k && /* @__PURE__ */ c(
890
+ "canvas",
891
+ {
892
+ ref: u,
893
+ width: y,
894
+ height: y,
895
+ style: { position: "absolute", inset: 0, pointerEvents: "none" }
896
+ }
897
+ ),
898
+ p && h === "idle" && /* @__PURE__ */ R(
899
+ "svg",
900
+ {
901
+ viewBox: "0 0 100 100",
902
+ style: {
903
+ position: "absolute",
904
+ inset: 0,
905
+ width: "100%",
906
+ height: "100%",
907
+ pointerEvents: "none",
908
+ opacity: 0.4
909
+ },
910
+ children: [
911
+ /* @__PURE__ */ c(
912
+ "circle",
913
+ {
914
+ cx: "50",
915
+ cy: "50",
916
+ r: "35",
917
+ fill: "none",
918
+ stroke: "white",
919
+ strokeWidth: "1",
920
+ strokeDasharray: "5 3"
921
+ }
922
+ ),
923
+ /* @__PURE__ */ c(
924
+ "circle",
925
+ {
926
+ cx: "50",
927
+ cy: "50",
928
+ r: "15",
929
+ fill: "none",
930
+ stroke: "white",
931
+ strokeWidth: "0.5",
932
+ strokeDasharray: "3 3"
933
+ }
934
+ ),
935
+ /* @__PURE__ */ c("line", { x1: "50", y1: "10", x2: "50", y2: "25", stroke: "white", strokeWidth: "0.5", opacity: "0.5" }),
936
+ /* @__PURE__ */ c("line", { x1: "50", y1: "75", x2: "50", y2: "90", stroke: "white", strokeWidth: "0.5", opacity: "0.5" }),
937
+ /* @__PURE__ */ c("line", { x1: "10", y1: "50", x2: "25", y2: "50", stroke: "white", strokeWidth: "0.5", opacity: "0.5" }),
938
+ /* @__PURE__ */ c("line", { x1: "75", y1: "50", x2: "90", y2: "50", stroke: "white", strokeWidth: "0.5", opacity: "0.5" })
939
+ ]
940
+ }
941
+ ),
942
+ (h === "scanning" || h === "processing") && /* @__PURE__ */ c(
943
+ "div",
944
+ {
945
+ style: {
946
+ position: "absolute",
947
+ inset: 0,
948
+ display: "flex",
949
+ alignItems: "center",
950
+ justifyContent: "center",
951
+ background: "rgba(0,0,0,0.2)"
952
+ },
953
+ children: /* @__PURE__ */ c(
954
+ "div",
955
+ {
956
+ style: {
957
+ width: y * 0.7,
958
+ height: 3,
959
+ background: E,
960
+ animation: "irisLineAnim 1.5s ease-in-out infinite",
961
+ position: "absolute",
962
+ opacity: 0.7
963
+ }
964
+ }
965
+ )
966
+ }
967
+ )
968
+ ]
969
+ }
970
+ ),
971
+ /* @__PURE__ */ c(
972
+ "div",
973
+ {
974
+ style: {
975
+ fontSize: 11,
976
+ color: "var(--security-text-muted)",
977
+ textTransform: "uppercase",
978
+ letterSpacing: 1
979
+ },
980
+ children: n === "both" ? b("security.iris.bothEyes", "Both eyes") : n === "left" ? b("security.iris.leftEye", "Left eye") : b("security.iris.rightEye", "Right eye")
981
+ }
982
+ ),
983
+ m && q > 0 && /* @__PURE__ */ c(
984
+ "div",
985
+ {
986
+ style: {
987
+ width: y * 0.6,
988
+ height: 4,
989
+ background: "var(--security-bg-panel)",
990
+ borderRadius: 2,
991
+ overflow: "hidden"
992
+ },
993
+ children: /* @__PURE__ */ c(
994
+ "div",
995
+ {
996
+ style: {
997
+ width: `${Math.min(100, q * 300)}%`,
998
+ height: "100%",
999
+ background: q > 0.3 ? "var(--security-success)" : q > 0.1 ? "var(--security-warning)" : "var(--security-error)",
1000
+ transition: "width 0.3s"
1001
+ }
1002
+ }
1003
+ )
1004
+ }
1005
+ ),
1006
+ /* @__PURE__ */ c(
1007
+ "div",
1008
+ {
1009
+ style: {
1010
+ fontSize: 13,
1011
+ color: "var(--security-text-secondary)",
1012
+ textAlign: "center",
1013
+ minHeight: 20
1014
+ },
1015
+ children: D ?? $
1016
+ }
1017
+ ),
1018
+ h !== "success" && h !== "failure" && /* @__PURE__ */ c(
1019
+ "button",
1020
+ {
1021
+ onClick: X,
1022
+ disabled: h === "scanning" || h === "processing",
1023
+ style: {
1024
+ padding: "10px 24px",
1025
+ fontSize: 14,
1026
+ fontWeight: 600,
1027
+ background: "var(--security-biometric)",
1028
+ color: "#fff",
1029
+ border: "none",
1030
+ borderRadius: "var(--security-radius)",
1031
+ cursor: "pointer",
1032
+ opacity: h === "scanning" || h === "processing" ? 0.6 : 1
1033
+ },
1034
+ children: t === "enroll" ? b("security.iris.captureBtn", "👁️ Capture Iris") : b("security.iris.verifyBtn", "👁️ Verify Iris")
1035
+ }
1036
+ ),
1037
+ (h === "failure" || h === "error") && /* @__PURE__ */ c(
1038
+ "button",
1039
+ {
1040
+ onClick: () => {
1041
+ _(0), F("idle"), B("");
1042
+ },
1043
+ style: {
1044
+ padding: "8px 20px",
1045
+ fontSize: 13,
1046
+ background: "var(--security-bg-panel)",
1047
+ color: "var(--security-text)",
1048
+ border: "1px solid var(--security-border)",
1049
+ borderRadius: "var(--security-radius)",
1050
+ cursor: "pointer"
1051
+ },
1052
+ children: b("security.common.retry", "Try Again")
1053
+ }
1054
+ ),
1055
+ /* @__PURE__ */ c("style", { children: `
1056
+ @keyframes irisLineAnim {
1057
+ 0%, 100% { transform: translateY(-${y * 0.3}px); opacity: 0.3; }
1058
+ 50% { transform: translateY(${y * 0.3}px); opacity: 0.8; }
1059
+ }
1060
+ ` })
1061
+ ]
1062
+ }
1063
+ );
1064
+ }, tt = { sm: 240, md: 320, lg: 440 }, Ct = (e) => {
1065
+ const {
1066
+ mode: t,
1067
+ enrolledTemplates: r = [],
1068
+ referencePhoto: n,
1069
+ onEnroll: i,
1070
+ onVerify: s,
1071
+ onStatusChange: o,
1072
+ onError: a,
1073
+ className: g,
1074
+ size: v = "md",
1075
+ label: f,
1076
+ showQuality: m = !0,
1077
+ showBoundingBox: k = !0,
1078
+ livenessSteps: p = 1,
1079
+ showReference: D = !0,
1080
+ instructionText: C,
1081
+ ...b
1082
+ } = e, { t: T } = ee(), y = de(b), S = tt[v], u = V(null), x = V(null), l = V(null), [h, L] = j("idle"), [q, Y] = j(0), [W, H] = j(0), [Z, _] = j(""), [$, B] = j(null), [F, K] = j(0), U = G(
1083
+ (w) => {
1084
+ L(w), o == null || o(w);
1085
+ },
1086
+ [o]
1087
+ ), X = G(async () => {
1088
+ try {
1089
+ const w = await fe("user");
1090
+ l.current = w, u.current && (u.current.srcObject = w, await u.current.play()), U("idle"), _(T("security.face.lookAtCamera", "Look at the camera"));
1091
+ } catch (w) {
1092
+ a == null || a(w instanceof Error ? w : new Error(String(w))), _(T("security.face.cameraError", "Camera access denied")), U("error");
1093
+ }
1094
+ }, [T, U, a]), E = G(() => {
1095
+ var w;
1096
+ (w = l.current) == null || w.getTracks().forEach((d) => d.stop()), l.current = null;
1097
+ }, []);
1098
+ te(() => (X(), E), [X, E]);
1099
+ const I = G(
1100
+ (w) => {
1101
+ var ge, me, ve;
1102
+ const d = (ge = x.current) == null ? void 0 : ge.getContext("2d");
1103
+ if (!d)
1104
+ return;
1105
+ const A = x.current.width, N = x.current.height;
1106
+ if (d.clearRect(0, 0, A, N), !w || !k)
1107
+ return;
1108
+ const P = w.boundingBox, O = A / (((me = u.current) == null ? void 0 : me.videoWidth) ?? A), J = N / (((ve = u.current) == null ? void 0 : ve.videoHeight) ?? N);
1109
+ d.strokeStyle = h === "success" ? "#10b981" : "#3b82f6", d.lineWidth = 2, d.setLineDash([6, 4]), d.strokeRect(P.x * O, P.y * J, P.width * O, P.height * J), d.setLineDash([]);
1110
+ const Q = [
1111
+ [P.x * O, P.y * J],
1112
+ [(P.x + P.width) * O, P.y * J],
1113
+ [P.x * O, (P.y + P.height) * J],
1114
+ [(P.x + P.width) * O, (P.y + P.height) * J]
1115
+ ], re = 12;
1116
+ d.lineWidth = 3;
1117
+ for (const [ne, ie] of Q)
1118
+ d.beginPath(), d.moveTo(ne === P.x * O ? ne : ne - re, ie), d.lineTo(ne, ie), d.lineTo(ne, ie === P.y * J ? ie + re : ie - re), d.stroke();
1119
+ },
1120
+ [k, h]
1121
+ ), z = G(async () => {
1122
+ if (!(!u.current || h === "processing" || h === "success")) {
1123
+ U("scanning"), _(T("security.face.scanning", "Scanning face…"));
1124
+ try {
1125
+ if (y.livenessDetection) {
1126
+ const A = [];
1127
+ for (let P = 0; P < 8; P++)
1128
+ A.push(ae(u.current).imageData), await new Promise((O) => setTimeout(O, 200));
1129
+ if (!Ae(A).isLive) {
1130
+ _(T("security.face.notLive", "Liveness check failed — move naturally")), U("idle");
1131
+ return;
1132
+ }
1133
+ }
1134
+ U("processing"), _(T("security.face.processing", "Analysing face…"));
1135
+ const { imageData: w } = ae(u.current);
1136
+ if (t === "compare" && n) {
1137
+ const A = typeof n == "string" ? await rt(n) : nt(n), { similarity: N, cameraFeatures: P, refFeatures: O } = Ke(w, A);
1138
+ K(N), Y((P == null ? void 0 : P.quality) ?? 0), I(P);
1139
+ const Q = {
1140
+ success: N >= y.matchThreshold,
1141
+ confidence: N,
1142
+ method: "face",
1143
+ timestamp: Date.now(),
1144
+ duration: 0,
1145
+ livenessPassed: y.livenessDetection
1146
+ };
1147
+ Q.success ? (_(T("security.face.matchFound", `Match: ${(N * 100).toFixed(0)}%`)), U("success")) : (H((re) => re + 1), W + 1 >= y.maxRetries ? (_(T("security.face.maxAttempts", "Maximum attempts reached")), U("failure")) : (_(T("security.face.noMatch", "No match — try again")), U("idle"))), s == null || s(Q);
1148
+ return;
1149
+ }
1150
+ const d = ue(w);
1151
+ if (!d) {
1152
+ _(T("security.face.noFaceDetected", "No face detected")), U("idle");
1153
+ return;
1154
+ }
1155
+ if (Y(d.quality), I(d), t === "enroll") {
1156
+ const A = await Ge(d, f ?? "face");
1157
+ i == null || i(A, d), _(T("security.face.enrolled", "Face enrolled successfully")), U("success");
1158
+ } else {
1159
+ let A = 0;
1160
+ for (const O of r) {
1161
+ const J = Je(O), Q = ke(d, J);
1162
+ Q > A && (A = Q);
1163
+ }
1164
+ K(A);
1165
+ const N = A >= y.matchThreshold, P = {
1166
+ success: N,
1167
+ confidence: A,
1168
+ method: "face",
1169
+ timestamp: Date.now(),
1170
+ duration: 0,
1171
+ livenessPassed: y.livenessDetection
1172
+ };
1173
+ if (N && y.verifyEndpoint) {
1174
+ const O = await le(), J = await ye(
1175
+ y.verifyEndpoint,
1176
+ {
1177
+ method: "face",
1178
+ templateData: btoa(JSON.stringify(d)),
1179
+ matchScore: A,
1180
+ deviceFingerprint: O
1181
+ },
1182
+ y.authToken
1183
+ );
1184
+ P.success = J.verified;
1185
+ }
1186
+ P.success ? (_(T("security.face.verified", "Face verified")), U("success")) : (H((O) => O + 1), W + 1 >= y.maxRetries ? (_(T("security.face.maxAttempts", "Maximum attempts reached")), U("failure")) : (_(T("security.face.noMatch", "No match — try again")), U("idle"))), s == null || s(P);
1187
+ }
1188
+ } catch (w) {
1189
+ a == null || a(w instanceof Error ? w : new Error(String(w))), _(T("security.face.error", "Error — try again")), U("error");
1190
+ }
1191
+ }
1192
+ }, [
1193
+ h,
1194
+ t,
1195
+ r,
1196
+ n,
1197
+ y,
1198
+ T,
1199
+ U,
1200
+ i,
1201
+ s,
1202
+ a,
1203
+ f,
1204
+ W,
1205
+ I
1206
+ ]), M = h === "success" ? "var(--security-success)" : h === "failure" || h === "error" ? "var(--security-error)" : h === "scanning" || h === "processing" ? "var(--security-biometric)" : "var(--security-border)";
1207
+ return /* @__PURE__ */ R(
1208
+ "div",
1209
+ {
1210
+ className: g,
1211
+ style: {
1212
+ display: "inline-flex",
1213
+ flexDirection: "column",
1214
+ alignItems: "center",
1215
+ gap: 12
1216
+ },
1217
+ children: [
1218
+ f && /* @__PURE__ */ c("div", { style: { fontSize: 14, fontWeight: 600, color: "var(--security-text)" }, children: f }),
1219
+ /* @__PURE__ */ R("div", { style: { display: "flex", gap: 16, alignItems: "center" }, children: [
1220
+ /* @__PURE__ */ R(
1221
+ "div",
1222
+ {
1223
+ style: {
1224
+ width: S,
1225
+ height: S * 0.75,
1226
+ position: "relative",
1227
+ borderRadius: "var(--security-radius-lg)",
1228
+ overflow: "hidden",
1229
+ border: `3px solid ${M}`,
1230
+ boxShadow: h === "scanning" ? `0 0 20px ${M}` : "var(--security-shadow)",
1231
+ transition: "border-color 0.3s, box-shadow 0.3s"
1232
+ },
1233
+ children: [
1234
+ /* @__PURE__ */ c(
1235
+ "video",
1236
+ {
1237
+ ref: u,
1238
+ style: { width: "100%", height: "100%", objectFit: "cover", transform: "scaleX(-1)" },
1239
+ playsInline: !0,
1240
+ muted: !0
1241
+ }
1242
+ ),
1243
+ /* @__PURE__ */ c(
1244
+ "canvas",
1245
+ {
1246
+ ref: x,
1247
+ width: S,
1248
+ height: S * 0.75,
1249
+ style: {
1250
+ position: "absolute",
1251
+ inset: 0,
1252
+ pointerEvents: "none",
1253
+ transform: "scaleX(-1)"
1254
+ }
1255
+ }
1256
+ ),
1257
+ /* @__PURE__ */ c(
1258
+ "svg",
1259
+ {
1260
+ viewBox: "0 0 100 75",
1261
+ style: {
1262
+ position: "absolute",
1263
+ inset: 0,
1264
+ width: "100%",
1265
+ height: "100%",
1266
+ pointerEvents: "none",
1267
+ opacity: 0.3
1268
+ },
1269
+ children: /* @__PURE__ */ c(
1270
+ "ellipse",
1271
+ {
1272
+ cx: "50",
1273
+ cy: "37",
1274
+ rx: "22",
1275
+ ry: "30",
1276
+ fill: "none",
1277
+ stroke: "white",
1278
+ strokeWidth: "0.8",
1279
+ strokeDasharray: "4 3"
1280
+ }
1281
+ )
1282
+ }
1283
+ ),
1284
+ (h === "scanning" || h === "processing") && /* @__PURE__ */ c(
1285
+ "div",
1286
+ {
1287
+ style: {
1288
+ position: "absolute",
1289
+ inset: 0,
1290
+ background: "rgba(0,0,0,0.15)",
1291
+ display: "flex",
1292
+ alignItems: "center",
1293
+ justifyContent: "center"
1294
+ },
1295
+ children: /* @__PURE__ */ c(
1296
+ "div",
1297
+ {
1298
+ style: {
1299
+ width: 50,
1300
+ height: 50,
1301
+ borderRadius: "50%",
1302
+ border: "3px solid transparent",
1303
+ borderTopColor: M,
1304
+ animation: "spin 0.8s linear infinite"
1305
+ }
1306
+ }
1307
+ )
1308
+ }
1309
+ )
1310
+ ]
1311
+ }
1312
+ ),
1313
+ t === "compare" && D && n && /* @__PURE__ */ R(
1314
+ "div",
1315
+ {
1316
+ style: {
1317
+ width: S * 0.4,
1318
+ height: S * 0.5,
1319
+ borderRadius: "var(--security-radius)",
1320
+ overflow: "hidden",
1321
+ border: "2px solid var(--security-border)"
1322
+ },
1323
+ children: [
1324
+ /* @__PURE__ */ c(
1325
+ "img",
1326
+ {
1327
+ src: typeof n == "string" ? n : void 0,
1328
+ alt: "Reference",
1329
+ style: { width: "100%", height: "100%", objectFit: "cover" }
1330
+ }
1331
+ ),
1332
+ /* @__PURE__ */ c(
1333
+ "div",
1334
+ {
1335
+ style: {
1336
+ textAlign: "center",
1337
+ fontSize: 10,
1338
+ padding: 4,
1339
+ color: "var(--security-text-muted)",
1340
+ background: "var(--security-bg-panel)"
1341
+ },
1342
+ children: T("security.face.reference", "Reference")
1343
+ }
1344
+ )
1345
+ ]
1346
+ }
1347
+ )
1348
+ ] }),
1349
+ F > 0 && /* @__PURE__ */ R("div", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 13 }, children: [
1350
+ /* @__PURE__ */ R("span", { style: { color: "var(--security-text-secondary)" }, children: [
1351
+ T("security.face.confidence", "Confidence"),
1352
+ ":"
1353
+ ] }),
1354
+ /* @__PURE__ */ c(
1355
+ "div",
1356
+ {
1357
+ style: {
1358
+ width: 100,
1359
+ height: 6,
1360
+ background: "var(--security-bg-panel)",
1361
+ borderRadius: 3,
1362
+ overflow: "hidden"
1363
+ },
1364
+ children: /* @__PURE__ */ c(
1365
+ "div",
1366
+ {
1367
+ style: {
1368
+ width: `${F * 100}%`,
1369
+ height: "100%",
1370
+ background: F >= y.matchThreshold ? "var(--security-success)" : "var(--security-warning)"
1371
+ }
1372
+ }
1373
+ )
1374
+ }
1375
+ ),
1376
+ /* @__PURE__ */ R(
1377
+ "span",
1378
+ {
1379
+ style: {
1380
+ fontWeight: 600,
1381
+ color: F >= y.matchThreshold ? "var(--security-success)" : "var(--security-warning)"
1382
+ },
1383
+ children: [
1384
+ (F * 100).toFixed(0),
1385
+ "%"
1386
+ ]
1387
+ }
1388
+ )
1389
+ ] }),
1390
+ /* @__PURE__ */ c(
1391
+ "div",
1392
+ {
1393
+ style: {
1394
+ fontSize: 13,
1395
+ color: "var(--security-text-secondary)",
1396
+ textAlign: "center",
1397
+ minHeight: 20
1398
+ },
1399
+ children: C ?? Z
1400
+ }
1401
+ ),
1402
+ h !== "success" && h !== "failure" && /* @__PURE__ */ c(
1403
+ "button",
1404
+ {
1405
+ onClick: z,
1406
+ disabled: h === "scanning" || h === "processing",
1407
+ style: {
1408
+ padding: "10px 24px",
1409
+ fontSize: 14,
1410
+ fontWeight: 600,
1411
+ background: "var(--security-biometric)",
1412
+ color: "#fff",
1413
+ border: "none",
1414
+ borderRadius: "var(--security-radius)",
1415
+ cursor: "pointer",
1416
+ opacity: h === "scanning" || h === "processing" ? 0.6 : 1
1417
+ },
1418
+ children: t === "enroll" ? T("security.face.captureBtn", "📸 Capture Face") : t === "compare" ? T("security.face.compareBtn", "📸 Compare") : T("security.face.verifyBtn", "📸 Verify Face")
1419
+ }
1420
+ ),
1421
+ (h === "failure" || h === "error") && /* @__PURE__ */ c(
1422
+ "button",
1423
+ {
1424
+ onClick: () => {
1425
+ H(0), K(0), U("idle"), _("");
1426
+ },
1427
+ style: {
1428
+ padding: "8px 20px",
1429
+ fontSize: 13,
1430
+ background: "var(--security-bg-panel)",
1431
+ color: "var(--security-text)",
1432
+ border: "1px solid var(--security-border)",
1433
+ borderRadius: "var(--security-radius)",
1434
+ cursor: "pointer"
1435
+ },
1436
+ children: T("security.common.retry", "Try Again")
1437
+ }
1438
+ ),
1439
+ /* @__PURE__ */ c("style", { children: "@keyframes spin { to { transform: rotate(360deg); } }" })
1440
+ ]
1441
+ }
1442
+ );
1443
+ };
1444
+ async function rt(e) {
1445
+ return new Promise((t, r) => {
1446
+ const n = new Image();
1447
+ n.crossOrigin = "anonymous", n.onload = () => {
1448
+ const i = document.createElement("canvas");
1449
+ i.width = n.naturalWidth, i.height = n.naturalHeight;
1450
+ const s = i.getContext("2d");
1451
+ s.drawImage(n, 0, 0), t(s.getImageData(0, 0, i.width, i.height));
1452
+ }, n.onerror = () => r(new Error("Failed to load reference image")), n.src = e;
1453
+ });
1454
+ }
1455
+ function nt(e) {
1456
+ const t = document.createElement("canvas");
1457
+ t.width = e.naturalWidth || e.width, t.height = e.naturalHeight || e.height;
1458
+ const r = t.getContext("2d");
1459
+ return r.drawImage(e, 0, 0), r.getImageData(0, 0, t.width, t.height);
1460
+ }
1461
+ const it = 4, st = 5, ot = 3e4, Pt = (e) => {
1462
+ const {
1463
+ length: t = it,
1464
+ scramble: r = !1,
1465
+ showDigits: n = !1,
1466
+ maxAttempts: i = st,
1467
+ lockoutDuration: s = ot,
1468
+ keySize: o = 64,
1469
+ haptic: a = !0,
1470
+ keyLabels: g,
1471
+ expectedHash: v,
1472
+ expectedPin: f,
1473
+ mode: m = "verify",
1474
+ onComplete: k,
1475
+ onVerify: p,
1476
+ onStatusChange: D,
1477
+ onError: C,
1478
+ showBiometricFallback: b = !1,
1479
+ onBiometricFallback: T,
1480
+ label: y,
1481
+ className: S
1482
+ } = e, { t: u } = ee(), [x, l] = j([]), [h, L] = j("idle"), [q, Y] = j(0), [W, H] = j(0), [Z, _] = j(null), $ = V(), B = se(() => {
1483
+ const z = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "back"];
1484
+ if (!r)
1485
+ return z;
1486
+ const M = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
1487
+ for (let w = M.length - 1; w > 0; w--) {
1488
+ const d = new Uint32Array(1);
1489
+ crypto.getRandomValues(d);
1490
+ const A = d[0] % (w + 1);
1491
+ [M[w], M[A]] = [M[A], M[w]];
1492
+ }
1493
+ return [
1494
+ M[0],
1495
+ M[1],
1496
+ M[2],
1497
+ M[3],
1498
+ M[4],
1499
+ M[5],
1500
+ M[6],
1501
+ M[7],
1502
+ M[8],
1503
+ "",
1504
+ M[9],
1505
+ "back"
1506
+ ];
1507
+ }, [r, h]), F = G(
1508
+ (z) => {
1509
+ L(z), D == null || D(z);
1510
+ },
1511
+ [D]
1512
+ );
1513
+ te(() => {
1514
+ if (!(W <= Date.now()))
1515
+ return $.current = setInterval(() => {
1516
+ Date.now() >= W && (clearInterval($.current), F("idle"), Y(0), l([]));
1517
+ }, 500), () => clearInterval($.current);
1518
+ }, [W, F]);
1519
+ const K = W > Date.now(), U = G(() => {
1520
+ a && navigator.vibrate && navigator.vibrate(20);
1521
+ }, [a]), X = G(
1522
+ async (z) => {
1523
+ if (K || h === "success")
1524
+ return;
1525
+ if (U(), z === "back") {
1526
+ l((A) => A.slice(0, -1));
1527
+ return;
1528
+ }
1529
+ if (z === "")
1530
+ return;
1531
+ const M = [...x, z];
1532
+ if (l(M), M.length < t)
1533
+ return;
1534
+ const w = M.join("");
1535
+ if (F("processing"), m === "set") {
1536
+ if (Z === null) {
1537
+ _(w), l([]), F("idle");
1538
+ return;
1539
+ }
1540
+ if (Z !== w) {
1541
+ _(null), l([]), F("failure"), setTimeout(() => F("idle"), 1200);
1542
+ return;
1543
+ }
1544
+ k == null || k(w), F("success");
1545
+ return;
1546
+ }
1547
+ let d = !1;
1548
+ if (v) {
1549
+ const A = new TextEncoder(), N = await crypto.subtle.digest("SHA-256", A.encode(w));
1550
+ d = Array.from(new Uint8Array(N)).map((O) => O.toString(16).padStart(2, "0")).join("") === v;
1551
+ } else if (f)
1552
+ d = w === f;
1553
+ else {
1554
+ k == null || k(w), F("success");
1555
+ return;
1556
+ }
1557
+ if (d)
1558
+ F("success"), p == null || p({
1559
+ success: !0,
1560
+ confidence: 1,
1561
+ method: "pin",
1562
+ timestamp: Date.now(),
1563
+ duration: 0
1564
+ }), k == null || k(w);
1565
+ else {
1566
+ const A = q + 1;
1567
+ if (Y(A), A >= i) {
1568
+ const N = Date.now() + s;
1569
+ H(N), F("failure"), C == null || C(new Error("Too many failed PIN attempts"));
1570
+ } else
1571
+ F("failure"), setTimeout(() => {
1572
+ F("idle"), l([]);
1573
+ }, 800);
1574
+ p == null || p({
1575
+ success: !1,
1576
+ confidence: 0,
1577
+ method: "pin",
1578
+ timestamp: Date.now(),
1579
+ duration: 0
1580
+ });
1581
+ }
1582
+ },
1583
+ [
1584
+ x,
1585
+ t,
1586
+ K,
1587
+ h,
1588
+ m,
1589
+ Z,
1590
+ v,
1591
+ f,
1592
+ q,
1593
+ i,
1594
+ s,
1595
+ U,
1596
+ F,
1597
+ k,
1598
+ p,
1599
+ C
1600
+ ]
1601
+ ), E = Math.max(0, Math.ceil((W - Date.now()) / 1e3)), I = h === "success" ? "var(--security-success)" : h === "failure" ? "var(--security-error)" : "var(--security-border)";
1602
+ return /* @__PURE__ */ R(
1603
+ "div",
1604
+ {
1605
+ className: S,
1606
+ style: {
1607
+ display: "inline-flex",
1608
+ flexDirection: "column",
1609
+ alignItems: "center",
1610
+ gap: 16,
1611
+ fontFamily: "var(--security-font)",
1612
+ color: "var(--security-text)"
1613
+ },
1614
+ children: [
1615
+ y && /* @__PURE__ */ c("div", { style: { fontSize: 14, fontWeight: 600 }, children: y }),
1616
+ /* @__PURE__ */ c(
1617
+ "div",
1618
+ {
1619
+ style: {
1620
+ fontSize: 13,
1621
+ color: "var(--security-text-secondary)",
1622
+ minHeight: 18,
1623
+ textAlign: "center"
1624
+ },
1625
+ children: K ? u("security.pin.locked", `Locked — try again in ${E}s`) : m === "set" && Z !== null ? u("security.pin.confirm", "Confirm your PIN") : m === "set" ? u("security.pin.setNew", "Enter a new PIN") : u("security.pin.enter", "Enter your PIN")
1626
+ }
1627
+ ),
1628
+ /* @__PURE__ */ c("div", { style: { display: "flex", gap: 12 }, children: Array.from({ length: t }, (z, M) => /* @__PURE__ */ c(
1629
+ "div",
1630
+ {
1631
+ style: {
1632
+ width: 16,
1633
+ height: 16,
1634
+ borderRadius: "50%",
1635
+ border: `2px solid ${I}`,
1636
+ background: M < x.length ? I : "transparent",
1637
+ transition: "background 0.15s, border-color 0.15s"
1638
+ }
1639
+ },
1640
+ M
1641
+ )) }),
1642
+ /* @__PURE__ */ c(
1643
+ "div",
1644
+ {
1645
+ style: {
1646
+ display: "grid",
1647
+ gridTemplateColumns: `repeat(3, ${o}px)`,
1648
+ gap: 10,
1649
+ opacity: K ? 0.4 : 1,
1650
+ pointerEvents: K ? "none" : "auto"
1651
+ },
1652
+ children: B.map((z, M) => {
1653
+ if (z === "")
1654
+ return /* @__PURE__ */ c("div", {}, M);
1655
+ const w = z === "back";
1656
+ return /* @__PURE__ */ c(
1657
+ "button",
1658
+ {
1659
+ onClick: () => X(z),
1660
+ disabled: K || h === "success",
1661
+ "aria-label": w ? "Backspace" : z,
1662
+ style: {
1663
+ width: o,
1664
+ height: o,
1665
+ borderRadius: "var(--security-key-border-radius, 50%)",
1666
+ border: "1px solid var(--security-key-border, var(--security-border))",
1667
+ background: "var(--security-key-bg, var(--security-bg-panel))",
1668
+ color: "var(--security-key-text, var(--security-text))",
1669
+ fontSize: w ? 20 : 22,
1670
+ fontWeight: 600,
1671
+ cursor: "pointer",
1672
+ display: "flex",
1673
+ alignItems: "center",
1674
+ justifyContent: "center",
1675
+ transition: "background 0.1s, transform 0.1s",
1676
+ userSelect: "none"
1677
+ },
1678
+ onMouseDown: (d) => {
1679
+ d.currentTarget.style.transform = "scale(0.92)";
1680
+ },
1681
+ onMouseUp: (d) => {
1682
+ d.currentTarget.style.transform = "";
1683
+ },
1684
+ onMouseLeave: (d) => {
1685
+ d.currentTarget.style.transform = "";
1686
+ },
1687
+ children: w ? "⌫" : (g == null ? void 0 : g[z]) ?? z
1688
+ },
1689
+ M
1690
+ );
1691
+ })
1692
+ }
1693
+ ),
1694
+ x.length > 0 && h !== "success" && /* @__PURE__ */ c(
1695
+ "button",
1696
+ {
1697
+ onClick: () => l([]),
1698
+ style: {
1699
+ fontSize: 12,
1700
+ background: "none",
1701
+ border: "none",
1702
+ color: "var(--security-text-secondary)",
1703
+ cursor: "pointer",
1704
+ textDecoration: "underline"
1705
+ },
1706
+ children: u("security.pin.clear", "Clear")
1707
+ }
1708
+ ),
1709
+ b && /* @__PURE__ */ R(
1710
+ "button",
1711
+ {
1712
+ onClick: T,
1713
+ style: {
1714
+ fontSize: 13,
1715
+ padding: "8px 16px",
1716
+ background: "none",
1717
+ border: "1px solid var(--security-border)",
1718
+ borderRadius: "var(--security-radius)",
1719
+ color: "var(--security-biometric)",
1720
+ cursor: "pointer"
1721
+ },
1722
+ children: [
1723
+ "🔐 ",
1724
+ u("security.pin.biometricFallback", "Use biometrics instead")
1725
+ ]
1726
+ }
1727
+ ),
1728
+ q > 0 && h !== "success" && !K && /* @__PURE__ */ c("div", { style: { fontSize: 11, color: "var(--security-warning)" }, children: u("security.pin.attempts", `${q}/${i} attempts`) })
1729
+ ]
1730
+ }
1731
+ );
1732
+ }, at = 3, ct = 4, lt = 5, ut = 14, Et = (e) => {
1733
+ const {
1734
+ gridSize: t = at,
1735
+ minLength: r = ct,
1736
+ showTrail: n = !0,
1737
+ showError: i = !0,
1738
+ maxAttempts: s = lt,
1739
+ dotSize: o = ut,
1740
+ trailColor: a,
1741
+ mode: g = "verify",
1742
+ expectedHash: v,
1743
+ expectedPattern: f,
1744
+ onComplete: m,
1745
+ onVerify: k,
1746
+ onStatusChange: p,
1747
+ onError: D,
1748
+ label: C,
1749
+ className: b,
1750
+ canvasSize: T
1751
+ } = e, { t: y } = ee(), S = V(null), [u, x] = j([]), [l, h] = j(!1), [L, q] = j("idle"), [Y, W] = j(0), [H, Z] = j(null), [_, $] = j(null), B = T ?? t * 80, F = B / t, K = G(
1752
+ (d) => {
1753
+ q(d), p == null || p(d);
1754
+ },
1755
+ [p]
1756
+ ), U = G(() => {
1757
+ const d = [];
1758
+ for (let A = 0; A < t; A++)
1759
+ for (let N = 0; N < t; N++)
1760
+ d.push({ x: N * F + F / 2, y: A * F + F / 2 });
1761
+ return d;
1762
+ }, [t, F]), X = G((d) => {
1763
+ const A = S.current.getBoundingClientRect(), N = "touches" in d ? d.touches[0].clientX : d.clientX, P = "touches" in d ? d.touches[0].clientY : d.clientY;
1764
+ return { x: N - A.left, y: P - A.top };
1765
+ }, []), E = G(
1766
+ (d, A) => {
1767
+ const N = U(), P = F * 0.38;
1768
+ for (let O = 0; O < N.length; O++) {
1769
+ const J = N[O].x - d, Q = N[O].y - A;
1770
+ if (J * J + Q * Q < P * P)
1771
+ return O;
1772
+ }
1773
+ return -1;
1774
+ },
1775
+ [U, F]
1776
+ ), I = G(() => {
1777
+ var O;
1778
+ const d = (O = S.current) == null ? void 0 : O.getContext("2d");
1779
+ if (!d)
1780
+ return;
1781
+ d.clearRect(0, 0, B, B);
1782
+ const A = U(), P = L === "failure" && i ? "var(--security-error)" : a ?? "var(--security-biometric)";
1783
+ for (let J = 0; J < A.length; J++) {
1784
+ const Q = u.includes(J);
1785
+ d.beginPath(), d.arc(A[J].x, A[J].y, Q ? o * 0.75 : o * 0.5, 0, Math.PI * 2), d.fillStyle = Q ? P : "var(--security-border)", d.fill(), Q && (d.beginPath(), d.arc(A[J].x, A[J].y, o * 1.2, 0, Math.PI * 2), d.strokeStyle = P, d.lineWidth = 1.5, d.globalAlpha = 0.3, d.stroke(), d.globalAlpha = 1);
1786
+ }
1787
+ if (n && u.length > 1) {
1788
+ d.beginPath(), d.moveTo(A[u[0]].x, A[u[0]].y);
1789
+ for (let J = 1; J < u.length; J++)
1790
+ d.lineTo(A[u[J]].x, A[u[J]].y);
1791
+ l && _ && d.lineTo(_.x, _.y), d.strokeStyle = P, d.lineWidth = 3, d.lineCap = "round", d.lineJoin = "round", d.globalAlpha = 0.5, d.stroke(), d.globalAlpha = 1;
1792
+ } else n && u.length === 1 && l && _ && (d.beginPath(), d.moveTo(A[u[0]].x, A[u[0]].y), d.lineTo(_.x, _.y), d.strokeStyle = a ?? "var(--security-biometric)", d.lineWidth = 3, d.globalAlpha = 0.4, d.stroke(), d.globalAlpha = 1);
1793
+ }, [
1794
+ B,
1795
+ U,
1796
+ o,
1797
+ u,
1798
+ l,
1799
+ _,
1800
+ L,
1801
+ n,
1802
+ i,
1803
+ a
1804
+ ]);
1805
+ te(() => {
1806
+ I();
1807
+ }, [I]);
1808
+ const z = G(
1809
+ (d) => {
1810
+ if (L === "success" || L === "failure")
1811
+ return;
1812
+ d.preventDefault();
1813
+ const { x: A, y: N } = X(d), P = E(A, N);
1814
+ P >= 0 && (h(!0), x([P]), $({ x: A, y: N }));
1815
+ },
1816
+ [L, X, E]
1817
+ ), M = G(
1818
+ (d) => {
1819
+ if (!l)
1820
+ return;
1821
+ d.preventDefault();
1822
+ const { x: A, y: N } = X(d);
1823
+ $({ x: A, y: N });
1824
+ const P = E(A, N);
1825
+ P >= 0 && !u.includes(P) && x((O) => [...O, P]);
1826
+ },
1827
+ [l, X, E, u]
1828
+ ), w = G(async () => {
1829
+ if (!l)
1830
+ return;
1831
+ if (h(!1), $(null), u.length < r) {
1832
+ x([]);
1833
+ return;
1834
+ }
1835
+ const d = u.join(",");
1836
+ if (g === "set") {
1837
+ if (H === null) {
1838
+ Z([...u]), x([]);
1839
+ return;
1840
+ }
1841
+ if (H.join(",") !== d) {
1842
+ Z(null), K("failure"), setTimeout(() => {
1843
+ K("idle"), x([]);
1844
+ }, 800);
1845
+ return;
1846
+ }
1847
+ m == null || m([...u]), K("success");
1848
+ return;
1849
+ }
1850
+ K("processing");
1851
+ let A = !1;
1852
+ if (v) {
1853
+ const N = new TextEncoder(), P = await crypto.subtle.digest("SHA-256", N.encode(d));
1854
+ A = Array.from(new Uint8Array(P)).map((J) => J.toString(16).padStart(2, "0")).join("") === v;
1855
+ } else if (f)
1856
+ A = d === f;
1857
+ else {
1858
+ m == null || m([...u]), K("success");
1859
+ return;
1860
+ }
1861
+ if (A)
1862
+ K("success"), k == null || k({
1863
+ success: !0,
1864
+ confidence: 1,
1865
+ method: "pattern",
1866
+ timestamp: Date.now(),
1867
+ duration: 0
1868
+ }), m == null || m([...u]);
1869
+ else {
1870
+ const N = Y + 1;
1871
+ W(N), K("failure"), N >= s && (D == null || D(new Error("Too many failed pattern attempts"))), setTimeout(() => {
1872
+ K("idle"), x([]);
1873
+ }, 900), k == null || k({
1874
+ success: !1,
1875
+ confidence: 0,
1876
+ method: "pattern",
1877
+ timestamp: Date.now(),
1878
+ duration: 0
1879
+ });
1880
+ }
1881
+ }, [
1882
+ l,
1883
+ u,
1884
+ r,
1885
+ g,
1886
+ H,
1887
+ v,
1888
+ f,
1889
+ Y,
1890
+ s,
1891
+ K,
1892
+ m,
1893
+ k,
1894
+ D
1895
+ ]);
1896
+ return /* @__PURE__ */ R(
1897
+ "div",
1898
+ {
1899
+ className: b,
1900
+ style: {
1901
+ display: "inline-flex",
1902
+ flexDirection: "column",
1903
+ alignItems: "center",
1904
+ gap: 12,
1905
+ fontFamily: "var(--security-font)",
1906
+ color: "var(--security-text)"
1907
+ },
1908
+ children: [
1909
+ C && /* @__PURE__ */ c("div", { style: { fontSize: 14, fontWeight: 600 }, children: C }),
1910
+ /* @__PURE__ */ c(
1911
+ "div",
1912
+ {
1913
+ style: {
1914
+ fontSize: 13,
1915
+ color: "var(--security-text-secondary)",
1916
+ minHeight: 18,
1917
+ textAlign: "center"
1918
+ },
1919
+ children: L === "success" ? y("security.pattern.success", "Pattern accepted") : L === "failure" ? y("security.pattern.wrong", "Wrong pattern") : g === "set" && H !== null ? y("security.pattern.confirm", "Draw pattern again to confirm") : g === "set" ? y("security.pattern.setNew", "Draw a new pattern") : y("security.pattern.draw", "Draw your pattern")
1920
+ }
1921
+ ),
1922
+ /* @__PURE__ */ c(
1923
+ "canvas",
1924
+ {
1925
+ ref: S,
1926
+ width: B,
1927
+ height: B,
1928
+ style: {
1929
+ touchAction: "none",
1930
+ borderRadius: "var(--security-radius-lg)",
1931
+ background: "var(--security-bg-panel)",
1932
+ border: `1px solid ${L === "failure" ? "var(--security-error)" : "var(--security-border)"}`,
1933
+ cursor: "pointer",
1934
+ transition: "border-color 0.3s"
1935
+ },
1936
+ onMouseDown: z,
1937
+ onMouseMove: M,
1938
+ onMouseUp: w,
1939
+ onMouseLeave: w,
1940
+ onTouchStart: z,
1941
+ onTouchMove: M,
1942
+ onTouchEnd: w
1943
+ }
1944
+ ),
1945
+ (L === "failure" || L === "success") && /* @__PURE__ */ c(
1946
+ "button",
1947
+ {
1948
+ onClick: () => {
1949
+ x([]), W(0), Z(null), K("idle");
1950
+ },
1951
+ style: {
1952
+ fontSize: 13,
1953
+ padding: "6px 16px",
1954
+ background: "var(--security-bg-panel)",
1955
+ border: "1px solid var(--security-border)",
1956
+ borderRadius: "var(--security-radius)",
1957
+ color: "var(--security-text)",
1958
+ cursor: "pointer"
1959
+ },
1960
+ children: y("security.common.retry", "Try Again")
1961
+ }
1962
+ ),
1963
+ Y > 0 && L !== "success" && /* @__PURE__ */ c("div", { style: { fontSize: 11, color: "var(--security-warning)" }, children: y("security.pattern.attempts", `${Y}/${s} attempts`) })
1964
+ ]
1965
+ }
1966
+ );
1967
+ }, dt = { sm: "8px 16px", md: "12px 24px", lg: "14px 32px" }, ht = { sm: 13, md: 14, lg: 16 }, Ft = (e) => {
1968
+ const {
1969
+ mode: t,
1970
+ credentialIds: r = [],
1971
+ challenge: n,
1972
+ rpName: i = window.location.hostname,
1973
+ rpId: s = window.location.hostname,
1974
+ user: o,
1975
+ attestation: a = "none",
1976
+ authenticatorAttachment: g,
1977
+ residentKey: v = "preferred",
1978
+ userVerification: f = "preferred",
1979
+ onRegister: m,
1980
+ onAuthenticate: k,
1981
+ onVerify: p,
1982
+ onStatusChange: D,
1983
+ onError: C,
1984
+ label: b,
1985
+ className: T,
1986
+ variant: y = "primary",
1987
+ size: S = "md",
1988
+ fullWidth: u = !1,
1989
+ icon: x
1990
+ } = e, { t: l } = ee(), [h, L] = j("idle"), [q, Y] = j(!0), [W, H] = j(!1), Z = G(
1991
+ (I) => {
1992
+ L(I), D == null || D(I);
1993
+ },
1994
+ [D]
1995
+ );
1996
+ te(() => {
1997
+ Y(Ie()), Ze().then(H);
1998
+ }, []);
1999
+ const _ = G(() => {
2000
+ if (n) {
2001
+ const I = atob(n.replace(/-/g, "+").replace(/_/g, "/")), z = new Uint8Array(I.length);
2002
+ for (let M = 0; M < I.length; M++)
2003
+ z[M] = I.charCodeAt(M);
2004
+ return z.buffer;
2005
+ }
2006
+ return crypto.getRandomValues(new Uint8Array(32)).buffer;
2007
+ }, [n]), $ = G(async () => {
2008
+ if (!q) {
2009
+ C == null || C(new Error("WebAuthn not available"));
2010
+ return;
2011
+ }
2012
+ Z("processing");
2013
+ try {
2014
+ if (t === "register") {
2015
+ const I = (o == null ? void 0 : o.id) ?? crypto.getRandomValues(new Uint8Array(16)), z = (o == null ? void 0 : o.name) ?? "user", M = (o == null ? void 0 : o.displayName) ?? z, w = _(), d = await Ye({
2016
+ rpName: i,
2017
+ rpId: s,
2018
+ userId: typeof I == "string" ? I : Array.from(I).join(""),
2019
+ userName: z,
2020
+ userDisplayName: M,
2021
+ challenge: w
2022
+ });
2023
+ Z("success"), d && (m == null || m(d)), p == null || p({
2024
+ success: !0,
2025
+ confidence: 1,
2026
+ method: "webauthn",
2027
+ timestamp: Date.now(),
2028
+ duration: 0
2029
+ });
2030
+ } else {
2031
+ const I = await Xe({
2032
+ rpId: s,
2033
+ challenge: _(),
2034
+ allowCredentials: r == null ? void 0 : r.map((z) => ({
2035
+ id: new TextEncoder().encode(z),
2036
+ type: "public-key"
2037
+ }))
2038
+ });
2039
+ Z("success"), I && (k == null || k(I)), p == null || p({
2040
+ success: !0,
2041
+ confidence: 1,
2042
+ method: "webauthn",
2043
+ timestamp: Date.now(),
2044
+ duration: 0
2045
+ });
2046
+ }
2047
+ } catch (I) {
2048
+ const z = I instanceof Error ? I : new Error(String(I));
2049
+ z.name === "NotAllowedError" ? Z("idle") : (Z("error"), C == null || C(z), p == null || p({
2050
+ success: !1,
2051
+ confidence: 0,
2052
+ method: "webauthn",
2053
+ timestamp: Date.now(),
2054
+ duration: 0
2055
+ }));
2056
+ }
2057
+ }, [
2058
+ q,
2059
+ t,
2060
+ r,
2061
+ o,
2062
+ i,
2063
+ s,
2064
+ a,
2065
+ g,
2066
+ v,
2067
+ f,
2068
+ _,
2069
+ Z,
2070
+ m,
2071
+ k,
2072
+ p,
2073
+ C
2074
+ ]), B = t === "register" ? W ? l("security.webauthn.registerPasskey", "🔑 Register Passkey") : l("security.webauthn.register", "🔐 Register Security Key") : W ? l("security.webauthn.signInPasskey", "🔑 Sign in with Passkey") : l("security.webauthn.signIn", "🔐 Sign in with Security Key"), F = b ?? B, K = {
2075
+ primary: "var(--security-biometric)",
2076
+ outline: "transparent",
2077
+ ghost: "transparent"
2078
+ }, U = {
2079
+ primary: "none",
2080
+ outline: "2px solid var(--security-biometric)",
2081
+ ghost: "none"
2082
+ }, X = {
2083
+ primary: "#fff",
2084
+ outline: "var(--security-biometric)",
2085
+ ghost: "var(--security-biometric)"
2086
+ }, E = !q || h === "processing" || h === "success";
2087
+ return /* @__PURE__ */ R(
2088
+ "div",
2089
+ {
2090
+ className: T,
2091
+ style: { display: u ? "block" : "inline-block", textAlign: "center" },
2092
+ children: [
2093
+ /* @__PURE__ */ R(
2094
+ "button",
2095
+ {
2096
+ onClick: $,
2097
+ disabled: E,
2098
+ style: {
2099
+ width: u ? "100%" : "auto",
2100
+ padding: dt[S],
2101
+ fontSize: ht[S],
2102
+ fontWeight: 600,
2103
+ fontFamily: "var(--security-font)",
2104
+ background: K[y],
2105
+ color: X[y],
2106
+ border: U[y],
2107
+ borderRadius: "var(--security-radius)",
2108
+ cursor: E ? "not-allowed" : "pointer",
2109
+ opacity: E ? 0.6 : 1,
2110
+ display: "inline-flex",
2111
+ alignItems: "center",
2112
+ justifyContent: "center",
2113
+ gap: 8,
2114
+ transition: "opacity 0.2s, transform 0.1s"
2115
+ },
2116
+ children: [
2117
+ h === "processing" && /* @__PURE__ */ c(
2118
+ "span",
2119
+ {
2120
+ style: {
2121
+ display: "inline-block",
2122
+ width: 16,
2123
+ height: 16,
2124
+ borderRadius: "50%",
2125
+ border: "2px solid transparent",
2126
+ borderTopColor: "currentColor",
2127
+ animation: "spin 0.6s linear infinite"
2128
+ }
2129
+ }
2130
+ ),
2131
+ h === "success" && /* @__PURE__ */ c("span", { children: "✓" }),
2132
+ x && h !== "processing" && h !== "success" && x,
2133
+ F
2134
+ ]
2135
+ }
2136
+ ),
2137
+ !q && /* @__PURE__ */ c("div", { style: { fontSize: 11, marginTop: 6, color: "var(--security-warning)" }, children: l("security.webauthn.notAvailable", "WebAuthn is not supported in this browser") }),
2138
+ h === "error" && /* @__PURE__ */ c("div", { style: { fontSize: 11, marginTop: 6, color: "var(--security-error)" }, children: l("security.webauthn.error", "Authentication failed — try again") }),
2139
+ /* @__PURE__ */ c("style", { children: "@keyframes spin { to { transform: rotate(360deg); } }" })
2140
+ ]
2141
+ }
2142
+ );
2143
+ }, ft = {
2144
+ success: "✅",
2145
+ failure: "❌",
2146
+ error: "⚠️",
2147
+ idle: "⏸️",
2148
+ scanning: "🔍",
2149
+ processing: "⏳",
2150
+ timeout: "⏰"
2151
+ }, yt = (e) => e >= 80 ? "var(--security-error)" : e >= 50 ? "var(--security-warning)" : "var(--security-success)", zt = ({
2152
+ entries: e,
2153
+ pageSize: t = 20,
2154
+ showExport: r = !0,
2155
+ filterMethods: n,
2156
+ onEntryClick: i,
2157
+ className: s,
2158
+ label: o
2159
+ }) => {
2160
+ const { t: a } = ee(), [g, v] = j("all"), [f, m] = j("all"), [k, p] = j(0), D = se(() => {
2161
+ let l = [...e];
2162
+ return g !== "all" && (l = l.filter((h) => h.method === g)), f !== "all" && (l = l.filter((h) => h.status === f)), l.sort((h, L) => L.timestamp - h.timestamp), l;
2163
+ }, [e, g, f]), C = Math.max(1, Math.ceil(D.length / t)), b = D.slice(k * t, (k + 1) * t), T = se(() => n || Array.from(new Set(e.map((l) => l.method))), [e, n]), y = se(() => Array.from(new Set(e.map((l) => l.status))), [e]), S = G(() => {
2164
+ const l = new Blob([JSON.stringify(D, null, 2)], { type: "application/json" }), h = URL.createObjectURL(l), L = document.createElement("a");
2165
+ L.href = h, L.download = `security-audit-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.json`, L.click(), URL.revokeObjectURL(h);
2166
+ }, [D]), u = (l) => new Date(l).toLocaleString(), x = {
2167
+ padding: "8px 12px",
2168
+ borderBottom: "1px solid var(--security-border)",
2169
+ fontSize: 13,
2170
+ whiteSpace: "nowrap"
2171
+ };
2172
+ return /* @__PURE__ */ R(
2173
+ "div",
2174
+ {
2175
+ className: s,
2176
+ style: {
2177
+ fontFamily: "var(--security-font)",
2178
+ color: "var(--security-text)",
2179
+ background: "var(--security-bg)",
2180
+ borderRadius: "var(--security-radius-lg)",
2181
+ border: "1px solid var(--security-border)",
2182
+ overflow: "hidden"
2183
+ },
2184
+ children: [
2185
+ /* @__PURE__ */ R(
2186
+ "div",
2187
+ {
2188
+ style: {
2189
+ display: "flex",
2190
+ alignItems: "center",
2191
+ justifyContent: "space-between",
2192
+ padding: "12px 16px",
2193
+ background: "var(--security-bg-panel)",
2194
+ borderBottom: "1px solid var(--security-border)"
2195
+ },
2196
+ children: [
2197
+ /* @__PURE__ */ c("div", { style: { fontWeight: 600, fontSize: 15 }, children: o ?? a("security.audit.title", "🔒 Security Audit Log") }),
2198
+ /* @__PURE__ */ R("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2199
+ /* @__PURE__ */ R(
2200
+ "select",
2201
+ {
2202
+ value: g,
2203
+ onChange: (l) => {
2204
+ v(l.target.value), p(0);
2205
+ },
2206
+ style: be,
2207
+ children: [
2208
+ /* @__PURE__ */ c("option", { value: "all", children: a("security.audit.allMethods", "All methods") }),
2209
+ T.map((l) => /* @__PURE__ */ c("option", { value: l, children: l }, l))
2210
+ ]
2211
+ }
2212
+ ),
2213
+ /* @__PURE__ */ R(
2214
+ "select",
2215
+ {
2216
+ value: f,
2217
+ onChange: (l) => {
2218
+ m(l.target.value), p(0);
2219
+ },
2220
+ style: be,
2221
+ children: [
2222
+ /* @__PURE__ */ c("option", { value: "all", children: a("security.audit.allStatuses", "All statuses") }),
2223
+ y.map((l) => /* @__PURE__ */ c("option", { value: l, children: l }, l))
2224
+ ]
2225
+ }
2226
+ ),
2227
+ r && /* @__PURE__ */ c("button", { onClick: S, style: pt, title: "Export JSON", children: "📥" })
2228
+ ] })
2229
+ ]
2230
+ }
2231
+ ),
2232
+ /* @__PURE__ */ c("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ R("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
2233
+ /* @__PURE__ */ c("thead", { children: /* @__PURE__ */ R(
2234
+ "tr",
2235
+ {
2236
+ style: {
2237
+ background: "var(--security-bg-panel)",
2238
+ fontSize: 12,
2239
+ color: "var(--security-text-secondary)",
2240
+ textTransform: "uppercase",
2241
+ letterSpacing: 0.5
2242
+ },
2243
+ children: [
2244
+ /* @__PURE__ */ c("th", { style: { ...x, textAlign: "left" }, children: a("security.audit.time", "Time") }),
2245
+ /* @__PURE__ */ c("th", { style: { ...x, textAlign: "left" }, children: a("security.audit.action", "Action") }),
2246
+ /* @__PURE__ */ c("th", { style: { ...x, textAlign: "center" }, children: a("security.audit.method", "Method") }),
2247
+ /* @__PURE__ */ c("th", { style: { ...x, textAlign: "center" }, children: a("security.audit.status", "Status") }),
2248
+ /* @__PURE__ */ c("th", { style: { ...x, textAlign: "center" }, children: a("security.audit.risk", "Risk") }),
2249
+ /* @__PURE__ */ c("th", { style: { ...x, textAlign: "left" }, children: a("security.audit.device", "Device") })
2250
+ ]
2251
+ }
2252
+ ) }),
2253
+ /* @__PURE__ */ R("tbody", { children: [
2254
+ b.length === 0 && /* @__PURE__ */ c("tr", { children: /* @__PURE__ */ c(
2255
+ "td",
2256
+ {
2257
+ colSpan: 6,
2258
+ style: {
2259
+ ...x,
2260
+ textAlign: "center",
2261
+ color: "var(--security-text-muted)",
2262
+ padding: 24
2263
+ },
2264
+ children: a("security.audit.noEntries", "No entries to show")
2265
+ }
2266
+ ) }),
2267
+ b.map((l) => /* @__PURE__ */ R(
2268
+ "tr",
2269
+ {
2270
+ onClick: () => i == null ? void 0 : i(l),
2271
+ style: { cursor: i ? "pointer" : "default" },
2272
+ onMouseEnter: (h) => {
2273
+ h.currentTarget.style.background = "var(--security-bg-panel)";
2274
+ },
2275
+ onMouseLeave: (h) => {
2276
+ h.currentTarget.style.background = "";
2277
+ },
2278
+ children: [
2279
+ /* @__PURE__ */ c("td", { style: x, children: u(l.timestamp) }),
2280
+ /* @__PURE__ */ c("td", { style: x, children: l.action }),
2281
+ /* @__PURE__ */ c("td", { style: { ...x, textAlign: "center" }, children: /* @__PURE__ */ c(
2282
+ "span",
2283
+ {
2284
+ style: {
2285
+ padding: "2px 8px",
2286
+ borderRadius: 12,
2287
+ fontSize: 11,
2288
+ fontWeight: 600,
2289
+ background: "var(--security-bg-panel)",
2290
+ border: "1px solid var(--security-border)"
2291
+ },
2292
+ children: l.method
2293
+ }
2294
+ ) }),
2295
+ /* @__PURE__ */ R("td", { style: { ...x, textAlign: "center" }, children: [
2296
+ ft[l.status] ?? "•",
2297
+ " ",
2298
+ l.status
2299
+ ] }),
2300
+ /* @__PURE__ */ c("td", { style: { ...x, textAlign: "center" }, children: l.riskScore != null && /* @__PURE__ */ c("span", { style: { color: yt(l.riskScore), fontWeight: 600 }, children: l.riskScore }) }),
2301
+ /* @__PURE__ */ c(
2302
+ "td",
2303
+ {
2304
+ style: {
2305
+ ...x,
2306
+ maxWidth: 200,
2307
+ overflow: "hidden",
2308
+ textOverflow: "ellipsis"
2309
+ },
2310
+ children: l.device ?? "—"
2311
+ }
2312
+ )
2313
+ ]
2314
+ },
2315
+ l.id
2316
+ ))
2317
+ ] })
2318
+ ] }) }),
2319
+ C > 1 && /* @__PURE__ */ R(
2320
+ "div",
2321
+ {
2322
+ style: {
2323
+ display: "flex",
2324
+ justifyContent: "center",
2325
+ alignItems: "center",
2326
+ gap: 12,
2327
+ padding: "10px 16px",
2328
+ fontSize: 13,
2329
+ color: "var(--security-text-secondary)",
2330
+ borderTop: "1px solid var(--security-border)"
2331
+ },
2332
+ children: [
2333
+ /* @__PURE__ */ R("button", { disabled: k === 0, onClick: () => p(k - 1), style: xe, children: [
2334
+ "← ",
2335
+ a("security.audit.prev", "Prev")
2336
+ ] }),
2337
+ /* @__PURE__ */ R("span", { children: [
2338
+ k + 1,
2339
+ " / ",
2340
+ C
2341
+ ] }),
2342
+ /* @__PURE__ */ R(
2343
+ "button",
2344
+ {
2345
+ disabled: k >= C - 1,
2346
+ onClick: () => p(k + 1),
2347
+ style: xe,
2348
+ children: [
2349
+ a("security.audit.next", "Next"),
2350
+ " →"
2351
+ ]
2352
+ }
2353
+ )
2354
+ ]
2355
+ }
2356
+ ),
2357
+ /* @__PURE__ */ c(
2358
+ "div",
2359
+ {
2360
+ style: {
2361
+ padding: "6px 16px",
2362
+ fontSize: 11,
2363
+ color: "var(--security-text-muted)",
2364
+ textAlign: "right"
2365
+ },
2366
+ children: a("security.audit.total", `${D.length} entries`)
2367
+ }
2368
+ )
2369
+ ]
2370
+ }
2371
+ );
2372
+ }, be = {
2373
+ fontSize: 12,
2374
+ padding: "4px 8px",
2375
+ background: "var(--security-bg)",
2376
+ color: "var(--security-text)",
2377
+ border: "1px solid var(--security-border)",
2378
+ borderRadius: "var(--security-radius)"
2379
+ }, pt = {
2380
+ background: "none",
2381
+ border: "1px solid var(--security-border)",
2382
+ borderRadius: "var(--security-radius)",
2383
+ padding: "4px 8px",
2384
+ cursor: "pointer",
2385
+ fontSize: 16
2386
+ }, xe = {
2387
+ background: "none",
2388
+ border: "none",
2389
+ cursor: "pointer",
2390
+ color: "var(--security-biometric)",
2391
+ fontWeight: 600,
2392
+ fontSize: 13
2393
+ }, gt = {
2394
+ fingerprint: "👆",
2395
+ iris: "👁️",
2396
+ face: "🧑",
2397
+ voice: "🎙️",
2398
+ webauthn: "🔑",
2399
+ pattern: "✦",
2400
+ pin: "🔢",
2401
+ passphrase: "🔤"
2402
+ }, Nt = ({
2403
+ options: e,
2404
+ requiredCount: t = 1,
2405
+ onSelect: r,
2406
+ onComplete: n,
2407
+ className: i,
2408
+ label: s,
2409
+ layout: o = "grid"
2410
+ }) => {
2411
+ const { t: a } = ee(), g = e.filter((f) => f.verified).length, v = g >= t;
2412
+ return /* @__PURE__ */ R(
2413
+ "div",
2414
+ {
2415
+ className: i,
2416
+ style: {
2417
+ fontFamily: "var(--security-font)",
2418
+ color: "var(--security-text)",
2419
+ display: "flex",
2420
+ flexDirection: "column",
2421
+ gap: 16
2422
+ },
2423
+ children: [
2424
+ s && /* @__PURE__ */ c("div", { style: { fontSize: 15, fontWeight: 600 }, children: s }),
2425
+ t > 1 && /* @__PURE__ */ c("div", { style: { fontSize: 13, color: "var(--security-text-secondary)" }, children: a("security.mfa.progress", `Verified ${g} of ${t} required`) }),
2426
+ /* @__PURE__ */ c(
2427
+ "div",
2428
+ {
2429
+ style: {
2430
+ display: o === "grid" ? "grid" : "flex",
2431
+ gridTemplateColumns: o === "grid" ? "repeat(auto-fill, minmax(140px, 1fr))" : void 0,
2432
+ flexDirection: o === "list" ? "column" : void 0,
2433
+ gap: 12
2434
+ },
2435
+ children: e.map((f) => {
2436
+ const m = f.verified ?? !1, k = f.disabled || v;
2437
+ return /* @__PURE__ */ R(
2438
+ "button",
2439
+ {
2440
+ onClick: () => !k && !m && (r == null ? void 0 : r(f.method)),
2441
+ disabled: k || m,
2442
+ style: {
2443
+ display: "flex",
2444
+ flexDirection: o === "grid" ? "column" : "row",
2445
+ alignItems: "center",
2446
+ gap: o === "grid" ? 8 : 12,
2447
+ padding: o === "grid" ? "20px 16px" : "12px 16px",
2448
+ background: m ? "rgba(16,185,129,0.08)" : "var(--security-bg-panel)",
2449
+ border: `2px solid ${m ? "var(--security-success)" : "var(--security-border)"}`,
2450
+ borderRadius: "var(--security-radius-lg)",
2451
+ cursor: k || m ? "default" : "pointer",
2452
+ opacity: k && !m ? 0.5 : 1,
2453
+ transition: "border-color 0.2s, background 0.2s",
2454
+ textAlign: o === "grid" ? "center" : "left"
2455
+ },
2456
+ children: [
2457
+ /* @__PURE__ */ c("span", { style: { fontSize: 28 }, children: m ? "✅" : f.icon ?? gt[f.method] ?? "🔐" }),
2458
+ /* @__PURE__ */ R("div", { children: [
2459
+ /* @__PURE__ */ c("div", { style: { fontSize: 14, fontWeight: 600, color: "var(--security-text)" }, children: f.label ?? f.method }),
2460
+ f.description && /* @__PURE__ */ c("div", { style: { fontSize: 11, color: "var(--security-text-muted)", marginTop: 2 }, children: f.description })
2461
+ ] })
2462
+ ]
2463
+ },
2464
+ f.method
2465
+ );
2466
+ })
2467
+ }
2468
+ ),
2469
+ v && /* @__PURE__ */ R(
2470
+ "div",
2471
+ {
2472
+ style: {
2473
+ textAlign: "center",
2474
+ fontSize: 14,
2475
+ fontWeight: 600,
2476
+ color: "var(--security-success)",
2477
+ padding: 8
2478
+ },
2479
+ children: [
2480
+ "✅ ",
2481
+ a("security.mfa.complete", "All factors verified")
2482
+ ]
2483
+ }
2484
+ )
2485
+ ]
2486
+ }
2487
+ );
2488
+ }, Lt = ({
2489
+ sessions: e,
2490
+ onRevoke: t,
2491
+ onRevokeAll: r,
2492
+ onTrust: n,
2493
+ className: i,
2494
+ label: s,
2495
+ showRevokeAll: o = !0
2496
+ }) => {
2497
+ const { t: a } = ee(), [g, v] = j(/* @__PURE__ */ new Set()), f = se(
2498
+ () => [...e].sort(
2499
+ (p, D) => (D.current ? 1 : 0) - (p.current ? 1 : 0) || D.lastActive - p.lastActive
2500
+ ),
2501
+ [e]
2502
+ ), m = (p) => {
2503
+ const D = new Date(p), b = Date.now() - p;
2504
+ return b < 6e4 ? a("security.session.justNow", "Just now") : b < 36e5 ? `${Math.floor(b / 6e4)}m ago` : b < 864e5 ? `${Math.floor(b / 36e5)}h ago` : D.toLocaleDateString();
2505
+ }, k = (p) => {
2506
+ v((D) => new Set(D).add(p)), t == null || t(p);
2507
+ };
2508
+ return /* @__PURE__ */ R(
2509
+ "div",
2510
+ {
2511
+ className: i,
2512
+ style: {
2513
+ fontFamily: "var(--security-font)",
2514
+ color: "var(--security-text)",
2515
+ background: "var(--security-bg)",
2516
+ borderRadius: "var(--security-radius-lg)",
2517
+ border: "1px solid var(--security-border)",
2518
+ overflow: "hidden"
2519
+ },
2520
+ children: [
2521
+ /* @__PURE__ */ R(
2522
+ "div",
2523
+ {
2524
+ style: {
2525
+ display: "flex",
2526
+ alignItems: "center",
2527
+ justifyContent: "space-between",
2528
+ padding: "12px 16px",
2529
+ background: "var(--security-bg-panel)",
2530
+ borderBottom: "1px solid var(--security-border)"
2531
+ },
2532
+ children: [
2533
+ /* @__PURE__ */ c("div", { style: { fontSize: 15, fontWeight: 600 }, children: s ?? a("security.session.title", "🖥️ Active Sessions") }),
2534
+ o && e.length > 1 && /* @__PURE__ */ c(
2535
+ "button",
2536
+ {
2537
+ onClick: r,
2538
+ style: {
2539
+ fontSize: 12,
2540
+ padding: "4px 12px",
2541
+ background: "none",
2542
+ border: "1px solid var(--security-error)",
2543
+ borderRadius: "var(--security-radius)",
2544
+ color: "var(--security-error)",
2545
+ cursor: "pointer"
2546
+ },
2547
+ children: a("security.session.revokeAll", "Revoke all others")
2548
+ }
2549
+ )
2550
+ ]
2551
+ }
2552
+ ),
2553
+ /* @__PURE__ */ R("div", { children: [
2554
+ f.map((p) => /* @__PURE__ */ R(
2555
+ "div",
2556
+ {
2557
+ style: {
2558
+ display: "flex",
2559
+ alignItems: "center",
2560
+ justifyContent: "space-between",
2561
+ padding: "12px 16px",
2562
+ borderBottom: "1px solid var(--security-border)",
2563
+ opacity: g.has(p.id) ? 0.5 : 1,
2564
+ background: p.current ? "rgba(59,130,246,0.04)" : void 0
2565
+ },
2566
+ children: [
2567
+ /* @__PURE__ */ R("div", { style: { display: "flex", gap: 12, alignItems: "center" }, children: [
2568
+ /* @__PURE__ */ c("span", { style: { fontSize: 24 }, children: p.device.toLowerCase().includes("mobile") ? "📱" : "💻" }),
2569
+ /* @__PURE__ */ R("div", { children: [
2570
+ /* @__PURE__ */ R("div", { style: { fontSize: 14, fontWeight: 500 }, children: [
2571
+ p.device,
2572
+ p.current && /* @__PURE__ */ c(
2573
+ "span",
2574
+ {
2575
+ style: {
2576
+ marginLeft: 8,
2577
+ fontSize: 10,
2578
+ padding: "1px 6px",
2579
+ background: "var(--security-biometric)",
2580
+ color: "#fff",
2581
+ borderRadius: 8
2582
+ },
2583
+ children: a("security.session.current", "Current")
2584
+ }
2585
+ ),
2586
+ p.trusted && /* @__PURE__ */ c(
2587
+ "span",
2588
+ {
2589
+ style: {
2590
+ marginLeft: 6,
2591
+ fontSize: 10,
2592
+ padding: "1px 6px",
2593
+ background: "var(--security-success)",
2594
+ color: "#fff",
2595
+ borderRadius: 8
2596
+ },
2597
+ children: a("security.session.trusted", "Trusted")
2598
+ }
2599
+ )
2600
+ ] }),
2601
+ /* @__PURE__ */ c("div", { style: { fontSize: 12, color: "var(--security-text-muted)", marginTop: 2 }, children: [p.browser, p.os, p.location].filter(Boolean).join(" · ") }),
2602
+ /* @__PURE__ */ R("div", { style: { fontSize: 11, color: "var(--security-text-muted)", marginTop: 1 }, children: [
2603
+ a("security.session.lastActive", "Last active"),
2604
+ ":",
2605
+ " ",
2606
+ m(p.lastActive)
2607
+ ] })
2608
+ ] })
2609
+ ] }),
2610
+ /* @__PURE__ */ R("div", { style: { display: "flex", gap: 6 }, children: [
2611
+ n && !p.current && /* @__PURE__ */ c(
2612
+ "button",
2613
+ {
2614
+ onClick: () => n(p.id, !p.trusted),
2615
+ style: {
2616
+ fontSize: 11,
2617
+ padding: "4px 8px",
2618
+ background: "none",
2619
+ border: "1px solid var(--security-border)",
2620
+ borderRadius: "var(--security-radius)",
2621
+ cursor: "pointer",
2622
+ color: "var(--security-text-secondary)"
2623
+ },
2624
+ children: p.trusted ? "🚫" : "✅"
2625
+ }
2626
+ ),
2627
+ !p.current && /* @__PURE__ */ c(
2628
+ "button",
2629
+ {
2630
+ onClick: () => k(p.id),
2631
+ disabled: g.has(p.id),
2632
+ style: {
2633
+ fontSize: 11,
2634
+ padding: "4px 10px",
2635
+ background: "none",
2636
+ border: "1px solid var(--security-error)",
2637
+ borderRadius: "var(--security-radius)",
2638
+ cursor: "pointer",
2639
+ color: "var(--security-error)"
2640
+ },
2641
+ children: a("security.session.revoke", "Revoke")
2642
+ }
2643
+ )
2644
+ ] })
2645
+ ]
2646
+ },
2647
+ p.id
2648
+ )),
2649
+ e.length === 0 && /* @__PURE__ */ c(
2650
+ "div",
2651
+ {
2652
+ style: {
2653
+ padding: 24,
2654
+ textAlign: "center",
2655
+ color: "var(--security-text-muted)",
2656
+ fontSize: 13
2657
+ },
2658
+ children: a("security.session.noSessions", "No active sessions")
2659
+ }
2660
+ )
2661
+ ] })
2662
+ ]
2663
+ }
2664
+ );
2665
+ }, $t = ({
2666
+ trustScore: e,
2667
+ onScoreComputed: t,
2668
+ trustThreshold: r = 60,
2669
+ showFactors: n = !0,
2670
+ showFingerprint: i = !1,
2671
+ className: s,
2672
+ label: o
2673
+ }) => {
2674
+ const { t: a } = ee(), [g, v] = j(e ?? null), [f, m] = j(!e), k = G(async () => {
2675
+ var D;
2676
+ m(!0);
2677
+ try {
2678
+ const C = Te(), b = await le(), T = [];
2679
+ let y = 50;
2680
+ C.platform && !C.platform.includes("Linux") && (T.push({
2681
+ name: "Known platform",
2682
+ score: 5,
2683
+ description: "Running on a recognized platform",
2684
+ weight: 0.05
2685
+ }), y += 5), navigator.cookieEnabled && (T.push({
2686
+ name: "Cookies enabled",
2687
+ score: 5,
2688
+ description: "Browser cookies are enabled",
2689
+ weight: 0.05
2690
+ }), y += 5), C.screenResolution[0] >= 360 && C.screenResolution[1] >= 640 && (T.push({
2691
+ name: "Standard resolution",
2692
+ score: 5,
2693
+ description: "Screen resolution within normal range",
2694
+ weight: 0.05
2695
+ }), y += 5), typeof window < "u" && window.isSecureContext && (T.push({
2696
+ name: "Secure context",
2697
+ score: 10,
2698
+ description: "Running in HTTPS secure context",
2699
+ weight: 0.1
2700
+ }), y += 10), ((D = navigator.languages) == null ? void 0 : D.length) > 0 && (T.push({
2701
+ name: "Language configured",
2702
+ score: 5,
2703
+ description: "Browser language is set",
2704
+ weight: 0.05
2705
+ }), y += 5), C.touchSupport && (T.push({
2706
+ name: "Touch device",
2707
+ score: 5,
2708
+ description: "Touch input is supported",
2709
+ weight: 0.05
2710
+ }), y += 5);
2711
+ try {
2712
+ const l = document.createElement("canvas").getContext("webgl");
2713
+ l && l.getExtension("WEBGL_debug_renderer_info") && (T.push({
2714
+ name: "Hardware GPU",
2715
+ score: 10,
2716
+ description: "Hardware GPU detected",
2717
+ weight: 0.1
2718
+ }), y += 10);
2719
+ } catch {
2720
+ }
2721
+ navigator.credentials && (T.push({
2722
+ name: "Credential API",
2723
+ score: 5,
2724
+ description: "Credential Management API available",
2725
+ weight: 0.05
2726
+ }), y += 5), y = Math.min(100, Math.max(0, y));
2727
+ const S = Date.now(), u = {
2728
+ score: y,
2729
+ factors: T,
2730
+ trusted: y >= r,
2731
+ firstSeen: S,
2732
+ lastSeen: S,
2733
+ fingerprint: b
2734
+ };
2735
+ v(u), t == null || t(u);
2736
+ } finally {
2737
+ m(!1);
2738
+ }
2739
+ }, [r, t]);
2740
+ te(() => {
2741
+ e || k();
2742
+ }, [e, k]), te(() => {
2743
+ e && v(e);
2744
+ }, [e]);
2745
+ const p = g ? g.score >= 80 ? "var(--security-success)" : g.score >= 50 ? "var(--security-warning)" : "var(--security-error)" : "var(--security-text-muted)";
2746
+ return /* @__PURE__ */ R(
2747
+ "div",
2748
+ {
2749
+ className: s,
2750
+ style: {
2751
+ fontFamily: "var(--security-font)",
2752
+ color: "var(--security-text)",
2753
+ background: "var(--security-bg-panel)",
2754
+ borderRadius: "var(--security-radius-lg)",
2755
+ border: "1px solid var(--security-border)",
2756
+ padding: 20,
2757
+ display: "flex",
2758
+ flexDirection: "column",
2759
+ gap: 14,
2760
+ alignItems: "center"
2761
+ },
2762
+ children: [
2763
+ /* @__PURE__ */ c("div", { style: { fontSize: 15, fontWeight: 600 }, children: o ?? a("security.trust.title", "🛡️ Device Trust") }),
2764
+ f ? /* @__PURE__ */ c("div", { style: { fontSize: 13, color: "var(--security-text-muted)" }, children: a("security.trust.computing", "Analysing device…") }) : g ? /* @__PURE__ */ R(Re, { children: [
2765
+ /* @__PURE__ */ R("div", { style: { position: "relative", width: 100, height: 100 }, children: [
2766
+ /* @__PURE__ */ R(
2767
+ "svg",
2768
+ {
2769
+ viewBox: "0 0 36 36",
2770
+ style: { width: "100%", height: "100%", transform: "rotate(-90deg)" },
2771
+ children: [
2772
+ /* @__PURE__ */ c(
2773
+ "circle",
2774
+ {
2775
+ cx: "18",
2776
+ cy: "18",
2777
+ r: "15.9",
2778
+ fill: "none",
2779
+ stroke: "var(--security-border)",
2780
+ strokeWidth: "2.5"
2781
+ }
2782
+ ),
2783
+ /* @__PURE__ */ c(
2784
+ "circle",
2785
+ {
2786
+ cx: "18",
2787
+ cy: "18",
2788
+ r: "15.9",
2789
+ fill: "none",
2790
+ stroke: p,
2791
+ strokeWidth: "2.5",
2792
+ strokeDasharray: `${g.score}, 100`,
2793
+ strokeLinecap: "round"
2794
+ }
2795
+ )
2796
+ ]
2797
+ }
2798
+ ),
2799
+ /* @__PURE__ */ R(
2800
+ "div",
2801
+ {
2802
+ style: {
2803
+ position: "absolute",
2804
+ inset: 0,
2805
+ display: "flex",
2806
+ flexDirection: "column",
2807
+ alignItems: "center",
2808
+ justifyContent: "center"
2809
+ },
2810
+ children: [
2811
+ /* @__PURE__ */ c("span", { style: { fontSize: 24, fontWeight: 700, color: p }, children: g.score }),
2812
+ /* @__PURE__ */ c("span", { style: { fontSize: 10, color: "var(--security-text-muted)" }, children: "/100" })
2813
+ ]
2814
+ }
2815
+ )
2816
+ ] }),
2817
+ /* @__PURE__ */ c(
2818
+ "div",
2819
+ {
2820
+ style: {
2821
+ fontSize: 14,
2822
+ fontWeight: 600,
2823
+ color: g.trusted ? "var(--security-success)" : "var(--security-warning)"
2824
+ },
2825
+ children: g.trusted ? a("security.trust.trusted", "✅ Device Trusted") : a("security.trust.untrusted", "⚠️ Low Trust Score")
2826
+ }
2827
+ ),
2828
+ n && g.factors.length > 0 && /* @__PURE__ */ R("div", { style: { width: "100%", fontSize: 12 }, children: [
2829
+ /* @__PURE__ */ R(
2830
+ "div",
2831
+ {
2832
+ style: {
2833
+ fontWeight: 600,
2834
+ marginBottom: 6,
2835
+ color: "var(--security-text-secondary)"
2836
+ },
2837
+ children: [
2838
+ a("security.trust.factors", "Contributing factors"),
2839
+ ":"
2840
+ ]
2841
+ }
2842
+ ),
2843
+ /* @__PURE__ */ c("ul", { style: { margin: 0, paddingLeft: 18, color: "var(--security-text-muted)" }, children: g.factors.map((D, C) => /* @__PURE__ */ c("li", { style: { marginBottom: 2 }, children: D.name }, C)) })
2844
+ ] }),
2845
+ i && g.fingerprint && /* @__PURE__ */ c(
2846
+ "div",
2847
+ {
2848
+ style: {
2849
+ fontSize: 10,
2850
+ color: "var(--security-text-muted)",
2851
+ wordBreak: "break-all",
2852
+ textAlign: "center",
2853
+ maxWidth: 280,
2854
+ fontFamily: "monospace"
2855
+ },
2856
+ children: g.fingerprint
2857
+ }
2858
+ )
2859
+ ] }) : null
2860
+ ]
2861
+ }
2862
+ );
2863
+ };
2864
+ function mt(e) {
2865
+ if (!e)
2866
+ return 0;
2867
+ let t = 0;
2868
+ return e.length >= 8 && t++, e.length >= 12 && t++, /[a-z]/.test(e) && /[A-Z]/.test(e) && t++, /\d/.test(e) && t++, /[^a-zA-Z0-9]/.test(e) && t++, /(.)\1{3,}/.test(e) && t--, Math.max(0, Math.min(4, t));
2869
+ }
2870
+ const vt = ["Very weak", "Weak", "Fair", "Strong", "Very strong"], we = ["#ef4444", "#f97316", "#eab308", "#22c55e", "#10b981"], jt = ({
2871
+ mode: e = "verify",
2872
+ expectedHash: t,
2873
+ minStrength: r = 2,
2874
+ minLength: n = 8,
2875
+ onComplete: i,
2876
+ onVerify: s,
2877
+ onStatusChange: o,
2878
+ onError: a,
2879
+ label: g,
2880
+ placeholder: v,
2881
+ className: f,
2882
+ showStrength: m = !0,
2883
+ maxAttempts: k = 5
2884
+ }) => {
2885
+ const { t: p } = ee(), [D, C] = j(""), [b, T] = j(""), [y, S] = j(!1), [u, x] = j("idle"), [l, h] = j(0), [L, q] = j(""), Y = V(null), W = mt(D), H = G(
2886
+ ($) => {
2887
+ x($), o == null || o($);
2888
+ },
2889
+ [o]
2890
+ ), Z = G(async () => {
2891
+ if (q(""), H("processing"), e === "set") {
2892
+ if (D.length < n) {
2893
+ q(p("security.passphrase.tooShort", `Minimum ${n} characters`)), H("idle");
2894
+ return;
2895
+ }
2896
+ if (W < r) {
2897
+ q(p("security.passphrase.tooWeak", "Passphrase is too weak")), H("idle");
2898
+ return;
2899
+ }
2900
+ if (D !== b) {
2901
+ q(p("security.passphrase.noMatch", "Passphrases do not match")), H("failure"), setTimeout(() => H("idle"), 1e3);
2902
+ return;
2903
+ }
2904
+ i == null || i(D), H("success");
2905
+ return;
2906
+ }
2907
+ if (t) {
2908
+ const $ = new TextEncoder(), B = await crypto.subtle.digest("SHA-256", $.encode(D));
2909
+ if (Array.from(new Uint8Array(B)).map((U) => U.toString(16).padStart(2, "0")).join("") === t)
2910
+ H("success"), s == null || s({
2911
+ success: !0,
2912
+ confidence: 1,
2913
+ method: "passphrase",
2914
+ timestamp: Date.now(),
2915
+ duration: 0
2916
+ }), i == null || i(D);
2917
+ else {
2918
+ const U = l + 1;
2919
+ h(U), U >= k ? (H("failure"), a == null || a(new Error("Too many failed attempts"))) : (q(p("security.passphrase.incorrect", "Incorrect passphrase")), H("idle")), s == null || s({
2920
+ success: !1,
2921
+ confidence: 0,
2922
+ method: "passphrase",
2923
+ timestamp: Date.now(),
2924
+ duration: 0
2925
+ });
2926
+ }
2927
+ } else
2928
+ i == null || i(D), H("success");
2929
+ }, [
2930
+ D,
2931
+ b,
2932
+ e,
2933
+ t,
2934
+ W,
2935
+ r,
2936
+ n,
2937
+ l,
2938
+ k,
2939
+ p,
2940
+ H,
2941
+ i,
2942
+ s,
2943
+ a
2944
+ ]), _ = {
2945
+ width: "100%",
2946
+ padding: "10px 14px",
2947
+ fontSize: 14,
2948
+ background: "var(--security-bg)",
2949
+ color: "var(--security-text)",
2950
+ border: `1px solid ${u === "failure" ? "var(--security-error)" : "var(--security-border)"}`,
2951
+ borderRadius: "var(--security-radius)",
2952
+ boxSizing: "border-box",
2953
+ fontFamily: "var(--security-font)"
2954
+ };
2955
+ return /* @__PURE__ */ R(
2956
+ "div",
2957
+ {
2958
+ className: f,
2959
+ style: {
2960
+ display: "flex",
2961
+ flexDirection: "column",
2962
+ gap: 10,
2963
+ maxWidth: 340,
2964
+ fontFamily: "var(--security-font)",
2965
+ color: "var(--security-text)"
2966
+ },
2967
+ children: [
2968
+ g && /* @__PURE__ */ c("label", { style: { fontSize: 14, fontWeight: 600 }, children: g }),
2969
+ /* @__PURE__ */ R("div", { style: { position: "relative" }, children: [
2970
+ /* @__PURE__ */ c(
2971
+ "input",
2972
+ {
2973
+ ref: Y,
2974
+ type: y ? "text" : "password",
2975
+ value: D,
2976
+ onChange: ($) => C($.target.value),
2977
+ placeholder: v ?? p("security.passphrase.placeholder", "Enter passphrase"),
2978
+ style: _,
2979
+ disabled: u === "success",
2980
+ onKeyDown: ($) => $.key === "Enter" && Z()
2981
+ }
2982
+ ),
2983
+ /* @__PURE__ */ c(
2984
+ "button",
2985
+ {
2986
+ type: "button",
2987
+ onClick: () => S(!y),
2988
+ style: {
2989
+ position: "absolute",
2990
+ right: 8,
2991
+ top: "50%",
2992
+ transform: "translateY(-50%)",
2993
+ background: "none",
2994
+ border: "none",
2995
+ cursor: "pointer",
2996
+ fontSize: 16,
2997
+ color: "var(--security-text-muted)"
2998
+ },
2999
+ tabIndex: -1,
3000
+ children: y ? "🙈" : "👁️"
3001
+ }
3002
+ )
3003
+ ] }),
3004
+ e === "set" && m && D.length > 0 && /* @__PURE__ */ R("div", { children: [
3005
+ /* @__PURE__ */ c("div", { style: { display: "flex", gap: 3, height: 4 }, children: [0, 1, 2, 3].map(($) => /* @__PURE__ */ c(
3006
+ "div",
3007
+ {
3008
+ style: {
3009
+ flex: 1,
3010
+ borderRadius: 2,
3011
+ background: $ < W ? we[W] : "var(--security-border)",
3012
+ transition: "background 0.2s"
3013
+ }
3014
+ },
3015
+ $
3016
+ )) }),
3017
+ /* @__PURE__ */ c("div", { style: { fontSize: 11, marginTop: 4, color: we[W] }, children: p(`security.passphrase.strength${W}`, vt[W]) })
3018
+ ] }),
3019
+ e === "set" && /* @__PURE__ */ c(
3020
+ "input",
3021
+ {
3022
+ type: y ? "text" : "password",
3023
+ value: b,
3024
+ onChange: ($) => T($.target.value),
3025
+ placeholder: p("security.passphrase.confirmPlaceholder", "Confirm passphrase"),
3026
+ style: _,
3027
+ disabled: u === "success",
3028
+ onKeyDown: ($) => $.key === "Enter" && Z(),
3029
+ onPaste: ($) => $.preventDefault()
3030
+ }
3031
+ ),
3032
+ L && /* @__PURE__ */ c("div", { style: { fontSize: 12, color: "var(--security-error)" }, children: L }),
3033
+ /* @__PURE__ */ c(
3034
+ "button",
3035
+ {
3036
+ onClick: Z,
3037
+ disabled: !D || u === "processing" || u === "success",
3038
+ style: {
3039
+ padding: "10px 20px",
3040
+ fontSize: 14,
3041
+ fontWeight: 600,
3042
+ background: u === "success" ? "var(--security-success)" : "var(--security-biometric)",
3043
+ color: "#fff",
3044
+ border: "none",
3045
+ borderRadius: "var(--security-radius)",
3046
+ cursor: u === "success" ? "default" : "pointer",
3047
+ opacity: !D || u === "processing" ? 0.6 : 1
3048
+ },
3049
+ children: u === "success" ? "✓ " + p("security.passphrase.accepted", "Accepted") : e === "set" ? p("security.passphrase.setBtn", "Set Passphrase") : p("security.passphrase.verifyBtn", "Verify")
3050
+ }
3051
+ ),
3052
+ l > 0 && u !== "success" && /* @__PURE__ */ c("div", { style: { fontSize: 11, color: "var(--security-warning)" }, children: p("security.passphrase.attempts", `${l}/${k} attempts`) })
3053
+ ]
3054
+ }
3055
+ );
3056
+ };
3057
+ function Bt(e) {
3058
+ const t = [], r = {
3059
+ defaultSrc: "default-src",
3060
+ scriptSrc: "script-src",
3061
+ styleSrc: "style-src",
3062
+ imgSrc: "img-src",
3063
+ fontSrc: "font-src",
3064
+ connectSrc: "connect-src",
3065
+ frameSrc: "frame-src",
3066
+ objectSrc: "object-src",
3067
+ mediaSrc: "media-src",
3068
+ workerSrc: "worker-src",
3069
+ childSrc: "child-src",
3070
+ formAction: "form-action",
3071
+ frameAncestors: "frame-ancestors",
3072
+ baseUri: "base-uri",
3073
+ reportUri: "report-uri",
3074
+ reportTo: "report-to",
3075
+ upgradeInsecureRequests: "upgrade-insecure-requests",
3076
+ blockAllMixedContent: "block-all-mixed-content"
3077
+ };
3078
+ return Object.entries(e.directives).forEach(([n, i]) => {
3079
+ const s = r[n];
3080
+ if (s) {
3081
+ if (typeof i == "boolean")
3082
+ i && t.push(s);
3083
+ else if (typeof i == "string")
3084
+ t.push(`${s} ${i}`);
3085
+ else if (Array.isArray(i)) {
3086
+ let o = i;
3087
+ e.nonce && (n === "scriptSrc" || n === "styleSrc") && (o = [...o, `'nonce-${e.nonce}'`]), t.push(`${s} ${o.join(" ")}`);
3088
+ }
3089
+ }
3090
+ }), t.join("; ");
3091
+ }
3092
+ function Wt(e) {
3093
+ const t = "'self'";
3094
+ return {
3095
+ defaultSrc: [t],
3096
+ scriptSrc: [t],
3097
+ styleSrc: [t, "'unsafe-inline'"],
3098
+ // Some CSS-in-JS libraries need this
3099
+ imgSrc: [t, "data:", "blob:", e == null ? void 0 : e.cdnDomain].filter(Boolean),
3100
+ fontSrc: [t, "data:", e == null ? void 0 : e.cdnDomain].filter(Boolean),
3101
+ connectSrc: [t, e == null ? void 0 : e.apiDomain, "wss:"].filter(Boolean),
3102
+ frameSrc: ["'none'"],
3103
+ objectSrc: ["'none'"],
3104
+ baseUri: [t],
3105
+ formAction: [t],
3106
+ frameAncestors: ["'none'"],
3107
+ upgradeInsecureRequests: !0,
3108
+ reportUri: e == null ? void 0 : e.reportUri
3109
+ };
3110
+ }
3111
+ function _t() {
3112
+ return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID().replace(/-/g, "") : Math.random().toString(36).substring(2) + Date.now().toString(36);
3113
+ }
3114
+ const bt = {
3115
+ "&": "&amp;",
3116
+ "<": "&lt;",
3117
+ ">": "&gt;",
3118
+ '"': "&quot;",
3119
+ "'": "&#x27;",
3120
+ "/": "&#x2F;",
3121
+ "`": "&#x60;",
3122
+ "=": "&#x3D;"
3123
+ };
3124
+ function xt(e) {
3125
+ return e.replace(/[&<>"'`=/]/g, (t) => bt[t] || t);
3126
+ }
3127
+ function Ut(e, t) {
3128
+ let r = xt(e);
3129
+ return t != null && t.maxLength && r.length > t.maxLength && (r = r.substring(0, t.maxLength)), r;
3130
+ }
3131
+ function Ht(e) {
3132
+ if (!e)
3133
+ return null;
3134
+ try {
3135
+ const t = new URL(e);
3136
+ return !["http:", "https:", "mailto:", "tel:"].includes(t.protocol) || e.toLowerCase().includes("javascript:") ? null : t.toString();
3137
+ } catch {
3138
+ return null;
3139
+ }
3140
+ }
3141
+ function Ot(e) {
3142
+ const t = ["script", "iframe", "object", "embed", "form"];
3143
+ let r = e;
3144
+ t.forEach((s) => {
3145
+ const o = new RegExp(`<${s}[^>]*>.*?</${s}>`, "gi");
3146
+ r = r.replace(o, "");
3147
+ const a = new RegExp(`<${s}[^>]*/>`, "gi");
3148
+ r = r.replace(a, "");
3149
+ });
3150
+ const n = /\s+on\w+\s*=/gi;
3151
+ r = r.replace(n, " data-removed=");
3152
+ const i = /javascript:/gi;
3153
+ return r = r.replace(i, ""), r;
3154
+ }
3155
+ function qt(e, t) {
3156
+ let r = e;
3157
+ if (t != null && t.allowedTags) {
3158
+ const n = /<\/?([a-z][a-z0-9]*)[^>]*>/gi;
3159
+ r = r.replace(n, (i, s) => t.allowedTags.includes(s.toLowerCase()) ? i : "");
3160
+ }
3161
+ return r = r.replace(/\s+on\w+\s*=/gi, " data-removed="), r = r.replace(/javascript:/gi, ""), { __html: r };
3162
+ }
3163
+ const pe = {
3164
+ headerName: "X-CSRF-Token",
3165
+ cookieName: "XSRF-TOKEN",
3166
+ fieldName: "_csrf"
3167
+ };
3168
+ function Kt() {
3169
+ if (typeof crypto < "u") {
3170
+ const e = new Uint8Array(32);
3171
+ return crypto.getRandomValues(e), Array.from(e, (t) => t.toString(16).padStart(2, "0")).join("");
3172
+ }
3173
+ return Math.random().toString(36).substring(2) + Date.now().toString(36);
3174
+ }
3175
+ function Me(e = pe.cookieName) {
3176
+ if (typeof document > "u")
3177
+ return null;
3178
+ const t = document.cookie.match(new RegExp(`(^| )${e}=([^;]+)`));
3179
+ return t ? decodeURIComponent(t[2]) : null;
3180
+ }
3181
+ function Gt(e = pe) {
3182
+ return async function(r, n = {}) {
3183
+ const i = Me(e.cookieName);
3184
+ i || console.warn("CSRF token not found");
3185
+ const s = new Headers(n.headers);
3186
+ return i && e.headerName && s.set(e.headerName, i), fetch(r, { ...n, headers: s });
3187
+ };
3188
+ }
3189
+ function Jt(e = pe) {
3190
+ const t = Me(e.cookieName);
3191
+ return {
3192
+ token: t,
3193
+ inputProps: {
3194
+ type: "hidden",
3195
+ name: e.fieldName,
3196
+ value: t || ""
3197
+ },
3198
+ headerName: e.headerName
3199
+ };
3200
+ }
3201
+ function wt(e) {
3202
+ const t = /* @__PURE__ */ new Map(), r = e.keyGenerator || ((s) => s.url);
3203
+ function n(s) {
3204
+ const o = r(s), a = Date.now();
3205
+ let g = t.get(o);
3206
+ (!g || a > g.resetAt) && (g = {
3207
+ count: 0,
3208
+ resetAt: a + e.windowMs
3209
+ }), g.count++, t.set(o, g);
3210
+ const v = g.count <= e.maxRequests, f = Math.max(0, e.maxRequests - g.count);
3211
+ return { allowed: v, remaining: f, resetAt: g.resetAt };
3212
+ }
3213
+ function i(s) {
3214
+ s ? t.delete(s) : t.clear();
3215
+ }
3216
+ return { checkLimit: n, reset: i };
3217
+ }
3218
+ function Zt(e) {
3219
+ const t = wt(e);
3220
+ return { checkAndFetch: async (n, i) => {
3221
+ const s = t.checkLimit({ url: n, method: i == null ? void 0 : i.method });
3222
+ if (!s.allowed) {
3223
+ const o = Math.ceil((s.resetAt - Date.now()) / 1e3);
3224
+ throw new Error(`Rate limit exceeded. Retry after ${o} seconds.`);
3225
+ }
3226
+ return fetch(n, i);
3227
+ }, checkLimit: t.checkLimit, reset: t.reset };
3228
+ }
3229
+ function St(e, t) {
3230
+ const r = [];
3231
+ if (t.allowedTypes && t.allowedTypes.length > 0 && (t.allowedTypes.includes(e.type) || r.push(
3232
+ `File type '${e.type}' is not allowed. Allowed types: ${t.allowedTypes.join(", ")}`
3233
+ )), t.maxSize && e.size > t.maxSize) {
3234
+ const s = (t.maxSize / 1048576).toFixed(2), o = (e.size / (1024 * 1024)).toFixed(2);
3235
+ r.push(`File size (${o}MB) exceeds maximum allowed size (${s}MB)`);
3236
+ }
3237
+ const n = [".exe", ".bat", ".cmd", ".sh", ".ps1", ".vbs", ".js", ".jar"], i = e.name.toLowerCase();
3238
+ for (const s of n)
3239
+ if (i.includes(s + ".") || i.endsWith(s)) {
3240
+ r.push(`File extension '${s}' is not allowed`);
3241
+ break;
3242
+ }
3243
+ return {
3244
+ valid: r.length === 0,
3245
+ errors: r,
3246
+ file: r.length === 0 ? e : void 0
3247
+ };
3248
+ }
3249
+ function Yt(e, t) {
3250
+ const r = [], n = [], i = [];
3251
+ t.maxFiles && e.length > t.maxFiles && r.push(`Too many files. Maximum allowed: ${t.maxFiles}`);
3252
+ const s = e.reduce((o, a) => o + a.size, 0);
3253
+ if (t.maxTotalSize && s > t.maxTotalSize) {
3254
+ const o = (t.maxTotalSize / 1048576).toFixed(2), a = (s / (1024 * 1024)).toFixed(2);
3255
+ r.push(`Total file size (${a}MB) exceeds maximum (${o}MB)`);
3256
+ }
3257
+ return e.forEach((o) => {
3258
+ const a = St(o, t);
3259
+ a.valid ? n.push(o) : i.push({ file: o, errors: a.errors });
3260
+ }), {
3261
+ valid: r.length === 0 && i.length === 0,
3262
+ errors: [...r, ...i.flatMap((o) => o.errors)],
3263
+ validFiles: n,
3264
+ invalidFiles: i
3265
+ };
3266
+ }
3267
+ async function Xt(e, t) {
3268
+ const r = new FormData();
3269
+ r.append("file", e);
3270
+ try {
3271
+ const n = await fetch(t, {
3272
+ method: "POST",
3273
+ body: r
3274
+ });
3275
+ if (!n.ok)
3276
+ throw new Error("Virus scan failed");
3277
+ return await n.json();
3278
+ } catch (n) {
3279
+ return console.error("Virus scan error:", n), { clean: !1, threat: "Scan failed" };
3280
+ }
3281
+ }
3282
+ function kt() {
3283
+ if (typeof localStorage > "u")
3284
+ return null;
3285
+ const e = localStorage.getItem("nice2dev_consent");
3286
+ if (!e)
3287
+ return null;
3288
+ try {
3289
+ return JSON.parse(e);
3290
+ } catch {
3291
+ return null;
3292
+ }
3293
+ }
3294
+ function Qt(e) {
3295
+ typeof localStorage > "u" || localStorage.setItem(
3296
+ "nice2dev_consent",
3297
+ JSON.stringify({
3298
+ ...e,
3299
+ necessary: !0,
3300
+ // Always required
3301
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3302
+ })
3303
+ );
3304
+ }
3305
+ function Vt(e) {
3306
+ const t = kt();
3307
+ return t ? t[e] === !0 : !1;
3308
+ }
3309
+ function er(e) {
3310
+ if (typeof document > "u")
3311
+ return;
3312
+ document.cookie.split(";").forEach((r) => {
3313
+ const [n] = r.trim().split("=");
3314
+ e.includes(n) || (document.cookie = `${n}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`);
3315
+ });
3316
+ }
3317
+ async function tr(e, t, r = fetch) {
3318
+ const n = {
3319
+ exportDate: (/* @__PURE__ */ new Date()).toISOString(),
3320
+ userId: e
3321
+ };
3322
+ return await Promise.all(
3323
+ Object.entries(t).map(async ([i, s]) => {
3324
+ try {
3325
+ const o = await r(s);
3326
+ o.ok && (n[i] = await o.json());
3327
+ } catch (o) {
3328
+ console.error(`Failed to fetch ${i} data:`, o), n[i] = { error: "Failed to retrieve data" };
3329
+ }
3330
+ })
3331
+ ), n;
3332
+ }
3333
+ async function rr(e, t, r = fetch) {
3334
+ try {
3335
+ const n = await r(t, {
3336
+ method: "DELETE",
3337
+ headers: { "Content-Type": "application/json" },
3338
+ body: JSON.stringify({ userId: e, timestamp: (/* @__PURE__ */ new Date()).toISOString() })
3339
+ });
3340
+ return n.ok ? { success: !0, confirmationId: (await n.json()).confirmationId } : { success: !1, error: "Deletion request failed" };
3341
+ } catch (n) {
3342
+ return { success: !1, error: String(n) };
3343
+ }
3344
+ }
3345
+ function nr(e, t) {
3346
+ var n;
3347
+ const r = {
3348
+ ...e,
3349
+ id: ((n = crypto.randomUUID) == null ? void 0 : n.call(crypto)) || Math.random().toString(36),
3350
+ timestamp: /* @__PURE__ */ new Date()
3351
+ };
3352
+ return t && fetch(t, {
3353
+ method: "POST",
3354
+ headers: { "Content-Type": "application/json" },
3355
+ body: JSON.stringify(r)
3356
+ }).catch(console.error), process.env.NODE_ENV === "development" && console.warn("[HIPAA] PHI Access:", r), r;
3357
+ }
3358
+ function ir(e) {
3359
+ let t = null, r = null, n = Date.now();
3360
+ const i = e.timeoutMinutes * 60 * 1e3, s = e.warningBeforeMs || 6e4;
3361
+ function o() {
3362
+ n = Date.now(), t && clearTimeout(t), r && clearTimeout(r), e.onWarning && (r = setTimeout(() => {
3363
+ var f;
3364
+ const v = i - (Date.now() - n);
3365
+ (f = e.onWarning) == null || f.call(e, v);
3366
+ }, i - s)), t = setTimeout(e.onTimeout, i);
3367
+ }
3368
+ function a() {
3369
+ t && clearTimeout(t), r && clearTimeout(r);
3370
+ }
3371
+ function g() {
3372
+ return Math.max(0, i - (Date.now() - n));
3373
+ }
3374
+ return o(), typeof window < "u" && ["mousedown", "keypress", "touchstart", "scroll"].forEach((f) => {
3375
+ window.addEventListener(f, o, { passive: !0 });
3376
+ }), { resetTimer: o, destroy: a, getTimeRemaining: g };
3377
+ }
3378
+ function sr(e, t) {
3379
+ const r = (o) => {
3380
+ const a = o.replace("#", ""), g = parseInt(a.substr(0, 2), 16) / 255, v = parseInt(a.substr(2, 2), 16) / 255, f = parseInt(a.substr(4, 2), 16) / 255, m = (k) => k <= 0.03928 ? k / 12.92 : Math.pow((k + 0.055) / 1.055, 2.4);
3381
+ return 0.2126 * m(g) + 0.7152 * m(v) + 0.0722 * m(f);
3382
+ }, n = r(e), i = r(t), s = (Math.max(n, i) + 0.05) / (Math.min(n, i) + 0.05);
3383
+ return {
3384
+ ratio: Math.round(s * 100) / 100,
3385
+ passesAA: s >= 4.5,
3386
+ // Normal text
3387
+ passesAAA: s >= 7,
3388
+ // Normal text enhanced
3389
+ passesAALarge: s >= 3,
3390
+ // Large text (18pt+ or 14pt bold)
3391
+ passesAAALarge: s >= 4.5
3392
+ // Large text enhanced
3393
+ };
3394
+ }
3395
+ function or(e) {
3396
+ var r, n, i;
3397
+ if (e.getAttribute("aria-label"))
3398
+ return !0;
3399
+ const t = e.getAttribute("aria-labelledby");
3400
+ if (t) {
3401
+ const s = document.getElementById(t);
3402
+ if ((r = s == null ? void 0 : s.textContent) != null && r.trim())
3403
+ return !0;
3404
+ }
3405
+ if (e.id) {
3406
+ const s = document.querySelector(`label[for="${e.id}"]`);
3407
+ if ((n = s == null ? void 0 : s.textContent) != null && n.trim())
3408
+ return !0;
3409
+ }
3410
+ return !!((i = e.textContent) != null && i.trim() || e.getAttribute("title") || e.placeholder);
3411
+ }
3412
+ function ar(e) {
3413
+ const r = (e || document.body).querySelectorAll("h1, h2, h3, h4, h5, h6"), n = [];
3414
+ let i = 0, s = !1;
3415
+ return r.forEach((o) => {
3416
+ const a = parseInt(o.tagName[1]);
3417
+ a === 1 && (s && n.push({
3418
+ level: a,
3419
+ element: o,
3420
+ issue: "Multiple H1 elements found"
3421
+ }), s = !0), a > i + 1 && i !== 0 && n.push({
3422
+ level: a,
3423
+ element: o,
3424
+ issue: `Skipped heading level: H${i} to H${a}`
3425
+ }), i = a;
3426
+ }), !s && r.length > 0 && n.push({
3427
+ level: 0,
3428
+ element: r[0],
3429
+ issue: "Missing H1 element"
3430
+ }), { valid: n.length === 0, issues: n };
3431
+ }
3432
+ function cr(e) {
3433
+ const t = [];
3434
+ let r = null;
3435
+ const n = e.batchSize || 10, i = e.flushInterval || 5e3;
3436
+ async function s() {
3437
+ if (t.length === 0)
3438
+ return;
3439
+ const v = t.splice(0, n);
3440
+ try {
3441
+ await fetch(e.endpoint, {
3442
+ method: "POST",
3443
+ headers: { "Content-Type": "application/json" },
3444
+ body: JSON.stringify({ entries: v })
3445
+ });
3446
+ } catch (f) {
3447
+ console.error("Failed to send audit logs:", f), t.unshift(...v);
3448
+ }
3449
+ }
3450
+ function o() {
3451
+ r || (r = setTimeout(() => {
3452
+ r = null, s();
3453
+ }, i));
3454
+ }
3455
+ function a(v) {
3456
+ var m;
3457
+ const f = {
3458
+ ...v,
3459
+ id: ((m = crypto.randomUUID) == null ? void 0 : m.call(crypto)) || Math.random().toString(36),
3460
+ timestamp: /* @__PURE__ */ new Date(),
3461
+ userAgent: e.includeUserAgent && typeof navigator < "u" ? navigator.userAgent : void 0
3462
+ };
3463
+ t.push(f), t.length >= n ? s() : o();
3464
+ }
3465
+ function g() {
3466
+ r && clearTimeout(r), s();
3467
+ }
3468
+ return { log: a, flush: s, destroy: g };
3469
+ }
3470
+ function lr() {
3471
+ return [
3472
+ // Security
3473
+ {
3474
+ controlId: "CC6.1",
3475
+ name: "Logical and Physical Access Controls",
3476
+ category: "security",
3477
+ status: "in_progress",
3478
+ lastAssessed: /* @__PURE__ */ new Date()
3479
+ },
3480
+ {
3481
+ controlId: "CC6.2",
3482
+ name: "User Registration and Authorization",
3483
+ category: "security",
3484
+ status: "in_progress",
3485
+ lastAssessed: /* @__PURE__ */ new Date()
3486
+ },
3487
+ {
3488
+ controlId: "CC6.3",
3489
+ name: "Access Control Removal",
3490
+ category: "security",
3491
+ status: "in_progress",
3492
+ lastAssessed: /* @__PURE__ */ new Date()
3493
+ },
3494
+ // Availability
3495
+ {
3496
+ controlId: "A1.1",
3497
+ name: "System Capacity",
3498
+ category: "availability",
3499
+ status: "in_progress",
3500
+ lastAssessed: /* @__PURE__ */ new Date()
3501
+ },
3502
+ {
3503
+ controlId: "A1.2",
3504
+ name: "Backup and Recovery",
3505
+ category: "availability",
3506
+ status: "in_progress",
3507
+ lastAssessed: /* @__PURE__ */ new Date()
3508
+ },
3509
+ // Confidentiality
3510
+ {
3511
+ controlId: "C1.1",
3512
+ name: "Confidential Information Classification",
3513
+ category: "confidentiality",
3514
+ status: "in_progress",
3515
+ lastAssessed: /* @__PURE__ */ new Date()
3516
+ },
3517
+ {
3518
+ controlId: "C1.2",
3519
+ name: "Confidential Information Disposal",
3520
+ category: "confidentiality",
3521
+ status: "in_progress",
3522
+ lastAssessed: /* @__PURE__ */ new Date()
3523
+ },
3524
+ // Privacy
3525
+ {
3526
+ controlId: "P1.1",
3527
+ name: "Privacy Notice",
3528
+ category: "privacy",
3529
+ status: "in_progress",
3530
+ lastAssessed: /* @__PURE__ */ new Date()
3531
+ },
3532
+ {
3533
+ controlId: "P2.1",
3534
+ name: "Consent",
3535
+ category: "privacy",
3536
+ status: "in_progress",
3537
+ lastAssessed: /* @__PURE__ */ new Date()
3538
+ },
3539
+ {
3540
+ controlId: "P3.1",
3541
+ name: "Collection",
3542
+ category: "privacy",
3543
+ status: "in_progress",
3544
+ lastAssessed: /* @__PURE__ */ new Date()
3545
+ }
3546
+ ];
3547
+ }
3548
+ const ur = {
3549
+ // Hardcoded secrets
3550
+ hardcodedSecrets: [
3551
+ { pattern: /password\s*[:=]\s*["'][^"']+["']/gi, name: "Hardcoded password" },
3552
+ { pattern: /api[_-]?key\s*[:=]\s*["'][^"']+["']/gi, name: "Hardcoded API key" },
3553
+ { pattern: /secret\s*[:=]\s*["'][^"']+["']/gi, name: "Hardcoded secret" },
3554
+ { pattern: /token\s*[:=]\s*["'][^"']+["']/gi, name: "Hardcoded token" }
3555
+ ],
3556
+ // SQL Injection
3557
+ sqlInjection: [
3558
+ { pattern: /execute\s*\(\s*["'`].*\$\{/gi, name: "Potential SQL injection (template literal)" },
3559
+ { pattern: /query\s*\(\s*["'`].*\+/gi, name: "Potential SQL injection (string concatenation)" }
3560
+ ],
3561
+ // XSS vulnerabilities
3562
+ xss: [
3563
+ { pattern: /dangerouslySetInnerHTML/g, name: "dangerouslySetInnerHTML usage" },
3564
+ { pattern: /innerHTML\s*=/g, name: "innerHTML assignment" },
3565
+ { pattern: /document\.write\s*\(/g, name: "document.write usage" },
3566
+ { pattern: /eval\s*\(/g, name: "eval usage" }
3567
+ ],
3568
+ // Insecure functions
3569
+ insecureFunctions: [
3570
+ { pattern: /Math\.random\s*\(\)/g, name: "Insecure random (use crypto)" },
3571
+ { pattern: /new Function\s*\(/g, name: "Function constructor (code injection risk)" },
3572
+ { pattern: /setTimeout\s*\(\s*["']/g, name: "setTimeout with string (code injection)" },
3573
+ { pattern: /setInterval\s*\(\s*["']/g, name: "setInterval with string (code injection)" }
3574
+ ],
3575
+ // Information exposure
3576
+ infoExposure: [
3577
+ {
3578
+ pattern: /console\.(log|info|warn|error)\s*\(/g,
3579
+ name: "Console logging (remove in production)"
3580
+ },
3581
+ { pattern: /debugger/g, name: "Debugger statement" },
3582
+ { pattern: /TODO.*password/gi, name: "TODO mentioning password" }
3583
+ ]
3584
+ };
3585
+ function dr() {
3586
+ return `# .github/workflows/sast.yml
3587
+ name: Security Scan (SAST)
3588
+
3589
+ on:
3590
+ push:
3591
+ branches: [main, develop]
3592
+ pull_request:
3593
+ branches: [main]
3594
+
3595
+ jobs:
3596
+ sast:
3597
+ runs-on: ubuntu-latest
3598
+ steps:
3599
+ - uses: actions/checkout@v4
3600
+
3601
+ - name: Run Semgrep
3602
+ uses: returntocorp/semgrep-action@v2
3603
+ with:
3604
+ config: >-
3605
+ p/security-audit
3606
+ p/secrets
3607
+ p/javascript
3608
+ p/typescript
3609
+
3610
+ - name: Run ESLint Security
3611
+ run: |
3612
+ npm ci
3613
+ npx eslint --config eslint.security.config.js --format json --output-file eslint-security.json ./src
3614
+
3615
+ - name: Upload SARIF
3616
+ uses: github/codeql-action/upload-sarif@v3
3617
+ with:
3618
+ sarif_file: semgrep.sarif
3619
+
3620
+ codeql:
3621
+ runs-on: ubuntu-latest
3622
+ permissions:
3623
+ security-events: write
3624
+ steps:
3625
+ - uses: actions/checkout@v4
3626
+
3627
+ - name: Initialize CodeQL
3628
+ uses: github/codeql-action/init@v3
3629
+ with:
3630
+ languages: javascript-typescript
3631
+
3632
+ - name: Perform Analysis
3633
+ uses: github/codeql-action/analyze@v3
3634
+ `;
3635
+ }
3636
+ function hr() {
3637
+ return `# .github/workflows/sca.yml
3638
+ name: Dependency Security (SCA)
3639
+
3640
+ on:
3641
+ push:
3642
+ branches: [main]
3643
+ pull_request:
3644
+ branches: [main]
3645
+ schedule:
3646
+ - cron: '0 0 * * *' # Daily at midnight
3647
+
3648
+ jobs:
3649
+ npm-audit:
3650
+ runs-on: ubuntu-latest
3651
+ steps:
3652
+ - uses: actions/checkout@v4
3653
+
3654
+ - name: Setup Node
3655
+ uses: actions/setup-node@v4
3656
+ with:
3657
+ node-version: '20'
3658
+
3659
+ - name: Install dependencies
3660
+ run: npm ci
3661
+
3662
+ - name: Run npm audit
3663
+ run: npm audit --audit-level=high --json > npm-audit.json || true
3664
+
3665
+ - name: Check critical vulnerabilities
3666
+ run: |
3667
+ CRITICAL=$(cat npm-audit.json | jq '.metadata.vulnerabilities.critical')
3668
+ HIGH=$(cat npm-audit.json | jq '.metadata.vulnerabilities.high')
3669
+ if [ "$CRITICAL" -gt 0 ] || [ "$HIGH" -gt 0 ]; then
3670
+ echo "Critical: $CRITICAL, High: $HIGH vulnerabilities found"
3671
+ exit 1
3672
+ fi
3673
+
3674
+ - name: Upload audit results
3675
+ uses: actions/upload-artifact@v4
3676
+ with:
3677
+ name: npm-audit
3678
+ path: npm-audit.json
3679
+
3680
+ license-check:
3681
+ runs-on: ubuntu-latest
3682
+ steps:
3683
+ - uses: actions/checkout@v4
3684
+
3685
+ - name: Check licenses
3686
+ run: |
3687
+ npx license-checker --production --onlyAllow "MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;CC0-1.0"
3688
+
3689
+ snyk:
3690
+ runs-on: ubuntu-latest
3691
+ steps:
3692
+ - uses: actions/checkout@v4
3693
+
3694
+ - name: Run Snyk
3695
+ uses: snyk/actions/node@master
3696
+ env:
3697
+ SNYK_TOKEN: \${{ secrets.SNYK_TOKEN }}
3698
+ with:
3699
+ args: --severity-threshold=high
3700
+ `;
3701
+ }
3702
+ const fr = [
3703
+ // API Keys
3704
+ { name: "AWS Access Key ID", pattern: /AKIA[0-9A-Z]{16}/g, severity: "critical" },
3705
+ { name: "AWS Secret Access Key", pattern: /[A-Za-z0-9/+=]{40}/g, severity: "critical" },
3706
+ { name: "Google API Key", pattern: /AIza[0-9A-Za-z-_]{35}/g, severity: "high" },
3707
+ { name: "GitHub Token", pattern: /gh[ps]_[A-Za-z0-9_]{36}/g, severity: "critical" },
3708
+ { name: "GitLab Token", pattern: /glpat-[A-Za-z0-9-_]{20}/g, severity: "critical" },
3709
+ {
3710
+ name: "Slack Token",
3711
+ pattern: /xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*/g,
3712
+ severity: "high"
3713
+ },
3714
+ { name: "Stripe Key", pattern: /sk_live_[0-9a-zA-Z]{24}/g, severity: "critical" },
3715
+ { name: "SendGrid Key", pattern: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g, severity: "high" },
3716
+ // Private Keys
3717
+ { name: "RSA Private Key", pattern: /-----BEGIN RSA PRIVATE KEY-----/g, severity: "critical" },
3718
+ {
3719
+ name: "SSH Private Key",
3720
+ pattern: /-----BEGIN OPENSSH PRIVATE KEY-----/g,
3721
+ severity: "critical"
3722
+ },
3723
+ {
3724
+ name: "PGP Private Key",
3725
+ pattern: /-----BEGIN PGP PRIVATE KEY BLOCK-----/g,
3726
+ severity: "critical"
3727
+ },
3728
+ // Credentials
3729
+ { name: "Basic Auth", pattern: /basic [a-zA-Z0-9_\-:.=]+/gi, severity: "high" },
3730
+ { name: "Bearer Token", pattern: /bearer [a-zA-Z0-9_\-.=]+/gi, severity: "high" },
3731
+ { name: "Connection String", pattern: /[a-z]+:\/\/[^:]+:[^@]+@[^/]+/gi, severity: "critical" }
3732
+ ];
3733
+ function yr() {
3734
+ return `#!/bin/sh
3735
+ # .git/hooks/pre-commit
3736
+
3737
+ echo "Scanning for secrets..."
3738
+
3739
+ # Define patterns to check
3740
+ PATTERNS=(
3741
+ 'AKIA[0-9A-Z]{16}'
3742
+ 'gh[ps]_[A-Za-z0-9_]{36}'
3743
+ 'sk_live_[0-9a-zA-Z]{24}'
3744
+ '-----BEGIN.*PRIVATE KEY-----'
3745
+ 'password.*=.*["'][^'"]+["']'
3746
+ )
3747
+
3748
+ FILES=$(git diff --cached --name-only --diff-filter=ACM)
3749
+
3750
+ for FILE in $FILES; do
3751
+ for PATTERN in "\${PATTERNS[@]}"; do
3752
+ if grep -qE "$PATTERN" "$FILE" 2>/dev/null; then
3753
+ echo "ERROR: Potential secret found in $FILE"
3754
+ echo "Pattern: $PATTERN"
3755
+ exit 1
3756
+ fi
3757
+ done
3758
+ done
3759
+
3760
+ echo "No secrets detected."
3761
+ exit 0
3762
+ `;
3763
+ }
3764
+ function pr() {
3765
+ return `# .github/workflows/secret-scanning.yml
3766
+ name: Secret Scanning
3767
+
3768
+ on:
3769
+ push:
3770
+ branches: [main, develop]
3771
+ pull_request:
3772
+ branches: [main]
3773
+
3774
+ jobs:
3775
+ gitleaks:
3776
+ runs-on: ubuntu-latest
3777
+ steps:
3778
+ - uses: actions/checkout@v4
3779
+ with:
3780
+ fetch-depth: 0
3781
+
3782
+ - name: Run Gitleaks
3783
+ uses: gitleaks/gitleaks-action@v2
3784
+ env:
3785
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
3786
+
3787
+ trufflehog:
3788
+ runs-on: ubuntu-latest
3789
+ steps:
3790
+ - uses: actions/checkout@v4
3791
+ with:
3792
+ fetch-depth: 0
3793
+
3794
+ - name: Run TruffleHog
3795
+ uses: trufflesecurity/trufflehog@main
3796
+ with:
3797
+ path: ./
3798
+ base: \${{ github.event.repository.default_branch }}
3799
+ head: HEAD
3800
+ `;
3801
+ }
3802
+ function gr(e) {
3803
+ return `# Security Advisory
3804
+
3805
+ ## ${e.cves.join(", ")} - ${e.description}
3806
+
3807
+ **Severity:** ${e.severity.toUpperCase()}
3808
+ **Date:** ${e.date}
3809
+
3810
+ ### Affected Versions
3811
+
3812
+ ${e.affectedVersions}
3813
+
3814
+ ### Fixed In
3815
+
3816
+ ${e.fixedIn}
3817
+
3818
+ ### Description
3819
+
3820
+ ${e.description}
3821
+
3822
+ ### Remediation
3823
+
3824
+ Update to version ${e.version} or later:
3825
+
3826
+ \`\`\`bash
3827
+ npm install @nice2dev/ui@${e.version}
3828
+ \`\`\`
3829
+
3830
+ ${e.acknowledgments ? `### Acknowledgments
3831
+
3832
+ Thank you to the following researchers for responsibly disclosing this issue:
3833
+
3834
+ ${e.acknowledgments.map((t) => `- ${t}`).join(`
3835
+ `)}
3836
+ ` : ""}
3837
+
3838
+ ### Timeline
3839
+
3840
+ - **Date reported:** ${e.date}
3841
+ - **Date fixed:** ${e.date}
3842
+ - **Date disclosed:** ${e.date}
3843
+
3844
+ ### References
3845
+
3846
+ ${e.cves.map((t) => `- [${t}](https://www.cve.org/CVERecord?id=${t})`).join(`
3847
+ `)}
3848
+ `;
3849
+ }
3850
+ function mr() {
3851
+ return `# Security Policy
3852
+
3853
+ ## Supported Versions
3854
+
3855
+ | Version | Supported |
3856
+ | ------- | ------------------ |
3857
+ | 1.0.x | :white_check_mark: |
3858
+ | < 1.0 | :x: |
3859
+
3860
+ ## Reporting a Vulnerability
3861
+
3862
+ We take security seriously. If you discover a security vulnerability, please follow these steps:
3863
+
3864
+ ### 1. Do Not Create a Public Issue
3865
+
3866
+ **Please do not report security vulnerabilities through public GitHub issues.**
3867
+
3868
+ ### 2. Report Privately
3869
+
3870
+ Send an email to **security@nice2dev.com** with:
3871
+
3872
+ - Description of the vulnerability
3873
+ - Steps to reproduce
3874
+ - Potential impact
3875
+ - Any suggested fixes (optional)
3876
+
3877
+ ### 3. Encryption
3878
+
3879
+ For sensitive reports, use our PGP key:
3880
+
3881
+ \`\`\`
3882
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
3883
+ [PGP KEY HERE]
3884
+ -----END PGP PUBLIC KEY BLOCK-----
3885
+ \`\`\`
3886
+
3887
+ ## Response Timeline
3888
+
3889
+ - **Initial Response:** Within 24 hours
3890
+ - **Severity Assessment:** Within 48 hours
3891
+ - **Fix Development:** Depends on severity
3892
+ - Critical: Within 24 hours
3893
+ - High: Within 72 hours
3894
+ - Medium: Within 1 week
3895
+ - Low: Within 2 weeks
3896
+ - **Disclosure:** After fix is released
3897
+
3898
+ ## Bug Bounty
3899
+
3900
+ We offer bug bounties for qualifying vulnerabilities:
3901
+
3902
+ | Severity | Bounty Range |
3903
+ | -------- | ------------ |
3904
+ | Critical | $1,000 - $5,000 |
3905
+ | High | $500 - $1,000 |
3906
+ | Medium | $100 - $500 |
3907
+ | Low | Acknowledgment |
3908
+
3909
+ ## Safe Harbor
3910
+
3911
+ We will not pursue legal action against researchers who:
3912
+
3913
+ - Make good faith efforts to comply with this policy
3914
+ - Report vulnerabilities in a timely manner
3915
+ - Do not access, modify, or delete user data
3916
+ - Do not disrupt our services
3917
+ - Do not disclose vulnerabilities before they are fixed
3918
+ `;
3919
+ }
3920
+ export {
3921
+ $t as NiceDeviceTrust,
3922
+ Ct as NiceFaceRecognition,
3923
+ Mt as NiceFingerprintScanner,
3924
+ Dt as NiceI18nProvider,
3925
+ Rt as NiceIrisScanner,
3926
+ Nt as NiceMfaSelector,
3927
+ jt as NicePassphraseInput,
3928
+ Et as NicePatternLock,
3929
+ Pt as NicePinKeypad,
3930
+ zt as NiceSecurityAuditLog,
3931
+ Lt as NiceSessionManager,
3932
+ Ft as NiceWebAuthnButton,
3933
+ fr as SECRET_PATTERNS,
3934
+ ur as SECURITY_PATTERNS,
3935
+ Xe as authenticateWebAuthn,
3936
+ ae as captureFrame,
3937
+ sr as checkColorContrast,
3938
+ ar as checkHeadingHierarchy,
3939
+ Ae as checkLiveness,
3940
+ er as clearNonEssentialCookies,
3941
+ Te as collectDeviceInfo,
3942
+ Ke as compareFaceToPhoto,
3943
+ cr as createAuditLogger,
3944
+ Gt as createCSRFFetch,
3945
+ ir as createHIPAASession,
3946
+ wt as createRateLimiter,
3947
+ qt as createSafeHtml,
3948
+ Ue as detectIris,
3949
+ xt as escapeHtml,
3950
+ ue as extractFaceFeatures,
3951
+ je as extractMinutiae,
3952
+ Ge as faceToTemplate,
3953
+ We as fingerprintToTemplate,
3954
+ Bt as generateCSPHeader,
3955
+ Kt as generateCSRFToken,
3956
+ tr as generateDataExport,
3957
+ le as generateDeviceFingerprint,
3958
+ It as generateLivenessChallenge,
3959
+ _t as generateNonce,
3960
+ yr as generatePreCommitHook,
3961
+ dr as generateSASTConfig,
3962
+ hr as generateSCAConfig,
3963
+ pr as generateSecretScanningConfig,
3964
+ gr as generateSecurityAdvisory,
3965
+ mr as generateSecurityMd,
3966
+ Me as getCSRFTokenFromCookie,
3967
+ fe as getCameraStream,
3968
+ kt as getConsentPreferences,
3969
+ Wt as getRecommendedCSP,
3970
+ lr as getSOC2Checklist,
3971
+ or as hasAccessibleName,
3972
+ Vt as hasConsent,
3973
+ Oe as irisToTemplate,
3974
+ Ze as isPasskeyAvailable,
3975
+ Ie as isWebAuthnAvailable,
3976
+ nr as logPHIAccess,
3977
+ ke as matchFaces,
3978
+ Be as matchFingerprints,
3979
+ He as matchIris,
3980
+ Ye as registerWebAuthn,
3981
+ rr as requestDataDeletion,
3982
+ de as resolveConfig,
3983
+ Ut as sanitizeInput,
3984
+ Ot as sanitizeSvg,
3985
+ Ht as sanitizeUrl,
3986
+ Qt as saveConsentPreferences,
3987
+ Xt as scanFileForViruses,
3988
+ Je as templateToFace,
3989
+ _e as templateToFingerprint,
3990
+ qe as templateToIris,
3991
+ Jt as useCSRFToken,
3992
+ ee as useNiceTranslation,
3993
+ Zt as useRateLimiter,
3994
+ St as validateFile,
3995
+ Yt as validateFiles,
3996
+ ye as verifyWithBackend
3997
+ };