Skip to content

[ResponseOps][Rules] Create Rules APIs package#214187

Merged
umbopepato merged 27 commits intoelastic:mainfrom
umbopepato:213059-response-ops-rules-apis-package
Mar 26, 2025
Merged

[ResponseOps][Rules] Create Rules APIs package#214187
umbopepato merged 27 commits intoelastic:mainfrom
umbopepato:213059-response-ops-rules-apis-package

Conversation

@umbopepato
Copy link
Member

@umbopepato umbopepato commented Mar 12, 2025

Summary

  • Creates a @kbn/response-ops-rules-apis package, following the proposed structure for ResponseOps Management Experiences package.
  • Moves relevant rules API fetchers and react-query hooks to the new package.
  • Adds an internal variant of the /api/alerting/rule_types endpoint (/internal/alerting/_rule_types), that returns the same value as the public one + the newly added internal solution field, that we don't want to expose publicly.

Verification steps

  1. Create rules that fire alerts
  2. Verify the usages of the moved/changed hooks, with limited privileges as well (i.e. only Rules Settings but not Stack Rules):
    2.1. Stack management and Observability rules, rule details and alerts pages
    2.2. Rules tab in the Connector editor flyout
    2.3. Alerts table row actions (••• icon)
    2.4. Tags filter in the rules list page
  3. Using the DevTools, compare the response of the public and internal rule_types endpoins:
    GET kbn:/api/alerting/rule_types
    GET kbn:/internal/alerting/_rule_types
    
    Checking that the solution field is present only in the internal one

References

Closes #213059

Checklist

@umbopepato umbopepato force-pushed the 213059-response-ops-rules-apis-package branch 5 times, most recently from e67c495 to 63a821c Compare March 13, 2025 14:29
@umbopepato umbopepato added release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// backport:version Backport to applied version labels v9.1.0 v8.19.0 labels Mar 13, 2025
@umbopepato umbopepato force-pushed the 213059-response-ops-rules-apis-package branch from 63a821c to 8251343 Compare March 13, 2025 16:30
"@kbn/response-ops-alerts-table": "link:src/platform/packages/shared/response-ops/alerts-table",
"@kbn/response-ops-rule-form": "link:src/platform/packages/shared/response-ops/rule_form",
"@kbn/response-ops-rule-params": "link:src/platform/packages/shared/response-ops/rule_params",
"@kbn/response-ops-rules-apis": "link:src/platform/packages/shared/response-ops/rules-apis",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using kebab-case for package folders as requested by the operations team

import type { Filter } from '@kbn/es-query';
import type { RuleNotifyWhenType, RRuleParams } from '.';

export type RuleTypeSolution = 'observability' | 'security' | 'stack';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to move this here to avoid circular dependencies between plugins and packages

};

