# Authentication Threat Model — Generator Prompt

A **copy-paste prompt** for customers. Paste the entire prompt below into an AI coding agent
(Claude Code, Cursor, Codex, …) opened at the root of **any project** that has the
`securenow` SDK installed (`node_modules/securenow`) and the CLI logged in. The agent will
analyze the codebase, build an exhaustive authentication threat model, ground every rule and
command in the **installed** SecureNow SDK, and emit a SecureNow-branded **two-track**
deliverable set: an operational **Detection & Mitigation** runbook (what to run in SecureNow,
with ready-to-copy rule + command blocks) and a **Code Findings & Recommendations** audit
(issues in the codebase + fixes), each in **Markdown + self-contained HTML** with offline copy
buttons.

Requirements on the customer machine: the project depends on `securenow` (so
`node_modules/securenow` exists — otherwise `npm i securenow`) and the CLI is authenticated
(`securenow login`; admin auth + app runtime connected). Everything else is discovered by the
agent.

---

<!-- ════════════════ COPY EVERYTHING BELOW THIS LINE ════════════════ -->

# Generate an Authentication Threat Model Report (SecureNow)

You are a senior application-security engineer. Produce an **exhaustive authentication
threat model for THIS codebase**, mapped to **SecureNow** detections and mitigations, with a
ready-to-run action plan. **Ground every alert rule and CLI command in the `securenow` SDK
that is actually installed in this repo** (`node_modules/securenow`) — never guess flags,
subcommands, event names, or SQL columns. Emit every detection as a **ready-to-copy** unit
(SQL → save to `rules/<name>.sql` → full `securenow alerts rules create …` → dry-run test).

You write **four** deliverables — **two tracks** — into `threat/01-authentication/` (create the
folder if needed):

1. `authentication-detection-mitigation.md` — the **operational runbook**: what to run in
   SecureNow (detection rules to create, mitigation commands, testing, response runbooks).
2. `authentication-detection-mitigation.html` — the same runbook as a **self-contained** HTML
   page (inline CSS + copy JS, no network requests) with a **Copy button on every command
   block**, using the SecureNow branding skeleton given at the end of this prompt.
3. `authentication-code-findings.md` — the **code audit**: authentication issues found in the
   codebase + recommended fixes (described, never applied).
4. `authentication-code-findings.html` — the same audit as a self-contained HTML page.

The two tracks **cross-link** each other: gap/instrumentation rows in the detection report link
to the relevant code finding, and each code finding links back to the detection row it backs.

Work in the phases below, in order. Never invent facts: if something is not in the codebase or
not returned by a CLI command, say "not found" — do not guess.

---

## Phase 0 — Verify SecureNow tooling

Run and record (use `--json` where supported):

```bash
securenow doctor              # connectivity must be healthy
securenow whoami              # admin auth + runtime app
securenow status --json       # app key(s), environment, firewall state
securenow alerts rules --json # detection rules that already exist
securenow automation --json   # blocklist automations that already exist
securenow env --json          # resolved SDK config (service name, endpoints)
```

If the CLI is missing or not logged in, **stop** and tell the user to run
`npm i -g securenow && securenow login`, then re-run this prompt. Capture the **app key**
(UUID) — every rule and command in the report must use it. If multiple apps exist, ask the
user which app this codebase maps to before continuing.

---

## Phase 0.5 — Ground every rule & command in the INSTALLED SDK

Before writing any SQL or CLI, read the SecureNow SDK that is actually installed in this repo so
every alert rule and command is correct for THIS version — never guess flags, subcommands, event
names, or SQL columns:

```bash
cat node_modules/securenow/package.json    # installed SDK version (record it in both reports)
ls node_modules/securenow                  # exported modules: events, sessions, register, run, …
ls node_modules/securenow/dist 2>/dev/null # built entrypoints / bundled CLI
npx securenow --help                       # top-level commands available in this version
npx securenow alerts rules --help          # exact create flags: --name/--sql/--apps/--severity/--schedule/--nlp
npx securenow event --help                 # `event send` shape for synthetic tests
npx securenow ratelimit --help; npx securenow challenge --help
npx securenow blocklist --help; npx securenow automation --help; npx securenow trusted --help
```

If `node_modules/securenow` is absent, run `npm ls securenow`; if still missing, tell the user to
`npm i securenow` (or `npm i -g securenow`) and stop. EVERY command, flag, `track('…')` event
name, and SQL column you emit MUST be one the installed SDK/CLI actually exposes. If the installed
version lacks a capability this prompt references, emit the rule but annotate it
`# requires securenow >= <version>` instead of a broken command. Record the resolved version in
the appendix of BOTH reports.

In Phase 4 and Phase 5, treat `node_modules/securenow` + `--help` as the source of truth: the
`securenow/events` `track()` signatures, the `securenow alerts rules` SQL columns, and every
mitigation subcommand are discoverable there. Cross-check before emitting.

---

## Phase 1 — Discover the authentication surface (codebase analysis)

Search the codebase and document what is **actually implemented**. Cover at minimum:

- **Mechanisms** — password login, magic link, OTP/SMS, OAuth/OIDC providers, SAML/SSO,
  WebAuthn/passkeys, API keys, mTLS, basic auth, dev/test backdoors.
- **Endpoints** — login, logout, signup, callback, token refresh, password reset/forgot,
  email/phone change, MFA enroll/challenge, session polling. List the exact routes.
- **Session model** — JWT vs server-side sessions, signing algorithm and secret source,
  lifetime, cookie flags (httpOnly/secure/SameSite/domain), revocation capability.
