securenow 7.5.1 → 7.6.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 (50) hide show
  1. package/CONSUMING-APPS-GUIDE.md +2 -0
  2. package/NPM_README.md +201 -237
  3. package/README.md +73 -26
  4. package/SKILL-API.md +205 -205
  5. package/SKILL-CLI.md +71 -64
  6. package/app-config.js +479 -83
  7. package/cli/apiKey.js +1 -1
  8. package/cli/apps.js +1 -1
  9. package/cli/config.js +31 -12
  10. package/cli/credentials.js +88 -0
  11. package/cli/diagnostics.js +68 -104
  12. package/cli/firewall.js +29 -14
  13. package/cli/init.js +211 -212
  14. package/cli/monitor.js +107 -43
  15. package/cli/security.js +24 -12
  16. package/cli/utils.js +2 -1
  17. package/cli.js +72 -40
  18. package/console-instrumentation.js +1 -1
  19. package/docs/ENVIRONMENT-VARIABLES.md +137 -863
  20. package/docs/ENVIRONMENTS.md +60 -0
  21. package/docs/EXPRESS-SETUP-GUIDE.md +3 -0
  22. package/docs/FIREWALL-GUIDE.md +3 -0
  23. package/docs/INDEX.md +6 -8
  24. package/docs/LOGGING-GUIDE.md +3 -0
  25. package/docs/MCP-GUIDE.md +8 -0
  26. package/docs/NEXTJS-GUIDE.md +3 -0
  27. package/docs/NEXTJS-QUICKSTART.md +22 -16
  28. package/docs/NUXT-GUIDE.md +3 -0
  29. package/docs/QUICKSTART-BODY-CAPTURE.md +3 -0
  30. package/docs/REQUEST-BODY-CAPTURE.md +3 -0
  31. package/firewall-cloud.js +10 -10
  32. package/firewall-only.js +25 -23
  33. package/firewall.js +47 -29
  34. package/free-trial-banner.js +1 -1
  35. package/mcp/catalog.js +104 -17
  36. package/nextjs-auto-capture.d.ts +7 -4
  37. package/nextjs-auto-capture.js +7 -7
  38. package/nextjs-middleware.js +4 -3
  39. package/nextjs-wrapper.js +6 -6
  40. package/nextjs.d.ts +36 -25
  41. package/nextjs.js +48 -55
  42. package/nuxt-server-plugin.mjs +35 -51
  43. package/nuxt.d.ts +29 -23
  44. package/package.json +1 -1
  45. package/postinstall.js +27 -61
  46. package/register.d.ts +19 -33
  47. package/register.js +8 -8
  48. package/resolve-ip.js +4 -5
  49. package/tracing.d.ts +21 -19
  50. package/tracing.js +34 -42
package/SKILL-API.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
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
4
 
5
- **CLI parity:** every capability exposed below (redaction, CIDR matching, log/span emission, firewall preload, config inspection) has an equivalent `securenow` CLI command. See [SKILL-CLI.md](./SKILL-CLI.md) for the terminal surface.
6
-
7
- **MCP parity (v7.5+):** `npx securenow mcp` starts a local stdio MCP server for Codex, Claude, and other MCP clients. It reuses the same `.securenow/credentials.json` file as the CLI/SDK and exposes SecureNow tools, bundled docs resources, and setup prompts to agents.
5
+ **CLI parity:** every capability exposed below (redaction, CIDR matching, log/span emission, firewall preload, config inspection) has an equivalent `securenow` CLI command. See [SKILL-CLI.md](./SKILL-CLI.md) for the terminal surface.
6
+
7
+ **MCP parity (v7.5+):** `npx securenow mcp` starts a local stdio MCP server for Codex, Claude, and other MCP clients. It reuses the same `.securenow/credentials.json` file as the CLI/SDK and exposes SecureNow tools, bundled docs resources, and setup prompts to agents.
8
8
 
9
9
  ## Installation
10
10
 
11
11
  ```bash
12
- npm install securenow
12
+ npm install securenow@latest
13
13
  ```
14
14
 
15
15
  ### Install This Skill in Cursor
@@ -18,14 +18,18 @@ Save this file as `.cursor/skills/securenow-api/SKILL.md` in your project. Your
18
18
 
19
19
  ## Quick Start — Any Node.js Framework
20
20
 
