securenow 8.0.2 → 8.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/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 (v8.0+):** 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
@@ -24,31 +24,31 @@ codex mcp add securenow -- npx securenow mcp
24
24
  npx -p securenow securenow-mcp
25
25
  ```
26
26
 
27
- The MCP server reads admin/control-plane auth from `.securenow/admin.json` and SDK runtime app credentials from `.securenow/runtime.json`, with legacy `.securenow/credentials.json` still supported. Admin/global tools use admin auth; runtime-scoped read tools can use the runtime API key where its scopes allow it. Write tools require `confirm:true` plus a reason.
27
+ The MCP server reads admin/control-plane auth from `.securenow/admin.json` and SDK runtime app credentials from `.securenow/runtime.json`, with legacy `.securenow/credentials.json` still supported. Admin/global tools use admin auth; runtime-scoped read tools can use the runtime API key where its scopes allow it. Write tools require `confirm:true` plus a reason.
28
28
 
29
29
  ### Authenticate
30
30
 
31
31
  ```bash
32
- securenow login # friendly flow: admin auth + app runtime connection
33
- securenow admin login # admin/control-plane CLI and MCP auth only
34
- securenow app connect # app/runtime SDK connection only
35
- securenow admin login --token <JWT> # headless / CI admin auth
36
- securenow whoami # verify both admin auth and runtime app status
37
- ```
38
-
39
- **Two-lane credentials (v8.0+):** admin/control-plane auth lives in `.securenow/admin.json`; SDK runtime app config and the runtime API key live in `.securenow/runtime.json`. `securenow login` can run both lanes for onboarding, but `securenow admin login` never replaces runtime app config and `securenow app connect` never replaces admin auth. Legacy combined `.securenow/credentials.json` files are still read.
32
+ securenow login # friendly flow: admin auth + app runtime connection
33
+ securenow admin login # admin/control-plane CLI and MCP auth only
34
+ securenow app connect # app/runtime SDK connection only
35
+ securenow admin login --token <JWT> # headless / CI admin auth
36
+ securenow whoami # verify both admin auth and runtime app status
37
+ ```
38
+
39
+ **Two-lane credentials (v8.0+):** admin/control-plane auth lives in `.securenow/admin.json`; SDK runtime app config and the runtime API key live in `.securenow/runtime.json`. `securenow login` can run both lanes for onboarding, but `securenow admin login` never replaces runtime app config and `securenow app connect` never replaces admin auth. Legacy combined `.securenow/credentials.json` files are still read.
40
40
 
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.
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 (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).
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
- 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.
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 **runtime API key** should live in runtime credentials as `apiKey`; it authenticates telemetry ingestion and firewall sync.
47
+ The **runtime API key** should live in runtime credentials as `apiKey`; it authenticates telemetry ingestion and firewall sync.
48
48
 
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
-
51
- **Environment model:** use one SecureNow app key for local, preview, staging, and production. The credentials field `config.runtime.deploymentEnvironment` separates traces/logs/firewall/forensics by environment. CLI security commands default to `production`; pass `--env local`, `--env staging`, or `--env all` only when that scope is intentional.
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
+
51
+ **Environment model:** use one SecureNow app key for local, preview, staging, and production. The credentials field `config.runtime.deploymentEnvironment` separates traces/logs/firewall/forensics by environment. CLI security commands default to `production`; pass `--env local`, `--env staging`, or `--env all` only when that scope is intentional.
52
52
 
53
53
  ### Integrate With Your App
54
54
 
@@ -65,11 +65,11 @@ node -r securenow/register src/index.js
65
65
  For Next.js, run the interactive scaffolding:
66
66
 
