securenow 5.14.0 → 5.15.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.
package/NPM_README.md CHANGED
@@ -3,15 +3,18 @@
3
3
  OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt applications. Send distributed traces and logs to any OTLP-compatible observability backend.
4
4
 
5
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
- - 🔧 Fully configurable via environment variables
13
- - 🖥️ Single `-r securenow/register` flag works for both CJS and ESM apps
14
- - 🟢 Native Nuxt 3 module (`securenow/nuxt`)
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`)
15
18
 
16
19
  ---
17
20
 
@@ -19,7 +22,7 @@ OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt application
19
22
 
20
23
  - [Installation](#installation)
21
24
  - [Quick Start](#quick-start)
22
- - [CLI Command Line Interface](#cli--command-line-interface)
25
+ - [CLI -- Command Line Interface](#cli--command-line-interface)
23
26
  - [Framework-Specific Setup](#framework-specific-setup)
24
27
  - [Express.js](#expressjs)
25
28
  - [Next.js](#nextjs)
@@ -28,7 +31,7 @@ OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt application
28
31
  - [NestJS](#nestjs)
29
32
  - [Koa](#koa)
30
33
  - [Hapi](#hapi)
31
- - [Firewall Automatic IP Blocking](#firewall--automatic-ip-blocking)
34
+ - [Firewall -- Automatic IP Blocking](#firewall--automatic-ip-blocking)
32
35
  - [Environment Variables Reference](#environment-variables-reference)
33
36
  - [Logging Setup](#logging-setup)
34
37
  - [Request Body Capture](#request-body-capture)
@@ -54,7 +57,23 @@ yarn add securenow
54
57
 
55
58
  ## Quick Start
56
59
 
57
- ### 1. Set Environment Variables
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
58
77
 
59
78
  ```bash
60
79
  # Required: Your application identifier
@@ -65,11 +84,14 @@ export SECURENOW_INSTANCE=http://your-otlp-collector:4318
65
84
 
66
85
  # Optional: Enable logging
67
86
  export SECURENOW_LOGGING_ENABLED=1
87
+
88
+ # Optional: Enable the firewall (set your API key)
89
+ export SECURENOW_API_KEY=snk_live_abc123...
68
90
  ```
69
91
 
70
- ### 2. Run Your Application
92
+ #### Run Your Application
71
93
 
72
- Add `-r securenow/register` to your start command that's the only change:
94
+ Add `-r securenow/register` to your start command -- that's the only change:
73
95
 
74
96
  ```bash
75
97
  node -r securenow/register app.js
@@ -106,15 +128,16 @@ const app = express();
106
128
  You'll see confirmation in the console:
107
129
 
108
130
  ```
109
- [securenow] OTel SDK started http://your-otlp-collector:4318/v1/traces
110
- [securenow] 📝 Request body capture: ENABLED
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)
111
134
  ```
112
135
 
113
136
  ---
114
137
 
115
- ## CLI Command Line Interface
138
+ ## CLI -- Command Line Interface
116
139
 
117
- 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.
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.
118
141
 
119
142
  ### Getting Started
120
143
 
@@ -129,6 +152,18 @@ npx securenow login --token <YOUR_JWT>
129
152
  npx securenow whoami
130
153
  ```
131
154
 
155
+ ### Project Setup
156
+
157
+ ```bash
158
+ # Auto-detect framework and scaffold instrumentation files
159
+ npx securenow init
160
+
161
+ # Pass your API key to auto-write it to .env.local
162
+ npx securenow init --key snk_live_abc123...
163
+ ```
164
+
165
+ 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.
166
+
132
167
  ### Managing Applications
133
168
 
134
169
  ```bash
@@ -213,7 +248,7 @@ npx securenow alerts history --limit 20
213
248
  ### IP Intelligence & Blocklist
214
249
 
215
250
  ```bash
216
- # Look up any IP geo, abuse score, verdict, risk factors
251
+ # Look up any IP -- geo, abuse score, verdict, risk factors
217
252
  npx securenow ip 203.0.113.42
218
253
 
219
254
  # Show traces from a specific IP
@@ -233,7 +268,7 @@ npx securenow trusted remove <id>
233
268
 
234
269
  ### Forensic Queries
235
270
 
236
- Ask questions in plain English the AI translates them to SQL and runs them against your data.
271
+ Ask questions in plain English -- the AI translates them to SQL and runs them against your data.
237
272
 
238
273
  ```bash
239
274
  # Run a forensic query
@@ -296,14 +331,6 @@ Config files are stored in `~/.securenow/`:
296
331
  | `config.json` | API URL, default app, output format |
297
332
  | `credentials.json` | Auth token (file permissions: 0600) |
298
333
 
299
- ### Initialize Instrumentation
300
-
301
- ```bash
302
- # Interactive setup — creates instrumentation files for Next.js
303
- npx securenow init
304
- npx securenow init --ts --src --force
305
- ```
306
-
307
334
  ### Global Flags
308
335
 
309
336
  Every command supports these flags:
@@ -344,6 +371,7 @@ fi
344
371
 
345
372
  | Category | Command | Description |
346
373
  |----------|---------|-------------|
374
+ | **Setup** | `init` | Auto-scaffold instrumentation for your framework |
347
375
  | **Auth** | `login` | Authenticate via browser or `--token` |
348
376
  | | `logout` | Clear credentials |
349
377
  | | `whoami` | Show session info |
@@ -389,7 +417,6 @@ fi
389
417
  | | `config get` | Show config |
390
418
  | | `config set <k> <v>` | Set config value |
391
419
  | | `config path` | Config file paths |
392
- | | `init` | Setup instrumentation |
393
420
  | | `version` | Show version |
394
421
 
395
422
  ---
@@ -439,6 +466,7 @@ module.exports = {
439
466
  env: {
440
467
  SECURENOW_APPID: 'your-app-key',
441
468
  SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
469
+ SECURENOW_API_KEY: 'snk_live_abc123...',
442
470
  SECURENOW_LOGGING_ENABLED: '1',
443
471
  SECURENOW_NO_UUID: '1',
444
472
  SECURENOW_CAPTURE_BODY: '1',
@@ -447,6 +475,8 @@ module.exports = {
447
475
  };
448
476
  ```
449
477
 
478
+ > **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.
479
+
450
480
  ---
451
481
 
452
482
  ### Fastify
@@ -476,7 +506,7 @@ fastify.listen({ port: 3000 }, (err) => {
476
506
  });
477
507
  ```
478
508
 
479
- > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify the body capture hook conflicts with Fastify's internal stream handling.
509
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Fastify -- the body capture hook conflicts with Fastify's internal stream handling.
480
510
 
481
511
  ---
482
512
 
@@ -519,7 +549,7 @@ app.listen(3000, () => console.log('Koa running on port 3000'));
519
549
  npm install securenow @nestjs/core @nestjs/common reflect-metadata ts-node typescript
520
550
  ```
521
551
 
522
- NestJS uses TypeScript securenow is loaded via `-r` flags instead of in-code `require()`:
552
+ NestJS uses TypeScript -- securenow is loaded via `-r` flags instead of in-code `require()`:
523
553
 
524
554
  ```typescript
525
555
  // app.ts
@@ -599,7 +629,7 @@ const init = async () => {
599
629
  init().catch((err) => { console.error(err); process.exit(1); });
600
630
  ```
601
631
 
602
- > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi the body capture hook consumes the request stream before Hapi's payload parser.
632
+ > **Important:** Set `SECURENOW_CAPTURE_BODY=0` with Hapi -- the body capture hook consumes the request stream before Hapi's payload parser.
603
633
 
604
634
  ---
605
635
 
@@ -642,7 +672,7 @@ http.createServer(toNodeListener(app)).listen(3000, () => {
642
672
  npm install securenow polka
643
673
  ```
644
674
 
645
- Polka is minimalist no built-in body parser:
675
+ Polka is minimalist -- no built-in body parser:
646
676
 
647
677
  ```javascript
648
678
  // app.js
@@ -719,7 +749,7 @@ http.createServer(handler).listen(3000, () => console.log('HTTP running on port
719
749
  npm install securenow hono @hono/node-server
720
750
  ```
721
751
 
722
- Hono uses ESM preload via `-r` flag (the ESM hook is auto-registered on Node >=20.6):
752
+ Hono uses ESM -- preload via `-r` flag (the ESM hook is auto-registered on Node >=20.6):
723
753
 
724
754
  ```javascript
725
755
  // app.mjs
@@ -753,7 +783,7 @@ node -r securenow/register app.mjs
753
783
  npm install securenow @feathersjs/feathers @feathersjs/express @feathersjs/errors
754
784
  ```
755
785
 
756
- Feathers uses Express transport same setup as Express:
786
+ Feathers uses Express transport -- same setup as Express:
757
787
 
758
788
  ```javascript
759
789
  // app.js
@@ -788,27 +818,101 @@ app.listen(3000, () => console.log('Feathers running on port 3000'));
788
818
 
789
819
  ### Next.js
790
820
 
791
- See [Next.js Complete Guide](./docs/NEXTJS-SETUP-COMPLETE.md)
821
+ See [Next.js Complete Guide](./docs/NEXTJS-SETUP-COMPLETE.md) for the full reference.
822
+
823
+ #### Option A: `withSecureNow()` wrapper (v5.13.0+ -- Recommended)
824
+
825
+ One wrapper handles everything: `serverExternalPackages` (Next 15) or `experimental.serverComponentsExternalPackages` (Next 14), `instrumentationHook`, and webpack warning suppression.
826
+
827
+ **1. Update `next.config.js`:**
828
+
829
+ ```javascript
830
+ const { withSecureNow } = require('securenow/nextjs-webpack-config');
831
+
832
+ module.exports = withSecureNow({
833
+ // your existing config -- reactStrictMode, images, rewrites, etc.
834
+ });
835
+ ```
792
836
 
793
- Create `instrumentation.ts` in your project root:
837
+ **2. Create `instrumentation.ts` (or `.js`):**
794
838
 
795
839
  ```typescript
796
840
  export async function register() {
797
841
  if (process.env.NEXT_RUNTIME === 'nodejs') {
798
- await import('securenow/register');
842
+ const { registerSecureNow } = require('securenow/nextjs');
843
+ registerSecureNow();
799
844
  }
800
845
  }
801
846
  ```
802
847
 
803
- `.env.local`:
848
+ Or run `npx securenow init` to auto-generate this file.
849
+
850
+ **3. Set environment variables in `.env.local`:**
804
851
 
805
852
  ```env
806
853
  SECURENOW_APPID=my-nextjs-app
807
854
  SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
855
+ SECURENOW_API_KEY=snk_live_abc123...
808
856
  SECURENOW_LOGGING_ENABLED=1
809
857
  SECURENOW_NO_UUID=1
810
858
  ```
811
859
 
860
+ That's it. `withSecureNow()` auto-detects your Next.js version and configures:
861
+ - **Next.js 15+**: Sets `serverExternalPackages` with all 13 required OTel packages
862
+ - **Next.js 14**: Sets `experimental.serverComponentsExternalPackages` and `experimental.instrumentationHook: true`
863
+ - **Both**: Suppresses webpack warnings from OpenTelemetry instrumentation packages
864
+
865
+ #### Option B: Manual configuration
866
+
867
+ If you prefer not to use the wrapper, manually add the packages:
868
+
869
+ ```javascript
870
+ // next.config.js (Next.js 15+)
871
+ module.exports = {
872
+ serverExternalPackages: [
873
+ 'securenow',
874
+ '@opentelemetry/sdk-node',
875
+ '@opentelemetry/auto-instrumentations-node',
876
+ '@opentelemetry/instrumentation-http',
877
+ '@opentelemetry/exporter-trace-otlp-http',
878
+ '@opentelemetry/exporter-logs-otlp-http',
879
+ '@opentelemetry/sdk-logs',
880
+ '@opentelemetry/instrumentation',
881
+ '@opentelemetry/resources',
882
+ '@opentelemetry/semantic-conventions',
883
+ '@opentelemetry/api',
884
+ '@opentelemetry/api-logs',
885
+ '@vercel/otel',
886
+ ],
887
+ };
888
+ ```
889
+
890
+ ```javascript
891
+ // next.config.js (Next.js 14)
892
+ module.exports = {
893
+ experimental: {
894
+ instrumentationHook: true,
895
+ serverComponentsExternalPackages: [
896
+ 'securenow',
897
+ '@opentelemetry/sdk-node',
898
+ '@opentelemetry/auto-instrumentations-node',
899
+ '@opentelemetry/instrumentation-http',
900
+ '@opentelemetry/exporter-trace-otlp-http',
901
+ '@opentelemetry/exporter-logs-otlp-http',
902
+ '@opentelemetry/sdk-logs',
903
+ '@opentelemetry/instrumentation',
904
+ '@opentelemetry/resources',
905
+ '@opentelemetry/semantic-conventions',
906
+ '@opentelemetry/api',
907
+ '@opentelemetry/api-logs',
908
+ '@vercel/otel',
909
+ ],
910
+ },
911
+ };
912
+ ```
913
+
914
+ **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.
915
+
812
916
  ---
813
917
 
814
918
  ### Nuxt 3
@@ -830,9 +934,10 @@ export default defineNuxtConfig({
830
934
  ```env
831
935
  SECURENOW_APPID=my-nuxt-app
832
936
  SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
937
+ SECURENOW_API_KEY=snk_live_abc123...
833
938
  ```
834
939
 
835
- That's it the Nuxt module handles OTel SDK initialization, Nitro externalization, and request tracing automatically. Optional config:
940
+ That's it -- the Nuxt module handles OTel SDK initialization, Nitro externalization, firewall activation, and request tracing automatically. Optional config:
836
941
 
837
942
  ```typescript
838
943
  export default defineNuxtConfig({
@@ -845,30 +950,32 @@ export default defineNuxtConfig({
845
950
  });
846
951
  ```
847
952
 
953
+ The Nuxt server plugin (v5.13.0+) initializes the firewall independently from OpenTelemetry, so IP blocking works even if tracing encounters an error.
954
+
848
955
  ---
849
956
 
850
957
  ### Compatibility Matrix
851
958
 
852
- | Framework | Traces | Logs | Body Capture | Notes |
853
- |-----------|--------|------|--------------|-------|
854
- | Express | Yes | Yes | Yes | Fully compatible |
855
- | Fastify | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
856
- | Koa | Yes | Yes | Yes | Needs `koa-bodyparser` |
857
- | NestJS | Yes | Yes | Yes | Use `-r ts-node/register` |
858
- | Hapi | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0` required |
859
- | h3 | Yes | Yes | Yes | Uses `toNodeListener()` |
860
- | Polka | Yes | Yes | Yes | Needs manual body parser |
861
- | Micro/HTTP | Yes | Yes | Yes | Full control |
862
- | Hono | Yes | Yes | **No** | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
863
- | Feathers | Yes | Yes | Yes | Uses Express transport |
864
- | Next.js | Yes | Yes | Yes | Use `instrumentation.ts` |
865
- | Nuxt 3 | Yes | Yes | Yes | Use `securenow/nuxt` module |
959
+ | Framework | Traces | Logs | Body Capture | Firewall | Notes |
960
+ |-----------|--------|------|--------------|----------|-------|
961
+ | Express | Yes | Yes | Yes | Yes | Fully compatible |
962
+ | Fastify | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0` required |
963
+ | Koa | Yes | Yes | Yes | Yes | Needs `koa-bodyparser` |
964
+ | NestJS | Yes | Yes | Yes | Yes | Use `-r ts-node/register` |
965
+ | Hapi | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0` required |
966
+ | h3 | Yes | Yes | Yes | Yes | Uses `toNodeListener()` |
967
+ | Polka | Yes | Yes | Yes | Yes | Needs manual body parser |
968
+ | Micro/HTTP | Yes | Yes | Yes | Yes | Full control |
969
+ | Hono | Yes | Yes | **No** | Yes | `SECURENOW_CAPTURE_BODY=0`; ESM `-r` flag |
970
+ | Feathers | Yes | Yes | Yes | Yes | Uses Express transport |
971
+ | Next.js | Yes | Yes | Yes | Yes | Use `instrumentation.ts` + `withSecureNow()` |
972
+ | Nuxt 3 | Yes | Yes | Yes | Yes | Use `securenow/nuxt` module |
866
973
 
867
974
  ---
868
975
 
869
- ## Firewall Automatic IP Blocking
976
+ ## Firewall -- Automatic IP Blocking
870
977
 
871
- SecureNow can automatically block IPs from your blocklist at the application layer. No code changes just set an API key and the firewall activates.
978
+ SecureNow can automatically block IPs from your blocklist at the application layer. No code changes -- just set an API key and the firewall activates.
872
979
 
873
980
  ### Enable the Firewall
874
981
 
@@ -885,17 +992,70 @@ That's it. On startup, you'll see:
885
992
  [securenow] Firewall: synced 142 blocked IPs (138 exact + 4 CIDR ranges)
886
993
  ```
887
994
 
995
+ ### How It Works
996
+
997
+ The firewall uses a version-based sync protocol for efficiency:
998
+
999
+ 1. **Version check** every 10 seconds (lightweight HEAD-like request with ETag)
1000
+ 2. **Full blocklist sync** only when the version changes (or every 5 minutes as a safety net)
1001
+ 3. **In-memory matching** with a pre-compiled set (exact IPs) and sorted CIDR list for sub-millisecond lookups
1002
+ 4. **Exponential backoff** with jitter when the API is temporarily unreachable
1003
+ 5. **Allowlist support** -- trusted IPs are never blocked, even if they appear on the blocklist
1004
+ 6. **Localhost fallback** -- when the configured API URL is unreachable (ECONNREFUSED), the SDK automatically tries `http://localhost:4000` for co-located deployments
1005
+
1006
+ After you block an IP in the dashboard or CLI, it typically takes 10-15 seconds to propagate to all running instances.
1007
+
1008
+ ### Firewall-Only Mode (No Tracing)
1009
+
1010
+ If you only need IP blocking without OpenTelemetry tracing overhead, use the standalone entry point:
1011
+
1012
+ ```bash
1013
+ node -r securenow/firewall-only app.js
1014
+ ```
1015
+
1016
+ Or in `package.json`:
1017
+
1018
+ ```json
1019
+ "scripts": {
1020
+ "start": "node -r securenow/firewall-only app.js"
1021
+ }
1022
+ ```
1023
+
1024
+ This is useful when:
1025
+ - You only need IP blocking, not observability
1026
+ - You want to minimize startup time and memory footprint
1027
+ - You're adding the firewall to a project that uses a different tracing solution
1028
+ - For Next.js, this avoids the need for `serverExternalPackages` entirely
1029
+
1030
+ Environment variables for firewall-only mode:
1031
+
1032
+ ```bash
1033
+ SECURENOW_API_KEY=snk_live_abc123... # Required
1034
+ SECURENOW_API_URL=https://api.securenow.ai # Optional (auto-detected)
1035
+ SECURENOW_FIREWALL_ENABLED=1 # Default: 1
1036
+ SECURENOW_FIREWALL_TCP=1 # Optional: Layer 2
1037
+ SECURENOW_FIREWALL_IPTABLES=1 # Optional: Layer 3
1038
+ SECURENOW_FIREWALL_CLOUD=cloudflare # Optional: Layer 4
1039
+ ```
1040
+
888
1041
  ### Blocking Layers
889
1042
 
890
- The firewall supports four layers Layer 1 is always on, the rest are opt-in:
1043
+ The firewall supports four layers -- Layer 1 is always on, the rest are opt-in:
891
1044
 
892
1045
  | Layer | Env Var | Description |
893
1046
  |-------|---------|-------------|
894
- | **Layer 1: HTTP** | *(always on)* | Returns 403 Forbidden. Works with proxy headers. |
895
- | **Layer 2: TCP** | `SECURENOW_FIREWALL_TCP=1` | `socket.destroy()` zero bytes sent back |
1047
+ | **Layer 1: HTTP** | *(always on)* | Returns 403 Forbidden with a security alert page. Works with proxy headers. |
1048
+ | **Layer 2: TCP** | `SECURENOW_FIREWALL_TCP=1` | `socket.destroy()` -- zero bytes sent back |
896
1049
  | **Layer 3: iptables** | `SECURENOW_FIREWALL_IPTABLES=1` | Kernel-level DROP (Linux, requires root) |
897
1050
  | **Layer 4: Cloud WAF** | `SECURENOW_FIREWALL_CLOUD=cloudflare` | Pushes to Cloudflare, AWS WAF, or GCP Cloud Armor |
898
1051
 
1052
+ ### Blocked Page
1053
+
1054
+ When an IP is blocked at Layer 1, the user sees a full-page security alert with:
1055
+ - Their detected IP address
1056
+ - A warning that malicious activity was detected
1057
+ - Contact information (`contact@securenow.ai`) for false positives
1058
+
899
1059
  ### Get an API Key
900
1060
 
901
1061
  ```bash
@@ -967,13 +1127,17 @@ See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
967
1127
  | Variable | Description | Default |
968
1128
  |----------|-------------|---------|
969
1129
  | `SECURENOW_API_KEY` | API key with `firewall:read` scope. Enables the firewall when set. | - |
970
- | `SECURENOW_API_URL` | SecureNow API base URL. | `https://api.securenow.ai` |
1130
+ | `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` |
971
1131
  | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch. Set to `0` to disable. | `1` |
972
- | `SECURENOW_FIREWALL_SYNC_INTERVAL` | Blocklist refresh interval in seconds. | `60` |
1132
+ | `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between version checks (lightweight ETag-based). | `10` |
1133
+ | `SECURENOW_FIREWALL_SYNC_INTERVAL` | Full blocklist refresh interval in seconds (safety net). | `300` |
973
1134
  | `SECURENOW_FIREWALL_FAIL_MODE` | `open` (allow when unavailable) or `closed` (block all). | `open` |
1135
+ | `SECURENOW_FIREWALL_STATUS_CODE` | HTTP status code for blocked requests. | `403` |
1136
+ | `SECURENOW_FIREWALL_LOG` | Log blocked requests and sync events to console. Set to `0` to silence. | `1` |
974
1137
  | `SECURENOW_FIREWALL_TCP` | Enable Layer 2 TCP blocking. | `0` |
975
1138
  | `SECURENOW_FIREWALL_IPTABLES` | Enable Layer 3 iptables blocking. | `0` |
976
1139
  | `SECURENOW_FIREWALL_CLOUD` | Cloud WAF provider: `cloudflare`, `aws`, or `gcp`. | - |
1140
+ | `SECURENOW_FIREWALL_CLOUD_DRY_RUN` | Log cloud pushes without applying changes. | `0` |
977
1141
  | `SECURENOW_TRUSTED_PROXIES` | Comma-separated trusted proxy IPs. | - |
978
1142
 
979
1143
  See [Firewall Guide](./docs/FIREWALL-GUIDE.md) for complete details on all layers.
@@ -993,6 +1157,22 @@ See [Firewall Guide](./docs/FIREWALL-GUIDE.md) for complete details on all layer
993
1157
 
994
1158
  ---
995
1159
 
1160
+ ## Entry Points Reference
1161
+
1162
+ SecureNow provides multiple entry points depending on your needs:
1163
+
1164
+ | Entry Point | Usage | Includes Tracing | Includes Firewall | Notes |
1165
+ |-------------|-------|-------------------|-------------------|-------|
1166
+ | `securenow/register` | `node -r securenow/register app.js` | Yes | Yes | Default -- full tracing + firewall |
1167
+ | `securenow/firewall-only` | `node -r securenow/firewall-only app.js` | No | Yes | Firewall only, no OTel overhead |
1168
+ | `securenow/nextjs` | `require('securenow/nextjs').registerSecureNow()` | Yes | Yes | Next.js instrumentation hook |
1169
+ | `securenow/nuxt` | `modules: ['securenow/nuxt']` | Yes | Yes | Nuxt 3 module |
1170
+ | `securenow/nextjs-webpack-config` | `withSecureNow(config)` | - | - | Next.js config wrapper |
1171
+ | `securenow/firewall` | `require('securenow/firewall').init({...})` | No | Yes | Programmatic firewall API |
1172
+ | `securenow/tracing` | `require('securenow/tracing')` | Yes | No | Programmatic tracing API |
1173
+
1174
+ ---
1175
+
996
1176
  ## Logging Setup
997
1177
 
998
1178
  ### Automatic Console Logging
@@ -1012,11 +1192,11 @@ console.debug('Debug info');
1012
1192
  ```
1013
1193
 
1014
1194
  **Severity mapping:**
1015
- - `console.log()` INFO
1016
- - `console.info()` INFO
1017
- - `console.warn()` WARN
1018
- - `console.error()` ERROR
1019
- - `console.debug()` DEBUG
1195
+ - `console.log()` -> INFO
1196
+ - `console.info()` -> INFO
1197
+ - `console.warn()` -> WARN
1198
+ - `console.error()` -> ERROR
1199
+ - `console.debug()` -> DEBUG
1020
1200
 
1021
1201
  **Environment variable:**
1022
1202
  ```bash
@@ -1086,11 +1266,11 @@ export SECURENOW_MAX_BODY_SIZE=10240 # 10KB (optional)
1086
1266
 
1087
1267
  ### Multipart Body Capture (v5.8.0+)
1088
1268
 
1089
- 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.
1269
+ 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.
1090
1270
 
1091
1271
  **What gets captured:**
1092
- - **Text fields** field name and value (up to 1000 chars), with sensitive fields auto-redacted
1093
- - **File fields** metadata only: field name, filename, content-type, and size in bytes
1272
+ - **Text fields** -- field name and value (up to 1000 chars), with sensitive fields auto-redacted
1273
+ - **File fields** -- metadata only: field name, filename, content-type, and size in bytes
1094
1274
 
1095
1275
  **Example trace attribute:**
1096
1276
  ```json
@@ -1159,6 +1339,12 @@ export SECURENOW_CAPTURE_BODY=1
1159
1339
  export SECURENOW_MAX_BODY_SIZE=20480
1160
1340
  export SECURENOW_SENSITIVE_FIELDS="internal_id,session_key"
1161
1341
 
1342
+ # Firewall
1343
+ export SECURENOW_API_KEY=snk_live_abc123...
1344
+ export SECURENOW_FIREWALL_TCP=1
1345
+ export SECURENOW_FIREWALL_VERSION_INTERVAL=10
1346
+ export SECURENOW_FIREWALL_SYNC_INTERVAL=300
1347
+
1162
1348
  # Environment
1163
1349
  export NODE_ENV=production
1164
1350
 
@@ -1261,13 +1447,21 @@ const enabled: boolean = isLoggingEnabled();
1261
1447
  // instrumentation.ts
1262
1448
  export async function register() {
1263
1449
  if (process.env.NEXT_RUNTIME === 'nodejs') {
1264
- process.env.SECURENOW_LOGGING_ENABLED = '1';
1265
-
1266
- await import('securenow/register');
1450
+ const { registerSecureNow } = require('securenow/nextjs');
1451
+ registerSecureNow();
1267
1452
  }
1268
1453
  }
1269
1454
  ```
1270
1455
 
1456
+ ```javascript
1457
+ // next.config.js
1458
+ const { withSecureNow } = require('securenow/nextjs-webpack-config');
1459
+
1460
+ module.exports = withSecureNow({
1461
+ reactStrictMode: true,
1462
+ });
1463
+ ```
1464
+
1271
1465
  ### NestJS with TypeScript
1272
1466
 
1273
1467
  Use `-r securenow/register -r ts-node/register` flags instead of in-code require:
@@ -1316,7 +1510,7 @@ node app.js
1316
1510
 
1317
1511
  Look for lines like:
1318
1512
  ```
1319
- [securenow] OTel SDK started http://localhost:4318/v1/traces
1513
+ [securenow] OTel SDK started -> http://localhost:4318/v1/traces
1320
1514
  ```
1321
1515
 
1322
1516
  **Check 4: Verify initialization order**
@@ -1324,15 +1518,52 @@ Look for lines like:
1324
1518
  SecureNow must be required BEFORE any other modules:
1325
1519
 
1326
1520
  ```javascript
1327
- // Correct
1521
+ // Correct
1328
1522
  require('securenow/register');
1329
1523
  const express = require('express');
1330
1524
 
1331
- // Wrong - too late!
1525
+ // Wrong -- too late!
1332
1526
  const express = require('express');
1333
1527
  require('securenow/register');
1334
1528
  ```
1335
1529
 
1530
+ ### Firewall Not Blocking IPs
1531
+
1532
+ **Check 1: Is `SECURENOW_API_KEY` set?**
1533
+
1534
+ ```bash
1535
+ echo $SECURENOW_API_KEY
1536
+ ```
1537
+
1538
+ **Check 2: Is the IP in the blocklist?**
1539
+
1540
+ ```bash
1541
+ npx securenow blocklist
1542
+ npx securenow firewall test-ip 1.2.3.4
1543
+ ```
1544
+
1545
+ **Check 3: Check startup logs for sync status**
1546
+
1547
+ You should see:
1548
+ ```
1549
+ [securenow] Firewall: ENABLED
1550
+ [securenow] Firewall: synced 142 blocked IPs
1551
+ ```
1552
+
1553
+ If you see `initial sync failed`, check the API URL and key.
1554
+
1555
+ **Check 4: Wait for propagation**
1556
+
1557
+ After blocking an IP, it takes 10-15 seconds to propagate (one version-check interval).
1558
+
1559
+ **Check 5: Are you behind a proxy?**
1560
+
1561
+ Set `SECURENOW_TRUSTED_PROXIES` to your proxy's IP so the firewall sees the real client IP.
1562
+
1563
+ **Check 6: Using PM2?**
1564
+
1565
+ Make sure `node_args: '-r securenow/register'` is in your `ecosystem.config.cjs`. Without it, PM2 restarts skip the SDK entirely.
1566
+
1336
1567
  ### Logs Not Appearing
1337
1568
 
1338
1569
  **Check 1: Is logging enabled?**
@@ -1352,7 +1583,7 @@ require('securenow/register');
1352
1583
 
1353
1584
  You should see:
1354
1585
  ```
1355
- [securenow] 📋 Logging: ENABLED http://localhost:4318/v1/logs
1586
+ [securenow] Logging: ENABLED -> http://localhost:4318/v1/logs
1356
1587
  ```
1357
1588
 
1358
1589
  **Check 4: Verify OTLP logs endpoint**
@@ -1407,22 +1638,24 @@ export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns,net
1407
1638
 
1408
1639
  ### Next.js Instrumentation Not Working
1409
1640
 
1410
- **Check 1: Verify instrumentation file location**
1641
+ **Check 1: Using `withSecureNow()`?**
1642
+
1643
+ ```javascript
1644
+ const { withSecureNow } = require('securenow/nextjs-webpack-config');
1645
+ module.exports = withSecureNow({ /* your config */ });
1646
+ ```
1647
+
1648
+ This auto-handles `serverExternalPackages` / `experimental.serverComponentsExternalPackages` and `instrumentationHook` based on your Next.js version.
1649
+
1650
+ **Check 2: Verify instrumentation file location**
1411
1651
 
1412
1652
  `instrumentation.ts` or `instrumentation.js` must be in the project root (same level as `app/` or `pages/`).
1413
1653
 
1414
- **Check 2: Enable instrumentation hook**
1654
+ **Check 3: Check for OTel MODULE_NOT_FOUND errors**
1415
1655
 
1416
- ```javascript
1417
- // next.config.js
1418
- module.exports = {
1419
- experimental: {
1420
- instrumentationHook: true,
1421
- },
1422
- };
1423
- ```
1656
+ If you see `MODULE_NOT_FOUND` for `@opentelemetry/*` packages, your `next.config.js` is missing the externalization. Use `withSecureNow()` to fix this automatically.
1424
1657
 
1425
- **Check 3: Restart dev server**
1658
+ **Check 4: Restart dev server**
1426
1659
 
1427
1660
  ```bash
1428
1661
  # Kill the server and restart
@@ -1441,12 +1674,12 @@ export SECURENOW_NO_UUID=1
1441
1674
 
1442
1675
  This uses the same service name for all workers.
1443
1676
 
1444
- **Problem: Workers not instrumented**
1677
+ **Problem: Workers not instrumented / firewall not active**
1445
1678
 
1446
1679
  **Solution: Use node_args in PM2 config**
1447
1680
 
1448
1681
  ```javascript
1449
- // ecosystem.config.js
1682
+ // ecosystem.config.cjs
1450
1683
  module.exports = {
1451
1684
  apps: [{
1452
1685
  name: 'my-app',
@@ -1456,11 +1689,14 @@ module.exports = {
1456
1689
  env: {
1457
1690
  SECURENOW_APPID: 'my-app',
1458
1691
  SECURENOW_INSTANCE: 'http://localhost:4318',
1692
+ SECURENOW_API_KEY: 'snk_live_abc123...',
1459
1693
  }
1460
1694
  }]
1461
1695
  };
1462
1696
  ```
1463
1697
 
1698
+ Without `node_args`, PM2 starts your script directly without the securenow preload, so neither tracing nor the firewall will be active.
1699
+
1464
1700
  ---
1465
1701
 
1466
1702
  ## Best Practices
@@ -1470,10 +1706,10 @@ module.exports = {
1470
1706
  Don't hardcode configuration. Use environment variables:
1471
1707
 
1472
1708
  ```javascript
1473
- // Bad
1709
+ // Bad
1474
1710
  process.env.SECURENOW_APPID = 'hardcoded-value';
1475
1711
 
1476
- // Good - use .env file or export
1712
+ // Good -- use .env file or export
1477
1713
  // .env
1478
1714
  SECURENOW_APPID=my-app
1479
1715
  SECURENOW_INSTANCE=http://localhost:4318
@@ -1484,10 +1720,10 @@ SECURENOW_INSTANCE=http://localhost:4318
1484
1720
  Pass objects to console methods for better filtering:
1485
1721
 
1486
1722
  ```javascript
1487
- // Less useful
1723
+ // Less useful
1488
1724
  console.log('User 123 logged in');
1489
1725
 
1490
- // Better - structured attributes
1726
+ // Better -- structured attributes
1491
1727
  console.log('User logged in', {
1492
1728
  userId: 123,
1493
1729
  email: 'user@example.com',
@@ -1517,13 +1753,13 @@ console.debug('Cache hit', { key: 'user:123' });
1517
1753
  Even though SecureNow automatically redacts common sensitive fields, avoid logging:
1518
1754
 
1519
1755
  ```javascript
1520
- // Bad
1756
+ // Bad
1521
1757
  console.log('Login attempt', {
1522
1758
  email: 'user@example.com',
1523
1759
  password: 'secret123', // Will be redacted, but don't log it!
1524
1760
  });
1525
1761
 
1526
- // Good
1762
+ // Good
1527
1763
  console.log('Login attempt', {
1528
1764
  email: 'user@example.com',
1529
1765
  timestamp: Date.now(),
@@ -1594,31 +1830,35 @@ No code changes needed!
1594
1830
  ## Architecture
1595
1831
 
1596
1832
  ```
1597
- ┌─────────────────────────────────┐
1598
- │ Your Application │
1599
- │ (Express/Next.js/etc) │
1600
- └───────────────┬─────────────────┘
1601
-
1602
-
1603
- ┌─────────────────────────────────┐
1604
- │ SecureNow Library │
1605
- │ - Auto-instrumentation │
1606
- - Console wrapper (optional)
1607
- │ - Body capture (optional) │
1608
- └───────────────┬─────────────────┘
1609
-
1610
-
1611
- ┌─────────────────────────────────┐
1612
- │ OpenTelemetry SDK │
1613
- │ - Trace/Log processors │
1614
- │ - OTLP exporters │
1615
- └───────────────┬─────────────────┘
1616
-
1617
-
1618
- ┌─────────────────────────────────┐
1619
- │ OTLP Collector/Backend │
1620
- │ (Your observability platform) │
1621
- └─────────────────────────────────┘
1833
+ Your Application
1834
+ (Express/Next.js/etc)
1835
+ |
1836
+ v
1837
+ +---------------------------+
1838
+ | SecureNow Library |
1839
+ | +---------------------+ |
1840
+ | | Firewall Layer | | <-- Blocks IPs before they reach your app
1841
+ | +---------------------+ |
1842
+ | | Auto-instrumentation | |
1843
+ | | Console wrapper | |
1844
+ | | Body capture | |
1845
+ | +---------------------+ |
1846
+ +---------------------------+
1847
+ |
1848
+ +---------+---------+
1849
+ | |
1850
+ v v
1851
+ +-----------+ +-----------+
1852
+ | OTel SDK | | SecureNow |
1853
+ | OTLP | | API |
1854
+ | Exporters | | (blocklist|
1855
+ +-----------+ | sync) |
1856
+ | +-----------+
1857
+ v
1858
+ +-----------+
1859
+ | Your OTLP |
1860
+ | Backend |
1861
+ +-----------+
1622
1862
  ```
1623
1863
 
1624
1864
  ---
@@ -1629,6 +1869,8 @@ No code changes needed!
1629
1869
  - **Batch export:** Traces and logs are batched before sending
1630
1870
  - **Async processing:** No blocking of application threads
1631
1871
  - **Configurable:** Disable instrumentations you don't need
1872
+ - **Firewall:** Sub-millisecond IP lookups using pre-compiled hash sets and sorted CIDR lists
1873
+ - **Smart sync:** Version-based polling with ETag/304 eliminates unnecessary data transfer
1632
1874
 
1633
1875
  ---
1634
1876
 
@@ -1636,10 +1878,12 @@ No code changes needed!
1636
1878
 
1637
1879
  - **Automatic redaction** of sensitive fields (passwords, tokens, keys)
1638
1880
  - **Configurable** sensitive field patterns
1639
- - **No data stored** locally - everything sent to your OTLP backend
1640
- - **Multi-layer firewall** blocks IPs at HTTP, TCP, OS, and cloud-edge levels
1881
+ - **No data stored** locally -- everything sent to your OTLP backend
1882
+ - **Multi-layer firewall** -- blocks IPs at HTTP, TCP, OS, and cloud-edge levels
1641
1883
  - **API keys** with granular scopes, IP allowlisting, and SHA-256 hashing
1642
- - **Open source** - audit the code yourself
1884
+ - **Allowlist support** -- trusted IPs are never blocked
1885
+ - **Fail-open by default** -- network issues never accidentally block legitimate traffic
1886
+ - **Open source** -- audit the code yourself
1643
1887
 
1644
1888
  ---
1645
1889
 
@@ -1677,4 +1921,4 @@ Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for gu
1677
1921
 
1678
1922
  ---
1679
1923
 
1680
- **Made with ❤️ for the Node.js community**
1924
+ **Made with care for the Node.js community**