@spektre/veil 0.1.0 → 0.1.2

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,5 +1,2 @@
1
1
  export { useSpektre } from './useSpektre';
2
2
  export { useProtectedFetch } from './useProtectedFetch';
3
- export { useVeil } from './useVeil';
4
- export type { UseSpektreReturn } from './useSpektre';
5
- export type { ProtectedFetch } from './useProtectedFetch';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- export { default as VeilProvider } from './components/VeilProvider';
2
- export { useVeil, useSpektre, useProtectedFetch } from './hooks';
3
- export { SpektreContext } from './SpektreContext';
4
- export { SpektreProvider } from './SpektreProvider';
5
1
  export { SecurityGate } from './SecurityGate';
6
- export type { SpektreConfig, SpektreState, ProtectionState, MonitoringState, BlockedRequest, BlockedAttack, TamperingDetails, SecurityGateProps, VeilConfig, VeilContextType, } from './types';
7
- export type { UseSpektreReturn, ProtectedFetch } from './hooks';
2
+ export { SpektreProvider } from './SpektreProvider';
3
+ export { SpektreContext } from './SpektreContext';
4
+ export { useSpektre } from './hooks/useSpektre';
5
+ export { useProtectedFetch } from './hooks/useProtectedFetch';
6
+ export type { SecurityGateProps, SpektreConfig, SpektreState, ProtectionState, MonitoringState, BlockedRequest, BlockedAttack, TamperingDetails, VeilConfig, VeilState, VeilProps, VeilContextType, } from './types';
package/dist/index.esm.js CHANGED
@@ -1,81 +1,8 @@
1
- import React, { createContext, useMemo, useCallback, useContext, useState, useEffect } from 'react';
2
-
3
- const VeilContext = createContext(undefined);
4
- const VeilProvider = ({ config, children }) => {
5
- const isMonitoring = useMemo(() => config.enableMonitoring ?? false, [config.enableMonitoring]);
6
- const logEvent = useCallback((event, data) => {
7
- if (isMonitoring) {
8
- console.log('[Veil]', event, data);
9
- }
10
- }, [isMonitoring]);
11
- const value = useMemo(() => ({
12
- config,
13
- isMonitoring,
14
- logEvent,
15
- }), [config, isMonitoring, logEvent]);
16
- return React.createElement(VeilContext.Provider, { value: value }, children);
17
- };
1
+ import React, { createContext, useState, useEffect, useContext } from 'react';
18
2
 
19
3
  const SpektreContext = createContext(null);
20
4
  SpektreContext.displayName = 'SpektreContext';
21
5
 
22
- const useSpektre = () => {
23
- const context = useContext(SpektreContext);
24
- if (!context) {
25
- throw new Error('useSpektre must be used within a SecurityGate component');
26
- }
27
- const runScan = async () => {
28
- if (typeof window.securityScan === 'function') {
29
- await window.securityScan();
30
- }
31
- };
32
- const getTelemetry = () => {
33
- if (typeof window.getSecurityTelemetry === 'function') {
34
- return window.getSecurityTelemetry();
35
- }
36
- return context.monitoring;
37
- };
38
- const getProtectionStats = () => {
39
- if (typeof window.getProtectionStats === 'function') {
40
- return window.getProtectionStats();
41
- }
42
- return context.protection;
43
- };
44
- return {
45
- isVerified: context.isVerified,
46
- sessionId: context.sessionId,
47
- protectionEnabled: context.protection?.enabled || false,
48
- blockedRequests: context.protection?.blockedRequests || [],
49
- totalBlocked: context.protection?.totalBlocked || 0,
50
- secretExposures: context.monitoring?.secretExposures || 0,
51
- scriptProfiles: context.monitoring?.scriptProfiles || 0,
52
- supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
53
- sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
54
- runScan,
55
- getTelemetry,
56
- getProtectionStats,
57
- };
58
- };
59
-
60
- const useProtectedFetch = () => {
61
- const { isVerified } = useSpektre();
62
- const protectedFetch = async (url, options) => {
63
- if (!isVerified) {
64
- throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
65
- }
66
- return fetch(url, options);
67
- };
68
- return protectedFetch;
69
- };
70
-
71
- const useVeil = () => {
72
- const context = useContext(VeilContext);
73
- if (context === undefined) {
74
- throw new Error('useVeil must be used within a VeilProvider');
75
- }
76
- return context;
77
- };
78
-
79
6
  const SpektreProvider = ({ value, children }) => {
80
7
  return React.createElement(SpektreContext.Provider, { value: value }, children);
81
8
  };
@@ -89,6 +16,9 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
89
16
  sessionId: null,
90
17
  });
91
18
  useEffect(() => {
19
+ // Set tampering detection marker
20
+ sessionStorage.setItem('spektre_js_enabled', 'true');
21
+ sessionStorage.setItem('spektre_init_time', Date.now().toString());
92
22
  const scriptUrl = `${SUPABASE_BASE_URL}/functions/v1/scanner_client`;
93
23
  const script = document.createElement('script');
94
24
  script.src = `${scriptUrl}?apiKey=${encodeURIComponent(apiKey)}`;
@@ -118,7 +48,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
118
48
  script.setAttribute('data-session', String(config.modules.sessionProtection));
119
49
  }
120
50
  if (config.modules.activeProtection !== undefined) {
121
- script.setAttribute('data-active', String(config.modules.activeProtection));
51
+ script.setAttribute('data-protection', String(config.modules.activeProtection));
122
52
  }
123
53
  }
124
54
  script.onload = () => {
@@ -141,6 +71,8 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
141
71
  protection,
142
72
  monitoring,
143
73
  });
74
+ // Start tampering detection after successful load
75
+ startTamperingDetection(config);
144
76
  }
145
77
  catch (err) {
146
78
  setState({
@@ -169,6 +101,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
169
101
  if (script.parentNode) {
170
102
  script.parentNode.removeChild(script);
171
103
  }
104
+ stopTamperingDetection();
172
105
  };
173
106
  }, [apiKey, config]);
174
107
  const handleRetry = () => {
@@ -185,10 +118,12 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
185
118
  return React.createElement(React.Fragment, null, loadingComponent);
186
119
  }
187
120
  return (React.createElement("div", { style: styles.container },
121
+ React.createElement("div", { style: styles.backgroundGlow },
122
+ React.createElement("div", { style: styles.orangeGlowLeft }),
123
+ React.createElement("div", { style: styles.orangeGlowRight })),
188
124
  React.createElement("div", { style: styles.content },
189
- React.createElement("div", { style: styles.icon },
190
- React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
191
- React.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }))),
125
+ React.createElement("div", { style: styles.logoContainer },
126
+ React.createElement("img", { src: "/image.png", alt: "Spektre", style: styles.logo })),
192
127
  React.createElement("h2", { style: styles.title }, "Initializing Security"),
193
128
  React.createElement("p", { style: styles.message }, "Please wait while we verify your application..."),
194
129
  React.createElement("div", { style: styles.spinner }))));
@@ -198,69 +133,256 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
198
133
  return React.createElement(React.Fragment, null, fallback);
199
134
  }