67
67
  ```bash
68
- securenow login
69
- securenow init
70
- ```
71
-
72
- This auto-detects your framework, creates the necessary `instrumentation.ts` and `next.config.js` changes, and reuses the app, instance, and runtime API key written by login or `app connect` to `.securenow/runtime.json`.
68
+ securenow login
69
+ securenow init
70
+ ```
71
+
72
+ This auto-detects your framework, creates the necessary `instrumentation.ts` and `next.config.js` changes, and reuses the app, instance, and runtime API key written by login or `app connect` to `.securenow/runtime.json`.
73
73
 
74
74
  ### Install This Skill in Cursor
75
75
 
@@ -79,19 +79,19 @@ Save this file as `.cursor/skills/securenow-cli/SKILL.md` in your project. Your
79
79
 
80
80
  Config lives in `~/.securenow/` (global) and optionally `.securenow/` (per-project):
81
81
 
82
- | File | Content |
83
- |------|---------|
84
- | `~/.securenow/config.json` | `apiUrl`, `appUrl`, `defaultApp`, `output` |
85
- | `~/.securenow/admin.json` | `token`, `email`, `expiresAt` for global admin/control-plane CLI and MCP auth |
86
- | `~/.securenow/runtime.json` | `apiKey`, `app`, `config` for global SDK runtime |
87
- | `.securenow/admin.json` | `token`, `email`, `expiresAt` for project-local admin/control-plane CLI and MCP auth |
88
- | `.securenow/runtime.json` | `apiKey`, `app`, `config`, `_securenow.explanations` for project-local SDK runtime |
89
- | `.securenow/credentials.json` | Legacy combined credentials; still read for backward compatibility |
90
- | `.securenow/credentials.<environment>.json` | Tokenless runtime credentials generated by `securenow credentials runtime --env <environment>`; read in a fixed order, not selected from env vars |
91
-
92
- **Credential resolution order:** runtime config resolves 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 -> global named runtime credentials. Admin auth resolves from `admin.json` first, then legacy `credentials.json`. Environment-variable fallbacks are not supported.
93
-
94
- **Runtime API key resolution (v8.0+):** project `.securenow/runtime.json` -> legacy project credentials -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> global runtime credentials -> legacy global credentials -> global named runtime credentials. Use `securenow app connect` for runtime setup or `securenow api-key set` to rotate a key without touching admin auth or env vars.
82
+ | File | Content |
83
+ |------|---------|
84
+ | `~/.securenow/config.json` | `apiUrl`, `appUrl`, `defaultApp`, `output` |
85
+ | `~/.securenow/admin.json` | `token`, `email`, `expiresAt` for global admin/control-plane CLI and MCP auth |
86
+ | `~/.securenow/runtime.json` | `apiKey`, `app`, `config` for global SDK runtime |
87
+ | `.securenow/admin.json` | `token`, `email`, `expiresAt` for project-local admin/control-plane CLI and MCP auth |
88
+ | `.securenow/runtime.json` | `apiKey`, `app`, `config`, `_securenow.explanations` for project-local SDK runtime |
89
+ | `.securenow/credentials.json` | Legacy combined credentials; still read for backward compatibility |
90
+ | `.securenow/credentials.<environment>.json` | Tokenless runtime credentials generated by `securenow credentials runtime --env <environment>`; read in a fixed order, not selected from env vars |
91
+
92
+ **Credential resolution order:** runtime config resolves 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 -> global named runtime credentials. Admin auth resolves from `admin.json` first, then legacy `credentials.json`. Environment-variable fallbacks are not supported.
93
+
94
+ **Runtime API key resolution (v8.0+):** project `.securenow/runtime.json` -> legacy project credentials -> project named runtime credentials in the fixed staging/production/preview/local/test/development/dev/prod order -> global runtime credentials -> legacy global credentials -> global named runtime credentials. Use `securenow app connect` for runtime setup or `securenow api-key set` to rotate a key without touching admin auth or env vars.
95
95
 
96
96
  ```bash
97
97
  securenow config set apiUrl https://api.securenow.ai
@@ -101,7 +101,7 @@ securenow config get defaultApp # show one
101
101
  securenow config path # print file paths + active auth source
102
102
  ```
103
103
 
104
- Legacy CLI overrides still exist for operator automation, but runtime SDK config should stay in the credentials file.
104
+ Legacy CLI overrides still exist for operator automation, but runtime SDK config should stay in the credentials file.
105
105
 
106
106
  ## Global Flags
107
107
 
@@ -113,7 +113,7 @@ Legacy CLI overrides still exist for operator automation, but runtime SDK config
113
113
  | `--force` | `-f` | Skip confirmations |
114
114
  | `--yes` | `-y` | Auto-confirm prompts |
115
115
 
116
- SecureNow-specific environment overrides are not supported; use `.securenow/runtime.json`, `.securenow/admin.json`, or `securenow config set`.
116
+ SecureNow-specific environment overrides are not supported; use `.securenow/runtime.json`, `.securenow/admin.json`, or `securenow config set`.
117
117
 
118
118
  ---
119
119
 
@@ -129,19 +129,19 @@ securenow run --firewall-only app.js # preload firewall only (no tracing
129
129
  securenow src/index.js # shorthand — auto-detected as "run"
130
130
  ```
131
131
 
132
- Spawns `node --require securenow/register [--import otel/hook.mjs] <script>`. ESM detection uses nearest `package.json` `"type"` field or `.mjs`/`.cjs` extension. With `--firewall-only`, uses `securenow/firewall-only` instead (credentials-file firewall, no OpenTelemetry).
132
+ Spawns `node --require securenow/register [--import otel/hook.mjs] <script>`. ESM detection uses nearest `package.json` `"type"` field or `.mjs`/`.cjs` extension. With `--firewall-only`, uses `securenow/firewall-only` instead (credentials-file firewall, no OpenTelemetry).
133
133
 
134
134
  ### Authentication
135
135
 