21
- ### 1. Set Environment Variables
21
+ ### 1. Install, Login, And Init
22
22
 
23
23
  ```bash
24
- # .env or .env.local
25
- SECURENOW_APPID=my-app
26
- SECURENOW_INSTANCE=https://your-collector:4318
24
+ npm install securenow@latest
25
+ node -p "require('./node_modules/securenow/package.json').version"
26
+ npx securenow version
27
+ npx securenow login
28
+ npx securenow init
27
29
  ```
28
30
 
31
+ Use `securenow@7.5.1` or newer. Start authentication with `npx securenow login`; do not manually open auth URLs, because the CLI generates the callback/state values. The login flow lets the user pick or create an app, enables the app firewall by default, writes `.securenow/credentials.json`, and `init` scaffolds the framework integration.
32
+
29
33
  ### 2. Run With Instrumentation
30
34
 
31
35
  **Option A — CLI (recommended):**
@@ -43,24 +47,24 @@ node -r securenow/register src/index.js
43
47
  **Option C — Auto-setup for Next.js:**
44
48
 
45
49
  ```bash
46
- npx securenow init --key snk_live_...
50
+ npx securenow init
47
51
  ```
48
52
 
49
- That's it. Traces and logs flow to your OTLP collector. No code changes for Express, Fastify, NestJS, Koa, Hapi, and raw Node.
53
+ That's it. Traces, logs, request body capture, multipart metadata capture, and firewall enforcement are on by default. No code changes for Express, Fastify, NestJS, Koa, Hapi, and raw Node.
50
54
 
51
- ### 3. Firewall Is Enabled by Default
55
+ ### 3. Firewall Is Enabled by Default
52
56
 
53
- Since v7.4.0, the browser login flow connects the firewall automatically after
54
- the user picks or creates an app. The firewall key lives in your credentials
55
- file — no env var required:
57
+ Since v7.5.1, the browser login flow connects the firewall automatically after
58
+ the user picks or creates an app. The firewall key lives in your credentials
59
+ file — no env var required:
56
60
 
57
61
  ```bash
58
- npx securenow login # pick/create app; firewall key is minted automatically
59
- # or, if you already have one:
60
- npx securenow api-key set snk_live_abc123...
62
+ npx securenow login # pick/create app; firewall key is minted automatically
63
+ # or, if you already have one:
64
+ npx securenow api-key set snk_live_abc123...
61
65
  ```
62
66
 
63
- Both paths write the key to `.securenow/credentials.json` (auto-gitignored) and the firewall activates on next start. Setting `SECURENOW_API_KEY=snk_live_...` in the environment still works and takes precedence.
67
+ Both paths write the key to `.securenow/credentials.json` (auto-gitignored) and the firewall activates on next start. For production, run `npx securenow credentials runtime --env production` and mount/copy the tokenless file as `.securenow/credentials.json`.
64
68
 
65
69
  The firewall syncs your blocklist and enforces it on every request — zero code changes.
66
70
 
@@ -110,77 +114,84 @@ npx securenow run app.js
110
114
  // ecosystem.config.cjs
111
115
  module.exports = {
112
116
  apps: [{
113
- name: 'my-app',
114
- script: './app.js',
115
- instances: 4,
116
- node_args: '-r securenow/register',
117
- env: {
118
- SECURENOW_APPID: 'my-app',
119
- SECURENOW_INSTANCE: 'https://your-collector:4318',
120
- SECURENOW_NO_UUID: '1',
121
- },
122
- }],
123
- };
124
- ```
117
+ name: 'my-app',
118
+ script: './app.js',
119
+ instances: 4,
120
+ node_args: '-r securenow/register',
121
+ // Reads .securenow/credentials.json from the project root.
122
+ }],
123
+ };
124
+ ```
125
125
 
126
126
  **Docker:**
127
127
 
128
- ```dockerfile
129
- ENV SECURENOW_APPID=my-app
130
- ENV SECURENOW_INSTANCE=https://your-collector:4318
131
- CMD ["node", "-r", "securenow/register", "app.js"]
132
- ```
128
+ ```dockerfile
129
+ COPY .securenow/credentials.json ./.securenow/credentials.json
130
+ CMD ["node", "-r", "securenow/register", "app.js"]
131
+ ```
133
132
 
134
133
  ---
135
134
 