200
135
  return (React.createElement("div", { style: styles.container },
136
+ React.createElement("div", { style: styles.backgroundGlow },
137
+ React.createElement("div", { style: styles.orangeGlowLeft }),
138
+ React.createElement("div", { style: styles.orangeGlowRight })),
201
139
  React.createElement("div", { style: styles.content },
202
- React.createElement("div", { style: { ...styles.icon, color: '#ef4444' } },
203
- React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
204
- React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
205
- React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
206
- React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" }))),
207
- React.createElement("h2", { style: styles.title }, "Security Verification Failed"),
208
- React.createElement("p", { style: styles.message }, state.error || 'Unable to verify application security'),
209
- React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry"))));
140
+ React.createElement("div", { style: styles.logoContainer },
141
+ React.createElement("img", { src: "/image.png", alt: "Spektre", style: styles.logo })),
142
+ React.createElement("h2", { style: styles.errorTitle }, "Security Protection Required"),
143
+ React.createElement("p", { style: styles.errorMessage }, "This application requires Spektre security protection to run safely."),
144
+ React.createElement("p", { style: styles.errorDetails }, state.error || 'Unable to verify application security'),
145
+ React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry Loading"))));
210
146
  }
211
147
  return React.createElement(SpektreProvider, { value: state }, children);
212
148
  };
149
+ // Tampering detection
150
+ let tamperingInterval = null;
151
+ let fetchIntegrityHash = null;
152
+ function startTamperingDetection(config) {
153
+ // Calculate integrity hash of fetch function
154
+ if (typeof window.fetch === 'function') {
155
+ fetchIntegrityHash = hashCode(window.fetch.toString());
156
+ }
157
+ tamperingInterval = window.setInterval(() => {
158
+ // Check 1: Verify JavaScript marker is still present
159
+ const jsEnabled = sessionStorage.getItem('spektre_js_enabled');
160
+ if (!jsEnabled) {
161
+ handleTampering('JavaScript marker removed', config);
162
+ return;
163
+ }
164
+ // Check 2: Verify Spektre script is still in DOM
165
+ const scriptExists = document.querySelector('script[src*="scanner_client"]');
166
+ if (!scriptExists) {
167
+ handleTampering('Security script removed from page', config);
168
+ return;
169
+ }
170
+ // Check 3: Verify fetch function hasn't been tampered with
171
+ if (typeof window.fetch === 'function') {
172
+ const currentHash = hashCode(window.fetch.toString());
173
+ if (fetchIntegrityHash && currentHash !== fetchIntegrityHash) {
174
+ // Fetch function was modified
175
+ const fetchCode = window.fetch.toString();
176
+ // Check if it still has Spektre protection
177
+ if (!fetchCode.includes('Spektre') && !fetchCode.includes('PROTECTION')) {
178
+ handleTampering('Security protection has been disabled', config);
179
+ return;
180
+ }
181
+ }
182
+ }
183
+ else {
184
+ handleTampering('Fetch function removed', config);
185
+ return;
186
+ }
187
+ // Check 4: Verify protection stats function exists
188
+ if (typeof window.getProtectionStats !== 'function') {
189
+ handleTampering('Security monitoring disabled', config);
190
+ return;
191
+ }
192
+ }, 2000); // Check every 2 seconds
193
+ }
194
+ function stopTamperingDetection() {
195
+ if (tamperingInterval) {
196
+ clearInterval(tamperingInterval);
197
+ tamperingInterval = null;
198
+ }
199
+ }
200
+ function handleTampering(reason, config) {
201
+ console.error('[Spektre SecurityGate] TAMPERING DETECTED:', reason);
202
+ // Stop checking to prevent infinite loops
203
+ stopTamperingDetection();
204
+ // Call callback if provided
205
+ if (config?.onTamperingDetected) {
206
+ config.onTamperingDetected(reason);
207
+ }
208
+ // Lock down the application
209
+ const root = document.getElementById('root');
210
+ if (root) {
211
+ root.innerHTML = '';
212
+ }
213
+ document.body.innerHTML = `
214
+ <div style="
215
+ position: fixed;
216
+ top: 0;
217
+ left: 0;
218
+ width: 100%;
219
+ height: 100%;
220
+ background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
221
+ color: white;
222
+ display: flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ flex-direction: column;
226
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
227
+ z-index: 999999;
228
+ ">
229
+ <div style="max-width: 500px; text-align: center; padding: 40px;">
230
+ <div style="font-size: 72px; margin-bottom: 24px;">⛔</div>
231
+ <h1 style="font-size: 28px; font-weight: 600; margin-bottom: 16px;">
232
+ Security Violation Detected
233
+ </h1>
234
+ <p style="font-size: 16px; line-height: 1.6; opacity: 0.9; margin-bottom: 24px;">
235
+ This application has been locked due to security tampering.
236
+ </p>
237
+ <div style="
238
+ background: rgba(255, 255, 255, 0.1);
239
+ border-radius: 8px;
240
+ padding: 16px;
241
+ margin-bottom: 24px;
242
+ font-size: 14px;
243
+ font-family: monospace;
244
+ ">
245
+ ${reason}
246
+ </div>
247
+ <button onclick="location.reload()" style="
248
+ padding: 12px 32px;
249
+ font-size: 16px;
250
+ font-weight: 500;
251
+ background: white;
252
+ color: #dc2626;
253
+ border: none;
254
+ border-radius: 8px;
255
+ cursor: pointer;
256
+ transition: transform 0.2s;
257
+ " onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
258
+ Reload Application
259
+ </button>
260
+ </div>
261
+ </div>
262
+ `;
263
+ }
264
+ // Simple hash function for integrity checking
265
+ function hashCode(str) {
266
+ let hash = 0;
267
+ for (let i = 0; i < str.length; i++) {
268
+ const char = str.charCodeAt(i);
269
+ hash = ((hash << 5) - hash) + char;
270
+ hash = hash & hash;
271
+ }
272
+ return hash.toString(36);
273
+ }
213
274
  const styles = {
214
275
  container: {
215
276
  display: 'flex',
216
277
  alignItems: 'center',
217
278
  justifyContent: 'center',
218
279
  minHeight: '100vh',
219
- backgroundColor: '#f9fafb',
280
+ background: '#000000',
220
281
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
282
+ position: 'relative',
283
+ overflow: 'hidden',
284
+ },
285
+ backgroundGlow: {
286
+ position: 'absolute',
287
+ inset: 0,
288
+ pointerEvents: 'none',
289
+ },
290
+ orangeGlowLeft: {
291
+ position: 'absolute',
292
+ top: 0,
293
+ right: 0,
294
+ width: '384px',
295
+ height: '100%',
296
+ background: 'linear-gradient(to left, rgba(249, 115, 22, 0.4), rgba(239, 68, 68, 0.4), transparent)',
297
+ filter: 'blur(96px)',
298
+ transform: 'translateX(30%)',
299
+ },
300
+ orangeGlowRight: {
301
+ position: 'absolute',
302
+ top: '50%',
303
+ right: 0,
304
+ width: '384px',
305
+ height: '384px',
306
+ background: 'linear-gradient(to left, rgba(249, 115, 22, 0.3), transparent)',
307
+ filter: 'blur(96px)',
308
+ transform: 'translateY(-50%)',
221
309
  },
222
310
  content: {
223
311
  textAlign: 'center',
224
312
  padding: '2rem',
225
- maxWidth: '400px',
313
+ maxWidth: '500px',
314
+ background: 'rgba(0, 0, 0, 0.5)',
315
+ border: '1px solid rgba(71, 85, 105, 0.5)',
316
+ borderRadius: '16px',
317
+ boxShadow: '0 20px 60px rgba(0, 0, 0, 0.5)',
318
+ backdropFilter: 'blur(16px)',
319
+ position: 'relative',
320
+ zIndex: 10,
226
321
  },
227
- icon: {
228
- color: '#3b82f6',
229
- marginBottom: '1rem',
322
+ logoContainer: {
323
+ marginBottom: '2rem',
230
324
  display: 'flex',
231
325
  justifyContent: 'center',
232
326
  },
327
+ logo: {
328
+ width: '56px',
329
+ height: '56px',
330
+ objectFit: 'contain',
331
+ },
233
332
  title: {
234
- fontSize: '1.5rem',
333
+ fontSize: '1.75rem',
235
334
  fontWeight: '600',
236
- color: '#111827',
237
- marginBottom: '0.5rem',
335
+ color: '#ffffff',
336
+ marginBottom: '0.75rem',
238
337
  },
239
338
  message: {
240
339
  fontSize: '1rem',
241
- color: '#6b7280',
340
+ color: '#cbd5e1',
341
+ marginBottom: '1.5rem',
342
+ lineHeight: '1.6',
343
+ },
344
+ errorTitle: {
345
+ fontSize: '1.75rem',
346
+ fontWeight: '600',
347
+ color: '#ffffff',
348
+ marginBottom: '0.75rem',
349
+ },
350
+ errorMessage: {
351
+ fontSize: '1rem',
352
+ color: '#cbd5e1',
353
+ marginBottom: '1rem',
354
+ lineHeight: '1.6',
355
+ },
356
+ errorDetails: {
357
+ fontSize: '0.875rem',
358
+ color: '#fca5a5',
242
359
  marginBottom: '1.5rem',
243
- lineHeight: '1.5',
360
+ padding: '0.75rem',
361
+ background: 'rgba(239, 68, 68, 0.1)',
362
+ border: '1px solid rgba(239, 68, 68, 0.3)',
363
+ borderRadius: '8px',
364
+ fontFamily: 'monospace',
244
365
  },
245
366
  spinner: {
246
- width: '32px',
247
- height: '32px',
248
- border: '3px solid #e5e7eb',
249
- borderTopColor: '#3b82f6',
367
+ width: '40px',
368
+ height: '40px',
369
+ border: '4px solid rgba(71, 85, 105, 0.3)',
370
+ borderTopColor: '#f97316',
250
371
  borderRadius: '50%',
251
372
  margin: '0 auto',
252
373
  animation: 'spin 1s linear infinite',
253
374
  },
254
375
  button: {
255
- backgroundColor: '#3b82f6',
376
+ backgroundColor: 'rgba(249, 115, 22, 0.6)',
256
377
  color: 'white',
257
- border: 'none',
258
- borderRadius: '0.5rem',
259
- padding: '0.75rem 1.5rem',
378
+ border: '1px solid rgba(249, 115, 22, 0.6)',
379
+ borderRadius: '9999px',
380
+ padding: '0.875rem 2rem',
260
381
  fontSize: '1rem',
261
- fontWeight: '500',
382
+ fontWeight: '600',
262
383
  cursor: 'pointer',
263
- transition: 'background-color 0.2s',
384
+ transition: 'all 0.2s',
385
+ boxShadow: '0 4px 12px rgba(249, 115, 22, 0.3)',
264
386
  },
265
387
  };
266
388
  const styleSheet = document.createElement('style');
@@ -273,5 +395,54 @@ styleSheet.textContent = `
273
395
  `;
274
396
  document.head.appendChild(styleSheet);
275
397
 
276
- export { SecurityGate, SpektreContext, SpektreProvider, VeilProvider, useProtectedFetch, useSpektre, useVeil };
398
+ const useSpektre = () => {
399
+ const context = useContext(SpektreContext);
400
+ if (!context) {
401
+ throw new Error('useSpektre must be used within a SecurityGate component');
402
+ }
403
+ const runScan = async () => {
404
+ if (typeof window.securityScan === 'function') {
405
+ await window.securityScan();
406
+ }
407
+ };
408
+ const getTelemetry = () => {
409
+ if (typeof window.getSecurityTelemetry === 'function') {
410
+ return window.getSecurityTelemetry();
411
+ }
412
+ return context.monitoring;
413
+ };
414
+ const getProtectionStats = () => {
415
+ if (typeof window.getProtectionStats === 'function') {
416
+ return window.getProtectionStats();
417
+ }
418
+ return context.protection;
419
+ };
420
+ return {
421
+ isVerified: context.isVerified,
422
+ sessionId: context.sessionId,
423
+ protectionEnabled: context.protection?.enabled || false,
424
+ blockedRequests: context.protection?.blockedRequests || [],
425
+ totalBlocked: context.protection?.totalBlocked || 0,
426
+ secretExposures: context.monitoring?.secretExposures || 0,
427
+ scriptProfiles: context.monitoring?.scriptProfiles || 0,
428
+ supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
429
+ sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
430
+ runScan,
431
+ getTelemetry,
432
+ getProtectionStats,
433
+ };
434
+ };
435
+
436
+ const useProtectedFetch = () => {
437
+ const { isVerified } = useSpektre();
438
+ const protectedFetch = async (url, options) => {
439
+ if (!isVerified) {
440
+ throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
441
+ }
442
+ return fetch(url, options);
443
+ };
444
+ return protectedFetch;
445
+ };
446
+
447
+ export { SecurityGate, SpektreContext, SpektreProvider, useProtectedFetch, useSpektre };
277
448
  //# 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,82 +2,9 @@
2
2
 
3
3
  var React = require('react');
4
4
 
5
- const VeilContext = React.createContext(undefined);
6
- const VeilProvider = ({ config, children }) => {
7
- const isMonitoring = React.useMemo(() => config.enableMonitoring ?? false, [config.enableMonitoring]);
8
- const logEvent = React.useCallback((event, data) => {
9
- if (isMonitoring) {
10
- console.log('[Veil]', event, data);
11
- }
12
- }, [isMonitoring]);
13
- const value = React.useMemo(() => ({
14
- config,
15
- isMonitoring,
16
- logEvent,
17
- }), [config, isMonitoring, logEvent]);
18
- return React.createElement(VeilContext.Provider, { value: value }, children);
19
- };
20
-
21
5
  const SpektreContext = React.createContext(null);
22
6
  SpektreContext.displayName = 'SpektreContext';
23
7
 
24
- const useSpektre = () => {
25
- const context = React.useContext(SpektreContext);
26
- if (!context) {
27
- throw new Error('useSpektre must be used within a SecurityGate component');
28
- }
29
- const runScan = async () => {
30
- if (typeof window.securityScan === 'function') {
31
- await window.securityScan();
32
- }
33
- };
34
- const getTelemetry = () => {
35
- if (typeof window.getSecurityTelemetry === 'function') {
36
- return window.getSecurityTelemetry();
37
- }
38
- return context.monitoring;
39
- };
40
- const getProtectionStats = () => {
41
- if (typeof window.getProtectionStats === 'function') {
42
- return window.getProtectionStats();
43
- }
44
- return context.protection;
45
- };
46
- return {
47
- isVerified: context.isVerified,
48
- sessionId: context.sessionId,
49
- protectionEnabled: context.protection?.enabled || false,
50
- blockedRequests: context.protection?.blockedRequests || [],
51
- totalBlocked: context.protection?.totalBlocked || 0,
52
- secretExposures: context.monitoring?.secretExposures || 0,
53
- scriptProfiles: context.monitoring?.scriptProfiles || 0,
54
- supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
55
- sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
56
- runScan,
57
- getTelemetry,
58
- getProtectionStats,
59
- };
60
- };
61
-
62
- const useProtectedFetch = () => {
63
- const { isVerified } = useSpektre();
64
- const protectedFetch = async (url, options) => {
65
- if (!isVerified) {
66
- throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
67
- }
68
- return fetch(url, options);
69
- };
70
- return protectedFetch;
71
- };
72
-
73
- const useVeil = () => {
74
- const context = React.useContext(VeilContext);
75
- if (context === undefined) {
76
- throw new Error('useVeil must be used within a VeilProvider');
77
- }
78
- return context;
79
- };
80
-
81
8
  const SpektreProvider = ({ value, children }) => {
82
9
  return React.createElement(SpektreContext.Provider, { value: value }, children);
83
10
  };
@@ -91,6 +18,9 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
91
18
  sessionId: null,
92
19
  });
93
20
  React.useEffect(() => {
21
+ // Set tampering detection marker
22
+ sessionStorage.setItem('spektre_js_enabled', 'true');
23
+ sessionStorage.setItem('spektre_init_time', Date.now().toString());
94
24
  const scriptUrl = `${SUPABASE_BASE_URL}/functions/v1/scanner_client`;
95
25
  const script = document.createElement('script');
96
26
  script.src = `${scriptUrl}?apiKey=${encodeURIComponent(apiKey)}`;
@@ -120,7 +50,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
120
50
  script.setAttribute('data-session', String(config.modules.sessionProtection));
121
51
  }
122
52
  if (config.modules.activeProtection !== undefined) {
123
- script.setAttribute('data-active', String(config.modules.activeProtection));
53
+ script.setAttribute('data-protection', String(config.modules.activeProtection));
124
54
  }
125
55
  }
126
56
  script.onload = () => {
@@ -143,6 +73,8 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
143
73
  protection,
144
74
  monitoring,
145
75
  });
