securenow 8.0.1 → 8.0.3

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
@@ -69,7 +69,7 @@ Run login - it is a browser flow that picks or creates an app and connects the f
69
69
  npx securenow login
70
70
  ```
71
71
 
72
- 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 runtime config into `.securenow/runtime.json`. Admin auth, when part of the flow, is saved separately to `.securenow/admin.json`. Traces, logs, POST body capture, multipart metadata capture, and firewall protection are enabled by default. No env vars, no copy-pasting keys.
72
+ During the browser step, the dashboard enables the selected app's firewall toggle, mints a one-time plaintext runtime API key scoped to that app only (scopes: `traces:write`, `logs:write`, `firewall:read`, `blocklist:read`, `allowlist:read`), and the CLI writes it as `apiKey` in `.securenow/runtime.json`. Admin auth, when part of the flow, is saved separately to `.securenow/admin.json`. Traces, logs, POST body capture, multipart metadata capture, and firewall protection are enabled by default. No env vars, no copy-pasting keys.
73
73
 
74
74
  Metrics export is intentionally off by default. SecureNow sets `OTEL_METRICS_EXPORTER=none` when the app has not explicitly configured metrics, preventing the OpenTelemetry SDK from creating a default metrics reader that retries `localhost:4318`.
75
75
 
@@ -77,7 +77,7 @@ For framework scaffolding (Next.js `instrumentation.ts`, `next.config.*`, etc.)
77
77
 
78
78
  ```bash
79
79
  npx securenow init
80
- # Optional, when you already have a key and did not use browser login:
80
+ # Optional, when you already have a runtime API key and did not use browser login:
81
81
  npx securenow init --key snk_live_abc123...
82
82
  ```
83
83
 
@@ -86,13 +86,13 @@ This detects your framework and:
86
86
  - **Next.js**: Creates `instrumentation.ts`, adds `serverExternalPackages: ['securenow']` plus `outputFileTracingIncludes` when safe, or prints a Codex/Claude-ready merge prompt for existing files
87
87
  - **Nuxt 3**: Suggests adding `securenow/nuxt` to modules
88
88
  - **Express / Node.js**: Shows how to add `-r securenow/register` to your start script
89
- - **All**: Stores `--key` in `.securenow/runtime.json`; no local `.env` file is needed
89
+ - **All**: Stores an optional `--key` in `.securenow/runtime.json`; no local `.env` file is needed. If the runtime API key is missing, run `npx securenow app connect` or `npx securenow api-key create` before sending telemetry.
90
90
 
91
91
  ### 2. Manual Setup
92
92
 
93
93
  #### Configure Locally
94
94
 
95
- Run `npx securenow app connect` to write `.securenow/runtime.json`. The SDK reads app identity, runtime API key, logging/body-capture defaults, and firewall defaults from that file at boot. Telemetry uses the default SecureNow ingestion gateway, routes by `app.key`, and authenticates with the runtime API key, so customer credentials do not expose per-instance collector URLs. Production uses the same file shape via `npx securenow credentials runtime --env production`.
95
+ Run `npx securenow app connect` to write `.securenow/runtime.json`. The SDK reads app identity, runtime API key, logging/body-capture defaults, and firewall defaults from that file at boot. Telemetry uses the default SecureNow ingestion gateway, routes by `app.key`, and authenticates with the runtime API key, so customer credentials do not expose per-instance collector URLs. Production uses the same file shape via `npx securenow credentials runtime --env production`. When rotating later with `npx securenow api-key create`, the CLI defaults to the current app in runtime credentials, resolves its app UUID to the server app id, creates a one-app `runtime_app` key, and stores the plaintext key back into `.securenow/runtime.json`.
96
96
 
97
97
  #### Run Your Application
98
98
 
@@ -144,7 +144,7 @@ You'll see confirmation in the console:
144
144
 
145
145
  The `securenow` CLI gives you full access to the SecureNow platform from the terminal -- no browser required for day-to-day workflows. Zero additional dependencies.
146
146
 
147
- **Full CLI/SDK parity (v6.1.0+):** every SDK export has a matching CLI command. `redactSensitiveData` -> `securenow redact`, `createMatcher` -> `securenow cidr match`, `getLogger().emit()` -> `securenow log send`, startup smoke spans -> `securenow test-span`, `node -r securenow/firewall-only` -> `securenow run --firewall-only`. False-positive triage (`fp create`, `fp ai-fill`, `fp mark`) works from the terminal without the web dashboard.
147
+ **Full CLI/SDK parity:** every SDK export has a matching CLI command. `redactSensitiveData` -> `securenow redact`, `createMatcher` -> `securenow cidr match`, `getLogger().emit()` -> `securenow log send`, startup smoke spans -> `securenow test-span`, `node -r securenow/firewall-only` -> `securenow run --firewall-only`. False-positive triage (`fp create`, `fp ai-fill`, `fp mark`) works from the terminal without the web dashboard.
148
148
 
149
149
  ### Getting Started
150
150
 
@@ -178,7 +178,7 @@ npx securenow api-key clear # remove just the key
178
178
  # Auto-detect framework and scaffold instrumentation files
179
179
  npx securenow init
180
180
 
181
- # Pass your API key to store it in .securenow/runtime.json
181
+ # Optional: pass an existing runtime API key to store it in .securenow/runtime.json
182
182
  npx securenow init --key snk_live_abc123...
183
183
  ```
184
184
 
@@ -505,7 +505,7 @@ npx securenow logs --json --level error | jq '.logs'
505
505
  | | `apps info <id>` | Application details |
506
506
  | | `apps delete <id>` | Delete application |
507
507
  | | `apps default <key>` | Set default app |
508
- | **API Key** | `api-key create [--name "CLI runtime"] [--global]` | Mint and save a runtime API key with your logged-in session |
508
+ | **API Key** | `api-key create [--name "CLI runtime"] [--app <key-or-id>] [--global]` | Mint and save a one-app `runtime_app` key with your logged-in session. Defaults to the current runtime app |
509
509
  | | `api-key set <snk_live_...> [--global]` | Save runtime API key to `.securenow/runtime.json` |
510
510
  | | `api-key show` | Show masked key + source |
511
511
  | | `api-key clear [--global]` | Remove stored key (leaves session/app) |
@@ -623,7 +623,7 @@ module.exports = {
623
623
  };
624
624
  ```
625
625
 
626
- > **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.
626
+ > **Important:** Put `.securenow/runtime.json` in the PM2 app root for local/dev deployments, or mount the production runtime export as `.securenow/credentials.json`. Keep `node_args: '-r securenow/register'`. PM2 restarts will then load the SDK, traces/logs, body capture, and firewall without any SecureNow env vars.
627
627
 
628
628
  ---
629
629
 
@@ -1003,7 +1003,7 @@ const nextConfig = {
1003
1003
  export default nextConfig;
1004
1004
  ```
