Skip to content

[POC][PND] AlertZero × recommended actions: two AD workers + per-action containment approval - #288196

Draft
opauloh wants to merge 34 commits into
elastic:mainfrom
opauloh:alertzero-recommended-actions
Draft

[POC][PND] AlertZero × recommended actions: two AD workers + per-action containment approval#288196
opauloh wants to merge 34 commits into
elastic:mainfrom
opauloh:alertzero-recommended-actions

Conversation

@opauloh

@opauloh opauloh commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Merges the AD recommended-actions HITL POC (#287158) into the AlertZero runnable POC (#287301), and implements the two-worker Attack Discovery split from elastic/security-team#18972 on top.

Relates to elastic/security-team#18972, #287158, #287301.

Two AD workers

  • New Attack Discovery Generation catalog watch (system-security-watch-attack-discovery-generation): per-space, scheduled trigger (concurrency: drop, max: 1), single security.attack-discovery.run step. Cadence (5m/15m/30m/hourly), alerts-per-run, lookback and connector are managed template values, editable from the watch's settings page in Watch Floor; a settings write re-asserts enablement so Task Manager reprograms the schedule.
  • Each net-new persisted discovery emits security.attackDiscoveryCreated and wakes one Watch Floor run per discovery. Keeping generation in its own workflow means a parked HITL gate can never stall or drop a generation tick, and the engine's avoid-loop guard passes.

Watch Floor Phase 3: recommended actions replace the containment stub (floor v25)

  • The per-discovery flow is unchanged through phases 1–2: "Open an investigation?" gate → Deep Watch true/false-positive verdict → "Escalate to an incident?" gate → incident conversation.
  • Phase 3 now stages actions via the recommended-actions Agent Builder skill (structured output, bounded), and the always-human incident_contained gate carries a per-action approval (approved_actions; per Nir's per-action-veto feedback). The queue card renders one toggle per Kibana-executable action (manual actions read-only; toggles default off; dismiss disables and empties).
  • Approved actions execute post-gate, as the approving analyst: create case (+ alert attachments, host/IP observables via the internal cases API), Entity Store EUID asset criticality, isolate host, kill process, persistence hunt — and analyze_exfiltration_ips runs as a strictly read-only ai.agent hunt whose findings post to the incident conversation.
  • Every staged action ends in a per-action ledger row (succeeded / submitted / failed / skipped / not_executed + reason), projected through GET /internal/pnd/executions/{correlationId} into a new Containment actions section and per-step badges in the four-phase lifecycle flyout. incident_closed and the phase-4 post-incident tuning lane are untouched.

Contracts & hardening

  • Staged actions ride the untruncated reasoning sections and a new bounded PndProposalRow.stagedActions field (the 8192-char summary bound truncated a real run's array mid-string; the summary label anchor stays as a fallback for already-parked rows).
  • _respond accepts and forwards approved_actions; gate registry label → "Review containment actions"; phase catalog gains Recommend containment actions / Execute approved actions rows (16-row skeleton).
  • open_incident continues on failure (the incident agent intermittently returns an empty structured response; a human-approved escalation must still reach the containment gate — same rationale as draft_tuning).
  • HITL approval card is height-capped and scrollable (pinned header/footer), and the machine-readable block is stripped from displayed reasoning where the toggle form renders it.
  • Carried from [POC][PND] Attack Discovery Worker recommended actions HITL #287158: the recommended-actions skill (+recommendedActionsSkill flag), @kbn/pnd-common action contracts, discoveries run-step sync-await, _schedule route (adapted to the per-space install model), workflow_crud_service includeGlobal fix.

Verified end to end

On a live stack (EIS connectors, real + synthetic alerts): scheduled generation → per-discovery floor runs → both HITL prompts → per-action containment approval → real case created, real Entity Store criticality write, endpoint actions honestly skipped (no agents), unapproved action ledgered not approved by analyst, read-only exfil hunt posting findings to the incident thread → incident_closed → post-incident tuning drafted, backtested and parked at its gate. Schedule reprogramming, concurrency drop, and settings persistence exercised live.

~6,300 tests green across the touched suites (managed workflows, kbn-pnd-common, pnd server/public, security_solution skills, discoveries); scoped type checks green. PND README, diagram and discoveries README updated.

Screenshot

ad-poc-recommended-actions-compressed.mp4

WIP / POC

Draft on the fork for review of the merged direction. Known follow-ups: AD dedup is fuzzy across LLM-reworded duplicates of the same attack (queue fills up on recurring scheduled runs); the threads _ensure title still says "Decision on confirming this incident is contained".

e40pud and others added 30 commits August 20, 2026 13:55
…ice)

Add a thin end-to-end Attack Discovery worker driven by the Watch Floor orchestrator on a schedule.

- New worker system-security-watch-attack-discovery: one security.attack-discovery.run step (retrieve -> generate -> validate -> persist to the shared ad-hoc AD index) -> ai.agent investigation conversation -> workflow.output; concurrency drop/max 1.
- watch_floor.yaml: add scheduled trigger (every 15m); route steps by execution.triggeredBy (alert -> triage, scheduled -> AD worker); pass AD inputs from consts.watch_policy.config.
- Register the worker and bump PND_WATCH_FLOOR_WORKFLOW version 4 -> 5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Managed static install writes the workflow document but never wires Task Manager, so Watch Floor's scheduled trigger never ran. Add a route-driven ensure-schedule that re-asserts enabled=true through the Workflows management API for the caller's space, which reaches syncSchedulerAfterSave and programs the task.

- New POST /internal/pnd/watches/{watchId}/_schedule -> WatchesService.ensureSchedule().
- Add PND_WATCH_SCHEDULE_URL_TEMPLATE / buildWatchScheduleUrl to kbn-pnd-common.
- Cover ensureSchedule (scheduled / not-found / unavailable) in watches_service.test.ts.
- Single-space: the task id workflow:<id>:scheduled is not space-scoped, so one global doc schedules one space; multi-space (per-space docs) is a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…dence

getEsWorkflowForScheduler re-read the workflow with an exact-spaceId filter, so it never matched a global (spaceId '*') managed workflow like the PND watches. syncSchedulerAfterSave then bailed ('not found after save') and no Task Manager task was created, even though updateWorkflow succeeded. Pass includeGlobal so the scheduler resolves global docs and programs their scheduled triggers.

- workflow_crud_service.getEsWorkflowForScheduler: buildWorkflowFilters space includeGlobal: true.
- watch_floor.yaml: scheduled trigger every 15m -> 1m; PND_WATCH_FLOOR_WORKFLOW version 5 -> 6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Revert the 1m test cadence to 15m; PND_WATCH_FLOOR_WORKFLOW version 6 -> 7 so versionStrategy:auto reinstalls. Takes effect after a Kibana restart + re-run of the _schedule endpoint (bulkUpdateSchedules updates the task interval).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… the AD worker

The run step returns { execution_uuid, status: 'pending' } once generation exceeds its 90s soft deadline, so the AD worker never saw the discoveries inline. Add an event-log-backed get_status step (reusing getWorkflowExecutionsTracking + extractPipelineValidationData) that resolves discoveries by execution_uuid, and rewire the worker to run async then while-poll get_status until terminal before writing the investigation.

- New step security.attack-discovery.get_status: common schema, server handler (+ unit test), public definition; registered in both server and public registries.
- watch_attack_discovery.yaml: run (mode: async) -> while-poll get_status (15s x40) -> final_status -> write_investigation -> output; worker version 1 -> 2.
- register_workflow_steps.test.ts updated for the 6th step.
- NOTE: the platform-wide Scout step_definitions_approval snapshot must be regenerated on a stack to include the new step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…_ stutter)

The step was named get_status, so the get<Name>StepDefinition factory produced getGetStatusStepDefinition / get_get_status_step_definition.ts. Rename the step to 'security.attack-discovery.status' so every symbol reads naturally (StatusStep*, getStatusStepDefinition) with a single get. The Agent Builder get_status tool is a separate registry and keeps its id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a PND-owned flyout that renders the AD Worker config controls (alert retrieval, generation, validation) mirroring the Security Solution schedule form, without depending on triggersActionsUi or the Assistant context. The connector dropdown is the one real reuse: the shared @kbn/inference-connectors useLoadConnectors hook (http-only). Config is local state only (no persistence) and its shape equals the security.attack-discovery.run step inputs, shown in a live JSON preview.

- New public/components/ad_worker_config/* module + OpenAdWorkerConfigButton hosted on the Settings page.
- Only new dependency: @kbn/inference-connectors (platform/shared) in tsconfig kbn_references.
- RTL test covers render, section presence, connector loading (featureId attack_discovery), ES|QL toggle, live preview, connector listing, and close.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tabs (Option A spike)

Feasibility spike for Option A (reuse the AD flyout's workflow_settings_view components). Vendors the self-contained security_solution controls into PND to prove they render outside that plugin and to surface the remaining blockers.

- Vendored (copied) StepAccordion, PipelineIndicator, QueryModeSelector — EUI/Emotion-only, drop in unchanged; provenance noted in each file.
- Recomposed the flyout as a numbered steps timeline (Alert retrieval -> Generation -> Validation) with the ES|QL <-> Query-builder mode toggle; Max alerts / time range / filter now live under the Query-builder tab; ES|QL editor under the ES|QL tab.
- Real workflow lists via http (GET /api/workflows): Alert-retrieval workflows multi-select + Validation workflow list. Added 'Run every' (maps to the orchestrator schedule).
- BLOCKERS deferred (documented in tooltip/report): connector '+ Add model' needs the elastic-assistant selector (triggersActionsUi + AssistantProvider); the KQL Query-builder needs data/data-view-manager. Production = shared @kbn/attack-discovery-workflow-config package (this vendors instead of extracting).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reverted the shared-package extraction spike (kept the components rebuilt inside PND) and refined per review: Alert retrieval is now ES|QL-only with a pre-populated ES|QL query, behind the mode switch buttons + an information icon (Query-builder mode shows a placeholder). Vendored steps timeline (StepAccordion/PipelineIndicator), Generation > Run every, and the Validation workflow list (built-in + validation workflows) are retained.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Use the valid EUI 'info' icon (questionInCircle no longer exists) for all info tooltips.
- 'Alert retrieval method' and 'Alert retrieval workflows' are now EuiSwitch toggles (enable/disable) with info icons, matching the AD flyout; the retrieval-workflows selector is revealed when its switch is on.
- Alert retrieval stays ES|QL-only with a pre-populated query (behind the mode switch buttons).
- Connector dropdown now includes a '+ Add model' option that navigates to the connectors management page (no triggersActionsUi / AssistantProvider needed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ed fields from output

- Rename the retrieval switch to 'ES|QL query' and drop the ES|QL/Query-builder mode tab; the switch just shows the ES|QL query field.
- ES|QL field now uses the Monaco CodeEditor (@kbn/code-editor + @kbn/monaco ESQL_LANG_ID) for syntax highlighting instead of a plain textarea.
- Add toWorkerInputs(): when the ES|QL switch is off, alert_retrieval_mode and esql_query are omitted from the resulting worker-inputs object (shown in the preview).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Watch AD worker uses security.attack-discovery.run in sync mode (default)
  with a step timeout; removes the async run + while-poll machinery and
  consumes the run output inline.
- Draft one investigation per discovered attack (foreach); create a single
  tracking investigation when a run completes with no attacks.
- Remove the security.attack-discovery.status step type (no longer needed):
  server/public registrations, barrels, definition + tests.
- Update AD worker flow diagram (png + mmd) to the simplified sync flow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ine)

The run step's sync mode raced a hard-coded 90s soft deadline and returned
{ execution_uuid, status: pending } for slow generations, so workflow callers
(e.g. the Watch Floor AD worker) never received discoveries and downstream
steps were skipped.

The 90s soft deadline exists to keep the Agent Builder run *tool* under its
120s wrapper ceiling; the AB tool is a separate implementation that applies
its own soft deadline and does not use this step. Sync mode in the run step
now awaits the pipeline to completion, bounded by the step's own timeout, and
returns discoveries inline. Async mode is unchanged.

Updates run-step tests and README timing table / ADR-012 accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The legacy `name`/`type` array output format constrains array items to
string/number/boolean, so the `recommended_actions` array of objects was
rejected at `emit_result` with "Output validation failed: recommended_actions:
Invalid input". Declare `outputs` in JSON Schema object format so the array can
hold objects, and bump the managed workflow version 5 -> 6.
Resolve two additive conflicts against main:
- managed workflow registry: keep both PND_WATCH_ATTACK_DISCOVERY_WORKFLOW and
  the new THREAT_INTEL_* workflows.
- security skills test: keep both recommendedActionsSkill and the siem_migration
  skills in imports and ALL_SKILLS.
Introduce the capability for the Watch Attack Discovery workflow to execute recommended Kibana API actions.

This change adds:
- A global `execute_actions` kill-switch, disabled by default.
- A `waitForInput` step for analysts to review and approve/disapprove individual actions.
- Logic to call Kibana APIs for creating cases, setting asset criticality, isolating hosts, killing processes, and hunting process persistence for approved actions.
- Robust logging of execution results (success, failure, skipped) for each attempt.
- Updates to the AI skill to guide the model on when and how to include `execution_params` for executable actions based on concrete evidence.
feat(pnd): Enhance AD worker robustness and action lifecycle tracking

Harden the AI `recommend_actions` step for robustness against failures and
tool hallucination, safeguarding downstream logic. Enhance case integration
by attaching source alerts and host/IP observables. Migrate asset criticality
updates to use Entity Store v2. Provide comprehensive accounting of all
recommended actions, including reasons for non-execution.
```
…sion of AlertZero, populated by Attack discovery 2.0.

![alertzero_home](https://github.com/user-attachments/assets/560d8bbb-3ed4-4dc3-b747-7c7a77fb14dc)

_Above: The AlertZero home page populated by running Attack discovery_

This POC also prototypes:

- Workflows use `waitForInput`, not branching logic, to _always_ pause for Human In the Loop (HITL) input
- An auto-approver that runs at higher levels of autonomy
- An additional flyout to show potential _future_ actions and link to previous worklfow executions

The screenshot below illustrates the first few workflow steps that run when Attack discoveries are generated:

![first_steps](https://github.com/user-attachments/assets/0d6f8feb-3896-494c-9ce3-d7281b2863b1)

_Above: The first workflow steps when Attack discoveries are generated_

When Attack discoveries are generated:

- A new `security.attackDiscoveryCreated` workflow trigger is invoked for each discovery
- Conversation IDs are derived for each discovery (to prevent duplicate conversations)
- An _investigation_ agent builder conversation is created via `/api/agent_builder/conversations` for each discovery
- A `type: 'text'` attachment for the attack discovery is added to the conversation
- Another agent builder conversation, the sub-conversation, is created for the `Open an investigation` HITL approval
- A `waitForInput` workflow step, which is paired with a sub-conversation, appears on the AlertZero page

![propsoals_to_open_an_investigation](https://github.com/user-attachments/assets/9c855602-4847-444c-8e2a-60302798d97e)

_Above: Each `waitForInput` HITL step is paired with a sub-conversation_

At the `manual` autonomy level, a human must approve the investigation with human in the loop (HITL) input, as illustrated by the following screenshot:

![open_investigaton_hitl](https://github.com/user-attachments/assets/ec2facc5-531b-4a07-a664-23793cc0d6fb)

_Above: Human in the loop (HITL) approval of an investigation_

- After a human or higher autonomy-level approves, a `workflow.execute` step kicks off (the separate) `system-security-watch-deep` workflow, with the attack discovery ID as input, to investigate:

![investigation](https://github.com/user-attachments/assets/7ecf2d9d-28f7-426d-a2e9-7dc7dc64acb4)

_Above: The `Investigate` step executes another workflow_

- The investigation workflow uses the `ai.agent` step to triage attack discovery alerts via the `alert-analysis` agent builder skill to determine if the discovery is a true positive

- If the investigation indicated the attack was real, a `waitForInput` step displays a HITL _Escalate_ entry on the AlertZero page:

![escalate](https://github.com/user-attachments/assets/ebda153a-95c9-435e-8514-79902d81b359)

_Above: Users are prompted to `Escalate to an incident`_

- A new _Incident_ agent builder conversation is created when users escalate

- The incident conversation includes references to the original investigation sub conversations

- Users conform the incident is contained via the _Contain_ HITL step:

![contain](https://github.com/user-attachments/assets/d571d623-4378-451e-9ee0-174d8325fafa)

_Above: Users are prompted to `Confirm containment`_

- This branch does _NOT_ prototype real containment

- The `await_incident_contained` step uses `waitForInput` to confirm the incident was contained

- After containment, the `Post-Incident Watch` workflow runs to suggest tuning / improvements to reduce detection gaps

- This POC does NOT impement real detection rule tuning e2e

- A (stubbed) HITL entry is displayed on the AlertZero page, representing the proposed tuning:

![tune](https://github.com/user-attachments/assets/4d04f403-7f63-4561-b49a-14edcf361dea)

_Above: A proposed detection rule tuning_

Each watch has three levels of automony:

| Level | HITL Approvals |
|---|---|
| `manual` | All phases (e.g. opening an investigation) require HITL approval |
| `assisted` | Routine, reversible actions are automatically approved. Anything else requires HITL approval. |
| `supervised` | Most actions are auto-approved via an allow-list. Some still require HITL. |

In the POC:

- Workflows _always_ `waitForInput`, regardless of the currently configured autonomy level
- At higher levels of autonomy, the `Watch Auto Approver` workflow uses an internal API to auto-approve workflows waiting for input

The POC implements an additional flyout (with placeholder UX) to show potential _future_ actions and link to previous workflow executions, as illustrated by the following screenshot:

![lifecycle](https://github.com/user-attachments/assets/03d38090-c261-4081-a144-a479247839b2)

_Above: The Lifecycle (placeholder) flyout shows actions that may happen in the future_

The POC implemnts a primative `/chats` page that _simulates_ parent-child relationships between agent builder conversations, as a stopgap until Agent Builder supports them natively.

The page has two separate groups of conversations:
- Incidents
- Investigations

as illustrated by the following screenshot:

![chat](https://github.com/user-attachments/assets/b953e1bd-04f6-4819-b289-b69c3575f62d)

_Above: Incident chats with Attack discovery attachments_

Running the POC requires enabling the AlertZero feature flag (details below) and the following Kibana advanced settings:

![advanced_settings](https://github.com/user-attachments/assets/427e8916-9f06-419c-8e3c-d8784dde95eb)

1) Enable the AlertZero feature flag in `kibana.dev.yml`:

```yaml
xpack.pnd:
  enabled: true
```

2) In Stack Management → Advanced Settings, enable Attack discovery 2.0:

- `securitySolution:enableAttackDiscoveryWorkflows: true`

In Stack Management → Advanced Settings, optionally enable the following settings:

a) `workflows:ui:showManagedWorkflows`
b) `workflows:experimentalFeatures`

See the AletZero [README](x-pack/solutions/security/plugins/pnd/README.md) for details.

_Created with Claude Code, Cursor, Opus 5, and Grok 4.6_
…values.

Catalog watches stay disabled until enabled in a space; autonomy lives on those template values instead of uiSettings, and boot only installs static helpers (including Detection and the auto-approver).

Co-authored-by: Cursor <cursoragent@cursor.com>
…ended-actions

Merges the AD recommended-actions HITL POC (elastic#287158) into the AlertZero
runnable POC (elastic#287301). Resolution strategy:

- AlertZero's four-phase Watch Floor orchestrator is kept as the foundation
  (watch_floor.yaml, definitions/pnd structure, settings page, watches service).
- The recommended-actions skill, @kbn/pnd-common action contracts, discoveries
  run-step sync-await change, ensure-schedule route/service, AD worker config
  UI components, and the workflow_crud_service includeGlobal fix are carried in.
- The 1478-line combined watch_attack_discovery worker is removed: its
  generation lane and its recommend/review/execute lane are re-landed next as a
  dedicated Attack Discovery Generation watch and a rebuilt Floor Phase 3.
- ensureSchedule and the _schedule route are adapted to AlertZero's per-space
  managed-install model and RouteAuthz factories.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Floor

Implements the two-worker Attack Discovery split and rebuilds Phase 3 of the
Watch Floor around recommended actions:

- New Attack Discovery Generation watch (per-space catalog watch,
  system-security-watch-attack-discovery-generation): scheduled trigger with a
  configurable cadence, alert size, lookback and connector persisted as managed
  template values, concurrency drop max 1. Each net-new persisted discovery
  emits security.attackDiscoveryCreated and wakes one Watch Floor run — keeping
  generation and the per-discovery HITL lifecycle in separate workflows so a
  parked gate can never stall a generation tick and the engine's avoid-loop
  guard passes.
- Watch Floor v21 Phase 3: recommend_actions (recommended-actions Agent Builder
  skill, structured output) stages containment actions; the always-human
  incident_contained gate now carries a per-action approval (approved_actions,
  embedded in the card via a label-anchored JSON contract); approved
  Kibana-executable actions execute post-gate as the approving analyst
  (create case + alert attachments + observables, Entity Store asset
  criticality, isolate host, kill process, hunt process persistence) with a
  complete per-action ledger; incident_closed and the post-incident tuning
  lane are unchanged.
- Queue UI: RecommendedActionsDecisionForm renders one toggle per staged action
  (manual actions listed read-only; surfaced-only actions flagged), defaulting
  everything off; dismiss disables and empties the approval.
- Lifecycle flyout: new Containment actions section + step-3-6 evidence badges
  render the execution ledger via the executions route's new containmentActions
  projection; phase catalog gains Recommend/Execute rows.
- Watch detail: Frequency select is live for the generation watch, plus a
  Generation section (alerts per run, alert window, connector); settings writes
  re-assert enablement so Task Manager reprograms the cadence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt gate

- watch_floor v22: open_incident continues on failure (same rationale as
  draft_tuning — a tool-call hallucination or empty structured response from
  the incident agent must not kill a run a human already escalated; no retry
  because the turn creates a conversation at a fixed id). The containment card
  says plainly when the incident brief is absent; recommend_actions already
  stages actions from the attack discovery and investigation assessment alone.
- ensureSchedule resolves the watch registration before the managed-workflows
  status read (type-correct id narrowing).
- Queue/watch/chat surfaces updated to the containment gate's new
  'Review containment actions' label; sixth watch labeled on the queue rows.
- PND README, discoveries README and the ad-worker-flow diagram updated to the
  merged two-worker + recommended-actions architecture.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…b-action errors

Watch Floor v23: the case-observable attachments now POST
/internal/cases/{case_id}/observables (the public versioned route no longer
exists on main and the cap is 10 per case), and the attach/observable ledger
records carry the failing error so a failed row explains itself. The
executions projection also fetches step outputs (includeOutput) so the
containment ledger actually reaches the lifecycle flyout.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
opauloh and others added 4 commits August 28, 2026 22:26
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…actions JSON

The chrome-less approval modal had no height bound and the card no internal
scroll, so a containment gate with a long staged-action list pushed its own
toggle form and the footer buttons off screen. The modal now caps at the
viewport, the card is a flex column whose middle region scrolls while the
header and Approve/Cancel footer stay put, and the machine-readable
`Staged containment actions JSON:` block is stripped from the displayed
reasoning on exactly the rows where the toggle form renders those actions —
the prose on either side of the anchor is kept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e agent hunt

analyze_exfiltration_ips was surfaced-only because no single Kibana endpoint
sits behind threat_hunting.exfil_ips. Watch Floor v24 gives an approved toggle
a real execution lane that fits what the action is: a scoped, strictly
read-only ai.agent hunt (ES|QL over the space's alert/event indices, bounded
to 7 days) whose findings are appended to the incident conversation — the
audit thread — and whose bounded structured result (summary, communicating
hosts, exfiltration_suspected) lands in the per-action ledger as
succeeded/failed. The accounting drops the surfaced-only carve-outs (a
dismissed or untoggled analysis now ledgers like any other Kibana action), and
the toggle form's badge now reads "Read-only agent hunt — findings post to the
incident chat" so the toggle states exactly what approval authorizes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ary bound

A staged-action array with full target lists can exceed the reasoning
summary's 8192-character projection bound on its own — a live run truncated
the JSON mid-string, and the toggle form correctly failed closed to the fixed
controls, losing the per-action approval. The machine-readable list now rides
the UNtruncated reasoning sections entry ('Staged containment actions', title
pinned on both sides): the server projects it verbatim onto a new bounded
PndProposalRow.stagedActions field for the containment gate only, the toggle
form prefers that field (the summary label anchor stays as the fallback for
already-parked rows), and the Floor's summary is prose-only again (v25). The
recommend_actions schema also bounds the target arrays as defense in depth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

@opauloh, this PR increases one or more page-load bundle sizes by 15% or more:

Limits file Plugin Before (bytes) After (bytes) Change
packages/kbn-rspack-optimizer/limits.yml alertingVTwo 21,472 50,017 +132.9%

Large bundle size increases can affect page load performance. Consider whether dependencies can be lazy-loaded or code split to reduce the bundle.

See the bundle optimization guide for tips.

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown
🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants