securenow 7.5.1 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +209 -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 +208 -206
  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 +71 -39
  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 +24 -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 +47 -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,86 @@ 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
+ import { createRequire } from 'node:module';
155
+
156
+ const require = createRequire(import.meta.url);
157
+
158
+ export async function register() {
159
+ if (process.env.NEXT_RUNTIME !== 'nodejs') return;
160
+ const { registerSecureNow } = require('securenow/nextjs');
161
+ registerSecureNow({ captureBody: true });
162
+ require('securenow/nextjs-auto-capture');
163
+ }
164
+ ```
164
165
 
165
166
  `registerSecureNow(options?)` accepts:
166
167
 
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
- ```
168
+ ```typescript
169
+ interface RegisterOptions {
170
+ serviceName?: string; // override credentials app key/name
171
+ endpoint?: string; // override credentials app instance
172
+ noUuid?: boolean; // override credentials config.runtime.noUuid
173
+ captureBody?: boolean; // override credentials config.capture.body
174
+ }
175
+ ```
176
+
177
+ On Vercel it uses `@vercel/otel`; self-hosted uses vanilla `@opentelemetry/sdk-node`.
178
+
179
+ **3. Credentials:**
180
+
181
+ ```json
182
+ {
183
+ "app": {
184
+ "key": "<uuid>",
185
+ "name": "my-nextjs-app",
186
+ "instance": "https://freetrial.securenow.ai:4318"
187
+ },
188
+ "config": {
189
+ "logging": { "enabled": true },
190
+ "capture": { "body": true, "multipart": true, "maxBodySize": 10240 },
191
+ "firewall": { "enabled": true }
192
+ }
193
+ }
194
+ ```
195
+
196
+ 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
197
 
185
198
  #### Next.js Body Capture
186
199
 
@@ -188,15 +201,18 @@ SECURENOW_INSTANCE=https://your-collector:4318
188
201
 
189
202
  Add to your `instrumentation.ts`:
190
203
 
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
- ```
204
+ ```typescript
205
+ import { createRequire } from 'node:module';
206
+
207
+ const require = createRequire(import.meta.url);
208
+
209
+ export async function register() {
210
+ if (process.env.NEXT_RUNTIME !== 'nodejs') return;
211
+ const { registerSecureNow } = require('securenow/nextjs');
212
+ registerSecureNow({ captureBody: true });
213
+ require('securenow/nextjs-auto-capture');
214
+ }
215
+ ```
200
216
 
201
217
  **Option B — Middleware:**
202
218
 
@@ -219,10 +235,11 @@ export const POST = withSecureNow(async (req) => {
219
235
  #### Next.js with `securenow init`
220
236
 
221
237
  ```bash
222
- npx securenow init --key snk_live_abc123...
238
+ npx securenow login
239
+ npx securenow init
223
240
  ```
224
241
 
225
- Auto-detects Next.js, creates `instrumentation.ts`, suggests `next.config` changes, writes API key to `.env.local`.
242
+ 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
243
 
227
244
  ---
228
245
 
@@ -232,21 +249,14 @@ Auto-detects Next.js, creates `instrumentation.ts`, suggests `next.config` chang
232
249
 
233
250
  ```typescript
234
251
  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.
252
+ modules: ['securenow/nuxt'],
253
+ securenow: {
254
+ // optional overrides (defaults come from .securenow/credentials.json)
255
+ },
256
+ });
257
+ ```
258
+
259
+ 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
260
 
251
261
  ---
252
262
 
@@ -267,7 +277,7 @@ Instruments document load, fetch, XMLHttpRequest, and user interactions with bro
267
277
 
268
278
  ## Firewall — Multi-Layer IP Blocking
269
279
 
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`.
280
+ 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
281
 
272
282
  ```
273
283
  Layer 4: Cloud/Edge WAF → blocked at CDN (Cloudflare, AWS WAF, GCP Cloud Armor)
@@ -279,16 +289,13 @@ Layer 1: HTTP Handler → 403 JSON response (always active)
279
289
  ### Activate
280
290
 
281
291
  ```bash
282
- # Zero-config (recommended) — writes the key to .securenow/credentials.json
283
- npx securenow login # pick/create app; firewall connects automatically
292
+ # Zero-config (recommended) — writes the key to .securenow/credentials.json
293
+ npx securenow login # pick/create app; firewall connects automatically
284
294
  # or, if you already have a key:
285
295
  npx securenow api-key set snk_live_abc123...
