)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"b6935c1b7b275c13a2dc56791428a88f9b2205d5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"b26ee94f_cec25e3e","updated":"2026-08-19 08:36:31.000000000","message":"(curated) AI review:\n\nDeleting the persistent entries is the right API. Two semantics still need attention: an SDK caller using this through an existing connection can keep using and later repersist the in-memory credential, and the method cannot remove an old keyring entry after cache.auth is disabled. The auth-free OSC companion command likely avoids the first path, but both behaviors contradict this public CloudRegion API\u0027s promise to discard cached authentication.","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"}],"openstack/config/cloud_region.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"00e9eeb089caa4a8b7b479a0236a62ad6af02b94","unresolved":false,"context_lines":[{"line_number":813,"context_line":"        \"\"\""},{"line_number":814,"context_line":"        assert self._auth is not None  # narrow type"},{"line_number":815,"context_line":""},{"line_number":816,"context_line":"        cache_id \u003d self._auth.get_unscoped_cache_id()"},{"line_number":817,"context_line":"        if not cache_id:"},{"line_number":818,"context_line":"            return None"},{"line_number":819,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"6f0f067d_fad6ba09","line":816,"updated":"2026-08-18 22:46:23.000000000","message":"pep8: error: \"BaseAuthPlugin\" has no attribute \"get_unscoped_cache_id\"  [attr-defined]","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"b6935c1b7b275c13a2dc56791428a88f9b2205d5","unresolved":true,"context_lines":[{"line_number":833,"context_line":"        except RuntimeError:  # the fail backend raises this"},{"line_number":834,"context_line":"            self.log.debug(\u0027Failed to set auth into keyring\u0027)"},{"line_number":835,"context_line":""},{"line_number":836,"context_line":"    def clear_auth_cache(self) -\u003e None:"},{"line_number":837,"context_line":"        \"\"\"Discard any authentication cached for this cloud."},{"line_number":838,"context_line":""},{"line_number":839,"context_line":"        The next connection authenticates from scratch, which for an"}],"source_content_type":"text/x-python","patch_set":1,"id":"1bff3086_1a814b24","line":836,"updated":"2026-08-19 08:36:31.000000000","message":"When this API is called through an existing SDK connection (for example conn.config.clear_auth_cache()), it deletes only the keyring copy. The plugin still holds auth_ref and _unscoped_auth_ref; the same connection continues using them, and the normal conn.close() path calls set_auth_cache() and writes the credential back. Please clear/invalidate the in-memory auth state too, and add a test that clears followed by set_auth_cache() and verifies nothing is restored. The separate auth-free OSC command is less exposed to this because it does not create an SDK connection.","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"b6935c1b7b275c13a2dc56791428a88f9b2205d5","unresolved":true,"context_lines":[{"line_number":841,"context_line":"        cached credential is known to be unusable, such as after it has been"},{"line_number":842,"context_line":"        revoked or when a different account is wanted."},{"line_number":843,"context_line":"        \"\"\""},{"line_number":844,"context_line":"        if self.skip_auth_cache():"},{"line_number":845,"context_line":"            return"},{"line_number":846,"context_line":""},{"line_number":847,"context_line":"        assert self._auth is not None  # narrow type"}],"source_content_type":"text/x-python","patch_set":1,"id":"a4e9cdf3_c71ee113","line":844,"updated":"2026-08-19 08:36:31.000000000","message":"skip_auth_cache() includes not self._cache_auth, so this recovery API cannot delete a credential after the user disables cache.auth. The old keyring entry remains and will be reused if caching is enabled again. Clearing should require a keyring and an auth plugin, but should not require caching to be currently enabled; the existing test that expects a no-op when caching is off should be inverted.","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"00e9eeb089caa4a8b7b479a0236a62ad6af02b94","unresolved":false,"context_lines":[{"line_number":879,"context_line":"            unscoped_state \u003d self._fetch_auth_state(unscoped_cache_id)"},{"line_number":880,"context_line":"            if unscoped_state:"},{"line_number":881,"context_line":"                self.log.debug(\u0027Reusing unscoped authentication from keyring\u0027)"},{"line_number":882,"context_line":"                self._auth.set_unscoped_auth_state(unscoped_state)"},{"line_number":883,"context_line":""},{"line_number":884,"context_line":"        cache_id \u003d self._auth.get_cache_id()"},{"line_number":885,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"890d5f0a_ae97a5fc","line":882,"updated":"2026-08-18 22:46:23.000000000","message":"pep8: error: \"BaseAuthPlugin\" has no attribute \"set_unscoped_auth_state\"; maybe \"set_auth_state\"?  [attr-defined]","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"00e9eeb089caa4a8b7b479a0236a62ad6af02b94","unresolved":false,"context_lines":[{"line_number":907,"context_line":"        # keeping the credential buys a round trip and costs having a token"},{"line_number":908,"context_line":"        # in the keyring that need not be there at all."},{"line_number":909,"context_line":"        unscoped_cache_id \u003d self._unscoped_auth_cache_id()"},{"line_number":910,"context_line":"        if unscoped_cache_id and self._auth.interactive_unscoped_auth:"},{"line_number":911,"context_line":"            unscoped_state \u003d self._auth.get_unscoped_auth_state()"},{"line_number":912,"context_line":"            if unscoped_state:"},{"line_number":913,"context_line":"                self._store_auth_state(unscoped_cache_id, unscoped_state)"}],"source_content_type":"text/x-python","patch_set":1,"id":"557bfe13_4737bcec","line":910,"updated":"2026-08-18 22:46:23.000000000","message":"pep8: error: \"BaseAuthPlugin\" has no attribute \"interactive_unscoped_auth\"  [attr-defined]","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"00e9eeb089caa4a8b7b479a0236a62ad6af02b94","unresolved":false,"context_lines":[{"line_number":908,"context_line":"        # in the keyring that need not be there at all."},{"line_number":909,"context_line":"        unscoped_cache_id \u003d self._unscoped_auth_cache_id()"},{"line_number":910,"context_line":"        if unscoped_cache_id and self._auth.interactive_unscoped_auth:"},{"line_number":911,"context_line":"            unscoped_state \u003d self._auth.get_unscoped_auth_state()"},{"line_number":912,"context_line":"            if unscoped_state:"},{"line_number":913,"context_line":"                self._store_auth_state(unscoped_cache_id, unscoped_state)"},{"line_number":914,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"396a6f2d_0674f233","line":911,"updated":"2026-08-18 22:46:23.000000000","message":"pep8: error: \"BaseAuthPlugin\" has no attribute \"get_unscoped_auth_state\"; maybe \"get_auth_state\"?  [attr-defined]","commit_id":"89d4b95e21b838e96239114dee9e6f07a15c0ef5"}]}