1005
1005
 
1006
- 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`.
1006
+ No `.env.local` is needed locally or in production. Local setup reads `.securenow/runtime.json`; production should use `npx securenow credentials runtime --env production` and mount/copy the resulting JSON as `.securenow/credentials.json`.
1007
1007
 
1008
1008
  #### Option B: Manual configuration
1009
1009
 
@@ -1050,7 +1050,7 @@ export default defineNuxtConfig({
1050
1050
  });
1051
1051
  ```
1052
1052
 
1053
- Local and production app identity and secure defaults come from `.securenow/credentials.json`.
1053
+ Local app identity, runtime API key, and secure defaults come from `.securenow/runtime.json`; production can mount the generated tokenless runtime file as `.securenow/credentials.json` or `.securenow/credentials.<env>.json`.
1054
1054
 
1055
1055
  That's it -- the Nuxt module handles OTel SDK initialization, Nitro externalization, firewall activation, and request tracing automatically. Optional config:
1056
1056
 
@@ -1097,18 +1097,18 @@ SecureNow can automatically block IPs from your blocklist at the application lay
1097
1097
  Pick whichever fits your environment:
1098
1098
 
1099
1099
  ```bash
1100
- # (a) Zero-config (v7.4+): login picks/creates an app and connects the firewall.
1101
- # Key is minted and written to .securenow/credentials.json automatically.
1100
+ # (a) Zero-config (v8+): login picks/creates an app and connects the firewall.
1101
+ # Runtime API key is minted and written to .securenow/runtime.json automatically.
1102
1102
  npx securenow login
1103
1103
 
1104
- # (b) Already have a key? Write it to the creds file directly:
1104
+ # (b) Already have a runtime API key? Write it to runtime credentials directly:
1105
1105
  npx securenow api-key set snk_live_abc123...
1106
1106
 
1107
1107
  # (c) Production? Generate a tokenless runtime credentials file:
1108
1108
  npx securenow credentials runtime --env production
1109
1109
  ```
1110
1110
 
1111
- The SDK resolves the runtime API key from project `./.securenow/credentials.json`, then project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order, then global `~/.securenow/credentials.json`, then global named runtime credentials in the same fixed order.
1111
+ The SDK resolves the runtime API key from project `./.securenow/runtime.json`, legacy project `./.securenow/credentials.json`, project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order, global `~/.securenow/runtime.json`, legacy global credentials, then global named runtime credentials in the same fixed order.
1112
1112
 
1113
1113
  On startup, you'll see:
1114
1114
 
@@ -1139,7 +1139,7 @@ If you only need IP blocking without OpenTelemetry tracing overhead, use the sta
1139
1139
  # Manual preload flag
1140
1140
  node -r securenow/firewall-only app.js
1141
1141
 
1142
- # Or via the CLI (v6.1.0+) - same effect, clearer intent
1142
+ # Or via the CLI - same effect, clearer intent
1143
1143
  securenow run --firewall-only app.js
1144
1144
  ```
1145
1145
 
@@ -1157,7 +1157,7 @@ This is useful when:
1157
1157
  - You're adding the firewall to a project that uses a different tracing solution
1158
1158
  - For non-Next Node apps, this avoids framework-specific tracing setup entirely
1159
1159
 
1160
- Firewall-only mode uses the same `.securenow/credentials.json` key written by `login`, `api-key set`, or mounted from a runtime credentials file:
1160
+ Firewall-only mode uses the same runtime API key written by `login`, `app connect`, `api-key create`, `api-key set`, or mounted from a runtime credentials file:
1161
1161
 
1162
1162
  ```bash
1163
1163
  npx securenow credentials runtime --env production
@@ -1197,9 +1197,9 @@ Use `npx securenow firewall status`, `npx securenow firewall apps`, and `npx sec
1197
1197
 
1198
1198
  ## Credentials Configuration
1199
1199
 
1200
- 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`.
1200
+ Local development uses `.securenow/runtime.json`. Run `npx securenow login` or `npx securenow app connect`, then `npx securenow init`; for production, run `npx securenow credentials runtime --env production` and mount/copy the generated JSON as `.securenow/credentials.json` or `.securenow/credentials.<env>.json`.
1201
1201
 
1202
- Use `.securenow/credentials.json` as the source of truth. Run `npx securenow env --json` to inspect resolved settings without exposing secrets.
1202
+ Use `.securenow/runtime.json` as the local source of truth. Run `npx securenow env --json` to inspect resolved settings without exposing secrets.
1203
1203
 
1204
1204
  ### Credentials Fields
1205
1205
 
@@ -1207,7 +1207,7 @@ Use `.securenow/credentials.json` as the source of truth. Run `npx securenow env
1207
1207
  |----------|-------------|---------|
1208
1208
  | `app.key` | App routing UUID. The SecureNow ingestion gateway routes telemetry by this key. | selected during login |
1209
1209
  | `app.name` | Human-readable app label. | selected during login |
1210
- | `apiKey` | Scoped runtime API key (`snk_live_...`) for telemetry ingestion and firewall sync. | minted during login |
1210
+ | `apiKey` | One-app scoped runtime API key (`snk_live_...`) for telemetry ingestion and firewall sync. Runtime scopes are `traces:write`, `logs:write`, `firewall:read`, `blocklist:read`, and `allowlist:read`. | minted during login |
1211
1211
  | `config.runtime.deploymentEnvironment` | `deployment.environment` trace/log scope. | `local` from init, `production` from runtime credentials |
1212
1212
  | `config.logging.enabled` | Automatic console log export. | `true` |
1213
1213
  | `config.capture.body` | Request body capture with redaction. | `true` |
@@ -1223,7 +1223,8 @@ Environment-variable fallback is not supported.
1223
1223
  **Default sensitive fields (auto-redacted):** `password`, `passwd`, `pwd`, `secret`, `token`, `api_key`, `apikey`, `access_token`, `auth`, `credentials`, `mysql_pwd`, `stripeToken`, `card`, `cardnumber`, `ccv`, `cvc`, `cvv`, `ssn`, `pin`
1224
1224
 
1225
1225
  For instrumentation, firewall layers, debugging, trusted proxies, and deployment
1226
- environment, edit the matching `config.*` keys in `.securenow/credentials.json`.
1226
+ environment, edit the matching `config.*` keys in `.securenow/runtime.json`
1227
+ locally or in the mounted production runtime credentials file.
1227
1228
  Use `npx securenow env --json` to inspect the resolved values and
1228
1229
  `npx securenow help firewall` for the firewall command reference.
1229
1230
 
@@ -1273,7 +1274,7 @@ console.debug('Debug info');
1273
1274
  - `console.error()` -> ERROR
1274
1275
  - `console.debug()` -> DEBUG
1275
1276
 
1276
- Logging is controlled by `config.logging.enabled` in `.securenow/credentials.json`.
1277
+ Logging is controlled by `config.logging.enabled` in `.securenow/runtime.json` locally or the mounted production runtime credentials file.
1277
1278
 
1278
1279
  ### Direct Logger API
1279
1280
 
@@ -1316,7 +1317,7 @@ node -r securenow/register app.js
1316
1317
 
1317
1318
  ## Request Body Capture
1318
1319
 
1319
- SecureNow captures HTTP request bodies in traces by default, with sensitive fields automatically redacted. Set `config.capture.body=false` in `.securenow/credentials.json` only when you need a local opt-out.
1320
+ SecureNow captures HTTP request bodies in traces by default, with sensitive fields automatically redacted. Set `config.capture.body=false` in `.securenow/runtime.json` locally or the mounted production runtime credentials file only when you need an opt-out.
1320
1321
 
1321
1322
  ### Body Capture Defaults
1322
1323
 
@@ -1470,10 +1471,10 @@ if (isLoggingEnabled()) {
1470
1471
 
1471
1472
  ### Programmatic Configuration
1472
1473
 
1473
- Use `.securenow/credentials.json` for local development, tests, CI, and production:
1474
+ Use `.securenow/runtime.json` for local development and tests; CI/production should mount the generated runtime credentials file:
1474
1475
 
1475
1476
  ```javascript
