securenow 7.1.0 → 7.2.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
@@ -59,17 +59,25 @@ yarn add securenow
59
59
 
60
60
  ### 1. Automatic Setup (Recommended)
61
61
 
62
- Run the init command after installing:
62
+ Run login it's a browser flow that picks an app and, since v7.1.0, also offers one-click firewall onboarding:
63
63
 
64
64
  ```bash
65
- npx securenow init --key snk_live_abc123...
65
+ npx securenow login
66
+ ```
67
+
68
+ During the browser step you can choose **Enable the Firewall?** — if you accept, the dashboard mints an API key (scoped `firewall:read + blocklist:read + allowlist:read`) and the CLI writes it into `.securenow/credentials.json`. No env vars, no copy-pasting keys.
69
+
70
+ For framework scaffolding (Next.js `instrumentation.ts`, etc.) use:
71
+
72
+ ```bash
73
+ npx securenow init --key snk_live_abc123... # --key is optional now that login handles it
66
74
  ```
67
75
 
68
76
  This detects your framework and:
69
77
  - **Next.js**: Creates `instrumentation.ts`, suggests `withSecureNow()` for `next.config.js`
70
78
  - **Nuxt 3**: Suggests adding `securenow/nuxt` to modules
71
79
  - **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
80
+ - **All**: Writes `SECURENOW_API_KEY` to `.env.local` when `--key` is provided (not needed if `login` already wrote it to `.securenow/credentials.json`)
73
81
 
74
82
  ### 2. Manual Setup
75
83
 
@@ -144,7 +152,10 @@ The `securenow` CLI gives you full access to the SecureNow platform from the ter
144
152
  ### Getting Started
145
153
 
146
154
  ```bash
147
- # Log in (opens browser for OAuth)
155
+ # Log in (opens browser for OAuth + app picker)
156
+ # Since v7.1.0 the browser flow also offers one-click firewall onboarding —
157
+ # accept "Enable the Firewall?" to have the CLI mint and store the API key
158
+ # in .securenow/credentials.json automatically (no env var needed).
148
159
  npx securenow login
149
160
 
150
161
  # Or use a token for CI/headless environments
@@ -155,6 +166,11 @@ npx securenow login --local
155
166
 
156
167
  # Check who you're logged in as (shows auth source)
157
168
  npx securenow whoami
169
+
170
+ # Already have a firewall key? Store it without re-running login:
171
+ npx securenow api-key set snk_live_abc123... # --global for ~/.securenow/
172
+ npx securenow api-key show # masked key + source
173
+ npx securenow api-key clear # remove just the key
158
174
  ```
159
175
 
160
176
  ### Project Setup
@@ -461,6 +477,9 @@ npx securenow logs --json --level error | jq '.logs'
461
477
  | | `apps info <id>` | Application details |
462
478
  | | `apps delete <id>` | Delete application |
463
479
  | | `apps default <key>` | Set default app |
480
+ | **API Key** | `api-key set <snk_live_...> [--global]` | Save firewall key to `.securenow/credentials.json` |
481
+ | | `api-key show` | Show masked key + source |
482
+ | | `api-key clear [--global]` | Remove stored key (leaves session/app) |
464
483
  | **Observe** | `traces` | List traces |
465
484
  | | `traces show <id>` | Trace details |
466
485
  | | `traces analyze <id>` | AI trace analysis |
@@ -1076,16 +1095,28 @@ The Nuxt server plugin (v5.13.0+) initializes the firewall independently from Op
1076
1095
 
1077
1096
  ## Firewall -- Automatic IP Blocking
1078
1097
 
1079
- SecureNow can automatically block IPs from your blocklist at the application layer. No code changes -- just set an API key and the firewall activates.
1098
+ SecureNow can automatically block IPs from your blocklist at the application layer. No code changes -- just provide an API key (via `securenow login`, the `api-key` CLI, or env var) and the firewall activates.
1080
1099
 
1081
1100
  ### Enable the Firewall
1082
1101
 
