@spektre/veil 0.1.6 → 0.1.8

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.
@@ -1,3 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { SecurityGateProps } from './types';
3
3
  export declare const SecurityGate: React.FC<SecurityGateProps>;
4
+ declare global {
5
+ interface Window {
6
+ __spektreDevDisabled?: boolean;
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ export declare function initializeDevUI(): void;
2
+ export declare function isSpektreDisabled(): boolean;
3
+ declare global {
4
+ interface Window {
5
+ __spektreDevDisabled?: boolean;
6
+ }
7
+ }
package/dist/index.esm.js CHANGED
@@ -1,5 +1,558 @@
1
1
  import React, { createContext, useState, useEffect, useContext } from 'react';
2
2
 
3
+ const DEV_UI_STORAGE_KEY = 'spektre_dev_enabled';
4
+ // Inject styles directly into the document
5
+ function injectDevUIStyles() {
6
+ if (document.getElementById('spektre-dev-ui-styles')) {
7
+ return; // Already injected
8
+ }
9
+ const styleSheet = document.createElement('style');
10
+ styleSheet.id = 'spektre-dev-ui-styles';
11
+ styleSheet.textContent = `
12
+ /* Spektre Dev UI Dot */
13
+ .spektre-dev-dot {
14
+ position: fixed;
15
+ bottom: 24px;
16
+ right: 24px;
17
+ width: 16px;
18
+ height: 16px;
19
+ background-color: #f97316;
20
+ border-radius: 50%;
21
+ cursor: pointer;
22
+ z-index: 9998;
23
+ box-shadow: 0 4px 12px rgba(249, 115, 22, 0.4);
24
+ transition: all 0.2s ease;
25
+ outline: none;
26
+ border: none;
27
+ }
28
+
29
+ .spektre-dev-dot:hover {
30
+ width: 20px;
31
+ height: 20px;
32
+ bottom: 22px;
33
+ right: 22px;
34
+ box-shadow: 0 6px 16px rgba(249, 115, 22, 0.6);
35
+ transform: scale(1.1);
36
+ }
37
+
38
+ .spektre-dev-dot.disabled {
39
+ background-color: #64748b;
40
+ box-shadow: 0 4px 12px rgba(100, 116, 139, 0.4);
41
+ }
42
+
43
+ .spektre-dev-dot.disabled:hover {
44
+ box-shadow: 0 6px 16px rgba(100, 116, 139, 0.6);
45
+ }
46
+
47
+ .spektre-dev-dot.warning {
48
+ background-color: #ef4444;
49
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.6);
50
+ animation: spektre-pulse 2s infinite;
51
+ }
52
+
53
+ @keyframes spektre-pulse {
54
+ 0%, 100% {
55
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.6);
56
+ }
57
+ 50% {
58
+ box-shadow: 0 4px 20px rgba(239, 68, 68, 0.8);
59
+ }
60
+ }
61
+
62
+ /* Modal Overlay */
63
+ .spektre-dev-modal-overlay {
64
+ position: fixed;
65
+ top: 0;
66
+ left: 0;
67
+ right: 0;
68
+ bottom: 0;
69
+ background-color: rgba(0, 0, 0, 0.7);
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ z-index: 9999;
74
+ animation: spektre-fade-in 0.2s ease;
75
+ }
76
+
77
+ @keyframes spektre-fade-in {
78
+ from {
79
+ opacity: 0;
80
+ }
81
+ to {
82
+ opacity: 1;
83
+ }
84
+ }
85
+
86
+ /* Modal Container */
87
+ .spektre-dev-modal {
88
+ background-color: #000000;
89
+ border: 1px solid #1e293b;
90
+ border-radius: 12px;
91
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
92
+ width: 90%;
93
+ max-width: 400px;
94
+ overflow: hidden;
95
+ animation: spektre-slide-up 0.3s ease;
96
+ }
97
+
98
+ @keyframes spektre-slide-up {
99
+ from {
100
+ transform: translateY(20px);
101
+ opacity: 0;
102
+ }
103
+ to {
104
+ transform: translateY(0);
105
+ opacity: 1;
106
+ }
107
+ }
108
+
109
+ /* Modal Header */
110
+ .spektre-dev-modal-header {
111
+ display: flex;
112
+ justify-content: space-between;
113
+ align-items: center;
114
+ padding: 20px;
115
+ border-bottom: 1px solid #1e293b;
116
+ background: linear-gradient(135deg, rgba(249, 115, 22, 0.1) 0%, rgba(0, 0, 0, 0.5) 100%);
117
+ }
118
+
119
+ .spektre-dev-modal-header h2 {
120
+ margin: 0;
121
+ font-size: 18px;
122
+ font-weight: 600;
123
+ color: #ffffff;
124
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
125
+ }
126
+
127
+ .spektre-dev-modal-close {
128
+ background: none;
129
+ border: none;
130
+ color: #94a3b8;
131
+ font-size: 24px;
132
+ cursor: pointer;
133
+ padding: 0;
134
+ width: 28px;
135
+ height: 28px;
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ transition: color 0.2s ease;
140
+ border-radius: 4px;
141
+ }
142
+
143
+ .spektre-dev-modal-close:hover {
144
+ color: #f97316;
145
+ background-color: rgba(249, 115, 22, 0.1);
146
+ }
147
+
148
+ /* Modal Body */
149
+ .spektre-dev-modal-body {
150
+ padding: 24px;
151
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
152
+ max-height: 60vh;
153
+ overflow-y: auto;
154
+ }
155
+
156
+ .spektre-dev-modal-info {
157
+ margin: 0 0 16px 0;
158
+ font-size: 14px;
159
+ color: #cbd5e1;
160
+ line-height: 1.5;
161
+ }
162
+
163
+ /* Status Badge */
164
+ .spektre-dev-modal-status {
165
+ display: inline-block;
166
+ padding: 8px 12px;
167
+ border-radius: 6px;
168
+ font-size: 14px;
169
+ font-weight: 500;
170
+ margin-bottom: 20px;
171
+ font-family: monospace;
172
+ transition: all 0.2s ease;
173
+ }
174
+
175
+ .spektre-dev-modal-status.enabled {
176
+ background-color: rgba(34, 197, 94, 0.15);
177
+ color: #86efac;
178
+ border: 1px solid rgba(34, 197, 94, 0.3);
179
+ }
180
+
181
+ .spektre-dev-modal-status.disabled {
182
+ background-color: rgba(100, 116, 139, 0.15);
183
+ color: #cbd5e1;
184
+ border: 1px solid rgba(100, 116, 139, 0.3);
185
+ }
186
+
187
+ /* Toggle Container */
188
+ .spektre-dev-modal-toggle-container {
189
+ display: flex;
190
+ align-items: center;
191
+ margin-bottom: 16px;
192
+ }
193
+
194
+ .spektre-dev-toggle-label {
195
+ display: flex;
196
+ align-items: center;
197
+ gap: 12px;
198
+ cursor: pointer;
199
+ font-size: 14px;
200
+ color: #e2e8f0;
201
+ user-select: none;
202
+ }
203
+
204
+ /* Toggle Switch */
205
+ .spektre-dev-toggle {
206
+ appearance: none;
207
+ -webkit-appearance: none;
208
+ width: 44px;
209
+ height: 24px;
210
+ background-color: #1e293b;
211
+ border: 1px solid #334155;
212
+ border-radius: 12px;
213
+ cursor: pointer;
214
+ position: relative;
215
+ transition: all 0.3s ease;
216
+ padding: 2px;
217
+ flex-shrink: 0;
218
+ }
219
+
220
+ .spektre-dev-toggle:checked {
221
+ background-color: #f97316;
222
+ border-color: #f97316;
223
+ }
224
+
225
+ .spektre-dev-toggle::before {
226
+ content: '';
227
+ position: absolute;
228
+ width: 18px;
229
+ height: 18px;
230
+ background-color: white;
231
+ border-radius: 10px;
232
+ top: 3px;
233
+ left: 3px;
234
+ transition: left 0.3s ease;
235
+ }
236
+
237
+ .spektre-dev-toggle:checked::before {
238
+ left: 23px;
239
+ }
240
+
241
+ .spektre-dev-toggle:focus {
242
+ outline: none;
243
+ box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.2);
244
+ }
245
+
246
+ /* Reload Message */
247
+ .spektre-dev-modal-reload-msg {
248
+ margin: 0;
249
+ padding: 12px;
250
+ background-color: rgba(249, 115, 22, 0.15);
251
+ border: 1px solid rgba(249, 115, 22, 0.3);
252
+ border-radius: 6px;
253
+ font-size: 13px;
254
+ color: #fed7aa;
255
+ text-align: center;
256
+ transition: opacity 0.2s ease;
257
+ font-weight: 500;
258
+ }
259
+
260
+ /* Security Scan Results */
261
+ .spektre-security-scan-container {
262
+ margin-top: 16px;
263
+ padding: 16px;
264
+ background-color: rgba(239, 68, 68, 0.1);
265
+ border: 1px solid rgba(239, 68, 68, 0.3);
266
+ border-radius: 8px;
267
+ }
268
+
269
+ .spektre-security-scan-title {
270
+ font-size: 14px;
271
+ font-weight: 600;
272
+ color: #fca5a5;
273
+ margin: 0 0 12px 0;
274
+ display: flex;
275
+ align-items: center;
276
+ gap: 8px;
277
+ }
278
+
279
+ .spektre-security-scan-issues {
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: 8px;
283
+ }
284
+
285
+ .spektre-security-issue {
286
+ font-size: 13px;
287
+ color: #fed7aa;
288
+ padding: 8px;
289
+ background-color: rgba(239, 68, 68, 0.15);
290
+ border-left: 3px solid #ef4444;
291
+ border-radius: 4px;
292
+ line-height: 1.4;
293
+ }
294
+
295
+ .spektre-security-scan-clean {
296
+ font-size: 13px;
297
+ color: #86efac;
298
+ padding: 12px;
299
+ background-color: rgba(34, 197, 94, 0.15);
300
+ border: 1px solid rgba(34, 197, 94, 0.3);
301
+ border-radius: 6px;
302
+ text-align: center;
303
+ font-weight: 500;
304
+ }
305
+
306
+ /* Accessibility */
307
+ @media (prefers-reduced-motion: reduce) {
308
+ .spektre-dev-dot,
309
+ .spektre-dev-modal-overlay,
310
+ .spektre-dev-modal,
311
+ .spektre-dev-toggle,
312
+ .spektre-dev-toggle::before {
313
+ animation: none;
314
+ transition: none;
315
+ }
316
+ }
317
+
318
+ /* Mobile responsiveness */
319
+ @media (max-width: 480px) {
320
+ .spektre-dev-dot {
321
+ bottom: 16px;
322
+ right: 16px;
323
+ width: 14px;
324
+ height: 14px;
325
+ }
326
+
327
+ .spektre-dev-dot:hover {
328
+ width: 18px;
329
+ height: 18px;
330
+ bottom: 14px;
331
+ right: 14px;
332
+ }
333
+
334
+ .spektre-dev-modal {
335
+ width: 85%;
336
+ max-width: 320px;
337
+ }
338
+
339
+ .spektre-dev-modal-header h2 {
340
+ font-size: 16px;
341
+ }
342
+
343
+ .spektre-dev-modal-body {
344
+ padding: 16px;
345
+ }
346
+ }
347
+ `;
348
+ document.head.appendChild(styleSheet);
349
+ }
350
+ function runSecurityScan() {
351
+ const issues = [];
352
+ // 1. Check for hardcoded API keys/tokens
353
+ const sensitivePatterns = [
354
+ { pattern: /api[_-]?key\s*[:=]\s*['"]\S+['"]/gi, label: 'API Key' },
355
+ { pattern: /token\s*[:=]\s*['"]\S+['"]/gi, label: 'Token' },
356
+ { pattern: /password\s*[:=]\s*['"]\S+['"]/gi, label: 'Password' },
357
+ { pattern: /secret\s*[:=]\s*['"]\S+['"]/gi, label: 'Secret' },
358
+ { pattern: /bearer\s+[A-Za-z0-9\-._~+/]+=*/gi, label: 'Bearer Token' },
359
+ ];
360
+ const pageHTML = document.documentElement.outerHTML;
361
+ const scriptTags = Array.from(document.querySelectorAll('script'));
362
+ const allText = pageHTML + scriptTags.map(s => s.textContent).join('\n');
363
+ sensitivePatterns.forEach(({ pattern, label }) => {
364
+ if (pattern.test(allText)) {
365
+ issues.push(`⚠️ Found hardcoded ${label} in page code`);
366
+ }
367
+ });
368
+ // 2. Check for dangerous functions
369
+ const dangerousPatterns = [
370
+ { pattern: /eval\s*\(/gi, label: 'eval() usage' },
371
+ { pattern: /innerHTML\s*=/gi, label: 'innerHTML manipulation' },
372
+ { pattern: /dangerouslySetInnerHTML/gi, label: 'dangerouslySetInnerHTML' },
373
+ { pattern: /document\.write/gi, label: 'document.write()' },
374
+ { pattern: /setTimeout\s*\(\s*['"`].*['"`]/gi, label: 'setTimeout with string' },
375
+ ];
376
+ dangerousPatterns.forEach(({ pattern, label }) => {
377
+ if (pattern.test(allText)) {
378
+ issues.push(`⚠️ Potential security risk: ${label}`);
379
+ }
380
+ });
381
+ // 3. Check localStorage for sensitive data
382
+ try {
383
+ for (let i = 0; i < localStorage.length; i++) {
384
+ const key = localStorage.key(i);
385
+ if (key) {
386
+ const value = localStorage.getItem(key);
387
+ if (value) {
388
+ if (/token|password|secret|key|auth/i.test(key) &&
389
+ value.length > 20) {
390
+ issues.push(`⚠️ Sensitive data in localStorage: "${key}"`);
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
396
+ catch (e) {
397
+ // localStorage access denied, skip
398
+ }
399
+ // 4. Check for missing CSP headers (via console warning detection)
400
+ const scripts = scriptTags.filter(s => s.src && !s.src.includes('spektre'));
401
+ if (scripts.length > 10) {
402
+ issues.push(`⚠️ Many external scripts loaded (${scripts.length})`);
403
+ }
404
+ return {
405
+ hasIssues: issues.length > 0,
406
+ issues,
407
+ };
408
+ }
409
+ function initializeDevUI() {
410
+ // Inject styles first
411
+ injectDevUIStyles();
412
+ // Check if Spektre is enabled in localStorage (default to true)
413
+ const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY);
414
+ const spektreEnabled = isEnabled === null ? true : isEnabled === 'true';
415
+ // If disabled, prevent core Spektre from initializing
416
+ if (!spektreEnabled) {
417
+ window.__spektreDevDisabled = true;
418
+ }
419
+ // Create and inject the orange dot
420
+ createDevDot();
421
+ // Run security scan after a short delay to ensure DOM is ready
422
+ setTimeout(() => {
423
+ const scanResult = runSecurityScan();
424
+ if (scanResult.hasIssues) {
425
+ // Update dot to warning state and auto-open modal
426
+ const dot = document.getElementById('spektre-dev-dot');
427
+ if (dot) {
428
+ dot.classList.add('warning');
429
+ }
430
+ openDevModal(scanResult);
431
+ }
432
+ }, 500);
433
+ }
434
+ function createDevDot() {
435
+ const dot = document.createElement('div');
436
+ dot.id = 'spektre-dev-dot';
437
+ dot.className = 'spektre-dev-dot';
438
+ dot.setAttribute('aria-label', 'Spektre development environment controls');
439
+ dot.addEventListener('click', () => {
440
+ openDevModal();
441
+ });
442
+ document.body.appendChild(dot);
443
+ }
444
+ function openDevModal(scanResult) {
445
+ // Check if modal already exists
446
+ if (document.getElementById('spektre-dev-modal')) {
447
+ return;
448
+ }
449
+ const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY) !== 'false';
450
+ const modal = document.createElement('div');
451
+ modal.id = 'spektre-dev-modal';
452
+ modal.className = 'spektre-dev-modal-overlay';
453
+ const modalContent = document.createElement('div');
454
+ modalContent.className = 'spektre-dev-modal';
455
+ const header = document.createElement('div');
456
+ header.className = 'spektre-dev-modal-header';
457
+ header.innerHTML = '<h2>Spektre Development Mode</h2>';
458
+ const closeButton = document.createElement('button');
459
+ closeButton.className = 'spektre-dev-modal-close';
460
+ closeButton.innerHTML = '✕';
461
+ closeButton.setAttribute('aria-label', 'Close modal');
462
+ closeButton.addEventListener('click', () => {
463
+ modal.remove();
464
+ });
465
+ header.appendChild(closeButton);
466
+ const body = document.createElement('div');
467
+ body.className = 'spektre-dev-modal-body';
468
+ const infoText = document.createElement('p');
469
+ infoText.className = 'spektre-dev-modal-info';
470
+ infoText.textContent = 'You are in a development environment. Spektre is currently:';
471
+ const statusBadge = document.createElement('div');
472
+ statusBadge.className = `spektre-dev-modal-status ${isEnabled ? 'enabled' : 'disabled'}`;
473
+ statusBadge.textContent = isEnabled ? '● Enabled' : '● Disabled';
474
+ const toggleContainer = document.createElement('div');
475
+ toggleContainer.className = 'spektre-dev-modal-toggle-container';
476
+ const toggleLabel = document.createElement('label');
477
+ toggleLabel.className = 'spektre-dev-toggle-label';
478
+ const toggleSwitch = document.createElement('input');
479
+ toggleSwitch.type = 'checkbox';
480
+ toggleSwitch.className = 'spektre-dev-toggle';
481
+ toggleSwitch.checked = isEnabled;
482
+ toggleSwitch.setAttribute('aria-label', 'Toggle Spektre');
483
+ toggleSwitch.addEventListener('change', (e) => {
484
+ const enabled = e.target.checked;
485
+ localStorage.setItem(DEV_UI_STORAGE_KEY, String(enabled));
486
+ // Update status badge
487
+ statusBadge.className = `spektre-dev-modal-status ${enabled ? 'enabled' : 'disabled'}`;
488
+ statusBadge.textContent = enabled ? '● Enabled' : '● Disabled';
489
+ // Update dot visual
490
+ const dot = document.getElementById('spektre-dev-dot');
491
+ if (dot) {
492
+ dot.classList.toggle('disabled', !enabled);
493
+ }
494
+ // Show reload message
495
+ const reloadMsg = document.querySelector('.spektre-dev-modal-reload-msg');
496
+ if (reloadMsg) {
497
+ reloadMsg.textContent = 'Reload the page for changes to take effect';
498
+ reloadMsg.style.opacity = '1';
499
+ }
500
+ });
501
+ toggleLabel.appendChild(toggleSwitch);
502
+ toggleLabel.appendChild(document.createTextNode('Enable Spektre'));
503
+ toggleContainer.appendChild(toggleLabel);
504
+ const reloadMessage = document.createElement('p');
505
+ reloadMessage.className = 'spektre-dev-modal-reload-msg';
506
+ reloadMessage.style.opacity = '0';
507
+ body.appendChild(infoText);
508
+ body.appendChild(statusBadge);
509
+ body.appendChild(toggleContainer);
510
+ body.appendChild(reloadMessage);
511
+ // Add security scan results if available
512
+ if (scanResult) {
513
+ const scanContainer = document.createElement('div');
514
+ scanContainer.className = 'spektre-security-scan-container';
515
+ const scanTitle = document.createElement('div');
516
+ scanTitle.className = 'spektre-security-scan-title';
517
+ scanTitle.innerHTML = '🔒 Security Check';
518
+ scanContainer.appendChild(scanTitle);
519
+ if (scanResult.hasIssues) {
520
+ const issuesContainer = document.createElement('div');
521
+ issuesContainer.className = 'spektre-security-scan-issues';
522
+ scanResult.issues.forEach(issue => {
523
+ const issueElement = document.createElement('div');
524
+ issueElement.className = 'spektre-security-issue';
525
+ issueElement.textContent = issue;
526
+ issuesContainer.appendChild(issueElement);
527
+ });
528
+ scanContainer.appendChild(issuesContainer);
529
+ }
530
+ else {
531
+ const cleanMessage = document.createElement('div');
532
+ cleanMessage.className = 'spektre-security-scan-clean';
533
+ cleanMessage.textContent = '✓ No security issues detected';
534
+ scanContainer.appendChild(cleanMessage);
535
+ }
536
+ body.appendChild(scanContainer);
537
+ }
538
+ modalContent.appendChild(header);
539
+ modalContent.appendChild(body);
540
+ modal.appendChild(modalContent);
541
+ // Close on overlay click
542
+ modal.addEventListener('click', (e) => {
543
+ if (e.target === modal) {
544
+ modal.remove();
545
+ }
546
+ });
547
+ // Close on escape key
548
+ document.addEventListener('keydown', (e) => {
549
+ if (e.key === 'Escape' && document.getElementById('spektre-dev-modal')) {
550
+ modal.remove();
551
+ }
552
+ }, { once: true });
553
+ document.body.appendChild(modal);
554
+ }
555
+
3
556
  const SpektreContext = createContext(null);
4
557
  SpektreContext.displayName = 'SpektreContext';
5
558
 
@@ -16,6 +569,16 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
16
569
  sessionId: null,
17
570
  });
18
571
  useEffect(() => {
572
+ // Check if Spektre is disabled in dev mode
573
+ if (window.__spektreDevDisabled) {
574
+ setState({
575
+ isVerified: true,
576
+ isLoading: false,
577
+ error: null,
578
+ sessionId: 'dev-disabled',
579
+ });
580
+ return;
581
+ }
19
582
  // Set tampering detection marker
20
583
  sessionStorage.setItem('spektre_js_enabled', 'true');
21
584
  sessionStorage.setItem('spektre_init_time', Date.now().toString());
@@ -430,5 +993,10 @@ const useProtectedFetch = () => {
430
993
  return protectedFetch;
431
994
  };
432
995
 
996
+ // Check if we're in an iframe (development environment) and initialize dev UI
997
+ if (typeof window !== 'undefined' && window.self !== window.top) {
998
+ initializeDevUI();
999
+ }
1000
+
433
1001
  export { SecurityGate, SpektreContext, SpektreProvider, useProtectedFetch, useSpektre };
434
1002
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -2,6 +2,559 @@
2
2
 
3
3
  var React = require('react');
4
4
 
5
+ const DEV_UI_STORAGE_KEY = 'spektre_dev_enabled';
6
+ // Inject styles directly into the document
7
+ function injectDevUIStyles() {
8
+ if (document.getElementById('spektre-dev-ui-styles')) {
9
+ return; // Already injected
10
+ }
11
+ const styleSheet = document.createElement('style');
12
+ styleSheet.id = 'spektre-dev-ui-styles';
13
+ styleSheet.textContent = `
14
+ /* Spektre Dev UI Dot */
15
+ .spektre-dev-dot {
16
+ position: fixed;
17
+ bottom: 24px;
18
+ right: 24px;
19
+ width: 16px;
20
+ height: 16px;
21
+ background-color: #f97316;
22
+ border-radius: 50%;
23
+ cursor: pointer;
24
+ z-index: 9998;
25
+ box-shadow: 0 4px 12px rgba(249, 115, 22, 0.4);
26
+ transition: all 0.2s ease;
27
+ outline: none;
28
+ border: none;
29
+ }
30
+
31
+ .spektre-dev-dot:hover {
32
+ width: 20px;
33
+ height: 20px;
34
+ bottom: 22px;
35
+ right: 22px;
36
+ box-shadow: 0 6px 16px rgba(249, 115, 22, 0.6);
37
+ transform: scale(1.1);
38
+ }
39
+
40
+ .spektre-dev-dot.disabled {
41
+ background-color: #64748b;
42
+ box-shadow: 0 4px 12px rgba(100, 116, 139, 0.4);
43
+ }
44
+
45
+ .spektre-dev-dot.disabled:hover {
46
+ box-shadow: 0 6px 16px rgba(100, 116, 139, 0.6);
47
+ }
48
+
49
+ .spektre-dev-dot.warning {
50
+ background-color: #ef4444;
51
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.6);
52
+ animation: spektre-pulse 2s infinite;
53
+ }
54
+
55
+ @keyframes spektre-pulse {
56
+ 0%, 100% {
57
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.6);
58
+ }
59
+ 50% {
60
+ box-shadow: 0 4px 20px rgba(239, 68, 68, 0.8);
61
+ }
62
+ }
63
+
64
+ /* Modal Overlay */
65
+ .spektre-dev-modal-overlay {
66
+ position: fixed;
67
+ top: 0;
68
+ left: 0;
69
+ right: 0;
70
+ bottom: 0;
71
+ background-color: rgba(0, 0, 0, 0.7);
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ z-index: 9999;
76
+ animation: spektre-fade-in 0.2s ease;
77
+ }
78
+
79
+ @keyframes spektre-fade-in {
80
+ from {
81
+ opacity: 0;
82
+ }
83
+ to {
84
+ opacity: 1;
85
+ }
86
+ }
87
+
88
+ /* Modal Container */
89
+ .spektre-dev-modal {
90
+ background-color: #000000;
91
+ border: 1px solid #1e293b;
92
+ border-radius: 12px;
93
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
94
+ width: 90%;
95
+ max-width: 400px;
96
+ overflow: hidden;
97
+ animation: spektre-slide-up 0.3s ease;
98
+ }
99
+
100
+ @keyframes spektre-slide-up {
101
+ from {
102
+ transform: translateY(20px);
103
+ opacity: 0;
104
+ }
105
+ to {
106
+ transform: translateY(0);
107
+ opacity: 1;
108
+ }
109
+ }
110
+
111
+ /* Modal Header */
112
+ .spektre-dev-modal-header {
113
+ display: flex;
114
+ justify-content: space-between;
115
+ align-items: center;
116
+ padding: 20px;
117
+ border-bottom: 1px solid #1e293b;
118
+ background: linear-gradient(135deg, rgba(249, 115, 22, 0.1) 0%, rgba(0, 0, 0, 0.5) 100%);
119
+ }
120
+
121
+ .spektre-dev-modal-header h2 {
122
+ margin: 0;
123
+ font-size: 18px;
124
+ font-weight: 600;
125
+ color: #ffffff;
126
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
127
+ }
128
+
129
+ .spektre-dev-modal-close {
130
+ background: none;
131
+ border: none;
132
+ color: #94a3b8;
133
+ font-size: 24px;
134
+ cursor: pointer;
135
+ padding: 0;
136
+ width: 28px;
137
+ height: 28px;
138
+ display: flex;
139
+ align-items: center;
140
+ justify-content: center;
141
+ transition: color 0.2s ease;
142
+ border-radius: 4px;
143
+ }
144
+
145
+ .spektre-dev-modal-close:hover {
146
+ color: #f97316;
147
+ background-color: rgba(249, 115, 22, 0.1);
148
+ }
149
+
150
+ /* Modal Body */
151
+ .spektre-dev-modal-body {
152
+ padding: 24px;
153
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
154
+ max-height: 60vh;
155
+ overflow-y: auto;
156
+ }
157
+
158
+ .spektre-dev-modal-info {
159
+ margin: 0 0 16px 0;
160
+ font-size: 14px;
161
+ color: #cbd5e1;
162
+ line-height: 1.5;
163
+ }
164
+
165
+ /* Status Badge */
166
+ .spektre-dev-modal-status {
167
+ display: inline-block;
168
+ padding: 8px 12px;
169
+ border-radius: 6px;
170
+ font-size: 14px;
171
+ font-weight: 500;
172
+ margin-bottom: 20px;
173
+ font-family: monospace;
174
+ transition: all 0.2s ease;
175
+ }
176
+
177
+ .spektre-dev-modal-status.enabled {
178
+ background-color: rgba(34, 197, 94, 0.15);
179
+ color: #86efac;
180
+ border: 1px solid rgba(34, 197, 94, 0.3);
181
+ }
182
+
183
+ .spektre-dev-modal-status.disabled {
184
+ background-color: rgba(100, 116, 139, 0.15);
185
+ color: #cbd5e1;
186
+ border: 1px solid rgba(100, 116, 139, 0.3);
187
+ }
188
+
189
+ /* Toggle Container */
190
+ .spektre-dev-modal-toggle-container {
191
+ display: flex;
192
+ align-items: center;
193
+ margin-bottom: 16px;
194
+ }
195
+
196
+ .spektre-dev-toggle-label {
197
+ display: flex;
198
+ align-items: center;
199
+ gap: 12px;
200
+ cursor: pointer;
201
+ font-size: 14px;
202
+ color: #e2e8f0;
203
+ user-select: none;
204
+ }
205
+
206
+ /* Toggle Switch */
207
+ .spektre-dev-toggle {
208
+ appearance: none;
209
+ -webkit-appearance: none;
210
+ width: 44px;
211
+ height: 24px;
212
+ background-color: #1e293b;
213
+ border: 1px solid #334155;
214
+ border-radius: 12px;
215
+ cursor: pointer;
216
+ position: relative;
217
+ transition: all 0.3s ease;
218
+ padding: 2px;
219
+ flex-shrink: 0;
220
+ }
221
+
222
+ .spektre-dev-toggle:checked {
223
+ background-color: #f97316;
224
+ border-color: #f97316;
225
+ }
226
+
227
+ .spektre-dev-toggle::before {
228
+ content: '';
229
+ position: absolute;
230
+ width: 18px;
231
+ height: 18px;
232
+ background-color: white;
233
+ border-radius: 10px;
234
+ top: 3px;
235
+ left: 3px;
236
+ transition: left 0.3s ease;
237
+ }
238
+
239
+ .spektre-dev-toggle:checked::before {
240
+ left: 23px;
241
+ }
242
+
243
+ .spektre-dev-toggle:focus {
244
+ outline: none;
245
+ box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.2);
246
+ }
247
+
248
+ /* Reload Message */
249
+ .spektre-dev-modal-reload-msg {
250
+ margin: 0;
251
+ padding: 12px;
252
+ background-color: rgba(249, 115, 22, 0.15);
253
+ border: 1px solid rgba(249, 115, 22, 0.3);
254
+ border-radius: 6px;
255
+ font-size: 13px;
256
+ color: #fed7aa;
257
+ text-align: center;
258
+ transition: opacity 0.2s ease;
259
+ font-weight: 500;
260
+ }
261
+
262
+ /* Security Scan Results */
263
+ .spektre-security-scan-container {
264
+ margin-top: 16px;
265
+ padding: 16px;
266
+ background-color: rgba(239, 68, 68, 0.1);
267
+ border: 1px solid rgba(239, 68, 68, 0.3);
268
+ border-radius: 8px;
269
+ }
270
+
271
+ .spektre-security-scan-title {
272
+ font-size: 14px;
273
+ font-weight: 600;
274
+ color: #fca5a5;
275
+ margin: 0 0 12px 0;
276
+ display: flex;
277
+ align-items: center;
278
+ gap: 8px;
279
+ }
280
+
281
+ .spektre-security-scan-issues {
282
+ display: flex;
283
+ flex-direction: column;
284
+ gap: 8px;
285
+ }
286
+
287
+ .spektre-security-issue {
288
+ font-size: 13px;
289
+ color: #fed7aa;
290
+ padding: 8px;
291
+ background-color: rgba(239, 68, 68, 0.15);
292
+ border-left: 3px solid #ef4444;
293
+ border-radius: 4px;
294
+ line-height: 1.4;
295
+ }
296
+
297
+ .spektre-security-scan-clean {
298
+ font-size: 13px;
299
+ color: #86efac;
300
+ padding: 12px;
301
+ background-color: rgba(34, 197, 94, 0.15);
302
+ border: 1px solid rgba(34, 197, 94, 0.3);
303
+ border-radius: 6px;
304
+ text-align: center;
305
+ font-weight: 500;
306
+ }
307
+
308
+ /* Accessibility */
309
+ @media (prefers-reduced-motion: reduce) {
310
+ .spektre-dev-dot,
311
+ .spektre-dev-modal-overlay,
312
+ .spektre-dev-modal,
313
+ .spektre-dev-toggle,
314
+ .spektre-dev-toggle::before {
315
+ animation: none;
316
+ transition: none;
317
+ }
318
+ }
319
+
320
+ /* Mobile responsiveness */
321
+ @media (max-width: 480px) {
322
+ .spektre-dev-dot {
323
+ bottom: 16px;
324
+ right: 16px;
325
+ width: 14px;
326
+ height: 14px;
327
+ }
328
+
329
+ .spektre-dev-dot:hover {
330
+ width: 18px;
331
+ height: 18px;
332
+ bottom: 14px;
333
+ right: 14px;
334
+ }
335
+
336
+ .spektre-dev-modal {
337
+ width: 85%;
338
+ max-width: 320px;
339
+ }
340
+
341
+ .spektre-dev-modal-header h2 {
342
+ font-size: 16px;
343
+ }
344
+
345
+ .spektre-dev-modal-body {
346
+ padding: 16px;
347
+ }
348
+ }
349
+ `;
350
+ document.head.appendChild(styleSheet);
351
+ }
352
+ function runSecurityScan() {
353
+ const issues = [];
354
+ // 1. Check for hardcoded API keys/tokens
355
+ const sensitivePatterns = [
356
+ { pattern: /api[_-]?key\s*[:=]\s*['"]\S+['"]/gi, label: 'API Key' },
357
+ { pattern: /token\s*[:=]\s*['"]\S+['"]/gi, label: 'Token' },
358
+ { pattern: /password\s*[:=]\s*['"]\S+['"]/gi, label: 'Password' },
359
+ { pattern: /secret\s*[:=]\s*['"]\S+['"]/gi, label: 'Secret' },
360
+ { pattern: /bearer\s+[A-Za-z0-9\-._~+/]+=*/gi, label: 'Bearer Token' },
361
+ ];
362
+ const pageHTML = document.documentElement.outerHTML;
363
+ const scriptTags = Array.from(document.querySelectorAll('script'));
364
+ const allText = pageHTML + scriptTags.map(s => s.textContent).join('\n');
365
+ sensitivePatterns.forEach(({ pattern, label }) => {
366
+ if (pattern.test(allText)) {
367
+ issues.push(`⚠️ Found hardcoded ${label} in page code`);
368
+ }
369
+ });
370
+ // 2. Check for dangerous functions
371
+ const dangerousPatterns = [
372
+ { pattern: /eval\s*\(/gi, label: 'eval() usage' },
373
+ { pattern: /innerHTML\s*=/gi, label: 'innerHTML manipulation' },
374
+ { pattern: /dangerouslySetInnerHTML/gi, label: 'dangerouslySetInnerHTML' },
375
+ { pattern: /document\.write/gi, label: 'document.write()' },
376
+ { pattern: /setTimeout\s*\(\s*['"`].*['"`]/gi, label: 'setTimeout with string' },
377
+ ];
378
+ dangerousPatterns.forEach(({ pattern, label }) => {
379
+ if (pattern.test(allText)) {
380
+ issues.push(`⚠️ Potential security risk: ${label}`);
381
+ }
382
+ });
383
+ // 3. Check localStorage for sensitive data
384
+ try {
385
+ for (let i = 0; i < localStorage.length; i++) {
386
+ const key = localStorage.key(i);
387
+ if (key) {
388
+ const value = localStorage.getItem(key);
389
+ if (value) {
390
+ if (/token|password|secret|key|auth/i.test(key) &&
391
+ value.length > 20) {
392
+ issues.push(`⚠️ Sensitive data in localStorage: "${key}"`);
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+ catch (e) {
399
+ // localStorage access denied, skip
400
+ }
401
+ // 4. Check for missing CSP headers (via console warning detection)
402
+ const scripts = scriptTags.filter(s => s.src && !s.src.includes('spektre'));
403
+ if (scripts.length > 10) {
404
+ issues.push(`⚠️ Many external scripts loaded (${scripts.length})`);
405
+ }
406
+ return {
407
+ hasIssues: issues.length > 0,
408
+ issues,
409
+ };
410
+ }
411
+ function initializeDevUI() {
412
+ // Inject styles first
413
+ injectDevUIStyles();
414
+ // Check if Spektre is enabled in localStorage (default to true)
415
+ const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY);
416
+ const spektreEnabled = isEnabled === null ? true : isEnabled === 'true';
417
+ // If disabled, prevent core Spektre from initializing
418
+ if (!spektreEnabled) {
419
+ window.__spektreDevDisabled = true;
420
+ }
421
+ // Create and inject the orange dot
422
+ createDevDot();
423
+ // Run security scan after a short delay to ensure DOM is ready
424
+ setTimeout(() => {
425
+ const scanResult = runSecurityScan();
426
+ if (scanResult.hasIssues) {
427
+ // Update dot to warning state and auto-open modal
428
+ const dot = document.getElementById('spektre-dev-dot');
429
+ if (dot) {
430
+ dot.classList.add('warning');
431
+ }
432
+ openDevModal(scanResult);
433
+ }
434
+ }, 500);
435
+ }
436
+ function createDevDot() {
437
+ const dot = document.createElement('div');
438
+ dot.id = 'spektre-dev-dot';
439
+ dot.className = 'spektre-dev-dot';
440
+ dot.setAttribute('aria-label', 'Spektre development environment controls');
441
+ dot.addEventListener('click', () => {
442
+ openDevModal();
443
+ });
444
+ document.body.appendChild(dot);
445
+ }
446
+ function openDevModal(scanResult) {
447
+ // Check if modal already exists
448
+ if (document.getElementById('spektre-dev-modal')) {
449
+ return;
450
+ }
451
+ const isEnabled = localStorage.getItem(DEV_UI_STORAGE_KEY) !== 'false';
452
+ const modal = document.createElement('div');
453
+ modal.id = 'spektre-dev-modal';
454
+ modal.className = 'spektre-dev-modal-overlay';
455
+ const modalContent = document.createElement('div');
456
+ modalContent.className = 'spektre-dev-modal';
457
+ const header = document.createElement('div');
458
+ header.className = 'spektre-dev-modal-header';
459
+ header.innerHTML = '<h2>Spektre Development Mode</h2>';
460
+ const closeButton = document.createElement('button');
461
+ closeButton.className = 'spektre-dev-modal-close';
462
+ closeButton.innerHTML = '✕';
463
+ closeButton.setAttribute('aria-label', 'Close modal');
464
+ closeButton.addEventListener('click', () => {
465
+ modal.remove();
466
+ });
467
+ header.appendChild(closeButton);
468
+ const body = document.createElement('div');
469
+ body.className = 'spektre-dev-modal-body';
470
+ const infoText = document.createElement('p');
471
+ infoText.className = 'spektre-dev-modal-info';
472
+ infoText.textContent = 'You are in a development environment. Spektre is currently:';
473
+ const statusBadge = document.createElement('div');
474
+ statusBadge.className = `spektre-dev-modal-status ${isEnabled ? 'enabled' : 'disabled'}`;
475
+ statusBadge.textContent = isEnabled ? '● Enabled' : '● Disabled';
476
+ const toggleContainer = document.createElement('div');
477
+ toggleContainer.className = 'spektre-dev-modal-toggle-container';
478
+ const toggleLabel = document.createElement('label');
479
+ toggleLabel.className = 'spektre-dev-toggle-label';
480
+ const toggleSwitch = document.createElement('input');
481
+ toggleSwitch.type = 'checkbox';
482
+ toggleSwitch.className = 'spektre-dev-toggle';
483
+ toggleSwitch.checked = isEnabled;
484
+ toggleSwitch.setAttribute('aria-label', 'Toggle Spektre');
485
+ toggleSwitch.addEventListener('change', (e) => {
486
+ const enabled = e.target.checked;
487
+ localStorage.setItem(DEV_UI_STORAGE_KEY, String(enabled));
488
+ // Update status badge
489
+ statusBadge.className = `spektre-dev-modal-status ${enabled ? 'enabled' : 'disabled'}`;
490
+ statusBadge.textContent = enabled ? '● Enabled' : '● Disabled';
491
+ // Update dot visual
492
+ const dot = document.getElementById('spektre-dev-dot');
493
+ if (dot) {
494
+ dot.classList.toggle('disabled', !enabled);
495
+ }
496
+ // Show reload message
497
+ const reloadMsg = document.querySelector('.spektre-dev-modal-reload-msg');
498
+ if (reloadMsg) {
499
+ reloadMsg.textContent = 'Reload the page for changes to take effect';
500
+ reloadMsg.style.opacity = '1';
501
+ }
502
+ });
503
+ toggleLabel.appendChild(toggleSwitch);
504
+ toggleLabel.appendChild(document.createTextNode('Enable Spektre'));
505
+ toggleContainer.appendChild(toggleLabel);
506
+ const reloadMessage = document.createElement('p');
507
+ reloadMessage.className = 'spektre-dev-modal-reload-msg';
508
+ reloadMessage.style.opacity = '0';
509
+ body.appendChild(infoText);
510
+ body.appendChild(statusBadge);
511
+ body.appendChild(toggleContainer);
512
+ body.appendChild(reloadMessage);
513
+ // Add security scan results if available
514
+ if (scanResult) {
515
+ const scanContainer = document.createElement('div');
516
+ scanContainer.className = 'spektre-security-scan-container';
517
+ const scanTitle = document.createElement('div');
518
+ scanTitle.className = 'spektre-security-scan-title';
519
+ scanTitle.innerHTML = '🔒 Security Check';
520
+ scanContainer.appendChild(scanTitle);
521
+ if (scanResult.hasIssues) {
522
+ const issuesContainer = document.createElement('div');
523
+ issuesContainer.className = 'spektre-security-scan-issues';
524
+ scanResult.issues.forEach(issue => {
525
+ const issueElement = document.createElement('div');
526
+ issueElement.className = 'spektre-security-issue';
527
+ issueElement.textContent = issue;
528
+ issuesContainer.appendChild(issueElement);
529
+ });
530
+ scanContainer.appendChild(issuesContainer);
531
+ }
532
+ else {
533
+ const cleanMessage = document.createElement('div');
534
+ cleanMessage.className = 'spektre-security-scan-clean';
535
+ cleanMessage.textContent = '✓ No security issues detected';
536
+ scanContainer.appendChild(cleanMessage);
537
+ }
538
+ body.appendChild(scanContainer);
539
+ }
540
+ modalContent.appendChild(header);
541
+ modalContent.appendChild(body);
542
+ modal.appendChild(modalContent);
543
+ // Close on overlay click
544
+ modal.addEventListener('click', (e) => {
545
+ if (e.target === modal) {
546
+ modal.remove();
547
+ }
548
+ });
549
+ // Close on escape key
550
+ document.addEventListener('keydown', (e) => {
551
+ if (e.key === 'Escape' && document.getElementById('spektre-dev-modal')) {
552
+ modal.remove();
553
+ }
554
+ }, { once: true });
555
+ document.body.appendChild(modal);
556
+ }
557
+
5
558
  const SpektreContext = React.createContext(null);
6
559
  SpektreContext.displayName = 'SpektreContext';
7
560
 
@@ -18,6 +571,16 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
18
571
  sessionId: null,
19
572
  });
20
573
  React.useEffect(() => {
574
+ // Check if Spektre is disabled in dev mode
575
+ if (window.__spektreDevDisabled) {
576
+ setState({
577
+ isVerified: true,
578
+ isLoading: false,
579
+ error: null,
580
+ sessionId: 'dev-disabled',
581
+ });
582
+ return;
583
+ }
21
584
  // Set tampering detection marker
22
585
  sessionStorage.setItem('spektre_js_enabled', 'true');
23
586
  sessionStorage.setItem('spektre_init_time', Date.now().toString());
@@ -432,6 +995,11 @@ const useProtectedFetch = () => {
432
995
  return protectedFetch;
433
996
  };
434
997
 
998
+ // Check if we're in an iframe (development environment) and initialize dev UI
999
+ if (typeof window !== 'undefined' && window.self !== window.top) {
1000
+ initializeDevUI();
1001
+ }
1002
+
435
1003
  exports.SecurityGate = SecurityGate;
436
1004
  exports.SpektreContext = SpektreContext;
437
1005
  exports.SpektreProvider = SpektreProvider;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spektre/veil",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "Security and monitoring wrapper for React apps built with AI tools",
6
6
  "main": "dist/index.js",