136
- ### Next.js
137
-
138
- Three files to touch:
139
-
140
- **1. `next.config.js`** (or `.mjs` / `.ts`):
141
-
142
- ```javascript
143
- const { withSecureNow } = require('securenow/nextjs-webpack-config');
144
-
145
- module.exports = withSecureNow({
146
- // your existing config
147
- });
148
- ```
149
-
150
- `withSecureNow()` auto-detects Next.js version:
151
- - **>=15**: sets `serverExternalPackages`
152
- - **<15**: sets `experimental.serverComponentsExternalPackages` + `experimental.instrumentationHook` + webpack ignore rules
153
-
154
- **2. `instrumentation.ts`** (or `.js`, can be in `src/`):
155
-
156
- ```typescript
157
- export async function register() {
158
- if (process.env.NEXT_RUNTIME === 'nodejs') {
159
- const { registerSecureNow } = require('securenow/nextjs');
160
- registerSecureNow();
161
- }
162
- }
163
- ```
135
+ ### Next.js
136
+
137
+ Run `npx securenow init` first. It creates the straightforward integration below when files are missing, and prints a Codex/Claude-ready merge prompt when existing files need careful edits.
138
+
139
+ **1. `next.config.js`** (or `.mjs` / `.ts`):
140
+
141
+ ```javascript
142
+ const nextConfig = {
143
+ serverExternalPackages: ['securenow'],
144
+ };
145
+
146
+ export default nextConfig;
147
+ ```
148
+
149
+ For Next.js < 15, add `securenow` to `experimental.serverComponentsExternalPackages` instead.
150
+
151
+ **2. `instrumentation.ts`** (or `.js`, can be in `src/`):
152
+
153
+ ```typescript
154
+ export async function register() {
155
+ if (process.env.NEXT_RUNTIME !== 'nodejs') return;
156
+
157
+ const securenowNext = await import(/* webpackIgnore: true */ 'securenow/nextjs');
158
+ const registerSecureNow = securenowNext.registerSecureNow || securenowNext.default?.registerSecureNow;
159
+ registerSecureNow({ captureBody: true });
160
+ await import(/* webpackIgnore: true */ 'securenow/nextjs-auto-capture');
161
+ }
162
+ ```
164
163
 
165
164
  `registerSecureNow(options?)` accepts:
166
165
 
167
- ```typescript
168
- interface RegisterOptions {
169
- serviceName?: string; // override SECURENOW_APPID
170
- endpoint?: string; // override SECURENOW_INSTANCE
171
- noUuid?: boolean; // override SECURENOW_NO_UUID
172
- captureBody?: boolean; // override SECURENOW_CAPTURE_BODY
173
- }
174
- ```
175
-
176
- On Vercel it uses `@vercel/otel`; self-hosted uses vanilla `@opentelemetry/sdk-node`.
177
-
178
- **3. `.env.local`:**
179
-
180
- ```bash
181
- SECURENOW_APPID=my-nextjs-app
182
- SECURENOW_INSTANCE=https://your-collector:4318
183
- ```
166
+ ```typescript
167
+ interface RegisterOptions {
168
+ serviceName?: string; // override credentials app key/name
169
+ endpoint?: string; // override credentials app instance
170
+ noUuid?: boolean; // override credentials config.runtime.noUuid
171
+ captureBody?: boolean; // override credentials config.capture.body
172
+ }
173
+ ```
174
+
175
+ On Vercel it uses `@vercel/otel`; self-hosted uses vanilla `@opentelemetry/sdk-node`.
176
+
177
+ **3. Credentials:**
178
+
179
+ ```json
180
+ {
181
+ "app": {
182
+ "key": "<uuid>",
183
+ "name": "my-nextjs-app",
184
+ "instance": "https://freetrial.securenow.ai:4318"
185
+ },
186
+ "config": {
187
+ "logging": { "enabled": true },
188
+ "capture": { "body": true, "multipart": true, "maxBodySize": 10240 },
189
+ "firewall": { "enabled": true }
190
+ }
191
+ }
192
+ ```
193
+
194
+ Local development and production do not need `.env.local`; `npx securenow login` and `npx securenow init` keep `.securenow/credentials.json` filled and gitignored. For production, run `npx securenow credentials runtime --env production` and mount/copy the generated JSON as `.securenow/credentials.json`.
184
195
 
185
196
  #### Next.js Body Capture
186
197
 
