securenow 5.18.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +40 -239
  3. package/cli.js +455 -415
  4. package/console-instrumentation.js +136 -147
  5. package/docs/ALL-FRAMEWORKS-QUICKSTART.md +455 -1339
  6. package/docs/ARCHITECTURE.md +3 -3
  7. package/docs/AUTO-BODY-CAPTURE.md +1 -1
  8. package/docs/AUTO-SETUP.md +4 -4
  9. package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
  10. package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
  11. package/docs/CHANGELOG-NEXTJS.md +1 -1
  12. package/docs/CUSTOMER-GUIDE.md +16 -16
  13. package/docs/EASIEST-SETUP.md +5 -5
  14. package/docs/ENVIRONMENT-VARIABLES.md +652 -880
  15. package/docs/EXPRESS-BODY-CAPTURE.md +12 -13
  16. package/docs/EXPRESS-SETUP-GUIDE.md +720 -719
  17. package/docs/INDEX.md +4 -22
  18. package/docs/LOGGING-GUIDE.md +708 -701
  19. package/docs/LOGGING-QUICKSTART.md +239 -234
  20. package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
  21. package/docs/NEXTJS-GUIDE.md +14 -14
  22. package/docs/NEXTJS-QUICKSTART.md +1 -1
  23. package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
  24. package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
  25. package/docs/REDACTION-EXAMPLES.md +1 -1
  26. package/docs/REQUEST-BODY-CAPTURE.md +10 -19
  27. package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
  28. package/examples/README.md +6 -6
  29. package/examples/instrumentation-with-auto-capture.ts +1 -1
  30. package/examples/nextjs-env-example.txt +2 -2
  31. package/examples/nextjs-instrumentation.js +1 -1
  32. package/examples/nextjs-instrumentation.ts +1 -1
  33. package/examples/nextjs-with-logging-example.md +6 -6
  34. package/examples/nextjs-with-options.ts +1 -1
  35. package/examples/test-nextjs-setup.js +1 -1
  36. package/nextjs-auto-capture.js +207 -199
  37. package/nextjs-middleware.js +181 -186
  38. package/nextjs-webpack-config.js +53 -88
  39. package/nextjs-wrapper.js +158 -158
  40. package/nextjs.d.ts +1 -1
  41. package/nextjs.js +135 -190
  42. package/package.json +45 -67
  43. package/postinstall.js +6 -6
  44. package/register.d.ts +1 -1
  45. package/register.js +4 -39
  46. package/tracing.d.ts +1 -2
  47. package/tracing.js +22 -287
  48. package/web-vite.mjs +156 -239
  49. package/CONSUMING-APPS-GUIDE.md +0 -455
  50. package/NPM_README.md +0 -1933
  51. package/SKILL-API.md +0 -600
  52. package/SKILL-CLI.md +0 -409
  53. package/cidr.js +0 -83
  54. package/cli/apps.js +0 -585
  55. package/cli/auth.js +0 -280
  56. package/cli/client.js +0 -115
  57. package/cli/config.js +0 -173
  58. package/cli/firewall.js +0 -100
  59. package/cli/fp.js +0 -638
  60. package/cli/init.js +0 -201
  61. package/cli/monitor.js +0 -440
  62. package/cli/run.js +0 -133
  63. package/cli/security.js +0 -1064
  64. package/cli/ui.js +0 -386
  65. package/docs/API-KEYS-GUIDE.md +0 -233
  66. package/docs/AUTO-SETUP-SUMMARY.md +0 -331
  67. package/docs/BODY-CAPTURE-FIX.md +0 -261
  68. package/docs/COMPLETION-REPORT.md +0 -408
  69. package/docs/FINAL-SOLUTION.md +0 -335
  70. package/docs/FIREWALL-GUIDE.md +0 -426
  71. package/docs/IMPLEMENTATION-SUMMARY.md +0 -410
  72. package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +0 -323
  73. package/docs/NEXTJS-SETUP-COMPLETE.md +0 -795
  74. package/docs/NUXT-GUIDE.md +0 -166
  75. package/docs/SOLUTION-SUMMARY.md +0 -312
  76. package/firewall-cloud.js +0 -212
  77. package/firewall-iptables.js +0 -139
  78. package/firewall-only.js +0 -38
  79. package/firewall-tcp.js +0 -74
  80. package/firewall.js +0 -720
  81. package/free-trial-banner.js +0 -174
  82. package/nuxt-server-plugin.mjs +0 -423
  83. package/nuxt.d.ts +0 -60
  84. package/nuxt.mjs +0 -75
  85. package/resolve-ip.js +0 -77