286
296
 
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_
297
+ # Production runtime file:
298
+ npx securenow credentials runtime --env production
292
299
  ```
293
300
 
294
301
  ### Firewall-Only Mode (No Tracing Overhead)
@@ -304,13 +311,14 @@ Loads only dotenv + firewall. No OpenTelemetry, no tracing, no external packages
304
311
 
305
312
  ### Programmatic Firewall API
306
313
 
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
314
+ ```javascript
315
+ const firewall = require('securenow/firewall');
316
+ const appConfig = require('securenow/app-config');
317
+
318
+ await firewall.init({
319
+ ...appConfig.resolveFirewallOptions(),
320
+ apiUrl: 'https://api.securenow.ai',
321
+ syncInterval: 300, // full sync every 5 min
314
322
  versionCheckInterval: 10, // lightweight version check every 10s
315
323
  failMode: 'open', // 'open' or 'closed'
316
324
  statusCode: 403,
@@ -440,7 +448,7 @@ const safe = redactSensitiveData({ username: 'alice', password: 's3cret', token:
440
448
 
441
449
  **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
450
 
443
- Add custom fields via `SECURENOW_SENSITIVE_FIELDS=field1,field2`.
451
+ Add custom fields via `config.capture.sensitiveFields` in `.securenow/credentials.json`; `SECURENOW_SENSITIVE_FIELDS=field1,field2` is a legacy fallback for existing installs.
444
452
 
445
453
  **CLI equivalent** (for piping, scripts, debugging what a payload looks like post-redaction):
446
454
 
@@ -451,20 +459,22 @@ securenow redact @request.json --fields internal_id,sessionHash
451
459
 
452
460
  ---
453
461
 
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` |
462
+ ## Credentials Configuration
463
+
464
+ 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.
465
+
466
+ ### App Identity
467
+
468
+ | Variable | Description | Default |
469
+ |----------|-------------|---------|
470
+ | `SECURENOW_APPID` | Legacy fallback for `app.key` / service name | from credentials file, then package name |
471
+ | `SECURENOW_INSTANCE` | Legacy fallback for `app.instance` / OTLP collector base URL | from credentials file, then `https://freetrial.securenow.ai:4318` |
462
472
 
463
473
  ### Service Naming
464
474
 
465
475
  | Variable | Description | Default |
466
476
  |----------|-------------|---------|
467
- | `OTEL_SERVICE_NAME` | OpenTelemetry standard; overrides `SECURENOW_APPID` | — |
477
+ | `OTEL_SERVICE_NAME` | Legacy fallback for `app.name` | — |
468
478
  | `SECURENOW_NO_UUID` | `1` to use exact app ID without UUID suffix | `0` |
469
479
  | `SECURENOW_STRICT` | `1` to exit if APPID missing in PM2 cluster | `0` |
470
480
 
@@ -472,9 +482,9 @@ securenow redact @request.json --fields internal_id,sessionHash
472
482
 
473
483
  | Variable | Description | Default |
474
484
  |----------|-------------|---------|
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` |
485
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Legacy fallback for `config.otel.endpoint` | — |
486
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Legacy fallback for `config.otel.tracesEndpoint` | `{instance}/v1/traces` |
487
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Legacy fallback for `config.otel.logsEndpoint` | `{instance}/v1/logs` |
478
488
  | `OTEL_EXPORTER_OTLP_HEADERS` | Comma-separated `key=value` headers for OTLP requests | — |
479
489
 
480
490
  ### Behavior
@@ -482,21 +492,21 @@ securenow redact @request.json --fields internal_id,sessionHash
482
492
  | Variable | Description | Default |
483
493
  |----------|-------------|---------|
484
494
  | `SECURENOW_LOGGING_ENABLED` | Enable OTLP log export | `1` |
485
- | `SECURENOW_CAPTURE_BODY` | Capture HTTP request bodies | `1` |
495
+ | `SECURENOW_CAPTURE_BODY` | Capture HTTP request bodies | `1` |
486
496
  | `SECURENOW_MAX_BODY_SIZE` | Max body size in bytes | `10240` |
487
- | `SECURENOW_CAPTURE_MULTIPART` | Capture multipart/form-data (streaming, metadata only) | `1` |
497
+ | `SECURENOW_CAPTURE_MULTIPART` | Capture multipart/form-data (streaming, metadata only) | `1` |
488
498
  | `SECURENOW_SENSITIVE_FIELDS` | Comma-separated extra fields to redact | — |
489
499
  | `SECURENOW_DISABLE_INSTRUMENTATIONS` | Comma-separated packages to skip (e.g. `fs,dns`) | — |
490
500
  | `SECURENOW_TEST_SPAN` | `1` to emit a test span on startup | `0` |
491
501
  | `SECURENOW_HIDE_BANNER` | `1` to suppress free-trial upgrade banner | `0` |
492
502
  | `OTEL_LOG_LEVEL` | SDK log level: `none`, `error`, `warn`, `info`, `debug` | `none` |
493
- | `NODE_ENV` | Sent as `deployment.environment` attribute | `production` |
503
+ | `SECURENOW_ENVIRONMENT` / `SECURENOW_DEPLOYMENT_ENVIRONMENT` / `NODE_ENV` | Legacy fallback for `config.runtime.deploymentEnvironment` | `production` |
494
504
 
495
505
  ### Firewall
496
506
 
497
507
  | Variable | Description | Default |
498
508
  |----------|-------------|---------|
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_`. | |
509
+ | `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
510
  | `SECURENOW_API_URL` | SecureNow API base URL | `https://api.securenow.ai` |
501
511
  | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch (`0` to disable) | `1` |
502
512
  | `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between lightweight version checks | `10` |
@@ -522,9 +532,9 @@ securenow redact @request.json --fields internal_id,sessionHash
522
532
 
523
533
  ### Priority Order
524
534
 
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`
535
+ **Service name:** credentials `app.key` > credentials `app.name` > legacy env fallback > package name
536
+
537
+ **Endpoint:** credentials `config.otel.tracesEndpoint` / `config.otel.endpoint` / `app.instance` > legacy env fallback > `https://freetrial.securenow.ai:4318`
528
538
 
529
539
  ---
530
540
 
@@ -533,16 +543,11 @@ securenow redact @request.json --fields internal_id,sessionHash
533
543
  ### Add Observability to an Existing Express App
534
544
 
535
545
  ```bash
536
- npm install securenow
546
+ npm install securenow@latest
547
+ npx securenow login
537
548
  ```
538
549
 
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
- ```
550
+ 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
551
 
547
552
  Update `package.json`:
548
553
  ```json
@@ -554,17 +559,11 @@ No code changes to the application needed.
554
559
  ### Add Observability + Firewall to a Next.js App
555
560
 
556
561
  ```bash
557
- npm install securenow
562
+ npm install securenow@latest
558
563
  npx securenow login # pick/create app; firewall key is minted automatically
559
564
  ```
560
565
 
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
- ```
566
+ `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
567
 
569
568
  ### Enable Firewall With Zero Tracing Overhead
570
569
 
@@ -574,24 +573,27 @@ For apps that only need IP blocking:
574
573
  node -r securenow/firewall-only app.js
575
574
  ```
576
575
 
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.
576
+ 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`.
578
577
 
579
- ### Production Hardened Configuration
580
-
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
- ```
578
+ ### Production Hardened Configuration
579
+
580
+ ```json
581
+ {
582
+ "apiKey": "snk_live_...",
583
+ "app": {
584
+ "key": "prod-api-uuid",
585
+ "name": "prod-api",
586
+ "instance": "https://collector.prod.internal:4318"
587
+ },
588
+ "config": {
589
+ "runtime": { "noUuid": true, "strict": true, "deploymentEnvironment": "production" },
590
+ "logging": { "enabled": true },
591
+ "capture": { "body": true, "multipart": true },
592
+ "firewall": { "enabled": true, "tcp": true, "syncInterval": 30, "failMode": "open" },
593
+ "otel": { "logLevel": "error" }
594
+ }
595
+ }
596
+ ```
595
597
 
596
598
  ### Instrument a Docker Container
597
599
 
@@ -600,25 +602,27 @@ FROM node:20-slim
600
602
  WORKDIR /app
601
603
  COPY package*.json ./
602
604
  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
- ```
605
+ COPY . .
606
+ # Mount/copy secret file at runtime as /app/.securenow/credentials.json.
607
+
608
+ CMD ["node", "-r", "securenow/register", "src/index.js"]
609
+ ```
612
610
 
613
611
  ### Kubernetes with Separate Trace/Log Collectors
614
612
 
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
- ```
613
+ ```json
614
+ {
615
+ "app": { "key": "k8s-service", "name": "k8s-service" },
616
+ "config": {
617
+ "otel": {
618
+ "tracesEndpoint": "http://tempo:4318/v1/traces",
619
+ "logsEndpoint": "http://loki:4318/v1/logs"
620
+ },
621
+ "logging": { "enabled": true },
622
+ "runtime": { "noUuid": true }
623
+ }
624
+ }
625
+ ```
622
626
 
623
627
  ---
624
628
 
@@ -626,21 +630,21 @@ SECURENOW_NO_UUID=1
626
630
 
627
631
  On startup, securenow logs its configuration:
628
632
 
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.
633
+ ```
634
+ [securenow] app.key="my-app" → service.name=my-app
635
+ [securenow] OTel SDK started → https://collector:4318/v1/traces
636
+ [securenow] Logging: ENABLED → https://collector:4318/v1/logs
637
+ [securenow] Request body capture: ENABLED (max: 10240 bytes)
638
+ [securenow] Firewall: ENABLED
639
+ [securenow] Firewall: synced 142 blocked IPs
640
+ ```
641
+
642
+ Set `config.otel.logLevel` to `debug` in `.securenow/credentials.json` or run `securenow test-span --env <env>` to troubleshoot connectivity issues.
639
643
 
640
644
  **CLI equivalent** (works without booting the SDK — useful when the app won't start):
641
645
 
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
- ```
646
+ ```bash
647
+ securenow env # show resolved app key, endpoints, and credentials fields
648
+ securenow doctor # probe OTLP + API endpoints, exits 1 on failure
649
+ securenow test-span # send a real span to the collector
650
+ ```