76
+ // Start tampering detection after successful load
77
+ startTamperingDetection(config);
146
78
  }
147
79
  catch (err) {
148
80
  setState({
@@ -171,6 +103,7 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
171
103
  if (script.parentNode) {
172
104
  script.parentNode.removeChild(script);
173
105
  }
106
+ stopTamperingDetection();
174
107
  };
175
108
  }, [apiKey, config]);
176
109
  const handleRetry = () => {
@@ -187,10 +120,12 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
187
120
  return React.createElement(React.Fragment, null, loadingComponent);
188
121
  }
189
122
  return (React.createElement("div", { style: styles.container },
123
+ React.createElement("div", { style: styles.backgroundGlow },
124
+ React.createElement("div", { style: styles.orangeGlowLeft }),
125
+ React.createElement("div", { style: styles.orangeGlowRight })),
190
126
  React.createElement("div", { style: styles.content },
191
- React.createElement("div", { style: styles.icon },
192
- React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
193
- React.createElement("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }))),
127
+ React.createElement("div", { style: styles.logoContainer },
128
+ React.createElement("img", { src: "/image.png", alt: "Spektre", style: styles.logo })),
194
129
  React.createElement("h2", { style: styles.title }, "Initializing Security"),
195
130
  React.createElement("p", { style: styles.message }, "Please wait while we verify your application..."),
196
131
  React.createElement("div", { style: styles.spinner }))));
@@ -200,69 +135,256 @@ const SecurityGate = ({ apiKey, children, config, fallback, loadingComponent, })
200
135
  return React.createElement(React.Fragment, null, fallback);
201
136
  }
202
137
  return (React.createElement("div", { style: styles.container },
138
+ React.createElement("div", { style: styles.backgroundGlow },
139
+ React.createElement("div", { style: styles.orangeGlowLeft }),
140
+ React.createElement("div", { style: styles.orangeGlowRight })),
203
141
  React.createElement("div", { style: styles.content },
204
- React.createElement("div", { style: { ...styles.icon, color: '#ef4444' } },
205
- React.createElement("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
206
- React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
207
- React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
208
- React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" }))),
209
- React.createElement("h2", { style: styles.title }, "Security Verification Failed"),
210
- React.createElement("p", { style: styles.message }, state.error || 'Unable to verify application security'),
211
- React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry"))));
142
+ React.createElement("div", { style: styles.logoContainer },
143
+ React.createElement("img", { src: "/image.png", alt: "Spektre", style: styles.logo })),
144
+ React.createElement("h2", { style: styles.errorTitle }, "Security Protection Required"),
145
+ React.createElement("p", { style: styles.errorMessage }, "This application requires Spektre security protection to run safely."),
146
+ React.createElement("p", { style: styles.errorDetails }, state.error || 'Unable to verify application security'),
147
+ React.createElement("button", { onClick: handleRetry, style: styles.button }, "Retry Loading"))));
212
148
  }
213
149
  return React.createElement(SpektreProvider, { value: state }, children);
214
150
  };
151
+ // Tampering detection
152
+ let tamperingInterval = null;
153
+ let fetchIntegrityHash = null;
154
+ function startTamperingDetection(config) {
155
+ // Calculate integrity hash of fetch function
156
+ if (typeof window.fetch === 'function') {
157
+ fetchIntegrityHash = hashCode(window.fetch.toString());
158
+ }
159
+ tamperingInterval = window.setInterval(() => {
160
+ // Check 1: Verify JavaScript marker is still present
161
+ const jsEnabled = sessionStorage.getItem('spektre_js_enabled');
162
+ if (!jsEnabled) {
163
+ handleTampering('JavaScript marker removed', config);
164
+ return;
165
+ }
166
+ // Check 2: Verify Spektre script is still in DOM
167
+ const scriptExists = document.querySelector('script[src*="scanner_client"]');
168
+ if (!scriptExists) {
169
+ handleTampering('Security script removed from page', config);
170
+ return;
171
+ }
172
+ // Check 3: Verify fetch function hasn't been tampered with
173
+ if (typeof window.fetch === 'function') {
174
+ const currentHash = hashCode(window.fetch.toString());
175
+ if (fetchIntegrityHash && currentHash !== fetchIntegrityHash) {
176
+ // Fetch function was modified
177
+ const fetchCode = window.fetch.toString();
178
+ // Check if it still has Spektre protection
179
+ if (!fetchCode.includes('Spektre') && !fetchCode.includes('PROTECTION')) {
180
+ handleTampering('Security protection has been disabled', config);
181
+ return;
182
+ }
183
+ }
184
+ }
185
+ else {
186
+ handleTampering('Fetch function removed', config);
187
+ return;
188
+ }
189
+ // Check 4: Verify protection stats function exists
190
+ if (typeof window.getProtectionStats !== 'function') {
191
+ handleTampering('Security monitoring disabled', config);
192
+ return;
193
+ }
194
+ }, 2000); // Check every 2 seconds
195
+ }
196
+ function stopTamperingDetection() {
197
+ if (tamperingInterval) {
198
+ clearInterval(tamperingInterval);
199
+ tamperingInterval = null;
200
+ }
201
+ }
202
+ function handleTampering(reason, config) {
203
+ console.error('[Spektre SecurityGate] TAMPERING DETECTED:', reason);
204
+ // Stop checking to prevent infinite loops
205
+ stopTamperingDetection();
206
+ // Call callback if provided
207
+ if (config?.onTamperingDetected) {
208
+ config.onTamperingDetected(reason);
209
+ }
210
+ // Lock down the application
211
+ const root = document.getElementById('root');
212
+ if (root) {
213
+ root.innerHTML = '';
214
+ }
215
+ document.body.innerHTML = `
216
+ <div style="
217
+ position: fixed;
218
+ top: 0;
219
+ left: 0;
220
+ width: 100%;
221
+ height: 100%;
222
+ background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
223
+ color: white;
224
+ display: flex;
225
+ align-items: center;
226
+ justify-content: center;
227
+ flex-direction: column;
228
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
229
+ z-index: 999999;
230
+ ">
231
+ <div style="max-width: 500px; text-align: center; padding: 40px;">
232
+ <div style="font-size: 72px; margin-bottom: 24px;">⛔</div>
233
+ <h1 style="font-size: 28px; font-weight: 600; margin-bottom: 16px;">
234
+ Security Violation Detected
235
+ </h1>
236
+ <p style="font-size: 16px; line-height: 1.6; opacity: 0.9; margin-bottom: 24px;">
237
+ This application has been locked due to security tampering.
238
+ </p>
239
+ <div style="
240
+ background: rgba(255, 255, 255, 0.1);
241
+ border-radius: 8px;
242
+ padding: 16px;
243
+ margin-bottom: 24px;
244
+ font-size: 14px;
245
+ font-family: monospace;
246
+ ">
247
+ ${reason}
248
+ </div>
249
+ <button onclick="location.reload()" style="
250
+ padding: 12px 32px;
251
+ font-size: 16px;
252
+ font-weight: 500;
253
+ background: white;
254
+ color: #dc2626;
255
+ border: none;
256
+ border-radius: 8px;
257
+ cursor: pointer;
258
+ transition: transform 0.2s;
259
+ " onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
260
+ Reload Application
261
+ </button>
262
+ </div>
263
+ </div>
264
+ `;
265
+ }
266
+ // Simple hash function for integrity checking
267
+ function hashCode(str) {
268
+ let hash = 0;
269
+ for (let i = 0; i < str.length; i++) {
270
+ const char = str.charCodeAt(i);
271
+ hash = ((hash << 5) - hash) + char;
272
+ hash = hash & hash;
273
+ }
274
+ return hash.toString(36);
275
+ }
215
276
  const styles = {
216
277
  container: {
217
278
  display: 'flex',
218
279
  alignItems: 'center',
219
280
  justifyContent: 'center',
220
281
  minHeight: '100vh',
221
- backgroundColor: '#f9fafb',
282
+ background: '#000000',
222
283
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
284
+ position: 'relative',
285
+ overflow: 'hidden',
286
+ },
287
+ backgroundGlow: {
288
+ position: 'absolute',
289
+ inset: 0,
290
+ pointerEvents: 'none',
291
+ },
292
+ orangeGlowLeft: {
293
+ position: 'absolute',
294
+ top: 0,
295
+ right: 0,
296
+ width: '384px',
297
+ height: '100%',
298
+ background: 'linear-gradient(to left, rgba(249, 115, 22, 0.4), rgba(239, 68, 68, 0.4), transparent)',
299
+ filter: 'blur(96px)',
300
+ transform: 'translateX(30%)',
301
+ },
302
+ orangeGlowRight: {
303
+ position: 'absolute',
304
+ top: '50%',
305
+ right: 0,
306
+ width: '384px',
307
+ height: '384px',
308
+ background: 'linear-gradient(to left, rgba(249, 115, 22, 0.3), transparent)',
309
+ filter: 'blur(96px)',
310
+ transform: 'translateY(-50%)',
223
311
  },
224
312
  content: {
225
313
  textAlign: 'center',
226
314
  padding: '2rem',
227
- maxWidth: '400px',
315
+ maxWidth: '500px',
316
+ background: 'rgba(0, 0, 0, 0.5)',
317
+ border: '1px solid rgba(71, 85, 105, 0.5)',
318
+ borderRadius: '16px',
319
+ boxShadow: '0 20px 60px rgba(0, 0, 0, 0.5)',
320
+ backdropFilter: 'blur(16px)',
321
+ position: 'relative',
322
+ zIndex: 10,
228
323
  },
229
- icon: {
230
- color: '#3b82f6',
231
- marginBottom: '1rem',
324
+ logoContainer: {
325
+ marginBottom: '2rem',
232
326
  display: 'flex',
233
327
  justifyContent: 'center',
234
328
  },
329
+ logo: {
330
+ width: '56px',
331
+ height: '56px',
332
+ objectFit: 'contain',
333
+ },
235
334
  title: {
236
- fontSize: '1.5rem',
335
+ fontSize: '1.75rem',
237
336
  fontWeight: '600',
238
- color: '#111827',
239
- marginBottom: '0.5rem',
337
+ color: '#ffffff',
338
+ marginBottom: '0.75rem',
240
339
  },
241
340
  message: {
242
341
  fontSize: '1rem',
243
- color: '#6b7280',
342
+ color: '#cbd5e1',
343
+ marginBottom: '1.5rem',
344
+ lineHeight: '1.6',
345
+ },
346
+ errorTitle: {
347
+ fontSize: '1.75rem',
348
+ fontWeight: '600',
349
+ color: '#ffffff',
350
+ marginBottom: '0.75rem',
351
+ },
352
+ errorMessage: {
353
+ fontSize: '1rem',
354
+ color: '#cbd5e1',
355
+ marginBottom: '1rem',
356
+ lineHeight: '1.6',
357
+ },
358
+ errorDetails: {
359
+ fontSize: '0.875rem',
360
+ color: '#fca5a5',
244
361
  marginBottom: '1.5rem',
245
- lineHeight: '1.5',
362
+ padding: '0.75rem',
363
+ background: 'rgba(239, 68, 68, 0.1)',
364
+ border: '1px solid rgba(239, 68, 68, 0.3)',
365
+ borderRadius: '8px',
366
+ fontFamily: 'monospace',
246
367
  },
247
368
  spinner: {
248
- width: '32px',
249
- height: '32px',
250
- border: '3px solid #e5e7eb',
251
- borderTopColor: '#3b82f6',
369
+ width: '40px',
370
+ height: '40px',
371
+ border: '4px solid rgba(71, 85, 105, 0.3)',
372
+ borderTopColor: '#f97316',
252
373
  borderRadius: '50%',
253
374
  margin: '0 auto',
254
375
  animation: 'spin 1s linear infinite',
255
376
  },
256
377
  button: {
257
- backgroundColor: '#3b82f6',
378
+ backgroundColor: 'rgba(249, 115, 22, 0.6)',
258
379
  color: 'white',
259
- border: 'none',
260
- borderRadius: '0.5rem',
261
- padding: '0.75rem 1.5rem',
380
+ border: '1px solid rgba(249, 115, 22, 0.6)',
381
+ borderRadius: '9999px',
382
+ padding: '0.875rem 2rem',
262
383
  fontSize: '1rem',
263
- fontWeight: '500',
384
+ fontWeight: '600',
264
385
  cursor: 'pointer',
265
- transition: 'background-color 0.2s',
386
+ transition: 'all 0.2s',
387
+ boxShadow: '0 4px 12px rgba(249, 115, 22, 0.3)',
266
388
  },
267
389
  };
268
390
  const styleSheet = document.createElement('style');
@@ -275,11 +397,58 @@ styleSheet.textContent = `
275
397
  `;
276
398
  document.head.appendChild(styleSheet);
277
399
 
400
+ const useSpektre = () => {
401
+ const context = React.useContext(SpektreContext);
402
+ if (!context) {
403
+ throw new Error('useSpektre must be used within a SecurityGate component');
404
+ }
405
+ const runScan = async () => {
406
+ if (typeof window.securityScan === 'function') {
407
+ await window.securityScan();
408
+ }
409
+ };
410
+ const getTelemetry = () => {
411
+ if (typeof window.getSecurityTelemetry === 'function') {
412
+ return window.getSecurityTelemetry();
413
+ }
414
+ return context.monitoring;
415
+ };
416
+ const getProtectionStats = () => {
417
+ if (typeof window.getProtectionStats === 'function') {
418
+ return window.getProtectionStats();
419
+ }
420
+ return context.protection;
421
+ };
422
+ return {
423
+ isVerified: context.isVerified,
424
+ sessionId: context.sessionId,
425
+ protectionEnabled: context.protection?.enabled || false,
426
+ blockedRequests: context.protection?.blockedRequests || [],
427
+ totalBlocked: context.protection?.totalBlocked || 0,
428
+ secretExposures: context.monitoring?.secretExposures || 0,
429
+ scriptProfiles: context.monitoring?.scriptProfiles || 0,
430
+ supplyChainAlerts: context.monitoring?.supplyChainAlerts || 0,
431
+ sessionAnomalies: context.monitoring?.sessionAnomalies || 0,
432
+ runScan,
433
+ getTelemetry,
434
+ getProtectionStats,
435
+ };
436
+ };
437
+
438
+ const useProtectedFetch = () => {
439
+ const { isVerified } = useSpektre();
440
+ const protectedFetch = async (url, options) => {
441
+ if (!isVerified) {
442
+ throw new Error('Security verification failed. Cannot make fetch requests until verification is complete.');
443
+ }
444
+ return fetch(url, options);
445
+ };
446
+ return protectedFetch;
447
+ };
448
+
278
449
  exports.SecurityGate = SecurityGate;
279
450
  exports.SpektreContext = SpektreContext;
280
451
  exports.SpektreProvider = SpektreProvider;
281
- exports.VeilProvider = VeilProvider;
282
452
  exports.useProtectedFetch = useProtectedFetch;
283
453
  exports.useSpektre = useSpektre;
284
- exports.useVeil = useVeil;
285
454
  //# sourceMappingURL=index.js.map
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/dist/types.d.ts CHANGED
@@ -1,8 +1,6 @@
1
- import { ReactNode } from 'react';
2
1
  export interface SpektreConfig {
3
- apiKey: string;
4
2
  endpoint?: string;
5
- environment?: 'dev' | 'staging' | 'prod';
3
+ environment?: string;
6
4
  enabledEnvironments?: string[];
7
5
  modules?: {
8
6
  performanceMonitoring?: boolean;
@@ -12,7 +10,7 @@ export interface SpektreConfig {
12
10
  sessionProtection?: boolean;
13
11
  activeProtection?: boolean;
14
12
  };
15
- onTamperingDetected?: (details: TamperingDetails) => void;
13
+ onTamperingDetected?: (reason: string) => void;
16
14
  onSecurityFailed?: (error: string) => void;
17
15
  onAttackBlocked?: (attack: BlockedAttack) => void;
18
16
  }
@@ -24,11 +22,22 @@ export interface SpektreState {
24
22
  protection?: ProtectionState;
25
23
  monitoring?: MonitoringState;
26
24
  }
25
+ export interface VeilContextType {
26
+ isVerified: boolean;
27
+ isLoading: boolean;
28
+ error: string | null;
29
+ sessionId: string | null;
30
+ protection?: ProtectionState;
31
+ monitoring?: MonitoringState;
32
+ }
27
33
  export interface ProtectionState {
28
34
  enabled: boolean;
29
35
  blockedRequests: BlockedRequest[];
30
36
  totalBlocked: number;
31
37
  }
38
+ export type VeilConfig = SpektreConfig;
39
+ export type VeilState = SpektreState;
40
+ export type VeilProps = SecurityGateProps;
32
41
  export interface MonitoringState {
33
42
  secretExposures: number;
34
43
  scriptProfiles: number;
@@ -39,15 +48,14 @@ export interface BlockedRequest {
39
48
  url: string;
40
49
  reason: string;
41
50
  timestamp: number;
42
- severity: 'low' | 'medium' | 'high' | 'critical';
51
+ severity?: 'low' | 'medium' | 'high' | 'critical';
43
52
  }
44
53
  export interface BlockedAttack {
45
- url: string;
46
- reason: string;
47
- timestamp: number;
48
- severity: 'low' | 'medium' | 'high' | 'critical';
49
54
  type: string;
55
+ severity: string;
50
56
  details: string;
57
+ timestamp: number;
58
+ url?: string;
51
59
  }
52
60
  export interface TamperingDetails {
53
61
  type: string;
@@ -56,19 +64,8 @@ export interface TamperingDetails {
56
64
  }
57
65
  export interface SecurityGateProps {
58
66
  apiKey: string;
59
- children: ReactNode;
60
- config?: Partial<SpektreConfig>;
61
- fallback?: ReactNode;
62
- loadingComponent?: ReactNode;
63
- }
64
- export interface VeilConfig {
65
- enableMonitoring?: boolean;
66
- enableSecurityChecks?: boolean;
67
- apiKey?: string;
68
- environment?: 'development' | 'production';
69
- }
70
- export interface VeilContextType {
71
- config: VeilConfig;
72
- isMonitoring: boolean;
73
- logEvent: (event: string, data?: Record<string, unknown>) => void;
67
+ children: React.ReactNode;
68
+ config?: SpektreConfig;
69
+ fallback?: React.ReactNode;
70
+ loadingComponent?: React.ReactNode;
74
71
  }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@spektre/veil",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
+ "type": "module",
4
5
  "description": "Security and monitoring wrapper for React apps built with AI tools",
5
6
  "main": "dist/index.js",
6
7
  "module": "dist/index.esm.js",
@@ -1,9 +0,0 @@
1
- import React from 'react';
2
- import type { VeilConfig, VeilContextType } from '../types';
3
- export declare const VeilContext: React.Context<VeilContextType | undefined>;
4
- interface VeilProviderProps {
5
- config: VeilConfig;
6
- children: React.ReactNode;
7
- }
8
- declare const VeilProvider: React.FC<VeilProviderProps>;
9
- export default VeilProvider;
@@ -1,2 +0,0 @@
1
- import type { VeilContextType } from '../types';
2
- export declare const useVeil: () => VeilContextType;