securenow 5.18.0 → 6.0.1

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