@@ -188,15 +199,16 @@ SECURENOW_INSTANCE=https://your-collector:4318
188
199
 
189
200
  Add to your `instrumentation.ts`:
190
201
 
191
- ```typescript
192
- export async function register() {
193
- if (process.env.NEXT_RUNTIME === 'nodejs') {
194
- const { registerSecureNow } = require('securenow/nextjs');
195
- registerSecureNow({ captureBody: true });
196
- require('securenow/nextjs-auto-capture');
197
- }
198
- }
199
- ```
202
+ ```typescript
203
+ export async function register() {
204
+ if (process.env.NEXT_RUNTIME !== 'nodejs') return;
205
+
206
+ const securenowNext = await import(/* webpackIgnore: true */ 'securenow/nextjs');
207
+ const registerSecureNow = securenowNext.registerSecureNow || securenowNext.default?.registerSecureNow;
208
+ registerSecureNow({ captureBody: true });
209
+ await import(/* webpackIgnore: true */ 'securenow/nextjs-auto-capture');
210
+ }
211
+ ```
200
212
 
201
213
  **Option B — Middleware:**
202
214
 
@@ -219,10 +231,11 @@ export const POST = withSecureNow(async (req) => {
219
231
  #### Next.js with `securenow init`
220
232
 
221
233
  ```bash
222
- npx securenow init --key snk_live_abc123...
234
+ npx securenow login
235
+ npx securenow init
223
236
  ```
224
237
 
225
- Auto-detects Next.js, creates `instrumentation.ts`, suggests `next.config` changes, writes API key to `.env.local`.
238
+ Auto-detects Next.js, creates `instrumentation.ts`, adds `serverExternalPackages: ['securenow']` when safe, and reuses the app, instance, firewall key, and secure defaults in `.securenow/credentials.json`. If files already exist, it prints an agent-ready prompt with the exact edits to propose.
226
239
 
227
240
  ---
228
241
 
@@ -232,21 +245,14 @@ Auto-detects Next.js, creates `instrumentation.ts`, suggests `next.config` chang
232
245
 
233
246
  ```typescript
234
247
  export default defineNuxtConfig({
235
- modules: ['securenow/nuxt'],
236
- securenow: {
237
- // optional overrides (defaults come from env vars)
238
- },
239
- });
240
- ```
241
-
242
- **`.env`:**
243
-
244
- ```bash
245
- SECURENOW_APPID=my-nuxt-app
246
- SECURENOW_INSTANCE=https://your-collector:4318
247
- ```
248
-
249
- The Nuxt module auto-configures Nitro externals, runtime config, and a server plugin that sets up OTel tracing + logging + firewall.
248
+ modules: ['securenow/nuxt'],
249
+ securenow: {
250
+ // optional overrides (defaults come from .securenow/credentials.json)
251
+ },
252
+ });
253
+ ```
254
+
255
+ The Nuxt module auto-configures Nitro externals, runtime config, and a server plugin that sets up OTel tracing + logging + firewall. Local and production app identity, firewall key, and secure defaults come from `.securenow/credentials.json`.
250
256
 
251
257
  ---
252
258
 
@@ -267,7 +273,7 @@ Instruments document load, fetch, XMLHttpRequest, and user interactions with bro
267
273
 
268
274
  ## Firewall — Multi-Layer IP Blocking
269
275
 
270
- The firewall auto-activates once an API key is resolvable and the app firewall toggle is on. Since **v7.4.0**, `npx securenow login` enables the selected app firewall and writes the key to `.securenow/credentials.json`; `securenow api-key set` can still write/rotate the key later. The `SECURENOW_API_KEY` env var is optional. Resolution order: env (must start with `snk_live_`) project `./.securenow/credentials.json` global `~/.securenow/credentials.json`.
276
+ The firewall auto-activates once an API key is resolvable and the app firewall toggle is on. Since **v7.5.1**, `npx securenow login` enables the selected app firewall by default and writes the scoped key to `.securenow/credentials.json`; `securenow api-key set` can still write/rotate the key later. Production should use the tokenless file generated by `securenow credentials runtime --env production`. Resolution order: project `./.securenow/credentials.json` -> global `~/.securenow/credentials.json`; legacy env vars are fallback-only for existing deployments.
271
277
 
272
278
  ```