1476
- // Reads .securenow/credentials.json from the project root.
1477
+ // Reads .securenow/runtime.json first, with legacy/generated runtime credentials as fallbacks.
1477
1478
  require('securenow/register');
1478
1479
  ```
1479
1480
 
@@ -1565,7 +1566,7 @@ npx securenow env
1565
1566
  npx securenow status --env local
1566
1567
  ```
1567
1568
 
1568
- The output should show an app key, collector endpoint, and deployment environment from `.securenow/credentials.json`.
1569
+ The output should show an app key, runtime API key source, collector endpoint, and deployment environment from `.securenow/runtime.json` or the mounted runtime credentials file.
1569
1570
 
1570
1571
  **Check 2: Verify OTLP collector is running**
1571
1572
 
@@ -1614,7 +1615,7 @@ require('securenow/register');
1614
1615
 
1615
1616
  ### Firewall Not Blocking IPs
1616
1617
 
1617
- **Check 1: Is an API key in `.securenow/credentials.json`?**
1618
+ **Check 1: Is a runtime API key in `.securenow/runtime.json` or the mounted runtime credentials file?**
1618
1619
 
1619
1620
  ```bash
1620
1621
  npx securenow api-key show
@@ -1651,7 +1652,7 @@ proxy_set_header X-Real-IP $remote_addr;
1651
1652
  proxy_set_header X-Forwarded-Proto $scheme;
1652
1653
  ```
1653
1654
 
1654
- SecureNow trusts private, loopback, and same-host proxy peers automatically. For external load balancers or public proxy IPs, add them to `config.networking.trustedProxies` in `.securenow/credentials.json`. If no forwarded header reaches the app, SecureNow can detect the attack shape but cannot recover the real visitor IP from traces.
1655
+ SecureNow trusts private, loopback, and same-host proxy peers automatically. For external load balancers or public proxy IPs, add them to `config.networking.trustedProxies` in `.securenow/runtime.json` or the mounted runtime credentials file. If no forwarded header reaches the app, SecureNow can detect the attack shape but cannot recover the real visitor IP from traces.
1655
1656
 
1656
1657
  **Check 6: Using PM2?**
1657
1658
 
@@ -1822,14 +1823,14 @@ Without `node_args`, PM2 starts your script directly without the securenow prelo
1822
1823
 
1823
1824
  ### 1. Use the Credentials File
1824
1825
 
1825
- Do not hardcode configuration in code or deployment dashboards. Use `.securenow/credentials.json` locally and mount the tokenless runtime file in production:
1826
+ Do not hardcode configuration in code or deployment dashboards. Use `.securenow/runtime.json` locally and mount the tokenless runtime file in production:
1826
1827
 
1827
1828
  ```javascript
1828
1829
  // Bad
1829
1830
  const appKey = 'hardcoded-value';
1830
1831
 
1831
- // Good: use .securenow/credentials.json
1832
- // { "app": { "key": "my-app", "instance": "https://ingest.securenow.ai" } }
1832
+ // Good: use .securenow/runtime.json
1833
+ // { "app": { "key": "<uuid>", "instance": "https://ingest.securenow.ai" }, "apiKey": "snk_live_..." }
1833
1834
  ```
1834
1835
 
1835
1836
  ### 2. Use Structured Logging
package/README.md CHANGED
@@ -37,7 +37,13 @@ That's it. No `.env` edits, no API keys to paste, no peer-dep warnings. Your tra
37
37
  `npx securenow login` opens a browser and runs both lanes for onboarding:
38
38
 
39
39
  - admin/control-plane CLI and MCP auth goes to `.securenow/admin.json`
40
- - app/runtime SDK config and the firewall API key go to `.securenow/runtime.json`
40
+ - app/runtime SDK config and the runtime API key go to `.securenow/runtime.json`
41
+
42
+ During app runtime onboarding, the browser flow returns a one-time plaintext
43
+ `snk_live_...` key scoped to the selected app only. The CLI writes that key as
44
+ `apiKey` in `.securenow/runtime.json`. Its `runtime_app` scopes are
45
+ `traces:write`, `logs:write`, `firewall:read`, `blocklist:read`, and
46
+ `allowlist:read`.
41
47
 
42
48
  Use `npx securenow admin login` to refresh only admin auth, or `npx securenow app connect` to refresh only runtime app config. Legacy combined `.securenow/credentials.json` files are still read for old installs.
43
49
 
@@ -60,7 +66,7 @@ Runtime credentials look like:
60
66
  }
61
67
  ```
62
68
 
63
- The SDK reads the runtime file at boot and sends traces/logs directly to the right app bucket. `npx securenow init` also fills the config block with secure defaults plus an `_securenow.explanations` section so users can see what every setting does. Local credential files are auto-added to `.gitignore` so they never land in git.
69
+ The SDK reads the runtime file at boot, sends traces/logs through the SecureNow ingest gateway, routes by `app.key`, and authenticates with the runtime API key. When you rotate with `npx securenow api-key create`, the CLI defaults to the current app in `.securenow/runtime.json`, resolves that app UUID to the server app id, creates a one-app `runtime_app` key, and stores the plaintext key back into runtime credentials. `npx securenow init` also fills the config block with secure defaults plus an `_securenow.explanations` section so users can see what every setting does.
64
70
 
65
71
  ---
66
72
 
@@ -75,7 +81,7 @@ npx securenow login
75
81
  Then ask your coding agent to wire each app with this prompt:
76
82
 
77
83
  ```text
