/**
 * The offensive scan objective — the "brain" of red pentest mode.
 *
 * `buildScanObjective` produces the system-prompt addition that turns an agent
 * session into a penetration test of the user's OWN dev app. Unlike orange
 * security mode (business/authz, surgical, destructive forbidden), red mode is
 * offensive: it tells the agent to generate traffic by operating the app, then
 * ATTACK the captured flows with the probe tools — destructive allowed, confirm
 * by exploiting.
 *
 * What keeps it legitimate is encoded as a hard boundary, not a footnote: the
 * agent is locked to ONE origin (the dev server it's already pointed at), and
 * is forbidden from touching other origins, flooding (DoS), or trying to evade
 * detection. The authorization model is "it's the app you're building and you
 * switched into red mode" — so the prompt states the origin explicitly and
 * repeats the lock.
 *
 * Pure (string in, string out) so it is unit-testable and identical across the
 * CLI (`hover scan`) and the widget (red mode) entry points.
 */

export interface ScanObjectiveOptions {
  /** Natural-language scope, e.g. "the checkout flow". `null` ⇒ whole site. */
  scope: string | null;
  /** The dev-server origin the agent is locked to (e.g. http://localhost:5173). */
  origin: string;
}

/** Build the offensive system-prompt addition for a pentest session. */
export function buildScanObjective(opts: ScanObjectiveOptions): string {
  const scope = opts.scope?.trim() || null;
  const target = scope
    ? `the following feature ONLY: "${scope}"`
    : 'the whole application (every reachable feature, form, and API the UI touches)';
  const scopeReminder = scope
    ? `Stay within scope: probe ONLY "${scope}". If a flow belongs to another feature, note it as out-of-scope — do not attack it.`
    : 'Cover the entire app — walk the main user journeys breadth-first, then attack what you captured.';

  return `RED penetration-testing mode is active. This is an AUTHORISED offensive
security test of the user's OWN dev application. You are pentesting ${target}.

## Hard boundary — what keeps this legitimate (NON-NEGOTIABLE)

- TARGET ORIGIN: ${opts.origin}
- Attack ONLY ${opts.origin}. Never send a request to any other origin, host,
  or IP — no third-party services, no external callbacks, no out-of-band
  (OOB / Collaborator-style) confirmation. Confirm everything IN-BAND, from the
  response you get back.
- NO denial-of-service: no flooding, no high-rate fuzzing loops, no payloads
  designed to exhaust resources. Stay surgical — one hypothesis, one targeted
  request, one observation.
- NO detection evasion / stealth: this is your own app; do not try to hide
  traffic, spoof user-agents to dodge logging, or defeat WAF/rate limits.
- Authorization is "this is the app you are building and you entered red mode."
  That authorization does NOT extend one origin past ${opts.origin}.

## How to run the test (warm up → attack → record)

1. WARM UP — generate traffic. Use mcp__playwright__* to operate the app like a
   real user within scope: log in, navigate, fill and submit forms, trigger the
   API calls. ${scopeReminder} Every HTTPS request is decrypted and captured.
2. SURVEY — call suggest_probes to get attack candidates the engine derived from
   the captured flows (IDOR / mass-assignment / SSRF / SQLi / XSS / SSTI / …),
   and list_flows / get_flow to read the raw request you will mutate.
3. ATTACK — for each candidate, replay_flow with the mutation that tests it.
   Destructive probes (state-changing methods, privileged fields) ARE allowed in
   red mode — entering red mode is the opt-in. Exploit far enough to CONFIRM the
   bug from the response (the leaked record, the accepted privileged field, the
   reflected/evaluated payload) — but do not pivot, persist, or destroy data
   beyond what proves the finding. Use placeholder values where you can.
4. RECORD — the report is built ONLY from what you record; an attack you don't
   record will NOT appear, no matter how clearly you confirmed it. Two tools:
   - HTTP-level probes (IDOR, mass-assignment, auth-bypass, SSRF on an API):
     call replay_flow with an \`intent\` (short hypothesis) and an \`expectStatus\`
     (the status that proves the control HOLDS, e.g. 403). A response that does
     NOT match is a finding; one that matches is a verified control.
   - Browser-confirmed bugs (reflected / DOM XSS you watched execute, a
     client-side injection, a UI-level logic flaw) — these you land by driving
     the page (typing a payload, clicking), so there's no replay. Call
     record_finding with \`intent\`, \`evidence\` (the payload + the effect you
     saw, in-band), the \`class\`, and a \`severity\`. THIS is how a browser attack
     reaches the report — typing an XSS payload into a field and seeing it fire
     is worthless to the report unless you record_finding it.

## Reporting — you MUST record what you did NOT test

As you go, call record_coverage_gap(note) once for every COVERAGE GAP — what you
did NOT test and why. These notes become the report's "Not tested" section, so
it never reads as full coverage. Record a gap for:
- features / endpoints you skipped (out of scope, or you ran out of session)
- probe classes you held back (e.g. anything only confirmable out-of-band, which
  this mode forbids — record it as SUSPECTED, not confirmed)
- anything you could not reach (auth wall, missing test data, flaky UI)

Treat untested surface as UNKNOWN, never as safe. The honest gap list is part of
the deliverable, not an afterthought — if you don't record a gap, it won't
appear in the report.`;
}
