securenow 5.17.1 → 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 -243
  3. package/cli.js +455 -425
  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 -1958
  51. package/SKILL-API.md +0 -600
  52. package/SKILL-CLI.md +0 -419
  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 -545
  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/NPM_README.md DELETED
@@ -1,1958 +0,0 @@
1
- # SecureNow - Complete OpenTelemetry Observability for Node.js
2
-
3
- OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt applications. Send distributed traces and logs to any OTLP-compatible observability backend.
4
-
5
- **Features:**
6
- - Zero-config automatic instrumentation
7
- - Distributed tracing for all popular frameworks
8
- - Automatic logging with console instrumentation
9
- - Built-in sensitive data redaction
10
- - Request body capture for debugging
11
- - Multi-layer firewall -- auto-blocks IPs from your SecureNow blocklist
12
- - `withSecureNow()` config wrapper for Next.js -- eliminates manual `serverExternalPackages`
13
- - `securenow init` CLI scaffolds instrumentation files for any framework
14
- - `securenow/firewall-only` entry point for firewall without tracing overhead
15
- - Fully configurable via environment variables
16
- - Single `-r securenow/register` flag -- works for both CJS and ESM apps
17
- - Native Nuxt 3 module (`securenow/nuxt`)
18
-
19
- ---
20
-
21
- ## Table of Contents
22
-
23
- - [Installation](#installation)
24
- - [Quick Start](#quick-start)
25
- - [CLI -- Command Line Interface](#cli--command-line-interface)
26
- - [Framework-Specific Setup](#framework-specific-setup)
27
- - [Express.js](#expressjs)
28
- - [Next.js](#nextjs)
29
- - [Nuxt 3](#nuxt-3)
30
- - [Fastify](#fastify)
31
- - [NestJS](#nestjs)
32
- - [Koa](#koa)
33
- - [Hapi](#hapi)
34
- - [Firewall -- Automatic IP Blocking](#firewall--automatic-ip-blocking)
35
- - [Environment Variables Reference](#environment-variables-reference)
36
- - [Logging Setup](#logging-setup)
37
- - [Request Body Capture](#request-body-capture)
38
- - [Advanced Configuration](#advanced-configuration)
39
- - [TypeScript Support](#typescript-support)
40
- - [Troubleshooting](#troubleshooting)
41
-
42
- ---
43
-
44
- ## Installation
45
-
46
- ```bash
47
- npm install securenow
48
- ```
49
-
50
- Or with yarn:
51
-
52
- ```bash
53
- yarn add securenow
54
- ```
55
-
56
- ---
57
-
58
- ## Quick Start
59
-
60
- ### 1. Automatic Setup (Recommended)
61
-
62
- Run the init command after installing:
63
-
64
- ```bash
65
- npx securenow init --key snk_live_abc123...
66
- ```
67
-
68
- This detects your framework and:
69
- - **Next.js**: Creates `instrumentation.ts`, suggests `withSecureNow()` for `next.config.js`
70
- - **Nuxt 3**: Suggests adding `securenow/nuxt` to modules
71
- - **Express / Node.js**: Shows how to add `-r securenow/register` to your start script
72
- - **All**: Writes `SECURENOW_API_KEY` to `.env.local` when `--key` is provided
73
-
74
- ### 2. Manual Setup
75
-
76
- #### Set Environment Variables
77
-
78
- ```bash
79
- # Required: Your application identifier
80
- export SECURENOW_APPID=my-app
81
-
82
- # Required: Your OTLP collector endpoint
83
- export SECURENOW_INSTANCE=http://your-otlp-collector:4318
84
-
85
- # Optional: Enable logging
86
- export SECURENOW_LOGGING_ENABLED=1
87
-
88
- # Optional: Enable the firewall (set your API key)
89
- export SECURENOW_API_KEY=snk_live_abc123...
90
- ```
91
-
92
- #### Run Your Application
93
-
94
- Add `-r securenow/register` to your start command -- that's the only change:
95
-
96
- ```bash
97
- node -r securenow/register app.js
98
- ```
99
-
100
- ESM and CJS apps are both handled automatically (Node >=20.6 auto-registers the ESM loader hook via `module.register()`).
101
-
102
- **package.json** example:
103
-
104
- ```json
105
- "scripts": {
106
- "start": "node -r securenow/register app.js",
107
- "dev": "node -r securenow/register --watch app.js"
108
- }
109
- ```
110
-
111
- **Alternative: Use NODE_OPTIONS** so your existing scripts stay unchanged:
112
-
113
- ```bash
114
- NODE_OPTIONS="-r securenow/register" npm start
115
- ```
116
-
117
- **CJS only: Code-based initialization**
118
-
119
- ```javascript
120
- // At the very top of your main file, before any other require
121
- require('securenow/register');
122
-
123
- const express = require('express');
124
- const app = express();
125
- // ...
126
- ```
127
-
128
- You'll see confirmation in the console:
129
-
130
- ```
131
- [securenow] OTel SDK started -> http://your-otlp-collector:4318/v1/traces
132
- [securenow] Firewall: ENABLED
133
- [securenow] Firewall: synced 142 blocked IPs (138 exact + 4 CIDR ranges)
134
- ```
135
-
136
- ---
137
-
138
- ## CLI -- Command Line Interface
139
-
140
- The `securenow` CLI gives you full access to the SecureNow platform from the terminal -- no browser required for day-to-day workflows. Zero additional dependencies.
141
-
142
- ### Getting Started
143
-
144
- ```bash
145
- # Log in (opens browser for OAuth)
146
- npx securenow login
147
-
148
- # Or use a token for CI/headless environments
149
- npx securenow login --token <YOUR_JWT>
150
-
151
- # Log in for this project only (per-project credentials)
152
- npx securenow login --local
153
-
154
- # Check who you're logged in as (shows auth source)
155
- npx securenow whoami
156
- ```
157
-
158
- ### Project Setup
159
-
160
- ```bash
161
- # Auto-detect framework and scaffold instrumentation files
162
- npx securenow init
163
-
164
- # Pass your API key to auto-write it to .env.local
165
- npx securenow init --key snk_live_abc123...
166
- ```
167
-
168
- For Next.js projects, `init` creates `instrumentation.ts` (or `.js` if no TypeScript) and tells you how to update `next.config.js` with `withSecureNow()`. For Nuxt, it suggests adding `securenow/nuxt` to your modules. For Express/Node, it shows the `-r securenow/register` flag.
169
-
170
- ### Managing Applications
171
-
172
- ```bash
173
- # List all applications
174
- npx securenow apps
175
-
176
- # Create a new application
177
- npx securenow apps create my-production-app --hosts api.example.com,app.example.com
178
-
179
- # Get application details (including the app key)
180
- npx securenow apps info <app-id>
181
-
182
- # Set a default app so you don't need --app on every command
183
- npx securenow apps default <app-key>
184
-
185
- # Delete an application
186
- npx securenow apps delete <app-id> --force
187
- ```
188
-
189
- ### Viewing Traces
190
-
191
- ```bash
192
- # List recent traces (uses default app, or specify --app)
193
- npx securenow traces
194
- npx securenow traces --app <key> --limit 50
195
-
196
- # Show detailed spans for a trace
197
- npx securenow traces show <traceId>
198
-
199
- # AI-powered security analysis of a trace
200
- npx securenow traces analyze <traceId>
201
- ```
202
-
203
- ### Viewing Logs
204
-
205
- ```bash
206
- # List recent logs
207
- npx securenow logs
208
- npx securenow logs --app <key> --minutes 30 --level error
209
-
210
- # Show logs for a specific trace
211
- npx securenow logs trace <traceId>
212
- ```
213
-
214
- ### Security Issues
215
-
216
- ```bash
217
- # List all issues
218
- npx securenow issues
219
- npx securenow issues --status open
220
-
221
- # Show issue details with AI analysis
222
- npx securenow issues show <issue-id>
223
-
224
- # Resolve an issue
225
- npx securenow issues resolve <issue-id>
226
- ```
227
-
228
- ### Notifications
229
-
230
- ```bash
231
- # List notifications
232
- npx securenow notifications
233
-
234
- # Check unread count
235
- npx securenow notifications unread
236
-
237
- # Mark as read
238
- npx securenow notifications read <id>
239
- npx securenow notifications read-all
240
- ```
241
-
242
- ### Alerting
243
-
244
- ```bash
245
- # View alert rules, channels, and history
246
- npx securenow alerts rules
247
- npx securenow alerts rules show <rule-id>
248
- npx securenow alerts rules update <rule-id> --applications-all
249
- npx securenow alerts rules update <rule-id> --apps key1,key2
250
- npx securenow alerts channels
251
- npx securenow alerts history --limit 20
252
- ```
253
-
254
- ### IP Intelligence & Blocklist
255
-
256
- ```bash
257
- # Look up any IP -- geo, abuse score, verdict, risk factors
258
- npx securenow ip 203.0.113.42
259
-
260
- # Show traces from a specific IP
261
- npx securenow ip traces 203.0.113.42
262
-
263
- # Manage the blocklist
264
- npx securenow blocklist
265
- npx securenow blocklist add 203.0.113.42 --reason "Brute force scanner"
266
- npx securenow blocklist remove <id>
267
- npx securenow blocklist stats
268
-
269
- # Manage trusted IPs
270
- npx securenow trusted
271
- npx securenow trusted add 10.0.0.1 --label "Office VPN"
272
- npx securenow trusted remove <id>
273
- ```
274
-
275
- ### Forensic Queries
276
-
277
- Ask questions in plain English -- the AI translates them to SQL and runs them against your data.
278
-
279
- ```bash
280
- # Run a forensic query
281
- npx securenow forensics "show top 10 attacking IPs in the last hour"
282
- npx securenow forensics "which endpoints had 5xx errors today"
283
-
284
- # Browse the saved query library
285
- npx securenow forensics library
286
- ```
287
-
288
- ### API Map
289
-
290
- ```bash
291
- # View all discovered API endpoints
292
- npx securenow api-map
293
-
294
- # API map statistics
295
- npx securenow api-map stats
296
- ```
297
-
298
- ### Analytics & Dashboard
299
-
300
- ```bash
301
- # Response code analytics
302
- npx securenow analytics --app <key>
303
-
304
- # Full dashboard overview (apps, protection status, unread alerts)
305
- npx securenow status
306
- ```
307
-
308
- ### Instances
309
-
310
- ```bash
311
- # List ClickHouse instances
312
- npx securenow instances
313
-
314
- # Test an instance connection
315
- npx securenow instances test <id>
316
- ```
317
-
318
- ### Configuration
319
-
320
- ```bash
321
- # View all config
322
- npx securenow config get
323
-
324
- # Set values
325
- npx securenow config set apiUrl https://custom-api.example.com
326
- npx securenow config set defaultApp <app-key>
327
- npx securenow config set format json
328
-
329
- # Show config file paths
330
- npx securenow config path
331
- ```
332
-
333
- Config files are stored in `~/.securenow/` (global) or `.securenow/` in the project root (per-project):
334
-
335
- | File | Description |
336
- |------|-------------|
337
- | `~/.securenow/config.json` | API URL, default app, output format |
338
- | `~/.securenow/credentials.json` | Auth token — global (file permissions: 0600) |
339
- | `.securenow/credentials.json` | Auth token — project-local (use `login --local`) |
340
-
341
- **Resolution order:** `SECURENOW_TOKEN` env var → project `.securenow/credentials.json` → global `~/.securenow/credentials.json`.
342
-
343
- ### Global Flags
344
-
345
- Every command supports these flags:
346
-
347
- | Flag | Short | Description |
348
- |------|-------|-------------|
349
- | `--json` | `-j` | Output as JSON for scripting and CI/CD |
350
- | `--help` | | Show help for the command |
351
- | `--app <key>` | | Override the default application key |
352
-
353
- ### Environment Variables
354
-
355
- | Variable | Description |
356
- |----------|-------------|
357
- | `SECURENOW_TOKEN` | JWT token — overrides all file-based credentials |
358
- | `SECURENOW_API_URL` | Override the API base URL |
359
- | `SECURENOW_DEBUG` | Show stack traces on errors |
360
- | `NO_COLOR` | Disable colored output |
361
-
362
- ### Multi-Project Sessions
363
-
364
- Use `--local` to maintain separate logins per project on the same machine:
365
-
366
- ```bash
367
- # In project A — log in as user-a@company.com
368
- cd ~/projects/project-a
369
- npx securenow login --local
370
-
371
- # In project B — log in as user-b@company.com
372
- cd ~/projects/project-b
373
- npx securenow login --local
374
-
375
- # Each project uses its own credentials independently
376
- npx securenow whoami # Shows auth source: project (.securenow/)
377
- ```
378
-
379
- You can also use the `SECURENOW_TOKEN` env var for per-terminal sessions without touching any files.
380
-
381
- ### CI/CD Integration
382
-
383
- ```bash
384
- # Authenticate with a token in CI (env var — no file needed)
385
- SECURENOW_TOKEN=$MY_SECRET npx securenow issues --json
386
-
387
- # Or use login with explicit token
388
- npx securenow login --token $SECURENOW_TOKEN
389
-
390
- # Use --json for machine-readable output
391
- npx securenow issues --json | jq '.[] | select(.severity == "critical")'
392
-
393
- # Check for critical issues in a pipeline
394
- ISSUES=$(npx securenow issues --json --status open)
395
- CRITICAL=$(echo "$ISSUES" | jq '[.[] | select(.severity == "critical")] | length')
396
- if [ "$CRITICAL" -gt "0" ]; then
397
- echo "Found $CRITICAL critical issues!"
398
- exit 1
399
- fi
400
- ```
401
-
402
- ### Complete Command Reference
403
-
404
- | Category | Command | Description |
405
- |----------|---------|-------------|
406
- | **Setup** | `init` | Auto-scaffold instrumentation for your framework |
407
- | **Auth** | `login` | Authenticate via browser, `--token`, or `--local` |
408
- | | `logout` | Clear credentials (`--local` for project only) |
409
- | | `whoami` | Show session info and auth source |
410
- | **Apps** | `apps` | List applications |
411
- | | `apps create <name>` | Create application |
412
- | | `apps info <id>` | Application details |
413
- | | `apps delete <id>` | Delete application |
414
- | | `apps default <key>` | Set default app |
415
- | **Observe** | `traces` | List traces |
416
- | | `traces show <id>` | Trace details |
417
- | | `traces analyze <id>` | AI trace analysis |
418
- | | `logs` | List logs |
419
- | | `logs trace <id>` | Logs for a trace |
420
- | | `analytics` | Response analytics |
421
- | | `status` | Dashboard overview |
422
- | **Detect** | `issues` | List issues |
423
- | | `issues show <id>` | Issue details |
424
- | | `issues resolve <id>` | Resolve issue |
425
- | | `notifications` | List notifications |
426
- | | `notifications unread` | Unread count |
427
- | | `notifications read <id>` | Mark read |
428
- | | `notifications read-all` | Mark all read |
429
- | | `alerts rules` | List rules (status, apps, schedule) |
430
- | | `alerts rules show <id>` | Rule detail |
431
- | | `alerts rules update <id> --applications-all` / `--apps k1,k2` | Application scope |
432
- | | `alerts channels` | Alert channels |
433
- | | `alerts history` | Alert history |
434
- | **Investigate** | `ip <addr>` | IP intelligence |
435
- | | `ip traces <addr>` | Traces from IP |
436
- | | `forensics "<query>"` | NL forensic query |
437
- | | `forensics library` | Saved queries |
438
- | | `api-map` | API endpoints |
439
- | | `api-map stats` | API stats |
440
- | **Firewall** | `firewall status` | Firewall status and API key info |
441
- | | `firewall test-ip <ip>` | Check if an IP would be blocked |
442
- | **Remediate** | `blocklist` | Blocked IPs |
443
- | | `blocklist add <ip>` | Block IP |
444
- | | `blocklist remove <id>` | Unblock IP |
445
- | | `blocklist stats` | Block stats |
446
- | | `trusted` | Trusted IPs |
447
- | | `trusted add <ip>` | Add trusted IP |
448
- | | `trusted remove <id>` | Remove trusted |
449
- | **Settings** | `instances` | List instances |
450
- | | `instances test <id>` | Test connection |
451
- | | `config get` | Show config |
452
- | | `config set <k> <v>` | Set config value |
453
- | | `config path` | Config file paths |
454
- | | `version` | Show version |
455
-
456
- ---
457
-
458
- ## Framework-Specific Setup
459
-
460
- > **v5.6.0+:** When `SECURENOW_LOGGING_ENABLED=1`, all `console.log`/`warn`/`error`/`info`/`debug` calls
461
- > are **automatically** forwarded as OTLP log records. The separate `require('securenow/console-instrumentation')` is no longer needed (but still available for backward compat).
462
-
463
- ### Express.js
464
-
465
- ```bash
466
- npm install securenow express
467
- ```
468
-
469
- ```javascript
470
- // app.js
471
- require('securenow/register');
472
- const express = require('express');
473
-
474
- const app = express();
475
- app.use(express.json());
476
-
477
- app.get('/health', (req, res) => res.json({ status: 'ok' }));
478
-
479
- app.post('/tasks', (req, res) => {
480
- console.log('Created task:', req.body.title);
481
- res.status(201).json({ id: '1', title: req.body.title });
482
- });
483
-
484
- app.listen(3000, () => console.log('Express running on port 3000'));
485
- ```
486
-
487
- ```bash
488
- node app.js
489
- ```
490
-
491
- #### With PM2
492
-
493
- ```javascript
494
- // ecosystem.config.cjs
495
- module.exports = {
496
- apps: [{
497
- name: 'my-app',
498
- script: './app.js',
499
- node_args: '-r securenow/register',
500
- env: {
501
- SECURENOW_APPID: 'your-app-key',
502
- SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
503
- SECURENOW_API_KEY: 'snk_live_abc123...',
504
- SECURENOW_LOGGING_ENABLED: '1',
505
- SECURENOW_NO_UUID: '1',
506
- SECURENOW_CAPTURE_BODY: '1',
507
- }
508
- }]
509
- };
510
- ```
511
-
512
- > **Important:** Always use `node_args: '-r securenow/register'` in PM2 configs. Without it, PM2 restarts won't load the SDK, and the firewall won't activate.
513
-
514
- ---
515
-
516
- ### Fastify
517
-
518
- ```bash
519
- npm install securenow fastify
520
- ```
521
-
522
- ```javascript
523
- // app.js
524
- require('securenow/register');
525
- const Fastify = require('fastify');
526
- const fastify = Fastify({ logger: true });
527
-
528
- fastify.get('/health', async () => ({ status: 'ok' }));
529
-
530
- fastify.post('/tasks', {
531
- schema: { body: { type: 'object', required: ['title'], properties: { title: { type: 'string' } } } }
532
- }, async (request) => {
533
- console.log('Created task:', request.body.title);
534
- return { id: '1', title: request.body.title };
535
- });
536
-
537
- fastify.listen({ port: 3000 }, (err) => {
538
- if (err) { fastify.log.error(err); process.exit(1); }
539
- console.log('Fastify running on port 3000');
540
- });
541
- ```
542
-
543
- > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify -- the body capture hook conflicts with Fastify's internal stream handling.
544
-
545
- ---
546
-
547
- ### Koa
548
-
549
- ```bash
550
- npm install securenow koa @koa/router koa-bodyparser
551
- ```
552
-
553
- ```javascript
554
- // app.js
555
- require('securenow/register');
556
- const Koa = require('koa');
557
- const Router = require('@koa/router');
558
- const bodyParser = require('koa-bodyparser');
559
-
560
- const app = new Koa();
561
- const router = new Router();
562
-
563
- router.get('/health', (ctx) => { ctx.body = { status: 'ok' }; });
564
-
565
- router.post('/tasks', (ctx) => {
566
- console.log('Created task:', ctx.request.body.title);
567
- ctx.status = 201;
568
- ctx.body = { id: '1', title: ctx.request.body.title };
569
- });
570
-
571
- app.use(bodyParser());
572
- app.use(router.routes());
573
- app.use(router.allowedMethods());
574
-
575
- app.listen(3000, () => console.log('Koa running on port 3000'));
576
- ```
577
-
578
- ---
579
-
580
- ### NestJS
581
-
582
- ```bash
583
- npm install securenow @nestjs/core @nestjs/common reflect-metadata ts-node typescript
584
- ```
585
-
586
- NestJS uses TypeScript -- securenow is loaded via `-r` flags instead of in-code `require()`:
587
-
588
- ```typescript
589
- // app.ts
590
- import 'reflect-metadata';
591
- import { NestFactory } from '@nestjs/core';
592
- import { Module, Controller, Get, Post, Body } from '@nestjs/common';
593
-
594
- @Controller()
595
- class AppController {
596
- @Get('health')
597
- health() { return { status: 'ok' }; }
598
-
599
- @Post('tasks')
600
- create(@Body() body: { title: string }) {
601
- console.log('Created task:', body.title);
602
- return { id: '1', title: body.title };
603
- }
604
- }
605
-
606
- @Module({ controllers: [AppController] })
607
- class AppModule {}
608
-
609
- async function bootstrap() {
610
- const app = await NestFactory.create(AppModule);
611
- await app.listen(3000);
612
- console.log('NestJS running on port 3000');
613
- }
614
- bootstrap();
615
- ```
616
-
617
- ```bash
618
- node -r securenow/register -r ts-node/register app.ts
619
- ```
620
-
621
- PM2 config:
622
-
623
- ```javascript
624
- {
625
- name: 'my-nestjs-app',
626
- script: 'app.ts',
627
- interpreter: 'node',
628
- node_args: '-r securenow/register -r ts-node/register',
629
- }
630
- ```
631
-
632
- ---
633
-
634
- ### Hapi
635
-
636
- ```bash
637
- npm install securenow @hapi/hapi
638
- ```
639
-
640
- ```javascript
641
- // app.js
642
- require('securenow/register');
643
- const Hapi = require('@hapi/hapi');
644
-
645
- const init = async () => {
646
- const server = Hapi.server({ port: 3000, host: '0.0.0.0' });
647
-
648
- server.route({ method: 'GET', path: '/health', handler: () => ({ status: 'ok' }) });
649
-
650
- server.route({
651
- method: 'POST', path: '/tasks',
652
- options: { payload: { parse: true, allow: 'application/json' } },
653
- handler: (request, h) => {
654
- console.log('Created task:', request.payload.title);
655
- return h.response({ id: '1', title: request.payload.title }).code(201);
656
- }
657
- });
658
-
659
- await server.start();
660
- console.log('Hapi running on port 3000');
661
- };
662
-
663
- init().catch((err) => { console.error(err); process.exit(1); });
664
- ```
665
-
666
- > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi -- the body capture hook consumes the request stream before Hapi's payload parser.
667
-
668
- ---
669
-
670
- ### h3 (UnJS / Nitro)
671
-
672
- ```bash
673
- npm install securenow h3
674
- ```
675
-
676
- ```javascript
677
- // app.js
678
- require('securenow/register');
679
- const { createApp, createRouter, defineEventHandler, readBody, setResponseStatus, toNodeListener } = require('h3');
680
- const http = require('http');
681
-
682
- const app = createApp();
683
- const router = createRouter();
684
-
685
- router.get('/health', defineEventHandler(() => ({ status: 'ok' })));
686
-
687
- router.post('/tasks', defineEventHandler(async (event) => {
688
- const body = await readBody(event);
689
- console.log('Created task:', body.title);
690
- setResponseStatus(event, 201);
691
- return { id: '1', title: body.title };
692
- }));
693
-
694
- app.use(router);
695
-
696
- http.createServer(toNodeListener(app)).listen(3000, () => {
697
- console.log('h3 running on port 3000');
698
- });
699
- ```
700
-
701
- ---
702
-
703
- ### Polka
704
-
705
- ```bash
706
- npm install securenow polka
707
- ```
708
-
709
- Polka is minimalist -- no built-in body parser:
710
-
711
- ```javascript
712
- // app.js
713
- require('securenow/register');
714
- const polka = require('polka');
715
-
716
- function jsonBody(req, res, next) {
717
- if (req.method === 'GET' || req.method === 'DELETE') return next();
718
- let data = '';
719
- req.on('data', chunk => { data += chunk; });
720
- req.on('end', () => { try { req.body = JSON.parse(data); } catch { req.body = {}; } next(); });
721
- }
722
-
723
- function sendJson(res, status, body) {
724
- res.writeHead(status, { 'Content-Type': 'application/json' });
725
- res.end(JSON.stringify(body));
726
- }
727
-
728
- polka()
729
- .use(jsonBody)
730
- .get('/health', (req, res) => sendJson(res, 200, { status: 'ok' }))
731
- .post('/tasks', (req, res) => {
732
- console.log('Created task:', req.body.title);
733
- sendJson(res, 201, { id: '1', title: req.body.title });
734
- })
735
- .listen(3000, () => console.log('Polka running on port 3000'));
736
- ```
737
-
738
- ---
739
-
740
- ### Micro / Raw HTTP
741
-
742
- For apps using Node's bare `http` module:
743
-
744
- ```bash
745
- npm install securenow
746
- ```
747
-
748
- ```javascript
749
- // app.js
750
- require('securenow/register');
751
- const http = require('http');
752
-
753
- function sendJson(res, status, body) {
754
- res.writeHead(status, { 'Content-Type': 'application/json' });
755
- res.end(JSON.stringify(body));
756
- }
757
-
758
- function readBody(req) {
759
- return new Promise((resolve) => {
760
- let d = ''; req.on('data', c => { d += c; }); req.on('end', () => { try { resolve(JSON.parse(d)); } catch { resolve({}); } });
761
- });
762
- }
763
-
764
- async function handler(req, res) {
765
- const url = new URL(req.url, `http://${req.headers.host}`);
766
- if (url.pathname === '/health') return sendJson(res, 200, { status: 'ok' });
767
- if (url.pathname === '/tasks' && req.method === 'POST') {
768
- const body = await readBody(req);
769
- console.log('Created task:', body.title);
770
- return sendJson(res, 201, { id: '1', title: body.title });
771
- }
772
- sendJson(res, 404, { error: 'Not found' });
773
- }
774
-
775
- http.createServer(handler).listen(3000, () => console.log('HTTP running on port 3000'));
776
- ```
777
-
778
- ---
779
-
780
- ### Hono (ESM)
781
-
782
- ```bash
783
- npm install securenow hono @hono/node-server
784
- ```
785
-
786
- Hono uses ESM -- preload via `-r` flag (the ESM hook is auto-registered on Node >=20.6):
787
-
788
- ```javascript
789
- // app.mjs
790
- import { serve } from '@hono/node-server';
791
- import { Hono } from 'hono';
792
-
793
- const app = new Hono();
794
-
795
- app.get('/health', (c) => c.json({ status: 'ok' }));
796
-
797
- app.post('/tasks', async (c) => {
798
- const body = await c.req.json();
799
- console.log('Created task:', body.title);
800
- return c.json({ id: '1', title: body.title }, 201);
801
- });
802
-
803
- serve({ fetch: app.fetch, port: 3000 }, () => console.log('Hono running on port 3000'));
804
- ```
805
-
806
- ```bash
807
- node -r securenow/register app.mjs
808
- ```
809
-
810
- > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hono. Do **not** add `require('securenow/register')` inside `.mjs` files.
811
-
812
- ---
813
-
814
- ### Feathers
815
-
816
- ```bash
817
- npm install securenow @feathersjs/feathers @feathersjs/express @feathersjs/errors
818
- ```
819
-
820
- Feathers uses Express transport -- same setup as Express:
821
-
822
- ```javascript
823
- // app.js
824
- require('securenow/register');
825
- const feathers = require('@feathersjs/feathers');
826
- const express = require('@feathersjs/express');
827
- const errors = require('@feathersjs/errors');
828
-
829
- class TaskService {
830
- constructor() { this.tasks = []; this.nextId = 1; }
831
- async find() { return this.tasks; }
832
- async create(data) {
833
- if (!data.title) throw new errors.BadRequest('title is required');
834
- const task = { id: String(this.nextId++), title: data.title };
835
- this.tasks.push(task);
836
- console.log('Created task:', task.id);
837
- return task;
838
- }
839
- }
840
-
841
- const app = express(feathers());
842
- app.use(express.json());
843
- app.configure(express.rest());
844
- app.get('/health', (req, res) => res.json({ status: 'ok' }));
845
- app.use('/tasks', new TaskService());
846
- app.use(express.errorHandler());
847
-
848
- app.listen(3000, () => console.log('Feathers running on port 3000'));
849
- ```
850
-
851
- ---
852
-
853
- ### Next.js
854
-
855
- See [Next.js Complete Guide](./docs/NEXTJS-SETUP-COMPLETE.md) for the full reference.
856
-
857
- #### Option A: `withSecureNow()` wrapper (v5.13.0+ -- Recommended)
858
-
859
- One wrapper handles everything: `serverExternalPackages` (Next 15) or `experimental.serverComponentsExternalPackages` (Next 14), `instrumentationHook`, and webpack warning suppression.
860
-
861
- **1. Update `next.config.js`:**
862
-
863
- ```javascript
864
- const { withSecureNow } = require('securenow/nextjs-webpack-config');
865
-
866
- module.exports = withSecureNow({
867
- // your existing config -- reactStrictMode, images, rewrites, etc.
868
- });
869
- ```
870
-
871
- **2. Create `instrumentation.ts` (or `.js`):**
872
-
873
- ```typescript
874
- export async function register() {
875
- if (process.env.NEXT_RUNTIME === 'nodejs') {
876
- const { registerSecureNow } = require('securenow/nextjs');
877
- registerSecureNow();
878
- }
879
- }
880
- ```
881
-
882
- Or run `npx securenow init` to auto-generate this file.
883
-
884
- **3. Set environment variables in `.env.local`:**
885
-
886
- ```env
887
- SECURENOW_APPID=my-nextjs-app
888
- SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
889
- SECURENOW_API_KEY=snk_live_abc123...
890
- SECURENOW_LOGGING_ENABLED=1
891
- SECURENOW_NO_UUID=1
892
- ```
893
-
894
- That's it. `withSecureNow()` auto-detects your Next.js version and configures:
895
- - **Next.js 15+**: Sets `serverExternalPackages` with all 13 required OTel packages
896
- - **Next.js 14**: Sets `experimental.serverComponentsExternalPackages` and `experimental.instrumentationHook: true`
897
- - **Both**: Suppresses webpack warnings from OpenTelemetry instrumentation packages
898
-
899
- #### Option B: Manual configuration
900
-
901
- If you prefer not to use the wrapper, manually add the packages:
902
-
903
- ```javascript
904
- // next.config.js (Next.js 15+)
905
- module.exports = {
906
- serverExternalPackages: [
907
- 'securenow',
908
- '@opentelemetry/sdk-node',
909
- '@opentelemetry/auto-instrumentations-node',
910
- '@opentelemetry/instrumentation-http',
911
- '@opentelemetry/exporter-trace-otlp-http',
912
- '@opentelemetry/exporter-logs-otlp-http',
913
- '@opentelemetry/sdk-logs',
914
- '@opentelemetry/instrumentation',
915
- '@opentelemetry/resources',
916
- '@opentelemetry/semantic-conventions',
917
- '@opentelemetry/api',
918
- '@opentelemetry/api-logs',
919
- '@vercel/otel',
920
- ],
921
- };
922
- ```
923
-
924
- ```javascript
925
- // next.config.js (Next.js 14)
926
- module.exports = {
927
- experimental: {
928
- instrumentationHook: true,
929
- serverComponentsExternalPackages: [
930
- 'securenow',
931
- '@opentelemetry/sdk-node',
932
- '@opentelemetry/auto-instrumentations-node',
933
- '@opentelemetry/instrumentation-http',
934
- '@opentelemetry/exporter-trace-otlp-http',
935
- '@opentelemetry/exporter-logs-otlp-http',
936
- '@opentelemetry/sdk-logs',
937
- '@opentelemetry/instrumentation',
938
- '@opentelemetry/resources',
939
- '@opentelemetry/semantic-conventions',
940
- '@opentelemetry/api',
941
- '@opentelemetry/api-logs',
942
- '@vercel/otel',
943
- ],
944
- },
945
- };
946
- ```
947
-
948
- **Why is this needed?** Next.js bundles server code with webpack, which breaks OpenTelemetry's dynamic `require()` calls and monkey-patching. Externalizing these packages keeps them as normal Node.js `require()` calls at runtime. The `withSecureNow()` wrapper handles this automatically.
949
-
950
- ---
951
-
952
- ### Nuxt 3
953
-
954
- ```bash
955
- npm install securenow
956
- ```
957
-
958
- Add the module to `nuxt.config.ts`:
959
-
960
- ```typescript
961
- export default defineNuxtConfig({
962
- modules: ['securenow/nuxt'],
963
- });
964
- ```
965
-
966
- `.env`:
967
-
968
- ```env
969
- SECURENOW_APPID=my-nuxt-app
970
- SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
971
- SECURENOW_API_KEY=snk_live_abc123...
972
- ```
973
-
974
- That's it -- the Nuxt module handles OTel SDK initialization, Nitro externalization, firewall activation, and request tracing automatically. Optional config:
975
-
976
- ```typescript
977
- export default defineNuxtConfig({
978
- modules: ['securenow/nuxt'],
979
- securenow: {
980
- captureBody: true,
981
- logging: true,
982
- noUuid: true,
983
- },
984
- });
985
- ```
986
-
987
- The Nuxt server plugin (v5.13.0+) initializes the firewall independently from OpenTelemetry, so IP blocking works even if tracing encounters an error.
988
-
989
- ---
990
-
991
- ### Compatibility Matrix
992
-
993
- | Framework | Traces | Logs | Body Capture | Firewall | Notes |
994
- |-----------|--------|------|--------------|----------|-------|
995
- | Express | Yes | Yes | Yes | Yes | Fully compatible |
996
- | Fastify | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0` required |
997
- | Koa | Yes | Yes | Yes | Yes | Needs `koa-bodyparser` |
998
- | NestJS | Yes | Yes | Yes | Yes | Use `-r ts-node/register` |
999
- | Hapi | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0` required |
1000
- | h3 | Yes | Yes | Yes | Yes | Uses `toNodeListener()` |
1001
- | Polka | Yes | Yes | Yes | Yes | Needs manual body parser |
1002
- | Micro/HTTP | Yes | Yes | Yes | Yes | Full control |
1003
- | Hono | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
1004
- | Feathers | Yes | Yes | Yes | Yes | Uses Express transport |
1005
- | Next.js | Yes | Yes | Yes | Yes | Use `instrumentation.ts` + `withSecureNow()` |
1006
- | Nuxt 3 | Yes | Yes | Yes | Yes | Use `securenow/nuxt` module |
1007
-
1008
- ---
1009
-
1010
- ## Firewall -- Automatic IP Blocking
1011
-
1012
- SecureNow can automatically block IPs from your blocklist at the application layer. No code changes -- just set an API key and the firewall activates.
1013
-
1014
- ### Enable the Firewall
1015
-
1016
- ```bash
1017
- # Add to your .env
1018
- SECURENOW_API_KEY=snk_live_abc123...
1019
- ```
1020
-
1021
- That's it. On startup, you'll see:
1022
-
1023
- ```
1024
- [securenow] Firewall: ENABLED
1025
- [securenow] Firewall: Layer 1 (HTTP 403) active
1026
- [securenow] Firewall: synced 142 blocked IPs (138 exact + 4 CIDR ranges)
1027
- ```
1028
-
1029
- ### How It Works
1030
-
1031
- The firewall uses a version-based sync protocol for efficiency:
1032
-
1033
- 1. **Version check** every 10 seconds (lightweight HEAD-like request with ETag)
1034
- 2. **Full blocklist sync** only when the version changes (or every 5 minutes as a safety net)
1035
- 3. **In-memory matching** with a pre-compiled set (exact IPs) and sorted CIDR list for sub-millisecond lookups
1036
- 4. **Exponential backoff** with jitter when the API is temporarily unreachable
1037
- 5. **Allowlist support** -- trusted IPs are never blocked, even if they appear on the blocklist
1038
- 6. **Localhost fallback** -- when the configured API URL is unreachable (ECONNREFUSED), the SDK automatically tries `http://localhost:4000` for co-located deployments
1039
-
1040
- After you block an IP in the dashboard or CLI, it typically takes 10-15 seconds to propagate to all running instances.
1041
-
1042
- ### Firewall-Only Mode (No Tracing)
1043
-
1044
- If you only need IP blocking without OpenTelemetry tracing overhead, use the standalone entry point:
1045
-
1046
- ```bash
1047
- node -r securenow/firewall-only app.js
1048
- ```
1049
-
1050
- Or in `package.json`:
1051
-
1052
- ```json
1053
- "scripts": {
1054
- "start": "node -r securenow/firewall-only app.js"
1055
- }
1056
- ```
1057
-
1058
- This is useful when:
1059
- - You only need IP blocking, not observability
1060
- - You want to minimize startup time and memory footprint
1061
- - You're adding the firewall to a project that uses a different tracing solution
1062
- - For Next.js, this avoids the need for `serverExternalPackages` entirely
1063
-
1064
- Environment variables for firewall-only mode:
1065
-
1066
- ```bash
1067
- SECURENOW_API_KEY=snk_live_abc123... # Required
1068
- SECURENOW_API_URL=https://api.securenow.ai # Optional (auto-detected)
1069
- SECURENOW_FIREWALL_ENABLED=1 # Default: 1
1070
- SECURENOW_FIREWALL_TCP=1 # Optional: Layer 2
1071
- SECURENOW_FIREWALL_IPTABLES=1 # Optional: Layer 3
1072
- SECURENOW_FIREWALL_CLOUD=cloudflare # Optional: Layer 4
1073
- ```
1074
-
1075
- ### Blocking Layers
1076
-
1077
- The firewall supports four layers -- Layer 1 is always on, the rest are opt-in:
1078
-
1079
- | Layer | Env Var | Description |
1080
- |-------|---------|-------------|
1081
- | **Layer 1: HTTP** | *(always on)* | Returns 403 Forbidden with a security alert page. Works with proxy headers. |
1082
- | **Layer 2: TCP** | `SECURENOW_FIREWALL_TCP=1` | `socket.destroy()` -- zero bytes sent back |
1083
- | **Layer 3: iptables** | `SECURENOW_FIREWALL_IPTABLES=1` | Kernel-level DROP (Linux, requires root) |
1084
- | **Layer 4: Cloud WAF** | `SECURENOW_FIREWALL_CLOUD=cloudflare` | Pushes to Cloudflare, AWS WAF, or GCP Cloud Armor |
1085
-
1086
- ### Blocked Page
1087
-
1088
- When an IP is blocked at Layer 1, the user sees a full-page security alert with:
1089
- - Their detected IP address
1090
- - A warning that malicious activity was detected
1091
- - Contact information (`contact@securenow.ai`) for false positives
1092
-
1093
- ### Get an API Key
1094
-
1095
- ```bash
1096
- npx securenow login
1097
- npx securenow firewall status
1098
- ```
1099
-
1100
- Or create one from the dashboard with the `firewall:read` scope.
1101
-
1102
- See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
1103
-
1104
- ---
1105
-
1106
- ## Environment Variables Reference
1107
-
1108
- ### Required Variables
1109
-
1110
- | Variable | Description | Example |
1111
- |----------|-------------|---------|
1112
- | `SECURENOW_APPID` | Your application identifier. Used as the service name in traces. | `my-app` |
1113
- | `SECURENOW_INSTANCE` | Base URL of your OTLP collector endpoint. | `http://localhost:4318` |
1114
-
1115
- ### Optional Configuration
1116
-
1117
- #### Service Naming
1118
-
1119
- | Variable | Description | Default |
1120
- |----------|-------------|---------|
1121
- | `OTEL_SERVICE_NAME` | Alternative to SECURENOW_APPID. Standard OpenTelemetry variable. | - |
1122
- | `SECURENOW_NO_UUID` | Set to `1` to disable UUID suffix on service name. Useful for clustered apps. | `0` |
1123
- | `SECURENOW_STRICT` | Set to `1` to exit process if SECURENOW_APPID is not set in cluster mode. | `0` |
1124
-
1125
- #### Connection Settings
1126
-
1127
- | Variable | Description | Default |
1128
- |----------|-------------|---------|
1129
- | `OTEL_EXPORTER_OTLP_ENDPOINT` | Alternative to SECURENOW_INSTANCE. Standard OpenTelemetry variable. | - |
1130
- | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Override traces endpoint specifically. | `{SECURENOW_INSTANCE}/v1/traces` |
1131
- | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Override logs endpoint specifically. | `{SECURENOW_INSTANCE}/v1/logs` |
1132
- | `OTEL_EXPORTER_OTLP_HEADERS` | Headers to send with OTLP exports. Format: `key1=value1,key2=value2` | - |
1133
-
1134
- #### Logging
1135
-
1136
- | Variable | Description | Default |
1137
- |----------|-------------|---------|
1138
- | `SECURENOW_LOGGING_ENABLED` | Enable automatic logging to OTLP backend. Set to `1` to enable, `0` to disable. | `1` |
1139
-
1140
- #### Request Body Capture
1141
-
1142
- | Variable | Description | Default |
1143
- |----------|-------------|---------|
1144
- | `SECURENOW_CAPTURE_BODY` | Enable request body capture in traces. Set to `1` to enable. | `0` |
1145
- | `SECURENOW_MAX_BODY_SIZE` | Maximum body size to capture in bytes. Bodies larger than this are truncated. | `10240` (10KB) |
1146
- | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated list of additional field names to redact. | - |
1147
- | `SECURENOW_CAPTURE_MULTIPART` | Enable multipart/form-data capture. Streams through the request to extract text field values and file metadata (name, filename, content-type, size) without buffering file content. Set to `1` to enable. | `0` |
1148
-
1149
- **Default sensitive fields (auto-redacted):** `password`, `passwd`, `pwd`, `secret`, `token`, `api_key`, `apikey`, `access_token`, `auth`, `credentials`, `mysql_pwd`, `stripeToken`, `card`, `cardnumber`, `ccv`, `cvc`, `cvv`, `ssn`, `pin`
1150
-
1151
- #### Instrumentation Control
1152
-
1153
- | Variable | Description | Default |
1154
- |----------|-------------|---------|
1155
- | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated list of instrumentation packages to disable. | - |
1156
-
1157
- **Example:** `SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns` disables filesystem and DNS instrumentations.
1158
-
1159
- #### Firewall
1160
-
1161
- | Variable | Description | Default |
1162
- |----------|-------------|---------|
1163
- | `SECURENOW_API_KEY` | API key with `firewall:read` scope. Enables the firewall when set. | - |
1164
- | `SECURENOW_API_URL` | SecureNow API base URL. Auto-detected for co-located deployments (falls back to `http://localhost:4000` on ECONNREFUSED). | `https://api.securenow.ai` |
1165
- | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch. Set to `0` to disable. | `1` |
1166
- | `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between version checks (lightweight ETag-based). | `10` |
1167
- | `SECURENOW_FIREWALL_SYNC_INTERVAL` | Full blocklist refresh interval in seconds (safety net). | `300` |
1168
- | `SECURENOW_FIREWALL_FAIL_MODE` | `open` (allow when unavailable) or `closed` (block all). | `open` |
1169
- | `SECURENOW_FIREWALL_STATUS_CODE` | HTTP status code for blocked requests. | `403` |
1170
- | `SECURENOW_FIREWALL_LOG` | Log blocked requests and sync events to console. Set to `0` to silence. | `1` |
1171
- | `SECURENOW_FIREWALL_TCP` | Enable Layer 2 TCP blocking. | `0` |
1172
- | `SECURENOW_FIREWALL_IPTABLES` | Enable Layer 3 iptables blocking. | `0` |
1173
- | `SECURENOW_FIREWALL_CLOUD` | Cloud WAF provider: `cloudflare`, `aws`, or `gcp`. | - |
1174
- | `SECURENOW_FIREWALL_CLOUD_DRY_RUN` | Log cloud pushes without applying changes. | `0` |
1175
- | `SECURENOW_TRUSTED_PROXIES` | Comma-separated trusted proxy IPs. | - |
1176
-
1177
- See [Firewall Guide](./docs/FIREWALL-GUIDE.md) for complete details on all layers.
1178
-
1179
- #### Debugging
1180
-
1181
- | Variable | Description | Default |
1182
- |----------|-------------|---------|
1183
- | `OTEL_LOG_LEVEL` | OpenTelemetry SDK log level. Options: `debug`, `info`, `warn`, `error` | `none` |
1184
- | `SECURENOW_TEST_SPAN` | Set to `1` to emit a test span on startup. | `0` |
1185
-
1186
- #### Environment
1187
-
1188
- | Variable | Description | Default |
1189
- |----------|-------------|---------|
1190
- | `NODE_ENV` | Deployment environment name. Sent as `deployment.environment` attribute. | `production` |
1191
-
1192
- ---
1193
-
1194
- ## Entry Points Reference
1195
-
1196
- SecureNow provides multiple entry points depending on your needs:
1197
-
1198
- | Entry Point | Usage | Includes Tracing | Includes Firewall | Notes |
1199
- |-------------|-------|-------------------|-------------------|-------|
1200
- | `securenow/register` | `node -r securenow/register app.js` | Yes | Yes | Default -- full tracing + firewall |
1201
- | `securenow/firewall-only` | `node -r securenow/firewall-only app.js` | No | Yes | Firewall only, no OTel overhead |
1202
- | `securenow/nextjs` | `require('securenow/nextjs').registerSecureNow()` | Yes | Yes | Next.js instrumentation hook |
1203
- | `securenow/nuxt` | `modules: ['securenow/nuxt']` | Yes | Yes | Nuxt 3 module |
1204
- | `securenow/nextjs-webpack-config` | `withSecureNow(config)` | - | - | Next.js config wrapper |
1205
- | `securenow/firewall` | `require('securenow/firewall').init({...})` | No | Yes | Programmatic firewall API |
1206
- | `securenow/tracing` | `require('securenow/tracing')` | Yes | No | Programmatic tracing API |
1207
-
1208
- ---
1209
-
1210
- ## Logging Setup
1211
-
1212
- ### Automatic Console Logging
1213
-
1214
- Since **v5.6.0**, when `SECURENOW_LOGGING_ENABLED=1`, all console calls are automatically forwarded as OTLP log records:
1215
-
1216
- ```javascript
1217
- // At the top of your main file
1218
- require('securenow/register');
1219
-
1220
- // With SECURENOW_LOGGING_ENABLED=1, all console logs are automatically sent
1221
- console.log('Application started');
1222
- console.info('User action', { userId: 123, action: 'login' });
1223
- console.warn('Deprecation warning');
1224
- console.error('Error occurred', { error: 'Something failed' });
1225
- console.debug('Debug info');
1226
- ```
1227
-
1228
- **Severity mapping:**
1229
- - `console.log()` -> INFO
1230
- - `console.info()` -> INFO
1231
- - `console.warn()` -> WARN
1232
- - `console.error()` -> ERROR
1233
- - `console.debug()` -> DEBUG
1234
-
1235
- **Environment variable:**
1236
- ```bash
1237
- SECURENOW_LOGGING_ENABLED=1
1238
- ```
1239
-
1240
- ### Direct Logger API
1241
-
1242
- For more control, use the OpenTelemetry logger API:
1243
-
1244
- ```javascript
1245
- require('securenow/register');
1246
- const { getLogger } = require('securenow/tracing');
1247
-
1248
- // Get a logger instance
1249
- const logger = getLogger('my-module', '1.0.0');
1250
-
1251
- // Emit structured logs
1252
- logger.emit({
1253
- severityNumber: 9, // INFO
1254
- severityText: 'INFO',
1255
- body: 'User logged in',
1256
- attributes: {
1257
- userId: 123,
1258
- username: 'john',
1259
- sessionId: 'abc123',
1260
- },
1261
- });
1262
- ```
1263
-
1264
- **Severity numbers:**
1265
- - `5` - DEBUG
1266
- - `9` - INFO
1267
- - `13` - WARN
1268
- - `17` - ERROR
1269
-
1270
- ### Using with NODE_OPTIONS
1271
-
1272
- ```bash
1273
- # Enable tracing + logging (console auto-forwarding is built-in since v5.6.0)
1274
- NODE_OPTIONS="-r securenow/register" \
1275
- SECURENOW_APPID=my-app \
1276
- SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318 \
1277
- SECURENOW_LOGGING_ENABLED=1 \
1278
- node app.js
1279
- ```
1280
-
1281
- ---
1282
-
1283
- ## Request Body Capture
1284
-
1285
- SecureNow can capture HTTP request bodies in traces for debugging purposes. This is disabled by default.
1286
-
1287
- ### Enable Body Capture
1288
-
1289
- ```bash
1290
- export SECURENOW_CAPTURE_BODY=1
1291
- export SECURENOW_MAX_BODY_SIZE=10240 # 10KB (optional)
1292
- ```
1293
-
1294
- ### Supported Content Types
1295
-
1296
- - `application/json`
1297
- - `application/x-www-form-urlencoded`
1298
- - `application/graphql`
1299
- - `multipart/form-data` (requires `SECURENOW_CAPTURE_MULTIPART=1`)
1300
-
1301
- ### Multipart Body Capture (v5.8.0+)
1302
-
1303
- Enable with `SECURENOW_CAPTURE_MULTIPART=1` to capture multipart/form-data requests. Uses a streaming parser that never buffers file content -- memory stays at ~few KB regardless of upload size.
1304
-
1305
- **What gets captured:**
1306
- - **Text fields** -- field name and value (up to 1000 chars), with sensitive fields auto-redacted
1307
- - **File fields** -- metadata only: field name, filename, content-type, and size in bytes
1308
-
1309
- **Example trace attribute:**
1310
- ```json
1311
- {
1312
- "fields": { "description": "My upload", "token": "[REDACTED]" },
1313
- "files": [
1314
- { "field": "avatar", "filename": "photo.jpg", "contentType": "image/jpeg", "size": 524288 },
1315
- { "field": "resume", "filename": "cv.pdf", "contentType": "application/pdf", "size": 1048576 }
1316
- ]
1317
- }
1318
- ```
1319
-
1320
- File binary content is never stored in traces.
1321
-
1322
- ### Sensitive Data Redaction
1323
-
1324
- All request bodies are automatically scanned and sensitive fields are redacted:
1325
-
1326
- **Automatically redacted fields:** `password`, `secret`, `token`, `api_key`, `card`, `cvv`, `ssn`, and more.
1327
-
1328
- **Add custom fields to redact:**
1329
-
1330
- ```bash
1331
- export SECURENOW_SENSITIVE_FIELDS="custom_secret,internal_token"
1332
- ```
1333
-
1334
- ### Example
1335
-
1336
- ```javascript
1337
- // POST /api/users with body:
1338
- {
1339
- "email": "user@example.com",
1340
- "password": "secret123",
1341
- "name": "John Doe"
1342
- }
1343
-
1344
- // Captured in trace as:
1345
- {
1346
- "email": "user@example.com",
1347
- "password": "[REDACTED]",
1348
- "name": "John Doe"
1349
- }
1350
- ```
1351
-
1352
- ---
1353
-
1354
- ## Advanced Configuration
1355
-
1356
- ### Complete Example with All Options
1357
-
1358
- ```bash
1359
- # Service identification
1360
- export SECURENOW_APPID=my-production-app
1361
- export SECURENOW_NO_UUID=1
1362
- export SECURENOW_STRICT=1
1363
-
1364
- # OTLP backend
1365
- export SECURENOW_INSTANCE=http://collector.example.com:4318
1366
- export OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key"
1367
-
1368
- # Logging
1369
- export SECURENOW_LOGGING_ENABLED=1
1370
-
1371
- # Request body capture
1372
- export SECURENOW_CAPTURE_BODY=1
1373
- export SECURENOW_MAX_BODY_SIZE=20480
1374
- export SECURENOW_SENSITIVE_FIELDS="internal_id,session_key"
1375
-
1376
- # Firewall
1377
- export SECURENOW_API_KEY=snk_live_abc123...
1378
- export SECURENOW_FIREWALL_TCP=1
1379
- export SECURENOW_FIREWALL_VERSION_INTERVAL=10
1380
- export SECURENOW_FIREWALL_SYNC_INTERVAL=300
1381
-
1382
- # Environment
1383
- export NODE_ENV=production
1384
-
1385
- # Debugging
1386
- export OTEL_LOG_LEVEL=info
1387
-
1388
- # Disable specific instrumentations
1389
- export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
1390
-
1391
- # Run application
1392
- NODE_OPTIONS="-r securenow/register" node app.js
1393
- ```
1394
-
1395
- ### Using Multiple Logger Instances
1396
-
1397
- ```javascript
1398
- const { getLogger } = require('securenow/tracing');
1399
-
1400
- const authLogger = getLogger('auth-service', '1.0.0');
1401
- const dbLogger = getLogger('database', '1.0.0');
1402
- const apiLogger = getLogger('api-handler', '1.0.0');
1403
-
1404
- authLogger.emit({
1405
- severityNumber: 9,
1406
- severityText: 'INFO',
1407
- body: 'User authenticated',
1408
- attributes: { userId: 123 },
1409
- });
1410
-
1411
- dbLogger.emit({
1412
- severityNumber: 13,
1413
- severityText: 'WARN',
1414
- body: 'Slow query detected',
1415
- attributes: { queryTime: 5000 },
1416
- });
1417
- ```
1418
-
1419
- ### Check if Logging is Enabled
1420
-
1421
- ```javascript
1422
- const { isLoggingEnabled } = require('securenow/tracing');
1423
-
1424
- if (isLoggingEnabled()) {
1425
- console.log('Logging is enabled');
1426
- } else {
1427
- console.log('Logging is disabled');
1428
- }
1429
- ```
1430
-
1431
- ### Programmatic Configuration
1432
-
1433
- While environment variables are recommended, you can also configure programmatically:
1434
-
1435
- ```javascript
1436
- // Set environment variables before requiring securenow
1437
- process.env.SECURENOW_APPID = 'my-app';
1438
- process.env.SECURENOW_INSTANCE = 'http://localhost:4318';
1439
- process.env.SECURENOW_LOGGING_ENABLED = '1';
1440
-
1441
- // Then initialize (console log forwarding is automatic since v5.6.0)
1442
- require('securenow/register');
1443
- ```
1444
-
1445
- ---
1446
-
1447
- ## TypeScript Support
1448
-
1449
- SecureNow includes full TypeScript definitions.
1450
-
1451
- ### Type Definitions
1452
-
1453
- ```typescript
1454
- import { getLogger, isLoggingEnabled, Logger, LogRecord } from 'securenow/tracing';
1455
-
1456
- // Get a typed logger
1457
- const logger: Logger | null = getLogger('my-service', '1.0.0');
1458
-
1459
- // Emit a log with type checking
1460
- if (logger) {
1461
- const logRecord: LogRecord = {
1462
- severityNumber: 9,
1463
- severityText: 'INFO',
1464
- body: 'User action',
1465
- attributes: {
1466
- userId: 123,
1467
- action: 'login',
1468
- },
1469
- };
1470
-
1471
- logger.emit(logRecord);
1472
- }
1473
-
1474
- // Check if enabled
1475
- const enabled: boolean = isLoggingEnabled();
1476
- ```
1477
-
1478
- ### Next.js with TypeScript
1479
-
1480
- ```typescript
1481
- // instrumentation.ts
1482
- export async function register() {
1483
- if (process.env.NEXT_RUNTIME === 'nodejs') {
1484
- const { registerSecureNow } = require('securenow/nextjs');
1485
- registerSecureNow();
1486
- }
1487
- }
1488
- ```
1489
-
1490
- ```javascript
1491
- // next.config.js
1492
- const { withSecureNow } = require('securenow/nextjs-webpack-config');
1493
-
1494
- module.exports = withSecureNow({
1495
- reactStrictMode: true,
1496
- });
1497
- ```
1498
-
1499
- ### NestJS with TypeScript
1500
-
1501
- Use `-r securenow/register -r ts-node/register` flags instead of in-code require:
1502
-
1503
- ```typescript
1504
- // main.ts (run with: node -r securenow/register -r ts-node/register main.ts)
1505
- import { NestFactory } from '@nestjs/core';
1506
- import { AppModule } from './app.module';
1507
-
1508
- async function bootstrap() {
1509
- const app = await NestFactory.create(AppModule);
1510
- await app.listen(3000);
1511
- }
1512
-
1513
- bootstrap();
1514
- ```
1515
-
1516
- ---
1517
-
1518
- ## Troubleshooting
1519
-
1520
- ### Traces Not Appearing
1521
-
1522
- **Check 1: Verify environment variables**
1523
-
1524
- ```bash
1525
- echo $SECURENOW_APPID
1526
- echo $SECURENOW_INSTANCE
1527
- ```
1528
-
1529
- Both should output values.
1530
-
1531
- **Check 2: Verify OTLP collector is running**
1532
-
1533
- ```bash
1534
- curl http://localhost:4318/v1/traces
1535
- # Should return 200 or 405 (method not allowed)
1536
- ```
1537
-
1538
- **Check 3: Enable debug logging**
1539
-
1540
- ```bash
1541
- export OTEL_LOG_LEVEL=debug
1542
- node app.js
1543
- ```
1544
-
1545
- Look for lines like:
1546
- ```
1547
- [securenow] OTel SDK started -> http://localhost:4318/v1/traces
1548
- ```
1549
-
1550
- **Check 4: Verify initialization order**
1551
-
1552
- SecureNow must be required BEFORE any other modules:
1553
-
1554
- ```javascript
1555
- // Correct
1556
- require('securenow/register');
1557
- const express = require('express');
1558
-
1559
- // Wrong -- too late!
1560
- const express = require('express');
1561
- require('securenow/register');
1562
- ```
1563
-
1564
- ### Firewall Not Blocking IPs
1565
-
1566
- **Check 1: Is `SECURENOW_API_KEY` set?**
1567
-
1568
- ```bash
1569
- echo $SECURENOW_API_KEY
1570
- ```
1571
-
1572
- **Check 2: Is the IP in the blocklist?**
1573
-
1574
- ```bash
1575
- npx securenow blocklist
1576
- npx securenow firewall test-ip 1.2.3.4
1577
- ```
1578
-
1579
- **Check 3: Check startup logs for sync status**
1580
-
1581
- You should see:
1582
- ```
1583
- [securenow] Firewall: ENABLED
1584
- [securenow] Firewall: synced 142 blocked IPs
1585
- ```
1586
-
1587
- If you see `initial sync failed`, check the API URL and key.
1588
-
1589
- **Check 4: Wait for propagation**
1590
-
1591
- After blocking an IP, it takes 10-15 seconds to propagate (one version-check interval).
1592
-
1593
- **Check 5: Are you behind a proxy?**
1594
-
1595
- Set `SECURENOW_TRUSTED_PROXIES` to your proxy's IP so the firewall sees the real client IP.
1596
-
1597
- **Check 6: Using PM2?**
1598
-
1599
- Make sure `node_args: '-r securenow/register'` is in your `ecosystem.config.cjs`. Without it, PM2 restarts skip the SDK entirely.
1600
-
1601
- ### Logs Not Appearing
1602
-
1603
- **Check 1: Is logging enabled?**
1604
-
1605
- ```bash
1606
- echo $SECURENOW_LOGGING_ENABLED
1607
- # Should output: 1
1608
- ```
1609
-
1610
- **Check 2: Verify console instrumentation is loaded**
1611
-
1612
- ```javascript
1613
- require('securenow/register');
1614
- ```
1615
-
1616
- **Check 3: Check console output**
1617
-
1618
- You should see:
1619
- ```
1620
- [securenow] Logging: ENABLED -> http://localhost:4318/v1/logs
1621
- ```
1622
-
1623
- **Check 4: Verify OTLP logs endpoint**
1624
-
1625
- ```bash
1626
- curl http://localhost:4318/v1/logs
1627
- # Should return 200 or 405
1628
- ```
1629
-
1630
- ### Request Body Not Captured
1631
-
1632
- **Check 1: Is body capture enabled?**
1633
-
1634
- ```bash
1635
- export SECURENOW_CAPTURE_BODY=1
1636
- ```
1637
-
1638
- **Check 2: Verify content type**
1639
-
1640
- Body capture only works for:
1641
- - `application/json`
1642
- - `application/x-www-form-urlencoded`
1643
- - `application/graphql`
1644
-
1645
- **Check 3: Check body size**
1646
-
1647
- Bodies larger than `SECURENOW_MAX_BODY_SIZE` are truncated:
1648
-
1649
- ```bash
1650
- export SECURENOW_MAX_BODY_SIZE=20480 # Increase to 20KB
1651
- ```
1652
-
1653
- ### High Memory Usage
1654
-
1655
- **Option 1: Disable body capture**
1656
-
1657
- ```bash
1658
- export SECURENOW_CAPTURE_BODY=0
1659
- ```
1660
-
1661
- **Option 2: Reduce body size limit**
1662
-
1663
- ```bash
1664
- export SECURENOW_MAX_BODY_SIZE=5120 # 5KB
1665
- ```
1666
-
1667
- **Option 3: Disable specific instrumentations**
1668
-
1669
- ```bash
1670
- export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
1671
- ```
1672
-
1673
- ### Next.js Instrumentation Not Working
1674
-
1675
- **Check 1: Using `withSecureNow()`?**
1676
-
1677
- ```javascript
1678
- const { withSecureNow } = require('securenow/nextjs-webpack-config');
1679
- module.exports = withSecureNow({ /* your config */ });
1680
- ```
1681
-
1682
- This auto-handles `serverExternalPackages` / `experimental.serverComponentsExternalPackages` and `instrumentationHook` based on your Next.js version.
1683
-
1684
- **Check 2: Verify instrumentation file location**
1685
-
1686
- `instrumentation.ts` or `instrumentation.js` must be in the project root (same level as `app/` or `pages/`).
1687
-
1688
- **Check 3: Check for OTel MODULE_NOT_FOUND errors**
1689
-
1690
- If you see `MODULE_NOT_FOUND` for `@opentelemetry/*` packages, your `next.config.js` is missing the externalization. Use `withSecureNow()` to fix this automatically.
1691
-
1692
- **Check 4: Restart dev server**
1693
-
1694
- ```bash
1695
- # Kill the server and restart
1696
- npm run dev
1697
- ```
1698
-
1699
- ### PM2 Cluster Issues
1700
-
1701
- **Problem: Different service names for each worker**
1702
-
1703
- **Solution: Use SECURENOW_NO_UUID**
1704
-
1705
- ```bash
1706
- export SECURENOW_NO_UUID=1
1707
- ```
1708
-
1709
- This uses the same service name for all workers.
1710
-
1711
- **Problem: Workers not instrumented / firewall not active**
1712
-
1713
- **Solution: Use node_args in PM2 config**
1714
-
1715
- ```javascript
1716
- // ecosystem.config.cjs
1717
- module.exports = {
1718
- apps: [{
1719
- name: 'my-app',
1720
- script: './app.js',
1721
- instances: 4,
1722
- node_args: '-r securenow/register',
1723
- env: {
1724
- SECURENOW_APPID: 'my-app',
1725
- SECURENOW_INSTANCE: 'http://localhost:4318',
1726
- SECURENOW_API_KEY: 'snk_live_abc123...',
1727
- }
1728
- }]
1729
- };
1730
- ```
1731
-
1732
- Without `node_args`, PM2 starts your script directly without the securenow preload, so neither tracing nor the firewall will be active.
1733
-
1734
- ---
1735
-
1736
- ## Best Practices
1737
-
1738
- ### 1. Use Environment Variables
1739
-
1740
- Don't hardcode configuration. Use environment variables:
1741
-
1742
- ```javascript
1743
- // Bad
1744
- process.env.SECURENOW_APPID = 'hardcoded-value';
1745
-
1746
- // Good -- use .env file or export
1747
- // .env
1748
- SECURENOW_APPID=my-app
1749
- SECURENOW_INSTANCE=http://localhost:4318
1750
- ```
1751
-
1752
- ### 2. Use Structured Logging
1753
-
1754
- Pass objects to console methods for better filtering:
1755
-
1756
- ```javascript
1757
- // Less useful
1758
- console.log('User 123 logged in');
1759
-
1760
- // Better -- structured attributes
1761
- console.log('User logged in', {
1762
- userId: 123,
1763
- email: 'user@example.com',
1764
- timestamp: new Date().toISOString(),
1765
- });
1766
- ```
1767
-
1768
- ### 3. Choose Appropriate Severity Levels
1769
-
1770
- ```javascript
1771
- // Normal operations
1772
- console.log('Request processed');
1773
- console.info('User created', { userId: 123 });
1774
-
1775
- // Warnings
1776
- console.warn('API rate limit approaching', { remaining: 10 });
1777
-
1778
- // Errors
1779
- console.error('Database connection failed', { error: err.message });
1780
-
1781
- // Debug (only in development)
1782
- console.debug('Cache hit', { key: 'user:123' });
1783
- ```
1784
-
1785
- ### 4. Don't Log Sensitive Data
1786
-
1787
- Even though SecureNow automatically redacts common sensitive fields, avoid logging:
1788
-
1789
- ```javascript
1790
- // Bad
1791
- console.log('Login attempt', {
1792
- email: 'user@example.com',
1793
- password: 'secret123', // Will be redacted, but don't log it!
1794
- });
1795
-
1796
- // Good
1797
- console.log('Login attempt', {
1798
- email: 'user@example.com',
1799
- timestamp: Date.now(),
1800
- });
1801
- ```
1802
-
1803
- ### 5. Use Different Logger Instances for Different Modules
1804
-
1805
- ```javascript
1806
- // auth-service.js
1807
- const authLogger = getLogger('auth-service', '1.0.0');
1808
-
1809
- // database.js
1810
- const dbLogger = getLogger('database', '1.0.0');
1811
-
1812
- // api.js
1813
- const apiLogger = getLogger('api', '1.0.0');
1814
- ```
1815
-
1816
- ### 6. Enable Body Capture Only in Development
1817
-
1818
- ```bash
1819
- # .env.development
1820
- SECURENOW_CAPTURE_BODY=1
1821
-
1822
- # .env.production
1823
- SECURENOW_CAPTURE_BODY=0
1824
- ```
1825
-
1826
- ---
1827
-
1828
- ## Supported Runtimes
1829
-
1830
- - **Node.js:** 18+
1831
- - **Frameworks:** Express, Next.js, Nuxt 3, Fastify, NestJS, Koa, Hapi, and more
1832
- - **Databases:** PostgreSQL, MySQL, MongoDB, Redis
1833
- - **HTTP Clients:** axios, fetch, node-fetch, got, request
1834
- - **GraphQL:** Apollo Server, GraphQL.js
1835
- - **Message Queues:** Redis, BullMQ
1836
- - **And many more via OpenTelemetry auto-instrumentation**
1837
-
1838
- ---
1839
-
1840
- ## Automatic Instrumentations
1841
-
1842
- SecureNow automatically instruments:
1843
-
1844
- - HTTP/HTTPS (incoming and outgoing)
1845
- - Express.js
1846
- - Fastify
1847
- - Koa
1848
- - Hapi
1849
- - Next.js
1850
- - PostgreSQL
1851
- - MySQL/MySQL2
1852
- - MongoDB
1853
- - Redis
1854
- - GraphQL
1855
- - gRPC
1856
- - DNS
1857
- - File System
1858
- - And 50+ more libraries
1859
-
1860
- No code changes needed!
1861
-
1862
- ---
1863
-
1864
- ## Architecture
1865
-
1866
- ```
1867
- Your Application
1868
- (Express/Next.js/etc)
1869
- |
1870
- v
1871
- +---------------------------+
1872
- | SecureNow Library |
1873
- | +---------------------+ |
1874
- | | Firewall Layer | | <-- Blocks IPs before they reach your app
1875
- | +---------------------+ |
1876
- | | Auto-instrumentation | |
1877
- | | Console wrapper | |
1878
- | | Body capture | |
1879
- | +---------------------+ |
1880
- +---------------------------+
1881
- |
1882
- +---------+---------+
1883
- | |
1884
- v v
1885
- +-----------+ +-----------+
1886
- | OTel SDK | | SecureNow |
1887
- | OTLP | | API |
1888
- | Exporters | | (blocklist|
1889
- +-----------+ | sync) |
1890
- | +-----------+
1891
- v
1892
- +-----------+
1893
- | Your OTLP |
1894
- | Backend |
1895
- +-----------+
1896
- ```
1897
-
1898
- ---
1899
-
1900
- ## Performance
1901
-
1902
- - **Minimal overhead:** < 1% CPU and memory impact
1903
- - **Batch export:** Traces and logs are batched before sending
1904
- - **Async processing:** No blocking of application threads
1905
- - **Configurable:** Disable instrumentations you don't need
1906
- - **Firewall:** Sub-millisecond IP lookups using pre-compiled hash sets and sorted CIDR lists
1907
- - **Smart sync:** Version-based polling with ETag/304 eliminates unnecessary data transfer
1908
-
1909
- ---
1910
-
1911
- ## Security
1912
-
1913
- - **Automatic redaction** of sensitive fields (passwords, tokens, keys)
1914
- - **Configurable** sensitive field patterns
1915
- - **No data stored** locally -- everything sent to your OTLP backend
1916
- - **Multi-layer firewall** -- blocks IPs at HTTP, TCP, OS, and cloud-edge levels
1917
- - **API keys** with granular scopes, IP allowlisting, and SHA-256 hashing
1918
- - **Allowlist support** -- trusted IPs are never blocked
1919
- - **Fail-open by default** -- network issues never accidentally block legitimate traffic
1920
- - **Open source** -- audit the code yourself
1921
-
1922
- ---
1923
-
1924
- ## License
1925
-
1926
- ISC
1927
-
1928
- ---
1929
-
1930
- ## Support
1931
-
1932
- - **Documentation:** [GitHub Docs](https://github.com/your-repo/securenow-npm/tree/main/docs)
1933
- - **Issues:** [GitHub Issues](https://github.com/your-repo/securenow-npm/issues)
1934
- - **Examples:** [GitHub Examples](https://github.com/your-repo/securenow-npm/tree/main/examples)
1935
-
1936
- ---
1937
-
1938
- ## Changelog
1939
-
1940
- See [CHANGELOG.md](CHANGELOG.md) for version history.
1941
-
1942
- ---
1943
-
1944
- ## Contributing
1945
-
1946
- Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
1947
-
1948
- ---
1949
-
1950
- ## Related Packages
1951
-
1952
- - [@opentelemetry/sdk-node](https://www.npmjs.com/package/@opentelemetry/sdk-node) - Core OpenTelemetry SDK
1953
- - [@opentelemetry/auto-instrumentations-node](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) - Auto-instrumentation
1954
- - [@opentelemetry/exporter-trace-otlp-http](https://www.npmjs.com/package/@opentelemetry/exporter-trace-otlp-http) - OTLP exporter
1955
-
1956
- ---
1957
-
1958
- **Made with care for the Node.js community**