78
- I already ran npx securenow login from the repo root. For every Node.js or Next.js app under this repo: install securenow@latest, run or merge npx securenow init, create or reuse a SecureNow app, write local .securenow/runtime.json plus tokenless .securenow/credentials.production.json, gitignore only SecureNow credential files, enable traces, logs, body capture, multipart metadata, and firewall, then verify with npx securenow env --json, npx securenow test-span, npx securenow log send, and a local HTTP smoke test where possible. Do not print secrets.
84
+ I already ran npx securenow login from the repo root. For every Node.js or Next.js app under this repo: install securenow@latest, run or merge npx securenow init, create or reuse a SecureNow app, write local .securenow/runtime.json plus tokenless .securenow/credentials.production.json for secret-file deployment, enable traces, logs, body capture, multipart metadata, and firewall, then verify with npx securenow env --json, npx securenow test-span, npx securenow log send, and a local HTTP smoke test where possible. Do not print secrets.
79
85
  ```
80
86
 
81
87
  For production, deploy the tokenless runtime credentials as a secret file mounted at `<app-root>/.securenow/credentials.json`.
@@ -163,7 +169,7 @@ SecureNow does not export metrics by default. The preload sets `OTEL_METRICS_EXP
163
169
 
164
170
  ## Production Without Env Vars
165
171
 
166
- Production uses the same file structure. Do not commit `.securenow/`; instead deploy a tokenless runtime credentials file as a secret file and mount/copy it to:
172
+ Production uses the same file structure. Deploy a tokenless runtime credentials file as a secret file and mount/copy it to:
167
173
 
168
174
  ```text
169
175
  <app-root>/.securenow/credentials.json
@@ -177,7 +183,7 @@ npx securenow credentials runtime --env production
177
183
 
178
184
  It writes `.securenow/credentials.production.json`, with the same `app`, `apiKey`, `config`, and `_securenow.explanations` shape, but without the CLI OAuth `token`, `email`, or `expiresAt`. Store that JSON in your deployment secret manager and materialize it as `.securenow/credentials.json` at runtime.
179
185
 
180
- Starting in v7.7.2, the SDK also accepts generated runtime filenames directly without reading environment variables to choose the file. If `.securenow/credentials.json` is missing, it checks named files in a deterministic order: staging, production, preview, local, test, development, dev, then prod.
186
+ The v8 SDK also accepts generated runtime filenames directly without reading environment variables to choose the file. If `.securenow/credentials.json` is missing, it checks named files in a deterministic order: staging, production, preview, local, test, development, dev, then prod.
181
187
 
182
188
  Resolution order:
183
189
 
@@ -258,7 +264,7 @@ Use `.securenow/runtime.json` fields for new local SDK/runtime setups. Productio
258
264
  |---|---|---|
259
265
  | `app.key` | selected during login | App routing UUID; the gateway routes telemetry by this key |
260
266
  | `app.name` | selected during login | Human-readable label for CLI and dashboard output |
261
- | `apiKey` | minted during login | Scoped runtime API key (`snk_live_...`) for telemetry ingestion and firewall sync |
267
+ | `apiKey` | minted during login | One-app scoped runtime API key (`snk_live_...`) for telemetry ingestion and firewall sync. Runtime scopes: `traces:write`, `logs:write`, `firewall:read`, `blocklist:read`, `allowlist:read` |
262
268
  | `config.runtime.deploymentEnvironment` | `local` from `init`, `production` from runtime credentials | Sent as OTel `deployment.environment` |
263
269
  | `config.logging.enabled` | `true` | Forward `console.*` as OTLP logs |
264
270
  | `config.capture.body` | `true` | Capture JSON / form request bodies with redaction |
@@ -330,7 +336,7 @@ After install, the `securenow` CLI is available via `npx securenow` or globally
330
336
  | `securenow logout` | Clear admin auth only; runtime app config stays intact |
331
337
  | `securenow logout --global` | Clear ~/.securenow/ instead |
332
338
  | `securenow whoami` | Show admin auth and runtime app status separately |
333
- | `securenow api-key create [--name "CLI runtime"]` | Mint and store a runtime API key using your session token |
339
+ | `securenow api-key create [--name "CLI runtime"] [--app <key-or-id>]` | Mint and store a one-app `runtime_app` key. Defaults to the current app in `.securenow/runtime.json` |
334
340
  | `securenow api-key set <snk_live_...>` | Store runtime API key in `.securenow/runtime.json` (`--global` for `~/.securenow/`) |
335
341
  | `securenow api-key show` | Print masked key + source file |
336
342
  | `securenow api-key clear` | Remove stored key (`--global` for `~/.securenow/`) |
package/SKILL-API.md CHANGED
@@ -32,7 +32,7 @@ npx securenow app connect # SDK runtime app + runtime API key only
32
32
  npx securenow init
33
33
  ```
34
34
 
35
- Use `securenow@7.8.0` or newer for split admin/runtime credentials. Start authentication with `npx securenow login`; do not manually open auth URLs, because the CLI generates the callback/state values. The friendly login flow can connect both lanes, while `npx securenow admin login` only writes `.securenow/admin.json` and `npx securenow app connect` only writes `.securenow/runtime.json`. `init` scaffolds the framework integration.
35
+ Use `securenow@8.0.0` or newer for split admin/runtime credentials and runtime-authenticated ingestion. Start authentication with `npx securenow login`; do not manually open auth URLs, because the CLI generates the callback/state values. The friendly login flow can connect both lanes, while `npx securenow admin login` only writes `.securenow/admin.json` and `npx securenow app connect` only writes `.securenow/runtime.json`. `init` scaffolds the framework integration.
36
36
 
37
37
  ### 2. Run With Instrumentation
38
38
 
@@ -70,7 +70,13 @@ npx securenow app connect # pick/create app; runtime API key is minted au
70
70
  npx securenow api-key set snk_live_abc123...
71
71
  ```
72
72
 
73
- Both paths write the key to `.securenow/runtime.json` (gitignored via credential-file patterns, not a whole-directory `.securenow/` ignore) and the firewall activates on next start. For production, run `npx securenow credentials runtime --env production` and mount/copy the tokenless file as `.securenow/credentials.json` or `.securenow/credentials.<env>.json`.
73
+ Both paths write the key to `.securenow/runtime.json` and the firewall activates on next start. For production, run `npx securenow credentials runtime --env production` and mount/copy the tokenless file as `.securenow/credentials.json` or `.securenow/credentials.<env>.json`.
74
+
75
+ The automatically created key is scoped to the selected app only. Its
76
+ `runtime_app` scopes are `traces:write`, `logs:write`, `firewall:read`,
77
+ `blocklist:read`, and `allowlist:read`. `securenow api-key create` uses the
78
+ current app from `.securenow/runtime.json` by default, resolves that app UUID to
79
+ the server app id, and stores the new one-time plaintext key back as `apiKey`.
74
80
 
75
81
  The firewall syncs your blocklist and enforces it on every request — zero code changes.
76
82
 
@@ -218,7 +224,7 @@ On Vercel it uses `@vercel/otel`; self-hosted uses vanilla `@opentelemetry/sdk-n
218
224
  }
