securenow 7.4.0 → 7.5.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.
package/cli/ui.js CHANGED
@@ -111,13 +111,21 @@ function keyValue(pairs) {
111
111
  }
112
112
  }
113
113
 
114
- function heading(text) {
115
- console.log(`\n${c.bold(c.cyan(text))}`);
116
- }
117
-
118
- function subheading(text) {
119
- console.log(`\n ${c.bold(text)}`);
120
- }
114
+ function heading(text) {
115
+ console.log(`\n${c.bold(c.cyan(text))}`);
116
+ }
117
+
118
+ function header(text) {
119
+ heading(text);
120
+ }
121
+
122
+ function bold(text) {
123
+ return c.bold(text);
124
+ }
125
+
126
+ function subheading(text) {
127
+ console.log(`\n ${c.bold(text)}`);
128
+ }
121
129
 
122
130
  function success(msg) {
123
131
  console.log(`${c.green('✓')} ${msg}`);
@@ -361,11 +369,13 @@ function durationColor(ms) {
361
369
  module.exports = {
362
370
  c,
363
371
  NO_COLOR,
364
- stripAnsi,
365
- table,
366
- keyValue,
367
- heading,
368
- subheading,
372
+ stripAnsi,
373
+ table,
374
+ keyValue,
375
+ heading,
376
+ header,
377
+ bold,
378
+ subheading,
369
379
  success,
370
380
  error,
371
381
  warn,
package/cli.js CHANGED
@@ -365,14 +365,19 @@ const COMMANDS = {
365
365
  usage: 'securenow doctor [--json]',
366
366
  run: (a, f) => require('./cli/diagnostics').doctor(a, f),
367
367
  },
368
- env: {
369
- desc: 'Show resolved SecureNow configuration (service name, endpoints, env vars)',
370
- usage: 'securenow env [--json]',
371
- run: (a, f) => require('./cli/diagnostics').env(a, f),
372
- },
373
- version: {
374
- desc: 'Show CLI version',
375
- run: () => {
368
+ env: {
369
+ desc: 'Show resolved SecureNow configuration (service name, endpoints, env vars)',
370
+ usage: 'securenow env [--json]',
371
+ run: (a, f) => require('./cli/diagnostics').env(a, f),
372
+ },
373
+ mcp: {
374
+ desc: 'Start the SecureNow MCP server over stdio',
375
+ usage: 'securenow mcp',
376
+ run: () => require('./mcp/server'),
377
+ },
378
+ version: {
379
+ desc: 'Show CLI version',
380
+ run: () => {
376
381
  try {
377
382
  const pkg = require('./package.json');
378
383
  console.log(`securenow v${pkg.version}`);
@@ -437,7 +442,7 @@ function showHelp(commandName) {
437
442
  'Firewall': ['firewall'],
438
443
  'Remediation': ['blocklist', 'allowlist', 'trusted'],
439
444
  'Telemetry': ['log', 'test-span'],
440
- 'Utilities': ['redact', 'cidr', 'doctor', 'env'],
445
+ 'Utilities': ['redact', 'cidr', 'doctor', 'env', 'mcp'],
441
446
  'Settings': ['instances', 'config', 'version'],
442
447
  };
443
448
 
@@ -119,9 +119,10 @@ SECURENOW_NO_UUID=1
119
119
  |----------|---------|---------|
120
120
  | `SECURENOW_APPID` | Your app key (from `securenow apps create`) | **Required** |
121
121
  | `SECURENOW_INSTANCE` | OTLP collector endpoint | `https://freetrial.securenow.ai:4318` |
122
- | `SECURENOW_LOGGING_ENABLED` | Auto-forward all `console.*` calls as OTLP logs | `0` |
122
+ | `SECURENOW_LOGGING_ENABLED` | Auto-forward all `console.*` calls as OTLP logs | `1` |
123
123
  | `SECURENOW_NO_UUID` | Keep `service.name` equal to your app key (no UUID suffix) | `0` |
124
- | `SECURENOW_CAPTURE_BODY` | Capture request/response bodies in traces | `0` |
124
+ | `SECURENOW_CAPTURE_BODY` | Capture request/response bodies in traces | `1` |
125
+ | `SECURENOW_CAPTURE_MULTIPART` | Capture multipart field/file metadata | `1` |
125
126
  | `SECURENOW_MAX_BODY_SIZE` | Max captured body size in bytes | `10240` |
126
127
  | `SECURENOW_SENSITIVE_FIELDS` | Extra field names to auto-redact (comma-separated) | — |
127
128
  | `SECURENOW_TRUSTED_PROXIES` | Comma-separated proxy IPs for X-Forwarded-For | — |
@@ -137,7 +138,8 @@ SECURENOW_APPID=my-app-prod
137
138
  SECURENOW_INSTANCE=https://collector.yourcompany.com:4318
138
139
  SECURENOW_LOGGING_ENABLED=1
139
140
  SECURENOW_NO_UUID=1
140
- SECURENOW_CAPTURE_BODY=0
141
+ SECURENOW_CAPTURE_BODY=1
142
+ SECURENOW_CAPTURE_MULTIPART=1
141
143
  SECURENOW_TRUSTED_PROXIES=10.0.0.1,10.0.0.2
142
144
  NODE_ENV=production
143
145
  ```
@@ -203,7 +205,7 @@ node app.js
203
205
  |---------|-----------|
204
206
  | Traces | Yes |
205
207
  | Logs | Yes |
206
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
208
+ | Body Capture | Yes - default on |
207
209
 
208
210
  ---
209
211
 
@@ -249,7 +251,7 @@ node app.js
249
251
  |---------|-----------|
250
252
  | Traces | Yes |
251
253
  | Logs | Yes |
252
- | Body Capture | **No** set `SECURENOW_CAPTURE_BODY=0` (stream conflict) |
254
+ | Body Capture | Yes - default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
253
255
 
254
256
  ---
255
257
 
@@ -299,7 +301,7 @@ node app.js
299
301
  |---------|-----------|
300
302
  | Traces | Yes |
301
303
  | Logs | Yes |
302
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
304
+ | Body Capture | Yes - default on |
303
305
 
304
306
  ---
305
307
 
@@ -376,7 +378,7 @@ Add both to your `package.json`:
376
378
  |---------|-----------|
377
379
  | Traces | Yes |
378
380
  | Logs | Yes |
379
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
381
+ | Body Capture | Yes - default on |
380
382
 
381
383
  ---
382
384
 
@@ -426,7 +428,7 @@ node app.js
426
428
  |---------|-----------|
427
429
  | Traces | Yes |
428
430
  | Logs | Yes |
429
- | Body Capture | **No** set `SECURENOW_CAPTURE_BODY=0` (payload stream conflict) |
431
+ | Body Capture | Yes - default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
430
432
 
431
433
  ---
432
434
 
@@ -473,7 +475,7 @@ node app.js
473
475
  |---------|-----------|
474
476
  | Traces | Yes |
475
477
  | Logs | Yes |
476
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
478
+ | Body Capture | Yes - default on |
477
479
 
478
480
  ---
479
481
 
@@ -528,7 +530,7 @@ node app.js
528
530
  |---------|-----------|
529
531
  | Traces | Yes |
530
532
  | Logs | Yes |
531
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
533
+ | Body Capture | Yes - default on |
532
534
 
533
535
  ---
534
536
 
@@ -591,7 +593,7 @@ node app.js
591
593
  |---------|-----------|
592
594
  | Traces | Yes |
593
595
  | Logs | Yes |
594
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
596
+ | Body Capture | Yes - default on |
595
597
 
596
598
  ---
597
599
 
@@ -632,7 +634,7 @@ node -r securenow/register app.mjs
632
634
  |---------|-----------|
633
635
  | Traces | Yes |
634
636
  | Logs | Yes |
635
- | Body Capture | **No** set `SECURENOW_CAPTURE_BODY=0` (stream conflict) |
637
+ | Body Capture | Yes - default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
636
638
 
637
639
  ---
638
640
 
@@ -687,7 +689,7 @@ node app.js
687
689
  |---------|-----------|
688
690
  | Traces | Yes |
689
691
  | Logs | Yes |
690
- | Body Capture | Yes set `SECURENOW_CAPTURE_BODY=1` |
692
+ | Body Capture | Yes - default on |
691
693
 
692
694
  ---
693
695
 
@@ -1284,7 +1286,8 @@ pm2 start ecosystem.config.cjs
1284
1286
  script: 'app.mjs',
1285
1287
  node_args: '-r securenow/register',
1286
1288
  env: {
1287
- SECURENOW_CAPTURE_BODY: '0', // Required for Hono
1289
+ SECURENOW_CAPTURE_BODY: '1',
1290
+ SECURENOW_CAPTURE_MULTIPART: '1',
1288
1291
  /* ... other vars ... */
1289
1292
  }
1290
1293
  }
@@ -1315,14 +1318,14 @@ CMD ["node", "-r", "securenow/register", "app.js"]
1315
1318
  | Framework | Traces | Logs | Body Capture | Init Method | Notes |
1316
1319
  |-----------|--------|------|--------------|-------------|-------|
1317
1320
  | Express | Yes | Yes | Yes | `require()` or `-r` | Fully compatible |
1318
- | Fastify | Yes | Yes | **No** | `require()` or `-r` | Set `SECURENOW_CAPTURE_BODY=0` |
1321
+ | Fastify | Yes | Yes | Yes | `require()` or `-r` | Default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
1319
1322
  | Koa | Yes | Yes | Yes | `require()` or `-r` | Needs `koa-bodyparser` |
1320
1323
  | NestJS | Yes | Yes | Yes | `instrument.js` + `-r ./instrument.js` | Create `instrument.js` with `require('securenow/register')` |
1321
- | Hapi | Yes | Yes | **No** | `require()` or `-r` | Set `SECURENOW_CAPTURE_BODY=0` |
1324
+ | Hapi | Yes | Yes | Yes | `require()` or `-r` | Default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
1322
1325
  | h3 | Yes | Yes | Yes | `require()` or `-r` | Uses `toNodeListener()` |
1323
1326
  | Polka | Yes | Yes | Yes | `require()` or `-r` | Needs manual body parser |
1324
1327
  | Micro/HTTP | Yes | Yes | Yes | `require()` or `-r` | Raw `http.createServer` |
1325
- | Hono | Yes | Yes | **No** | `-r` flag only (ESM) | Set `SECURENOW_CAPTURE_BODY=0` |
1328
+ | Hono | Yes | Yes | Yes | `-r` flag only (ESM) | Default on; set `SECURENOW_CAPTURE_BODY=0` only for a local stream conflict |
1326
1329
  | Feathers | Yes | Yes | Yes | `require()` or `-r` | Express transport |
1327
1330
  | Next.js | Yes | Yes | Yes | `instrumentation.ts` | Use `securenow init` |
1328
1331
 
@@ -1349,7 +1352,7 @@ Do **not** add `require('securenow/register')` inside `.mjs` files.
1349
1352
 
1350
1353
  ### Body capture crashes / empty payloads
1351
1354
 
1352
- Set `SECURENOW_CAPTURE_BODY=0` for Fastify, Hapi, and Hono. These frameworks use custom stream handling that conflicts with the body capture hook.
1355
+ Body capture is on by default. If a specific framework version or plugin stack reports request-stream conflicts, set `SECURENOW_CAPTURE_BODY=0` as a local override for that app.
1353
1356
 
1354
1357
  ### CLI says "Not logged in"
1355
1358
 
@@ -54,8 +54,8 @@ Since v7.1.0, the firewall reads its API key from `.securenow/credentials.json`
54
54
  ### Writing the key to the credentials file
55
55
 
56
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
57
+ # Interactive onboarding - picks/creates an app, enables that app's firewall,
58
+ # and mints a key scoped firewall:read + blocklist:read + allowlist:read
59
59
  # (the "firewall" preset, used by default for CLI firewall onboarding)
60
60
  # and writes it to ./.securenow/credentials.json automatically.
61
61
  npx securenow login
@@ -16,7 +16,7 @@ Complete reference for all environment variables supported by SecureNow.
16
16
  | **SECURENOW_INSTANCE** | Optional | `https://freetrial.securenow.ai:4318` | OTLP collector base URL |
17
17
  | **SECURENOW_API_KEY** | Optional | from credentials file | API key (same UUID as APPID). Enables firewall. |
18
18
  | **SECURENOW_LOGGING_ENABLED** | Optional | `1` (on) | Forward `console.*` as OTLP logs. Set to `0` to disable. |
19
- | **SECURENOW_CAPTURE_BODY** | Optional | `1` (on) | Capture request body. Set to `0` for Fastify/Hapi/Hono. |
19
+ | **SECURENOW_CAPTURE_BODY** | Optional | `1` (on) | Capture request body. Set to `0` only for a local stream conflict. |
20
20
  | **SECURENOW_CAPTURE_MULTIPART** | Optional | `1` (on) | Capture multipart field/file metadata. |
21
21
  | **SECURENOW_MAX_BODY_SIZE** | Optional | `10240` | Max body size in bytes |
22
22
  | **SECURENOW_SENSITIVE_FIELDS** | Optional | - | Comma-separated extra fields to redact |
@@ -288,11 +288,12 @@ export SECURENOW_LOGGING_ENABLED=0
288
288
 
289
289
  **Format:** `1` (enabled) or `0` (disabled)
290
290
 
291
- **Default:** `0` (disabled)
291
+ **Default:** `1` (enabled)
292
292
 
293
293
  **Example:**
294
294
  ```bash
295
- export SECURENOW_CAPTURE_BODY=1
295
+ # Default is enabled. Use this only to opt out:
296
+ export SECURENOW_CAPTURE_BODY=0
296
297
  ```
297
298
 
298
299
  **Supported content types:**
@@ -300,8 +301,7 @@ export SECURENOW_CAPTURE_BODY=1
300
301
  - `application/x-www-form-urlencoded`
301
302
  - `application/graphql`
302
303
 
303
- **Not captured (unless separately enabled):**
304
- - `multipart/form-data` — requires `SECURENOW_CAPTURE_MULTIPART=1` (see below)
304
+ **Not captured:**
305
305
  - Bodies larger than `SECURENOW_MAX_BODY_SIZE`
306
306
 
307
307
  **Security:**
@@ -373,11 +373,12 @@ export SECURENOW_SENSITIVE_FIELDS="custom_secret,private_data,internal_id"
373
373
 
374
374
  **Format:** `1` (enabled) or `0` (disabled)
375
375
 
376
- **Default:** `0` (disabled)
376
+ **Default:** `1` (enabled)
377
377
 
378
378
  **Example:**
379
379
  ```bash
380
- export SECURENOW_CAPTURE_MULTIPART=1
380
+ # Default is enabled. Use this only to opt out:
381
+ export SECURENOW_CAPTURE_MULTIPART=0
381
382
  ```
382
383
 
383
384
  **What gets captured:**
@@ -405,7 +406,7 @@ export SECURENOW_CAPTURE_MULTIPART=1
405
406
 
406
407
  **Parts limit:** 100 parts maximum per request (safety guard).
407
408
 
408
- **Requires:** `SECURENOW_CAPTURE_BODY=1` must also be set (multipart capture is gated behind general body capture).
409
+ **Relationship to body capture:** multipart metadata capture has its own opt-out flag. Leave `SECURENOW_CAPTURE_MULTIPART` unset, `1`, or `true` to keep it enabled.
409
410
 
410
411
  **Since:** v5.8.0
411
412
 
@@ -533,7 +534,7 @@ export NODE_ENV=test
533
534
  export SECURENOW_API_KEY=snk_live_a1b2c3d4e5f6...
534
535
  ```
535
536
 
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
+ **v7.4.0+:** the firewall also reads this key from `.securenow/credentials.json` (written by `securenow login`, which enables the selected app firewall by default, 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
538
 
538
539
  ---
539
540
 
@@ -47,10 +47,11 @@ All layers share the same in-memory blocklist, synced from the SecureNow API usi
47
47
  Two ways to get the firewall wired up — pick whichever fits:
48
48
 
49
49
  ```bash
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.
53
- npx securenow login
50
+ # (a) Zero-config (v7.4+): run login, pick/create an app, and connect.
51
+ # The selected app's firewall toggle is enabled automatically.
52
+ # The dashboard mints a key scoped firewall:read + blocklist:read + allowlist:read
53
+ # and the CLI writes it to .securenow/credentials.json. No further config needed.
54
+ npx securenow login
54
55
 
55
56
  # (b) Already have a key? Drop it into the credentials file directly:
56
57
  npx securenow api-key set snk_live_abc123...
@@ -0,0 +1,50 @@
1
+ # SecureNow MCP Guide
2
+
3
+ SecureNow ships an MCP server for agent clients such as Codex and Claude.
4
+
5
+ ## Local stdio MCP
6
+
7
+ Use this when the agent is running on the same machine as your project:
8
+
9
+ ```bash
10
+ npx securenow login
11
+ codex mcp add securenow -- npx securenow mcp
12
+ ```
13
+
14
+ You can also run the server directly:
15
+
16
+ ```bash
17
+ npx -p securenow securenow-mcp
18
+ ```
19
+
20
+ The local MCP server reads the same project-local `.securenow/credentials.json`
21
+ as the CLI and SDK. No production deployment is required.
22
+
23
+ ## Hosted MCP
24
+
25
+ For hosted clients, expose the secured API endpoint:
26
+
27
+ ```text
28
+ https://api.securenow.ai/mcp
29
+ ```
30
+
31
+ The hosted endpoint must be authenticated with `Authorization: Bearer ...`.
32
+ It accepts SecureNow JWT sessions and `snk_live_...` API keys through the same
33
+ API auth path used by the rest of SecureNow.
34
+
35
+ ## Security Model
36
+
37
+ - Read tools require the matching `*:read` scope.
38
+ - Write tools require the matching `*:write` scope or `applications:write` for
39
+ app firewall settings.
40
+ - Write tools also require `confirm: true` and a non-empty `reason`.
41
+ - Full tokens and API keys are never returned by tools or resources.
42
+ - Hosted MCP validates browser origins and rate-limits requests.
43
+ - Tool calls are proxied through existing API routes so tenant isolation and
44
+ scope enforcement stay centralized.
45
+
46
+ ## Tools
47
+
48
+ The MCP exposes applications, traces, logs, firewall, IP intelligence,
49
+ forensics, notifications, blocklist, allowlist, trusted IPs, analytics, bundled
50
+ docs resources, and setup prompts.