1102
+ Pick whichever fits your environment:
1103
+
1083
1104
  ```bash
1084
- # Add to your .env
1105
+ # (a) Zero-config (v7.1+): login + opt in to the firewall in the browser.
1106
+ # Key is minted and written to .securenow/credentials.json automatically.
1107
+ npx securenow login
1108
+
1109
+ # (b) Already have a key? Write it to the creds file directly:
1110
+ npx securenow api-key set snk_live_abc123...
1111
+
1112
+ # (c) Old-school env var (still works; preferred for CI/Docker/prod):
1113
+ # .env
1085
1114
  SECURENOW_API_KEY=snk_live_abc123...
1086
1115
  ```
1087
1116
 
1088
- That's it. On startup, you'll see:
1117
+ The SDK resolves the firewall key in this order: `SECURENOW_API_KEY` env var (only if it starts with `snk_live_`) → project `./.securenow/credentials.json` global `~/.securenow/credentials.json`.
1118
+
1119
+ On startup, you'll see:
1089
1120
 
1090
1121
  ```
1091
1122
  [securenow] Firewall: ENABLED
@@ -1231,7 +1262,7 @@ See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
1231
1262
 
1232
1263
  | Variable | Description | Default |
1233
1264
  |----------|-------------|---------|
1234
- | `SECURENOW_API_KEY` | API key with `firewall:read` scope. Enables the firewall when set. | - |
1265
+ | `SECURENOW_API_KEY` | API key with `firewall:read` scope. Enables the firewall when set. Since v7.1.0 the firewall also reads this from `.securenow/credentials.json` (written by `securenow login` or `securenow api-key set`); env var only wins if it starts with `snk_live_`. | from creds file |
1235
1266
  | `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` |
1236
1267
  | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch. Set to `0` to disable. | `1` |
1237
1268
  | `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between version checks (lightweight ETag-based). | `10` |
package/README.md CHANGED
@@ -12,7 +12,9 @@ Zero-config OpenTelemetry for Node.js, Next.js, and Nuxt — traces, logs, body
12
12
  # 1. Install
13
13
  npm install securenow
14
14
 
15
- # 2. Pick (or create) your app in the browser — writes .securenow/ locally
15
+ # 2. Pick (or create) your app in the browser — writes .securenow/ locally.
16
+ # Since v7.1.0, the browser step also offers one-click firewall onboarding:
17
+ # say yes and the CLI stores a scoped API key in the same file — no env vars.
16
18
  npx securenow login
17
19
 
18
20
  # 3. Start your app — one flag is all it takes
@@ -135,10 +137,11 @@ Resolution order (first non-empty wins):
135
137
 
136
138
  ```bash
137
139
  # Setup
138
- npx securenow login # browser auth + app picker (saves to ./.securenow/)
140
+ npx securenow login # browser auth + app picker + firewall onboarding (saves to ./.securenow/)
139
141
  npx securenow login --global # save to ~/.securenow/ instead
140
142
  npx securenow login --token <TOKEN> # headless (CI)
141
143
  npx securenow init # scaffold Next.js instrumentation files
144
+ npx securenow api-key set snk_live_... # store firewall key in .securenow/credentials.json
142
145
 
143
146
  # Apps
144
147
  npx securenow apps # list all apps
@@ -241,12 +244,15 @@ After install, the `securenow` CLI is available via `npx securenow` or globally
241
244
 
242
245
  | Command | Description |
243
246
  |---|---|
244
- | `securenow login` | Browser auth + pick app (writes ./.securenow/ by default) |
247
+ | `securenow login` | Browser auth + pick app + optional firewall key onboarding (writes ./.securenow/ by default) |
245
248
  | `securenow login --global` | Save to ~/.securenow/ instead |
246
249
  | `securenow login --token <TOKEN>` | Headless (CI/servers) |
247
250
  | `securenow logout` | Clear project-local credentials |
248
251
  | `securenow logout --global` | Clear ~/.securenow/ instead |
249
252
  | `securenow whoami` | Show current session (email, app, expiry) |
253
+ | `securenow api-key set <snk_live_...>` | Store firewall key in `.securenow/credentials.json` (`--global` for `~/.securenow/`) |
254
+ | `securenow api-key show` | Print masked key + source file |
255
+ | `securenow api-key clear` | Remove stored key (`--global` for `~/.securenow/`) |
250
256
 
251
257
  ### Applications
252
258
 
package/SKILL-API.md CHANGED
@@ -48,12 +48,16 @@ That's it. Traces and logs flow to your OTLP collector. No code changes for Expr
48
48
 
49
49
  ### 3. Enable the Firewall (Optional)
50
50
 
51
- Add one more env var to auto-activate IP blocking:
51
+ Since v7.1.0 the firewall key lives in your credentials file — no env var required:
52
52
 
53
53
  ```bash
