)]}'
{"keystone/resource/core.py":[{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":331,"context_line":"    def _check_whole_subtree_is_disabled(self, project_id, subtree_list\u003dNone):"},{"line_number":332,"context_line":"        if not subtree_list:"},{"line_number":333,"context_line":"            subtree_list \u003d self.list_projects_in_subtree(project_id)"},{"line_number":334,"context_line":"        subtree_enabled \u003d [ref.get(\u0027enabled\u0027, False) for ref in subtree_list]"},{"line_number":335,"context_line":"        return not any(subtree_enabled)"},{"line_number":336,"context_line":""},{"line_number":337,"context_line":"    def _update_project("}],"source_content_type":"text/x-python","patch_set":1,"id":"8efb7f89_5fe3ab5b","line":334,"updated":"2026-06-15 18:46:55.000000000","message":"I think this change is a no-op for the actual `enabled\u003dNone` case it\u0027s meant to address. `subtree_list` is built from `_get_children`, which returns `to_dict()` of `Project` rows. `ModelBase.to_dict` iterates `cls.attributes` and unconditionally sets `d[\u0027enabled\u0027] \u003d getattr(self, \u0027enabled\u0027)`, so for a NULL row the dict has `{\u0027enabled\u0027: None}` -- the key is always present. `dict.get` only applies the default when the key is absent, so for a NULL row both `.get(\u0027enabled\u0027, True)` and `.get(\u0027enabled\u0027, False)` return `None`. `subtree_enabled` ends up as `[None, ...]`, `any([None, ...])` is `False`, and the function still returns `True` (subtree treated as all disabled). The default change doesn\u0027t reach this code path. The OSSN draft on the bug lists this exact path as affected; to actually fix it the None case needs explicit handling, e.g. `[ref.get(\u0027enabled\u0027) is True for ref in subtree_list]`.","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"}],"keystone/tests/unit/resource/test_core.py":[{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":874,"context_line":""},{"line_number":875,"context_line":"    The `enabled` column on the project table is nullable. When enabled\u003dNone,"},{"line_number":876,"context_line":"    it should be treated as enabled (not disabled), consistent with the"},{"line_number":877,"context_line":"    semantic convention used throughout keystone to prevent regression."},{"line_number":878,"context_line":"    \"\"\""},{"line_number":879,"context_line":""},{"line_number":880,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"56889d21_ebae1541","line":877,"updated":"2026-06-15 18:46:55.000000000","message":"The class docstring says enabled\u003dNone \"should be treated as enabled (not disabled)\", but the rest of this commit treats project enabled\u003dNone as fail-closed (disabled). Could you please update the docstring? It contradicts the implementation.","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":888,"context_line":"    def test_subtree_with_null_enabled_prevents_parent_disable(self):"},{"line_number":889,"context_line":"        # Regression test: project subtree with enabled\u003dNone children should"},{"line_number":890,"context_line":"        # be considered as \"not all disabled\", preventing parent disable."},{"line_number":891,"context_line":"        # Previously `any([None, None])` returned False, so the function"},{"line_number":892,"context_line":"        # incorrectly reported subtree as \"all disabled\"."},{"line_number":893,"context_line":""},{"line_number":894,"context_line":"        parent \u003d unit.new_project_ref(is_domain\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":1,"id":"f7c5a3bf_3cbe2e79","line":891,"updated":"2026-06-15 18:46:55.000000000","message":"The test docstring says the subtree \"should be considered as \u0027not all disabled\u0027, preventing parent disable\", and references `any([None, None])` returning False as the bug. But the assertion `self.assertTrue(result)` expects `_check_whole_subtree_is_disabled` to return True (subtree IS all disabled). The docstring and assertion contradict each other. The behaviour asserted is also identical before and after the patch, so this isn\u0027t a regression test. Please clarify the intent and align the docstring with the assertion (and with whatever fix lands for `_check_whole_subtree_is_disabled`).","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":912,"context_line":"        result \u003d PROVIDERS.resource_api._check_whole_subtree_is_disabled("},{"line_number":913,"context_line":"            parent[\u0027id\u0027]"},{"line_number":914,"context_line":"        )"},{"line_number":915,"context_line":"        self.assertTrue(result)"},{"line_number":916,"context_line":""},{"line_number":917,"context_line":""},{"line_number":918,"context_line":"class EnabledNullNormalisationTest(unit.SQLDriverOverrides, unit.TestCase):"}],"source_content_type":"text/x-python","patch_set":1,"id":"9764f4f1_48c1bc4a","line":915,"updated":"2026-06-15 18:46:55.000000000","message":"This assertion locks in the current (pre-patch) behaviour rather than the intended fix. There is no test that demonstrates the scenario described in the OSSN draft -- \"parent disable is prevented when the subtree contains a child with enabled\u003dNULL\". A regression test for the actual fix would create a parent with a NULL-enabled child, attempt to disable the parent via `update_project`, and expect `ForbiddenNotSecurity` (because the subtree is not all disabled). Such a test would currently pass against the buggy behaviour and fail against a correct fix, which is the inverse of what is needed. Could you please add a test that exercises the fixed behaviour?","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":982,"context_line":"        )"},{"line_number":983,"context_line":"        updated \u003d PROVIDERS.resource_api.get_project(project[\u0027id\u0027])"},{"line_number":984,"context_line":"        self.assertFalse(updated[\u0027enabled\u0027])"},{"line_number":985,"context_line":""},{"line_number":986,"context_line":"        PROVIDERS.resource_api.update_project(project[\u0027id\u0027], {\u0027enabled\u0027: None})"},{"line_number":987,"context_line":"        PROVIDERS.resource_api.get_project.invalidate("},{"line_number":988,"context_line":"            PROVIDERS.resource_api, project[\u0027id\u0027]"}],"source_content_type":"text/x-python","patch_set":1,"id":"2cb8d048_4333fc7a","line":985,"updated":"2026-06-15 18:46:55.000000000","message":"Lines 972-998 are duplicated copies of the same `update_project({\u0027enabled\u0027: None})` block already covered above. Please remove the duplicates.","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"}],"keystone/tests/unit/token/test_fernet_provider.py":[{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":360,"context_line":"        self.assertEqual(user_ref[\u0027id\u0027], token.user_id)"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    @mock.patch(\u0027keystone.notifications.invalidate_token_cache_notification\u0027)"},{"line_number":363,"context_line":"    def test_update_user_enabled_none_triggers_cache_invalidation("},{"line_number":364,"context_line":"        self, mock_cache_notification"},{"line_number":365,"context_line":"    ):"},{"line_number":366,"context_line":"        # Regression test: updating user.enabled from False to None should"}],"source_content_type":"text/x-python","patch_set":1,"id":"a7067800_78c0ada6","line":363,"updated":"2026-06-15 18:46:55.000000000","message":"The test name says \"enabled_none_triggers_cache_invalidation\" but the body asserts `mock_cache_notification.assert_not_called()` -- i.e. that cache invalidation does NOT happen. The docstring also describes False→None triggering invalidation, but the actual update is None→True. Please rename the test and rewrite the docstring to match what the test does, or change the test body to match the stated intent.","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"}],"releasenotes/notes/align-enabled-null-handling-46bab42eee1f29dc.yaml":[{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"3942cacadc5b303b1fd3de83e701d02182a6d09f","unresolved":true,"context_lines":[{"line_number":2,"context_line":"security:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Improper handling of the null values for user.enabled and project.enabled"},{"line_number":5,"context_line":"    flag leaded to bypass of the PCI-DSS access expiration requirements and"},{"line_number":6,"context_line":"    other unpredictable error. Some paths of the project.enabling handing"},{"line_number":7,"context_line":"    were fail-close, some were fail-open. They are now aligned to be fail-close"},{"line_number":8,"context_line":"    consistently. For the user.enabled the fail-open behavior is preserved to"}],"source_content_type":"text/x-yaml","patch_set":1,"id":"e3feae09_7bc95e64","line":5,"updated":"2026-06-15 18:46:55.000000000","message":"A few small wording fixes would help readability: \"leaded\" → \"led\"; \"other unpredictable error\" → \"other unpredictable errors\"; \"project.enabling handing\" → \"project.enabled handling\"; \"fail-close\" → \"fail-closed\".","commit_id":"d490848342bfaec538edb7d5baf7c26604f7a10e"}]}