136
136
  ```bash
137
- securenow login # friendly flow: admin auth + app runtime connection
138
- securenow admin login # admin/control-plane CLI and MCP auth only
139
- securenow admin login --token <JWT> # headless / CI admin auth
140
- securenow app connect # app/runtime SDK connection only
141
- securenow logout # clear admin auth; runtime app config remains
142
- securenow logout --global # clear global admin auth only
143
- securenow whoami # show admin auth and runtime app status separately
144
- ```
137
+ securenow login # friendly flow: admin auth + app runtime connection
138
+ securenow admin login # admin/control-plane CLI and MCP auth only
139
+ securenow admin login --token <JWT> # headless / CI admin auth
140
+ securenow app connect # app/runtime SDK connection only
141
+ securenow logout # clear admin auth; runtime app config remains
142
+ securenow logout --global # clear global admin auth only
143
+ securenow whoami # show admin auth and runtime app status separately
144
+ ```
145
145
 
146
146
  ### Applications
147
147
 
@@ -158,39 +158,39 @@ securenow apps scan [--yes] # scan all app domains for new subd
158
158
 
159
159
  ### API Key Management
160
160
 
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.
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
- ```bash
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
166
- securenow api-key set snk_live_xxxxxxxxxx # save to project ./.securenow/ (default)
167
- securenow api-key set snk_live_xxx --global # save to ~/.securenow/ instead
168
- securenow api-key show # print the masked current key + its source
169
- securenow api-key clear # remove just the API key (keeps session/app)
170
- securenow api-key clear --global # same, but from the global file
171
- securenow credentials runtime --env production # write .securenow/credentials.production.json for production secret-file deploys
163
+ ```bash
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
166
+ securenow api-key set snk_live_xxxxxxxxxx # save to project ./.securenow/ (default)
167
+ securenow api-key set snk_live_xxx --global # save to ~/.securenow/ instead
168
+ securenow api-key show # print the masked current key + its source
169
+ securenow api-key clear # remove just the API key (keeps session/app)
170
+ securenow api-key clear --global # same, but from the global file
171
+ securenow credentials runtime --env production # write .securenow/credentials.production.json for production secret-file deploys
172
172
  ```
173
173
 
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
+ 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`.
175
175
 
176
176
  ### Init — Project Setup
177
177
 
178
178
  ```bash
179
- securenow init [--env local] [--key <API_KEY>]
179
+ securenow init [--env local] [--key <API_KEY>]
180
180
  ```
181
181
 
182
- Auto-detects framework (Next.js, Nuxt, Express, Fastify, Koa, Hapi, Node) from `package.json`. Then:
183
- - **Credentials**: ensures `.securenow/runtime.json` exists, has secure defaults/explanations, and local credential JSON files are gitignored without ignoring the whole `.securenow/` directory
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
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
186
- - **Nuxt**: tells you to add `securenow/nuxt` to modules
187
- - **Node/Express/etc.**: suggests adding `-r securenow/register` to start script
188
- - Reuses `.securenow/runtime.json` written by login/app connect; production should mount/copy the tokenless runtime file generated by `securenow credentials runtime --env production`
182
+ Auto-detects framework (Next.js, Nuxt, Express, Fastify, Koa, Hapi, Node) from `package.json`. Then:
183
+ - **Credentials**: ensures `.securenow/runtime.json` exists with secure defaults and explanations
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
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
186
+ - **Nuxt**: tells you to add `securenow/nuxt` to modules
187
+ - **Node/Express/etc.**: suggests adding `-r securenow/register` to start script
188
+ - Reuses `.securenow/runtime.json` written by login/app connect; production should mount/copy the tokenless runtime file generated by `securenow credentials runtime --env production`
189
189
 
190
190
  ### Dashboard & Status
191
191
 
192
192
  ```bash
193
- securenow status [--app <key>] [--env local|production|all] # dashboard overview
193
+ securenow status [--app <key>] [--env local|production|all] # dashboard overview
194
194
  securenow analytics [--app <key>] # response analytics
195
195
  ```
196
196
 
@@ -199,83 +199,91 @@ securenow analytics [--app <key>] # response analytics
199
199
  ### Traces
200
200
 
201
201
  ```bash
202
- securenow traces [--app <key>] [--env production] [--limit N] [--start ISO] [--end ISO]
203
- securenow traces list --app my-app --env production --limit 50
204
- securenow traces show <traceId> --env production # full trace detail with spans
205
- securenow traces analyze <traceId> --env production # AI-powered trace analysis
202
+ securenow traces [--app <key>] [--env production] [--limit N] [--start ISO] [--end ISO]
203
+ securenow traces list --app my-app --env production --limit 50
204
+ securenow traces show <traceId> --env production # full trace detail with spans
205
+ securenow traces analyze <traceId> --env production # AI-powered trace analysis
206
206
  ```
207
207
 
208
208
  ### Logs
209
209
 
210
210
  ```bash