273
279
  Layer 4: Cloud/Edge WAF → blocked at CDN (Cloudflare, AWS WAF, GCP Cloud Armor)
@@ -279,16 +285,13 @@ Layer 1: HTTP Handler → 403 JSON response (always active)
279
285
  ### Activate
280
286
 
281
287
  ```bash
282
- # Zero-config (recommended) — writes the key to .securenow/credentials.json
283
- npx securenow login # pick/create app; firewall connects automatically
288
+ # Zero-config (recommended) — writes the key to .securenow/credentials.json
289
+ npx securenow login # pick/create app; firewall connects automatically
284
290
  # or, if you already have a key:
285
291
  npx securenow api-key set snk_live_abc123...
286
292
 
287
- # Optional .env overrides for the stronger layers
288
- SECURENOW_FIREWALL_TCP=1 # opt-in Layer 2
289
- SECURENOW_FIREWALL_IPTABLES=1 # opt-in Layer 3 (Linux, needs root)
290
- SECURENOW_FIREWALL_CLOUD=cloudflare # opt-in Layer 4
291
- # SECURENOW_API_KEY=snk_live_... # still honored; only wins if it starts with snk_live_
293
+ # Production runtime file:
294
+ npx securenow credentials runtime --env production
292
295
  ```
293
296
 
294
297
  ### Firewall-Only Mode (No Tracing Overhead)
@@ -304,13 +307,14 @@ Loads only dotenv + firewall. No OpenTelemetry, no tracing, no external packages
304
307
 
305
308
  ### Programmatic Firewall API
306
309
 