54
- SECURENOW_API_KEY=snk_live_abc123...
54
+ npx securenow login # pick app + click "Enable firewall" in browser
55
+ # or, if you already have one:
56
+ npx securenow api-key set snk_live_abc123...
55
57
  ```
56
58
 
59
+ 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.
60
+
57
61
  The firewall syncs your blocklist and enforces it on every request — zero code changes.
58
62
 
59
63
  ---
@@ -259,7 +263,7 @@ Instruments document load, fetch, XMLHttpRequest, and user interactions with bro
259
263
 
260
264
  ## Firewall — Multi-Layer IP Blocking
261
265
 
262
- 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:
266
+ The firewall auto-activates once an API key is resolvable. Since **v7.1.0** the key is read from `.securenow/credentials.json` (written by `npx securenow login` or `securenow api-key set`), so the `SECURENOW_API_KEY` env var is optional. Resolution order: env (must start with `snk_live_`) → project `./.securenow/credentials.json` → global `~/.securenow/credentials.json`.
263
267
 
264
268
  ```
265
269
  Layer 4: Cloud/Edge WAF → blocked at CDN (Cloudflare, AWS WAF, GCP Cloud Armor)
@@ -271,11 +275,16 @@ Layer 1: HTTP Handler → 403 JSON response (always active)
271
275
  ### Activate
272
276
 
273
277
  ```bash
274
- # .env
275
- SECURENOW_API_KEY=snk_live_abc123... # auto-activates Layer 1
278
+ # Zero-config (recommended) — writes the key to .securenow/credentials.json
279
+ npx securenow login # pick app + click "Enable firewall"
280
+ # or, if you already have a key:
281
+ npx securenow api-key set snk_live_abc123...
282
+
283
+ # Optional .env overrides for the stronger layers
276
284
  SECURENOW_FIREWALL_TCP=1 # opt-in Layer 2
277
285
  SECURENOW_FIREWALL_IPTABLES=1 # opt-in Layer 3 (Linux, needs root)
278
286
  SECURENOW_FIREWALL_CLOUD=cloudflare # opt-in Layer 4
287
+ # SECURENOW_API_KEY=snk_live_... # still honored; only wins if it starts with snk_live_
279
288
  ```
280
289
 
281
290
  ### Firewall-Only Mode (No Tracing Overhead)
@@ -483,7 +492,7 @@ securenow redact @request.json --fields internal_id,sessionHash
483
492
 
484
493
  | Variable | Description | Default |
485
494
  |----------|-------------|---------|
486
- | `SECURENOW_API_KEY` | API key (`snk_live_...`); activates firewall when set | — |
495
+ | `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_`. | — |
487
496
  | `SECURENOW_API_URL` | SecureNow API base URL | `https://api.securenow.ai` |
488
497
  | `SECURENOW_FIREWALL_ENABLED` | Master kill-switch (`0` to disable) | `1` |
489
498
  | `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between lightweight version checks | `10` |
@@ -542,16 +551,16 @@ No code changes to the application needed.
542
551
 
543
552
  ```bash
544
553
  npm install securenow
545
- npx securenow init --key snk_live_abc123...
554
+ npx securenow login # pick app + "Enable firewall" in browser
546
555
  ```
547
556
 
548
- The `init` command creates `instrumentation.ts` and suggests `next.config` changes. Then set env vars in `.env.local`:
557
+ `securenow login` writes session, app, and firewall key to `.securenow/credentials.json` (auto-gitignored). The `init` command still works for manual setup — it creates `instrumentation.ts` and suggests `next.config` changes. Most users only need this `.env.local`:
549
558
 
550
559
  ```
551
560
  SECURENOW_APPID=my-nextjs-app
552
561
  SECURENOW_INSTANCE=https://your-collector:4318
553
- SECURENOW_API_KEY=snk_live_abc123...
554
562
  SECURENOW_CAPTURE_BODY=1
