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.
- package/CONSUMING-APPS-GUIDE.md +2 -0
- package/NPM_README.md +201 -237
- package/README.md +73 -26
- package/SKILL-API.md +209 -205
- package/SKILL-CLI.md +71 -64
- package/app-config.js +479 -83
- package/cli/apiKey.js +1 -1
- package/cli/apps.js +1 -1
- package/cli/config.js +31 -12
- package/cli/credentials.js +88 -0
- package/cli/diagnostics.js +68 -104
- package/cli/firewall.js +29 -14
- package/cli/init.js +208 -206
- package/cli/monitor.js +107 -43
- package/cli/security.js +24 -12
- package/cli/utils.js +2 -1
- package/cli.js +71 -39
- package/console-instrumentation.js +1 -1
- package/docs/ENVIRONMENT-VARIABLES.md +137 -863
- package/docs/ENVIRONMENTS.md +60 -0
- package/docs/EXPRESS-SETUP-GUIDE.md +3 -0
- package/docs/FIREWALL-GUIDE.md +3 -0
- package/docs/INDEX.md +6 -8
- package/docs/LOGGING-GUIDE.md +3 -0
- package/docs/MCP-GUIDE.md +8 -0
- package/docs/NEXTJS-GUIDE.md +3 -0
- package/docs/NEXTJS-QUICKSTART.md +24 -16
- package/docs/NUXT-GUIDE.md +3 -0
- package/docs/QUICKSTART-BODY-CAPTURE.md +3 -0
- package/docs/REQUEST-BODY-CAPTURE.md +3 -0
- package/firewall-cloud.js +10 -10
- package/firewall-only.js +25 -23
- package/firewall.js +47 -29
- package/free-trial-banner.js +1 -1
- package/mcp/catalog.js +104 -17
- package/nextjs-auto-capture.d.ts +7 -4
- package/nextjs-auto-capture.js +7 -7
- package/nextjs-middleware.js +4 -3
- package/nextjs-wrapper.js +6 -6
- package/nextjs.d.ts +36 -25
- package/nextjs.js +47 -55
- package/nuxt-server-plugin.mjs +35 -51
- package/nuxt.d.ts +29 -23
- package/package.json +1 -1
- package/postinstall.js +27 -61
- package/register.d.ts +19 -33
- package/register.js +8 -8
- package/resolve-ip.js +4 -5
- package/tracing.d.ts +21 -19
- package/tracing.js +34 -42
package/NPM_README.md
CHANGED
|
@@ -9,10 +9,9 @@ OpenTelemetry instrumentation library for Node.js, Next.js, and Nuxt application
|
|
|
9
9
|
- Built-in sensitive data redaction
|
|
10
10
|
- Request body capture for debugging
|
|
11
11
|
- Multi-layer firewall -- auto-blocks IPs from your SecureNow blocklist
|
|
12
|
-
- `
|
|
13
|
-
- `securenow init` CLI scaffolds instrumentation files for any framework
|
|
12
|
+
- `securenow init` scaffolds Next.js instrumentation and safe `serverExternalPackages`
|
|
14
13
|
- `securenow/firewall-only` entry point for firewall without tracing overhead
|
|
15
|
-
-
|
|
14
|
+
- Local and production configuration via `.securenow/credentials.json`
|
|
16
15
|
- Single `-r securenow/register` flag -- works for both CJS and ESM apps
|
|
17
16
|
- Native Nuxt 3 module (`securenow/nuxt`)
|
|
18
17
|
|
|
@@ -68,35 +67,26 @@ npx securenow login
|
|
|
68
67
|
|
|
69
68
|
During the browser step, the dashboard enables the selected app's firewall toggle, mints an API key (scoped `firewall:read + blocklist:read + allowlist:read`), and the CLI writes it into `.securenow/credentials.json`. Traces, logs, POST body capture, multipart metadata capture, and firewall protection are enabled by default. No env vars, no copy-pasting keys.
|
|
70
69
|
|
|
71
|
-
For framework scaffolding (Next.js `instrumentation.ts`, etc.) use:
|
|
70
|
+
For framework scaffolding (Next.js `instrumentation.ts`, `next.config.*`, etc.) use:
|
|
72
71
|
|
|
73
72
|
```bash
|
|
74
|
-
npx securenow init
|
|
73
|
+
npx securenow init
|
|
74
|
+
# Optional, when you already have a key and did not use browser login:
|
|
75
|
+
npx securenow init --key snk_live_abc123...
|
|
75
76
|
```
|
|
76
77
|
|
|
77
78
|
This detects your framework and:
|
|
78
|
-
- **
|
|
79
|
+
- **Credentials**: Ensures `.securenow/credentials.json` has secure defaults and explanations
|
|
80
|
+
- **Next.js**: Creates `instrumentation.ts`, adds `serverExternalPackages: ['securenow']` when safe, or prints a Codex/Claude-ready merge prompt for existing files
|
|
79
81
|
- **Nuxt 3**: Suggests adding `securenow/nuxt` to modules
|
|
80
82
|
- **Express / Node.js**: Shows how to add `-r securenow/register` to your start script
|
|
81
|
-
- **All**:
|
|
83
|
+
- **All**: Stores `--key` in `.securenow/credentials.json`; no local `.env` file is needed
|
|
82
84
|
|
|
83
85
|
### 2. Manual Setup
|
|
84
86
|
|
|
85
|
-
####
|
|
86
|
-
|
|
87
|
-
```bash
|
|
88
|
-
# Required: Your application identifier
|
|
89
|
-
export SECURENOW_APPID=my-app
|
|
87
|
+
#### Configure Locally
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
export SECURENOW_INSTANCE=http://your-otlp-collector:4318
|
|
93
|
-
|
|
94
|
-
# Optional: Enable logging
|
|
95
|
-
export SECURENOW_LOGGING_ENABLED=1
|
|
96
|
-
|
|
97
|
-
# Optional: Enable the firewall (set your API key)
|
|
98
|
-
export SECURENOW_API_KEY=snk_live_abc123...
|
|
99
|
-
```
|
|
89
|
+
Run `npx securenow login` to write `.securenow/credentials.json`. The SDK reads app identity, collector URL, firewall key, logging/body-capture defaults, and firewall defaults from that file at boot. Production uses the same file shape via `npx securenow credentials runtime --env production`.
|
|
100
90
|
|
|
101
91
|
#### Run Your Application
|
|
102
92
|
|
|
@@ -161,8 +151,8 @@ npx securenow login
|
|
|
161
151
|
# Or use a token for CI/headless environments
|
|
162
152
|
npx securenow login --token <YOUR_JWT>
|
|
163
153
|
|
|
164
|
-
#
|
|
165
|
-
npx securenow login --
|
|
154
|
+
# Save to ~/.securenow/ instead of this project
|
|
155
|
+
npx securenow login --global
|
|
166
156
|
|
|
167
157
|
# Check who you're logged in as (shows auth source)
|
|
168
158
|
npx securenow whoami
|
|
@@ -179,11 +169,11 @@ npx securenow api-key clear # remove just the key
|
|
|
179
169
|
# Auto-detect framework and scaffold instrumentation files
|
|
180
170
|
npx securenow init
|
|
181
171
|
|
|
182
|
-
# Pass your API key to
|
|
172
|
+
# Pass your API key to store it in .securenow/credentials.json
|
|
183
173
|
npx securenow init --key snk_live_abc123...
|
|
184
174
|
```
|
|
185
175
|
|
|
186
|
-
For Next.js projects, `init` creates `instrumentation.ts` (or `.js` if no TypeScript) and
|
|
176
|
+
For Next.js projects, `init` creates `instrumentation.ts` (or `.js` if no TypeScript), adds `serverExternalPackages: ['securenow']` when safe, and prints exact merge instructions for Codex/Claude when existing files need judgment. For Nuxt, it suggests adding `securenow/nuxt` to your modules. For Express/Node, it shows the `-r securenow/register` flag.
|
|
187
177
|
|
|
188
178
|
### MCP for Codex and Claude
|
|
189
179
|
|
|
@@ -394,7 +384,7 @@ npx securenow redact @request.json --fields internal_id,sessionHash
|
|
|
394
384
|
npx securenow cidr match 10.0.0.5 10.0.0.0/8,192.168.1.0/24 # exit 0 = hit, 2 = miss
|
|
395
385
|
npx securenow cidr parse 10.0.0.0/24 # network, broadcast, mask, size
|
|
396
386
|
|
|
397
|
-
# Show resolved config (service name, endpoints,
|
|
387
|
+
# Show resolved config (service name, endpoints, credentials, firewall layers)
|
|
398
388
|
npx securenow env # human-readable
|
|
399
389
|
npx securenow env --json # pipe to jq
|
|
400
390
|
|
|
@@ -423,10 +413,10 @@ Config files are stored in `~/.securenow/` (global) or `.securenow/` in the proj
|
|
|
423
413
|
| File | Description |
|
|
424
414
|
|------|-------------|
|
|
425
415
|
| `~/.securenow/config.json` | API URL, default app, output format |
|
|
426
|
-
| `~/.securenow/credentials.json` | Auth token
|
|
427
|
-
| `.securenow/credentials.json` | Auth token
|
|
416
|
+
| `~/.securenow/credentials.json` | Auth token, app, API key, config - global (use `login --global`) |
|
|
417
|
+
| `.securenow/credentials.json` | Auth token, app, API key, config, explanations - project-local default |
|
|
428
418
|
|
|
429
|
-
**Resolution order:**
|
|
419
|
+
**Resolution order:** project `.securenow/credentials.json` → global `~/.securenow/credentials.json`. Legacy CLI token overrides still work for existing automation.
|
|
430
420
|
|
|
431
421
|
### Global Flags
|
|
432
422
|
|
|
@@ -449,31 +439,31 @@ Every command supports these flags:
|
|
|
449
439
|
|
|
450
440
|
### Multi-Project Sessions
|
|
451
441
|
|
|
452
|
-
|
|
442
|
+
Project-local credentials are the default, so separate projects can use separate SecureNow apps on the same machine:
|
|
453
443
|
|
|
454
444
|
```bash
|
|
455
445
|
# In project A — log in as user-a@company.com
|
|
456
446
|
cd ~/projects/project-a
|
|
457
|
-
npx securenow login
|
|
447
|
+
npx securenow login
|
|
458
448
|
|
|
459
449
|
# In project B — log in as user-b@company.com
|
|
460
450
|
cd ~/projects/project-b
|
|
461
|
-
npx securenow login
|
|
451
|
+
npx securenow login
|
|
462
452
|
|
|
463
453
|
# Each project uses its own credentials independently
|
|
464
454
|
npx securenow whoami # Shows auth source: project (.securenow/)
|
|
465
455
|
```
|
|
466
456
|
|
|
467
|
-
|
|
457
|
+
For new automation, prefer project-local or runtime credentials files. `SECURENOW_TOKEN` remains a legacy fallback for per-terminal sessions.
|
|
468
458
|
|
|
469
459
|
### CI/CD Integration
|
|
470
460
|
|
|
471
461
|
```bash
|
|
472
|
-
#
|
|
473
|
-
|
|
462
|
+
# Generate a tokenless runtime file from a logged-in project
|
|
463
|
+
npx securenow credentials runtime --env production
|
|
474
464
|
|
|
475
|
-
#
|
|
476
|
-
|
|
465
|
+
# Store .securenow/credentials.production.json as a deployment secret file,
|
|
466
|
+
# then materialize it as .securenow/credentials.json in the running app.
|
|
477
467
|
|
|
478
468
|
# Use --json for machine-readable output
|
|
479
469
|
npx securenow logs --json --level error | jq '.logs'
|
|
@@ -545,7 +535,7 @@ npx securenow logs --json --level error | jq '.logs'
|
|
|
545
535
|
| **Utilities** | `redact '<json>' [--fields f1,f2]` | Redact sensitive fields (accepts `@file.json`) |
|
|
546
536
|
| | `cidr match <ip> <cidrs>` | IP vs. CIDR list (exit 0 hit / 2 miss) |
|
|
547
537
|
| | `cidr parse <cidr>` | Parse CIDR (network, broadcast, mask, size) |
|
|
548
|
-
| | `env [--json]` | Show resolved config (service name, endpoints,
|
|
538
|
+
| | `env [--json]` | Show resolved config (service name, endpoints, credentials) |
|
|
549
539
|
| | `doctor [--json]` | Probe OTLP + API endpoints, check config |
|
|
550
540
|
| **Settings** | `instances` | List instances |
|
|
551
541
|
| | `instances test <id>` | Test connection |
|
|
@@ -598,19 +588,11 @@ module.exports = {
|
|
|
598
588
|
name: 'my-app',
|
|
599
589
|
script: './app.js',
|
|
600
590
|
node_args: '-r securenow/register',
|
|
601
|
-
env: {
|
|
602
|
-
SECURENOW_APPID: 'your-app-key',
|
|
603
|
-
SECURENOW_INSTANCE: 'https://freetrial.securenow.ai:4318',
|
|
604
|
-
SECURENOW_API_KEY: 'snk_live_abc123...',
|
|
605
|
-
SECURENOW_LOGGING_ENABLED: '1',
|
|
606
|
-
SECURENOW_NO_UUID: '1',
|
|
607
|
-
SECURENOW_CAPTURE_BODY: '1',
|
|
608
|
-
}
|
|
609
591
|
}]
|
|
610
592
|
};
|
|
611
593
|
```
|
|
612
594
|
|
|
613
|
-
> **Important:**
|
|
595
|
+
> **Important:** Put `.securenow/credentials.json` in the PM2 app root and keep `node_args: '-r securenow/register'`. PM2 restarts will then load the SDK, traces/logs, body capture, and firewall without any SecureNow env vars.
|
|
614
596
|
|
|
615
597
|
---
|
|
616
598
|
|
|
@@ -955,70 +937,50 @@ app.listen(3000, () => console.log('Feathers running on port 3000'));
|
|
|
955
937
|
|
|
956
938
|
See [Next.js Complete Guide](./docs/NEXTJS-SETUP-COMPLETE.md) for the full reference.
|
|
957
939
|
|
|
958
|
-
#### Option A: `
|
|
959
|
-
|
|
960
|
-
One wrapper handles everything: `serverExternalPackages` (Next 15) or `experimental.serverComponentsExternalPackages` (Next 14), `instrumentationHook`, and webpack warning suppression.
|
|
940
|
+
#### Option A: `securenow init` (Recommended)
|
|
961
941
|
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
```javascript
|
|
965
|
-
const { withSecureNow } = require('securenow/nextjs-webpack-config');
|
|
942
|
+
The init command handles the boring parts: credentials defaults, `instrumentation.ts`, body auto-capture, and `serverExternalPackages` for Next 15+. If existing files are custom, it prints a Codex/Claude-ready prompt instead of guessing.
|
|
966
943
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
944
|
+
```bash
|
|
945
|
+
npx securenow login
|
|
946
|
+
npx securenow init
|
|
970
947
|
```
|
|
971
948
|
|
|
972
|
-
**
|
|
949
|
+
**Generated `instrumentation.ts` (or `.js`):**
|
|
973
950
|
|
|
974
951
|
```typescript
|
|
952
|
+
import { createRequire } from 'node:module';
|
|
953
|
+
|
|
954
|
+
const require = createRequire(import.meta.url);
|
|
955
|
+
|
|
975
956
|
export async function register() {
|
|
976
|
-
if (process.env.NEXT_RUNTIME
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
957
|
+
if (process.env.NEXT_RUNTIME !== 'nodejs') return;
|
|
958
|
+
const { registerSecureNow } = require('securenow/nextjs');
|
|
959
|
+
registerSecureNow({ captureBody: true });
|
|
960
|
+
require('securenow/nextjs-auto-capture');
|
|
980
961
|
}
|
|
981
962
|
```
|
|
982
963
|
|
|
983
|
-
|
|
964
|
+
**Next.js 15+ `next.config.*`:**
|
|
984
965
|
|
|
985
|
-
|
|
966
|
+
```javascript
|
|
967
|
+
const nextConfig = {
|
|
968
|
+
serverExternalPackages: ['securenow'],
|
|
969
|
+
};
|
|
986
970
|
|
|
987
|
-
|
|
988
|
-
SECURENOW_APPID=my-nextjs-app
|
|
989
|
-
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
990
|
-
SECURENOW_API_KEY=snk_live_abc123...
|
|
991
|
-
SECURENOW_LOGGING_ENABLED=1
|
|
992
|
-
SECURENOW_NO_UUID=1
|
|
971
|
+
export default nextConfig;
|
|
993
972
|
```
|
|
994
973
|
|
|
995
|
-
|
|
996
|
-
- **Next.js 15+**: Sets `serverExternalPackages` with all 13 required OTel packages
|
|
997
|
-
- **Next.js 14**: Sets `experimental.serverComponentsExternalPackages` and `experimental.instrumentationHook: true`
|
|
998
|
-
- **Both**: Suppresses webpack warnings from OpenTelemetry instrumentation packages
|
|
974
|
+
No `.env.local` is needed locally or in production. Use `npx securenow credentials runtime --env production` and mount/copy the resulting JSON as `.securenow/credentials.json`.
|
|
999
975
|
|
|
1000
976
|
#### Option B: Manual configuration
|
|
1001
977
|
|
|
1002
|
-
If you prefer not to
|
|
978
|
+
If you prefer not to run `init`, manually externalize SecureNow:
|
|
1003
979
|
|
|
1004
980
|
```javascript
|
|
1005
981
|
// next.config.js (Next.js 15+)
|
|
1006
982
|
module.exports = {
|
|
1007
|
-
serverExternalPackages: [
|
|
1008
|
-
'securenow',
|
|
1009
|
-
'@opentelemetry/sdk-node',
|
|
1010
|
-
'@opentelemetry/auto-instrumentations-node',
|
|
1011
|
-
'@opentelemetry/instrumentation-http',
|
|
1012
|
-
'@opentelemetry/exporter-trace-otlp-http',
|
|
1013
|
-
'@opentelemetry/exporter-logs-otlp-http',
|
|
1014
|
-
'@opentelemetry/sdk-logs',
|
|
1015
|
-
'@opentelemetry/instrumentation',
|
|
1016
|
-
'@opentelemetry/resources',
|
|
1017
|
-
'@opentelemetry/semantic-conventions',
|
|
1018
|
-
'@opentelemetry/api',
|
|
1019
|
-
'@opentelemetry/api-logs',
|
|
1020
|
-
'@vercel/otel',
|
|
1021
|
-
],
|
|
983
|
+
serverExternalPackages: ['securenow'],
|
|
1022
984
|
};
|
|
1023
985
|
```
|
|
1024
986
|
|
|
@@ -1027,26 +989,12 @@ module.exports = {
|
|
|
1027
989
|
module.exports = {
|
|
1028
990
|
experimental: {
|
|
1029
991
|
instrumentationHook: true,
|
|
1030
|
-
serverComponentsExternalPackages: [
|
|
1031
|
-
'securenow',
|
|
1032
|
-
'@opentelemetry/sdk-node',
|
|
1033
|
-
'@opentelemetry/auto-instrumentations-node',
|
|
1034
|
-
'@opentelemetry/instrumentation-http',
|
|
1035
|
-
'@opentelemetry/exporter-trace-otlp-http',
|
|
1036
|
-
'@opentelemetry/exporter-logs-otlp-http',
|
|
1037
|
-
'@opentelemetry/sdk-logs',
|
|
1038
|
-
'@opentelemetry/instrumentation',
|
|
1039
|
-
'@opentelemetry/resources',
|
|
1040
|
-
'@opentelemetry/semantic-conventions',
|
|
1041
|
-
'@opentelemetry/api',
|
|
1042
|
-
'@opentelemetry/api-logs',
|
|
1043
|
-
'@vercel/otel',
|
|
1044
|
-
],
|
|
992
|
+
serverComponentsExternalPackages: ['securenow'],
|
|
1045
993
|
},
|
|
1046
994
|
};
|
|
1047
995
|
```
|
|
1048
996
|
|
|
1049
|
-
**Why is this needed?** Next.js bundles server code with webpack, which
|
|
997
|
+
**Why is this needed?** Next.js bundles server code with webpack, which can break OpenTelemetry's dynamic `require()` calls and monkey-patching. Externalizing `securenow` keeps the SDK as normal Node.js runtime code.
|
|
1050
998
|
|
|
1051
999
|
---
|
|
1052
1000
|
|
|
@@ -1064,13 +1012,7 @@ export default defineNuxtConfig({
|
|
|
1064
1012
|
});
|
|
1065
1013
|
```
|
|
1066
1014
|
|
|
1067
|
-
`.
|
|
1068
|
-
|
|
1069
|
-
```env
|
|
1070
|
-
SECURENOW_APPID=my-nuxt-app
|
|
1071
|
-
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
1072
|
-
SECURENOW_API_KEY=snk_live_abc123...
|
|
1073
|
-
```
|
|
1015
|
+
Local and production app identity and secure defaults come from `.securenow/credentials.json`.
|
|
1074
1016
|
|
|
1075
1017
|
That's it -- the Nuxt module handles OTel SDK initialization, Nitro externalization, firewall activation, and request tracing automatically. Optional config:
|
|
1076
1018
|
|
|
@@ -1103,14 +1045,14 @@ The Nuxt server plugin (v5.13.0+) initializes the firewall independently from Op
|
|
|
1103
1045
|
| Micro/HTTP | Yes | Yes | Yes | Yes | Full control |
|
|
1104
1046
|
| Hono | Yes | Yes | Yes | Yes | Use ESM `-r` preload |
|
|
1105
1047
|
| Feathers | Yes | Yes | Yes | Yes | Uses Express transport |
|
|
1106
|
-
| Next.js | Yes | Yes | Yes | Yes | Use `instrumentation.ts` + `
|
|
1048
|
+
| Next.js | Yes | Yes | Yes | Yes | Use `instrumentation.ts` + `serverExternalPackages: ['securenow']` |
|
|
1107
1049
|
| Nuxt 3 | Yes | Yes | Yes | Yes | Use `securenow/nuxt` module |
|
|
1108
1050
|
|
|
1109
1051
|
---
|
|
1110
1052
|
|
|
1111
1053
|
## Firewall -- Automatic IP Blocking
|
|
1112
1054
|
|
|
1113
|
-
SecureNow can automatically block IPs from your blocklist at the application layer. No code changes --
|
|
1055
|
+
SecureNow can automatically block IPs from your blocklist at the application layer. No code changes -- provide an API key via `securenow login`, the `api-key` CLI, or a runtime credentials file and the firewall activates.
|
|
1114
1056
|
|
|
1115
1057
|
### Firewall Is Enabled by Default
|
|
1116
1058
|
|
|
@@ -1124,12 +1066,11 @@ npx securenow login
|
|
|
1124
1066
|
# (b) Already have a key? Write it to the creds file directly:
|
|
1125
1067
|
npx securenow api-key set snk_live_abc123...
|
|
1126
1068
|
|
|
1127
|
-
# (c)
|
|
1128
|
-
|
|
1129
|
-
SECURENOW_API_KEY=snk_live_abc123...
|
|
1069
|
+
# (c) Production? Generate a tokenless runtime credentials file:
|
|
1070
|
+
npx securenow credentials runtime --env production
|
|
1130
1071
|
```
|
|
1131
1072
|
|
|
1132
|
-
The SDK resolves the firewall key
|
|
1073
|
+
The SDK resolves the firewall key from project `./.securenow/credentials.json`, then global `~/.securenow/credentials.json`. Legacy `SECURENOW_API_KEY` overrides still work for existing deployments.
|
|
1133
1074
|
|
|
1134
1075
|
On startup, you'll see:
|
|
1135
1076
|
|
|
@@ -1178,15 +1119,11 @@ This is useful when:
|
|
|
1178
1119
|
- You're adding the firewall to a project that uses a different tracing solution
|
|
1179
1120
|
- For Next.js, this avoids the need for `serverExternalPackages` entirely
|
|
1180
1121
|
|
|
1181
|
-
|
|
1122
|
+
Firewall-only mode uses the same `.securenow/credentials.json` key written by `login`, `api-key set`, or mounted from a runtime credentials file:
|
|
1182
1123
|
|
|
1183
1124
|
```bash
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
SECURENOW_FIREWALL_ENABLED=1 # Default: 1
|
|
1187
|
-
SECURENOW_FIREWALL_TCP=1 # Optional: Layer 2
|
|
1188
|
-
SECURENOW_FIREWALL_IPTABLES=1 # Optional: Layer 3
|
|
1189
|
-
SECURENOW_FIREWALL_CLOUD=cloudflare # Optional: Layer 4
|
|
1125
|
+
npx securenow credentials runtime --env production
|
|
1126
|
+
node -r securenow/firewall-only app.js
|
|
1190
1127
|
```
|
|
1191
1128
|
|
|
1192
1129
|
### Blocking Layers
|
|
@@ -1220,14 +1157,34 @@ See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
|
|
|
1220
1157
|
|
|
1221
1158
|
---
|
|
1222
1159
|
|
|
1223
|
-
##
|
|
1160
|
+
## Credentials Configuration
|
|
1161
|
+
|
|
1162
|
+
Local development and production use `.securenow/credentials.json`. Run `npx securenow login` and `npx securenow init`; for production, run `npx securenow credentials runtime --env production` and mount/copy the generated JSON as `.securenow/credentials.json`.
|
|
1163
|
+
|
|
1164
|
+
See [docs/ENVIRONMENT-VARIABLES.md](./docs/ENVIRONMENT-VARIABLES.md) and [docs/ENVIRONMENTS.md](./docs/ENVIRONMENTS.md) for the full credentials and environment reference.
|
|
1165
|
+
|
|
1166
|
+
### Credentials Fields
|
|
1224
1167
|
|
|
1225
|
-
|
|
1168
|
+
| Field | Description | Default |
|
|
1169
|
+
|----------|-------------|---------|
|
|
1170
|
+
| `app.key` | SecureNow app routing UUID / OTel service name. | chosen during login |
|
|
1171
|
+
| `app.instance` | OTLP collector base URL. | `https://freetrial.securenow.ai:4318` |
|
|
1172
|
+
| `apiKey` | Scoped firewall key (`snk_live_...`). | minted during login |
|
|
1173
|
+
| `config.runtime.deploymentEnvironment` | `deployment.environment` trace/log scope. | `local` from init, `production` from runtime credentials |
|
|
1174
|
+
| `config.logging.enabled` | Automatic console log export. | `true` |
|
|
1175
|
+
| `config.capture.body` | Request body capture with redaction. | `true` |
|
|
1176
|
+
| `config.capture.multipart` | Multipart metadata capture, never file content. | `true` |
|
|
1177
|
+
| `config.firewall.enabled` | Local SDK firewall switch; dashboard toggle is per environment. | `true` |
|
|
1178
|
+
| `config.otel.*` | Optional custom endpoints, headers, and log level. | empty |
|
|
1179
|
+
|
|
1180
|
+
Legacy env fallback aliases are listed below for existing installs only.
|
|
1181
|
+
|
|
1182
|
+
### Legacy App Identity Fallbacks
|
|
1226
1183
|
|
|
1227
1184
|
| Variable | Description | Example |
|
|
1228
1185
|
|----------|-------------|---------|
|
|
1229
|
-
| `SECURENOW_APPID` |
|
|
1230
|
-
| `SECURENOW_INSTANCE` | Base URL of your OTLP collector endpoint. | `
|
|
1186
|
+
| `SECURENOW_APPID` | Fallback for missing credentials `app.key`. Used as the app routing key/service name. | `<uuid>` |
|
|
1187
|
+
| `SECURENOW_INSTANCE` | Fallback for missing credentials `app.instance`. Base URL of your OTLP collector endpoint. | `https://freetrial.securenow.ai:4318` |
|
|
1231
1188
|
|
|
1232
1189
|
### Optional Configuration
|
|
1233
1190
|
|
|
@@ -1235,18 +1192,18 @@ See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
|
|
|
1235
1192
|
|
|
1236
1193
|
| Variable | Description | Default |
|
|
1237
1194
|
|----------|-------------|---------|
|
|
1238
|
-
| `OTEL_SERVICE_NAME` |
|
|
1239
|
-
| `SECURENOW_NO_UUID` |
|
|
1240
|
-
| `SECURENOW_STRICT` |
|
|
1195
|
+
| `OTEL_SERVICE_NAME` | Fallback for missing `app.name`. Standard OpenTelemetry variable. | - |
|
|
1196
|
+
| `SECURENOW_NO_UUID` | Legacy fallback for `config.runtime.noUuid`. | `0` |
|
|
1197
|
+
| `SECURENOW_STRICT` | Legacy fallback for `config.runtime.strict`. | `0` |
|
|
1241
1198
|
|
|
1242
1199
|
#### Connection Settings
|
|
1243
1200
|
|
|
1244
1201
|
| Variable | Description | Default |
|
|
1245
1202
|
|----------|-------------|---------|
|
|
1246
|
-
| `OTEL_EXPORTER_OTLP_ENDPOINT` |
|
|
1247
|
-
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` |
|
|
1248
|
-
| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` |
|
|
1249
|
-
| `OTEL_EXPORTER_OTLP_HEADERS` |
|
|
1203
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Fallback for `config.otel.endpoint`. | - |
|
|
1204
|
+
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Fallback for `config.otel.tracesEndpoint`. | `{instance}/v1/traces` |
|
|
1205
|
+
| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Fallback for `config.otel.logsEndpoint`. | `{instance}/v1/logs` |
|
|
1206
|
+
| `OTEL_EXPORTER_OTLP_HEADERS` | Fallback for `config.otel.headers`. Format: `key1=value1,key2=value2` | - |
|
|
1250
1207
|
|
|
1251
1208
|
#### Logging
|
|
1252
1209
|
|
|
@@ -1277,7 +1234,7 @@ See the [Firewall Guide](./docs/FIREWALL-GUIDE.md) for the full reference.
|
|
|
1277
1234
|
|
|
1278
1235
|
| Variable | Description | Default |
|
|
1279
1236
|
|----------|-------------|---------|
|
|
1280
|
-
| `SECURENOW_API_KEY` |
|
|
1237
|
+
| `SECURENOW_API_KEY` | Legacy firewall key override. Prefer `apiKey` in `.securenow/credentials.json`. | from creds file |
|
|
1281
1238
|
| `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` |
|
|
1282
1239
|
| `SECURENOW_FIREWALL_ENABLED` | Master kill-switch. Set to `0` to disable. | `1` |
|
|
1283
1240
|
| `SECURENOW_FIREWALL_VERSION_INTERVAL` | Seconds between version checks (lightweight ETag-based). | `10` |
|
|
@@ -1304,7 +1261,7 @@ See [Firewall Guide](./docs/FIREWALL-GUIDE.md) for complete details on all layer
|
|
|
1304
1261
|
|
|
1305
1262
|
| Variable | Description | Default |
|
|
1306
1263
|
|----------|-------------|---------|
|
|
1307
|
-
| `
|
|
1264
|
+
| `SECURENOW_ENVIRONMENT` / `SECURENOW_DEPLOYMENT_ENVIRONMENT` / `NODE_ENV` | Fallback for `config.runtime.deploymentEnvironment`. | `production` |
|
|
1308
1265
|
|
|
1309
1266
|
---
|
|
1310
1267
|
|
|
@@ -1388,11 +1345,7 @@ logger.emit({
|
|
|
1388
1345
|
|
|
1389
1346
|
```bash
|
|
1390
1347
|
# Enable tracing + logging (console auto-forwarding is built-in since v5.6.0)
|
|
1391
|
-
|
|
1392
|
-
SECURENOW_APPID=my-app \
|
|
1393
|
-
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318 \
|
|
1394
|
-
SECURENOW_LOGGING_ENABLED=1 \
|
|
1395
|
-
node app.js
|
|
1348
|
+
node -r securenow/register app.js
|
|
1396
1349
|
```
|
|
1397
1350
|
|
|
1398
1351
|
---
|
|
@@ -1472,41 +1425,34 @@ export SECURENOW_SENSITIVE_FIELDS="custom_secret,internal_token"
|
|
|
1472
1425
|
|
|
1473
1426
|
### Complete Example with All Options
|
|
1474
1427
|
|
|
1475
|
-
```
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
export OTEL_LOG_LEVEL=info
|
|
1504
|
-
|
|
1505
|
-
# Disable specific instrumentations
|
|
1506
|
-
export SECURENOW_DISABLE_INSTRUMENTATIONS=fs,dns
|
|
1507
|
-
|
|
1508
|
-
# Run application
|
|
1509
|
-
NODE_OPTIONS="-r securenow/register" node app.js
|
|
1428
|
+
```json
|
|
1429
|
+
{
|
|
1430
|
+
"apiKey": "snk_live_...",
|
|
1431
|
+
"app": {
|
|
1432
|
+
"key": "my-production-app",
|
|
1433
|
+
"name": "my-production-app",
|
|
1434
|
+
"instance": "http://collector.example.com:4318"
|
|
1435
|
+
},
|
|
1436
|
+
"config": {
|
|
1437
|
+
"runtime": { "noUuid": true, "strict": true, "deploymentEnvironment": "production" },
|
|
1438
|
+
"otel": {
|
|
1439
|
+
"headers": { "x-api-key": "your-api-key" },
|
|
1440
|
+
"logLevel": "info",
|
|
1441
|
+
"disableInstrumentations": ["fs", "dns"]
|
|
1442
|
+
},
|
|
1443
|
+
"logging": { "enabled": true },
|
|
1444
|
+
"capture": {
|
|
1445
|
+
"body": true,
|
|
1446
|
+
"maxBodySize": 20480,
|
|
1447
|
+
"sensitiveFields": ["internal_id", "session_key"]
|
|
1448
|
+
},
|
|
1449
|
+
"firewall": {
|
|
1450
|
+
"tcp": true,
|
|
1451
|
+
"versionCheckInterval": 10,
|
|
1452
|
+
"syncInterval": 300
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1510
1456
|
```
|
|
1511
1457
|
|
|
1512
1458
|
### Using Multiple Logger Instances
|
|
@@ -1547,15 +1493,10 @@ if (isLoggingEnabled()) {
|
|
|
1547
1493
|
|
|
1548
1494
|
### Programmatic Configuration
|
|
1549
1495
|
|
|
1550
|
-
|
|
1496
|
+
Use `.securenow/credentials.json` for local development, tests, CI, and production:
|
|
1551
1497
|
|
|
1552
1498
|
```javascript
|
|
1553
|
-
//
|
|
1554
|
-
process.env.SECURENOW_APPID = 'my-app';
|
|
1555
|
-
process.env.SECURENOW_INSTANCE = 'http://localhost:4318';
|
|
1556
|
-
process.env.SECURENOW_LOGGING_ENABLED = '1';
|
|
1557
|
-
|
|
1558
|
-
// Then initialize (console log forwarding is automatic since v5.6.0)
|
|
1499
|
+
// Reads .securenow/credentials.json from the project root.
|
|
1559
1500
|
require('securenow/register');
|
|
1560
1501
|
```
|
|
1561
1502
|
|
|
@@ -1636,14 +1577,14 @@ bootstrap();
|
|
|
1636
1577
|
|
|
1637
1578
|
### Traces Not Appearing
|
|
1638
1579
|
|
|
1639
|
-
**Check 1: Verify
|
|
1580
|
+
**Check 1: Verify credentials resolution**
|
|
1640
1581
|
|
|
1641
1582
|
```bash
|
|
1642
|
-
|
|
1643
|
-
|
|
1583
|
+
npx securenow env
|
|
1584
|
+
npx securenow status --env local
|
|
1644
1585
|
```
|
|
1645
1586
|
|
|
1646
|
-
|
|
1587
|
+
The output should show an app key, collector endpoint, and deployment environment from `.securenow/credentials.json`.
|
|
1647
1588
|
|
|
1648
1589
|
**Check 2: Verify OTLP collector is running**
|
|
1649
1590
|
|
|
@@ -1652,11 +1593,14 @@ curl http://localhost:4318/v1/traces
|
|
|
1652
1593
|
# Should return 200 or 405 (method not allowed)
|
|
1653
1594
|
```
|
|
1654
1595
|
|
|
1655
|
-
**Check 3: Enable debug logging**
|
|
1596
|
+
**Check 3: Enable debug logging in credentials**
|
|
1656
1597
|
|
|
1657
|
-
```
|
|
1658
|
-
|
|
1659
|
-
|
|
1598
|
+
```json
|
|
1599
|
+
{
|
|
1600
|
+
"config": {
|
|
1601
|
+
"otel": { "logLevel": "debug" }
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1660
1604
|
```
|
|
1661
1605
|
|
|
1662
1606
|
Look for lines like:
|
|
@@ -1680,10 +1624,10 @@ require('securenow/register');
|
|
|
1680
1624
|
|
|
1681
1625
|
### Firewall Not Blocking IPs
|
|
1682
1626
|
|
|
1683
|
-
**Check 1: Is
|
|
1627
|
+
**Check 1: Is an API key in `.securenow/credentials.json`?**
|
|
1684
1628
|
|
|
1685
1629
|
```bash
|
|
1686
|
-
|
|
1630
|
+
npx securenow api-key show
|
|
1687
1631
|
```
|
|
1688
1632
|
|
|
1689
1633
|
**Check 2: Is the IP in the blocklist?**
|
|
@@ -1709,7 +1653,7 @@ After blocking an IP, it takes 10-15 seconds to propagate (one version-check int
|
|
|
1709
1653
|
|
|
1710
1654
|
**Check 5: Are you behind a proxy?**
|
|
1711
1655
|
|
|
1712
|
-
|
|
1656
|
+
Add your proxy IPs to `config.networking.trustedProxies` in `.securenow/credentials.json` so the firewall sees the real client IP.
|
|
1713
1657
|
|
|
1714
1658
|
**Check 6: Using PM2?**
|
|
1715
1659
|
|
|
@@ -1719,9 +1663,12 @@ Make sure `node_args: '-r securenow/register'` is in your `ecosystem.config.cjs`
|
|
|
1719
1663
|
|
|
1720
1664
|
**Check 1: Is logging enabled?**
|
|
1721
1665
|
|
|
1722
|
-
```
|
|
1723
|
-
|
|
1724
|
-
|
|
1666
|
+
```json
|
|
1667
|
+
{
|
|
1668
|
+
"config": {
|
|
1669
|
+
"logging": { "enabled": true }
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1725
1672
|
```
|
|
1726
1673
|
|
|
1727
1674
|
**Check 2: Verify console instrumentation is loaded**
|
|
@@ -1748,9 +1695,12 @@ curl http://localhost:4318/v1/logs
|
|
|
1748
1695
|
|
|
1749
1696
|
**Check 1: Make sure body capture was not explicitly disabled**
|
|
1750
1697
|
|
|
1751
|
-
```
|
|
1752
|
-
|
|
1753
|
-
|
|
1698
|
+
```json
|
|
1699
|
+
{
|
|
1700
|
+
"config": {
|
|
1701
|
+
"capture": { "body": true }
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1754
1704
|
```
|
|
1755
1705
|
|
|
1756
1706
|
**Check 2: Verify content type**
|
|
@@ -1762,42 +1712,59 @@ Body capture only works for:
|
|
|
1762
1712
|
|
|
1763
1713
|
**Check 3: Check body size**
|
|
1764
1714
|
|
|
1765
|
-
Bodies larger than `
|
|
1715
|
+
Bodies larger than `config.capture.maxBodySize` are truncated:
|
|
1766
1716
|
|
|
1767
|
-
```
|
|
1768
|
-
|
|
1717
|
+
```json
|
|
1718
|
+
{
|
|
1719
|
+
"config": {
|
|
1720
|
+
"capture": { "maxBodySize": 20480 }
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1769
1723
|
```
|
|
1770
1724
|
|
|
1771
1725
|
### High Memory Usage
|
|
1772
1726
|
|
|
1773
1727
|
**Option 1: Disable body capture**
|
|
1774
1728
|
|
|
1775
|
-
```
|
|
1776
|
-
|
|
1729
|
+
```json
|
|
1730
|
+
{
|
|
1731
|
+
"config": {
|
|
1732
|
+
"capture": { "body": false }
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1777
1735
|
```
|
|
1778
1736
|
|
|
1779
1737
|
**Option 2: Reduce body size limit**
|
|
1780
1738
|
|
|
1781
|
-
```
|
|
1782
|
-
|
|
1739
|
+
```json
|
|
1740
|
+
{
|
|
1741
|
+
"config": {
|
|
1742
|
+
"capture": { "maxBodySize": 5120 }
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1783
1745
|
```
|
|
1784
1746
|
|
|
1785
1747
|
**Option 3: Disable specific instrumentations**
|
|
1786
1748
|
|
|
1787
|
-
```
|
|
1788
|
-
|
|
1749
|
+
```json
|
|
1750
|
+
{
|
|
1751
|
+
"config": {
|
|
1752
|
+
"otel": { "disableInstrumentations": ["fs", "dns", "net"] }
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1789
1755
|
```
|
|
1790
1756
|
|
|
1791
1757
|
### Next.js Instrumentation Not Working
|
|
1792
1758
|
|
|
1793
|
-
**Check 1:
|
|
1759
|
+
**Check 1: Is `securenow` externalized?**
|
|
1794
1760
|
|
|
1795
1761
|
```javascript
|
|
1796
|
-
|
|
1797
|
-
|
|
1762
|
+
module.exports = {
|
|
1763
|
+
serverExternalPackages: ['securenow'],
|
|
1764
|
+
};
|
|
1798
1765
|
```
|
|
1799
1766
|
|
|
1800
|
-
|
|
1767
|
+
For Next.js < 15, add `securenow` to `experimental.serverComponentsExternalPackages` and enable `experimental.instrumentationHook`.
|
|
1801
1768
|
|
|
1802
1769
|
**Check 2: Verify instrumentation file location**
|
|
1803
1770
|
|
|
@@ -1805,7 +1772,7 @@ This auto-handles `serverExternalPackages` / `experimental.serverComponentsExter
|
|
|
1805
1772
|
|
|
1806
1773
|
**Check 3: Check for OTel MODULE_NOT_FOUND errors**
|
|
1807
1774
|
|
|
1808
|
-
If you see `MODULE_NOT_FOUND` for `@opentelemetry/*` packages, your `next.config.js` is missing the externalization.
|
|
1775
|
+
If you see `MODULE_NOT_FOUND` for `@opentelemetry/*` packages, your `next.config.js` is missing the externalization. Run `npx securenow init`; if your config is custom, use the prompt it prints to merge the edit safely.
|
|
1809
1776
|
|
|
1810
1777
|
**Check 4: Restart dev server**
|
|
1811
1778
|
|
|
@@ -1818,10 +1785,14 @@ npm run dev
|
|
|
1818
1785
|
|
|
1819
1786
|
**Problem: Different service names for each worker**
|
|
1820
1787
|
|
|
1821
|
-
**Solution:
|
|
1788
|
+
**Solution: Set `config.runtime.noUuid`**
|
|
1822
1789
|
|
|
1823
|
-
```
|
|
1824
|
-
|
|
1790
|
+
```json
|
|
1791
|
+
{
|
|
1792
|
+
"config": {
|
|
1793
|
+
"runtime": { "noUuid": true }
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1825
1796
|
```
|
|
1826
1797
|
|
|
1827
1798
|
This uses the same service name for all workers.
|
|
@@ -1838,11 +1809,6 @@ module.exports = {
|
|
|
1838
1809
|
script: './app.js',
|
|
1839
1810
|
instances: 4,
|
|
1840
1811
|
node_args: '-r securenow/register',
|
|
1841
|
-
env: {
|
|
1842
|
-
SECURENOW_APPID: 'my-app',
|
|
1843
|
-
SECURENOW_INSTANCE: 'http://localhost:4318',
|
|
1844
|
-
SECURENOW_API_KEY: 'snk_live_abc123...',
|
|
1845
|
-
}
|
|
1846
1812
|
}]
|
|
1847
1813
|
};
|
|
1848
1814
|
```
|
|
@@ -1853,18 +1819,16 @@ Without `node_args`, PM2 starts your script directly without the securenow prelo
|
|
|
1853
1819
|
|
|
1854
1820
|
## Best Practices
|
|
1855
1821
|
|
|
1856
|
-
### 1. Use
|
|
1822
|
+
### 1. Use the Credentials File
|
|
1857
1823
|
|
|
1858
|
-
|
|
1824
|
+
Do not hardcode configuration in code or deployment dashboards. Use `.securenow/credentials.json` locally and mount the tokenless runtime file in production:
|
|
1859
1825
|
|
|
1860
1826
|
```javascript
|
|
1861
1827
|
// Bad
|
|
1862
1828
|
process.env.SECURENOW_APPID = 'hardcoded-value';
|
|
1863
1829
|
|
|
1864
|
-
// Good
|
|
1865
|
-
// .
|
|
1866
|
-
SECURENOW_APPID=my-app
|
|
1867
|
-
SECURENOW_INSTANCE=http://localhost:4318
|
|
1830
|
+
// Good: use .securenow/credentials.json
|
|
1831
|
+
// { "app": { "key": "my-app", "instance": "https://freetrial.securenow.ai:4318" } }
|
|
1868
1832
|
```
|
|
1869
1833
|
|
|
1870
1834
|
### 2. Use Structured Logging
|
|
@@ -1933,12 +1897,12 @@ const apiLogger = getLogger('api', '1.0.0');
|
|
|
1933
1897
|
|
|
1934
1898
|
### 6. Disable Body Capture Outside Development
|
|
1935
1899
|
|
|
1936
|
-
```
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1900
|
+
```json
|
|
1901
|
+
{
|
|
1902
|
+
"config": {
|
|
1903
|
+
"capture": { "body": false }
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1942
1906
|
```
|
|
1943
1907
|
|
|
1944
1908
|
---
|