307
- ```javascript
308
- const firewall = require('securenow/firewall');
309
-
310
- await firewall.init({
311
- apiKey: process.env.SECURENOW_API_KEY,
312
- apiUrl: 'https://api.securenow.ai',
313
- syncInterval: 300, // full sync every 5 min
310
+ ```javascript
311
+ const firewall = require('securenow/firewall');
312
+ const appConfig = require('securenow/app-config');
313
+
314
+ await firewall.init({
315
+ ...appConfig.resolveFirewallOptions(),
316
+ apiUrl: 'https://api.securenow.ai',
317
+ syncInterval: 300, // full sync every 5 min
314
318
  versionCheckInterval: 10, // lightweight version check every 10s
315
319
  failMode: 'open', // 'open' or 'closed'
316
320
  statusCode: 403,
@@ -440,7 +444,7 @@ const safe = redactSensitiveData({ username: 'alice', password: 's3cret', token:
440
444
 
441
445
  **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`.
442
446
 
443
- Add custom fields via `SECURENOW_SENSITIVE_FIELDS=field1,field2`.
447
+ Add custom fields via `config.capture.sensitiveFields` in `.securenow/credentials.json`; `SECURENOW_SENSITIVE_FIELDS=field1,field2` is a legacy fallback for existing installs.
444
448
 
445
449
  **CLI equivalent** (for piping, scripts, debugging what a payload looks like post-redaction):
446
450
 
@@ -451,20 +455,22 @@ securenow redact @request.json --fields internal_id,sessionHash
451
455
 
452
456
  ---
453
457
 
454
- ## Environment Variables — Complete Reference
455
-
456
- ### Required
457
-
458
- | Variable | Description | Default |
459
- |----------|-------------|---------|
460
- | `SECURENOW_APPID` | Service name / app identifier | *(auto-generated with UUID)* |
461
- | `SECURENOW_INSTANCE` | OTLP collector base URL | `https://freetrial.securenow.ai:4318` |
458
+ ## Credentials Configuration
459
+
460
+ Local development and production use `.securenow/credentials.json`. Every setting below lives under `app` or `config`; `npx securenow credentials runtime --env production` creates a tokenless production file with the same structure. Environment variables are legacy fallbacks only.
461
+
462
+ ### App Identity
463
+
464
+ | Variable | Description | Default |
465
+ |----------|-------------|---------|
466
+ | `SECURENOW_APPID` | Legacy fallback for `app.key` / service name | from credentials file, then package name |
467
+ | `SECURENOW_INSTANCE` | Legacy fallback for `app.instance` / OTLP collector base URL | from credentials file, then `https://freetrial.securenow.ai:4318` |
462
468
 
463
469
  ### Service Naming
464
470
 
465
471
  | Variable | Description | Default |
466
472
  |----------|-------------|---------|
467
- | `OTEL_SERVICE_NAME` | OpenTelemetry standard; overrides `SECURENOW_APPID` | — |
473
+ | `OTEL_SERVICE_NAME` | Legacy fallback for `app.name` | — |
468
474
  | `SECURENOW_NO_UUID` | `1` to use exact app ID without UUID suffix | `0` |
469
475
  | `SECURENOW_STRICT` | `1` to exit if APPID missing in PM2 cluster | `0` |
470
476
 
@@ -472,9 +478,9 @@ securenow redact @request.json --fields internal_id,sessionHash
472
478
 
473
479
  | Variable | Description | Default |
474
480
  |----------|-------------|---------|
475
- | `OTEL_EXPORTER_OTLP_ENDPOINT` | Standard OTel endpoint; overrides `SECURENOW_INSTANCE` | — |
476
- | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Override traces endpoint specifically | `{instance}/v1/traces` |
477
- | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Override logs endpoint specifically | `{instance}/v1/logs` |
481
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Legacy fallback for `config.otel.endpoint` | — |
482
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Legacy fallback for `config.otel.tracesEndpoint` | `{instance}/v1/traces` |
483
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Legacy fallback for `config.otel.logsEndpoint` | `{instance}/v1/logs` |
478
484
  | `OTEL_EXPORTER_OTLP_HEADERS` | Comma-separated `key=value` headers for OTLP requests | — |
479
485
 
480
486
  ### Behavior
@@ -482,21 +488,21 @@ securenow redact @request.json --fields internal_id,sessionHash
482
488
  | Variable | Description | Default |
483
489
  |----------|-------------|---------|
484
490
  | `SECURENOW_LOGGING_ENABLED` | Enable OTLP log export | `1` |
485
- | `SECURENOW_CAPTURE_BODY` | Capture HTTP request bodies | `1` |
491
+ | `SECURENOW_CAPTURE_BODY` | Capture HTTP request bodies | `1` |
486
492
  | `SECURENOW_MAX_BODY_SIZE` | Max body size in bytes | `10240` |
487
- | `SECURENOW_CAPTURE_MULTIPART` | Capture multipart/form-data (streaming, metadata only) | `1` |
493
+ | `SECURENOW_CAPTURE_MULTIPART` | Capture multipart/form-data (streaming, metadata only) | `1` |
488
494
  | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated extra fields to redact | — |
489
495
  | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated packages to skip (e.g. `fs,dns`) | — |
490
496
  | `SECURENOW_TEST_SPAN` | `1` to emit a test span on startup | `0` |
491
497
  | `SECURENOW_HIDE_BANNER` | `1` to suppress free-trial upgrade banner | `0` |
492
498
  | `OTEL_LOG_LEVEL` | SDK log level: `none`, `error`, `warn`, `info`, `debug` | `none` |
493
- | `NODE_ENV` | Sent as `deployment.environment` attribute | `production` |
499
+ | `SECURENOW_ENVIRONMENT` / `SECURENOW_DEPLOYMENT_ENVIRONMENT` / `NODE_ENV` | Legacy fallback for `config.runtime.deploymentEnvironment` | `production` |
494
500
 
495
501
  ### Firewall
496
502
 
497
503
  | Variable | Description | Default |
498
504
  |----------|-------------|---------|
499
- | `SECURENOW_API_KEY` | API key (`snk_live_...`); activates firewall when set. Since v7.1.0, this is also read from `.securenow/credentials.json` — env var only wins when it starts with `snk_live_`. | |
505
+ | `SECURENOW_API_KEY` | Legacy env override for the `apiKey` field (`snk_live_...`). Since v7.5.1, login writes the scoped firewall key to `.securenow/credentials.json`. | - |
500
506
  | `SECURENOW_API_URL` | SecureNow API base URL | `https://api.securenow.ai` |
501
507
  | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch (`0` to disable) | `1` |
502
508
  | `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between lightweight version checks | `10` |
@@ -522,9 +528,9 @@ securenow redact @request.json --fields internal_id,sessionHash
522
528
 
523
529
  ### Priority Order
524
530
 
525
- **Service name:** `OTEL_SERVICE_NAME` > `SECURENOW_APPID` > auto-generated
526
-
527
- **Endpoint:** `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` > `OTEL_EXPORTER_OTLP_ENDPOINT` > `SECURENOW_INSTANCE` > `https://freetrial.securenow.ai:4318`
531
+ **Service name:** credentials `app.key` > credentials `app.name` > legacy env fallback > package name
532
+
533
+ **Endpoint:** credentials `config.otel.tracesEndpoint` / `config.otel.endpoint` / `app.instance` > legacy env fallback > `https://freetrial.securenow.ai:4318`
528
534
 
529
535
  ---
530
536
 
@@ -533,16 +539,11 @@ securenow redact @request.json --fields internal_id,sessionHash
533
539
  ### Add Observability to an Existing Express App
534
540
 
535
541
  ```bash
536
- npm install securenow
542
+ npm install securenow@latest
543
+ npx securenow login
537
544
  ```
538
545
 
539
- Create `.env`:
540
- ```
541
- SECURENOW_APPID=my-express-api
542
- SECURENOW_INSTANCE=https://your-collector:4318
543
- SECURENOW_LOGGING_ENABLED=1
544
- SECURENOW_CAPTURE_BODY=1
545
- ```
546
+ No `.env` is needed. `npx securenow login` writes app identity, collector URL, firewall key, and secure defaults to `.securenow/credentials.json`; `npx securenow init` makes sure the file has explanations and is gitignored.
546
547
 
547
548
  Update `package.json`:
548
549
  ```json
@@ -554,17 +555,11 @@ No code changes to the application needed.
554
555
  ### Add Observability + Firewall to a Next.js App
555
556
 
556
557
  ```bash
557
- npm install securenow
558
+ npm install securenow@latest
558
559
  npx securenow login # pick/create app; firewall key is minted automatically
559
560
  ```
560
561
 
561
- `securenow login` enables the selected app's firewall toggle and writes session, app, and firewall key to `.securenow/credentials.json` (auto-gitignored). Traces, logs, request body capture, multipart metadata capture, and firewall enforcement are enabled by default. The `init` command still works for manual setup — it creates `instrumentation.ts` and suggests `next.config` changes. Most users only need this `.env.local`:
562
-
563
- ```
564
- SECURENOW_APPID=my-nextjs-app
565
- SECURENOW_INSTANCE=https://your-collector:4318
566
- # SECURENOW_API_KEY=snk_live_... (otherwise lives in .securenow/credentials.json)
567
- ```
562
+ `securenow login` enables the selected app's firewall toggle and writes session, app, and firewall key to `.securenow/credentials.json` (auto-gitignored). Traces, logs, request body capture, multipart metadata capture, and firewall enforcement are enabled by default. Then run `npx securenow init`; it creates `instrumentation.ts`, patches `next.config.*` when safe, or prints exact Codex/Claude merge instructions for existing files.
568
563
 
569
564
  ### Enable Firewall With Zero Tracing Overhead
570
565
 
@@ -574,24 +569,27 @@ For apps that only need IP blocking:
574
569
  node -r securenow/firewall-only app.js
575
570
  ```
576
571
 
577
- Make sure an API key is resolvable either run `npx securenow login` / `securenow api-key set snk_live_...` (writes the creds file), or set `SECURENOW_API_KEY` in the environment. No other configuration needed.
578
-
579
- ### Production Hardened Configuration
572
+ Make sure an API key is resolvable by running `npx securenow login` first. If you already have a key, `securenow api-key set snk_live_...` writes the creds file. For production, run `npx securenow credentials runtime --env production` and mount/copy it as `.securenow/credentials.json`.
580
573
 
581
- ```bash
582
- SECURENOW_APPID=prod-api
583
- SECURENOW_INSTANCE=https://collector.prod.internal:4318
584
- SECURENOW_NO_UUID=1
585
- SECURENOW_STRICT=1
586
- SECURENOW_LOGGING_ENABLED=1
587
- SECURENOW_CAPTURE_BODY=0
588
- SECURENOW_API_KEY=snk_live_abc123...
589
- SECURENOW_FIREWALL_TCP=1
590
- SECURENOW_FIREWALL_SYNC_INTERVAL=30
591
- SECURENOW_FIREWALL_FAIL_MODE=open
592
- OTEL_LOG_LEVEL=error
593
- NODE_ENV=production
594
- ```
574
+ ### Production Hardened Configuration
575
+
576
+ ```json
577
+ {
578
+ "apiKey": "snk_live_...",
579
+ "app": {
580
+ "key": "prod-api-uuid",
581
+ "name": "prod-api",
582
+ "instance": "https://collector.prod.internal:4318"
583
+ },
584
+ "config": {
585
+ "runtime": { "noUuid": true, "strict": true, "deploymentEnvironment": "production" },
586
+ "logging": { "enabled": true },
587
+ "capture": { "body": true, "multipart": true },
588
+ "firewall": { "enabled": true, "tcp": true, "syncInterval": 30, "failMode": "open" },
589
+ "otel": { "logLevel": "error" }
590
+ }
591
+ }
592
+ ```
595
593
 
596
594
  ### Instrument a Docker Container
597
595
 
@@ -600,25 +598,27 @@ FROM node:20-slim
600
598
  WORKDIR /app
601
599
  COPY package*.json ./
602
600
  RUN npm ci --omit=dev
603
- COPY . .
604
-
605
- ENV SECURENOW_APPID=my-service
606
- ENV SECURENOW_INSTANCE=http://otel-collector:4318
607
- ENV SECURENOW_NO_UUID=1
608
- ENV SECURENOW_API_KEY=snk_live_abc123...
609
-
610
- CMD ["node", "-r", "securenow/register", "src/index.js"]
611
- ```
601
+ COPY . .
602
+ # Mount/copy secret file at runtime as /app/.securenow/credentials.json.
603
+
604
+ CMD ["node", "-r", "securenow/register", "src/index.js"]
605
+ ```
612
606
 
613
607
  ### Kubernetes with Separate Trace/Log Collectors
614
608
 
615
- ```bash
616
- SECURENOW_APPID=k8s-service
617
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://tempo:4318/v1/traces
618
- OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://loki:4318/v1/logs
619
- SECURENOW_LOGGING_ENABLED=1
620
- SECURENOW_NO_UUID=1
621
- ```
609
+ ```json
610
+ {
611
+ "app": { "key": "k8s-service", "name": "k8s-service" },
612
+ "config": {
613
+ "otel": {
614
+ "tracesEndpoint": "http://tempo:4318/v1/traces",
615
+ "logsEndpoint": "http://loki:4318/v1/logs"
616
+ },
617
+ "logging": { "enabled": true },
618
+ "runtime": { "noUuid": true }
619
+ }
620
+ }
621
+ ```
622
622
 
623
623
  ---
624
624
 
@@ -626,21 +626,21 @@ SECURENOW_NO_UUID=1
626
626
 
627
627
  On startup, securenow logs its configuration:
628
628
 
629
- ```
630
- [securenow] pid=12345 SECURENOW_APPID="my-app" → service.name=my-app
631
- [securenow] OTel SDK started → https://collector:4318/v1/traces
632
- [securenow] Logging: ENABLED → https://collector:4318/v1/logs
633
- [securenow] Request body capture: ENABLED (max: 10240 bytes)
634
- [securenow] Firewall: ENABLED
635
- [securenow] Firewall: synced 142 blocked IPs
636
- ```
637
-
638
- Use `OTEL_LOG_LEVEL=debug` and `SECURENOW_TEST_SPAN=1` to troubleshoot connectivity issues.
629
+ ```
630
+ [securenow] app.key="my-app" → service.name=my-app
631
+ [securenow] OTel SDK started → https://collector:4318/v1/traces
632
+ [securenow] Logging: ENABLED → https://collector:4318/v1/logs
633
+ [securenow] Request body capture: ENABLED (max: 10240 bytes)
634
+ [securenow] Firewall: ENABLED
635
+ [securenow] Firewall: synced 142 blocked IPs
636
+ ```
637
+
638
+ Set `config.otel.logLevel` to `debug` in `.securenow/credentials.json` or run `securenow test-span --env <env>` to troubleshoot connectivity issues.
639
639
 
640
640
  **CLI equivalent** (works without booting the SDK — useful when the app won't start):
641
641
 
642
- ```bash
643
- securenow env # show resolved service name, endpoints, env vars
644
- securenow doctor # probe OTLP + API endpoints, exits 1 on failure
645
- securenow test-span # send a real span to the collector
646
- ```
642
+ ```bash
643
+ securenow env # show resolved app key, endpoints, and credentials fields
644
+ securenow doctor # probe OTLP + API endpoints, exits 1 on failure
645
+ securenow test-span # send a real span to the collector
646
+ ```