-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(security): extend Feature
definition to support explicit feature replacements
#206660
feat(security): extend Feature
definition to support explicit feature replacements
#206660
Conversation
* `replacedBy` fields of the feature privileges. However, if the feature privileges are replaced by the privileges | ||
* of multiple features, this behavior is not always desired and can be overridden here. | ||
*/ | ||
replacedBy?: readonly string[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: I couldn't come up with a better name to describe what it's for, but open to suggestions...
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
|
/** | ||
* Describes parameters used to retrieve all Kibana features (for public consumers). | ||
*/ | ||
export interface GetKibanaFeaturesParams { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: Due to the way the start contract of the Feature plugin was defined, it was technically possible to pass any arguments to the getKibanaFeatures
method, even though this was not reflected in the type definition:
getKibanaFeatures: this.featureRegistry.getAllKibanaFeatures.bind(this.featureRegistry),
This change explicitly defines the list of accepted arguments, ensuring that only omitDeprecated
is exposed publicly:
getKibanaFeatures: (params) => this.featureRegistry.getAllKibanaFeatures(
params && { omitDeprecated: params.omitDeprecated }
),
@@ -106,7 +106,10 @@ export function initSpacesOnPostAuthRequestInterceptor({ | |||
} | |||
} | |||
|
|||
const allFeatures = features.getKibanaFeatures(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: getKibanaFeatures
in setup
contract is deprecated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Core changes LGTM. Code review only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! tested and synced with @azasypkin about the changes.
@elasticmachine merge upstream |
Starting backport for target branches: 8.x |
…re replacements (elastic#206660) ## Summary Today, when a developer deprecates a feature and replaces its privileges with those of another feature, we reasonably assume that the new feature fully replaces the old one in all possible contexts - whether in role management UIs or in the Spaces feature toggles visibility UI. However, when deprecated privileges are replaced by the privileges of multiple features, such as in [this case](elastic#202863 (comment)) where the Discover/Dashboard/Maps feature privileges are replaced by the privileges of Discover_v2/Dashboard_v2/Maps_v2, respectively, **and** the privileges of the Saved Query Management feature, the choice is ambiguous. Which of these features should be treated as the replacement for the deprecated feature in contexts that deal with entire features (like the Spaces feature toggles visibility UI) rather than individual privileges (like in role management UIs)? Should all referenced features be considered replacements? Or just a subset - or even a single feature? If so, which one? Currently, we treat all referenced features as replacements for the deprecated feature, which creates problems, as described in detail in [this discussion](elastic#202863 (comment)). This PR allows developers to customize this behavior by specifying which features Kibana should treat as direct successors to deprecated features in contexts that deal with whole features rather than individual privileges: ```ts deps.features.registerKibanaFeature({ deprecated: { notice: 'The feature is deprecated because … well, there’s a reason.', --> replacedBy: ['feature_id_v2'], <-- }, id: 'feature_id' name: `Case elastic#4 feature ${suffix} (DEPRECATED)`, … }); ``` ## How to test 1. Run test server ```bash node scripts/functional_tests_server.js --config x-pack/test/security_api_integration/features.config.ts ``` 2. Execute the following request from the Dev Tools (`case_4_feature_a` is a deprecated feature that is replaced by multiple features and **doesn't use** `deprecated.replacedBy`) ```http PUT kbn:/api/spaces/space/default?overwrite=true { "id":"default", "name":"Default", "description":"This is your default space!", "color":"#00bfb3", "disabledFeatures":["case_4_feature_a"], "_reserved":true, "imageUrl":"", "initials":"D" } ``` 3. Observe that in response deprecated `case_4_feature_a` is replaced by two features (you can also check http://localhost:5620/app/management/kibana/spaces/edit/default to see how it's reflected in UI) ```http { "id": "default", "name": "Default", "description": "This is your default space!", "color": "#00bfb3", "initials": "D", "imageUrl": "", "disabledFeatures": [ "case_4_feature_a_v2", "case_4_feature_c" ], "_reserved": true } ``` 4. Execute the following request from the Dev Tools (`case_4_feature_b` is a deprecated feature that is replaced by multiple features, but **uses** `deprecated.replacedBy` to set the conceptual feature-successor) ```http PUT kbn:/api/spaces/space/default?overwrite=true { "id":"default", "name":"Default", "description":"This is your default space!", "color":"#00bfb3", "disabledFeatures":["case_4_feature_b"], "_reserved":true, "imageUrl":"", "initials":"D" } ``` 5. Observe that in response deprecated `case_4_feature_b` is replaced by a single feature (you can also check http://localhost:5620/app/management/kibana/spaces/edit/default to see how it's reflected in UI) ```http { "id": "default", "name": "Default", "description": "This is your default space!", "color": "#00bfb3", "initials": "D", "imageUrl": "", "disabledFeatures": [ "case_4_feature_b_v2" ], "_reserved": true } ``` __Required by:__ elastic#202863 (comment) //cc @davismcphee (cherry picked from commit dd3ce0e)
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
…t explicit feature replacements (#206660) (#206925) # Backport This will backport the following commits from `main` to `8.x`: - [feat(security): extend `Feature` definition to support explicit feature replacements (#206660)](#206660) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Aleh Zasypkin","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-01-16T11:35:32Z","message":"feat(security): extend `Feature` definition to support explicit feature replacements (#206660)\n\n## Summary\n\nToday, when a developer deprecates a feature and replaces its privileges\nwith those of another feature, we reasonably assume that the new feature\nfully replaces the old one in all possible contexts - whether in role\nmanagement UIs or in the Spaces feature toggles visibility UI. However,\nwhen deprecated privileges are replaced by the privileges of multiple\nfeatures, such as in [this\ncase](https://github.com/elastic/kibana/pull/202863#discussion_r1892672114)\nwhere the Discover/Dashboard/Maps feature privileges are replaced by the\nprivileges of Discover_v2/Dashboard_v2/Maps_v2, respectively, **and**\nthe privileges of the Saved Query Management feature, the choice is\nambiguous.\n\nWhich of these features should be treated as the replacement for the\ndeprecated feature in contexts that deal with entire features (like the\nSpaces feature toggles visibility UI) rather than individual privileges\n(like in role management UIs)? Should all referenced features be\nconsidered replacements? Or just a subset - or even a single feature? If\nso, which one? Currently, we treat all referenced features as\nreplacements for the deprecated feature, which creates problems, as\ndescribed in detail in [this\ndiscussion](https://github.com/elastic/kibana/pull/202863#discussion_r1892672114).\n\nThis PR allows developers to customize this behavior by specifying which\nfeatures Kibana should treat as direct successors to deprecated features\nin contexts that deal with whole features rather than individual\nprivileges:\n\n```ts\ndeps.features.registerKibanaFeature({\n deprecated: {\n notice: 'The feature is deprecated because … well, there’s a reason.',\n --> replacedBy: ['feature_id_v2'], <--\n },\n id: 'feature_id'\n name: `Case #4 feature ${suffix} (DEPRECATED)`,\n …\n});\n```\n\n## How to test\n\n1. Run test server\n```bash\nnode scripts/functional_tests_server.js --config x-pack/test/security_api_integration/features.config.ts\n```\n\n2. Execute the following request from the Dev Tools (`case_4_feature_a`\nis a deprecated feature that is replaced by multiple features and\n**doesn't use** `deprecated.replacedBy`)\n```http\nPUT kbn:/api/spaces/space/default?overwrite=true\n{\n \"id\":\"default\",\n \"name\":\"Default\",\n \"description\":\"This is your default space!\",\n \"color\":\"#00bfb3\",\n \"disabledFeatures\":[\"case_4_feature_a\"],\n \"_reserved\":true,\n \"imageUrl\":\"\",\n \"initials\":\"D\"\n}\n```\n\n3. Observe that in response deprecated `case_4_feature_a` is replaced by\ntwo features (you can also check\nhttp://localhost:5620/app/management/kibana/spaces/edit/default to see\nhow it's reflected in UI)\n```http\n{\n \"id\": \"default\",\n \"name\": \"Default\",\n \"description\": \"This is your default space!\",\n \"color\": \"#00bfb3\",\n \"initials\": \"D\",\n \"imageUrl\": \"\",\n \"disabledFeatures\": [\n \"case_4_feature_a_v2\",\n \"case_4_feature_c\"\n ],\n \"_reserved\": true\n}\n```\n\n4. Execute the following request from the Dev Tools (`case_4_feature_b`\nis a deprecated feature that is replaced by multiple features, but\n**uses** `deprecated.replacedBy` to set the conceptual\nfeature-successor)\n```http\nPUT kbn:/api/spaces/space/default?overwrite=true\n{\n \"id\":\"default\",\n \"name\":\"Default\",\n \"description\":\"This is your default space!\",\n \"color\":\"#00bfb3\",\n \"disabledFeatures\":[\"case_4_feature_b\"],\n \"_reserved\":true,\n \"imageUrl\":\"\",\n \"initials\":\"D\"\n}\n```\n\n5. Observe that in response deprecated `case_4_feature_b` is replaced by\na single feature (you can also check\nhttp://localhost:5620/app/management/kibana/spaces/edit/default to see\nhow it's reflected in UI)\n```http\n{\n \"id\": \"default\",\n \"name\": \"Default\",\n \"description\": \"This is your default space!\",\n \"color\": \"#00bfb3\",\n \"initials\": \"D\",\n \"imageUrl\": \"\",\n \"disabledFeatures\": [\n \"case_4_feature_b_v2\"\n ],\n \"_reserved\": true\n}\n```\n\n__Required by:__\nhttps://github.com//pull/202863#discussion_r1892672114\n\n//cc @davismcphee","sha":"dd3ce0e7f534279f48be8c125853c89aa92969e2","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:Security/Spaces","release_note:skip","Feature:Security/Authorization","v9.0.0","backport:prev-minor"],"title":"feat(security): extend `Feature` definition to support explicit feature replacements","number":206660,"url":"https://github.com/elastic/kibana/pull/206660","mergeCommit":{"message":"feat(security): extend `Feature` definition to support explicit feature replacements (#206660)\n\n## Summary\n\nToday, when a developer deprecates a feature and replaces its privileges\nwith those of another feature, we reasonably assume that the new feature\nfully replaces the old one in all possible contexts - whether in role\nmanagement UIs or in the Spaces feature toggles visibility UI. However,\nwhen deprecated privileges are replaced by the privileges of multiple\nfeatures, such as in [this\ncase](https://github.com/elastic/kibana/pull/202863#discussion_r1892672114)\nwhere the Discover/Dashboard/Maps feature privileges are replaced by the\nprivileges of Discover_v2/Dashboard_v2/Maps_v2, respectively, **and**\nthe privileges of the Saved Query Management feature, the choice is\nambiguous.\n\nWhich of these features should be treated as the replacement for the\ndeprecated feature in contexts that deal with entire features (like the\nSpaces feature toggles visibility UI) rather than individual privileges\n(like in role management UIs)? Should all referenced features be\nconsidered replacements? Or just a subset - or even a single feature? If\nso, which one? Currently, we treat all referenced features as\nreplacements for the deprecated feature, which creates problems, as\ndescribed in detail in [this\ndiscussion](https://github.com/elastic/kibana/pull/202863#discussion_r1892672114).\n\nThis PR allows developers to customize this behavior by specifying which\nfeatures Kibana should treat as direct successors to deprecated features\nin contexts that deal with whole features rather than individual\nprivileges:\n\n```ts\ndeps.features.registerKibanaFeature({\n deprecated: {\n notice: 'The feature is deprecated because … well, there’s a reason.',\n --> replacedBy: ['feature_id_v2'], <--\n },\n id: 'feature_id'\n name: `Case #4 feature ${suffix} (DEPRECATED)`,\n …\n});\n```\n\n## How to test\n\n1. Run test server\n```bash\nnode scripts/functional_tests_server.js --config x-pack/test/security_api_integration/features.config.ts\n```\n\n2. Execute the following request from the Dev Tools (`case_4_feature_a`\nis a deprecated feature that is replaced by multiple features and\n**doesn't use** `deprecated.replacedBy`)\n```http\nPUT kbn:/api/spaces/space/default?overwrite=true\n{\n \"id\":\"default\",\n \"name\":\"Default\",\n \"description\":\"This is your default space!\",\n \"color\":\"#00bfb3\",\n \"disabledFeatures\":[\"case_4_feature_a\"],\n \"_reserved\":true,\n \"imageUrl\":\"\",\n \"initials\":\"D\"\n}\n```\n\n3. Observe that in response deprecated `case_4_feature_a` is replaced by\ntwo features (you can also check\nhttp://localhost:5620/app/management/kibana/spaces/edit/default to see\nhow it's reflected in UI)\n```http\n{\n \"id\": \"default\",\n \"name\": \"Default\",\n \"description\": \"This is your default space!\",\n \"color\": \"#00bfb3\",\n \"initials\": \"D\",\n \"imageUrl\": \"\",\n \"disabledFeatures\": [\n \"case_4_feature_a_v2\",\n \"case_4_feature_c\"\n ],\n \"_reserved\": true\n}\n```\n\n4. Execute the following request from the Dev Tools (`case_4_feature_b`\nis a deprecated feature that is replaced by multiple features, but\n**uses** `deprecated.replacedBy` to set the conceptual\nfeature-successor)\n```http\nPUT kbn:/api/spaces/space/default?overwrite=true\n{\n \"id\":\"default\",\n \"name\":\"Default\",\n \"description\":\"This is your default space!\",\n \"color\":\"#00bfb3\",\n \"disabledFeatures\":[\"case_4_feature_b\"],\n \"_reserved\":true,\n \"imageUrl\":\"\",\n \"initials\":\"D\"\n}\n```\n\n5. Observe that in response deprecated `case_4_feature_b` is replaced by\na single feature (you can also check\nhttp://localhost:5620/app/management/kibana/spaces/edit/default to see\nhow it's reflected in UI)\n```http\n{\n \"id\": \"default\",\n \"name\": \"Default\",\n \"description\": \"This is your default space!\",\n \"color\": \"#00bfb3\",\n \"initials\": \"D\",\n \"imageUrl\": \"\",\n \"disabledFeatures\": [\n \"case_4_feature_b_v2\"\n ],\n \"_reserved\": true\n}\n```\n\n__Required by:__\nhttps://github.com//pull/202863#discussion_r1892672114\n\n//cc @davismcphee","sha":"dd3ce0e7f534279f48be8c125853c89aa92969e2"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/206660","number":206660,"mergeCommit":{"message":"feat(security): extend `Feature` definition to support explicit feature replacements (#206660)\n\n## Summary\n\nToday, when a developer deprecates a feature and replaces its privileges\nwith those of another feature, we reasonably assume that the new feature\nfully replaces the old one in all possible contexts - whether in role\nmanagement UIs or in the Spaces feature toggles visibility UI. However,\nwhen deprecated privileges are replaced by the privileges of multiple\nfeatures, such as in [this\ncase](https://github.com/elastic/kibana/pull/202863#discussion_r1892672114)\nwhere the Discover/Dashboard/Maps feature privileges are replaced by the\nprivileges of Discover_v2/Dashboard_v2/Maps_v2, respectively, **and**\nthe privileges of the Saved Query Management feature, the choice is\nambiguous.\n\nWhich of these features should be treated as the replacement for the\ndeprecated feature in contexts that deal with entire features (like the\nSpaces feature toggles visibility UI) rather than individual privileges\n(like in role management UIs)? Should all referenced features be\nconsidered replacements? Or just a subset - or even a single feature? If\nso, which one? Currently, we treat all referenced features as\nreplacements for the deprecated feature, which creates problems, as\ndescribed in detail in [this\ndiscussion](https://github.com/elastic/kibana/pull/202863#discussion_r1892672114).\n\nThis PR allows developers to customize this behavior by specifying which\nfeatures Kibana should treat as direct successors to deprecated features\nin contexts that deal with whole features rather than individual\nprivileges:\n\n```ts\ndeps.features.registerKibanaFeature({\n deprecated: {\n notice: 'The feature is deprecated because … well, there’s a reason.',\n --> replacedBy: ['feature_id_v2'], <--\n },\n id: 'feature_id'\n name: `Case #4 feature ${suffix} (DEPRECATED)`,\n …\n});\n```\n\n## How to test\n\n1. Run test server\n```bash\nnode scripts/functional_tests_server.js --config x-pack/test/security_api_integration/features.config.ts\n```\n\n2. Execute the following request from the Dev Tools (`case_4_feature_a`\nis a deprecated feature that is replaced by multiple features and\n**doesn't use** `deprecated.replacedBy`)\n```http\nPUT kbn:/api/spaces/space/default?overwrite=true\n{\n \"id\":\"default\",\n \"name\":\"Default\",\n \"description\":\"This is your default space!\",\n \"color\":\"#00bfb3\",\n \"disabledFeatures\":[\"case_4_feature_a\"],\n \"_reserved\":true,\n \"imageUrl\":\"\",\n \"initials\":\"D\"\n}\n```\n\n3. Observe that in response deprecated `case_4_feature_a` is replaced by\ntwo features (you can also check\nhttp://localhost:5620/app/management/kibana/spaces/edit/default to see\nhow it's reflected in UI)\n```http\n{\n \"id\": \"default\",\n \"name\": \"Default\",\n \"description\": \"This is your default space!\",\n \"color\": \"#00bfb3\",\n \"initials\": \"D\",\n \"imageUrl\": \"\",\n \"disabledFeatures\": [\n \"case_4_feature_a_v2\",\n \"case_4_feature_c\"\n ],\n \"_reserved\": true\n}\n```\n\n4. Execute the following request from the Dev Tools (`case_4_feature_b`\nis a deprecated feature that is replaced by multiple features, but\n**uses** `deprecated.replacedBy` to set the conceptual\nfeature-successor)\n```http\nPUT kbn:/api/spaces/space/default?overwrite=true\n{\n \"id\":\"default\",\n \"name\":\"Default\",\n \"description\":\"This is your default space!\",\n \"color\":\"#00bfb3\",\n \"disabledFeatures\":[\"case_4_feature_b\"],\n \"_reserved\":true,\n \"imageUrl\":\"\",\n \"initials\":\"D\"\n}\n```\n\n5. Observe that in response deprecated `case_4_feature_b` is replaced by\na single feature (you can also check\nhttp://localhost:5620/app/management/kibana/spaces/edit/default to see\nhow it's reflected in UI)\n```http\n{\n \"id\": \"default\",\n \"name\": \"Default\",\n \"description\": \"This is your default space!\",\n \"color\": \"#00bfb3\",\n \"initials\": \"D\",\n \"imageUrl\": \"\",\n \"disabledFeatures\": [\n \"case_4_feature_b_v2\"\n ],\n \"_reserved\": true\n}\n```\n\n__Required by:__\nhttps://github.com//pull/202863#discussion_r1892672114\n\n//cc @davismcphee","sha":"dd3ce0e7f534279f48be8c125853c89aa92969e2"}}]}] BACKPORT--> Co-authored-by: Aleh Zasypkin <[email protected]>
…re replacements (elastic#206660) ## Summary Today, when a developer deprecates a feature and replaces its privileges with those of another feature, we reasonably assume that the new feature fully replaces the old one in all possible contexts - whether in role management UIs or in the Spaces feature toggles visibility UI. However, when deprecated privileges are replaced by the privileges of multiple features, such as in [this case](elastic#202863 (comment)) where the Discover/Dashboard/Maps feature privileges are replaced by the privileges of Discover_v2/Dashboard_v2/Maps_v2, respectively, **and** the privileges of the Saved Query Management feature, the choice is ambiguous. Which of these features should be treated as the replacement for the deprecated feature in contexts that deal with entire features (like the Spaces feature toggles visibility UI) rather than individual privileges (like in role management UIs)? Should all referenced features be considered replacements? Or just a subset - or even a single feature? If so, which one? Currently, we treat all referenced features as replacements for the deprecated feature, which creates problems, as described in detail in [this discussion](elastic#202863 (comment)). This PR allows developers to customize this behavior by specifying which features Kibana should treat as direct successors to deprecated features in contexts that deal with whole features rather than individual privileges: ```ts deps.features.registerKibanaFeature({ deprecated: { notice: 'The feature is deprecated because … well, there’s a reason.', --> replacedBy: ['feature_id_v2'], <-- }, id: 'feature_id' name: `Case elastic#4 feature ${suffix} (DEPRECATED)`, … }); ``` ## How to test 1. Run test server ```bash node scripts/functional_tests_server.js --config x-pack/test/security_api_integration/features.config.ts ``` 2. Execute the following request from the Dev Tools (`case_4_feature_a` is a deprecated feature that is replaced by multiple features and **doesn't use** `deprecated.replacedBy`) ```http PUT kbn:/api/spaces/space/default?overwrite=true { "id":"default", "name":"Default", "description":"This is your default space!", "color":"#00bfb3", "disabledFeatures":["case_4_feature_a"], "_reserved":true, "imageUrl":"", "initials":"D" } ``` 3. Observe that in response deprecated `case_4_feature_a` is replaced by two features (you can also check http://localhost:5620/app/management/kibana/spaces/edit/default to see how it's reflected in UI) ```http { "id": "default", "name": "Default", "description": "This is your default space!", "color": "#00bfb3", "initials": "D", "imageUrl": "", "disabledFeatures": [ "case_4_feature_a_v2", "case_4_feature_c" ], "_reserved": true } ``` 4. Execute the following request from the Dev Tools (`case_4_feature_b` is a deprecated feature that is replaced by multiple features, but **uses** `deprecated.replacedBy` to set the conceptual feature-successor) ```http PUT kbn:/api/spaces/space/default?overwrite=true { "id":"default", "name":"Default", "description":"This is your default space!", "color":"#00bfb3", "disabledFeatures":["case_4_feature_b"], "_reserved":true, "imageUrl":"", "initials":"D" } ``` 5. Observe that in response deprecated `case_4_feature_b` is replaced by a single feature (you can also check http://localhost:5620/app/management/kibana/spaces/edit/default to see how it's reflected in UI) ```http { "id": "default", "name": "Default", "description": "This is your default space!", "color": "#00bfb3", "initials": "D", "imageUrl": "", "disabledFeatures": [ "case_4_feature_b_v2" ], "_reserved": true } ``` __Required by:__ elastic#202863 (comment) //cc @davismcphee
Summary
Today, when a developer deprecates a feature and replaces its privileges with those of another feature, we reasonably assume that the new feature fully replaces the old one in all possible contexts - whether in role management UIs or in the Spaces feature toggles visibility UI. However, when deprecated privileges are replaced by the privileges of multiple features, such as in this case where the Discover/Dashboard/Maps feature privileges are replaced by the privileges of Discover_v2/Dashboard_v2/Maps_v2, respectively, and the privileges of the Saved Query Management feature, the choice is ambiguous.
Which of these features should be treated as the replacement for the deprecated feature in contexts that deal with entire features (like the Spaces feature toggles visibility UI) rather than individual privileges (like in role management UIs)? Should all referenced features be considered replacements? Or just a subset - or even a single feature? If so, which one? Currently, we treat all referenced features as replacements for the deprecated feature, which creates problems, as described in detail in this discussion.
This PR allows developers to customize this behavior by specifying which features Kibana should treat as direct successors to deprecated features in contexts that deal with whole features rather than individual privileges:
How to test
case_4_feature_a
is a deprecated feature that is replaced by multiple features and doesn't usedeprecated.replacedBy
)case_4_feature_a
is replaced by two features (you can also check http://localhost:5620/app/management/kibana/spaces/edit/default to see how it's reflected in UI)case_4_feature_b
is a deprecated feature that is replaced by multiple features, but usesdeprecated.replacedBy
to set the conceptual feature-successor)case_4_feature_b
is replaced by a single feature (you can also check http://localhost:5620/app/management/kibana/spaces/edit/default to see how it's reflected in UI)Required by: #202863 (comment)
//cc @davismcphee