- **Credential storage** — hashing algorithm and parameters, salting, pepper.
- **MFA** — factors offered, where it can be skipped, recovery codes, remember-me.
- **Recovery flows** — reset-token generation, lifetime, single-use, host/URL construction.
- **Existing protections** — rate limiters (and whether in-memory or shared), lockout
  policy, CAPTCHA, WAF/CDN in front.
- **Machine auth** — API key format/scopes/rotation, service-to-service trust, webhooks.
- **Secrets hygiene** — auth secrets in the repo, in client bundles, in logs.
- **SecureNow instrumentation already present** — `securenow/register` or `securenow run`,
  `securenow/sessions` `guard()`/`capture()`, `securenow/events` `track()` calls, NextAuth
  event wiring. This determines which detections work *today* vs *after instrumentation*.

Output of this phase = the **Surface & inventory** section of the **code-findings** report: a
component table (Login / Session / Storage / MFA / Recovery / Existing limits / Sensitive paths)
plus a short paragraph naming the real attack surface for this stack. The detection report's
"SDK & environment" section reuses the relevant subset (app key, env, existing instrumentation).

---

## Phase 2 — Enumerate threats (exhaustive catalog)

Evaluate **every** threat below against the discovered stack. Each item is either
**modeled** (gets a row in the threat matrix) or **explicitly N/A** (one line in an
"Out of scope" subsection with the reason — e.g. "password spraying: N/A, passwordless
app"). Never silently drop an item. Add stack-specific threats you discover that are not
listed — this catalog is the floor, not the ceiling.

**A. Credential attacks**
1. Single-IP brute force on login
2. Distributed / low-and-slow brute force (botnet, rotating IPs within an ASN)
3. Credential stuffing (breached pairs; one IP or ASN → many accounts)
4. Password spraying (one password → many accounts, lockout-evading)
5. Default / weak / seeded test credentials reachable in production

**B. Enumeration & reconnaissance**
6. Account enumeration via login/signup/reset response or timing oracle
7. Identifier harvesting at scale (one IP probing many emails/usernames)
8. Auth-surface scanning (forced browsing for admin/login panels, .git, env files)

**C. Session & account takeover**
9. Session/cookie theft — XSS, malware, AiTM phishing proxy (Evilginx-class)
10. Session fixation
11. Missing/broken revocation (logout doesn't invalidate; no server-side kill switch)
12. Concurrent session use from 2+ networks (theft indicator)
13. CSRF on state-changing auth endpoints
14. Weak cookie configuration (missing httpOnly/secure/SameSite, broad domain)
15. Excessive session lifetime / replay after logical expiry
16. Login from anomalous network (hosting/VPN/datacenter ASN, impossible travel)

**D. Token attacks (JWT / opaque / refresh)**
17. `alg=none` / algorithm-confusion (RS256→HS256) acceptance
18. Weak or brute-forceable signing secret
19. Missing `exp` / `aud` / `iss` validation
20. Refresh-token theft; missing rotation and reuse detection
21. Token leakage — URLs, logs, Referer headers, localStorage exposed to XSS

**E. Passwordless / OTP / magic links**
22. Magic-link or OTP request flooding (email/SMS bombing; provider cost abuse)
23. OTP / magic-link token brute force on the callback
24. Link/OTP interception (open redirects, email forwarding) and reuse
25. Long-lived or non-single-use login tokens

**F. MFA**
26. MFA bypass routes (legacy API, remember-me, recovery flow that skips MFA)
27. Push fatigue / MFA prompt bombing
28. Recovery-code brute force
29. Post-takeover factor enrollment / MFA reset hijack
30. SMS factor SIM-swap exposure

**G. OAuth / OIDC / SSO / SAML**
31. `redirect_uri` manipulation / open redirect → code theft
32. Missing `state` (CSRF) or missing PKCE on public clients
33. Authorization-code interception or replay
34. Account-linking confusion (auto-link on unverified email; IdP mix-up)
35. SAML signature wrapping / unsigned assertion acceptance
36. Over-broad JIT provisioning or role-mapping abuse

**H. Account lifecycle & recovery**
37. Password-reset poisoning (Host-header / URL injection in reset links)
38. Reset-token brute force or predictable tokens
39. Email/phone change without re-auth + no notification to the old channel
40. Signup abuse — bots, disposable emails, mass account creation
41. Lockout abuse as targeted DoS against victim accounts

**I. API & machine-to-machine auth**
42. API key leakage (repo history, client bundle, logs)
43. Over-privileged keys; missing scopes/rotation/IP allowlisting
44. Invalid-key spray / key brute force on API endpoints
45. Unauthenticated internal/service endpoints reachable from outside

**J. Availability**
46. Login-endpoint DoS (expensive password-hash amplification)
47. Session-store / signup-flood storage exhaustion
48. Email/SMS provider quota exhaustion (cost DoS via auth flows)

**K. Transport, storage & secrets**
49. Weak or unsalted password hashing (MD5/SHA-1, low work factor)
50. Missing TLS/HSTS; cookies transmittable over HTTP
51. Auth secrets committed to the repo or baked into client bundles
52. Credentials/tokens captured in application logs and traces

**L. Post-auth privilege boundary (brief — link to a future authorization model)**
53. Privilege escalation via client-controlled token claims (role tampering)
54. IDOR on account-management endpoints (other users' sessions/profile/factors)

---

## Phase 3 — Map every modeled threat to SecureNow detection + mitigation

Classify each threat with exactly one coverage badge:

- 🟢 **COVERED** — detectable + mitigable with SecureNow today (existing rule, or a rule
  you provide the SQL for, on telemetry that is already flowing).
- 🟡 **PARTIAL** — works after the customer adds instrumentation (`track()` events or
  `guard()`), or the detection is inherently false-positive-prone (notify-only).
- 🔴 **GAP** — SecureNow cannot detect or mitigate this today. **Still include it**: give
  the app-level fix (in the code-findings report), then add the line *"Requires SecureNow
  team — contact your SecureNow account contact (or in-dashboard support) to request support
  for this threat."* Collect all gaps in the detection report's "Known gaps & SecureNow
  feature requests" section.

Code-level fixes that are the app's own responsibility (cookie flags, PKCE, hashing
parameters…) go in the mitigation column as **app fix** — they coexist with SecureNow
controls, they don't replace detection — and they are detailed in the **code-findings**
report (App / config fixes), cross-linked from the matrix row.

Use **only** the SecureNow building blocks below, and only the flags/events/columns the
**installed** SDK/CLI from Phase 0.5 actually exposes. Never invent CLI flags, event names, or
SQL columns.

### 3a. Instrumentation (what detections feed on)

```js
// Sessions: one line — emits `session.seen` and enforces revocations
const securenow = require('securenow/sessions');
app.use(securenow.guard());

// Events: fire-and-forget in your auth handlers — never throws
const { track } = require('securenow/events');
track('auth.login.failure', { userId, sessionId, ip, attributes: { reason: 'bad_password' } });
track('auth.login.success', { userId, sessionId, ip });
```

Standard event taxonomy — rules match these **exact strings** (confirm each exists in the
installed `securenow/events` from Phase 0.5):

| Event | Emit when |
|---|---|
| `auth.login.success` / `auth.login.failure` | every login attempt resolves |
| `auth.signup` | account created |
| `auth.logout` | explicit logout |
| `auth.magiclink.requested` / `auth.otp.requested` | passwordless link/code issued (hash the email into an attribute) |
| `auth.otp.failure` | wrong code submitted |
| `auth.password.reset.requested` / `auth.password.reset.completed` | recovery flow |
| `auth.mfa.challenge` / `auth.mfa.failure` / `auth.mfa.enrolled` | MFA lifecycle |
| `auth.email.changed` | contact-channel change |
| `auth.account.locked` | lockout triggered |
| `session.seen` | automatic via `guard()` |

Ingest enriches every event IP with **ASN/org** (`client.asn`, `client.as_org`), enabling
network-level detections (distributed attacks, hosting/VPN logins) with no extra code.
HTTP traffic (status codes, paths, IPs) is captured automatically once the app runs under
`securenow run` / `securenow/register` / `securenow init` — traffic-based rules need no
events at all.

### 3b. Detection rules — SQL conventions

Two query shapes. Both **must** keep the tenant scope and **must** select an `ip`
column (per-IP aggregation is what remediation/auto-block keys on). **The tenant-scope
column differs by table** — using the wrong one fails with `UNKNOWN_IDENTIFIER`:

- **logs** (`signoz_logs.distributed_logs_v2`) → `resources_string['service.name'] IN (__USER_APP_KEYS__)`
- **traces** (`signoz_traces.distributed_signoz_index_v3`) → `` `resource_string_service$$name` IN (__USER_APP_KEYS__) ``

When grouping by `ip`, add `HAVING ip != '' AND …` so rows with no client IP don't
aggregate into an empty-key bucket.

**Events-based** (auth events from `track()`/`guard()` — query the **logs** table):

```sql
SELECT
  attributes_string['http.client_ip'] AS ip,
  count() AS failures,
  uniqExact(attributes_string['enduser.id']) AS distinct_accounts
FROM signoz_logs.distributed_logs_v2
WHERE resources_string['service.name'] IN (__USER_APP_KEYS__)
  AND attributes_string['event.type'] = 'auth.login.failure'
  AND timestamp >= now() - INTERVAL 15 MINUTE
GROUP BY ip
HAVING ip != '' AND failures >= 10
```

Useful event attributes: `event.type`, `enduser.id`, `session.id`, `http.client_ip`,
`client.asn`, `client.as_org`.

**Traffic-based** (HTTP spans, no events needed):

```sql
WITH coalesce(nullIf(attributes_string['http.client_ip'], ''), nullIf(attributes_string['net.peer.ip'], ''), nullIf(attributes_string['network.peer.address'], '')) AS client_ip
SELECT client_ip AS ip, count() AS hits
FROM signoz_traces.distributed_signoz_index_v3
WHERE `resource_string_service$$name` IN (__USER_APP_KEYS__)
  AND timestamp >= now64(9) - INTERVAL 15 MINUTE
  AND ts_bucket_start >= toUInt64(toUnixTimestamp(now() - INTERVAL 15 MINUTE)) - 1800
  AND kind = 2
  AND attributes_string['http.target'] LIKE '/api/auth/%'
GROUP BY ip
HAVING hits >= 20
```

### 3c. Mitigation commands — the full SecureNow toolbox (select per threat)

Once a threat is confirmed, **choose the narrowest effective mitigation(s) from ALL of these**
and combine them (e.g. rate-limit `/api/login` + block the worst IPs + challenge a NAT egress).
Re-check every command/flag against the installed SDK in Phase 0.5 (`securenow <cmd> --help`);
annotate `# requires securenow >= <ver>` if absent. Scope by **app / env / route / method / IP /
duration** to avoid hitting real users.

| # | Mitigation | Command (ready-to-copy) | Use / scope |
|---|---|---|---|
| 1 | **Free firewall (network)** | `securenow firewall enable --app <APP_KEY> --env production` · `securenow run --firewall-only` · test `securenow firewall test-ip <ip> --path /x --method GET` | 500k+ known-bad IPs, hourly refresh; drop scanners before the app. No app change. |
| 2 | **Exploit-signature instant block** | enable the `instant` config on the system SQLi/XSS/RCE signature rules (dashboard / MCP `securenow_alert_rule_instant_update`); custom rule → create with `--execution-mode instant` | synchronous ~2.6s block of the matching request (payload injection). Don't duplicate pattern SQL. |
| 3 | **IP block — global** | `securenow blocklist add <ip> --app <APP_KEY> --env production --reason "..."` | confirmed-malicious source, all routes. |
| 4 | **IP block — scoped to route (+ method)** | `securenow blocklist add <ip> --route /admin* --mode prefix --method ALL --app <APP_KEY> --env production --reason "..."` (`--mode exact\|prefix\|regex`, `--method GET\|POST\|…\|ALL`) | block an IP only on sensitive paths (e.g. `/api/auth/*`, `/admin*`); least collateral. |
| 5 | **IP block — temporary / time-boxed** | `securenow blocklist add <ip> --duration 24h --reason "..."` (`30m`,`24h`,`7d`) · reverse `securenow blocklist unblock <id> --reason "..."` | auto-expiring containment; audit-preserving unblock. |
| 6 | **Rate limit — per IP** | `securenow ratelimit add <ip> --limit 100 --window 1m --duration 24h --reason "..."` | throttle one abusive client across the app. |
| 7 | **Rate limit — per route (all clients, per-IP budget)** | `securenow ratelimit add --route /api/auth/reset --mode prefix --method POST --limit 5 --window 1m --key-by ip` | cap an expensive/abusable endpoint (login, reset, OTP request) for everyone, budgeted per IP. |
| 8 | **Rate limit — per route + IP** | `securenow ratelimit add <ip> --route /api/login --mode exact --method POST --limit 5 --window 1m --duration 24h` · NL `securenow ratelimit from-text "rate limit /api/login to 5/min for 24h" --yes` · test `securenow ratelimit test <ip> --path /api/login --method POST` | precise throttle of one client on one route. |
| 9 | **CAPTCHA / proof-of-work challenge** | `securenow challenge add --route /login --difficulty 16 --clearance 30m` (route-wide) **or** `securenow challenge add <ip> --route /api/search --difficulty 18 --clearance 30m` · test `securenow challenge test <ip> --path /login --method GET` | bot login/signup/scraping abuse from **shared / NAT / CGNAT** egress — a human passes once, a script can't. Prefer over a hard block when real users share the IP. |
| 10 | **Auto-block (risk-scored)** | `securenow automation defaults --yes` (≥95→7d, 90–94→72h, 85–89→24h) · custom `securenow automation create --conditions '[...]' --actions '[...]'` · preview `securenow automation dry-run <id>` | hands-off blocking by risk score; actions include block / rate_limit / requireCaptcha. |
| 11 | **Session revocation** | `securenow revoke session <id> --reason "..."` / `securenow revoke user <id>` / `revoke list` / `revoke restore <id>` (SDK `securenow/sessions` `guard()` / `isRevoked()`) | session theft / account takeover — kill the stolen session, not the IP. |
| 12 | **Trusted IP (suppress)** | `securenow trusted add <ip> --label "Office VPN / partner / monitor"` | stop false positives from known-good infra — suppresses detection **and** mitigation. NOT deny-by-default. |
| 13 | **Allowlist (deny-by-default)** | `securenow allowlist add <ip> --label "..." --reason "..."` ⚠️ once any entry exists, ONLY listed IPs reach the app | lockdown of an internal/admin-only surface. Never for a public app. |
| 14 | **False-positive exclusion** | `securenow fp create --conditions '[...]' --rule-scope this_rule --reason "..."` · `securenow fp mark <notification-id> <ip> --rule-scope this_rule` · preview `securenow fp dry-run --conditions '[...]'` | keep a noisy rule quiet without weakening it. |
| 15 | **App / config / code fix (primary for root cause)** | *described in the Code-Findings report, never auto-applied* | the actual fix (cookie flags, PKCE/`state`, hashing parameters, reset-token single-use, secret rotation, retire dev backdoor). SecureNow contains; the fix removes. |

**Choosing per threat** — by **confidence**: exploit-signature/exact IoC → instant-block or
block; probable bot on shared egress → **challenge**; noisy/legit-mixed traffic (brute-force /
enumeration / flood thresholds) → **rate-limit (test-mode first)**; session compromise →
**revoke**; known-good noise → **trusted / fp**. By **blast radius**: always scope to the
narrowest `route`/`method`/`IP`/`duration` that stops the abuse; on NAT/CGNAT/shared IPs prefer
challenge/rate-limit over a hard block. Always pair an edge mitigation with the **app/config fix**
(Code-Findings report) when SecureNow can only contain the actor. (All commands are verified
against the installed SDK in Phase 0.5.)

### 3d. Testing every detection and mitigation

Only test against apps/environments the user owns; prefer `--env local`/staging. For
synthetic source IPs use TEST-NET ranges (`192.0.2.0/24`, `198.51.100.0/24`,
`203.0.113.0/24`).

```bash
# Synthetic auth events — exercise an events-based rule end to end
for i in $(seq 1 12); do
  securenow event send auth.login.failure --user victim@example.com \
    --session test-$i --ip 203.0.113.99 --attrs reason=bad_password,test=true
done

# Validate a rule query without waiting for the schedule
securenow alerts rules test <RULE_ID> --mode dry_run --wait

# Traffic-based rules — simulate, then check the pipeline
securenow test-span "threat-model.smoke"
securenow forensics "failed logins by IP in the last hour" --env production

# Mitigation verification
securenow firewall test-ip 203.0.113.99 --app <APP_KEY> --env production
securenow ratelimit test 203.0.113.99 --path /api/login --method POST
securenow revoke list

# Confirm + clean up
securenow notifications list --limit 10
securenow blocklist list   # then: securenow blocklist unblock <id> --reason "threat-model test"
```

Every 🟢/🟡 threat row in the report must have a concrete test recipe (commands + expected
outcome: which rule fires, which notification appears, what the mitigation does).

---

## Phase 4 — Build the ready-to-copy detection units

Treat `node_modules/securenow` + the `--help` output from Phase 0.5 as the source of truth for
every flag, event name, and SQL column. For **each** modeled threat that becomes a detection,
emit a **complete, copyable unit** — never a fragment. For each rule emit, in order: the SQL, a
line saving it to `rules/<name>.sql`, the full create command, the dry-run test. In Markdown
each is its own fenced block (so it copies cleanly). Example:

````markdown
**Rule: Auth — failed-login brute force (single IP)**  · 🟢 COVERED · OWASP A07 / CWE-307 · high

```sql
-- rules/auth-bruteforce-single-ip.sql
SELECT
  attributes_string['http.client_ip'] AS ip,
  count() AS failures,
  uniqExact(attributes_string['enduser.id']) AS distinct_accounts
FROM signoz_logs.distributed_logs_v2
WHERE resources_string['service.name'] IN (__USER_APP_KEYS__)
  AND attributes_string['event.type'] = 'auth.login.failure'
  AND timestamp >= now() - INTERVAL 15 MINUTE
GROUP BY ip
HAVING ip != '' AND failures >= 10
```

```bash
securenow alerts rules create \
  --name "Auth: failed-login brute force (single IP)" \
  --sql @rules/auth-bruteforce-single-ip.sql \
  --apps <APP_KEY> --severity high --schedule "*/15 * * * *" \
  --nlp "single IP with 10+ failed logins in 15 minutes"

securenow alerts rules test <RULE_ID> --mode dry_run --wait     # validate before it runs live
```
````

The exact flags must match `securenow alerts rules --help` from Phase 0.5. Save each rule's SQL
to `rules/<name>.sql` so `--sql @rules/<name>.sql` works. Keep the SQL conventions from 3b
(tenant scope + `ip` column + `HAVING ip != ''`). **Note pre-existing/system rules** discovered
in Phase 0 instead of duplicating them. Injection-class / exploit-signature threats reference the
**system signature rules + `instant.block`**, not duplicate SQL. If the installed SDK lacks a
flag this prompt references, emit the rule but annotate it `# requires securenow >= <version>`.

### Test mode for false-positive-prone rules — ship `--mode test` first

Alert rules have a lifecycle **mode**: `test` = **detect-only, NO mitigation** vs `prod` = full
(mitigation / auto-action armed) — plus a **status** (`Active | Disabled | Paused`). Manage with:

```bash
securenow alerts rules update <RULE_ID> --mode test     # detect-only: fires notifications, takes NO action
# …observe real traffic for several days; tune the threshold; add securenow fp exclusions for any FPs…
securenow alerts rules update <RULE_ID> --mode prod      # promote: arm the mitigation / auto-action
securenow alerts rules update <RULE_ID> --status Paused  # or --enable / --disable / --pause shortcuts
```

**Rule of thumb:** any detection that can **false-positive** — heuristic thresholds (brute-force /
flood / enumeration / signup counts), broad patterns, anomaly / volume / hosting-ASN-login rules,
anything tuned to YOUR traffic — must ship in **`--mode test` first**. Run it detect-only for
**3–7 days of real traffic**, review what it flags, raise/lower the threshold and add `securenow
fp` exclusions for legitimate hits, then `--mode prod` to arm mitigation. Only **high-precision**
rules (exploit-signature SQLi/XSS/RCE matches, exact-match IoCs, known-bad ASN hits) may go
straight to `prod`. **Tag every rule `test-first` or `prod-ready`** and say why. (`securenow alerts
rules test <id> --mode dry_run --wait` is the separate one-off *query* validation — run it before
either mode.)

For the **mitigation** side, use the full toolbox from 3c: every per-threat mitigation is itself
a ready-to-copy command (with `<APP_KEY>` substituted) plus its reversibility note.

---

## Phase 5 — Write the deliverables (two tracks, four files)

Write all four files into `threat/01-authentication/`. The two tracks cross-link each other:
the detection report's gap and instrumentation rows link to the relevant code finding, and each
code finding links back to the detection-report row it backs.

### 5a. Detection & Mitigation report — `authentication-detection-mitigation.{md,html}`

The **operational runbook**: what to run in SecureNow. Sections, in order (same in .md and
.html):

1. **Executive summary** — stats line (threats modeled · covered · partial · gaps · rules to
   create · mitigations), top 3 detectable risks for this stack, installed `securenow` version +
   app key + firewall state.
2. **SDK & environment** — installed SDK version (from `node_modules/securenow`), app key(s),
   environment, firewall state, existing rules/automations/challenge rules (from Phase 0),
   system signature rules present.
3. **Threat → Detection → Mitigation matrix** — one row per modeled threat:
   `# | Threat | OWASP/CWE | Coverage 🟢/🟡/🔴 | Detection rule | Signal (threshold+window) | Schedule | Sev | Mode | Mitigation`.
   Each row's **Mitigation** cell must pick **specific, scoped mitigation(s) from the §3c
   toolbox** (named layer + scope: route/method/IP/duration) — never a generic "block the IP."
   The **Mode** cell tags each rule `test-first` or `prod-ready` per the §3c test-mode rule of
   thumb. Then the "Out of scope" N/A list and the deferred-to-sibling rows. Severity ∈ {critical,
   high, medium, low}.
4. **Detection rules to create** — each as the ready-to-copy unit from Phase 4 (SQL → save →
   create → dry-run). **Mark each rule `test-first` or `prod-ready`**; for every `test-first`
   rule include the `--mode test` → observe (3–7 days) → `--mode prod` promotion step. Injection-
   class rows reference the **system signature rules + `instant.block`**, not duplicate SQL. Note
   rules that already exist from Phase 0.
5. **Instrumentation the detections need** — only the `track('…')` events the rules above
   consume, each as a copyable snippet; point to the code-findings report for *where* to add
   them.
6. **Mitigation mechanisms** — render the **full §3c toolbox table** (1 Free firewall · 2 Exploit-
   signature instant block · 3–5 IP block [global / route+method / temporary] · 6–8 rate-limit
   [IP / route / IP+route] · 9 challenge · 10 auto-block · 11 session revocation · 12 trusted ·
   13 allowlist · 14 fp exclusion · 15 app/config fix) + the "Choosing per threat" paragraph +
   per-threat ready-to-copy mitigation command (scoped, `<APP_KEY>` substituted) with its
   reversibility note.
7. **Action plan (copy-paste, ordered)** — ① firewall + signature instant-block, ② add
   instrumentation, ③ create rules — **FP-prone rules created in `--mode test`**, ④ enable
   automations/challenge, ⑤ test, ⑥ verify, ⑦ **promote each `test-first` rule to `--mode prod`
   after N days (3–7) of clean traffic**, ⑧ schedule the app/config fixes (from the code report).
   Real commands, `<APP_KEY>` substituted.
8. **Testing & validation** — per-rule recipe: `securenow event send …` / `test-span` / dry-run
   + expected outcome + cleanup (TEST-NET IPs 192.0.2/198.51.100/203.0.113).
9. **Response runbooks** — per notification type: confirm TP → respond command (copy) → reverse
   command (copy).
10. **Known gaps & SecureNow feature requests** — each 🔴: why not coverable, interim fix (link
    to code report), and the "contact the SecureNow team" line.
11. **Appendix** — resolved SDK/CLI version, app key, environment, rule IDs created, date.

### 5b. Code Findings & Recommendations report — `authentication-code-findings.{md,html}`

State at top: *"Findings only — no application code was modified."* Sections, in order (same in
.md and .html):

1. **Executive summary** — findings by severity (critical/high/med/low), top 3 code risks,
   one-paragraph posture verdict.
2. **Surface & inventory** — the Phase 1 inventory for authentication (mechanisms / endpoints /
   session model / storage / MFA / recovery / existing limits / sensitive paths).
3. **Threat catalog** — the exhaustive Phase 2 catalog A1–L54 (grouped, each tagged OWASP/CWE,
   modeled or explicit N/A).
4. **Code-level findings (audit)** — table
   `# | Location (file:line) | Threat | OWASP/CWE | Sev | Issue | Recommended fix`, each with the
   quoted 1–8 line snippet and the described fix (never applied).
5. **Strengths** — controls already present and correct (honest posture).
6. **App / config fixes (primary remediation)** — the config/code changes that remove the root
   cause (described, not applied): cookie flags, PKCE/`state`, hashing parameters, reset-token
   single-use, secret rotation, etc. Each linked to the detection-report matrix row it backs.
7. **Instrumentation recommendations** — the `track('…')` calls to add and the exact file:line
   to add them (from Phase 1), so the detection rules light up.
8. **Appendix** — files reviewed, resolved SDK version, date, link to the detection-mitigation
   report.

### 5c. HTML skeletons — two self-contained files (offline; inline CSS + copy JS; no network)

Both HTML files share the `<head>` below (brand tokens + copy-button styles) and the copy
`<script>` at the end of `<body>`. Change only the `<title>`, the sidebar subtitle, and the
section content. Wrap **EVERY** command/SQL block as a `.cmd` (so it gets a Copy button).

**Shared `<head>` + `<body>` shell + copy `<script>`** (identical for both files):

```html
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title><!-- "Detection & Mitigation — Authentication — SecureNow" OR "Code Findings — Authentication — SecureNow" --></title>
<style>
  :root{--bg:#0f1419;--panel:#161c24;--panel2:#1b2330;--border:#26303d;--txt:#dbe3ec;--muted:#8b97a7;
    --accent:#3ea6ff;--accent2:#16c79a;--crit:#ff5c6c;--high:#ff9f43;--med:#f7c948;--low:#8b97a7;
    --ok:#16c79a;--info:#3ea6ff;--rev:#b388ff;}
  *{box-sizing:border-box}html{scroll-behavior:smooth}
  body{margin:0;background:var(--bg);color:var(--txt);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
  a{color:var(--accent);text-decoration:none}
  code{background:#0b0f14;border:1px solid var(--border);border-radius:5px;padding:.08em .4em;font:13px/1.4 ui-monospace,"SF Mono",Menlo,Consolas,monospace;color:#9fe0c0}
  .wrap{display:grid;grid-template-columns:240px 1fr;max-width:1280px;margin:0 auto}
  nav{position:sticky;top:0;align-self:start;height:100vh;overflow:auto;padding:28px 18px;border-right:1px solid var(--border);background:var(--panel)}
  nav .brand{font-weight:700;font-size:15px;letter-spacing:.3px}nav .brand span{color:var(--accent)}
  nav .sub{color:var(--muted);font-size:12px;margin-bottom:22px}
  nav a{display:block;color:var(--muted);padding:7px 10px;border-radius:7px;font-size:13.5px}
  nav a:hover{background:var(--panel2);color:var(--txt)}
  main{padding:36px 40px 80px;min-width:0}
  header.top h1{margin:0 0 6px;font-size:26px}header.top p{margin:0;color:var(--muted)}
  .pill{display:inline-block;font-size:11px;font-weight:600;padding:3px 9px;border-radius:999px;border:1px solid var(--border);color:var(--muted);background:var(--panel)}
  .stats{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin:26px 0 34px}
  .stat{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:16px 18px}
  .stat .n{font-size:26px;font-weight:700}.stat .l{color:var(--muted);font-size:12.5px;margin-top:2px}
  section{margin:0 0 40px}
  h2{font-size:18px;margin:0 0 14px;padding-bottom:8px;border-bottom:1px solid var(--border)}
  h2 .num{color:var(--accent);font-weight:700;margin-right:8px}
  table{width:100%;border-collapse:collapse;font-size:13.5px;background:var(--panel);border:1px solid var(--border);border-radius:12px;overflow:hidden}
  th,td{text-align:left;padding:11px 13px;border-bottom:1px solid var(--border);vertical-align:top}
  th{background:var(--panel2);color:var(--muted);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.4px}
  tr:last-child td{border-bottom:none}tr:hover td{background:#19212c}
  .rid{font:12px ui-monospace,Menlo,Consolas,monospace;color:#7fd1ff;white-space:nowrap}
  .b{display:inline-block;font-size:11px;font-weight:700;padding:2px 8px;border-radius:6px;white-space:nowrap}
  .b.crit{background:rgba(255,92,108,.15);color:var(--crit);border:1px solid rgba(255,92,108,.35)}
  .b.high{background:rgba(255,159,67,.13);color:var(--high);border:1px solid rgba(255,159,67,.32)}
  .b.med{background:rgba(247,201,72,.13);color:var(--med);border:1px solid rgba(247,201,72,.32)}
  .b.low{background:rgba(139,151,167,.13);color:var(--low);border:1px solid rgba(139,151,167,.32)}
  .c{display:inline-block;font-size:11px;font-weight:700;padding:2px 8px;border-radius:6px;white-space:nowrap}
  .c.cov{background:rgba(22,199,154,.13);color:var(--ok);border:1px solid rgba(22,199,154,.35)}
  .c.part{background:rgba(247,201,72,.13);color:var(--med);border:1px solid rgba(247,201,72,.32)}
  .c.gap{background:rgba(255,92,108,.15);color:var(--crit);border:1px solid rgba(255,92,108,.35)}
  .owasp,.cwe{display:inline-block;font:11px ui-monospace,Menlo,Consolas,monospace;color:var(--accent);border:1px solid rgba(62,166,255,.3);border-radius:6px;padding:1px 6px;white-space:nowrap}
  .cwe{color:var(--rev);border-color:rgba(179,136,255,.3)}
  .m{display:inline-block;font-size:11px;font-weight:600;padding:2px 8px;border-radius:6px;border:1px solid var(--border)}
  .m.block{color:var(--crit);border-color:rgba(255,92,108,.35)}.m.rate{color:var(--info);border-color:rgba(62,166,255,.35)}
  .m.challenge{color:var(--accent2);border-color:rgba(22,199,154,.35)}.m.firewall{color:var(--ok);border-color:rgba(22,199,154,.35)}
  .m.signature{color:var(--crit);border-color:rgba(255,92,108,.35)}.m.notify{color:var(--muted)}.m.appfix{color:var(--high);border-color:rgba(255,159,67,.35)}
  .card{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:18px 20px}
  .grid2{display:grid;grid-template-columns:1fr 1fr;gap:16px}
  pre{background:#0b0f14;border:1px solid var(--border);border-radius:10px;padding:14px 16px;overflow:auto;font:13px ui-monospace,Menlo,Consolas,monospace;color:#cfe8da;margin:0}
  .cmd{position:relative;margin:10px 0}
  .copy{position:absolute;top:8px;right:8px;font:11px ui-monospace,Menlo,Consolas,monospace;color:var(--muted);background:var(--panel2);border:1px solid var(--border);border-radius:6px;padding:3px 9px;cursor:pointer}
  .copy:hover{color:var(--txt);border-color:var(--accent)}.copy.done{color:var(--ok);border-color:var(--ok)}
  .flow{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:6px 0 14px}
  .flow .step{background:var(--panel2);border:1px solid var(--border);border-radius:9px;padding:8px 12px;font-size:13px}.flow .arr{color:var(--accent);font-weight:700}
  .note{border-left:3px solid var(--high);background:rgba(255,159,67,.06);padding:10px 14px;border-radius:0 8px 8px 0;color:#e7d3bd;font-size:13.5px;margin:10px 0}
  footer{color:var(--muted);font-size:12px;border-top:1px solid var(--border);padding-top:18px;margin-top:30px}
  @media(max-width:880px){.wrap{grid-template-columns:1fr}nav{display:none}.stats,.grid2{grid-template-columns:1fr 1fr}main{padding:24px 18px}}
</style></head>
<body>
<div class="wrap">
  <nav>
    <div class="brand">Secure<span>Now</span></div>
    <div class="sub"><!-- "Detection & Mitigation · Authentication" OR "Code Findings · Authentication" --></div>
    <!-- one <a href="#…"> per section -->
  </nav>
  <main>
    <header class="top"><h1><!-- report title --></h1>
      <p><code><!-- app name / domain --></code> · <span class="pill">securenow <!-- installed version --></span></p></header>
    <div class="stats"><!-- 5 .stat cards; numbers MUST equal the table/finding counts --></div>
    <!-- <section id="…"> blocks mirroring the Markdown sections of THIS track (5a or 5b) -->
    <footer>Generated by the SecureNow authentication threat-model prompt · <!-- date --> · securenow <!-- version --> · app <code><!-- APP_KEY --></code></footer>
  </main>
</div>
<script>
document.querySelectorAll('.copy').forEach(function(b){b.addEventListener('click',function(){
  var pre=b.parentElement.querySelector('pre'); if(!pre)return; var t=pre.innerText;
  function done(){b.textContent='Copied';b.classList.add('done');setTimeout(function(){b.textContent='Copy';b.classList.remove('done');},1500);}
  function fb(){var ta=document.createElement('textarea');ta.value=t;ta.style.position='fixed';ta.style.opacity='0';document.body.appendChild(ta);ta.focus();ta.select();try{document.execCommand('copy');}catch(e){}document.body.removeChild(ta);done();}
  if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(t).then(done,fb);}else{fb();}
});});
</script>
</body></html>
```

**File 2 — `authentication-detection-mitigation.html`** uses the shell above with:
- `<title>`: `Detection & Mitigation — Authentication — SecureNow`
- sidebar subtitle: `Detection & Mitigation · Authentication`
- `<h1>`: `Authentication — Detection & Mitigation`
- the 11 sections of **5a**, with **every** SQL/command block wrapped in the copyable `.cmd`
  pattern below.
- 5 stat cards: threats modeled · covered · partial · gaps · rules to create (numbers MUST
  equal the matrix counts).

**File 4 — `authentication-code-findings.html`** uses the same shell with:
- `<title>`: `Code Findings — Authentication — SecureNow`
- sidebar subtitle: `Code Findings · Authentication`
- `<h1>`: `Authentication — Code Findings & Recommendations`
- the 8 sections of **5b**; prose may omit copy buttons, but any example/fix command is still
  wrapped in `.cmd`.
- 5 stat cards: total findings · critical · high · medium · low (numbers MUST equal the
  findings-table counts).

Every SQL/command block in the **Detection & Mitigation** HTML uses the copyable wrapper:

```html
<div class="cmd"><button class="copy" type="button">Copy</button><pre>securenow alerts rules create \
  --name "..." --sql @rules/&lt;name&gt;.sql --apps &lt;APP_KEY&gt; --severity high \
  --schedule "*/5 * * * *" --nlp "..."</pre></div>
```

Badge usage: severity `<span class="b crit|high|med|low">`; coverage
`<span class="c cov|part|gap">COVERED|PARTIAL|GAP</span>`; OWASP `<span class="owasp">A07</span>`;
CWE `<span class="cwe">CWE-307</span>`; mitigation
`<span class="m firewall|signature|rate|challenge|block|notify|appfix">`; rule IDs
`<span class="rid">`. Stats numbers must equal the matrix/findings row counts. The Code-Findings
HTML may omit copy buttons on prose, but still wraps any example/fix command in `.cmd`.

---

## Quality bar (the report is rejected if any of these fail)

- Every catalog item A1–L54 is either a matrix row (detection report) / catalog entry (code
  report) or an explicit N/A line — never silently dropped.
- Every matrix row has a concrete signal (threshold + window), severity, and mitigation —
  no "monitor for suspicious activity" filler.
- Every detection SQL keeps `__USER_APP_KEYS__` scoping (correct column per table) and selects
  an `ip` column with `HAVING ip != ''`.
- **Phase 0.5 ran**: the resolved installed `securenow` version appears in BOTH reports'
  appendix, and no command/flag/event/column is emitted that the installed SDK/CLI does not
  expose (else it is annotated `# requires securenow >= <version>`).
- Every detection rule is a **complete copyable unit** (SQL → `rules/<name>.sql` → full
  `securenow alerts rules create …` → dry-run test); flags match `alerts rules --help`.
- Every 🔴 gap appears in the detection report's "Known gaps" section with an interim app fix
  (linked to the code report) **and** the "contact the SecureNow team" line.
- The action plan runs top-to-bottom with `<APP_KEY>` substituted in.
- **Four** files are written to `threat/01-authentication/` (detection-mitigation .md+.html,
  code-findings .md+.html); the two tracks cross-link; both HTML files are self-contained
  (inline CSS/JS, no CDN/fonts/network) and **every command block in the detection HTML has a
  working Copy button**; the stats cards in each HTML match its table/finding counts.
- The split is honest: SecureNow-runnable detections/mitigations live in the Detection report;
  code/config changes live in the Code-Findings report; nothing security-relevant is dropped.
- The Detection report's mitigation section presents the **full toolbox** (§3c: firewall ·
  instant-block · block [global / route / method / temporary] · rate-limit [IP / route / IP+route]
  · challenge · auto-block · revoke · trusted · allowlist · fp · app-fix), and **each modeled
  threat's matrix row selects specific, scoped mitigation(s) from it** — never a generic "block
  the IP."
- **Every false-positive-prone rule is tagged `test-first`** and carries the `--mode test` →
  observe (3–7 days) → `--mode prod` promotion workflow; only high-precision rules are
  `prod-ready`. The action plan creates the test-first rules in `--mode test` and has an explicit
  "promote after N days" step.
- A one-line summary is printed back: per-track file paths, threat counts, rules-to-create
  count, code findings by severity, gaps, resolved SDK version.

<!-- ════════════════ END OF PROMPT ════════════════ -->