563
+ # SECURENOW_API_KEY=snk_live_... (otherwise lives in .securenow/credentials.json)
555
564
  ```
556
565
 
557
566
  ### Enable Firewall With Zero Tracing Overhead
@@ -562,7 +571,7 @@ For apps that only need IP blocking:
562
571
  node -r securenow/firewall-only app.js
563
572
  ```
564
573
 
565
- Set `SECURENOW_API_KEY` in the environment. No other configuration needed.
574
+ 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.
566
575
 
567
576
  ### Production Hardened Configuration
568
577
 
package/SKILL-CLI.md CHANGED
@@ -26,9 +26,13 @@ securenow whoami # verify session (shows email, app, auth source)
26
26
 
27
27
  **Zero-config flow (v7+):** the browser step lets the user pick (or create) an app. The CLI stores the app's **key (UUID)**, **name**, and **instance URL** in `.securenow/credentials.json`. The SDK reads this file at boot and sends traces/logs to the right app bucket — **no env vars required for local dev**.
28
28
 
29
+ **Firewall onboarding (v7.1+):** after picking the app, `securenow login` asks "Enable the Firewall?" in the browser. If you accept, the dashboard mints an API key with `firewall:read + blocklist:read + allowlist:read` scopes and the CLI writes it into `.securenow/credentials.json` automatically — no `SECURENOW_API_KEY` env var needed. To add or rotate a key later without re-running login, use `securenow api-key set snk_live_...` (see [API Key Management](#api-key-management) below).
30
+
29
31
  Credentials resolve in order: `SECURENOW_TOKEN` env var → project `.securenow/credentials.json` → global `~/.securenow/credentials.json`.
30
32
 
31
- For CI / Docker / production, set env vars directly (always win over the file): `SECURENOW_APPID=<uuid>`, `SECURENOW_INSTANCE=<url>`, `SECURENOW_API_KEY=<uuid>`.
33
+ The **firewall API key** resolves in a slightly different order: `SECURENOW_API_KEY` env var (only if it starts with `snk_live_`) → project `.securenow/credentials.json` → global `~/.securenow/credentials.json`. An env var that isn't the `snk_live_` format is ignored, so the file can still win.
34
+
35
+ For CI / Docker / production, set env vars directly (always win over the file): `SECURENOW_APPID=<uuid>`, `SECURENOW_INSTANCE=<url>`, `SECURENOW_API_KEY=snk_live_<...>`.
32
36
 
33
37
  ### Integrate With Your App
34
38
 
@@ -66,6 +70,8 @@ Config lives in `~/.securenow/` (global) and optionally `.securenow/` (per-proje
66
70
 
67
71
  **Credential resolution order:** `SECURENOW_TOKEN` env var → `.securenow/credentials.json` (project) → `~/.securenow/credentials.json` (global).
68
72
 
73
+ **Firewall API key resolution (v7.1+):** `SECURENOW_API_KEY` env var (only honored if it starts with `snk_live_`) → project `.securenow/credentials.json` → global `~/.securenow/credentials.json`. Use `securenow api-key set` to write the key to the credentials file without touching env vars.
74
+
69
75
  ```bash
70
76
  securenow config set apiUrl https://api.securenow.ai
71
77
  securenow config set defaultApp my-app-key
@@ -128,6 +134,20 @@ securenow apps discover [appId] [--domain example.com] # discover subdomains, a
128
134
  securenow apps scan [--yes] # scan all app domains for new subdomains
129
135
  ```
130
136
 
137
+ ### API Key Management
138
+
139
+ Manage the firewall API key stored in the credentials file. Since v7.1.0 the firewall reads `snk_live_...` keys from `.securenow/credentials.json` so no env var is required.
140
+
141
+ ```bash
142
+ securenow api-key set snk_live_xxxxxxxxxx # save to project ./.securenow/ (default)
143
+ securenow api-key set snk_live_xxx --global # save to ~/.securenow/ instead
144
+ securenow api-key show # print the masked current key + its source
145
+ securenow api-key clear # remove just the API key (keeps session/app)
146
+ securenow api-key clear --global # same, but from the global file
147
+ ```
148
+
149
+ The key must start with `snk_live_`. `securenow login` with firewall enabled writes the key automatically; use `api-key set` when you already have a key from the dashboard, or to rotate it later.
150
+
131
151
  ### Init — Project Setup
132
152
 
133
153
  ```bash
@@ -225,6 +245,8 @@ securenow firewall status # layers, sync time, blocked count,
225
245
  securenow firewall test-ip <ip> # check if IP would be blocked
226
246
  ```
227
247
 
248
+ **Zero-config setup (v7.1+):** running `securenow login` and opting into "Enable the Firewall?" in the browser auto-mints an API key (scoped `firewall:read + blocklist:read + allowlist:read`) and writes it to the credentials file. No `SECURENOW_API_KEY` env var needed. If the user already has a key, `securenow api-key set snk_live_...` achieves the same thing. See [the landing firewall page](https://securenow.ai/firewall) for an overview.
249
+
228
250
  ### Blocklist — Block Malicious IPs
229
251
 
230
252
  ```bash
package/cli/auth.js CHANGED
@@ -46,6 +46,13 @@ async function loginWithBrowser() {
46
46
  let pendingToken = null;
47
47
  let pendingApp = null;
48
48
  let pendingApiKey = null;
49
+ const sockets = new Set();
50
+
51
+ const closeServer = () => {
52
+ try { server.close(); } catch {}
53
+ for (const s of sockets) { try { s.destroy(); } catch {} }
54
+ sockets.clear();
55
+ };
49
56
 
50
57
  const server = http.createServer((req, res) => {
51
58
  const url = new URL(req.url, `http://127.0.0.1`);
@@ -63,14 +70,14 @@ async function loginWithBrowser() {
63
70
 
64
71
  if (error) {
65
72
  res.end('<html><body style="font-family:system-ui;text-align:center;padding:60px"><h2>Authentication Failed</h2><p>You can close this window.</p></body></html>');
66
- server.close();
73
+ closeServer();
67
74
  reject(new CLIError(`Authentication failed: ${error}`));
68
75
  return;
69
76
  }
70
77
 
71
78
  if (returnedState !== nonce) {
72
79
  res.end('<html><body style="font-family:system-ui;text-align:center;padding:60px"><h2>Security Error</h2><p>State mismatch — this request may not have originated from your CLI. Please try again.</p></body></html>');
73
- server.close();
80
+ closeServer();
74
81
  reject(new CLIError('State mismatch on callback — possible CSRF. Please retry `securenow login`.'));
75
82
  return;
76
83
  }
@@ -129,7 +136,7 @@ async function loginWithBrowser() {
129
136
  }
130
137
 
131
138
  res.end('<html><body style="font-family:system-ui;text-align:center;padding:60px"><h2>Something went wrong</h2><p>No token received. Please try again.</p></body></html>');
132
- server.close();
139
+ closeServer();
133
140
  reject(new CLIError('No token received in callback'));
134
141
  return;
135
142
  }
@@ -148,7 +155,7 @@ async function loginWithBrowser() {
148
155
  pendingToken = null;
149
156
  pendingApp = null;
150
157
  pendingApiKey = null;
151
- server.close();
158
+ closeServer();
152
159
  resolve({ token, app, apiKey: apiKeyFromLogin });
153
160
  return;
154
161
  }
@@ -157,6 +164,11 @@ async function loginWithBrowser() {
157
164
  res.end();
158
165
  });
159
166
 
167
+ server.on('connection', (socket) => {
168
+ sockets.add(socket);
169
+ socket.once('close', () => sockets.delete(socket));
170
+ });
171
+
160
172
  server.listen(0, '127.0.0.1', () => {
161
173
  const port = server.address().port;
162
174
  const authUrl = `${appUrl}/cli/auth?callback=http://127.0.0.1:${port}/callback&state=${encodeURIComponent(nonce)}`;
@@ -177,7 +189,7 @@ async function loginWithBrowser() {
177
189
  console.log(ui.c.dim(' Waiting for authentication...'));
178
190
 
179
191
  const timeout = setTimeout(() => {
180
- server.close();
192
+ closeServer();
181
193
  reject(new CLIError('Login timed out after 5 minutes. Try `securenow login --token <TOKEN>` instead.'));
182
194
  }, 5 * 60 * 1000);
183
195
 
package/cli.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
4
  const ui = require('./cli/ui');
@@ -41,6 +41,43 @@ The `snk_live_` prefix makes it easy to identify SecureNow keys in your codebase
41
41
 
42
42
  ---
43
43
 
44
+ ## Storing the API Key
45
+
46
+ Since v7.1.0, the firewall reads its API key from `.securenow/credentials.json` as well as `SECURENOW_API_KEY`. You don't need to manage env vars for local dev.
47
+
48
+ **Resolution order (firewall):**
49
+
50
+ 1. `SECURENOW_API_KEY` env var — **only if it starts with `snk_live_`** (non-matching values are ignored so the file can still win)
51
+ 2. Project `./.securenow/credentials.json`
52
+ 3. Global `~/.securenow/credentials.json`
53
+
54
+ ### Writing the key to the credentials file
55
+
56
+ ```bash
57
+ # Interactive onboarding — picks/creates an app and, if you opt in,
58
+ # mints a key scoped firewall:read + blocklist:read + allowlist:read
59
+ # (the "firewall" preset, used by default for CLI firewall onboarding)
60
+ # and writes it to ./.securenow/credentials.json automatically.
61
+ npx securenow login
62
+
63
+ # Already have a key? Write it directly:
64
+ npx securenow api-key set snk_live_abc123...
65
+
66
+ # Save to ~/.securenow/ instead of the project
67
+ npx securenow api-key set snk_live_abc123... --global
68
+
69
+ # Inspect (masked) and see which file it came from
70
+ npx securenow api-key show
71
+
72
+ # Remove just the API key (leaves session/app in place)
73
+ npx securenow api-key clear
74
+ npx securenow api-key clear --global
75
+ ```
76
+
77
+ The key must start with `snk_live_` — `api-key set` rejects anything else.
78
+
79
+ ---
80
+
44
81
  ## Scopes (Permissions)
45
82
 
46
83
  Each API key has a set of scopes that control what it can access. Scopes follow the `resource:action` pattern.
@@ -117,13 +154,21 @@ curl -s https://api.securenow.ai/api/v1/blocklist \
117
154
 
118
155
  ### In the Firewall SDK
119
156
 
120
- Set the `SECURENOW_API_KEY` environment variable:
157
+ Easiest path (v7.1+) — let the CLI write the key to the credentials file for you:
158
+
159
+ ```bash
160
+ npx securenow login # firewall onboarding in the browser
161
+ # or, if you already have a key:
162
+ npx securenow api-key set snk_live_abc...
163
+ ```
164
+
165
+ Or set the env var the old way:
121
166
 
122
167
  ```bash
123
168
  SECURENOW_API_KEY=snk_live_abc123...
124
169
  ```
125
170
 
126
- The firewall SDK reads this automatically on startup.
171
+ The firewall SDK reads the credentials file on startup if the env var is unset (or isn't a `snk_live_` key). Env vars still take precedence when present and well-formed — useful in CI / Docker / prod.
127
172
 
128
173
  ### In CI/CD
129
174
 
@@ -533,6 +533,8 @@ export NODE_ENV=test
533
533
  export SECURENOW_API_KEY=snk_live_a1b2c3d4e5f6...
534
534
  ```
535
535
 
536
+ **v7.1.0+:** the firewall also reads this key from `.securenow/credentials.json` (written by `securenow login` with firewall enabled, or by `securenow api-key set`). The env var only wins if it starts with `snk_live_` — otherwise the credentials file is used, so you can rely on the file for local dev without unsetting any stray env var. Setting an app UUID here (the old pre-7.1 habit) is ignored for firewall auth and would produce silent 401s; always use a `snk_live_...` key.
537
+
536
538
  ---
537
539
 
538
540
  ### SECURENOW_API_URL
@@ -44,17 +44,26 @@ All layers share the same in-memory blocklist, synced from the SecureNow API usi
44
44
 
45
45
  ### 1. Get an API Key
46
46
 
47
+ Two ways to get the firewall wired up — pick whichever fits:
48
+
47
49
  ```bash
48
- # Log in to SecureNow
50
+ # (a) Zero-config (v7.1+): run login and choose "Enable firewall" in the browser.
51
+ # The dashboard mints a key scoped firewall:read + blocklist:read + allowlist:read
52
+ # and the CLI writes it to .securenow/credentials.json. No further config needed.
49
53
  npx securenow login
50
54
 
51
- # View your firewall status and API key
55
+ # (b) Already have a key? Drop it into the credentials file directly:
56
+ npx securenow api-key set snk_live_abc123...
57
+
58
+ # View your firewall status and API key source
52
59
  npx securenow firewall status
53
60
  ```
54
61
 
55
62
  Or create an API key from the dashboard: **Settings → API Keys → Create Key** with the `firewall:read` scope.
56
63
 
57
- ### 2. Add the Key to Your Environment
64
+ ### 2. Add the Key to Your Environment (optional)
65
+
66
+ If you used `securenow login` or `securenow api-key set` above, you can **skip this step** — the SDK reads the key from `.securenow/credentials.json` at boot. Env vars are still supported for CI / Docker / prod:
58
67
 
59
68
  ```bash
60
69
  # .env
@@ -67,7 +76,7 @@ SECURENOW_API_KEY=snk_live_abc123...
67
76
  node -r securenow/register app.js
68
77
  ```
69
78
 
70
- That's it. The firewall auto-activates when `SECURENOW_API_KEY` is present. You'll see:
79
+ That's it. The firewall auto-activates as soon as a valid `snk_live_...` key is available (env var or credentials file). You'll see:
71
80
 
72
81
  ```
73
82
  [securenow] Firewall: ENABLED
@@ -191,7 +200,7 @@ SECURENOW_FIREWALL_CLOUD_DRY_RUN=1
191
200
 
192
201
  | Variable | Default | Description |
193
202
  |----------|---------|-------------|
194
- | `SECURENOW_API_KEY` | *(required)* | API key with `firewall:read` scope |
203
+ | `SECURENOW_API_KEY` | *(from creds file)* | API key with `firewall:read` scope. Since v7.1.0 the firewall also reads this from `.securenow/credentials.json` (written by `securenow login` or `securenow api-key set`), so this env var is optional. The env var only wins if it starts with `snk_live_`; otherwise the credentials file is used. |
195
204
  | `SECURENOW_API_URL` | `https://api.securenow.ai` | API base URL. Auto-fallback to `http://localhost:4000` on ECONNREFUSED. |
196
205
  | `SECURENOW_FIREWALL_ENABLED` | `1` | Master kill-switch (`0` to disable) |
197
206
  | `SECURENOW_FIREWALL_VERSION_INTERVAL` | `10` | Seconds between version checks (lightweight ETag-based) |
package/docs/INDEX.md CHANGED
@@ -80,8 +80,8 @@ Complete documentation for SecureNow - OpenTelemetry instrumentation for Node.js
80
80
 
81
81
  ### 🛡️ Security & Protection
82
82
 
83
- - **[Firewall Guide](FIREWALL-GUIDE.md)** - Automatic IP blocking (multi-layer: HTTP, TCP, iptables, Cloud WAF)
84
- - **[API Keys Guide](API-KEYS-GUIDE.md)** - Creating, managing, and securing API keys
83
+ - **[Firewall Guide](FIREWALL-GUIDE.md)** - Automatic IP blocking (multi-layer: HTTP, TCP, iptables, Cloud WAF). v7.1+: `securenow login` now offers one-click firewall onboarding that writes the key to `.securenow/credentials.json`.
84
+ - **[API Keys Guide](API-KEYS-GUIDE.md)** - Creating, managing, and securing API keys. Includes the `securenow api-key set|show|clear` command family (v7.1+).
85
85
  - **[Redaction Examples](REDACTION-EXAMPLES.md)** - How sensitive data is redacted
86
86
  - **[Automatic IP Capture](AUTOMATIC-IP-CAPTURE.md)** - IP address and metadata collection
87
87
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securenow",
3
- "version": "7.1.0",
3
+ "version": "7.2.0",
4
4
  "description": "OpenTelemetry instrumentation for Node.js, Next.js, and Nuxt - Send traces and logs to any OTLP-compatible backend",
5
5
  "type": "commonjs",
6
6
  "main": "register.js",
@@ -165,7 +165,8 @@
165
165
  },
166
166
  "overrides": {
167
167
  "@opentelemetry/api": "1.7.0",
168
- "@opentelemetry/api-logs": "0.47.0"
168
+ "@opentelemetry/api-logs": "0.47.0",
169
+ "protobufjs": "^7.5.5"
169
170
  },
170
171
  "sideEffects": true,
171
172
  "license": "ISC"