Skip to content

fix(rules): keep a rule's condition and preview it before saving - #1169

Merged
catinspace-au merged 1 commit into
mainfrom
fix/rule-assistant-api
Nov 15, 2026
Merged

catinspace-au merged 1 commit into
mainfrom
fix/rule-assistant-api

Conversation

@catinspace-au

Copy link
Copy Markdown
Contributor

The engine stores builder conditions and previews saves for the console UI Kay and Kaz can build against these endpoints.

  • A rule takes a structured condition or raw user_sql, not both. The engine compiles the condition to the rule's SQL and stores both, so editing reopens the builder. A rule saved as SQL has no condition.
  • POST /api/v1/rules/preview runs the same checks as saving, with the same organisation boundary. It writes nothing. For a condition that saving would reject, it returns 200 with reasons in sql_errors or matches_everything.
  • The operators are the source form's six plus lt, lte, gt, gte and in. The RuleCondition schema in openapi.json publishes them with each operator's value kind (x-dfe-operand-kinds) and the nesting limit (x-dfe-max-nesting).
  • GET /api/v1/hunts?rule=<name> lists the hunts that run a rule.
  • source-detections.md showed a rule as a where_clause file while the API takes a full SELECT. It now says what is stored and documents conditions.
  • RuleCondition is its own model with the source form's field names. Sharing SourceMatch would let a source save lt or in, which the receiver has no test for.
  • Text operands go through quote_literal. Fields are split into quoted identifier parts. A field uses the matching source-table column if it exists. Otherwise, it uses a path inside _json, read as its operand's type.
  • Compilation fails if ClickHouse is configured but cannot be read. It does not guess whether a field is a column or a path.

Done when the console can create, preview, edit and reopen a rule through these endpoints with no engine change.

The engine stores structured conditions so the console's rule builder can reopen them for editing.

- A rule takes either a structured condition or raw SQL. The engine compiles the condition to SQL and stores both. A rule saved as SQL has no condition.
- POST /api/v1/rules/preview runs the same checks with the same organisation restrictions as saving, without writing anything. For a condition that saving would reject, it returns 200 with the reasons.
- The condition operators are the source form's six plus lt, lte, gt, gte and in. The RuleCondition schema in openapi.json lists them with each operator's value type and the nesting limit.
- GET /api/v1/hunts takes rule=<name> to list the hunts that run a rule.
- source-detections.md showed a rule as a where_clause file while the API takes a full SELECT. It now documents stored rules and conditions.

Every text operand goes through quote_literal. Each field is split into quoted identifier parts. A field uses the matching source-table column, or a path inside _json read as the operand's type. Compilation fails when ClickHouse is configured but cannot be read.
@catinspace-au
catinspace-au merged commit b7a5e29 into main Nov 15, 2026
19 checks passed
@catinspace-au
catinspace-au deleted the fix/rule-assistant-api branch November 15, 2026 00:46
@github-actions

Copy link
Copy Markdown

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.

1 participant