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/README.md CHANGED
@@ -43,30 +43,33 @@ See the [All Frameworks Quick Start](./docs/ALL-FRAMEWORKS-QUICKSTART.md) for te
43
43
 
44
44
  ### For Next.js Applications
45
45
 
46
- **The easiest way to add observability to Next.js!**
47
-
48
46
  ```bash
49
- # Just install - setup is automatic!
47
+ # 1. Install
50
48
  npm install securenow
49
+
50
+ # 2. Auto-scaffold instrumentation files
51
+ npx securenow init --key snk_live_abc123...
51
52
  ```
52
53
 
53
- **🎉 The installer will automatically:**
54
- - Detect your Next.js project
55
- - Create `instrumentation.ts` (or `.js`)
56
- - Create `.env.local` template
54
+ This creates `instrumentation.ts` and tells you to wrap your `next.config.js`:
57
55
 
58
- **Just answer "Y" when prompted!**
56
+ ```javascript
57
+ // next.config.js
58
+ const { withSecureNow } = require('securenow/nextjs-webpack-config');
59
+
60
+ module.exports = withSecureNow({
61
+ // your existing config
62
+ });
63
+ ```
59
64
 
60
- Then configure your `.env.local`:
65
+ `withSecureNow()` auto-detects Next.js 14 vs 15 and sets the correct externalization config. No manual `serverExternalPackages` list needed.
66
+
67
+ Configure `.env.local`:
61
68
 
62
69
  ```bash
63
70
  SECURENOW_APPID=my-nextjs-app
64
71
  SECURENOW_INSTANCE=http://your-otlp-collector:4318
65
- ```
66
-
67
- **Alternative:** Use the CLI command
68
- ```bash
69
- npx securenow init
72
+ SECURENOW_API_KEY=snk_live_abc123...
70
73
  ```
71
74
 
72
75
  **Done!** See [Next.js Complete Guide](./docs/NEXTJS-GUIDE.md) for details.
@@ -95,13 +98,16 @@ SECURENOW_APPID=my-nuxt-app
95
98
  SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
96
99
  ```
97
100
 
98
- **Done!** All server-side requests are now traced automatically. See the [Nuxt 3 Complete Guide](./docs/NUXT-GUIDE.md) for details.
101
+ **Done!** All server-side requests are now traced automatically. The firewall also activates automatically when `SECURENOW_API_KEY` is set. See the [Nuxt 3 Complete Guide](./docs/NUXT-GUIDE.md) for details.
99
102
 
100
103
  ---
101
104
 
102
- ### CLI Manage Everything from the Terminal
105
+ ### CLI -- Manage Everything from the Terminal
103
106
 
104
107
  ```bash
108
+ # Set up your project (auto-detects framework, creates instrumentation files)
109
+ npx securenow init --key snk_live_abc123...
110
+
105
111
  # Authenticate
106
112
  npx securenow login
107
113
 
@@ -337,7 +343,7 @@ Most users won't need this — just add `-r securenow/register` to your existing
337
343
  | `securenow config get` | Show all config values |
338
344
  | `securenow config set <key> <value>` | Set a config value |
339
345
  | `securenow config path` | Show config file locations |
340
- | `securenow init` | Initialize instrumentation files |
346
+ | `securenow init [--key <KEY>]` | Auto-scaffold instrumentation for your framework |
341
347
  | `securenow version` | Show CLI version |
342
348
 
343
349
  ### Global Flags