package/web-vite.mjs CHANGED
@@ -1,239 +1,156 @@
1
- // web-vite.ts — Browser OTel for Vite (ESM)
2
- // Defaults & naming rules match your Node tracing.js
3
-
4
- import { WebTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-web';
5
- import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
6
- import { Resource } from '@opentelemetry/resources';
7
- import { SemanticResourceAttributes as S } from '@opentelemetry/semantic-conventions';
8
- import { registerInstrumentations } from '@opentelemetry/instrumentation';
9
- import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
10
- import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';
11
- import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
12
- import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
13
-
14
- // ---- helpers / env ----
15
- const viteEnv: any = (import.meta as any).env || {};
16
-
17
- function env(k: string): string | undefined {
18
- // Accept both Vite envs (VITE_*) and raw names for window.__SECURENOW__
19
- const direct =
20
- viteEnv[k] ??
21
- viteEnv[k.toUpperCase()] ??
22
- viteEnv[k.toLowerCase()];
23
- if (direct != null) return String(direct);
24
-
25
- // Optionally support runtime overrides via window.__SECURENOW__
26
- const w = (globalThis as any).window as any;
27
- if (w && w.__SECURENOW__ && k in w.__SECURENOW__) return String(w.__SECURENOW__[k]);
28
- return undefined;
29
- }
30
-
31
- function parseHeaders(str?: string) {
32
- const out: Record<string, string> = {};
33
- if (!str) return out;
34
- String(str).split(',').forEach(raw => {
35
- const s = raw.trim();
36
- if (!s) return;
37
- const i = s.indexOf('=');
38
- if (i === -1) return;
39
- out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
40
- });
41
- return out;
42
- }
43
-
44
- // ---- endpoints (same defaults as tracing.js) ----
45
- const endpointBase =
46
- (env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'https://freetrial.securenow.ai:4318')
47
- .replace(/\/$/, '');
48
- const tracesUrl =
49
- env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
50
- const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
51
-
52
- // ---- naming rules (mirrors tracing.js) ----
53
- const rawBase = (env('OTEL_SERVICE_NAME') || env('SECURENOW_APPID') || '').trim().replace(/^['"]|['"]$/g, '');
54
- const baseName = rawBase || null;
55
- const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
56
- const strict = String(env('SECURENOW_STRICT')) === '1' || String(env('SECURENOW_STRICT')).toLowerCase() === 'true';
57
-
58
- function uuidv4(): string {
59
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
60
- return crypto.randomUUID();
61
- }
62
- const bytes = new Uint8Array(16);
63
- if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
64
- crypto.getRandomValues(bytes);
65
- } else {
66
- for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);
67
- }
68
- bytes[6] = (bytes[6] & 0x0f) | 0x40;
69
- bytes[8] = (bytes[8] & 0x3f) | 0x80;
70
- const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
71
- return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
72
- }
73
-
74
- let serviceName: string;
75
- let disabled = false;
76
- if (baseName) {
77
- serviceName = noUuid ? baseName : `${baseName}-${uuidv4()}`;
78
- } else {
79
- if (strict) {
80
- console.error('[securenow/web-vite] FATAL: SECURENOW_APPID/OTEL_SERVICE_NAME missing and SECURENOW_STRICT=1. Tracing disabled.');
81
- // @ts-expect-error
82
- window.__SECURENOW_DISABLED__ = true;
83
- disabled = true;
84
- serviceName = 'disabled';
85
- } else {
86
- serviceName = `securenow-free-${uuidv4()}`;
87
- }
88
- }
89
-
90
- const instancePrefix = baseName || 'securenow';
91
- const serviceInstanceId = `${instancePrefix}-${uuidv4()}`;
92
-
93
- // Loud line
94
- try {
95
- // eslint-disable-next-line no-console
96
- console.log(
97
- '[securenow] web preload loaded SECURENOW_APPID=%s OTEL_SERVICE_NAME=%s SECURENOW_NO_UUID=%s SECURENOW_STRICT=%s → service.name=%s instance.id=%s',
98
- JSON.stringify(env('SECURENOW_APPID')),
99
- JSON.stringify(env('OTEL_SERVICE_NAME')),
100
- JSON.stringify(env('SECURENOW_NO_UUID')),
101
- JSON.stringify(env('SECURENOW_STRICT')),
102
- serviceName,
103
- serviceInstanceId
104
- );
105
- } catch {}
106
-
107
- // ---- Provider / Exporter ----
108
- let started = false;
109
-
110
- export function startSecurenowWeb() {
111
- if (started || disabled) return;
112
- started = true;
113
-
114
- const exporter = new OTLPTraceExporter({
115
- url: tracesUrl,
116
- headers,
117
- });
118
-
119
- const provider = new WebTracerProvider({
120
- resource: new Resource({
121
- [S.SERVICE_NAME]: serviceName,
122
- [S.SERVICE_INSTANCE_ID]: serviceInstanceId,
123
- [S.DEPLOYMENT_ENVIRONMENT]: viteEnv.MODE || 'production',
124
- [S.SERVICE_VERSION]: viteEnv.VITE_APP_VERSION || undefined,
125
- }),
126
- });
127
-
128
- provider.addSpanProcessor(new BatchSpanProcessor(exporter));
129
- provider.register();
130
-
131
- registerInstrumentations({
132
- instrumentations: [
133
- new DocumentLoadInstrumentation(),
134
- new UserInteractionInstrumentation(),
135
- new FetchInstrumentation({
136
- propagateTraceHeaderCorsUrls: [new RegExp(`^${location.origin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`)],
137
- ignoreUrls: [/\/vite\/hmr/, /^chrome-extension:\/\//, /sockjs/],
138
- }),
139
- new XMLHttpRequestInstrumentation({
140
- propagateTraceHeaderCorsUrls: [new RegExp(`^${location.origin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`)],
141
- }),
142
- ],
143
- });
144
-
145
- // Optional smoke span (same flag name)
146
- if (String(env('SECURENOW_TEST_SPAN')) === '1') {
147
- import('@opentelemetry/api').then(api => {
148
- const tracer = api.trace.getTracer('securenow-smoke');
149
- const span = tracer.startSpan('securenow.startup.smoke.web'); span.end();
150
- }).catch(() => {});
151
- }
152
-
153
- // eslint-disable-next-line no-console
154
- console.log('[securenow] Web OTel started → %s', tracesUrl);
155
- }
156
-
157
- // ---- Free trial banner (browser DOM injection) ----
158
- function injectFreeTrialBanner(): void {
159
- const FREETRIAL_HOST = 'freetrial.securenow.ai';
160
- const hideBanner = String(env('SECURENOW_HIDE_BANNER')) === '1';
161
- if (hideBanner || !endpointBase.includes(FREETRIAL_HOST)) return;
162
- if (typeof document === 'undefined') return;
163
-
164
- function create(): void {
165
- if (document.getElementById('sn-ft-banner')) return;
166
-
167
- const d = document.createElement('div');
168
- d.id = 'sn-ft-banner';
169
- d.style.cssText =
170
- 'position:fixed;top:0;left:0;right:0;z-index:2147483647;' +
171
- 'background:#FEF3CD;color:#856404;padding:10px 16px;' +
172
- 'font-family:system-ui,-apple-system,sans-serif;font-size:13px;' +
173
- 'text-align:center;border-bottom:2px solid #FFE69C;' +
174
- 'display:flex;align-items:center;justify-content:center;gap:6px;' +
175
- 'box-shadow:0 2px 8px rgba(0,0,0,0.12)';
176
-
177
- const icon = document.createElement('span');
178
- icon.textContent = '\u26a0\ufe0f';
179
- d.appendChild(icon);
180
-
181
- const msg = document.createElement('span');
182
- const strong = document.createElement('strong');
183
- strong.textContent = 'Testing Environment:';
184
- msg.appendChild(strong);
185
- msg.appendChild(document.createTextNode(
186
- ' Only add test applications. For production usage, '
187
- ));
188
-
189
- const link = document.createElement('a');
190
- link.href = 'https://app.securenow.ai/dashboard/settings/instances';
191
- link.target = '_blank';
192
- link.rel = 'noopener';
193
- link.style.cssText = 'color:#664D03;font-weight:600;text-decoration:underline';
194
- link.textContent = 'create a new production instance';
195
- msg.appendChild(link);
196
- msg.appendChild(document.createTextNode('.'));
197
- d.appendChild(msg);
198
-
199
- const upgradeBtn = document.createElement('a');
200
- upgradeBtn.href = 'https://app.securenow.ai/dashboard/settings/instances';
201
- upgradeBtn.target = '_blank';
202
- upgradeBtn.rel = 'noopener';
203
- upgradeBtn.textContent = '\u26a1 Upgrade';
204
- upgradeBtn.style.cssText =
205
- 'display:inline-flex;align-items:center;gap:4px;' +
206
- 'background:#D97706;color:#fff;padding:4px 12px;border-radius:4px;' +
207
- 'font-size:12px;font-weight:600;text-decoration:none;margin-left:10px;' +
208
- 'white-space:nowrap;transition:background 0.15s';
209
- upgradeBtn.onmouseover = () => { upgradeBtn.style.background = '#B45309'; };
210
- upgradeBtn.onmouseout = () => { upgradeBtn.style.background = '#D97706'; };
211
- d.appendChild(upgradeBtn);
212
-
213
- const close = document.createElement('button');
214
- close.textContent = '\u00d7';
215
- close.style.cssText =
216
- 'background:none;border:none;color:#856404;font-size:18px;' +
217
- 'cursor:pointer;margin-left:12px;padding:0 4px;line-height:1';
218
- close.onclick = () => { d.style.display = 'none'; };
219
- d.appendChild(close);
220
-
221
- document.body.prepend(d);
222
- }
223
-
224
- if (document.readyState === 'loading') {
225
- document.addEventListener('DOMContentLoaded', create);
226
- } else {
227
- create();
228
- }
229
- }
230
-
231
- // Auto-start
232
- try {
233
- startSecurenowWeb();
234
- injectFreeTrialBanner();
235
- } catch (e: any) {
236
- console.error('[securenow/web-vite] failed to start:', e);
237
- }
238
-
239
- export default startSecurenowWeb;
1
+ // web-vite.ts — Browser OTel for Vite (ESM)
2
+ // Defaults & naming rules match your Node tracing.js
3
+
4
+ import { WebTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-web';
5
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
6
+ import { Resource } from '@opentelemetry/resources';
7
+ import { SemanticResourceAttributes as S } from '@opentelemetry/semantic-conventions';
8
+ import { registerInstrumentations } from '@opentelemetry/instrumentation';
9
+ import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
10
+ import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';
11
+ import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
12
+ import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
13
+
14
+ // ---- helpers / env ----
15
+ const viteEnv: any = (import.meta as any).env || {};
16
+
17
+ function env(k: string): string | undefined {
18
+ // Accept both Vite envs (VITE_*) and raw names for window.__SECURENOW__
19
+ const direct =
20
+ viteEnv[k] ??
21
+ viteEnv[k.toUpperCase()] ??
22
+ viteEnv[k.toLowerCase()];
23
+ if (direct != null) return String(direct);
24
+
25
+ // Optionally support runtime overrides via window.__SECURENOW__
26
+ const w = (globalThis as any).window as any;
27
+ if (w && w.__SECURENOW__ && k in w.__SECURENOW__) return String(w.__SECURENOW__[k]);
28
+ return undefined;
29
+ }
30
+
31
+ function parseHeaders(str?: string) {
32
+ const out: Record<string, string> = {};
33
+ if (!str) return out;
34
+ String(str).split(',').forEach(raw => {
35
+ const s = raw.trim();
36
+ if (!s) return;
37
+ const i = s.indexOf('=');
38
+ if (i === -1) return;
39
+ out[s.slice(0, i).trim().toLowerCase()] = s.slice(i + 1).trim();
40
+ });
41
+ return out;
42
+ }
43
+
44
+ // ---- endpoints (same defaults as tracing.js) ----
45
+ const endpointBase =
46
+ (env('SECURENOW_INSTANCE') || env('OTEL_EXPORTER_OTLP_ENDPOINT') || 'https://freetrial.securenow.ai:4318')
47
+ .replace(/\/$/, '');
48
+ const tracesUrl =
49
+ env('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT') || `${endpointBase}/v1/traces`;
50
+ const headers = parseHeaders(env('OTEL_EXPORTER_OTLP_HEADERS'));
51
+
52
+ // ---- naming rules (mirrors tracing.js) ----
53
+ const rawBase = (env('OTEL_SERVICE_NAME') || env('SECURENOW_APPID') || '').trim().replace(/^['"]|['"]$/g, '');
54
+ const baseName = rawBase || null;
55
+ const noUuid = String(env('SECURENOW_NO_UUID')) === '1' || String(env('SECURENOW_NO_UUID')).toLowerCase() === 'true';
56
+ const strict = String(env('SECURENOW_STRICT')) === '1' || String(env('SECURENOW_STRICT')).toLowerCase() === 'true';
57
+
58
+ // Simple UUID v4 (no crypto dependency needed)
59
+ function uuidv4(): string {
60
+ const rnd = (n = 16) => Array.from({ length: n }, () => Math.floor(Math.random() * 16).toString(16)).join('');
61
+ return `${rnd(8)}-${rnd(4)}-4${rnd(3)}-${((8 + Math.random()*4)|0).toString(16)}${rnd(3)}-${rnd(12)}`;
62
+ }
63
+
64
+ let serviceName: string;
65
+ if (baseName) {
66
+ serviceName = noUuid ? baseName : `${baseName}-${uuidv4()}`;
67
+ } else {
68
+ if (strict) {
69
+ console.error('[securenow/web-vite] FATAL: SECURENOW_APPID/OTEL_SERVICE_NAME missing and SECURENOW_STRICT=1. Tracing disabled.');
70
+ // Do not start tracing
71
+ // @ts-expect-error
72
+ window.__SECURENOW_DISABLED__ = true;
73
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
74
+ const _noop = true;
75
+ // early return by throwing a no-op error caught below:
76
+ throw new Error('__SECURENOW_NO_START__');
77
+ }
78
+ serviceName = `securenow-free-${uuidv4()}`;
79
+ }
80
+
81
+ const instancePrefix = baseName || 'securenow';
82
+ const serviceInstanceId = `${instancePrefix}-${uuidv4()}`;
83
+
84
+ // Loud line
85
+ try {
86
+ // eslint-disable-next-line no-console
87
+ console.log(
88
+ '[securenow] web preload loaded SECURENOW_APPID=%s OTEL_SERVICE_NAME=%s SECURENOW_NO_UUID=%s SECURENOW_STRICT=%s → service.name=%s instance.id=%s',
89
+ JSON.stringify(env('SECURENOW_APPID')),
90
+ JSON.stringify(env('OTEL_SERVICE_NAME')),
91
+ JSON.stringify(env('SECURENOW_NO_UUID')),
92
+ JSON.stringify(env('SECURENOW_STRICT')),
93
+ serviceName,
94
+ serviceInstanceId
95
+ );
96
+ } catch {}
97
+
98
+ // ---- Provider / Exporter ----
99
+ let started = false;
100
+
101
+ export function startSecurenowWeb() {
102
+ if (started) return;
103
+ started = true;
104
+
105
+ const exporter = new OTLPTraceExporter({
106
+ url: tracesUrl,
107
+ headers,
108
+ });
109
+
110
+ const provider = new WebTracerProvider({
111
+ resource: new Resource({
112
+ [S.SERVICE_NAME]: serviceName,
113
+ [S.SERVICE_INSTANCE_ID]: serviceInstanceId,
114
+ [S.DEPLOYMENT_ENVIRONMENT]: viteEnv.MODE || 'production',
115
+ [S.SERVICE_VERSION]: viteEnv.VITE_APP_VERSION || undefined,
116
+ }),
117
+ });
118
+
119
+ provider.addSpanProcessor(new BatchSpanProcessor(exporter));
120
+ provider.register();
121
+
122
+ registerInstrumentations({
123
+ instrumentations: [
124
+ new DocumentLoadInstrumentation(),
125
+ new UserInteractionInstrumentation(),
126
+ new FetchInstrumentation({
127
+ propagateTraceHeaderCorsUrls: [/.*/],
128
+ ignoreUrls: [/\/vite\/hmr/, /^chrome-extension:\/\//, /sockjs/],
129
+ }),
130
+ new XMLHttpRequestInstrumentation({
131
+ propagateTraceHeaderCorsUrls: [/.*/],
132
+ }),
133
+ ],
134
+ });
135
+
136
+ // Optional smoke span (same flag name)
137
+ if (String(env('SECURENOW_TEST_SPAN')) === '1') {
138
+ const api = await import('@opentelemetry/api');
139
+ const tracer = api.trace.getTracer('securenow-smoke');
140
+ const span = tracer.startSpan('securenow.startup.smoke.web'); span.end();
141
+ }
142
+
143
+ // eslint-disable-next-line no-console
144
+ console.log('[securenow] Web OTel started → %s', tracesUrl);
145
+ }
146
+
147
+ // Auto-start
148
+ try {
149
+ startSecurenowWeb();
150
+ } catch (e: any) {
151
+ if (String(e?.message) !== '__SECURENOW_NO_START__') {
152
+ console.error('[securenow/web-vite] failed to start:', e);
153
+ }
154
+ }
155
+
156
+ export default startSecurenowWeb;