securenow 6.0.2 → 6.1.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 +455 -0
- package/NPM_README.md +2029 -0
- package/README.md +297 -40
- package/SKILL-API.md +634 -0
- package/SKILL-CLI.md +454 -0
- package/cidr.js +83 -0
- package/cli/apps.js +585 -0
- package/cli/auth.js +280 -0
- package/cli/client.js +115 -0
- package/cli/config.js +173 -0
- package/cli/diagnostics.js +387 -0
- package/cli/firewall.js +100 -0
- package/cli/fp.js +638 -0
- package/cli/init.js +201 -0
- package/cli/monitor.js +440 -0
- package/cli/run.js +148 -0
- package/cli/security.js +980 -0
- package/cli/ui.js +386 -0
- package/cli/utils.js +127 -0
- package/cli.js +466 -455
- package/console-instrumentation.js +147 -136
- package/docs/ALL-FRAMEWORKS-QUICKSTART.md +1377 -455
- package/docs/API-KEYS-GUIDE.md +233 -0
- package/docs/ARCHITECTURE.md +3 -3
- package/docs/AUTO-BODY-CAPTURE.md +1 -1
- package/docs/AUTO-SETUP-SUMMARY.md +331 -0
- package/docs/AUTO-SETUP.md +4 -4
- package/docs/AUTOMATIC-IP-CAPTURE.md +5 -5
- package/docs/BODY-CAPTURE-FIX.md +261 -0
- package/docs/BODY-CAPTURE-QUICKSTART.md +2 -2
- package/docs/CHANGELOG-NEXTJS.md +1 -35
- package/docs/COMPLETION-REPORT.md +408 -0
- package/docs/CUSTOMER-GUIDE.md +16 -16
- package/docs/EASIEST-SETUP.md +5 -5
- package/docs/ENVIRONMENT-VARIABLES.md +880 -652
- package/docs/EXPRESS-BODY-CAPTURE.md +13 -12
- package/docs/EXPRESS-SETUP-GUIDE.md +719 -720
- package/docs/FINAL-SOLUTION.md +335 -0
- package/docs/FIREWALL-GUIDE.md +426 -0
- package/docs/IMPLEMENTATION-SUMMARY.md +410 -0
- package/docs/INDEX.md +22 -4
- package/docs/LOGGING-GUIDE.md +701 -708
- package/docs/LOGGING-QUICKSTART.md +234 -255
- package/docs/NEXTJS-BODY-CAPTURE-COMPARISON.md +323 -0
- package/docs/NEXTJS-BODY-CAPTURE.md +2 -2
- package/docs/NEXTJS-GUIDE.md +14 -14
- package/docs/NEXTJS-QUICKSTART.md +1 -1
- package/docs/NEXTJS-SETUP-COMPLETE.md +795 -0
- package/docs/NEXTJS-WRAPPER-APPROACH.md +1 -1
- package/docs/NUXT-GUIDE.md +166 -0
- package/docs/QUICKSTART-BODY-CAPTURE.md +2 -2
- package/docs/REDACTION-EXAMPLES.md +1 -1
- package/docs/REQUEST-BODY-CAPTURE.md +19 -10
- package/docs/SOLUTION-SUMMARY.md +312 -0
- package/docs/VERCEL-OTEL-MIGRATION.md +3 -3
- package/examples/README.md +6 -6
- package/examples/instrumentation-with-auto-capture.ts +1 -1
- package/examples/nextjs-env-example.txt +2 -2
- package/examples/nextjs-instrumentation.js +1 -1
- package/examples/nextjs-instrumentation.ts +1 -1
- package/examples/nextjs-with-logging-example.md +6 -6
- package/examples/nextjs-with-options.ts +1 -1
- package/examples/test-nextjs-setup.js +1 -1
- package/firewall-cloud.js +212 -0
- package/firewall-iptables.js +139 -0
- package/firewall-only.js +38 -0
- package/firewall-tcp.js +74 -0
- package/firewall.js +720 -0
- package/free-trial-banner.js +174 -0
- package/nextjs-auto-capture.js +199 -207
- package/nextjs-middleware.js +186 -181
- package/nextjs-webpack-config.js +88 -53
- package/nextjs-wrapper.js +158 -158
- package/nextjs.d.ts +1 -1
- package/nextjs.js +639 -647
- package/nuxt-server-plugin.mjs +423 -0
- package/nuxt.d.ts +60 -0
- package/nuxt.mjs +75 -0
- package/package.json +186 -164
- package/postinstall.js +6 -6
- package/register.d.ts +1 -1
- package/register.js +39 -4
- package/resolve-ip.js +77 -0
- package/tracing.d.ts +2 -1
- package/tracing.js +295 -34
- package/web-vite.mjs +239 -156
- package/LICENSE +0 -15
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# SecureNow — Nuxt 3 Setup Guide
|
|
2
|
+
|
|
3
|
+
## Quick Start (1 minute)
|
|
4
|
+
|
|
5
|
+
### 1. Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install securenow
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### 2. Add the module to `nuxt.config.ts`
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
export default defineNuxtConfig({
|
|
15
|
+
modules: ['securenow/nuxt'],
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### 3. Set environment variables
|
|
20
|
+
|
|
21
|
+
Create a `.env` file in your project root:
|
|
22
|
+
|
|
23
|
+
```env
|
|
24
|
+
SECURENOW_APPID=my-nuxt-app
|
|
25
|
+
SECURENOW_INSTANCE=https://freetrial.securenow.ai:4318
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 4. Start your app
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
nuxt dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
You should see in the console:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
[securenow] Nuxt module loaded — server plugin registered
|
|
38
|
+
[securenow] 🚀 Nuxt OTel SDK started → https://freetrial.securenow.ai:4318/v1/traces
|
|
39
|
+
[securenow] service.name=my-nuxt-app instance.id=my-nuxt-app-...
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
That's it — all server-side requests are now traced.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Configuration
|
|
47
|
+
|
|
48
|
+
### Module options in `nuxt.config.ts`
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
export default defineNuxtConfig({
|
|
52
|
+
modules: ['securenow/nuxt'],
|
|
53
|
+
securenow: {
|
|
54
|
+
serviceName: 'my-nuxt-app', // overrides SECURENOW_APPID
|
|
55
|
+
endpoint: 'http://host:4318', // overrides SECURENOW_INSTANCE
|
|
56
|
+
noUuid: true, // single service.name (no UUID suffix)
|
|
57
|
+
captureBody: true, // capture POST/PUT/PATCH bodies
|
|
58
|
+
logging: true, // forward console.* as OTLP logs
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Environment variables
|
|
64
|
+
|
|
65
|
+
All standard SecureNow env vars are supported:
|
|
66
|
+
|
|
67
|
+
| Variable | Description | Default |
|
|
68
|
+
|----------|-------------|---------|
|
|
69
|
+
| `SECURENOW_APPID` | Service name | `nuxt-app-<uuid>` |
|
|
70
|
+
| `SECURENOW_INSTANCE` | OTLP base URL | `https://freetrial.securenow.ai:4318` |
|
|
71
|
+
| `SECURENOW_NO_UUID` | Don't append UUID to service name | `false` |
|
|
72
|
+
| `SECURENOW_LOGGING_ENABLED` | Forward console logs as OTLP | `false` |
|
|
73
|
+
| `SECURENOW_CAPTURE_BODY` | Capture request bodies | `false` |
|
|
74
|
+
| `SECURENOW_MAX_BODY_SIZE` | Max body size to capture (bytes) | `10240` |
|
|
75
|
+
| `SECURENOW_SENSITIVE_FIELDS` | Extra fields to redact (CSV) | _(built-in list)_ |
|
|
76
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Alternative OTLP base URL | — |
|
|
77
|
+
| `OTEL_EXPORTER_OTLP_HEADERS` | OTLP headers (k=v,k2=v2) | — |
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## What gets traced
|
|
82
|
+
|
|
83
|
+
### Automatic (out of the box)
|
|
84
|
+
|
|
85
|
+
- All Nitro server handler requests (API routes, SSR pages, middleware)
|
|
86
|
+
- HTTP method, path, status code, duration
|
|
87
|
+
- Client IP address (with proxy-aware resolution)
|
|
88
|
+
- User-Agent, Referer, Origin, Host
|
|
89
|
+
- Security header presence (auth, cookies, CSRF)
|
|
90
|
+
- Request IDs and correlation headers
|
|
91
|
+
|
|
92
|
+
### With `captureBody: true`
|
|
93
|
+
|
|
94
|
+
- POST/PUT/PATCH request bodies (JSON, form-urlencoded, GraphQL)
|
|
95
|
+
- Sensitive fields auto-redacted (passwords, tokens, etc.)
|
|
96
|
+
- Bodies larger than `SECURENOW_MAX_BODY_SIZE` are skipped
|
|
97
|
+
|
|
98
|
+
### With `logging: true`
|
|
99
|
+
|
|
100
|
+
- All `console.log/info/warn/error/debug` calls forwarded as OTLP log records
|
|
101
|
+
- Logs correlated with active trace spans
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Comparison with Next.js integration
|
|
106
|
+
|
|
107
|
+
| Feature | Nuxt (`securenow/nuxt`) | Next.js (`securenow/nextjs`) |
|
|
108
|
+
|---------|-------------------------|------------------------------|
|
|
109
|
+
| Setup | Add to `modules` array | Create `instrumentation.ts` |
|
|
110
|
+
| Config | `nuxt.config.ts` | `.env.local` + `next.config.js` |
|
|
111
|
+
| Server tracing | Nitro hooks | HTTP instrumentation |
|
|
112
|
+
| Edge runtime | Not supported | Skipped gracefully |
|
|
113
|
+
| Vercel support | Via env vars | `@vercel/otel` integration |
|
|
114
|
+
| Body capture | HTTP instrumentation | Middleware + `Request.clone()` |
|
|
115
|
+
| Logging | Console patching | Console patching |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Deployment
|
|
120
|
+
|
|
121
|
+
### Node.js server (PM2, Docker, etc.)
|
|
122
|
+
|
|
123
|
+
Works out of the box with `nuxt build && node .output/server/index.mjs`.
|
|
124
|
+
|
|
125
|
+
### Vercel / Netlify / Cloudflare
|
|
126
|
+
|
|
127
|
+
Set env vars in the platform dashboard:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
SECURENOW_APPID=my-nuxt-app
|
|
131
|
+
SECURENOW_INSTANCE=https://your-otlp-backend:4318
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> Note: On edge runtimes (Cloudflare Workers, Vercel Edge), some Node.js-specific
|
|
135
|
+
> instrumentations may not be available. Server-handler tracing via Nitro hooks
|
|
136
|
+
> still works.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Troubleshooting
|
|
141
|
+
|
|
142
|
+
### No traces appearing
|
|
143
|
+
|
|
144
|
+
1. Check that `SECURENOW_APPID` and `SECURENOW_INSTANCE` are set
|
|
145
|
+
2. Look for `[securenow] 🚀 Nuxt OTel SDK started` in the console
|
|
146
|
+
3. Verify the OTLP endpoint is reachable from your server
|
|
147
|
+
|
|
148
|
+
### Module not loading
|
|
149
|
+
|
|
150
|
+
Make sure you're using Nuxt 3 (`nuxt: ">=3.0.0"`) and the module is listed
|
|
151
|
+
in the `modules` array (not `buildModules`).
|
|
152
|
+
|
|
153
|
+
### OpenTelemetry packages bundled by Nitro
|
|
154
|
+
|
|
155
|
+
The module automatically externalizes OTel packages. If you see bundling errors,
|
|
156
|
+
manually add to `nuxt.config.ts`:
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
export default defineNuxtConfig({
|
|
160
|
+
nitro: {
|
|
161
|
+
externals: {
|
|
162
|
+
external: ['securenow', '@opentelemetry/api', '@opentelemetry/sdk-node'],
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
```
|
|
@@ -8,7 +8,7 @@ This approach **never interferes** with your middleware or routing.
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
SECURENOW_APPID=my-app
|
|
11
|
-
SECURENOW_INSTANCE=http://
|
|
11
|
+
SECURENOW_INSTANCE=http://otel-collector:4318
|
|
12
12
|
SECURENOW_CAPTURE_BODY=1
|
|
13
13
|
```
|
|
14
14
|
|
|
@@ -155,7 +155,7 @@ export async function GET() {
|
|
|
155
155
|
```bash
|
|
156
156
|
# Required
|
|
157
157
|
SECURENOW_APPID=my-nextjs-app
|
|
158
|
-
SECURENOW_INSTANCE=http://your-
|
|
158
|
+
SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
159
159
|
|
|
160
160
|
# Body capture
|
|
161
161
|
SECURENOW_CAPTURE_BODY=1 # Enable body capture
|
|
@@ -439,7 +439,7 @@ If "token" is sensitive, these get redacted:
|
|
|
439
439
|
-d '{"username":"test","password":"secret123"}'
|
|
440
440
|
```
|
|
441
441
|
|
|
442
|
-
3. **Check
|
|
442
|
+
3. **Check SecureNow:**
|
|
443
443
|
- Find the trace
|
|
444
444
|
- Look for `http.request.body`
|
|
445
445
|
- Verify password shows `[REDACTED]`
|
|
@@ -55,16 +55,24 @@ SECURENOW_SENSITIVE_FIELDS=credit_card,email,phone
|
|
|
55
55
|
```
|
|
56
56
|
Parsed into object and sensitive fields redacted.
|
|
57
57
|
|
|
58
|
-
4. **Multipart** (`multipart/form-data`) -
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
4. **Multipart** (`multipart/form-data`) - ✅ Streaming Metadata Capture (v5.8.0+)
|
|
59
|
+
|
|
60
|
+
Requires `SECURENOW_CAPTURE_MULTIPART=1`. Uses a streaming parser — file binary content is never buffered.
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"fields": { "description": "Profile update", "token": "[REDACTED]" },
|
|
65
|
+
"files": [
|
|
66
|
+
{ "field": "avatar", "filename": "photo.jpg", "contentType": "image/jpeg", "size": 524288 }
|
|
67
|
+
]
|
|
68
|
+
}
|
|
61
69
|
```
|
|
62
|
-
|
|
70
|
+
Text field values are captured with sensitive-field redaction. File parts record metadata only (field, filename, content-type, size). Memory stays at ~few KB regardless of upload size.
|
|
63
71
|
|
|
64
72
|
### ❌ What's NOT Captured
|
|
65
73
|
|
|
66
74
|
- GET requests (no body)
|
|
67
|
-
- File
|
|
75
|
+
- File binary content (only metadata when multipart capture is enabled)
|
|
68
76
|
- Bodies larger than max size
|
|
69
77
|
- Binary data
|
|
70
78
|
- Non-POST/PUT/PATCH requests
|
|
@@ -218,6 +226,7 @@ mutation Login {
|
|
|
218
226
|
| `SECURENOW_CAPTURE_BODY` | `0` (disabled) | Enable body capture |
|
|
219
227
|
| `SECURENOW_MAX_BODY_SIZE` | `10240` (10KB) | Maximum body size to capture |
|
|
220
228
|
| `SECURENOW_SENSITIVE_FIELDS` | `` | Comma-separated custom sensitive fields |
|
|
229
|
+
| `SECURENOW_CAPTURE_MULTIPART` | `0` (disabled) | Enable multipart/form-data streaming capture (v5.8.0+) |
|
|
221
230
|
|
|
222
231
|
### Programmatic (Next.js)
|
|
223
232
|
|
|
@@ -235,7 +244,7 @@ export function register() {
|
|
|
235
244
|
|
|
236
245
|
---
|
|
237
246
|
|
|
238
|
-
## 🔍 Viewing in
|
|
247
|
+
## 🔍 Viewing in SecureNow
|
|
239
248
|
|
|
240
249
|
### Query Examples
|
|
241
250
|
|
|
@@ -277,7 +286,7 @@ Request bodies may contain personal data. Consider:
|
|
|
277
286
|
|
|
278
287
|
1. **Legal Basis** - Ensure you have legitimate interest or consent
|
|
279
288
|
2. **Data Minimization** - Only capture what you need
|
|
280
|
-
3. **Retention** - Configure
|
|
289
|
+
3. **Retention** - Configure SecureNow retention policies
|
|
281
290
|
4. **Anonymization** - Add more fields to redact list
|
|
282
291
|
|
|
283
292
|
### PCI-DSS Compliance
|
|
@@ -397,7 +406,7 @@ Field matching is case-insensitive and uses `includes()`:
|
|
|
397
406
|
}
|
|
398
407
|
```
|
|
399
408
|
|
|
400
|
-
3. **Filter in
|
|
409
|
+
3. **Filter in SecureNow**
|
|
401
410
|
- Use sampling to reduce volume
|
|
402
411
|
- Set up trace tail sampling
|
|
403
412
|
|
|
@@ -529,7 +538,7 @@ SECURENOW_SENSITIVE_FIELDS="" # Don't do this!
|
|
|
529
538
|
|
|
530
539
|
### Q: Does this work with file uploads?
|
|
531
540
|
|
|
532
|
-
**A:**
|
|
541
|
+
**A:** Yes! Since v5.8.0, set `SECURENOW_CAPTURE_MULTIPART=1` to capture multipart/form-data requests. The streaming parser extracts text field values and file metadata (name, filename, content-type, size) without ever buffering file binary content. Memory stays bounded at ~few KB regardless of upload size.
|
|
533
542
|
|
|
534
543
|
### Q: What's the performance impact?
|
|
535
544
|
|
|
@@ -564,7 +573,7 @@ SECURENOW_SENSITIVE_FIELDS="" # Don't do this!
|
|
|
564
573
|
|
|
565
574
|
3. **Deploy!** Bodies are captured with sensitive data automatically redacted.
|
|
566
575
|
|
|
567
|
-
**View in
|
|
576
|
+
**View in SecureNow:**
|
|
568
577
|
- `http.request.body` - The captured body (redacted)
|
|
569
578
|
- `http.request.body.size` - Body size in bytes
|
|
570
579
|
- `http.request.body.type` - Content type (json, graphql, form)
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# ✅ Self-Sufficient Body Capture Solution - Complete!
|
|
2
|
+
|
|
3
|
+
## 🎯 The Challenge
|
|
4
|
+
|
|
5
|
+
**Problem:** Next.js request streams can only be read once. Reading them at the HTTP instrumentation level locks the stream and causes:
|
|
6
|
+
```
|
|
7
|
+
TypeError: Response body object should not be disturbed or locked
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
**Solution:** Use Next.js middleware that:
|
|
11
|
+
- Clones the request before reading (doesn't lock original)
|
|
12
|
+
- Reads body safely
|
|
13
|
+
- All logic is in the package (self-sufficient!)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🚀 How It Works (Self-Sufficient!)
|
|
18
|
+
|
|
19
|
+
### For Your Customers - Only 2 Steps!
|
|
20
|
+
|
|
21
|
+
**Step 1: During Installation**
|
|
22
|
+
|
|
23
|
+
When they run `npm install securenow`, the installer asks:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
Would you like to automatically create instrumentation file? (Y/n) Y
|
|
27
|
+
✅ Created instrumentation.ts
|
|
28
|
+
|
|
29
|
+
Would you like to enable request body capture? (y/N) y
|
|
30
|
+
✅ Created middleware.ts
|
|
31
|
+
→ Captures JSON, GraphQL, Form bodies with auto-redaction
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Step 2: Configure**
|
|
35
|
+
|
|
36
|
+
Edit `.env.local` (already created by installer):
|
|
37
|
+
```bash
|
|
38
|
+
SECURENOW_APPID=my-app
|
|
39
|
+
SECURENOW_INSTANCE=http://otel-collector:4318
|
|
40
|
+
SECURENOW_CAPTURE_BODY=1 # Enable body capture
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**That's IT!** 🎉 No code to write!
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 📦 What's in the Package (Self-Sufficient!)
|
|
48
|
+
|
|
49
|
+
### 1. nextjs-middleware.js
|
|
50
|
+
|
|
51
|
+
**Exports ready-to-use middleware:**
|
|
52
|
+
```javascript
|
|
53
|
+
export { middleware } from 'securenow/nextjs-middleware';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Customers just re-export it!** No code to write:
|
|
57
|
+
```typescript
|
|
58
|
+
// middleware.ts (created by installer)
|
|
59
|
+
export { middleware } from 'securenow/nextjs-middleware';
|
|
60
|
+
|
|
61
|
+
export const config = {
|
|
62
|
+
matcher: '/api/:path*',
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 2. All Logic is in the Package
|
|
67
|
+
|
|
68
|
+
**The middleware handles:**
|
|
69
|
+
- ✅ Request cloning (doesn't lock stream)
|
|
70
|
+
- ✅ Body parsing (JSON, GraphQL, Form)
|
|
71
|
+
- ✅ Sensitive field redaction (20+ fields)
|
|
72
|
+
- ✅ Size limits
|
|
73
|
+
- ✅ Error handling
|
|
74
|
+
- ✅ Span attribution
|
|
75
|
+
|
|
76
|
+
**Customer writes: 0 lines of logic!**
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 🔧 Technical Solution
|
|
81
|
+
|
|
82
|
+
### The Key: request.clone()
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// In nextjs-middleware.js (part of package)
|
|
86
|
+
async function middleware(request) {
|
|
87
|
+
// Clone request so original is not consumed
|
|
88
|
+
const clonedRequest = request.clone();
|
|
89
|
+
const bodyText = await clonedRequest.text();
|
|
90
|
+
|
|
91
|
+
// Original request is untouched!
|
|
92
|
+
// Next.js can still read it normally
|
|
93
|
+
|
|
94
|
+
// Parse and redact body
|
|
95
|
+
const redacted = redactSensitiveData(JSON.parse(bodyText));
|
|
96
|
+
|
|
97
|
+
// Add to span
|
|
98
|
+
span.setAttribute('http.request.body', JSON.stringify(redacted));
|
|
99
|
+
|
|
100
|
+
// Continue to Next.js
|
|
101
|
+
return NextResponse.next();
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Why this works:**
|
|
106
|
+
- `request.clone()` creates a copy
|
|
107
|
+
- Clone can be read without affecting original
|
|
108
|
+
- Next.js reads the original stream normally
|
|
109
|
+
- No locking errors!
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 📊 Comparison
|
|
114
|
+
|
|
115
|
+
### ❌ Previous Approach (Broken)
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// In requestHook - DOESN'T WORK
|
|
119
|
+
request.on('data', (chunk) => {
|
|
120
|
+
chunks.push(chunk); // Consumes stream
|
|
121
|
+
});
|
|
122
|
+
// → Next.js can't read stream → ERROR
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### ✅ New Approach (Works!)
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
// In Next.js middleware - WORKS
|
|
129
|
+
const cloned = request.clone();
|
|
130
|
+
const body = await cloned.text(); // Read clone
|
|
131
|
+
// → Original stream is untouched → No error!
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🎯 Customer Journey (Fully Automated!)
|
|
137
|
+
|
|
138
|
+
### Installation Experience
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
$ npm install securenow
|
|
142
|
+
|
|
143
|
+
┌─────────────────────────────────────────────────┐
|
|
144
|
+
│ 🎉 SecureNow installed successfully! │
|
|
145
|
+
│ Next.js project detected │
|
|
146
|
+
└─────────────────────────────────────────────────┘
|
|
147
|
+
|
|
148
|
+
Would you like to automatically create instrumentation file? (Y/n) Y
|
|
149
|
+
✅ Created instrumentation.ts
|
|
150
|
+
|
|
151
|
+
Would you like to enable request body capture? (y/N) y
|
|
152
|
+
✅ Created middleware.ts
|
|
153
|
+
→ Captures JSON, GraphQL, Form bodies with auto-redaction
|
|
154
|
+
|
|
155
|
+
✅ Created .env.local template
|
|
156
|
+
|
|
157
|
+
┌─────────────────────────────────────────────────┐
|
|
158
|
+
│ 🚀 Next Steps: │
|
|
159
|
+
│ │
|
|
160
|
+
│ 1. Edit .env.local and set: │
|
|
161
|
+
│ SECURENOW_APPID=your-app-name │
|
|
162
|
+
│ SECURENOW_INSTANCE=http://otel-collector:4318 │
|
|
163
|
+
│ SECURENOW_CAPTURE_BODY=1 │
|
|
164
|
+
│ │
|
|
165
|
+
│ 2. Run your app: npm run dev │
|
|
166
|
+
│ │
|
|
167
|
+
│ 3. Check SecureNow for traces! │
|
|
168
|
+
│ │
|
|
169
|
+
│ 📝 Body capture enabled with auto-redaction │
|
|
170
|
+
└─────────────────────────────────────────────────┘
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Total customer code written: 0 lines!**
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## ✨ Self-Sufficient Features
|
|
178
|
+
|
|
179
|
+
### What the Package Provides
|
|
180
|
+
|
|
181
|
+
1. **nextjs-middleware.js**
|
|
182
|
+
- Complete middleware implementation
|
|
183
|
+
- All parsing logic
|
|
184
|
+
- All redaction logic
|
|
185
|
+
- Error handling
|
|
186
|
+
- Span attribution
|
|
187
|
+
|
|
188
|
+
2. **Postinstall Script**
|
|
189
|
+
- Auto-detects Next.js
|
|
190
|
+
- Offers to create files
|
|
191
|
+
- Creates middleware.ts with correct import
|
|
192
|
+
- Updates .env.local template
|
|
193
|
+
|
|
194
|
+
3. **Examples**
|
|
195
|
+
- `examples/nextjs-middleware.ts`
|
|
196
|
+
- `examples/nextjs-middleware.js`
|
|
197
|
+
- Ready to copy if needed
|
|
198
|
+
|
|
199
|
+
4. **Documentation**
|
|
200
|
+
- `NEXTJS-BODY-CAPTURE.md` - Complete guide
|
|
201
|
+
- Shows the one-line import
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## 🔒 Security (Built Into Package!)
|
|
206
|
+
|
|
207
|
+
**All in the package:**
|
|
208
|
+
- ✅ 20+ sensitive fields redacted
|
|
209
|
+
- ✅ Recursive redaction
|
|
210
|
+
- ✅ GraphQL pattern matching
|
|
211
|
+
- ✅ Size limits
|
|
212
|
+
- ✅ Type detection
|
|
213
|
+
|
|
214
|
+
**Customer configuration:**
|
|
215
|
+
```bash
|
|
216
|
+
# Optional: add custom fields
|
|
217
|
+
SECURENOW_SENSITIVE_FIELDS=email,phone
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Customer code: 0 lines!**
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 📝 Files Created for Customer
|
|
225
|
+
|
|
226
|
+
### By Installer
|
|
227
|
+
|
|
228
|
+
1. **instrumentation.ts** (or .js)
|
|
229
|
+
```typescript
|
|
230
|
+
export { middleware } from 'securenow/nextjs-middleware';
|
|
231
|
+
```
|
|
232
|
+
*Just a re-export!*
|
|
233
|
+
|
|
234
|
+
2. **middleware.ts** (or .js) - If they choose body capture
|
|
235
|
+
```typescript
|
|
236
|
+
export { middleware } from 'securenow/nextjs-middleware';
|
|
237
|
+
export const config = { matcher: '/api/:path*' };
|
|
238
|
+
```
|
|
239
|
+
*Just a re-export + config!*
|
|
240
|
+
|
|
241
|
+
3. **.env.local**
|
|
242
|
+
```bash
|
|
243
|
+
SECURENOW_APPID=my-app
|
|
244
|
+
SECURENOW_INSTANCE=http://otel-collector:4318
|
|
245
|
+
SECURENOW_CAPTURE_BODY=1
|
|
246
|
+
```
|
|
247
|
+
*Just configuration!*
|
|
248
|
+
|
|
249
|
+
**Total logic written by customer: 0 lines!**
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 🎉 Result
|
|
254
|
+
|
|
255
|
+
### For Next.js Users
|
|
256
|
+
|
|
257
|
+
**Before (broken):**
|
|
258
|
+
- Install package
|
|
259
|
+
- Enable body capture
|
|
260
|
+
- → Get stream locking error
|
|
261
|
+
- → App breaks
|
|
262
|
+
|
|
263
|
+
**After (self-sufficient):**
|
|
264
|
+
- Install package
|
|
265
|
+
- Answer "Y" twice
|
|
266
|
+
- Edit config values
|
|
267
|
+
- → Everything works
|
|
268
|
+
- → Bodies captured
|
|
269
|
+
- → Sensitive data redacted
|
|
270
|
+
- → Zero code to write
|
|
271
|
+
|
|
272
|
+
### For You
|
|
273
|
+
|
|
274
|
+
**Self-sufficient package:**
|
|
275
|
+
- ✅ Customers write 0 lines of code
|
|
276
|
+
- ✅ Just import from package
|
|
277
|
+
- ✅ All logic in package
|
|
278
|
+
- ✅ No stream locking errors
|
|
279
|
+
- ✅ Works perfectly with Next.js
|
|
280
|
+
- ✅ Automatic setup via installer
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## ✅ Checklist
|
|
285
|
+
|
|
286
|
+
- [x] Fixed stream locking error
|
|
287
|
+
- [x] Created nextjs-middleware.js with all logic
|
|
288
|
+
- [x] Updated package.json exports
|
|
289
|
+
- [x] Enhanced postinstall to offer middleware creation
|
|
290
|
+
- [x] Created example files
|
|
291
|
+
- [x] Updated documentation
|
|
292
|
+
- [x] Zero customer code required
|
|
293
|
+
- [x] Tested - no linter errors
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 🚀 Ready to Ship!
|
|
298
|
+
|
|
299
|
+
**The error is fixed and the solution is self-sufficient!**
|
|
300
|
+
|
|
301
|
+
Customers get:
|
|
302
|
+
- ✅ Automatic file creation (installer)
|
|
303
|
+
- ✅ One-line imports (re-export from package)
|
|
304
|
+
- ✅ All logic in package (no code to write)
|
|
305
|
+
- ✅ Automatic redaction (built-in)
|
|
306
|
+
- ✅ No stream errors (uses clone)
|
|
307
|
+
|
|
308
|
+
**Status: Production Ready!** 🎯
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
@@ -62,7 +62,7 @@ export function register() {
|
|
|
62
62
|
```bash
|
|
63
63
|
# .env.local
|
|
64
64
|
SECURENOW_APPID=my-nextjs-app
|
|
65
|
-
SECURENOW_INSTANCE=http://your-
|
|
65
|
+
SECURENOW_INSTANCE=http://your-otlp-backend:4318
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
### What They Get
|
|
@@ -89,7 +89,7 @@ SECURENOW_INSTANCE=http://your-signoz:4318
|
|
|
89
89
|
- `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`
|
|
90
90
|
3. SecureNow calls `@vercel/otel`'s `registerOTel()`
|
|
91
91
|
4. @vercel/otel handles all the OpenTelemetry setup
|
|
92
|
-
5. Traces flow to
|
|
92
|
+
5. Traces flow to SecureNow
|
|
93
93
|
|
|
94
94
|
### What @vercel/otel Does
|
|
95
95
|
|
|
@@ -185,7 +185,7 @@ All options still work:
|
|
|
185
185
|
```typescript
|
|
186
186
|
registerSecureNow({
|
|
187
187
|
serviceName: 'my-app',
|
|
188
|
-
endpoint: 'http://
|
|
188
|
+
endpoint: 'http://otel-collector:4318',
|
|
189
189
|
noUuid: false,
|
|
190
190
|
});
|
|
191
191
|
```
|
package/examples/README.md
CHANGED
|
@@ -160,7 +160,7 @@ OTEL_LOG_LEVEL=info
|
|
|
160
160
|
```bash
|
|
161
161
|
# Set in Vercel dashboard:
|
|
162
162
|
SECURENOW_APPID=my-app
|
|
163
|
-
SECURENOW_INSTANCE=http://your-
|
|
163
|
+
SECURENOW_INSTANCE=http://your-collector-host:4318
|
|
164
164
|
OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-key"
|
|
165
165
|
```
|
|
166
166
|
|
|
@@ -180,7 +180,7 @@ npm install securenow@latest
|
|
|
180
180
|
1. Check console for `[securenow] ✅ OpenTelemetry started`
|
|
181
181
|
2. Enable debug mode: `OTEL_LOG_LEVEL=debug`
|
|
182
182
|
3. Run test script: `node examples/test-nextjs-setup.js`
|
|
183
|
-
4. Verify
|
|
183
|
+
4. Verify OTLP collector accessibility: `curl http://your-collector-host:4318/v1/traces`
|
|
184
184
|
|
|
185
185
|
### Too many spans
|
|
186
186
|
|
|
@@ -206,7 +206,7 @@ registerSecureNow({
|
|
|
206
206
|
```typescript
|
|
207
207
|
registerSecureNow({
|
|
208
208
|
headers: {
|
|
209
|
-
'x-api-key': process.env.
|
|
209
|
+
'x-api-key': process.env.SECURENOW_API_KEY,
|
|
210
210
|
'x-environment': process.env.NODE_ENV,
|
|
211
211
|
},
|
|
212
212
|
});
|
|
@@ -229,7 +229,7 @@ After setting up:
|
|
|
229
229
|
|
|
230
230
|
1. **Run your app** and verify traces appear
|
|
231
231
|
2. **Test key user flows** to see end-to-end tracing
|
|
232
|
-
3. **Check
|
|
232
|
+
3. **Check SecureNow dashboard** for service map and traces
|
|
233
233
|
4. **Adjust configuration** based on your needs
|
|
234
234
|
5. **Deploy to production** with proper environment variables
|
|
235
235
|
|
|
@@ -242,12 +242,12 @@ $ npm run dev
|
|
|
242
242
|
|
|
243
243
|
[securenow] Next.js integration loading (pid=12345)
|
|
244
244
|
[securenow] 🚀 Next.js App → service.name=my-app-abc123
|
|
245
|
-
[securenow] ✅ OpenTelemetry started for Next.js → http://
|
|
245
|
+
[securenow] ✅ OpenTelemetry started for Next.js → http://your-collector-host:4318/v1/traces
|
|
246
246
|
|
|
247
247
|
✓ Ready in 1.2s
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
Then in
|
|
250
|
+
Then in SecureNow:
|
|
251
251
|
- ✅ See your service in service map
|
|
252
252
|
- ✅ View traces for requests
|
|
253
253
|
- ✅ Analyze performance metrics
|
|
@@ -30,7 +30,7 @@ export function register() {
|
|
|
30
30
|
*
|
|
31
31
|
* Configuration in .env.local:
|
|
32
32
|
* SECURENOW_APPID=my-app
|
|
33
|
-
* SECURENOW_INSTANCE=http://
|
|
33
|
+
* SECURENOW_INSTANCE=http://localhost:4318
|
|
34
34
|
* SECURENOW_CAPTURE_BODY=1
|
|
35
35
|
* SECURENOW_MAX_BODY_SIZE=10240
|
|
36
36
|
* SECURENOW_SENSITIVE_FIELDS=custom_field
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
# Required: Your application identifier
|
|
5
5
|
SECURENOW_APPID=my-nextjs-app
|
|
6
6
|
|
|
7
|
-
# Optional: Your
|
|
7
|
+
# Optional: Your OTLP collector endpoint (SecureNow or any OTLP-compatible backend)
|
|
8
8
|
# Default: https://freetrial.securenow.ai:4318
|
|
9
|
-
SECURENOW_INSTANCE=http://your-
|
|
9
|
+
SECURENOW_INSTANCE=http://your-otlp-collector:4318
|
|
10
10
|
|
|
11
11
|
# Optional: API Key or authentication headers
|
|
12
12
|
OTEL_EXPORTER_OTLP_HEADERS="x-api-key=your-api-key-here"
|