package/SKILL-API.md ADDED
@@ -0,0 +1,597 @@
1
+ # SecureNow SDK — Agent Skill
2
+
3
+ Instrument any Node.js application with OpenTelemetry tracing, structured logging, request body capture, and a multi-layer IP firewall. Supports Express, Fastify, NestJS, Koa, Hapi, Next.js, Nuxt 3, Vite (browser), and raw `http.createServer` — with zero code changes for most setups.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install securenow
9
+ ```
10
+
11
+ ### Install This Skill in Cursor
12
+
13
+ Save this file as `.cursor/skills/securenow-api/SKILL.md` in your project. Your AI agent will auto-discover it whenever you ask about integrating securenow, configuring tracing, setting up the firewall, or instrumenting any framework.
14
+
15
+ ## Quick Start — Any Node.js Framework
16
+
17
+ ### 1. Set Environment Variables
18
+
19
+ ```bash
20
+ # .env or .env.local
21
+ SECURENOW_APPID=my-app
22
+ SECURENOW_INSTANCE=https://your-collector:4318
23
+ ```
24
+
25
+ ### 2. Run With Instrumentation
26
+
27
+ **Option A — CLI (recommended):**
28
+
29
+ ```bash
30
+ npx securenow run src/index.js
31
+ ```
32
+
33
+ **Option B — Node preload flag:**
34
+
35
+ ```bash
36
+ node -r securenow/register src/index.js
37
+ ```
38
+
39
+ **Option C — Auto-setup for Next.js:**
40
+
41
+ ```bash
42
+ npx securenow init --key snk_live_...
43
+ ```
44
+
45
+ That's it. Traces and logs flow to your OTLP collector. No code changes for Express, Fastify, NestJS, Koa, Hapi, and raw Node.
46
+
47
+ ### 3. Enable the Firewall (Optional)
48
+
49
+ Add one more env var to auto-activate IP blocking:
50
+
51
+ ```bash
52
+ SECURENOW_API_KEY=snk_live_abc123...
53
+ ```
54
+
55
+ The firewall syncs your blocklist and enforces it on every request — zero code changes.
56
+
57
+ ---
58
+
59
+ ## Import Map
60
+
61
+ | Import | Purpose | Type |
62
+ |--------|---------|------|
63
+ | `securenow` / `securenow/register` | Auto-register tracing + firewall (side-effect) | Preload (`-r`) |
64
+ | `securenow/tracing` | Core OTel SDK; exports `getLogger()`, `isLoggingEnabled()` | CJS |
65
+ | `securenow/nextjs` | Next.js instrumentation; exports `registerSecureNow(options?)` | CJS |
66
+ | `securenow/nextjs-webpack-config` | Next.js config wrapper; exports `withSecureNow()`, `getSecureNowWebpackConfig()`, `EXTERNAL_PACKAGES` | CJS |
67
+ | `securenow/nextjs-middleware` | Edge middleware body capture; exports `middleware()`, `redactSensitiveData()`, `DEFAULT_SENSITIVE_FIELDS` | CJS |
68
+ | `securenow/nextjs-wrapper` | Route handler wrappers; exports `withSecureNow()`, `withSecureNowAsync()`, `captureRequestBody()`, `redactSensitiveData()` | CJS |
69
+ | `securenow/nextjs-auto-capture` | Auto-patch Next request for body capture; exports `patchNextRequest()`, `safeBodyCapture()`, `redactSensitiveData()`, `isBodyCaptureEnabled()` | CJS |
70
+ | `securenow/nuxt` | Nuxt 3 module (add to `modules` array) | ESM |
71
+ | `securenow/firewall` | Standalone firewall; exports `init()`, `shutdown()`, `getStats()`, `getMatcher()`, `getAllowlistMatcher()` | CJS |
72
+ | `securenow/firewall-only` | Preload: dotenv + firewall only, no tracing | Preload (`-r`) |
73
+ | `securenow/cidr` | CIDR utilities; exports `createMatcher()`, `ipToInt()`, `parseCidr()`, `matchesCidr()` | CJS |
74
+ | `securenow/resolve-ip` | IP resolution; exports `resolveClientIp()`, `resolveSocketIp()`, `isFromTrustedProxy()` | CJS |
75
+ | `securenow/console-instrumentation` | Console→OTLP bridge; exports `originalConsole`, `restoreConsole()` | CJS |
76
+ | `securenow/web-vite` | Browser OTel (document load, fetch, XHR, user interaction); default export `startSecurenowWeb()` | ESM |
77
+ | `securenow/register-vite` | CJS bridge for Vite preload | CJS |
78
+
79
+ ---
80
+
81
+ ## Framework Integration Guides
82
+
83
+ ### Express / Fastify / NestJS / Koa / Hapi / Raw Node
84
+
85
+ No code changes. Use the preload:
86
+
87
+ ```bash
88
+ node -r securenow/register app.js
89
+ ```
90
+
91
+ Or with the CLI:
92
+
93
+ ```bash
94
+ npx securenow run app.js
95
+ ```
96
+
97
+ **PM2:**
98
+
99
+ ```javascript
100
+ // ecosystem.config.cjs
101
+ module.exports = {
102
+ apps: [{
103
+ name: 'my-app',
104
+ script: './app.js',
105
+ instances: 4,
106
+ node_args: '-r securenow/register',
107
+ env: {
108
+ SECURENOW_APPID: 'my-app',
109
+ SECURENOW_INSTANCE: 'https://your-collector:4318',
110
+ SECURENOW_NO_UUID: '1',
111
+ },
112
+ }],
113
+ };
114
+ ```
115
+
116
+ **Docker:**
117
+
118
+ ```dockerfile
119
+ ENV SECURENOW_APPID=my-app
120
+ ENV SECURENOW_INSTANCE=https://your-collector:4318
121
+ CMD ["node", "-r", "securenow/register", "app.js"]
122
+ ```
123
+
124
+ ---
125
+
126
+ ### Next.js
127
+
128
+ Three files to touch:
129
+
130
+ **1. `next.config.js`** (or `.mjs` / `.ts`):
131
+
132
+ ```javascript
133
+ const { withSecureNow } = require('securenow/nextjs-webpack-config');
134
+
135
+ module.exports = withSecureNow({
136
+ // your existing config
137
+ });
138
+ ```
139
+
140
+ `withSecureNow()` auto-detects Next.js version:
141
+ - **>=15**: sets `serverExternalPackages`
142
+ - **<15**: sets `experimental.serverComponentsExternalPackages` + `experimental.instrumentationHook` + webpack ignore rules
143
+
144
+ **2. `instrumentation.ts`** (or `.js`, can be in `src/`):
145
+
146
+ ```typescript
147
+ export async function register() {
148
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
149
+ const { registerSecureNow } = require('securenow/nextjs');
150
+ registerSecureNow();
151
+ }
152
+ }
153
+ ```
154
+
155
+ `registerSecureNow(options?)` accepts:
156
+
157
+ ```typescript
158
+ interface RegisterOptions {
159
+ serviceName?: string; // override SECURENOW_APPID
160
+ endpoint?: string; // override SECURENOW_INSTANCE
161
+ noUuid?: boolean; // override SECURENOW_NO_UUID
162
+ captureBody?: boolean; // override SECURENOW_CAPTURE_BODY
163
+ }
164
+ ```
165
+
166
+ On Vercel it uses `@vercel/otel`; self-hosted uses vanilla `@opentelemetry/sdk-node`.
167
+
168
+ **3. `.env.local`:**
169
+
170
+ ```bash
171
+ SECURENOW_APPID=my-nextjs-app
172
+ SECURENOW_INSTANCE=https://your-collector:4318
173
+ ```
174
+
175
+ #### Next.js Body Capture
176
+
177
+ **Option A — Auto-capture (recommended):**
178
+
179
+ Add to your `instrumentation.ts`:
180
+
181
+ ```typescript
182
+ export async function register() {
183
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
184
+ const { registerSecureNow } = require('securenow/nextjs');
185
+ registerSecureNow({ captureBody: true });
186
+ require('securenow/nextjs-auto-capture');
187
+ }
188
+ }
189
+ ```
190
+
191
+ **Option B — Middleware:**
192
+
193
+ ```typescript
194
+ // middleware.ts
195
+ export { middleware } from 'securenow/nextjs-middleware';
196
+ export const config = { matcher: ['/api/:path*'] };
197
+ ```
198
+
199
+ **Option C — Per-route wrapper:**
200
+
201
+ ```typescript
202
+ import { withSecureNow } from 'securenow/nextjs-wrapper';
203
+
204
+ export const POST = withSecureNow(async (req) => {
205
+ // handler
206
+ });
207
+ ```
208
+
209
+ #### Next.js with `securenow init`
210
+
211
+ ```bash
212
+ npx securenow init --key snk_live_abc123...
213
+ ```
214
+
215
+ Auto-detects Next.js, creates `instrumentation.ts`, suggests `next.config` changes, writes API key to `.env.local`.
216
+
217
+ ---
218
+
219
+ ### Nuxt 3
220
+
221
+ **`nuxt.config.ts`:**
222
+
223
+ ```typescript
224
+ export default defineNuxtConfig({
225
+ modules: ['securenow/nuxt'],
226
+ securenow: {
227
+ // optional overrides (defaults come from env vars)
228
+ },
229
+ });
230
+ ```
231
+
232
+ **`.env`:**
233
+
234
+ ```bash
235
+ SECURENOW_APPID=my-nuxt-app
236
+ SECURENOW_INSTANCE=https://your-collector:4318
237
+ ```
238
+
239
+ The Nuxt module auto-configures Nitro externals, runtime config, and a server plugin that sets up OTel tracing + logging + firewall.
240
+
241
+ ---
242
+
243
+ ### Vite / Browser
244
+
245
+ ```javascript
246
+ import startSecurenowWeb from 'securenow/web-vite';
247
+
248
+ startSecurenowWeb({
249
+ serviceName: 'my-frontend',
250
+ endpoint: 'https://your-collector:4318',
251
+ });
252
+ ```
253
+
254
+ Instruments document load, fetch, XMLHttpRequest, and user interactions with browser-side OpenTelemetry.
255
+
256
+ ---
257
+
258
+ ## Firewall — Multi-Layer IP Blocking
259
+
260
+ The firewall auto-activates when `SECURENOW_API_KEY` is set. It syncs your blocklist from the SecureNow API and enforces it across up to four layers:
261
+
262
+ ```
263
+ Layer 4: Cloud/Edge WAF → blocked at CDN (Cloudflare, AWS WAF, GCP Cloud Armor)
264
+ Layer 3: OS Firewall → kernel-level DROP (iptables/nftables)
265
+ Layer 2: TCP Socket → socket.destroy() before HTTP parsing
266
+ Layer 1: HTTP Handler → 403 JSON response (always active)
267
+ ```
268
+
269
+ ### Activate
270
+
271
+ ```bash
272
+ # .env
273
+ SECURENOW_API_KEY=snk_live_abc123... # auto-activates Layer 1
274
+ SECURENOW_FIREWALL_TCP=1 # opt-in Layer 2
275
+ SECURENOW_FIREWALL_IPTABLES=1 # opt-in Layer 3 (Linux, needs root)
276
+ SECURENOW_FIREWALL_CLOUD=cloudflare # opt-in Layer 4
277
+ ```
278
+
279
+ ### Firewall-Only Mode (No Tracing Overhead)
280
+
281
+ ```bash
282
+ node -r securenow/firewall-only app.js
283
+ ```
284
+
285
+ Loads only dotenv + firewall. No OpenTelemetry, no tracing, no external packages needed.
286
+
287
+ ### Programmatic Firewall API
288
+
289
+ ```javascript
290
+ const firewall = require('securenow/firewall');
291
+
292
+ await firewall.init({
293
+ apiKey: process.env.SECURENOW_API_KEY,
294
+ apiUrl: 'https://api.securenow.ai',
295
+ syncInterval: 300, // full sync every 5 min
296
+ versionCheckInterval: 10, // lightweight version check every 10s
297
+ failMode: 'open', // 'open' or 'closed'
298
+ statusCode: 403,
299
+ log: true,
300
+ tcp: false,
301
+ iptables: false,
302
+ cloud: null, // 'cloudflare' | 'aws' | 'gcp'
303
+ });
304
+
305
+ const stats = firewall.getStats();
306
+ const matcher = firewall.getMatcher(); // (ip) => boolean
307
+ const allowMatcher = firewall.getAllowlistMatcher();
308
+
309
+ await firewall.shutdown();
310
+ ```
311
+
312
+ ### Cloud WAF Providers
313
+
314
+ **Cloudflare:**
315
+ ```bash
316
+ SECURENOW_FIREWALL_CLOUD=cloudflare
317
+ CLOUDFLARE_API_TOKEN=your-token
318
+ CLOUDFLARE_ACCOUNT_ID=your-account-id
319
+ ```
320
+
321
+ **AWS WAF:**
322
+ ```bash
323
+ SECURENOW_FIREWALL_CLOUD=aws
324
+ AWS_WAF_IP_SET_ID=your-ip-set-id
325
+ # + standard AWS credentials (env, profile, or IAM role)
326
+ ```
327
+ Requires peer dep: `npm install @aws-sdk/client-wafv2`
328
+
329
+ **GCP Cloud Armor:**
330
+ ```bash
331
+ SECURENOW_FIREWALL_CLOUD=gcp
332
+ GCP_PROJECT_ID=your-project
333
+ GCP_SECURITY_POLICY=your-policy-name
334
+ ```
335
+ Requires peer dep: `npm install @google-cloud/compute`
336
+
337
+ **Dry-run (log only, no actual WAF changes):**
338
+ ```bash
339
+ SECURENOW_FIREWALL_CLOUD_DRY_RUN=1
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Logging
345
+
346
+ Logging is enabled by default (`SECURENOW_LOGGING_ENABLED=1`). Logs are exported to your OTLP collector alongside traces.
347
+
348
+ ### Get a Logger
349
+
350
+ ```javascript
351
+ const { getLogger } = require('securenow/tracing');
352
+
353
+ const logger = getLogger('my-module', '1.0.0');
354
+ if (logger) {
355
+ logger.emit({ body: 'User login succeeded', severityText: 'INFO', attributes: { userId: '123' } });
356
+ }
357
+ ```
358
+
359
+ ### Console Instrumentation
360
+
361
+ When tracing is active, `console.log/warn/error` are automatically patched to emit OTLP log records correlated with the active trace span. To access the original console:
362
+
363
+ ```javascript
364
+ const { originalConsole, restoreConsole } = require('securenow/console-instrumentation');
365
+ originalConsole.log('This bypasses OTLP');
366
+ restoreConsole(); // undo the patch
367
+ ```
368
+
369
+ ---
370
+
371
+ ## IP Resolution Utilities
372
+
373
+ ```javascript
374
+ const { resolveClientIp, resolveSocketIp, isFromTrustedProxy } = require('securenow/resolve-ip');
375
+
376
+ // From an HTTP request (respects X-Forwarded-For from trusted proxies)
377
+ const clientIp = resolveClientIp(req);
378
+
379
+ // Direct socket IP
380
+ const socketIp = resolveSocketIp(req);
381
+
382
+ // Check if request comes from a trusted proxy
383
+ const trusted = isFromTrustedProxy(req);
384
+ ```
385
+
386
+ ### CIDR Matching
387
+
388
+ ```javascript
389
+ const { createMatcher, ipToInt, parseCidr, matchesCidr } = require('securenow/cidr');
390
+
391
+ const isBlocked = createMatcher(['10.0.0.0/8', '192.168.1.0/24']);
392
+ isBlocked('10.0.0.5'); // true
393
+ isBlocked('8.8.8.8'); // false
394
+ ```
395
+
396
+ ---
397
+
398
+ ## Sensitive Data Redaction
399
+
400
+ Available from multiple entry points (`securenow/nextjs-middleware`, `securenow/nextjs-wrapper`, `securenow/nextjs-auto-capture`):
401
+
402
+ ```javascript
403
+ const { redactSensitiveData, DEFAULT_SENSITIVE_FIELDS } = require('securenow/nextjs-middleware');
404
+
405
+ const safe = redactSensitiveData({ username: 'alice', password: 's3cret', token: 'abc' });
406
+ // { username: 'alice', password: '[REDACTED]', token: '[REDACTED]' }
407
+ ```
408
+
409
+ **Auto-redacted fields:** `password`, `passwd`, `pwd`, `secret`, `token`, `api_key`, `apikey`, `access_token`, `auth`, `credentials`, `mysql_pwd`, `stripeToken`, `card`, `cardnumber`, `ccv`, `cvc`, `cvv`, `ssn`, `pin`.
410
+
411
+ Add custom fields via `SECURENOW_SENSITIVE_FIELDS=field1,field2`.
412
+
413
+ ---
414
+
415
+ ## Environment Variables — Complete Reference
416
+
417
+ ### Required
418
+
419
+ | Variable | Description | Default |
420
+ |----------|-------------|---------|
421
+ | `SECURENOW_APPID` | Service name / app identifier | *(auto-generated with UUID)* |
422
+ | `SECURENOW_INSTANCE` | OTLP collector base URL | `https://freetrial.securenow.ai:4318` |
423
+
424
+ ### Service Naming
425
+
426
+ | Variable | Description | Default |
427
+ |----------|-------------|---------|
428
+ | `OTEL_SERVICE_NAME` | OpenTelemetry standard; overrides `SECURENOW_APPID` | — |
429
+ | `SECURENOW_NO_UUID` | `1` to use exact app ID without UUID suffix | `0` |
430
+ | `SECURENOW_STRICT` | `1` to exit if APPID missing in PM2 cluster | `0` |
431
+
432
+ ### OTLP Connection
433
+
434
+ | Variable | Description | Default |
435
+ |----------|-------------|---------|
436
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Standard OTel endpoint; overrides `SECURENOW_INSTANCE` | — |
437
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Override traces endpoint specifically | `{instance}/v1/traces` |
438
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Override logs endpoint specifically | `{instance}/v1/logs` |
439
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Comma-separated `key=value` headers for OTLP requests | — |
440
+
441
+ ### Behavior
442
+
443
+ | Variable | Description | Default |
444
+ |----------|-------------|---------|
445
+ | `SECURENOW_LOGGING_ENABLED` | Enable OTLP log export | `1` |
446
+ | `SECURENOW_CAPTURE_BODY` | Capture HTTP request bodies | `0` |
447
+ | `SECURENOW_MAX_BODY_SIZE` | Max body size in bytes | `10240` |
448
+ | `SECURENOW_CAPTURE_MULTIPART` | Capture multipart/form-data (streaming, metadata only) | `0` |
449
+ | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated extra fields to redact | — |
450
+ | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated packages to skip (e.g. `fs,dns`) | — |
451
+ | `SECURENOW_TEST_SPAN` | `1` to emit a test span on startup | `0` |
452
+ | `SECURENOW_HIDE_BANNER` | `1` to suppress free-trial upgrade banner | `0` |
453
+ | `OTEL_LOG_LEVEL` | SDK log level: `none`, `error`, `warn`, `info`, `debug` | `none` |
454
+ | `NODE_ENV` | Sent as `deployment.environment` attribute | `production` |
455
+
456
+ ### Firewall
457
+
458
+ | Variable | Description | Default |
459
+ |----------|-------------|---------|
460
+ | `SECURENOW_API_KEY` | API key (`snk_live_...`); activates firewall when set | — |
461
+ | `SECURENOW_API_URL` | SecureNow API base URL | `https://api.securenow.ai` |
462
+ | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch (`0` to disable) | `1` |
463
+ | `SECURENOW_FIREWALL_SYNC_INTERVAL` | Full blocklist refresh interval in seconds | `300` |
464
+ | `SECURENOW_FIREWALL_FAIL_MODE` | `open` (allow all when unavailable) or `closed` | `open` |
465
+ | `SECURENOW_FIREWALL_STATUS_CODE` | HTTP status for blocked requests | `403` |
466
+ | `SECURENOW_FIREWALL_LOG` | Log blocked requests | `1` |
467
+ | `SECURENOW_FIREWALL_TCP` | Enable Layer 2 TCP blocking | `0` |
468
+ | `SECURENOW_FIREWALL_IPTABLES` | Enable Layer 3 iptables/nftables | `0` |
469
+ | `SECURENOW_FIREWALL_CLOUD` | Cloud WAF: `cloudflare`, `aws`, or `gcp` | — |
470
+ | `SECURENOW_FIREWALL_CLOUD_DRY_RUN` | `1` to log cloud pushes without applying | `0` |
471
+ | `SECURENOW_TRUSTED_PROXIES` | Comma-separated trusted proxy IPs | — |
472
+
473
+ ### Cloud WAF Provider Variables
474
+
475
+ | Provider | Variables |
476
+ |----------|-----------|
477
+ | Cloudflare | `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` |
478
+ | AWS WAF | `AWS_WAF_IP_SET_ID`, `AWS_WAF_IP_SET_NAME`, `AWS_WAF_SCOPE` |
479
+ | GCP | `GCP_PROJECT_ID`, `GCP_SECURITY_POLICY` |
480
+
481
+ ### Priority Order
482
+
483
+ **Service name:** `OTEL_SERVICE_NAME` > `SECURENOW_APPID` > auto-generated
484
+
485
+ **Endpoint:** `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` > `OTEL_EXPORTER_OTLP_ENDPOINT` > `SECURENOW_INSTANCE` > `https://freetrial.securenow.ai:4318`
486
+
487
+ ---
488
+
489
+ ## Recipes for Agentic AI
490
+
491
+ ### Add Observability to an Existing Express App
492
+
493
+ ```bash
494
+ npm install securenow
495
+ ```
496
+
497
+ Create `.env`:
498
+ ```
499
+ SECURENOW_APPID=my-express-api
500
+ SECURENOW_INSTANCE=https://your-collector:4318
501
+ SECURENOW_LOGGING_ENABLED=1
502
+ SECURENOW_CAPTURE_BODY=1
503
+ ```
504
+
505
+ Update `package.json`:
506
+ ```json
507
+ { "scripts": { "start": "node -r securenow/register src/index.js" } }
508
+ ```
509
+
510
+ No code changes to the application needed.
511
+
512
+ ### Add Observability + Firewall to a Next.js App
513
+
514
+ ```bash
515
+ npm install securenow
516
+ npx securenow init --key snk_live_abc123...
517
+ ```
518
+
519
+ The `init` command creates `instrumentation.ts` and suggests `next.config` changes. Then set env vars in `.env.local`:
520
+
521
+ ```
522
+ SECURENOW_APPID=my-nextjs-app
523
+ SECURENOW_INSTANCE=https://your-collector:4318
524
+ SECURENOW_API_KEY=snk_live_abc123...
525
+ SECURENOW_CAPTURE_BODY=1
526
+ ```
527
+
528
+ ### Enable Firewall With Zero Tracing Overhead
529
+
530
+ For apps that only need IP blocking:
531
+
532
+ ```bash
533
+ node -r securenow/firewall-only app.js
534
+ ```
535
+
536
+ Set `SECURENOW_API_KEY` in the environment. No other configuration needed.
537
+
538
+ ### Production Hardened Configuration
539
+
540
+ ```bash
541
+ SECURENOW_APPID=prod-api
542
+ SECURENOW_INSTANCE=https://collector.prod.internal:4318
543
+ SECURENOW_NO_UUID=1
544
+ SECURENOW_STRICT=1
545
+ SECURENOW_LOGGING_ENABLED=1
546
+ SECURENOW_CAPTURE_BODY=0
547
+ SECURENOW_API_KEY=snk_live_abc123...
548
+ SECURENOW_FIREWALL_TCP=1
549
+ SECURENOW_FIREWALL_SYNC_INTERVAL=30
550
+ SECURENOW_FIREWALL_FAIL_MODE=open
551
+ OTEL_LOG_LEVEL=error
552
+ NODE_ENV=production
553
+ ```
554
+
555
+ ### Instrument a Docker Container
556
+
557
+ ```dockerfile
558
+ FROM node:20-slim
559
+ WORKDIR /app
560
+ COPY package*.json ./
561
+ RUN npm ci --omit=dev
562
+ COPY . .
563
+
564
+ ENV SECURENOW_APPID=my-service
565
+ ENV SECURENOW_INSTANCE=http://otel-collector:4318
566
+ ENV SECURENOW_NO_UUID=1
567
+ ENV SECURENOW_API_KEY=snk_live_abc123...
568
+
569
+ CMD ["node", "-r", "securenow/register", "src/index.js"]
570
+ ```
571
+
572
+ ### Kubernetes with Separate Trace/Log Collectors
573
+
574
+ ```bash
575
+ SECURENOW_APPID=k8s-service
576
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://tempo:4318/v1/traces
577
+ OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://loki:4318/v1/logs
578
+ SECURENOW_LOGGING_ENABLED=1
579
+ SECURENOW_NO_UUID=1
580
+ ```
581
+
582
+ ---
583
+
584
+ ## Verification
585
+
586
+ On startup, securenow logs its configuration:
587
+
588
+ ```
589
+ [securenow] pid=12345 SECURENOW_APPID="my-app" → service.name=my-app
590
+ [securenow] OTel SDK started → https://collector:4318/v1/traces
591
+ [securenow] Logging: ENABLED → https://collector:4318/v1/logs
592
+ [securenow] Request body capture: ENABLED (max: 10240 bytes)
593
+ [securenow] Firewall: ENABLED
594
+ [securenow] Firewall: synced 142 blocked IPs
595
+ ```
596
+
597
+ Use `OTEL_LOG_LEVEL=debug` and `SECURENOW_TEST_SPAN=1` to troubleshoot connectivity issues.