211
- securenow logs [--app <key>] [--env production] [--limit N] [--minutes M] [--level error|warn|info]
212
- securenow logs list --app my-app --env production --minutes 30 --level error
213
- securenow logs trace <traceId> --env production # logs correlated to a specific trace
214
- ```
215
-
216
- ### Notifications
217
-
218
- ```bash
219
- securenow notifications [--limit N] [--page P]
220
- securenow notifications list --limit 20
221
- securenow notifications read <id> # mark one as read
222
- securenow notifications read-all # mark all as read
223
- securenow notifications unread # unread count
224
- ```
225
-
226
- ### Human Actions — AI-Prepared Decision Queue
227
-
228
- Use this for the same work shown in **Requires Human**: AI has already grouped alerts, fetched traces, built a report, and left a final Block IP or False Positive decision.
229
-
230
- ```bash
231
- securenow human # list human decisions, most urgent first
232
- securenow human list --limit 20
233
- securenow human show 1 # inspect row 1 with AI report, investigation steps, proofs, trace links
234
- securenow human block 1 --yes --reason "AI evidence confirmed malicious"
235
- securenow human fp 1 --yes --reason "Scoped false positive after evidence review"
236
- securenow human action 1 --status rejected --yes --reason "Tuning guard is too broad"
237
- securenow human prompt 1 # print a Codex/Claude MCP prompt for this row
238
- securenow human work --limit 10 # list queue + print MCP runbook for deep queue work
239
- ```
240
-
241
- MCP parity:
242
-
243
- - `securenow_human_actions_list`
244
- - `securenow_notifications_get`
245
- - `securenow_human_action_report`
246
- - `securenow_human_action_block`
247
- - `securenow_human_action_false_positive`
248
- - `securenow_human_case_action_update`
249
- - prompts: `investigate_human_action_row`, `work_human_actions`
250
-
251
- Write tools still require `confirm:true` plus a reason. False positives should stay restrictive to the app, alert rule, path, method/status, user-agent, body pattern, or other exact evidence the AI report supports. Notification IP investigations can include `metadata.matchedSubdetectors`; prefer that exact field over inferring which subdetector fired from the title or sample body.
252
-
253
- ### Alerts
254
-
255
- ```bash
256
- securenow alerts # list alert rules (default)
211
+ securenow logs [--app <key>] [--env production] [--limit N] [--minutes M] [--level error|warn|info]
212
+ securenow logs list --app my-app --env production --minutes 30 --level error
213
+ securenow logs trace <traceId> --env production # logs correlated to a specific trace
214
+ ```
215
+
216
+ ### Notifications
217
+
218
+ ```bash
219
+ securenow notifications [--limit N] [--page P]
220
+ securenow notifications list --limit 20
221
+ securenow notifications read <id> # mark one as read
222
+ securenow notifications read-all # mark all as read
223
+ securenow notifications unread # unread count
224
+ ```
225
+
226
+ ### Human Actions — AI-Prepared Decision Queue
227
+
228
+ Use this for the same work shown in **Requires Human**: AI has already grouped alerts, fetched traces, built a report, and left a final Block IP or False Positive decision.
229
+
230
+ ```bash
231
+ securenow human # list human decisions, most urgent first
232
+ securenow human list --limit 20
233
+ securenow human show 1 # inspect row 1 with AI report, investigation steps, proofs, trace links
234
+ securenow human block 1 --yes --reason "AI evidence confirmed malicious"
235
+ securenow human fp 1 --yes --reason "Scoped false positive after evidence review"
236
+ securenow human action 1 --status rejected --yes --reason "Tuning guard is too broad"
237
+ securenow human prompt 1 # print a Codex/Claude MCP prompt for this row
238
+ securenow human work --limit 10 # list queue + print MCP runbook for deep queue work
239
+ ```
240
+
241
+ MCP parity:
242
+
243
+ - `securenow_human_actions_list`
244
+ - `securenow_notifications_get`
245
+ - `securenow_human_action_report`
246
+ - `securenow_human_action_block`
247
+ - `securenow_human_action_false_positive`
248
+ - `securenow_human_case_action_update`
249
+ - prompts: `investigate_human_action_row`, `work_human_actions`
250
+
251
+ Write tools still require `confirm:true` plus a reason. False positives should stay restrictive to the app, alert rule, path, method/status, user-agent, body pattern, or other exact evidence the AI report supports. Notification IP investigations can include `metadata.matchedSubdetectors`; prefer that exact field over inferring which subdetector fired from the title or sample body.
252
+
253
+ ### Alerts
254
+
255
+ ```bash
256
+ securenow alerts # list alert rules (default)
257
257
  securenow alerts rules # list alert rules (columns: Status, Applications, Schedule)
258
- securenow alerts rules show <id> # one rule; JSON: --json
259
- securenow alerts rules update <id> --applications-all # all current & future apps
260
- securenow alerts rules update <id> --apps key1,key2 # explicit app keys only
261
- securenow alerts rules test <id> --mode dry_run --wait # validate a rule query
262
- securenow alerts rules dry-run-query <id> --sql @candidate.sql --app <key> --wait
263
- securenow alerts rules tune-query <id> --sql @candidate.sql --reason "Preserve exploit detector, remove benign broad match" --apply-globally --yes
264
- securenow alerts rules exclusions <id> list # embedded rule exclusions
265
- securenow alerts channels # list alert channels (Slack, email, etc.)
266
- securenow alerts history [--limit N] # past triggered alerts
267
- ```
268
-
269
- MCP parity for noisy alert-rule reviews:
270
-
271
- - `securenow_alert_rule_get`
272
- - `securenow_alert_rule_candidate_test` dry-runs a full candidate SQL query without saving it.
273
- - `securenow_alert_rule_test_result` polls the dry-run.
274
- - `securenow_alert_rule_query_update` updates the shared public query mapping behind a system rule for all customer copies. It is admin-only, requires `confirm:true`, `applyGlobally:true`, `reason`, and SQL that keeps `__USER_APP_KEYS__` tenant scoping.
275
- - `securenow_alert_rule_instant_update` patches Instant rule conditions/config with stale-write guards. Fetch the rule first, pass `expectedRuleVersion` plus `expectedCurrentInstantHash`, use operations such as `remove_condition` / `add_condition` / `update_condition`, and set `applyGlobally:true` for system rules. The API runs seeded before/after checks and returns benign samples removed plus attack samples still matching. If global tuning is denied, it returns a structured admin handoff with the exact patch and missing permission.
276
- - `securenow_alert_rule_exclusion_add` remains the last-resort customer-specific path; it supports restrictive conditions plus `matchMode` and should not be used to hide a generic system-rule bug.
277
-
278
- For system-rule tuning, dry-run the candidate SQL first for scheduled rules, or use `dryRun:true` on `securenow_alert_rule_instant_update` for Instant rules. Save only when the guard preserves attack detection. Good guards add exact exploit tokens, dangerous schemes, matched subdetectors, sensitive path/status evidence, malicious user agents, or repeat thresholds; bad guards simply suppress a noisy path.
258
+ securenow alerts rules create \ # NEW: create a custom detection rule from inline SQL
259
+ --name "Auth: magic-link brute force" \
260
+ --sql @rule.sql \ # SQL, @file, or - for stdin; scope apps with __USER_APP_KEYS__
261
+ --apps key1,key2 \ # or --applications-all
262
+ --severity high --schedule "*/15 * * * *" \
263
+ --nlp "single IP flooding /api/auth/signin or /api/auth/callback"
264
+ securenow alerts rules show <id> # one rule; JSON: --json
265
+ securenow alerts rules update <id> --applications-all # all current & future apps
266
+ securenow alerts rules update <id> --apps key1,key2 # explicit app keys only
267
+ securenow alerts rules test <id> --mode dry_run --wait # validate a rule query
268
+ securenow alerts rules dry-run-query <id> --sql @candidate.sql --app <key> --wait
269
+ securenow alerts rules tune-query <id> --sql @candidate.sql --reason "Preserve exploit detector, remove benign broad match" --apply-globally --yes
270
+ securenow alerts rules exclusions <id> list # embedded rule exclusions
271
+ securenow alerts channels # list alert channels (Slack, email, etc.)
272
+ securenow alerts history [--limit N] # past triggered alerts
273
+ ```
274
+
275
+ `alerts rules create` flags: `--name` (required); one of `--sql <sql|@file|->` or `--query-mapping-id <id>`; one of `--apps k1,k2` or `--applications-all`; optional `--description`, `--nlp` (plain-English intent), `--category`, `--severity critical|high|medium|low`, `--schedule <cron>` (default `*/15 * * * *`), `--throttle-minutes N` / `--no-throttle`, `--execution-mode scheduled|instant|hybrid`, `--channel id1,id2` (defaults to your in-app SecureNow channel). Detection SQL must scope app keys via the `__USER_APP_KEYS__` placeholder and select an `ip` column for per-IP aggregation/remediation. Requires `alerts:write`.
276
+
277
+ MCP parity for noisy alert-rule reviews:
278
+
279
+ - `securenow_alert_rule_get`
280
+ - `securenow_alert_rule_candidate_test` dry-runs a full candidate SQL query without saving it.
281
+ - `securenow_alert_rule_test_result` polls the dry-run.
282
+ - `securenow_alert_rule_query_update` updates the shared public query mapping behind a system rule for all customer copies. It is admin-only, requires `confirm:true`, `applyGlobally:true`, `reason`, and SQL that keeps `__USER_APP_KEYS__` tenant scoping.
283
+ - `securenow_alert_rule_instant_update` patches Instant rule conditions/config with stale-write guards. Fetch the rule first, pass `expectedRuleVersion` plus `expectedCurrentInstantHash`, use operations such as `remove_condition` / `add_condition` / `update_condition`, and set `applyGlobally:true` for system rules. The API runs seeded before/after checks and returns benign samples removed plus attack samples still matching. If global tuning is denied, it returns a structured admin handoff with the exact patch and missing permission.
284
+ - `securenow_alert_rule_exclusion_add` remains the last-resort customer-specific path; it supports restrictive conditions plus `matchMode` and should not be used to hide a generic system-rule bug.
285
+
286
+ For system-rule tuning, dry-run the candidate SQL first for scheduled rules, or use `dryRun:true` on `securenow_alert_rule_instant_update` for Instant rules. Save only when the guard preserves attack detection. Good guards add exact exploit tokens, dangerous schemes, matched subdetectors, sensitive path/status evidence, malicious user agents, or repeat thresholds; bad guards simply suppress a noisy path.
279
287
 
280
288
  ---
281
289
 
@@ -284,15 +292,15 @@ For system-rule tuning, dry-run the candidate SQL first for scheduled rules, or
284
292
  ```bash
285
293
  securenow ip <ip-address> # lookup (geo, ASN, threat score, reputation)
286
294
  securenow ip lookup <ip-address> # same as above
287
- securenow ip traces <ip-address> --env production # traces originating from this IP
295
+ securenow ip traces <ip-address> --env production # traces originating from this IP
288
296
  ```
289
297
 
290
298
  ### Forensics — Natural Language Security Queries
291
299
 
292
300
  ```bash
293
- securenow forensics "show me all SQL injection attempts in the last 24h" --env production
294
- securenow forensics query "top 10 IPs by blocked requests" --app my-app --env production
295
- securenow forensics chat --app my-app --env production # interactive forensics chat session
301
+ securenow forensics "show me all SQL injection attempts in the last 24h" --env production
302
+ securenow forensics query "top 10 IPs by blocked requests" --app my-app --env production
303
+ securenow forensics chat --app my-app --env production # interactive forensics chat session
296
304
  securenow forensics library # view saved/template queries
297
305
  ```
298
306
 
@@ -309,100 +317,100 @@ securenow api-map stats # endpoint statistics
309
317
  ### Firewall
310
318
 
311
319
  ```bash
312
- securenow firewall # show status (default)
313
- securenow firewall status --app <key> --env production # app/env toggle, sync time, blocked count
314
- securenow firewall test-ip <ip> --app <key> --env local # check if IP would be blocked
320
+ securenow firewall # show status (default)
321
+ securenow firewall status --app <key> --env production # app/env toggle, sync time, blocked count
322
+ securenow firewall test-ip <ip> --app <key> --env local # check if IP would be blocked
315
323
  ```
316
324
 
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.
325
+ **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.
318
326
 
319
327
  ### Blocklist — Block Malicious IPs
320
328
 
