From e1f7981c2eb7c9b248c90e34a5d7f1fa4a1d7df8 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Tue, 14 Jul 2026 16:37:41 +0200 Subject: [PATCH 1/7] clean up rule changes history feature flags --- .../methods/common_utils/log_rule_changes.ts | 11 ++--- .../shared/alerting/server/config.test.ts | 1 - .../plugins/shared/alerting/server/config.ts | 1 - .../plugins/shared/alerting/server/plugin.ts | 4 +- .../apis/create/create_rule_route.test.ts | 1 - .../rules_client/methods/get_rule_history.ts | 3 +- .../alerting/server/test_utils/index.ts | 1 - .../alerting_api_integration/common/config.ts | 11 ++--- .../group6/change_tracking/enabled.ts | 2 +- .../config_with_change_tracking_enabled.ts | 2 +- .../common/experimental_features.ts | 9 +--- .../pages/rule_details/index.tsx | 8 +--- .../rule_actions_overflow/index.tsx | 8 +--- .../security_solution/public/rules/routes.tsx | 7 +--- .../rule_management/api/register_routes.ts | 10 ++--- .../server/ui_settings.test.ts | 2 +- .../security_solution/server/ui_settings.ts | 41 +++++++++---------- .../queries/get_changes_history_usage.ts | 5 +-- .../server/plugin.ts | 6 +-- .../config/ess/config.base.ts | 3 -- .../config/serverless/config.base.ts | 2 - .../change_tracking.ts | 10 ++--- 22 files changed, 48 insertions(+), 100 deletions(-) diff --git a/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/common_utils/log_rule_changes.ts b/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/common_utils/log_rule_changes.ts index 2a2fb9dfa3b16..7bda5f0e84bfa 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/common_utils/log_rule_changes.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/rule/methods/common_utils/log_rule_changes.ts @@ -105,18 +105,15 @@ export async function logRuleChanges({ const ruleType = getRuleType(ruleTypeRegistry, ruleSO.attributes.alertTypeId, logger); - // "ruleType.trackChanges" is activated at Alerting plugin's "plugin.ts". - // - // The activation is gated by the feature flag "xpack.alerting.ruleChangeTracking.enabled". - // On top of that "xpack.alerting.ruleChangeTracking.scope" controls what solution rule - // types will be activated, e.g. "security" or "observability". - // + // "ruleType.trackChanges" is activated at Alerting plugin's "plugin.ts", based on + // "xpack.alerting.ruleChangeTracking.scope", which controls what solution rule + // types are activated, e.g. "security" or "observability". if (!ruleType?.trackChanges) { continue; } // Security Solution additionally gates rule changes history per-space via its - // "Enable rule changes history" advanced setting, on top of the static config flag above. + // "Enable rule changes history" advanced setting. if (ruleType.solution === 'security') { if (securityRuleChangesHistoryEnabled === undefined) { try { diff --git a/x-pack/platform/plugins/shared/alerting/server/config.test.ts b/x-pack/platform/plugins/shared/alerting/server/config.test.ts index e8134190fe09b..492006deda0d8 100644 --- a/x-pack/platform/plugins/shared/alerting/server/config.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/config.test.ts @@ -26,7 +26,6 @@ describe('config validation', () => { "removalDelay": "1h", }, "ruleChangeTracking": Object { - "enabled": true, "scope": Array [ "security", ], diff --git a/x-pack/platform/plugins/shared/alerting/server/config.ts b/x-pack/platform/plugins/shared/alerting/server/config.ts index 379f03f1f4eae..56c256f906be2 100644 --- a/x-pack/platform/plugins/shared/alerting/server/config.ts +++ b/x-pack/platform/plugins/shared/alerting/server/config.ts @@ -97,7 +97,6 @@ export const configSchema = schema.object({ coordinateInstallation: schema.boolean({ defaultValue: true }), }), ruleChangeTracking: schema.object({ - enabled: schema.boolean({ defaultValue: true }), scope: schema.arrayOf(ruleChangeTrackingSolutions, { defaultValue: ['security'] }), }), cancelAlertsOnRuleTimeout: schema.boolean({ defaultValue: true }), diff --git a/x-pack/platform/plugins/shared/alerting/server/plugin.ts b/x-pack/platform/plugins/shared/alerting/server/plugin.ts index d32862095c9d9..a5adbc8d56e47 100644 --- a/x-pack/platform/plugins/shared/alerting/server/plugin.ts +++ b/x-pack/platform/plugins/shared/alerting/server/plugin.ts @@ -281,9 +281,7 @@ export class AlertingPlugin { this.disabledRuleTypes = new Set(this.config.disabledRuleTypes || []); this.enabledRuleTypes = this.config.enabledRuleTypes != null ? new Set(this.config.enabledRuleTypes) : null; - if (this.config.ruleChangeTracking.enabled) { - this.changeTrackingService = new ChangeTrackingService(this.logger, this.kibanaVersion); - } + this.changeTrackingService = new ChangeTrackingService(this.logger, this.kibanaVersion); } public setup( diff --git a/x-pack/platform/plugins/shared/alerting/server/routes/rule/apis/create/create_rule_route.test.ts b/x-pack/platform/plugins/shared/alerting/server/routes/rule/apis/create/create_rule_route.test.ts index 59548b69b41a1..3ff3611af2b68 100644 --- a/x-pack/platform/plugins/shared/alerting/server/routes/rule/apis/create/create_rule_route.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/routes/rule/apis/create/create_rule_route.test.ts @@ -52,7 +52,6 @@ describe('createRuleRoute', () => { }, cancelAlertsOnRuleTimeout: true, ruleChangeTracking: { - enabled: false, scope: ['security'] as string[], }, rules: { diff --git a/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_rule_history.ts b/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_rule_history.ts index 62e07a73aca7c..3642bd65c429c 100644 --- a/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_rule_history.ts +++ b/x-pack/platform/plugins/shared/alerting/server/rules_client/methods/get_rule_history.ts @@ -22,8 +22,7 @@ import type { RuleChangeHistorySnapshot } from '../lib/change_tracking'; import { getRuleSo } from '../../data/rule'; /** - * Thrown by {@link RulesClient.getHistory} when rule change tracking is - * disabled at the framework level (`xpack.alerting.ruleChangeTracking.enabled = false`). + * Thrown by {@link RulesClient.getHistory} when the change tracking service is unavailable. */ export class RuleChangeTrackingDisabledError extends Error { constructor(message = 'Rule change tracking is disabled.') { diff --git a/x-pack/platform/plugins/shared/alerting/server/test_utils/index.ts b/x-pack/platform/plugins/shared/alerting/server/test_utils/index.ts index 2a70884db7092..a3ad7dc396004 100644 --- a/x-pack/platform/plugins/shared/alerting/server/test_utils/index.ts +++ b/x-pack/platform/plugins/shared/alerting/server/test_utils/index.ts @@ -63,7 +63,6 @@ export function generateAlertingConfig(overwrites: Partial = {}) coordinateInstallation: true, }, ruleChangeTracking: { - enabled: false, scope: ['security'], }, invalidateApiKeysTask: { diff --git a/x-pack/platform/test/alerting_api_integration/common/config.ts b/x-pack/platform/test/alerting_api_integration/common/config.ts index 837d88eea2341..bfd449482f1fb 100644 --- a/x-pack/platform/test/alerting_api_integration/common/config.ts +++ b/x-pack/platform/test/alerting_api_integration/common/config.ts @@ -42,7 +42,7 @@ interface CreateTestConfigOptions { maxAlerts?: number; emailMaximumBodyLength?: number; indexRefreshInterval?: string | false; - ruleChangeTrackingEnabled?: boolean; + ruleChangeTrackingScope?: string[]; } // test.not-enabled is specifically not enabled @@ -236,7 +236,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) experimentalFeatures = [], maxAlerts = 20, indexRefreshInterval, - ruleChangeTrackingEnabled = false, + ruleChangeTrackingScope, } = options; return async ({ readConfigFile }: FtrConfigProviderContext) => { @@ -332,11 +332,8 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ? [] : [`--xpack.actions.email.maximum_body_length=${options.emailMaximumBodyLength}`]; - const ruleChangeTrackingSettings = ruleChangeTrackingEnabled - ? [ - '--xpack.alerting.ruleChangeTracking.enabled=true', - `--xpack.alerting.ruleChangeTracking.scope=${JSON.stringify(['stack'])}`, - ] + const ruleChangeTrackingSettings = ruleChangeTrackingScope + ? [`--xpack.alerting.ruleChangeTracking.scope=${JSON.stringify(ruleChangeTrackingScope)}`] : []; return { diff --git a/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/change_tracking/enabled.ts b/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/change_tracking/enabled.ts index 66f12b8d58a12..027c3cce02879 100644 --- a/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/change_tracking/enabled.ts +++ b/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/change_tracking/enabled.ts @@ -14,7 +14,7 @@ export default function changeTrackingEnabledTest({ getService }: FtrProviderCon const retry = getService('retry'); describe('change tracking service - enabled', () => { - it('should create the change history data stream when ruleChangeTracking is enabled', async () => { + it('should create the change history data stream for stack-scoped rule types', async () => { const client = asKibanaClient(es); await retry.tryForTime(30_000, async () => { const response = await client.indices.getDataStream({ name: '.kibana_change_history' }); diff --git a/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/config_with_change_tracking_enabled.ts b/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/config_with_change_tracking_enabled.ts index 288359cf7e936..4743f9ffc2d37 100644 --- a/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/config_with_change_tracking_enabled.ts +++ b/x-pack/platform/test/alerting_api_integration/spaces_only/tests/alerting/group6/config_with_change_tracking_enabled.ts @@ -13,7 +13,7 @@ export default createTestConfig('spaces_only', { enableActionsProxy: false, verificationMode: 'none', useDedicatedTaskRunner: false, - ruleChangeTrackingEnabled: true, + ruleChangeTrackingScope: ['stack'], testFiles: [require.resolve('./change_tracking/enabled.ts')], reportName: 'X-Pack Alerting API Integration Tests - Change Tracking Enabled', }); diff --git a/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts b/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts index 29a31e7fe0de5..7dee1937a3e98 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts @@ -322,14 +322,9 @@ export const allowedExperimentalValues = Object.freeze({ prebuiltRulesDeprecationUIEnabled: true, /** - * Enables the Detection Rule Changes History API endpoint - * (`GET /api/detection_engine/rules/_history`). - * - * Independent of the alerting framework's `xpack.alerting.ruleChangeTracking.enabled` - * config flag, which gates the underlying primitive that produces the history - * records. Both must be enabled for the API to return non-empty results. + * Enables the Agents, Discover and Workflows external links in the classic Security Solution side navigation */ - ruleChangesHistoryEnabled: true, + securityClassicNavExternalLinks: true, /** * Enables the agent builder `run_rule_preview` tool and the `security.rule.preview` diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index d46cec84a71f3..478d3f3fff095 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -152,7 +152,6 @@ import { useManualRuleRunConfirmation } from '../../../rule_gaps/components/manu // eslint-disable-next-line no-restricted-imports import { useLegacyUrlRedirect } from './use_redirect_legacy_url'; import { RuleDetailTabs, useRuleDetailsTabs } from './use_rule_details_tabs'; -import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useRuleUpdateCallout } from '../../../rule_management/hooks/use_rule_update_callout'; import { useDeprecatedRuleDetailsCallout } from '../../../rule_management/components/rule_deprecation'; import { useUserPrivileges } from '../../../../common/components/user_privileges'; @@ -235,14 +234,9 @@ export const RuleDetailsPage = connector( clearEventsLoading, clearSelected, }: DetectionEngineComponentProps) { - const ruleChangesHistoryFFEnabled = useIsExperimentalFeatureEnabled( - 'ruleChangesHistoryEnabled' - ); - const [ruleChangesHistoryAdvancedSetting] = useUiSetting$( + const [isRuleChangesHistoryEnabled] = useUiSetting$( ENABLE_RULE_CHANGES_HISTORY_SETTING ); - const isRuleChangesHistoryEnabled = - ruleChangesHistoryFFEnabled && ruleChangesHistoryAdvancedSetting; const { application, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_actions_overflow/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_actions_overflow/index.tsx index f3b9e938fbf8c..f228b07925fc7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_actions_overflow/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/rule_actions_overflow/index.tsx @@ -28,7 +28,6 @@ import { getRuleChangesHistoryUrl, } from '../../../../../common/components/link_to/redirect_to_detection_engine'; import { useBoolState } from '../../../../../common/hooks/use_bool_state'; -import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import { SINGLE_RULE_ACTIONS } from '../../../../../common/lib/apm/user_actions'; import { useStartTransaction } from '../../../../../common/lib/apm/use_start_transaction'; import { useKibana, useUiSetting$ } from '../../../../../common/lib/kibana'; @@ -106,12 +105,7 @@ const RuleActionsOverflowComponent = ({ state: { doesBaseVersionExist }, } = useRuleCustomizationsContext(); - const ruleChangesHistoryFFEnabled = useIsExperimentalFeatureEnabled('ruleChangesHistoryEnabled'); - const [ruleChangesHistoryAdvancedSetting] = useUiSetting$( - ENABLE_RULE_CHANGES_HISTORY_SETTING - ); - const isRuleChangesHistoryEnabled = - ruleChangesHistoryFFEnabled && ruleChangesHistoryAdvancedSetting; + const [isRuleChangesHistoryEnabled] = useUiSetting$(ENABLE_RULE_CHANGES_HISTORY_SETTING); const actions = useMemo( () => [ diff --git a/x-pack/solutions/security/plugins/security_solution/public/rules/routes.tsx b/x-pack/solutions/security/plugins/security_solution/public/rules/routes.tsx index 25f4594b60912..294665b83de16 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/rules/routes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/rules/routes.tsx @@ -202,12 +202,7 @@ const RulesContainerComponent: React.FC = () => { const isEndpointExceptionsMovedFFEnabled = useIsExperimentalFeatureEnabled( 'endpointExceptionsMovedUnderManagement' ); - const ruleChangesHistoryFFEnabled = useIsExperimentalFeatureEnabled('ruleChangesHistoryEnabled'); - const [ruleChangesHistoryAdvancedSetting] = useUiSetting$( - ENABLE_RULE_CHANGES_HISTORY_SETTING - ); - const isRuleChangesHistoryEnabled = - ruleChangesHistoryFFEnabled && ruleChangesHistoryAdvancedSetting; + const [isRuleChangesHistoryEnabled] = useUiSetting$(ENABLE_RULE_CHANGES_HISTORY_SETTING); const subRoutes = useMemo(() => { return getRulesSubRoutes(capabilities, { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts index 436e31bbc5350..edc14d01d1ac2 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_management/api/register_routes.ts @@ -59,11 +59,7 @@ export const registerRuleManagementRoutes = ( // Rules coverage overview getCoverageOverviewRoute(router); - // Rule changes history (gated by experimental flag; the feature also - // requires `xpack.alerting.ruleChangeTracking.enabled` to be on for the - // alerting framework to actually produce history records). - if (config.experimentalFeatures.ruleChangesHistoryEnabled) { - ruleHistoryRoute(router); - restoreRuleFromHistoryRoute(router); - } + // Rule changes history + ruleHistoryRoute(router); + restoreRuleFromHistoryRoute(router); }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts b/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts index 656a7b6c626a7..0ac59f451a613 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts @@ -27,7 +27,7 @@ describe('initUiSettings', () => { const mockExperimentalFeatures = { enableAlertsAndAttacksAlignment: false, extendedRuleExecutionLoggingEnabled: false, - newFlyoutSystemDisabled: false, + newFlyoutSystemEnabled: false, ruleChangesHistoryEnabled: false, } as ExperimentalFeatures; diff --git a/x-pack/solutions/security/plugins/security_solution/server/ui_settings.ts b/x-pack/solutions/security/plugins/security_solution/server/ui_settings.ts index 08d6585b22b6a..a6f8b9be7597e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/ui_settings.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/ui_settings.ts @@ -416,28 +416,25 @@ export const initUiSettings = ( solutionViews: ['classic', 'security'], }, }), - // TODO(rule-changes-history GA): remove this setting and its call sites (including alerting `log_rule_changes.ts`) - ...(experimentalFeatures.ruleChangesHistoryEnabled && { - [ENABLE_RULE_CHANGES_HISTORY_SETTING]: { - name: i18n.translate('xpack.securitySolution.uiSettings.enableRuleChangesHistoryLabel', { - defaultMessage: 'Enable detection rule changes history', - }), - description: i18n.translate( - 'xpack.securitySolution.uiSettings.enableRuleChangesHistoryDescription', - { - defaultMessage: - '

Enables the detection rule changes history feature within Security Solution.

', - values: { p: (chunks) => `

${chunks}

` }, - } - ), - type: 'boolean', - value: true, - category: [APP_ID], - requiresPageReload: true, - schema: schema.boolean(), - solutionViews: ['classic', 'security'], - }, - }), + [ENABLE_RULE_CHANGES_HISTORY_SETTING]: { + name: i18n.translate('xpack.securitySolution.uiSettings.enableRuleChangesHistoryLabel', { + defaultMessage: 'Enable detection rule changes history', + }), + description: i18n.translate( + 'xpack.securitySolution.uiSettings.enableRuleChangesHistoryDescription', + { + defaultMessage: + '

Enables the detection rule changes history feature within Security Solution.

', + values: { p: (chunks) => `

${chunks}

` }, + } + ), + type: 'boolean', + value: true, + category: [APP_ID], + requiresPageReload: true, + schema: schema.boolean(), + solutionViews: ['classic', 'security'], + }, [NEWS_FEED_URL_SETTING]: { name: i18n.translate('xpack.securitySolution.uiSettings.newsFeedUrl', { defaultMessage: 'News feed URL', diff --git a/x-pack/solutions/security/plugins/security_solution/server/usage/queries/get_changes_history_usage.ts b/x-pack/solutions/security/plugins/security_solution/server/usage/queries/get_changes_history_usage.ts index 8e85041ca1ddb..f0f65c9122c04 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/usage/queries/get_changes_history_usage.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/usage/queries/get_changes_history_usage.ts @@ -44,9 +44,8 @@ interface ChangesHistoryUsageAggs { * window, aggregated from the `.kibana_change_history` data stream. * * Degrades to `{ revision_saved: 0, rule_restored: 0 }` (never throws) on - * any ES error, including `index_not_found_exception` when - * `xpack.alerting.ruleChangeTracking.enabled` is disabled (the default) and - * the data stream does not exist. The catch is local so a missing index + * any ES error, including `index_not_found_exception` when the + * `.kibana_change_history` data stream does not exist yet. The catch is local so a missing index * only zeros these two fields, never the whole `detection_rules` metrics * group. * @param esClient the elastic client which should be a system based client diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/server/plugin.ts b/x-pack/solutions/security/plugins/security_solution_serverless/server/plugin.ts index d092417968837..cf437b29ba7f8 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/server/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_serverless/server/plugin.ts @@ -128,11 +128,7 @@ export class SecuritySolutionServerlessPlugin projectSettings.push(ENABLE_ALERTS_AND_ATTACKS_ALIGNMENT_SETTING); } - // TODO(rule-changes-history GA): remove this block when the feature is GA - // This setting is only registered when `ruleChangesHistoryEnabled` is enabled - if (this.config.experimentalFeatures.ruleChangesHistoryEnabled) { - projectSettings.push('securitySolution:enableRuleChangesHistory'); - } + projectSettings.push('securitySolution:enableRuleChangesHistory'); // Workflows is enabled by default since 9.4.0. The setting is retained so admins can opt out. // It is only registered in complete and EASE tiers; adding it while in the essentials tier causes an error. diff --git a/x-pack/solutions/security/test/security_solution_api_integration/config/ess/config.base.ts b/x-pack/solutions/security/test/security_solution_api_integration/config/ess/config.base.ts index b09dc4d53dc83..17d6ff90a4465 100644 --- a/x-pack/solutions/security/test/security_solution_api_integration/config/ess/config.base.ts +++ b/x-pack/solutions/security/test/security_solution_api_integration/config/ess/config.base.ts @@ -109,10 +109,7 @@ export function createTestConfig(options: CreateTestConfigOptions, testFiles?: s `--xpack.securitySolution.enableExperimental=${JSON.stringify([ 'previewTelemetryUrlEnabled', 'endpointExceptionsMovedUnderManagement', - 'ruleChangesHistoryEnabled', ])}`, - '--xpack.alerting.ruleChangeTracking.enabled=true', - '--uiSettings.overrides.securitySolution:enableRuleChangesHistory=true', `--plugin-path=${path.resolve( __dirname, '../../../../../../../src/platform/test/analytics/plugins/analytics_ftr_helpers' diff --git a/x-pack/solutions/security/test/security_solution_api_integration/config/serverless/config.base.ts b/x-pack/solutions/security/test/security_solution_api_integration/config/serverless/config.base.ts index 6dc20ff730907..07b383ec5aca2 100644 --- a/x-pack/solutions/security/test/security_solution_api_integration/config/serverless/config.base.ts +++ b/x-pack/solutions/security/test/security_solution_api_integration/config/serverless/config.base.ts @@ -60,9 +60,7 @@ export function createTestConfig(options: CreateTestConfigOptions) { `--xpack.fleet.internal.skipUploadPackageValidation=true`, `--xpack.securitySolution.enableExperimental=${JSON.stringify([ 'endpointExceptionsMovedUnderManagement', - 'ruleChangesHistoryEnabled', ])}`, - '--xpack.alerting.ruleChangeTracking.enabled=true', ...(options.kbnTestServerArgs || []), `--plugin-path=${path.resolve( __dirname, diff --git a/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts b/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts index 3ea1d551840a2..421c9998168e0 100644 --- a/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts +++ b/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts @@ -35,11 +35,9 @@ export default ({ getService }: FtrProviderContext): void => { const detectionsApi = getService('detectionsApi'); const es = getService('es'); const log = getService('log'); + const utils = getService('securitySolutionUtils'); - // Skip in Serverless until "xpack.alerting.ruleChangeTracking.enabled" and - // xpack.securitySolution.enableExperimental: [ruleChangesHistoryEnabled] feature flags - // permanently enabled - describe('@ess @skipInServerless rule change history', () => { + describe('@ess @serverless rule change history', () => { beforeEach(async () => { await deleteAllRules(supertest, log); await deleteAllPrebuiltRuleAssets(es, log); @@ -63,9 +61,11 @@ export default ({ getService }: FtrProviderContext): void => { expect(body.total).toBe(1); expect(body.items).toHaveLength(1); + const username = await utils.getUsername(); + const [item] = body.items; expect(item.action).toBe('rule_create'); - expect(item.user).toEqual({ name: 'elastic' }); + expect(item.user).toEqual({ name: username }); expect(item.rule).toMatchObject({ id: rule.id, revision: 0 }); expect(item.old_values).toBeNull(); }); From 57bd80603ea4ab504efbfab6bcac2e348e8c06a9 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Wed, 15 Jul 2026 10:51:37 +0200 Subject: [PATCH 2/7] remove kbn-change-history package FLAGS --- .../platform/packages/shared/kbn-change-history/index.ts | 5 ----- .../kbn-change-history/integration_tests/client.test.ts | 3 --- .../packages/shared/kbn-change-history/src/client.test.ts | 4 +--- .../packages/shared/kbn-change-history/src/client.ts | 7 +------ .../packages/shared/kbn-change-history/src/constants.ts | 8 -------- .../common/plugins/alerts/server/plugin.ts | 5 ----- 6 files changed, 2 insertions(+), 30 deletions(-) diff --git a/x-pack/platform/packages/shared/kbn-change-history/index.ts b/x-pack/platform/packages/shared/kbn-change-history/index.ts index d8256ece40ad4..de578fff5d76c 100644 --- a/x-pack/platform/packages/shared/kbn-change-history/index.ts +++ b/x-pack/platform/packages/shared/kbn-change-history/index.ts @@ -9,8 +9,3 @@ export type * from './src/types'; export * from './src/client'; export { CHANGE_HISTORY_AGGREGATE_FIELDS, LEGACY_CHANGE_HISTORY_ACTION_IDS } from './src/types'; export { DEFAULT_FIELD_AGGREGATION_SIZE } from './src/constants'; -/** - * @internal exported for test use only — do NOT use in production code, - * this could cause the index to be created before the feature is ready for GA - */ -export { FLAGS } from './src/constants'; diff --git a/x-pack/platform/packages/shared/kbn-change-history/integration_tests/client.test.ts b/x-pack/platform/packages/shared/kbn-change-history/integration_tests/client.test.ts index b45c4dbf18496..2062a91141134 100644 --- a/x-pack/platform/packages/shared/kbn-change-history/integration_tests/client.test.ts +++ b/x-pack/platform/packages/shared/kbn-change-history/integration_tests/client.test.ts @@ -10,7 +10,6 @@ import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { ToolingLog } from '@kbn/tooling-log'; import type { EsTestCluster } from '@kbn/test'; import { createTestEsCluster } from '@kbn/test'; -import { FLAGS } from '../src/constants'; import { ChangeHistoryClient } from '..'; import { DATA_STREAM_NAME } from '../src/client'; import type { LogChangeHistoryOptions, ObjectChange } from '..'; @@ -47,7 +46,6 @@ describe('ChangeHistoryClient', () => { }; beforeAll(async () => { - FLAGS.FEATURE_ENABLED = true; jest.setTimeout(30_000); esServer = createTestEsCluster({ log: new ToolingLog({ writeTo: process.stdout, level: 'debug' }), @@ -58,7 +56,6 @@ describe('ChangeHistoryClient', () => { afterAll(async () => { await esServer.stop(); - FLAGS.FEATURE_ENABLED = false; }); afterEach(async () => { diff --git a/x-pack/platform/packages/shared/kbn-change-history/src/client.test.ts b/x-pack/platform/packages/shared/kbn-change-history/src/client.test.ts index d30b3df6fb3ba..58a89a29374c0 100644 --- a/x-pack/platform/packages/shared/kbn-change-history/src/client.test.ts +++ b/x-pack/platform/packages/shared/kbn-change-history/src/client.test.ts @@ -9,7 +9,6 @@ import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { DataStreamClient } from '@kbn/data-streams'; import { withSpan } from '@kbn/apm-utils'; -import { FLAGS } from './constants'; import { ChangeHistoryClient } from './client'; import type { ObjectChange } from './types'; @@ -48,7 +47,6 @@ describe('ChangeHistoryClient', () => { }; beforeEach(() => { - FLAGS.FEATURE_ENABLED = true; DataStreamClientMock.initialize.mockResolvedValue(dataStreamClientMock as never); }); @@ -435,7 +433,7 @@ describe('ChangeHistoryClient.logBulk', () => { }; beforeEach(() => { - FLAGS.FEATURE_ENABLED = true; + DataStreamClientMock.initialize.mockResolvedValue({} as never); }); afterEach(() => { diff --git a/x-pack/platform/packages/shared/kbn-change-history/src/client.ts b/x-pack/platform/packages/shared/kbn-change-history/src/client.ts index 9ba70cae9de60..ab3f036235ce0 100644 --- a/x-pack/platform/packages/shared/kbn-change-history/src/client.ts +++ b/x-pack/platform/packages/shared/kbn-change-history/src/client.ts @@ -19,13 +19,13 @@ import type { ClientCreateRequest } from '@kbn/data-streams/src/types/es_api'; import type { Logger } from '@kbn/logging'; import { changeHistoryMappings } from './mappings'; import { - FLAGS, DATA_STREAM_NAME, SEPARATOR_CHAR, ECS_VERSION, DEFAULT_RESULT_SIZE, DEFAULT_FIELD_AGGREGATION_SIZE, } from './constants'; +import { DATA_STREAM_NAME, SEPARATOR_CHAR, ECS_VERSION, DEFAULT_RESULT_SIZE } from './constants'; import type { ChangeHistoryAggregateField, ChangeHistoryDocument, @@ -116,11 +116,6 @@ export class ChangeHistoryClient implements IChangeHistoryClient { * @throws An error if the data stream is not initialized properly. */ async initialize(elasticsearchClient: ElasticsearchClient) { - if (!FLAGS.FEATURE_ENABLED) { - const error = new Error(`Change history is disabled. Skipping initialization.`); - this.logger.error(error); - throw error; - } const definition: DataStreamDefinition = { name: DATA_STREAM_NAME, diff --git a/x-pack/platform/packages/shared/kbn-change-history/src/constants.ts b/x-pack/platform/packages/shared/kbn-change-history/src/constants.ts index 85391cfae0c5a..90abbf8b211ee 100644 --- a/x-pack/platform/packages/shared/kbn-change-history/src/constants.ts +++ b/x-pack/platform/packages/shared/kbn-change-history/src/constants.ts @@ -26,11 +26,3 @@ export const DEFAULT_RESULT_SIZE = 100; * Default maximum number of buckets returned per field by {@link ChangeHistoryClient.getHistoryByFields}. */ export const DEFAULT_FIELD_AGGREGATION_SIZE = 100; - -/** - * Acts like a feature flag for this package as it prevents initialization. - * Remove this after General Availability - * */ -export const FLAGS = { - FEATURE_ENABLED: true, -}; diff --git a/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts b/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts index 79c711a53c10e..64f6a9b02b6fb 100644 --- a/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts +++ b/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/server/plugin.ts @@ -30,7 +30,6 @@ import type { IEventLogClientService, IEventLogService } from '@kbn/event-log-pl import type { NotificationsPluginStart } from '@kbn/notifications-plugin/server'; import { RULE_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server'; import { ALERTING_FEATURE_ID } from '@kbn/alerting-plugin/common'; -import { FLAGS as CHANGE_HISTORY_FLAGS } from '@kbn/change-history'; import { defineRoutes } from './routes'; import { defineActionTypes } from './action_types'; import { defineRuleTypes } from './rule_types'; @@ -112,7 +111,6 @@ export class FixturePlugin implements Plugin, { features, actions, alerting, taskManager, ruleRegistry, eventLog }: FixtureSetupDeps ) { - CHANGE_HISTORY_FLAGS.FEATURE_ENABLED = true; features.registerKibanaFeature({ id: 'alertsFixture', name: 'Alerts', @@ -228,7 +226,4 @@ export class FixturePlugin implements Plugin Date: Wed, 15 Jul 2026 14:13:52 +0200 Subject: [PATCH 3/7] remove accidentally introduced feature flag --- .../security_solution/common/experimental_features.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts b/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts index 7dee1937a3e98..36323c7109a84 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts @@ -321,11 +321,6 @@ export const allowedExperimentalValues = Object.freeze({ */ prebuiltRulesDeprecationUIEnabled: true, - /** - * Enables the Agents, Discover and Workflows external links in the classic Security Solution side navigation - */ - securityClassicNavExternalLinks: true, - /** * Enables the agent builder `run_rule_preview` tool and the `security.rule.preview` * attachment (server type + client renderer). Gates registration so the feature can From 5b2533e64f6eb000629189e35fde9b39685b2265 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Wed, 15 Jul 2026 14:16:58 +0200 Subject: [PATCH 4/7] auto-fix configs --- .../alerting_api_integration/common/plugins/alerts/moon.yml | 1 - .../common/plugins/alerts/tsconfig.json | 1 - .../plugins/security_solution/server/ui_settings.test.ts | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/moon.yml b/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/moon.yml index 96358295e3e03..5f7aa37164728 100644 --- a/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/moon.yml +++ b/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/moon.yml @@ -35,7 +35,6 @@ dependsOn: - '@kbn/alerts-as-data-utils' - '@kbn/data-plugin' - '@kbn/zod' - - '@kbn/change-history' tags: - plugin - prod diff --git a/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/tsconfig.json b/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/tsconfig.json index 3eb4f142feae0..5d18f4412763a 100644 --- a/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/tsconfig.json +++ b/x-pack/platform/test/alerting_api_integration/common/plugins/alerts/tsconfig.json @@ -28,7 +28,6 @@ "@kbn/alerts-as-data-utils", "@kbn/data-plugin", "@kbn/zod", - "@kbn/change-history", ], "exclude": [ "target/**/*", diff --git a/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts b/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts index 0ac59f451a613..e1160bf05385d 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/ui_settings.test.ts @@ -27,8 +27,7 @@ describe('initUiSettings', () => { const mockExperimentalFeatures = { enableAlertsAndAttacksAlignment: false, extendedRuleExecutionLoggingEnabled: false, - newFlyoutSystemEnabled: false, - ruleChangesHistoryEnabled: false, + newFlyoutSystemDisabled: false, } as ExperimentalFeatures; beforeEach(() => { From a4b849de50b131547aff8120846e7bead8e55623 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Fri, 11 Sep 2026 18:11:54 +0200 Subject: [PATCH 5/7] clean up conflict resolving artifacts --- x-pack/platform/packages/shared/kbn-change-history/src/client.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/platform/packages/shared/kbn-change-history/src/client.ts b/x-pack/platform/packages/shared/kbn-change-history/src/client.ts index ab3f036235ce0..1b0507537a8bd 100644 --- a/x-pack/platform/packages/shared/kbn-change-history/src/client.ts +++ b/x-pack/platform/packages/shared/kbn-change-history/src/client.ts @@ -25,7 +25,6 @@ import { DEFAULT_RESULT_SIZE, DEFAULT_FIELD_AGGREGATION_SIZE, } from './constants'; -import { DATA_STREAM_NAME, SEPARATOR_CHAR, ECS_VERSION, DEFAULT_RESULT_SIZE } from './constants'; import type { ChangeHistoryAggregateField, ChangeHistoryDocument, From fb36b49e6a36c2b8f7c02381faec5aade1332edb Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Fri, 11 Sep 2026 18:35:01 +0200 Subject: [PATCH 6/7] register ruleChangeTracking.enabled as deprecated --- .../alerting/server/config_deprecations.test.ts | 17 +++++++++++++++++ .../alerting/server/config_deprecations.ts | 2 ++ 2 files changed, 19 insertions(+) diff --git a/x-pack/platform/plugins/shared/alerting/server/config_deprecations.test.ts b/x-pack/platform/plugins/shared/alerting/server/config_deprecations.test.ts index b735e77766dec..78f8e329d25cf 100644 --- a/x-pack/platform/plugins/shared/alerting/server/config_deprecations.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/config_deprecations.test.ts @@ -33,6 +33,23 @@ const applyConfigDeprecations = (settings = {}) => { }; describe('config deprecations', () => { + it('removes xpack.alerting.ruleChangeTracking.enabled', async () => { + const config = { + ruleChangeTracking: { + enabled: false, + scope: ['security'], + }, + }; + const { messages, migrated } = applyConfigDeprecations(cloneDeep(config)); + expect(migrated.ruleChangeTracking?.enabled).not.toBeDefined(); + expect(migrated.ruleChangeTracking?.scope).toEqual(['security']); + expect(messages).toMatchInlineSnapshot(` + Array [ + "You no longer need to configure \\"ruleChangeTracking.enabled\\".", + ] + `); + }); + it('renames xpack.alerting.maintenanceWindow.enabled to xpack.maintenanceWindows.enabled', async () => { const config = { xpack: { diff --git a/x-pack/platform/plugins/shared/alerting/server/config_deprecations.ts b/x-pack/platform/plugins/shared/alerting/server/config_deprecations.ts index 7205dbd164932..ce470a62e44d4 100644 --- a/x-pack/platform/plugins/shared/alerting/server/config_deprecations.ts +++ b/x-pack/platform/plugins/shared/alerting/server/config_deprecations.ts @@ -10,7 +10,9 @@ import type { ConfigDeprecationProvider } from '@kbn/core/server'; export const autocompleteConfigDeprecationProvider: ConfigDeprecationProvider = ({ renameFromRoot, deprecate, + unused, }) => [ + unused('ruleChangeTracking.enabled', { level: 'warning' }), deprecate('maxEphemeralActionsPerAlert', '9.0.0', { level: 'warning', message: `The setting "xpack.alerting.maxEphemeralActionsPerAlert" is deprecated and currently ignored by the system. Please remove this setting.`, From 2ea712aa2f4c59a80f0e5be936794c5680a18f49 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Fri, 11 Sep 2026 22:48:22 +0200 Subject: [PATCH 7/7] fix failing tests --- .../trial_license_complete_tier/change_tracking.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts b/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts index 421c9998168e0..773558e7f2b94 100644 --- a/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts +++ b/x-pack/solutions/security/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_management/trial_license_complete_tier/change_tracking.ts @@ -294,9 +294,11 @@ export default ({ getService }: FtrProviderContext): void => { expect(body.items).toHaveLength(1); + const username = await utils.getUsername(); + const [item] = body.items; expect(item.action).toBe('rule_import'); - expect(item.user).toEqual({ name: 'elastic' }); + expect(item.user).toEqual({ name: username }); expect(item.old_values).toBeNull(); expect(item.metadata?.bulk_count).toBe(1); expect(item.rule).toMatchObject({ @@ -347,9 +349,11 @@ export default ({ getService }: FtrProviderContext): void => { expect(body.items).toHaveLength(1); + const username = await utils.getUsername(); + const [item] = body.items; expect(item.action).toBe('rule_import'); - expect(item.user).toEqual({ name: 'elastic' }); + expect(item.user).toEqual({ name: username }); expect(item.old_values).toBeNull(); expect(item.metadata?.bulk_count).toBe(1); expect(item.rule).toMatchObject({ @@ -403,9 +407,11 @@ export default ({ getService }: FtrProviderContext): void => { expect(body.total).toBe(2); expect(body.items).toHaveLength(2); + const username = await utils.getUsername(); + const [imported, created] = body.items; expect(imported.action).toBe('rule_import'); - expect(imported.user).toEqual({ name: 'elastic' }); + expect(imported.user).toEqual({ name: username }); expect(imported.metadata?.bulk_count).toBe(1); expect(imported.rule).toMatchObject({ id: rule.id,