219
225
  ```
220
226
 
221
- Local development and production do not need `.env.local`; `npx securenow app connect` and `npx securenow init` keep `.securenow/runtime.json` filled and gitignored. For production, run `npx securenow credentials runtime --env production` and mount/copy the generated JSON as `.securenow/credentials.json` or `.securenow/credentials.production.json`.
227
+ Local development and production do not need `.env.local`; `npx securenow app connect` and `npx securenow init` keep `.securenow/runtime.json` filled with runtime credentials and secure defaults. For production, run `npx securenow credentials runtime --env production` and mount/copy the generated JSON as `.securenow/credentials.json` or `.securenow/credentials.production.json`.
222
228
 
223
229
  #### Next.js Body Capture
224
230
 
@@ -543,7 +549,7 @@ Local development uses `.securenow/runtime.json`; legacy `.securenow/credentials
543
549
  |---|---|
544
550
  | `app.key` | App routing UUID. The SecureNow ingestion gateway routes telemetry by this key |
545
551
  | `app.name` | Human-readable app label |
546
- | `apiKey` | Scoped runtime API key (`snk_live_...`) |
552
+ | `apiKey` | One-app scoped runtime API key (`snk_live_...`) for telemetry ingestion and firewall sync. Runtime scopes: `traces:write`, `logs:write`, `firewall:read`, `blocklist:read`, `allowlist:read` |
547
553
  | `config.otel.endpoint` | Optional OTLP base endpoint override |
548
554
  | `config.otel.tracesEndpoint` | Optional full traces endpoint |
549
555
  | `config.otel.logsEndpoint` | Optional full logs endpoint |
@@ -589,7 +595,7 @@ npm install securenow@latest
589
595
  npx securenow login
590
596
  ```
591
597
 
592
- No `.env` is needed. `npx securenow app connect` writes app identity, runtime API key, and secure defaults to `.securenow/runtime.json`; the SDK uses the default SecureNow ingestion gateway and the gateway routes by `app.key` while authenticating with the runtime API key. `npx securenow init` makes sure the file has explanations and is gitignored without ignoring the whole `.securenow/` directory.
598
+ No `.env` is needed. `npx securenow app connect` writes app identity, runtime API key, and secure defaults to `.securenow/runtime.json`; the SDK uses the default SecureNow ingestion gateway and the gateway routes by `app.key` while authenticating with the runtime API key. `npx securenow init` makes sure the file has explanations and secure SDK defaults.
593
599
 
594
600
  Update `package.json`:
595
601
  ```json
@@ -605,7 +611,7 @@ npm install securenow@latest
605
611
  npx securenow app connect # pick/create app; runtime API key is minted automatically
606
612
  ```
607
613
 
608
- `securenow app connect` enables the selected app's firewall toggle and writes app/runtime config plus the runtime API key to `.securenow/runtime.json` (gitignored via credential-file patterns, not a whole-directory `.securenow/` ignore). Traces, logs, request body capture, multipart metadata capture, and firewall enforcement are enabled by default. Then run `npx securenow init`; it creates `instrumentation.ts`, patches `next.config.*` when safe, or prints exact Codex/Claude merge instructions for existing files.
614
+ `securenow app connect` enables the selected app's firewall toggle and writes app/runtime config plus the runtime API key to `.securenow/runtime.json`. Traces, logs, request body capture, multipart metadata capture, and firewall enforcement are enabled by default. Then run `npx securenow init`; it creates `instrumentation.ts`, patches `next.config.*` when safe, or prints exact Codex/Claude merge instructions for existing files.
609
615
 
610
616
  ### Enable Firewall With Zero Tracing Overhead
611
617
 
package/SKILL-CLI.md CHANGED
@@ -15,7 +15,7 @@ npx securenow <command>
15
15
 
16
16
  **Full parity with the SDK:** every capability the `securenow` Node SDK exposes has a CLI counterpart — redaction, CIDR matching, log/span emission, firewall preload, config inspection. If you can do it in code, you can do it from the terminal.
17
17
 
18
- **MCP parity (v7.5+):** the same package also ships a local stdio MCP server for Codex, Claude, and other MCP clients:
18
+ **MCP parity (v8.0+):** the same package also ships a local stdio MCP server for Codex, Claude, and other MCP clients:
19
19
 
20
20
  ```bash
21
21
  npx securenow login
@@ -40,11 +40,11 @@ securenow whoami # verify both admin auth and runtime app status
40
40
 
41
41
  **Zero-config runtime flow:** the browser step lets the user pick (or create) an app. The CLI stores the app's **key (UUID)** and **name** in `.securenow/runtime.json`. The SDK sends traces/logs to the default SecureNow ingestion gateway, which routes by app key, so no env vars or per-instance collector URLs are required for local dev or production.
42
42
 
43
- **Default-on security (v7.5.1+):** after picking or creating the app, `securenow app connect` turns on that app's firewall toggle, mints an API key with `firewall:read + blocklist:read + allowlist:read` scopes, and writes it into `.securenow/runtime.json`. Traces, logs, POST body capture, multipart metadata capture, and the firewall are enabled by default. No `SECURENOW_API_KEY` env var is needed. To add or rotate a key later without re-running app connect, use `securenow api-key set snk_live_...` (see [API Key Management](#api-key-management) below).
43
+ **Default-on security (v8.0+):** after picking or creating the app, `securenow app connect` turns on that app's firewall toggle, mints a runtime API key with `traces:write + logs:write + firewall:read + blocklist:read + allowlist:read` scopes, and writes it into `.securenow/runtime.json`. Traces, logs, POST body capture, multipart metadata capture, and the firewall are enabled by default. No `SECURENOW_API_KEY` env var is needed. To add or rotate a key later without re-running app connect, use `securenow api-key create` or `securenow api-key set snk_live_...` (see [API Key Management](#api-key-management) below).
44
44
 
45
45
  Runtime credentials resolve in order: project `.securenow/runtime.json` -> legacy project `.securenow/credentials.json` -> project named runtime credentials -> global `.securenow/runtime.json` -> legacy global credentials -> global named runtime credentials. Admin auth resolves from `admin.json` first, then legacy `credentials.json`. Runtime config is credentials-json based; environment-variable fallbacks are not supported.
46
46
 