321
329
  ```bash
322
- securenow blocklist # list blocked IPs
323
- securenow blocklist list
324
- securenow blocklist add <ip> --app <key> --env production --reason "Brute force"
325
- securenow blocklist add <ip> --route /admin* --mode prefix --method ALL --reason "Admin probing"
326
- securenow blocklist unblock <id> --reason "False alarm after review"
327
- securenow blocklist remove <id> # compatibility alias for unblock
328
- securenow blocklist list --status removed # audit retained unblocks
329
- securenow blocklist stats # block counts, top reasons
330
- ```
331
-
332
- Scoped blocks use the same model as rate limits: `--route`/`--path`/`--pattern`
333
- sets `pathPattern`, `--mode`/`--path-mode` chooses `prefix`, `exact`, or
334
- `regex`, and `--method` limits enforcement to one HTTP method or `ALL`.
335
-
336
- Unblock stops firewall enforcement but preserves the block report, history, and
337
- unblock audit fields. Reblocking the same IP later creates a fresh active block
338
- without erasing the previous investigation trail.
339
-
340
- MCP exposes legacy pending-block cleanup separately from current Requires Human
341
- work:
342
-
343
- - `securenow_blocklist_unblock`
344
- - `securenow_blocklist_remove` (compatibility alias for unblock)
345
- - `securenow_blocklist_pending_list`
346
- - `securenow_blocklist_pending_approve`
347
- - `securenow_blocklist_pending_reject`
348
- - `securenow_blocklist_pending_bulk_approve`
349
- - `securenow_blocklist_pending_bulk_reject`
350
- - prompt: `cleanup_legacy_pending_blocks`
351
-
352
- ### Rate Limits - Soft Remediation
353
-
354
- ```bash
355
- securenow ratelimit list --env production
356
- securenow ratelimit add 203.0.113.42 --route /api/login --limit 2 --window 1m --duration 24h
357
- securenow ratelimit parse "rate limit 203.0.113.42 on POST /api/login to 2 attempts per minute"
358
- securenow ratelimit from-text "rate limit /api/login for this IP to 2 attempts per minute for 24h" --yes
359
- securenow ratelimit test 203.0.113.42 --path /api/login --method POST
360
- ```
361
-
362
- MCP parity:
363
-
364
- - `securenow_rate_limit_parse`
365
- - `securenow_rate_limit_create_from_text`
366
-
367
- ### Automation Rules
368
-
369
- ```bash
370
- securenow automation # list blocklist automation rules
371
- securenow automation defaults --yes # ensure built-in default risk-score rules
372
- securenow automation show <id>
373
- securenow automation dry-run <id> --limit 500
374
- securenow automation execute <id> --yes
375
- ```
376
-
377
- Built-in default automation is enabled by default for all apps/environments and
378
- uses the canonical `riskScore`: 95-100 blocks for 7 days, 90-94 blocks for 72h,
379
- 85-89 blocks for 24h, and scores below 85 stay in investigation/review unless
380
- the customer adds a stricter custom rule. Raw SecureNow IPDB confidence remains
381
- supporting evidence, not the primary automation score.
330
+ securenow blocklist # list blocked IPs
331
+ securenow blocklist list
332
+ securenow blocklist add <ip> --app <key> --env production --reason "Brute force"
333
+ securenow blocklist add <ip> --route /admin* --mode prefix --method ALL --reason "Admin probing"
334
+ securenow blocklist unblock <id> --reason "False alarm after review"
335
+ securenow blocklist remove <id> # compatibility alias for unblock
336
+ securenow blocklist list --status removed # audit retained unblocks
337
+ securenow blocklist stats # block counts, top reasons
338
+ ```
339
+
340
+ Scoped blocks use the same model as rate limits: `--route`/`--path`/`--pattern`
341
+ sets `pathPattern`, `--mode`/`--path-mode` chooses `prefix`, `exact`, or
342
+ `regex`, and `--method` limits enforcement to one HTTP method or `ALL`.
343
+
344
+ Unblock stops firewall enforcement but preserves the block report, history, and
345
+ unblock audit fields. Reblocking the same IP later creates a fresh active block
346
+ without erasing the previous investigation trail.
347
+
348
+ MCP exposes legacy pending-block cleanup separately from current Requires Human
349
+ work:
350
+
351
+ - `securenow_blocklist_unblock`
352
+ - `securenow_blocklist_remove` (compatibility alias for unblock)
353
+ - `securenow_blocklist_pending_list`
354
+ - `securenow_blocklist_pending_approve`
355
+ - `securenow_blocklist_pending_reject`
356
+ - `securenow_blocklist_pending_bulk_approve`
357
+ - `securenow_blocklist_pending_bulk_reject`
358
+ - prompt: `cleanup_legacy_pending_blocks`
359
+
360
+ ### Rate Limits - Soft Remediation
361
+
362
+ ```bash
363
+ securenow ratelimit list --env production
364
+ securenow ratelimit add 203.0.113.42 --route /api/login --limit 2 --window 1m --duration 24h
365
+ securenow ratelimit parse "rate limit 203.0.113.42 on POST /api/login to 2 attempts per minute"
366
+ securenow ratelimit from-text "rate limit /api/login for this IP to 2 attempts per minute for 24h" --yes
367
+ securenow ratelimit test 203.0.113.42 --path /api/login --method POST
368
+ ```
369
+
370
+ MCP parity:
371
+
372
+ - `securenow_rate_limit_parse`
373
+ - `securenow_rate_limit_create_from_text`
374
+
375
+ ### Automation Rules
376
+
377
+ ```bash
378
+ securenow automation # list blocklist automation rules
379
+ securenow automation defaults --yes # ensure built-in default risk-score rules
380
+ securenow automation show <id>
381
+ securenow automation dry-run <id> --limit 500
382
+ securenow automation execute <id> --yes
383
+ ```
384
+
385
+ Built-in default automation is enabled by default for all apps/environments and
386
+ uses the canonical `riskScore`: 95-100 blocks for 7 days, 90-94 blocks for 72h,
387
+ 85-89 blocks for 24h, and scores below 85 stay in investigation/review unless
388
+ the customer adds a stricter custom rule. Raw SecureNow IPDB confidence remains
389
+ supporting evidence, not the primary automation score.
382
390
 
383
391
  ### Allowlist — Restrict to Known IPs
384
392
 
385
- Dangerous production mode: IP Allowlist is deny-by-default. Once any active
386
- allowlist entry exists for an app/environment, only listed IPs can reach it and
387
- all other IPs are blocked. Do not use allowlist to mark an IP trusted, suppress
388
- false positives, or clean up investigations. Use `securenow trusted add` for
389
- known-safe monitors, office/VPN traffic, or trusted bypass cases.
390
-
391
- ```bash
392
- securenow allowlist # list allowed IPs
393
- securenow allowlist list
394
- securenow allowlist add <ip> --app <key> --env local --label "Office" --reason "Corporate VPN"
393
+ Dangerous production mode: IP Allowlist is deny-by-default. Once any active
394
+ allowlist entry exists for an app/environment, only listed IPs can reach it and
395
+ all other IPs are blocked. Do not use allowlist to mark an IP trusted, suppress
396
+ false positives, or clean up investigations. Use `securenow trusted add` for
397
+ known-safe monitors, office/VPN traffic, or trusted bypass cases.
398
+
399
+ ```bash
400
+ securenow allowlist # list allowed IPs
401
+ securenow allowlist list
402
+ securenow allowlist add <ip> --app <key> --env local --label "Office" --reason "Corporate VPN"
395
403
  securenow allowlist remove <id>
396
404
  securenow allowlist stats
397
405
  ```
398
406
 
399
- ### Trusted IPs
407
+ ### Trusted IPs
408
+
409
+ Trusted IPs are the safe bypass/suppression mechanism for known infrastructure
410
+ and do not enable deny-by-default allowlist mode.
400
411
 
401
- Trusted IPs are the safe bypass/suppression mechanism for known infrastructure
402
- and do not enable deny-by-default allowlist mode.
403
-
404
- ```bash
405
- securenow trusted # list trusted IPs
412
+ ```bash
413
+ securenow trusted # list trusted IPs
406
414
  securenow trusted list
407
415
  securenow trusted add <ip> [--label "CloudFlare edge"]
408
416
  securenow trusted remove <id>
@@ -496,7 +504,7 @@ securenow test-span
496
504
  securenow test-span "ci.smoke-test" # custom span name
497
505
  ```
498
506
 
499
- Both commands use the default SecureNow ingestion gateway plus optional advanced `config.otel.*` overrides from `.securenow/runtime.json` or legacy runtime credentials, and return non-zero on HTTP errors so CI/cron can detect failures.
507
+ Both commands use the default SecureNow ingestion gateway plus optional advanced `config.otel.*` overrides from `.securenow/runtime.json` or legacy runtime credentials, and return non-zero on HTTP errors so CI/cron can detect failures.
500
508
 
501
509
  ### Utilities — Redaction, CIDR, Diagnostics
502
510
 
@@ -511,7 +519,7 @@ securenow redact @request.json --fields internal_id,sessionHash
511
519
  securenow cidr match 10.0.0.5 10.0.0.0/24,192.168.0.0/16
512
520
  securenow cidr parse 10.0.0.0/24 # network, broadcast, mask, size
513
521
 
514
- # Show resolved config (service name, endpoints, credentials, firewall layers)
522
+ # Show resolved config (service name, endpoints, credentials, firewall layers)
515
523
  securenow env # human-readable
516
524
  securenow env --json # pipe to jq
517
525
 
@@ -520,7 +528,7 @@ securenow doctor # exits 0 if healthy, 1 otherwise
520
528
  securenow doctor --json
521
529
  ```
522
530
 
523
- The `redact` command accepts a JSON string or `@path/to/file.json` and layers your `--fields` flag on top of `DEFAULT_SENSITIVE_FIELDS`. Exit code from `cidr match` is `0` if the IP matches the list, `2` otherwise — scriptable.
531
+ The `redact` command accepts a JSON string or `@path/to/file.json` and layers your `--fields` flag on top of `DEFAULT_SENSITIVE_FIELDS`. Exit code from `cidr match` is `0` if the IP matches the list, `2` otherwise — scriptable.
524
532
 
525
533
  ---
526
534
 
@@ -604,10 +612,10 @@ All commands support `--json` for structured output. When piping to other tools
604
612
 
605
613
  | Exit code / Error | Meaning | Recovery |
606
614
  |------------------|---------|----------|
607
- | `Session expired` | Admin JWT expired | `securenow admin login` (or `admin login --global` for shared admin auth) |
608
- | `Not logged in` | No admin token found | `securenow admin login`; runtime `.securenow/runtime.json` is unrelated |
609
- | `Access denied (403)` | Insufficient plan or permissions | Upgrade plan or check user role |
610
- | `Cannot connect` | API unreachable | Check `securenow config get apiUrl` or network |
615
+ | `Session expired` | Admin JWT expired | `securenow admin login` (or `admin login --global` for shared admin auth) |
616
+ | `Not logged in` | No admin token found | `securenow admin login`; runtime `.securenow/runtime.json` is unrelated |
617
+ | `Access denied (403)` | Insufficient plan or permissions | Upgrade plan or check user role |
618
+ | `Cannot connect` | API unreachable | Check `securenow config get apiUrl` or network |
611
619
  | `Unknown command` | Typo or unrecognized command | `securenow help` |
612
620
 
613
- SecureNow-specific environment overrides are intentionally unsupported for troubleshooting; use explicit CLI config files and normal terminal logs.
621
+ SecureNow-specific environment overrides are intentionally unsupported for troubleshooting; use explicit CLI config files and normal terminal logs.