export const useLoadRuleTypesQuery = ({
export const useGetRuleTypesPermissions = ({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hook was acting as the main rule types fetcher but also as privilege checker, returning computed values and not the original query. I extracted the react-query part that only fetches rule types to the new package, keeping this hook as a more privilege-checking-focused one (hence the new name). I avoided further refactors such as removing the returned rule types registry thing since there is a bit of filtering logic that might be worth studying better, and moving the hook to the new package as it's not properly a data-fetching hook (I'm wondering where these higher-level hooks should belong in our new package structure 🤔).


export const BASE_ALERTING_API_PATH = '/api/alerting';

export const queryKeys = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved all queryKeys and queryMutations of the new packages to dedicated files to increase visibility and because they aren't properly constants in the JS reference sense of the term

notifications: NotificationsStart;
}

export const getKey = queryKeys.getMutedAlerts;
Copy link
Member Author

@umbopepato umbopepato Mar 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying out the WIP proposal of co-locating key creators by re-exporting them from the factory

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the idea behind this?


export const queryKeys = {
root: 'rules',
getRuleTags: ({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying out the WIP proposal of using the same exact name as the fetchFn for the key creator (for better discoverability)

]
`);
});

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this test to its dedicated file in the new package

filteredRuleTypes,
});

const authorizedRuleTypes = [...ruleTypes.values()];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same logic that the useLoadRuleTypesQuery was using internally, I used the calculated value from the hook directly

@umbopepato
Copy link
Member Author

umbopepato commented Mar 24, 2025

@umbopepato I'm missing a link to the mentioned "proposed structure for ResponseOps Management Experiences package"

and #214187 (comment)

@jcger unfortunately I cannot link either document here but I shared them with you on other channels. The idea behind re-exporting the query key factory is to both have a centralized query key factory for each api package but also co-locate them along with their respective hooks for convenience. Trying it out with these new API packages, if we see it's not useful we can always remove it 🙂

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
alerting 229 232 +3
apm 1896 1899 +3
cases 1015 1018 +3
discover 1179 1182 +3
embeddableAlertsTable 283 288 +5
infra 1454 1457 +3
ml 2403 2408 +5
monitoring 655 658 +3
observability 1313 1318 +5
securitySolution 7095 7098 +3
slo 1130 1133 +3
synthetics 1217 1220 +3
transform 716 719 +3
triggersActionsUi 837 841 +4
uptime 812 815 +3
total +52

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/alerting-types 248 249 +1
triggersActionsUi 525 520 -5
total -4

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
alerting 98.5KB 98.7KB +276.0B
apm 2.5MB 2.5MB +374.0B
cases 1.3MB 1.3MB +283.0B
discover 951.1KB 951.5KB +379.0B
embeddableAlertsTable 803.8KB 804.2KB +390.0B
infra 1.2MB 1.2MB +379.0B
ml 5.4MB 5.4MB +416.0B
monitoring 642.4KB 642.8KB +376.0B
observability 1.3MB 1.3MB +224.0B
securitySolution 8.9MB 8.9MB +305.0B
slo 921.8KB 922.1KB +376.0B
synthetics 985.8KB 986.2KB +376.0B
transform 634.3KB 634.7KB +376.0B
triggersActionsUi 1.5MB 1.5MB +670.0B
uptime 533.1KB 533.5KB +376.0B
total +5.4KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
alerting 52 51 -1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
observability 94.6KB 94.6KB -1.0B
triggersActionsUi 108.8KB 107.3KB -1.5KB
total -1.5KB
Unknown metric groups

API count

id before after diff
@kbn/alerting-types 252 253 +1
triggersActionsUi 531 526 -5
total -4

ESLint disabled in files

id before after diff
@kbn/response-ops-rules-apis - 2 +2

ESLint disabled line counts

id before after diff
@kbn/test-suites-xpack 727 729 +2

Total ESLint disabled count

id before after diff
@kbn/response-ops-rules-apis - 2 +2
@kbn/test-suites-xpack 753 755 +2
total +4

History

@maryam-saeidi maryam-saeidi self-requested a review March 25, 2025 09:25
Copy link
Member

@maryam-saeidi maryam-saeidi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM!

I tested having only logs or infra permissions, and it looked good.
One thing that I don't think is related to this PR was not showing "Anomaly detection rule" when we only have Logs or Infra permissions, but "useGetAvailableRulesWithDescriptions" returns this rule correctly.

Permission Rules
image image

Is this a known issue?

Copy link
Contributor

@consulthys consulthys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGT Stack Monitoring

@cnasikas
Copy link
Member

One thing that I don't think is related to this PR was not showing "Anomaly detection rule" when we only have Logs or Infra permissions, but "useGetAvailableRulesWithDescriptions" returns this rule correctly.

To my understanding, you need to have ML permission for this rule type, correct?

@umbopepato umbopepato merged commit 7aac590 into elastic:main Mar 26, 2025
10 checks passed
@kibanamachine
Copy link
Contributor

Starting backport for target branches: 8.x

https://github.com/elastic/kibana/actions/runs/14079314201

@kibanamachine
Copy link
Contributor

💔 All backports failed

Status Branch Result
8.x Backport failed because of merge conflicts

Manual backport

To create the backport manually run:

node scripts/backport --pr 214187

Questions ?

Please refer to the Backport tool documentation

umbopepato added a commit to umbopepato/kibana that referenced this pull request Mar 26, 2025
## Summary

- Creates a `@kbn/response-ops-rules-apis` package, following the
proposed structure for ResponseOps Management Experiences package.
- Moves relevant rules API fetchers and react-query hooks to the new
package.
- Adds an internal variant of the `/api/alerting/rule_types` endpoint
(`/internal/alerting/_rule_types`), that returns the same value as the
public one + the newly added internal [`solution`
field](elastic#212017), that we don't
want to expose publicly.

## Verification steps

1. Create rules that fire alerts
2. Verify the usages of the moved/changed hooks, with limited privileges
as well (i.e. only `Rules Settings` but not `Stack Rules`):
2.1. Stack management and Observability rules, rule details and alerts
pages
2.2. Rules tab in the Connector editor flyout
2.3. Alerts table row actions (••• icon)
2.4. Tags filter in the rules list page
3. Using the DevTools, compare the response of the public and internal
`rule_types` endpoins:
    ```
    GET kbn:/api/alerting/rule_types
    GET kbn:/internal/alerting/_rule_types
    ```
Checking that the `solution` field is present only in the internal one

## References

Closes elastic#213059

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit 7aac590)

# Conflicts:
#	.github/CODEOWNERS
#	x-pack/platform/plugins/shared/alerting/common/routes/rule/apis/list_types/schemas/v1.ts
#	x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/rule_types_internal.ts
#	x-pack/test/alerting_api_integration/security_and_spaces/group5/tests/alerting/index.ts
#	x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_rule_tags.ts
@umbopepato
Copy link
Member Author

💚 All backports created successfully

Status Branch Result
8.x

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

umbopepato added a commit that referenced this pull request Mar 26, 2025
# Backport

This will backport the following commits from `main` to `8.x`:
- [[ResponseOps][Rules] Create Rules APIs package
(#214187)](#214187)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Umberto
Pepato","email":"umbopepato@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-03-26T09:01:51Z","message":"[ResponseOps][Rules]
Create Rules APIs package (#214187)\n\n## Summary\n\n- Creates a
`@kbn/response-ops-rules-apis` package, following the\nproposed
structure for ResponseOps Management Experiences package.\n- Moves
relevant rules API fetchers and react-query hooks to the
new\npackage.\n- Adds an internal variant of the
`/api/alerting/rule_types` endpoint\n(`/internal/alerting/_rule_types`),
that returns the same value as the\npublic one + the newly added
internal
[`solution`\nfield](#212017),
that we don't\nwant to expose publicly.\n\n## Verification steps\n\n1.
Create rules that fire alerts\n2. Verify the usages of the moved/changed
hooks, with limited privileges\nas well (i.e. only `Rules Settings` but
not `Stack Rules`):\n2.1. Stack management and Observability rules, rule
details and alerts\npages\n2.2. Rules tab in the Connector editor
flyout\n2.3. Alerts table row actions (••• icon)\n2.4. Tags filter in
the rules list page\n3. Using the DevTools, compare the response of the
public and internal\n`rule_types` endpoins:\n ```\n GET
kbn:/api/alerting/rule_types\n GET kbn:/internal/alerting/_rule_types\n
```\nChecking that the `solution` field is present only in the internal
one\n\n## References \n\nCloses #213059 \n\n### Checklist\n\n- [x] [Unit
or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"7aac590af4e245049f3865ea23ed88a179a80a28","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:ResponseOps","Team:obs-ux-management","backport:version","v9.1.0","v8.19.0"],"title":"[ResponseOps][Rules]
Create Rules APIs
package","number":214187,"url":"https://github.com/elastic/kibana/pull/214187","mergeCommit":{"message":"[ResponseOps][Rules]
Create Rules APIs package (#214187)\n\n## Summary\n\n- Creates a
`@kbn/response-ops-rules-apis` package, following the\nproposed
structure for ResponseOps Management Experiences package.\n- Moves
relevant rules API fetchers and react-query hooks to the
new\npackage.\n- Adds an internal variant of the
`/api/alerting/rule_types` endpoint\n(`/internal/alerting/_rule_types`),
that returns the same value as the\npublic one + the newly added
internal
[`solution`\nfield](#212017),
that we don't\nwant to expose publicly.\n\n## Verification steps\n\n1.
Create rules that fire alerts\n2. Verify the usages of the moved/changed
hooks, with limited privileges\nas well (i.e. only `Rules Settings` but
not `Stack Rules`):\n2.1. Stack management and Observability rules, rule
details and alerts\npages\n2.2. Rules tab in the Connector editor
flyout\n2.3. Alerts table row actions (••• icon)\n2.4. Tags filter in
the rules list page\n3. Using the DevTools, compare the response of the
public and internal\n`rule_types` endpoins:\n ```\n GET
kbn:/api/alerting/rule_types\n GET kbn:/internal/alerting/_rule_types\n
```\nChecking that the `solution` field is present only in the internal
one\n\n## References \n\nCloses #213059 \n\n### Checklist\n\n- [x] [Unit
or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"7aac590af4e245049f3865ea23ed88a179a80a28"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/214187","number":214187,"mergeCommit":{"message":"[ResponseOps][Rules]
Create Rules APIs package (#214187)\n\n## Summary\n\n- Creates a
`@kbn/response-ops-rules-apis` package, following the\nproposed
structure for ResponseOps Management Experiences package.\n- Moves
relevant rules API fetchers and react-query hooks to the
new\npackage.\n- Adds an internal variant of the
`/api/alerting/rule_types` endpoint\n(`/internal/alerting/_rule_types`),
that returns the same value as the\npublic one + the newly added
internal
[`solution`\nfield](#212017),
that we don't\nwant to expose publicly.\n\n## Verification steps\n\n1.
Create rules that fire alerts\n2. Verify the usages of the moved/changed
hooks, with limited privileges\nas well (i.e. only `Rules Settings` but
not `Stack Rules`):\n2.1. Stack management and Observability rules, rule
details and alerts\npages\n2.2. Rules tab in the Connector editor
flyout\n2.3. Alerts table row actions (••• icon)\n2.4. Tags filter in
the rules list page\n3. Using the DevTools, compare the response of the
public and internal\n`rule_types` endpoins:\n ```\n GET
kbn:/api/alerting/rule_types\n GET kbn:/internal/alerting/_rule_types\n
```\nChecking that the `solution` field is present only in the internal
one\n\n## References \n\nCloses #213059 \n\n### Checklist\n\n- [x] [Unit
or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"7aac590af4e245049f3865ea23ed88a179a80a28"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Alex Szabo <alex.szabo@elastic.co>
cqliu1 pushed a commit to cqliu1/kibana that referenced this pull request Mar 31, 2025
## Summary

- Creates a `@kbn/response-ops-rules-apis` package, following the
proposed structure for ResponseOps Management Experiences package.
- Moves relevant rules API fetchers and react-query hooks to the new
package.
- Adds an internal variant of the `/api/alerting/rule_types` endpoint
(`/internal/alerting/_rule_types`), that returns the same value as the
public one + the newly added internal [`solution`
field](elastic#212017), that we don't
want to expose publicly.

## Verification steps

1. Create rules that fire alerts
2. Verify the usages of the moved/changed hooks, with limited privileges
as well (i.e. only `Rules Settings` but not `Stack Rules`):
2.1. Stack management and Observability rules, rule details and alerts
pages
2.2. Rules tab in the Connector editor flyout
2.3. Alerts table row actions (••• icon)
2.4. Tags filter in the rules list page
3. Using the DevTools, compare the response of the public and internal
`rule_types` endpoins:
    ```
    GET kbn:/api/alerting/rule_types
    GET kbn:/internal/alerting/_rule_types
    ```
Checking that the `solution` field is present only in the internal one

## References 

Closes elastic#213059 

### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
umbopepato added a commit that referenced this pull request Apr 17, 2025
## Summary

Implements the alerts filters form that will be used to pre-filter the
alerts table embeddable.

<img width="1004" alt="image"
src="https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af"
/>

> [!NOTE]
> I'm using the terminology "form" to distinguish this from the alert
filter _controls_ or other type of more KQL-bar-like filters. Other
alternatives that came to mind were `alerts-boolean-filters-...` or
`alerts-filters-builder`.

<details>
<summary>

## Implementation details

</summary>

### Filters expression state

I opted for a tree state representation of the form's boolean expression
to accommodate potential future requirements such as more complex
boolean expressions (negation, parenthesized subexpressions to manually
control operators precedence):

```ts
{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}
```

This state is saved in the embeddable panel state and represents the
editor form. The embeddable alerts table wrapper component will then
transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent
flattened state is used:

```ts
[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]
```

### Filters model

Each filter is described by an `AlertsFilterMetadata<T>` object, where
`T` is the type of the filter value:

```tsx
export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};
```

</details>

## Verification steps

1. Run Kibana with examples (`yarn start --run-examples`)
2. Create rules in different solutions with tags
3. Navigate to `/app/triggersActionsUiExample/alerts_filters_form`
4. Check that the solution selector options are coherent with the rule
types the user can access
5. Select a solution
6. Build filters expressions, checking that the rule tags and rule types
are coherent with the solution selection and the rules created
previously
7. Repeat steps 3-6 with different roles:
7.1. having access to rule types from just one solution (in this case
the solution selector shouldn't appear at all),
7.2. having access just to Observability and Stack but not Security (in
this case the solution selector shouldn't appear at all),
8. Repeat steps 3-6 in the three serverless project types:
    ```shell
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    ```
(If the authentication fails when switching between project types, use a
clean session)
8.1. ES project types should have access only to Stack rules (no
selector)
8.2. Observability project types should have access only to
Observability and Stack rules (no selector)
8.3. Security project types should have access only to Security and
Stack rules (selector shows Stack instead of Observability)

## References

Depends on #214187
Closes #213061

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <xristosnasikas@gmail.com>
davismcphee pushed a commit to davismcphee/kibana that referenced this pull request Apr 22, 2025
## Summary

Implements the alerts filters form that will be used to pre-filter the
alerts table embeddable.

<img width="1004" alt="image"
src="https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af"
/>

> [!NOTE]
> I'm using the terminology "form" to distinguish this from the alert
filter _controls_ or other type of more KQL-bar-like filters. Other
alternatives that came to mind were `alerts-boolean-filters-...` or
`alerts-filters-builder`.

<details>
<summary>

## Implementation details

</summary>

### Filters expression state

I opted for a tree state representation of the form's boolean expression
to accommodate potential future requirements such as more complex
boolean expressions (negation, parenthesized subexpressions to manually
control operators precedence):

```ts
{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}
```

This state is saved in the embeddable panel state and represents the
editor form. The embeddable alerts table wrapper component will then
transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent
flattened state is used:

```ts
[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]
```

### Filters model

Each filter is described by an `AlertsFilterMetadata<T>` object, where
`T` is the type of the filter value:

```tsx
export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};
```

</details>

## Verification steps

1. Run Kibana with examples (`yarn start --run-examples`)
2. Create rules in different solutions with tags
3. Navigate to `/app/triggersActionsUiExample/alerts_filters_form`
4. Check that the solution selector options are coherent with the rule
types the user can access
5. Select a solution
6. Build filters expressions, checking that the rule tags and rule types
are coherent with the solution selection and the rules created
previously
7. Repeat steps 3-6 with different roles:
7.1. having access to rule types from just one solution (in this case
the solution selector shouldn't appear at all),
7.2. having access just to Observability and Stack but not Security (in
this case the solution selector shouldn't appear at all),
8. Repeat steps 3-6 in the three serverless project types:
    ```shell
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    ```
(If the authentication fails when switching between project types, use a
clean session)
8.1. ES project types should have access only to Stack rules (no
selector)
8.2. Observability project types should have access only to
Observability and Stack rules (no selector)
8.3. Security project types should have access only to Security and
Stack rules (selector shows Stack instead of Observability)

## References

Depends on elastic#214187
Closes elastic#213061

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <xristosnasikas@gmail.com>
umbopepato added a commit to umbopepato/kibana that referenced this pull request Apr 22, 2025
## Summary

Implements the alerts filters form that will be used to pre-filter the
alerts table embeddable.

<img width="1004" alt="image"
src="https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af"
/>

> [!NOTE]
> I'm using the terminology "form" to distinguish this from the alert
filter _controls_ or other type of more KQL-bar-like filters. Other
alternatives that came to mind were `alerts-boolean-filters-...` or
`alerts-filters-builder`.

<details>
<summary>

## Implementation details

</summary>

### Filters expression state

I opted for a tree state representation of the form's boolean expression
to accommodate potential future requirements such as more complex
boolean expressions (negation, parenthesized subexpressions to manually
control operators precedence):

```ts
{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}
```

This state is saved in the embeddable panel state and represents the
editor form. The embeddable alerts table wrapper component will then
transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent
flattened state is used:

```ts
[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]
```

### Filters model

Each filter is described by an `AlertsFilterMetadata<T>` object, where
`T` is the type of the filter value:

```tsx
export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};
```

</details>

## Verification steps

1. Run Kibana with examples (`yarn start --run-examples`)
2. Create rules in different solutions with tags
3. Navigate to `/app/triggersActionsUiExample/alerts_filters_form`
4. Check that the solution selector options are coherent with the rule
types the user can access
5. Select a solution
6. Build filters expressions, checking that the rule tags and rule types
are coherent with the solution selection and the rules created
previously
7. Repeat steps 3-6 with different roles:
7.1. having access to rule types from just one solution (in this case
the solution selector shouldn't appear at all),
7.2. having access just to Observability and Stack but not Security (in
this case the solution selector shouldn't appear at all),
8. Repeat steps 3-6 in the three serverless project types:
    ```shell
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    ```
(If the authentication fails when switching between project types, use a
clean session)
8.1. ES project types should have access only to Stack rules (no
selector)
8.2. Observability project types should have access only to
Observability and Stack rules (no selector)
8.3. Security project types should have access only to Security and
Stack rules (selector shows Stack instead of Observability)

## References

Depends on elastic#214187
Closes elastic#213061

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <xristosnasikas@gmail.com>
(cherry picked from commit c44efc5)

# Conflicts:
#	x-pack/examples/triggers_actions_ui_example/public/application.tsx
umbopepato added a commit that referenced this pull request Apr 22, 2025
…218759)

# Backport

This will backport the following commits from `main` to `8.19`:
- [[ResponseOps][Alerts] Implement alerts filters form
(#214982)](#214982)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Umberto
Pepato","email":"umbopepato@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-04-17T14:18:24Z","message":"[ResponseOps][Alerts]
Implement alerts filters form (#214982)\n\n## Summary\n\nImplements the
alerts filters form that will be used to pre-filter the\nalerts table
embeddable.\n\n<img width=\"1004\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af\"\n/>\n\n>
[!NOTE]\n> I'm using the terminology \"form\" to distinguish this from
the alert\nfilter _controls_ or other type of more KQL-bar-like filters.
Other\nalternatives that came to mind were `alerts-boolean-filters-...`
or\n`alerts-filters-builder`.\n\n<details>\n<summary>\n\n##
Implementation details\n\n</summary>\n\n### Filters expression
state\n\nI opted for a tree state representation of the form's boolean
expression\nto accommodate potential future requirements such as more
complex\nboolean expressions (negation, parenthesized subexpressions to
manually\ncontrol operators precedence):\n\n```ts\n{\n operator: 'or',\n
operands: [\n {\n operator: 'or',\n operands: [\n { type: 'ruleTags',
value: ['tag-1'] },\n { type: 'ruleTags', value: ['tag-2'] },\n {\n
operator: 'and',\n operands: [{ type: 'ruleTypes', value: ['type-1'] },
{ type: 'ruleTypes', value: ['type-2'] }],\n },\n ],\n },\n { type:
'ruleTags', value: ['tag-3'] },\n ],\n}\n```\n\nThis state is saved in
the embeddable panel state and represents the\neditor form. The
embeddable alerts table wrapper component will then\ntransform this to
an actual ES query.\n\nTo simplify interactions inside the form, an
intermediate equivalent\nflattened state is used:\n\n```ts\n[\n {
filter: { type: 'ruleTags', value: ['tag-1'] } },\n { operator: 'or'
},\n { filter: { type: 'ruleTags', value: ['tag-2'] } },\n { operator:
'or' },\n { filter: { type: 'ruleTypes', value: ['type-1'] }},\n {
operator: 'and' },\n { filter: { type: 'ruleTypes', value: ['type-2'] }
},\n { operator: 'or' },\n { filter: { type: 'ruleTags', value:
['tag-3'] } },\n]\n```\n\n### Filters model\n\nEach filter is described
by an `AlertsFilterMetadata<T>` object, where\n`T` is the type of the
filter value:\n\n```tsx\nexport const filterMetadata:
AlertsFilterMetadata<string[]> = {\n id: 'ruleTags',\n displayName:
RULE_TAGS_FILTER_LABEL,\n component: AlertsFilterByRuleTags,\n //
Filter-specific empty check\n isEmpty: (value?: string[]) =>
!value?.length,\n // Conversion to ES query DSL\n toEsQuery: (value:
string[]) => {\n return {\n terms: {\n [ALERT_RULE_TAGS]: value,\n },\n
};\n },\n};\n```\n\n</details>\n\n## Verification steps\n\n1. Run Kibana
with examples (`yarn start --run-examples`)\n2. Create rules in
different solutions with tags\n3. Navigate to
`/app/triggersActionsUiExample/alerts_filters_form`\n4. Check that the
solution selector options are coherent with the rule\ntypes the user can
access\n5. Select a solution\n6. Build filters expressions, checking
that the rule tags and rule types\nare coherent with the solution
selection and the rules created\npreviously\n7. Repeat steps 3-6 with
different roles:\n7.1. having access to rule types from just one
solution (in this case\nthe solution selector shouldn't appear at
all),\n7.2. having access just to Observability and Stack but not
Security (in\nthis case the solution selector shouldn't appear at
all),\n8. Repeat steps 3-6 in the three serverless project types:\n
```shell\n $ yarn es serverless —ssl --projectType <es|oblt|security>\n
$ yarn serverless-<es|oblt|security> --ssl --run-examples\n ```\n(If the
authentication fails when switching between project types, use a\nclean
session)\n8.1. ES project types should have access only to Stack rules
(no\nselector)\n8.2. Observability project types should have access only
to\nObservability and Stack rules (no selector)\n8.3. Security project
types should have access only to Security and\nStack rules (selector
shows Stack instead of Observability)\n\n## References\n\nDepends on
#214187\nCloses #213061\n\n### Checklist\n\n- [x] Any text added follows
[EUI's
writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\nsentence case text and includes
[i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n-
[x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Christos Nasikas
<xristosnasikas@gmail.com>","sha":"c44efc52f62f2bb80c8cb8c288cfb40fc3164344","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:ResponseOps","backport
missing","backport:version","v9.1.0","v8.19.0"],"title":"[ResponseOps][Alerts]
Implement alerts filters
form","number":214982,"url":"https://github.com/elastic/kibana/pull/214982","mergeCommit":{"message":"[ResponseOps][Alerts]
Implement alerts filters form (#214982)\n\n## Summary\n\nImplements the
alerts filters form that will be used to pre-filter the\nalerts table
embeddable.\n\n<img width=\"1004\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af\"\n/>\n\n>
[!NOTE]\n> I'm using the terminology \"form\" to distinguish this from
the alert\nfilter _controls_ or other type of more KQL-bar-like filters.
Other\nalternatives that came to mind were `alerts-boolean-filters-...`
or\n`alerts-filters-builder`.\n\n<details>\n<summary>\n\n##
Implementation details\n\n</summary>\n\n### Filters expression
state\n\nI opted for a tree state representation of the form's boolean
expression\nto accommodate potential future requirements such as more
complex\nboolean expressions (negation, parenthesized subexpressions to
manually\ncontrol operators precedence):\n\n```ts\n{\n operator: 'or',\n
operands: [\n {\n operator: 'or',\n operands: [\n { type: 'ruleTags',
value: ['tag-1'] },\n { type: 'ruleTags', value: ['tag-2'] },\n {\n
operator: 'and',\n operands: [{ type: 'ruleTypes', value: ['type-1'] },
{ type: 'ruleTypes', value: ['type-2'] }],\n },\n ],\n },\n { type:
'ruleTags', value: ['tag-3'] },\n ],\n}\n```\n\nThis state is saved in
the embeddable panel state and represents the\neditor form. The
embeddable alerts table wrapper component will then\ntransform this to
an actual ES query.\n\nTo simplify interactions inside the form, an
intermediate equivalent\nflattened state is used:\n\n```ts\n[\n {
filter: { type: 'ruleTags', value: ['tag-1'] } },\n { operator: 'or'
},\n { filter: { type: 'ruleTags', value: ['tag-2'] } },\n { operator:
'or' },\n { filter: { type: 'ruleTypes', value: ['type-1'] }},\n {
operator: 'and' },\n { filter: { type: 'ruleTypes', value: ['type-2'] }
},\n { operator: 'or' },\n { filter: { type: 'ruleTags', value:
['tag-3'] } },\n]\n```\n\n### Filters model\n\nEach filter is described
by an `AlertsFilterMetadata<T>` object, where\n`T` is the type of the
filter value:\n\n```tsx\nexport const filterMetadata:
AlertsFilterMetadata<string[]> = {\n id: 'ruleTags',\n displayName:
RULE_TAGS_FILTER_LABEL,\n component: AlertsFilterByRuleTags,\n //
Filter-specific empty check\n isEmpty: (value?: string[]) =>
!value?.length,\n // Conversion to ES query DSL\n toEsQuery: (value:
string[]) => {\n return {\n terms: {\n [ALERT_RULE_TAGS]: value,\n },\n
};\n },\n};\n```\n\n</details>\n\n## Verification steps\n\n1. Run Kibana
with examples (`yarn start --run-examples`)\n2. Create rules in
different solutions with tags\n3. Navigate to
`/app/triggersActionsUiExample/alerts_filters_form`\n4. Check that the
solution selector options are coherent with the rule\ntypes the user can
access\n5. Select a solution\n6. Build filters expressions, checking
that the rule tags and rule types\nare coherent with the solution
selection and the rules created\npreviously\n7. Repeat steps 3-6 with
different roles:\n7.1. having access to rule types from just one
solution (in this case\nthe solution selector shouldn't appear at
all),\n7.2. having access just to Observability and Stack but not
Security (in\nthis case the solution selector shouldn't appear at
all),\n8. Repeat steps 3-6 in the three serverless project types:\n
```shell\n $ yarn es serverless —ssl --projectType <es|oblt|security>\n
$ yarn serverless-<es|oblt|security> --ssl --run-examples\n ```\n(If the
authentication fails when switching between project types, use a\nclean
session)\n8.1. ES project types should have access only to Stack rules
(no\nselector)\n8.2. Observability project types should have access only
to\nObservability and Stack rules (no selector)\n8.3. Security project
types should have access only to Security and\nStack rules (selector
shows Stack instead of Observability)\n\n## References\n\nDepends on
#214187\nCloses #213061\n\n### Checklist\n\n- [x] Any text added follows
[EUI's
writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\nsentence case text and includes
[i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n-
[x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Christos Nasikas
<xristosnasikas@gmail.com>","sha":"c44efc52f62f2bb80c8cb8c288cfb40fc3164344"}},"sourceBranch":"main","suggestedTargetBranches":["8.19"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/214982","number":214982,"mergeCommit":{"message":"[ResponseOps][Alerts]
Implement alerts filters form (#214982)\n\n## Summary\n\nImplements the
alerts filters form that will be used to pre-filter the\nalerts table
embeddable.\n\n<img width=\"1004\"
alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af\"\n/>\n\n>
[!NOTE]\n> I'm using the terminology \"form\" to distinguish this from
the alert\nfilter _controls_ or other type of more KQL-bar-like filters.
Other\nalternatives that came to mind were `alerts-boolean-filters-...`
or\n`alerts-filters-builder`.\n\n<details>\n<summary>\n\n##
Implementation details\n\n</summary>\n\n### Filters expression
state\n\nI opted for a tree state representation of the form's boolean
expression\nto accommodate potential future requirements such as more
complex\nboolean expressions (negation, parenthesized subexpressions to
manually\ncontrol operators precedence):\n\n```ts\n{\n operator: 'or',\n
operands: [\n {\n operator: 'or',\n operands: [\n { type: 'ruleTags',
value: ['tag-1'] },\n { type: 'ruleTags', value: ['tag-2'] },\n {\n
operator: 'and',\n operands: [{ type: 'ruleTypes', value: ['type-1'] },
{ type: 'ruleTypes', value: ['type-2'] }],\n },\n ],\n },\n { type:
'ruleTags', value: ['tag-3'] },\n ],\n}\n```\n\nThis state is saved in
the embeddable panel state and represents the\neditor form. The
embeddable alerts table wrapper component will then\ntransform this to
an actual ES query.\n\nTo simplify interactions inside the form, an
intermediate equivalent\nflattened state is used:\n\n```ts\n[\n {
filter: { type: 'ruleTags', value: ['tag-1'] } },\n { operator: 'or'
},\n { filter: { type: 'ruleTags', value: ['tag-2'] } },\n { operator:
'or' },\n { filter: { type: 'ruleTypes', value: ['type-1'] }},\n {
operator: 'and' },\n { filter: { type: 'ruleTypes', value: ['type-2'] }
},\n { operator: 'or' },\n { filter: { type: 'ruleTags', value:
['tag-3'] } },\n]\n```\n\n### Filters model\n\nEach filter is described
by an `AlertsFilterMetadata<T>` object, where\n`T` is the type of the
filter value:\n\n```tsx\nexport const filterMetadata:
AlertsFilterMetadata<string[]> = {\n id: 'ruleTags',\n displayName:
RULE_TAGS_FILTER_LABEL,\n component: AlertsFilterByRuleTags,\n //
Filter-specific empty check\n isEmpty: (value?: string[]) =>
!value?.length,\n // Conversion to ES query DSL\n toEsQuery: (value:
string[]) => {\n return {\n terms: {\n [ALERT_RULE_TAGS]: value,\n },\n
};\n },\n};\n```\n\n</details>\n\n## Verification steps\n\n1. Run Kibana
with examples (`yarn start --run-examples`)\n2. Create rules in
different solutions with tags\n3. Navigate to
`/app/triggersActionsUiExample/alerts_filters_form`\n4. Check that the
solution selector options are coherent with the rule\ntypes the user can
access\n5. Select a solution\n6. Build filters expressions, checking
that the rule tags and rule types\nare coherent with the solution
selection and the rules created\npreviously\n7. Repeat steps 3-6 with
different roles:\n7.1. having access to rule types from just one
solution (in this case\nthe solution selector shouldn't appear at
all),\n7.2. having access just to Observability and Stack but not
Security (in\nthis case the solution selector shouldn't appear at
all),\n8. Repeat steps 3-6 in the three serverless project types:\n
```shell\n $ yarn es serverless —ssl --projectType <es|oblt|security>\n
$ yarn serverless-<es|oblt|security> --ssl --run-examples\n ```\n(If the
authentication fails when switching between project types, use a\nclean
session)\n8.1. ES project types should have access only to Stack rules
(no\nselector)\n8.2. Observability project types should have access only
to\nObservability and Stack rules (no selector)\n8.3. Security project
types should have access only to Security and\nStack rules (selector
shows Stack instead of Observability)\n\n## References\n\nDepends on
#214187\nCloses #213061\n\n### Checklist\n\n- [x] Any text added follows
[EUI's
writing\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\nsentence case text and includes
[i18n\nsupport](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)\n-
[x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common
scenarios\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Christos Nasikas
<xristosnasikas@gmail.com>","sha":"c44efc52f62f2bb80c8cb8c288cfb40fc3164344"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
akowalska622 pushed a commit to akowalska622/kibana that referenced this pull request May 29, 2025
## Summary

Implements the alerts filters form that will be used to pre-filter the
alerts table embeddable.

<img width="1004" alt="image"
src="https://github.com/user-attachments/assets/b51ce051-40d2-42d0-a9c1-0fba3fd919af"
/>

> [!NOTE]
> I'm using the terminology "form" to distinguish this from the alert
filter _controls_ or other type of more KQL-bar-like filters. Other
alternatives that came to mind were `alerts-boolean-filters-...` or
`alerts-filters-builder`.

<details>
<summary>

## Implementation details

</summary>

### Filters expression state

I opted for a tree state representation of the form's boolean expression
to accommodate potential future requirements such as more complex
boolean expressions (negation, parenthesized subexpressions to manually
control operators precedence):

```ts
{
  operator: 'or',
  operands: [
    {
      operator: 'or',
      operands: [
        { type: 'ruleTags', value: ['tag-1'] },
        { type: 'ruleTags', value: ['tag-2'] },
        {
          operator: 'and',
          operands: [{ type: 'ruleTypes', value: ['type-1'] }, { type: 'ruleTypes', value: ['type-2'] }],
        },
      ],
    },
    { type: 'ruleTags', value: ['tag-3'] },
  ],
}
```

This state is saved in the embeddable panel state and represents the
editor form. The embeddable alerts table wrapper component will then
transform this to an actual ES query.

To simplify interactions inside the form, an intermediate equivalent
flattened state is used:

```ts
[
  { filter: { type: 'ruleTags', value: ['tag-1'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTypes', value: ['type-1'] }},
  { operator: 'and' },
  { filter: { type: 'ruleTypes', value: ['type-2'] } },
  { operator: 'or' },
  { filter: { type: 'ruleTags', value: ['tag-3'] } },
]
```

### Filters model

Each filter is described by an `AlertsFilterMetadata<T>` object, where
`T` is the type of the filter value:

```tsx
export const filterMetadata: AlertsFilterMetadata<string[]> = {
  id: 'ruleTags',
  displayName: RULE_TAGS_FILTER_LABEL,
  component: AlertsFilterByRuleTags,
  // Filter-specific empty check
  isEmpty: (value?: string[]) => !value?.length,
  // Conversion to ES query DSL
  toEsQuery: (value: string[]) => {
    return {
      terms: {
        [ALERT_RULE_TAGS]: value,
      },
    };
  },
};
```

</details>

## Verification steps

1. Run Kibana with examples (`yarn start --run-examples`)
2. Create rules in different solutions with tags
3. Navigate to `/app/triggersActionsUiExample/alerts_filters_form`
4. Check that the solution selector options are coherent with the rule
types the user can access
5. Select a solution
6. Build filters expressions, checking that the rule tags and rule types
are coherent with the solution selection and the rules created
previously
7. Repeat steps 3-6 with different roles:
7.1. having access to rule types from just one solution (in this case
the solution selector shouldn't appear at all),
7.2. having access just to Observability and Stack but not Security (in
this case the solution selector shouldn't appear at all),
8. Repeat steps 3-6 in the three serverless project types:
    ```shell
    $ yarn es serverless —ssl --projectType <es|oblt|security>
    $ yarn serverless-<es|oblt|security> --ssl --run-examples
    ```
(If the authentication fails when switching between project types, use a
clean session)
8.1. ES project types should have access only to Stack rules (no
selector)
8.2. Observability project types should have access only to
Observability and Stack rules (no selector)
8.3. Security project types should have access only to Security and
Stack rules (selector shows Stack instead of Observability)

## References

Depends on elastic#214187
Closes elastic#213061

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Christos Nasikas <xristosnasikas@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:version Backport to applied version labels release_note:skip Skip the PR/issue when compiling release notes Team:actionable-obs Formerly "obs-ux-management", responsible for SLO, o11y alerting, significant events, & synthetics. Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// v8.19.0 v9.1.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ResponseOps][Rules] Create @kbn/response-ops-rules-apis package and move relevant data fetching logic there

8 participants