47
- The **firewall API key** should live in runtime credentials as `apiKey`.
47
+ The **runtime API key** should live in runtime credentials as `apiKey`; it authenticates telemetry ingestion and firewall sync.
48
48
 
49
49
  For CI / Docker / production, use `securenow credentials runtime --env production` to generate a tokenless runtime file, then mount/copy it as `.securenow/credentials.json`. Since v7.7.2, mounting the generated `.securenow/credentials.production.json` filename directly also works when `credentials.json` is absent.
50
50
 
@@ -161,7 +161,8 @@ securenow apps scan [--yes] # scan all app domains for new subd
161
161
  Manage the runtime API key stored in runtime credentials. Since v8.0 the app runtime flow writes app-scoped `snk_live_...` keys to `.securenow/runtime.json` by default, so no env var is required for local dev.
162
162
 
163
163
  ```bash
164
- securenow api-key create --name "CLI runtime" # mint + save a runtime API key with your logged-in session
164
+ securenow api-key create --name "CLI runtime" # mint + save a current-app runtime key
165
+ securenow api-key create --app <key-or-id> # mint + save a runtime key scoped to another app
165
166
  securenow api-key set snk_live_xxxxxxxxxx # save to project ./.securenow/ (default)
166
167
  securenow api-key set snk_live_xxx --global # save to ~/.securenow/ instead
167
168
  securenow api-key show # print the masked current key + its source
@@ -170,7 +171,7 @@ securenow api-key clear --global # same, but from the global file
170
171
  securenow credentials runtime --env production # write .securenow/credentials.production.json for production secret-file deploys
171
172
  ```
172
173
 
173
- The key must start with `snk_live_`. `securenow app connect` writes the key automatically; use `api-key create` when you have admin auth but no runtime key yet, or `api-key set` when you already have a key from the dashboard.
174
+ The key must start with `snk_live_`. `securenow app connect` writes the key automatically; use `api-key create` when you have admin auth but no runtime key yet, or `api-key set` when you already have a key from the dashboard. `api-key create` defaults to the current app in `.securenow/runtime.json`, resolves that app UUID to the server app id, creates a one-app `runtime_app` key with `traces:write`, `logs:write`, `firewall:read`, `blocklist:read`, and `allowlist:read`, then stores the one-time plaintext key as `apiKey`.
174
175
 
175
176
  ### Init — Project Setup
176
177
 
@@ -179,7 +180,7 @@ securenow init [--env local] [--key <API_KEY>]
179
180
  ```
180
181
 
181
182
  Auto-detects framework (Next.js, Nuxt, Express, Fastify, Koa, Hapi, Node) from `package.json`. Then:
182
- - **Credentials**: ensures `.securenow/runtime.json` exists, has secure defaults/explanations, and local credential JSON files are gitignored without ignoring the whole `.securenow/` directory
183
+ - **Credentials**: ensures `.securenow/runtime.json` exists with secure defaults and explanations
183
184
  - **Next.js**: creates `instrumentation.ts/js` with `securenow/nextjs` + `securenow/nextjs-auto-capture`, and adds `serverExternalPackages: ['securenow']` plus `outputFileTracingIncludes` when the config can be patched safely
184
185
  - **Existing Next.js files**: prints a Codex/Claude-ready merge prompt when instrumentation or config already exists or is too custom to safely patch
185
186
  - **Nuxt**: tells you to add `securenow/nuxt` to modules
@@ -313,7 +314,7 @@ securenow firewall status --app <key> --env production # app/env toggle, sync
313
314
  securenow firewall test-ip <ip> --app <key> --env local # check if IP would be blocked
314
315
  ```
315
316
 
316
- **Zero-config setup:** running `securenow app connect` enables the selected app's firewall toggle, auto-mints an API key (scoped `firewall:read + blocklist:read + allowlist:read`), and writes it to `.securenow/runtime.json` after the app is selected. 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.
317
+ **Zero-config setup:** running `securenow app connect` enables the selected app's firewall toggle, auto-mints a runtime API key (scoped `traces:write + logs:write + firewall:read + blocklist:read + allowlist:read`), and writes it to `.securenow/runtime.json` after the app is selected. No `SECURENOW_API_KEY` env var needed. If the user already has a key, `securenow api-key set snk_live_...` achieves the same thing; if they only have admin auth, `securenow api-key create` mints and saves a fresh runtime key. See [the landing firewall page](https://securenow.ai/firewall) for an overview.
317
318
 
318
319
  ### Blocklist — Block Malicious IPs
319
320
 
package/app-config.js CHANGED
@@ -419,7 +419,7 @@ function withCredentialDefaults(credentials) {
419
419
  out.config = mergeMissing(out.config, DEFAULT_CONFIG);
420
420
  out._securenow = mergeMissing(out._securenow, {
421
421
  schemaVersion: CONFIG_SCHEMA_VERSION,
422
- note: 'Local SecureNow credentials and secure SDK defaults. This file may contain secrets; keep .securenow/ in .gitignore.',
422
+ note: 'Local SecureNow credentials and secure SDK defaults. This file may contain secrets.',
423
423
  precedence: 'The same credentials file works in local development and production. SDK runtime config is read from credentials JSON only.',
424
424
  explanations: CONFIG_EXPLANATIONS,
425
425
  });
package/cli/apiKey.js CHANGED
@@ -8,11 +8,31 @@ const PRESET_SCOPES = {
8
8
  runtime_app: ['traces:write', 'logs:write', 'firewall:read', 'blocklist:read', 'allowlist:read'],
9
9
  };
10
10
 
11
+ const OBJECT_ID_RE = /^[a-f0-9]{24}$/i;
12
+
11
13
  function maskKey(key) {
12
14
  if (!key || key.length < 16) return key || '';
13
15
  return `${key.slice(0, 12)}••••••${key.slice(-4)}`;
14
16
  }
15
17
 
18
+ async function resolveAppScopeForApi(appIdentifier) {
19
+ const raw = String(appIdentifier || '').trim();
20
+ if (!raw || OBJECT_ID_RE.test(raw)) return raw || null;
21
+
22
+ const data = await api.get('/applications');
23
+ const app = (data.applications || []).find((candidate) =>
24
+ candidate.key === raw ||
25
+ candidate._id === raw ||
26
+ candidate.id === raw
27
+ );
28
+
29
+ if (!app) {
30
+ throw new Error(`Could not find application for --app ${raw}`);
31
+ }
32
+
33
+ return app._id || app.id || raw;
34
+ }
35
+
16
36
  async function create(args, flags) {
17
37
  requireAuth();
18
38
 
@@ -27,10 +47,9 @@ async function create(args, flags) {
27
47
  if (PRESET_SCOPES[preset]) {
28
48
  body.scopes = PRESET_SCOPES[preset];
29
49
  }
30
- if (flags.app) {
31
- body.apps = [flags.app];
32
- } else if (preset === 'runtime_app' && app?.key) {
33
- body.apps = [app.key];
50
+ const appScope = flags.app || (preset === 'runtime_app' && app?.key ? app.key : null);
51
+ if (appScope) {
52
+ body.apps = [await resolveAppScopeForApi(appScope)];
34
53
  }
35
54
 
36
55
  const result = await api.post('/api-keys', body);
@@ -39,7 +39,7 @@ function buildRuntimeCredentials(options = {}) {
39
39
  },
40
40
  _securenow: {
41
41
  ...(creds._securenow || {}),
42
- note: 'Runtime SecureNow credentials and SDK defaults. Mount or copy this JSON as .securenow/credentials.json or .securenow/credentials.<environment>.json in production. Do not commit it.',
42
+ note: 'Runtime SecureNow credentials and SDK defaults. Mount or copy this JSON as .securenow/credentials.json or .securenow/credentials.<environment>.json in production.',
43
43
  routing: 'Telemetry is sent to the default SecureNow ingestion gateway. The gateway routes by app.key, so runtime credentials do not expose per-instance collector URLs.',
44
44
  runtimeOnly: 'This file intentionally omits CLI OAuth fields: token, email, and expiresAt.',
45
45
  production: 'Production can use this same file shape instead of environment variables.',
package/cli.js CHANGED
@@ -116,11 +116,11 @@ const COMMANDS = {
116
116
  sub: {
117
117
  create: {
118
118
  desc: 'Create a runtime API key with your session token and save it',
119
- usage: 'securenow api-key create [name] [--name <name>] [--preset runtime_app] [--app <appKey>] [--global]',
119
+ usage: 'securenow api-key create [name] [--name <name>] [--preset runtime_app] [--app <appKeyOrId>] [--global]',
120
120
  flags: {
121
121
  name: 'Human-readable key name',
122
122
  preset: 'API key preset to create (default: runtime_app)',
123
- app: 'Application key/id to scope this key to',
123
+ app: 'Application key or id to scope this key to (defaults to current runtime app)',
124
124
  global: 'Save to ~/.securenow/ instead of project-local',
125
125
  },
126
126
  run: (a, f) => require('./cli/apiKey').create(a, f),
package/mcp/catalog.js CHANGED
@@ -10,7 +10,7 @@ const MARKDOWN = 'text/markdown';
10
10
  const UNIVERSAL_SECURENOW_SETUP_PROMPT = `You are working in an existing JavaScript or TypeScript app. Set up SecureNow end-to-end for the framework/runtime already used by this repo. Treat this as a real onboarding, not just a package install.
11
11
 
12
12
  Primary goals:
13
- - Use the latest published SecureNow npm package. Require securenow@7.8.0 or newer for split admin/runtime credentials.
13
+ - Use the latest published SecureNow npm package. Require securenow@8.0.0 or newer for split admin/runtime credentials and runtime-authenticated ingestion.
14
14
  - By default, enable tracing, logs, POST request body capture, multipart metadata capture, and the SecureNow firewall.
15
15
  - If I explicitly ask for firewall-only mode, keep the same install/login/verification gates, but use firewall-only preload and do not add tracing, logging, or OTel instrumentation.
16
16
  - The firewall must protect the selected SecureNow app, use SecureNow's own blocklist/allowlist/IPDB data, and respect that app's SecureNow AI IPDB confidence threshold. Do not add custom IP reputation providers or custom auto-blocking.
@@ -18,7 +18,7 @@ Primary goals:
18
18
 
19
19
  Safety rules:
20
20
  - Do not print full API keys, JWTs, tokens, or local SecureNow credential files (.securenow/admin.json, .securenow/runtime.json, legacy .securenow/credentials.json, or .securenow/credentials.*.json). Mask secrets.
21
- - Do not commit secrets. Ignore only local SecureNow credential files (.securenow/admin.json, .securenow/runtime.json, .securenow/credentials.json, and .securenow/credentials.*.json); keep the .securenow/ directory itself trackable for repo-owned docs/templates.
21
+ - Keep local SecureNow credential files secret (.securenow/admin.json, .securenow/runtime.json, legacy .securenow/credentials.json, and .securenow/credentials.*.json). Do not print them; mask secrets in summaries.
22
22
  - Do not manually browse to a SecureNow auth URL. Always start auth with npx securenow login so the CLI generates the required callback and state.
23
23
  - If the browser says "Missing callback parameter", you opened the wrong URL: rerun npx securenow login from the project root.
24
24
  - Do not skip login, app selection, firewall connection, or verification unless I explicitly say to.
@@ -32,7 +32,7 @@ Runbook:
32
32
  2. Install or upgrade SecureNow with the detected package manager, using securenow@latest. Verify the actual installed version with:
33
33
  node -p "require('./node_modules/securenow/package.json').version"
34
34
  npx securenow version
35
- Stop and fix the install if either is below 7.8.0 or npx still resolves an older local package.
35
+ Stop and fix the install if either is below 8.0.0 or npx still resolves an older local package.
36
36
  3. Read the installed package surface before editing files: node_modules/securenow/package.json, README/NPM_README, SKILL-API, SKILL-CLI, npx securenow help, and relevant subcommand help for login/init/firewall/doctor/env/test-span/log/mcp.
37
37
  4. Mandatory auth/runtime gate:
38
38
  - Run npx securenow whoami from the project root.
@@ -43,10 +43,10 @@ Runbook:
43
43
  5. Validate project-local credentials without exposing secrets:
44
44
  - Confirm .securenow/runtime.json exists for SDK runtime setup, or legacy .securenow/credentials.json exists for old installs.
45
45
  - Confirm the runtime file has SecureNow's default config/explanations block.
46
- - Confirm the runtime file has an app key/name/instance and a firewall API key after app selection.
46
+ - Confirm the runtime file has an app key/name/instance and a runtime API key after app selection. The app key only routes telemetry; the runtime API key is required to authenticate telemetry ingestion and firewall sync.
47
47
  - Confirm .securenow/admin.json exists only when admin CLI/MCP auth is needed.
48
48
  - Confirm .securenow/admin.json, .securenow/runtime.json, legacy .securenow/credentials.json, and any .securenow/credentials.*.json runtime files are ignored by git, without ignoring the entire .securenow/ directory.
49
- 6. Run npx securenow init. If it fails with ui.header is not a function or another CLI bug, upgrade to securenow@latest, verify >=7.8.0, and retry. Do not silently ignore init failures.
49
+ 6. Run npx securenow init. If it fails with ui.header is not a function or another CLI bug, upgrade to securenow@latest, verify >=8.0.0, and retry. Do not silently ignore init failures.
50
50
  7. Configure the least invasive framework-specific integration:
51
51
  - Next.js: preserve instrumentation.js/ts. Register securenow/nextjs only when NEXT_RUNTIME is nodejs. In ESM files, use createRequire before require("securenow/nextjs"). Include require("securenow/nextjs-auto-capture") for body capture. For Next 15+, add securenow to serverExternalPackages. For older Next.js, use experimental.serverComponentsExternalPackages. Preserve proxy.js/middleware.js.
52
52
  - Nuxt/Nitro: use the documented securenow/nuxt module or Nitro server plugin.
@@ -61,6 +61,7 @@ Runbook:
61
61
  - config.firewall.failMode: "open"
62
62
  - config.capture.maxBodySize: 10240
63
63
  For production, run npx securenow credentials runtime --env production, store the resulting JSON as a deployment secret file, and mount/copy it to <app-root>/.securenow/credentials.json or <app-root>/.securenow/credentials.production.json. Do not recommend env vars unless the user explicitly asks for legacy fallbacks.
64
+ Do not proceed with telemetry verification if the runtime API key is missing; run npx securenow app connect or npx securenow api-key create first. The v8 ingestion gateway rejects app-key-only telemetry.
64
65
  Local credentials should use config.runtime.deploymentEnvironment="local". Production runtime credentials should use "production". The app key stays the same; traces, logs, firewall status, forensics, and CLI/MCP queries are scoped by environment.
65
66
  9. Verify firewall and threshold:
66
67
  - Run npx securenow firewall apps and npx securenow firewall status.
package/nextjs.js CHANGED
@@ -31,12 +31,12 @@
31
31
  */
32
32
 
33
33
  const { randomUUID } = require('crypto');
34
- const { defaultMetricsExporterToNone } = require('./otel-defaults');
34
+ const { nodeSdkDefaultTelemetryOptions } = require('./otel-defaults');
35
35
  const appConfig = require('./app-config');
36
36
  const { resolveClientIpWithDetails } = require('./resolve-ip');
37
37
  const otelResources = require('@opentelemetry/resources');
38
38
 
39
- defaultMetricsExporterToNone();
39
+ const nodeSdkTelemetryOptions = nodeSdkDefaultTelemetryOptions();
40
40
 
41
41
  let isRegistered = false;
42
42
 
@@ -477,6 +477,7 @@ function registerSecureNow(options = {}) {
477
477
  });
478
478
 
479
479
  const sdk = new NodeSDK({
480
+ ...nodeSdkTelemetryOptions,
480
481
  serviceName: serviceName,
481
482
  traceExporter: traceExporter,
482
483
  instrumentations: [httpInstrumentation],
@@ -20,8 +20,8 @@ import { randomUUID } from 'node:crypto';
20
20
  const nodeRequire = createRequire(import.meta.url);
21
21
  const appConfig = nodeRequire('./app-config');
22
22
  const { resolveClientIpWithDetails } = nodeRequire('./resolve-ip');
23
- const { defaultMetricsExporterToNone } = nodeRequire('./otel-defaults');
24
- defaultMetricsExporterToNone();
23
+ const { nodeSdkDefaultTelemetryOptions } = nodeRequire('./otel-defaults');
24
+ const nodeSdkTelemetryOptions = nodeSdkDefaultTelemetryOptions();
25
25
 
26
26
  const { NodeSDK } = nodeRequire('@opentelemetry/sdk-node');
27
27
  const { OTLPTraceExporter } = nodeRequire('@opentelemetry/exporter-trace-otlp-http');
@@ -219,6 +219,7 @@ export default defineNitroPlugin(async (nitroApp) => {
219
219
  const traceExporter = new OTLPTraceExporter({ url: tracesUrl, headers });
220
220
 
221
221
  const sdk = new NodeSDK({
222
+ ...nodeSdkTelemetryOptions,
222
223
  traceExporter,
223
224
  resource,
224
225
  instrumentations: [httpInstrumentation],
package/otel-defaults.js CHANGED
@@ -1,11 +1,39 @@
1
1
  'use strict';
2
2
 
3
+ function isUnset(value) {
4
+ return value == null || String(value).trim() === '';
5
+ }
6
+
7
+ function listIncludes(value, needle) {
8
+ return String(value || '')
9
+ .split(',')
10
+ .map((part) => part.trim().toLowerCase())
11
+ .includes(needle);
12
+ }
13
+
3
14
  function defaultMetricsExporterToNone(env = process.env) {
4
15
  if (!env) return false;
5
16
  const current = env.OTEL_METRICS_EXPORTER;
6
- if (current != null && String(current).trim() !== '') return false;
17
+ if (!isUnset(current)) return false;
7
18
  env.OTEL_METRICS_EXPORTER = 'none';
8
19
  return true;
9
20
  }
10
21
 
11
- module.exports = { defaultMetricsExporterToNone };
22
+ function nodeSdkDefaultTelemetryOptions(env = process.env) {
23
+ const options = {};
24
+
25
+ defaultMetricsExporterToNone(env);
26
+ if (listIncludes(env?.OTEL_METRICS_EXPORTER, 'none')) {
27
+ options.metricReaders = [];
28
+ }
29
+
30
+ // SecureNow installs its own log exporter. Without this, sdk-node falls back
31
+ // to the upstream OTEL_LOGS_EXPORTER default and tries localhost:4318.
32
+ if (env && isUnset(env.OTEL_LOGS_EXPORTER)) {
33
+ options.logRecordProcessors = [];
34
+ }
35
+
36
+ return options;
37
+ }
38
+
39
+ module.exports = { defaultMetricsExporterToNone, nodeSdkDefaultTelemetryOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securenow",
3
- "version": "8.0.1",
3
+ "version": "8.0.3",
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",
package/tracing.js CHANGED
@@ -14,8 +14,8 @@
14
14
  * Production should mount/copy tokenless runtime credentials to the same path.
15
15
  */
16
16
 
17
- const { defaultMetricsExporterToNone } = require('./otel-defaults');
18
- defaultMetricsExporterToNone();
17
+ const { nodeSdkDefaultTelemetryOptions } = require('./otel-defaults');
18
+ const nodeSdkTelemetryOptions = nodeSdkDefaultTelemetryOptions();
19
19
 
20
20
  const { diag, DiagConsoleLogger, DiagLogLevel, context, trace } = require('@opentelemetry/api');
21
21
  const { NodeSDK } = require('@opentelemetry/sdk-node');
@@ -654,6 +654,7 @@ process.on('unhandledRejection', (reason) => {
654
654
  // -------- SDK --------
655
655
  const traceExporter = new OTLPTraceExporter({ url: tracesUrl, headers });
656
656
  const sdk = new NodeSDK({
657
+ ...nodeSdkTelemetryOptions,
657
658
  traceExporter,
658
659
  instrumentations: [
659
660
  httpInstrumentation,