)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":5,"context_line":"CommitDate: 2026-08-13 17:46:20 -0500"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add a v3websso authentication plugin"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Implement Keystone\u0027s WebSSO protocol as a v3websso authentication plugin."},{"line_number":10,"context_line":"The plugin opens Keystone\u0027s WebSSO endpoint in the user\u0027s browser, receives"},{"line_number":11,"context_line":"the unscoped token that Keystone posts back to a listener on a loopback"},{"line_number":12,"context_line":"port, and rescopes it as the other federated plugins do."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"WebSSO is not a standardised protocol. Keystone defined it so that Horizon"},{"line_number":15,"context_line":"could authenticate users against an external identity provider, modelling"},{"line_number":16,"context_line":"it on the SAML 2.0 Web Browser SSO Profile. The callback path and the"},{"line_number":17,"context_line":"default port are the values given in the Horizon and Keystone federation"},{"line_number":18,"context_line":"installation guides, since Keystone matches the callback against its"},{"line_number":19,"context_line":"trusted_dashboard list verbatim."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"The unscoped token is cached on disk so that rescoping to another project"},{"line_number":22,"context_line":"does not require authenticating in a browser again. The token-cache option"},{"line_number":23,"context_line":"chooses between reusing a cached token, refreshing one that is known to be"},{"line_number":24,"context_line":"bad, and disabling the cache entirely; cache-path relocates it."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Derived from the keystoneauth-oidc plugin originally developed by the"},{"line_number":27,"context_line":"Spanish National Research Council and INDIGO-DataCloud."},{"line_number":28,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"8b73fb0e_701b89ca","line":25,"range":{"start_line":8,"start_character":1,"end_line":25,"end_character":1},"updated":"2026-08-17 16:34:18.000000000","message":"nit: can you wrap this at \u003c\u003d72 characters","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":false,"context_lines":[{"line_number":5,"context_line":"CommitDate: 2026-08-13 17:46:20 -0500"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add a v3websso authentication plugin"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Implement Keystone\u0027s WebSSO protocol as a v3websso authentication plugin."},{"line_number":10,"context_line":"The plugin opens Keystone\u0027s WebSSO endpoint in the user\u0027s browser, receives"},{"line_number":11,"context_line":"the unscoped token that Keystone posts back to a listener on a loopback"},{"line_number":12,"context_line":"port, and rescopes it as the other federated plugins do."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"WebSSO is not a standardised protocol. Keystone defined it so that Horizon"},{"line_number":15,"context_line":"could authenticate users against an external identity provider, modelling"},{"line_number":16,"context_line":"it on the SAML 2.0 Web Browser SSO Profile. The callback path and the"},{"line_number":17,"context_line":"default port are the values given in the Horizon and Keystone federation"},{"line_number":18,"context_line":"installation guides, since Keystone matches the callback against its"},{"line_number":19,"context_line":"trusted_dashboard list verbatim."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"The unscoped token is cached on disk so that rescoping to another project"},{"line_number":22,"context_line":"does not require authenticating in a browser again. The token-cache option"},{"line_number":23,"context_line":"chooses between reusing a cached token, refreshing one that is known to be"},{"line_number":24,"context_line":"bad, and disabling the cache entirely; cache-path relocates it."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Derived from the keystoneauth-oidc plugin originally developed by the"},{"line_number":27,"context_line":"Spanish National Research Council and INDIGO-DataCloud."},{"line_number":28,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"a1674d6c_dca4ae25","line":25,"range":{"start_line":8,"start_character":1,"end_line":25,"end_character":1},"in_reply_to":"8b73fb0e_701b89ca","updated":"2026-08-18 16:07:53.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"c61077000012348c80982a042949977135385f1f","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"591bd369_49d4c594","updated":"2026-08-12 17:56:36.000000000","message":"So this was my re-attempt after the last one fell apart. We started with keystoneauth-oidc and implemented changes with the intent to upstream it. We adhered to @stephenfin@redhat.com request of no additional dependencies. We\u0027ve made changes to cache the token via the caller of keystoneauth, but that requires the caller passing a cache object that conforms to an ABC interface in. Which is a bit more of an involved change. I\u0027m hoping we can use this patch to discuss that surface area. I did this a number of months ago in a different repo over many different commits and we use that plugin but this patch is Claude taking that repo and smashing it into one change with docs and moving it as a change against keystoneauth so that\u0027s the other reason its WIP.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"f6491094e0bbb60d02e5b3581fc6ed6353ea660d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"571e136d_5dc7c296","updated":"2026-08-12 22:01:22.000000000","message":"review is AI-assisted, but I think these are correct findings from what I can see","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"a616cf8eb0ee48c081757f768163f5010903d9a8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"0f783081_8b9adc1a","in_reply_to":"591bd369_49d4c594","updated":"2026-08-20 19:35:50.000000000","message":"Done","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"5716219f_9f144062","updated":"2026-08-17 16:34:18.000000000","message":"I\u0027d be interested in knowing where the existing caching logic falls apart, and whether we can do anything with it to make it fit this use case. I have a couple of other comments inline also","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"edb378d90d9b20f167e7a5570cb1dc312f7ea9ac","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":4,"id":"834e29d0_0c759e28","updated":"2026-08-19 08:30:24.000000000","message":"So for the thing with the duplicate v3websso entry-point thread: keystoneauth-websso 0.2.5 still registers the same name and I understand why you\u0027re using that name here, and that\u0027s fine... The issue is that if both this package AND that package are installed, depending on which version of stevedore is used it will either reject duplicate names or selects the last-discovered implementation (I don\u0027t remember which versions do which, but the whole thing is not deterministic and could very well be not the expected version). I think there should be a way to handle that here explicitly while still using this name for compatibility? Let the user know they should be uninstalling the old one?","commit_id":"90938c2dbf36899222f896afcb0187f999aeddca"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"a616cf8eb0ee48c081757f768163f5010903d9a8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"e2861211_a9573ae9","in_reply_to":"834e29d0_0c759e28","updated":"2026-08-20 19:35:50.000000000","message":"Separate from this change I\u0027ll write a patch to use the new conflict resoluton in stevedore for ksa.","commit_id":"90938c2dbf36899222f896afcb0187f999aeddca"}],"doc/source/authentication-plugins.rst":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":277,"context_line":"  Connect Client Credentials grant type."},{"line_number":278,"context_line":"- :py:class:`~keystoneauth1.identity.v3:OpenIDConnectPassword`: OpenID Connect"},{"line_number":279,"context_line":"  Resource Owner Password Credentials grant type."},{"line_number":280,"context_line":"- :py:class:`~keystoneauth1.identity.v3.WebSSO`: Browser based Web Single Sign"},{"line_number":281,"context_line":"  On. See :doc:`plugins/websso`."},{"line_number":282,"context_line":"- :py:class:`~keystoneauth1.identity.v3.Keystone2Keystone`: Keystone to"},{"line_number":283,"context_line":"  Keystone Federation."}],"source_content_type":"text/x-rst","patch_set":2,"id":"45ce6418_f27f14d2","line":280,"updated":"2026-08-17 16:34:18.000000000","message":"nit:\n\n```suggestion\n- :py:class:`~keystoneauth1.identity.v3.WebSSO`: Browser-based Web Single Sign\n```","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":false,"context_lines":[{"line_number":277,"context_line":"  Connect Client Credentials grant type."},{"line_number":278,"context_line":"- :py:class:`~keystoneauth1.identity.v3:OpenIDConnectPassword`: OpenID Connect"},{"line_number":279,"context_line":"  Resource Owner Password Credentials grant type."},{"line_number":280,"context_line":"- :py:class:`~keystoneauth1.identity.v3.WebSSO`: Browser based Web Single Sign"},{"line_number":281,"context_line":"  On. See :doc:`plugins/websso`."},{"line_number":282,"context_line":"- :py:class:`~keystoneauth1.identity.v3.Keystone2Keystone`: Keystone to"},{"line_number":283,"context_line":"  Keystone Federation."}],"source_content_type":"text/x-rst","patch_set":2,"id":"440d0012_f419d92f","line":280,"in_reply_to":"45ce6418_f27f14d2","updated":"2026-08-18 16:07:53.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"}],"doc/source/plugins/websso.rst":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":".. code-block:: bash"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    openstack --os-auth-url https://keystone.example.org:5000/v3 \\"},{"line_number":61,"context_line":"      --os-auth-type v3websso \\"},{"line_number":62,"context_line":"      --os-identity-provider \u003cidentity-provider\u003e \\"},{"line_number":63,"context_line":"      --os-protocol openid \\"}],"source_content_type":"text/x-rst","patch_set":2,"id":"162f5052_24b76d81","line":60,"updated":"2026-08-17 16:34:18.000000000","message":"nit: Let\u0027s drop the `:5000` here and elsewhere in this file: we\u0027re already indicating an subdomain (`keystone`) here","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":".. code-block:: bash"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    openstack --os-auth-url https://keystone.example.org:5000/v3 \\"},{"line_number":61,"context_line":"      --os-auth-type v3websso \\"},{"line_number":62,"context_line":"      --os-identity-provider \u003cidentity-provider\u003e \\"},{"line_number":63,"context_line":"      --os-protocol openid \\"}],"source_content_type":"text/x-rst","patch_set":2,"id":"6db7fb64_8f68c89a","line":60,"in_reply_to":"162f5052_24b76d81","updated":"2026-08-18 16:07:53.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":64,"context_line":"      --os-identity-api-version 3 \\"},{"line_number":65,"context_line":"      token issue"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"This opens your browser at the identity provider, waits for the callback, and"},{"line_number":68,"context_line":"prints the resulting token. For a project scoped token, add the usual scope"},{"line_number":69,"context_line":"options:"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":".. code-block:: bash"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"ba9ad335_33cb05a8","line":69,"range":{"start_line":67,"start_character":77,"end_line":69,"end_character":8},"updated":"2026-08-17 16:34:18.000000000","message":"```suggestion\nprints the resulting token.\n\nFor a project-scoped token, add the usual scope options:\n```","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":64,"context_line":"      --os-identity-api-version 3 \\"},{"line_number":65,"context_line":"      token issue"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"This opens your browser at the identity provider, waits for the callback, and"},{"line_number":68,"context_line":"prints the resulting token. For a project scoped token, add the usual scope"},{"line_number":69,"context_line":"options:"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":".. code-block:: bash"},{"line_number":72,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"61966486_a56ca548","line":69,"range":{"start_line":67,"start_character":77,"end_line":69,"end_character":8},"in_reply_to":"ba9ad335_33cb05a8","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":78,"context_line":"      --os-project-domain-name \u003cproject-domain\u003e \\"},{"line_number":79,"context_line":"      --os-identity-api-version 3 \\"},{"line_number":80,"context_line":"      token issue"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"Environment variables"},{"line_number":83,"context_line":"---------------------"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":".. code-block:: bash"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    export OS_AUTH_TYPE\u003dv3websso"},{"line_number":88,"context_line":"    export OS_AUTH_URL\u003dhttps://keystone.example.org:5000/v3"},{"line_number":89,"context_line":"    export OS_IDENTITY_PROVIDER\u003d\u003cidentity-provider\u003e"},{"line_number":90,"context_line":"    export OS_PROTOCOL\u003dopenid"},{"line_number":91,"context_line":"    export OS_PROJECT_NAME\u003d\u003cproject-name\u003e"},{"line_number":92,"context_line":"    export OS_PROJECT_DOMAIN_NAME\u003d\u003cdomain-name\u003e"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    openstack token issue"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"``clouds.yaml``"},{"line_number":97,"context_line":"---------------"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":".. code-block:: yaml"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    clouds:"},{"line_number":102,"context_line":"      my_cloud:"},{"line_number":103,"context_line":"        auth_type: v3websso"},{"line_number":104,"context_line":"        auth:"},{"line_number":105,"context_line":"          auth_url: https://keystone.example.org:5000/v3"},{"line_number":106,"context_line":"          identity_provider: \u003cidentity-provider\u003e"},{"line_number":107,"context_line":"          protocol: openid"},{"line_number":108,"context_line":"          project_name: \u003cproject-name\u003e"},{"line_number":109,"context_line":"          project_domain_name: \u003cdomain-name\u003e"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"Then:"},{"line_number":112,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"4595b20f_9e93e090","line":109,"range":{"start_line":81,"start_character":1,"end_line":109,"end_character":44},"updated":"2026-08-17 16:34:18.000000000","message":"nit: Can you invert the order of these. `clouds.yaml` is heavily preferred","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":true,"context_lines":[{"line_number":78,"context_line":"      --os-project-domain-name \u003cproject-domain\u003e \\"},{"line_number":79,"context_line":"      --os-identity-api-version 3 \\"},{"line_number":80,"context_line":"      token issue"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"Environment variables"},{"line_number":83,"context_line":"---------------------"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":".. code-block:: bash"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    export OS_AUTH_TYPE\u003dv3websso"},{"line_number":88,"context_line":"    export OS_AUTH_URL\u003dhttps://keystone.example.org:5000/v3"},{"line_number":89,"context_line":"    export OS_IDENTITY_PROVIDER\u003d\u003cidentity-provider\u003e"},{"line_number":90,"context_line":"    export OS_PROTOCOL\u003dopenid"},{"line_number":91,"context_line":"    export OS_PROJECT_NAME\u003d\u003cproject-name\u003e"},{"line_number":92,"context_line":"    export OS_PROJECT_DOMAIN_NAME\u003d\u003cdomain-name\u003e"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    openstack token issue"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"``clouds.yaml``"},{"line_number":97,"context_line":"---------------"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":".. code-block:: yaml"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    clouds:"},{"line_number":102,"context_line":"      my_cloud:"},{"line_number":103,"context_line":"        auth_type: v3websso"},{"line_number":104,"context_line":"        auth:"},{"line_number":105,"context_line":"          auth_url: https://keystone.example.org:5000/v3"},{"line_number":106,"context_line":"          identity_provider: \u003cidentity-provider\u003e"},{"line_number":107,"context_line":"          protocol: openid"},{"line_number":108,"context_line":"          project_name: \u003cproject-name\u003e"},{"line_number":109,"context_line":"          project_domain_name: \u003cdomain-name\u003e"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"Then:"},{"line_number":112,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"4b6ca129_278aec4d","line":109,"range":{"start_line":81,"start_character":1,"end_line":109,"end_character":44},"in_reply_to":"4595b20f_9e93e090","updated":"2026-08-18 16:07:53.000000000","message":"Ahead of the command line even?","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":78,"context_line":"      --os-project-domain-name \u003cproject-domain\u003e \\"},{"line_number":79,"context_line":"      --os-identity-api-version 3 \\"},{"line_number":80,"context_line":"      token issue"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"Environment variables"},{"line_number":83,"context_line":"---------------------"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":".. code-block:: bash"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    export OS_AUTH_TYPE\u003dv3websso"},{"line_number":88,"context_line":"    export OS_AUTH_URL\u003dhttps://keystone.example.org:5000/v3"},{"line_number":89,"context_line":"    export OS_IDENTITY_PROVIDER\u003d\u003cidentity-provider\u003e"},{"line_number":90,"context_line":"    export OS_PROTOCOL\u003dopenid"},{"line_number":91,"context_line":"    export OS_PROJECT_NAME\u003d\u003cproject-name\u003e"},{"line_number":92,"context_line":"    export OS_PROJECT_DOMAIN_NAME\u003d\u003cdomain-name\u003e"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":"    openstack token issue"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"``clouds.yaml``"},{"line_number":97,"context_line":"---------------"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":".. code-block:: yaml"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    clouds:"},{"line_number":102,"context_line":"      my_cloud:"},{"line_number":103,"context_line":"        auth_type: v3websso"},{"line_number":104,"context_line":"        auth:"},{"line_number":105,"context_line":"          auth_url: https://keystone.example.org:5000/v3"},{"line_number":106,"context_line":"          identity_provider: \u003cidentity-provider\u003e"},{"line_number":107,"context_line":"          protocol: openid"},{"line_number":108,"context_line":"          project_name: \u003cproject-name\u003e"},{"line_number":109,"context_line":"          project_domain_name: \u003cdomain-name\u003e"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"Then:"},{"line_number":112,"context_line":""}],"source_content_type":"text/x-rst","patch_set":2,"id":"9c31137e_92645aba","line":109,"range":{"start_line":81,"start_character":1,"end_line":109,"end_character":44},"in_reply_to":"4b6ca129_278aec4d","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":153,"context_line":"The default location follows the platform\u0027s user cache directory:"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":156,"context_line":"Linux         ``$XDG_CACHE_HOME/keystoneauth/websso/``, or"},{"line_number":157,"context_line":"              ``~/.cache/keystoneauth/websso/``"},{"line_number":158,"context_line":"macOS         ``~/Library/Caches/keystoneauth/websso/``"},{"line_number":159,"context_line":"Windows       ``%LOCALAPPDATA%\\keystoneauth\\websso\\``"}],"source_content_type":"text/x-rst","patch_set":2,"id":"b056acb3_06358dfc","line":156,"updated":"2026-08-17 16:34:18.000000000","message":"bike shedding: do we want to use `openstack` rather than `keystoneauth`?\n\nlater, after thinking on it more: probably not actually. gophercloud won\u0027t be able to use it. But keystoneauth probably isn\u0027t the thing that should be doing this. Rather, an application like openstackclient should (meaning we\u0027d use e.g. `~/.cache/openstackclient/websso`). More on this later.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":153,"context_line":"The default location follows the platform\u0027s user cache directory:"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":156,"context_line":"Linux         ``$XDG_CACHE_HOME/keystoneauth/websso/``, or"},{"line_number":157,"context_line":"              ``~/.cache/keystoneauth/websso/``"},{"line_number":158,"context_line":"macOS         ``~/Library/Caches/keystoneauth/websso/``"},{"line_number":159,"context_line":"Windows       ``%LOCALAPPDATA%\\keystoneauth\\websso\\``"}],"source_content_type":"text/x-rst","patch_set":2,"id":"3fa0efb5_4a09b4db","line":156,"in_reply_to":"b056acb3_06358dfc","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":159,"context_line":"Windows       ``%LOCALAPPDATA%\\keystoneauth\\websso\\``"},{"line_number":160,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"Set ``cache-path`` to override it. Cache files are created with user-only"},{"line_number":163,"context_line":"permissions (``0600``) in a user-only directory (``0700``), and a cached token"},{"line_number":164,"context_line":"is discarded once it is close to expiring. A cache file that cannot be read or"},{"line_number":165,"context_line":"parsed is removed and ignored rather than treated as an error."}],"source_content_type":"text/x-rst","patch_set":2,"id":"5d1874d0_04f8bd07","line":162,"updated":"2026-08-17 16:34:18.000000000","message":"It\u0027s still not entirely clear to me from this what `cache-path` is or how you set it. Is it an auth option? Is it a Python argument? Is it something else? fwiw, it shouldn\u0027t be an auth-option since it\u0027s not something that I believe will/should change from cloud to cloud. Rather, it\u0027s an application-specific \"thing\". We can avoid worrying about this if we make this openstacksdk/OSC\u0027s problem.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":159,"context_line":"Windows       ``%LOCALAPPDATA%\\keystoneauth\\websso\\``"},{"line_number":160,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"Set ``cache-path`` to override it. Cache files are created with user-only"},{"line_number":163,"context_line":"permissions (``0600``) in a user-only directory (``0700``), and a cached token"},{"line_number":164,"context_line":"is discarded once it is close to expiring. A cache file that cannot be read or"},{"line_number":165,"context_line":"parsed is removed and ignored rather than treated as an error."}],"source_content_type":"text/x-rst","patch_set":2,"id":"296ab96a_fdd38782","line":162,"in_reply_to":"5d1874d0_04f8bd07","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":166,"context_line":""},{"line_number":167,"context_line":"Controlling the cache"},{"line_number":168,"context_line":"---------------------"},{"line_number":169,"context_line":""},{"line_number":170,"context_line":"``token-cache`` selects what to do with the cache:"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"``reuse``"},{"line_number":173,"context_line":"  The default. Reuse a cached token when one is available."},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"``refresh``"},{"line_number":176,"context_line":"  Discard the cached token, authenticate in a browser again, and cache the"},{"line_number":177,"context_line":"  result. Use this when the cached token is known to be bad, for example after"},{"line_number":178,"context_line":"  it has been revoked. The old token is removed before the flow starts, so a"},{"line_number":179,"context_line":"  failed login cannot leave it behind to be picked up later."},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"``disabled``"},{"line_number":182,"context_line":"  Neither read nor write the cache. Every command needs a browser round trip."},{"line_number":183,"context_line":""},{"line_number":184,"context_line":".. code-block:: bash"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"    # the cached token is bad; get a new one and replace it"}],"source_content_type":"text/x-rst","patch_set":2,"id":"6903599f_8bce7d27","line":183,"range":{"start_line":169,"start_character":1,"end_line":183,"end_character":1},"updated":"2026-08-17 16:34:18.000000000","message":"Do we really want the ``refresh`` option? It seems like (IMO) we\u0027d be better served by having an API to manage the cache in keystoneauth and adding a command to interact with this from openstackclient?\n\nIf we don\u0027t want that option, do we want the rest? Couldn\u0027t we just set `cache-path` to `None`/the empty string (`\u0027\u0027`) to disable it? Or suggest people point to `/dev/null`?","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":166,"context_line":""},{"line_number":167,"context_line":"Controlling the cache"},{"line_number":168,"context_line":"---------------------"},{"line_number":169,"context_line":""},{"line_number":170,"context_line":"``token-cache`` selects what to do with the cache:"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"``reuse``"},{"line_number":173,"context_line":"  The default. Reuse a cached token when one is available."},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"``refresh``"},{"line_number":176,"context_line":"  Discard the cached token, authenticate in a browser again, and cache the"},{"line_number":177,"context_line":"  result. Use this when the cached token is known to be bad, for example after"},{"line_number":178,"context_line":"  it has been revoked. The old token is removed before the flow starts, so a"},{"line_number":179,"context_line":"  failed login cannot leave it behind to be picked up later."},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"``disabled``"},{"line_number":182,"context_line":"  Neither read nor write the cache. Every command needs a browser round trip."},{"line_number":183,"context_line":""},{"line_number":184,"context_line":".. code-block:: bash"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"    # the cached token is bad; get a new one and replace it"}],"source_content_type":"text/x-rst","patch_set":2,"id":"562b7a58_89c1e9f7","line":183,"range":{"start_line":169,"start_character":1,"end_line":183,"end_character":1},"in_reply_to":"6903599f_8bce7d27","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"}],"keystoneauth1/identity/v3/websso.py":[{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"f6491094e0bbb60d02e5b3581fc6ed6353ea660d","unresolved":true,"context_lines":[{"line_number":219,"context_line":"        self.token \u003d token"},{"line_number":220,"context_line":"        return \u0027200 OK\u0027, _SUCCESS_HTML"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _check_fetch_metadata("},{"line_number":223,"context_line":"        self, environ: wsgiref.types.WSGIEnvironment"},{"line_number":224,"context_line":"    ) -\u003e tuple[str, str] | None:"},{"line_number":225,"context_line":"        \"\"\"Reject requests that cannot have come from Keystone."}],"source_content_type":"text/x-python","patch_set":1,"id":"75ee18df_afded0e5","line":222,"updated":"2026-08-12 22:01:22.000000000","message":"The Fetch Metadata checks reject fetch(), but not a scripted cross-origin form submission: that request also has Sec-Fetch-Mode: navigate, Sec-Fetch-Dest: document, and Sec-Fetch-Site: cross-site. For the documented HTTPS-to-HTTP callback, the default strict referrer policy sends Origin: null and omits Referer, and this code does not check Origin; an attacker-controlled page can therefore submit another valid Keystone token. Please remove the claim that this rejects cross-origin posts and either add a reliable request-binding mechanism or document the remaining login-CSRF risk.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"ce9585dedc5fb435566399f47c95ac84c3f12e51","unresolved":false,"context_lines":[{"line_number":219,"context_line":"        self.token \u003d token"},{"line_number":220,"context_line":"        return \u0027200 OK\u0027, _SUCCESS_HTML"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _check_fetch_metadata("},{"line_number":223,"context_line":"        self, environ: wsgiref.types.WSGIEnvironment"},{"line_number":224,"context_line":"    ) -\u003e tuple[str, str] | None:"},{"line_number":225,"context_line":"        \"\"\"Reject requests that cannot have come from Keystone."}],"source_content_type":"text/x-python","patch_set":1,"id":"6c32de28_017c7013","line":222,"in_reply_to":"072d6e8b_4a40d6a5","updated":"2026-08-13 22:45:45.000000000","message":"Done","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"3f7b083b5dc8c69168ba829fef9019b56b9cc0b4","unresolved":true,"context_lines":[{"line_number":219,"context_line":"        self.token \u003d token"},{"line_number":220,"context_line":"        return \u0027200 OK\u0027, _SUCCESS_HTML"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def _check_fetch_metadata("},{"line_number":223,"context_line":"        self, environ: wsgiref.types.WSGIEnvironment"},{"line_number":224,"context_line":"    ) -\u003e tuple[str, str] | None:"},{"line_number":225,"context_line":"        \"\"\"Reject requests that cannot have come from Keystone."}],"source_content_type":"text/x-python","patch_set":1,"id":"072d6e8b_4a40d6a5","line":222,"in_reply_to":"75ee18df_afded0e5","updated":"2026-08-12 22:42:37.000000000","message":"Yeah good call out. The loophole for an attack is still there. I was hoping to close this down entirely but keystone doesn\u0027t pass the right details in the request. I\u0027ve got a pending patch to keystone to do so. This came from the code that was doing that but then when testing this change it failed and it was made less strict but the wording wasn\u0027t changed.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"f6491094e0bbb60d02e5b3581fc6ed6353ea660d","unresolved":true,"context_lines":[{"line_number":385,"context_line":"        query \u003d urllib.parse.urlencode({\u0027origin\u0027: self.redirect_uri})"},{"line_number":386,"context_line":"        url \u003d f\u0027{self.federated_token_url}?{query}\u0027"},{"line_number":387,"context_line":""},{"line_number":388,"context_line":"        if not webbrowser.open(url, new\u003d0):"},{"line_number":389,"context_line":"            _logger.warning("},{"line_number":390,"context_line":"                \u0027Could not open a browser automatically. Open the following \u0027"},{"line_number":391,"context_line":"                \u0027URL to continue authenticating: %s\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"0ea91455_831fffde","line":388,"updated":"2026-08-12 22:01:22.000000000","message":"webbrowser.open() runs before _wait_for_token(), and make_server() is only called inside _wait_for_token(). If the browser already has an IdP session, Keystone can POST before the loopback socket is listening, producing a connection failure and losing the one-shot callback. Bind the server before opening the browser; add a test whose opener immediately connects to the callback port.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"3f7b083b5dc8c69168ba829fef9019b56b9cc0b4","unresolved":true,"context_lines":[{"line_number":385,"context_line":"        query \u003d urllib.parse.urlencode({\u0027origin\u0027: self.redirect_uri})"},{"line_number":386,"context_line":"        url \u003d f\u0027{self.federated_token_url}?{query}\u0027"},{"line_number":387,"context_line":""},{"line_number":388,"context_line":"        if not webbrowser.open(url, new\u003d0):"},{"line_number":389,"context_line":"            _logger.warning("},{"line_number":390,"context_line":"                \u0027Could not open a browser automatically. Open the following \u0027"},{"line_number":391,"context_line":"                \u0027URL to continue authenticating: %s\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"3564d23d_afb2b5e1","line":388,"in_reply_to":"0ea91455_831fffde","updated":"2026-08-12 22:42:37.000000000","message":"Yeah I can invert that. Looking at commit history, I actually cheated it to speed it up by firing off the async request to the browser and then starting up the server purposefully so that the port was setup for listening while the browser was coming to life.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"ce9585dedc5fb435566399f47c95ac84c3f12e51","unresolved":false,"context_lines":[{"line_number":385,"context_line":"        query \u003d urllib.parse.urlencode({\u0027origin\u0027: self.redirect_uri})"},{"line_number":386,"context_line":"        url \u003d f\u0027{self.federated_token_url}?{query}\u0027"},{"line_number":387,"context_line":""},{"line_number":388,"context_line":"        if not webbrowser.open(url, new\u003d0):"},{"line_number":389,"context_line":"            _logger.warning("},{"line_number":390,"context_line":"                \u0027Could not open a browser automatically. Open the following \u0027"},{"line_number":391,"context_line":"                \u0027URL to continue authenticating: %s\u0027,"}],"source_content_type":"text/x-python","patch_set":1,"id":"8e2860c8_cd8f77b4","line":388,"in_reply_to":"3564d23d_afb2b5e1","updated":"2026-08-13 22:45:45.000000000","message":"Done","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"f6491094e0bbb60d02e5b3581fc6ed6353ea660d","unresolved":true,"context_lines":[{"line_number":429,"context_line":""},{"line_number":430,"context_line":"        return auth_ref"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":433,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":434,"context_line":""},{"line_number":435,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":1,"id":"957176ef_4581f016","line":432,"updated":"2026-08-12 22:01:22.000000000","message":"_cache_file() does not distinguish federated accounts. After the browser\u0027s IdP session changes from account A to B, this plugin still returns A\u0027s cached token until it nears expiry; it never opens the browser to observe B. Add an explicit cache namespace/account selector, or at minimum document that users must delete the cache file or disable token-cache when switching accounts.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":429,"context_line":""},{"line_number":430,"context_line":"        return auth_ref"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":433,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":434,"context_line":""},{"line_number":435,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":1,"id":"a93294d7_2a937351","line":432,"in_reply_to":"759722cb_ae7c972e","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"3f7b083b5dc8c69168ba829fef9019b56b9cc0b4","unresolved":true,"context_lines":[{"line_number":429,"context_line":""},{"line_number":430,"context_line":"        return auth_ref"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":433,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":434,"context_line":""},{"line_number":435,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":1,"id":"eb2bb1d3_35402d1b","line":432,"in_reply_to":"957176ef_4581f016","updated":"2026-08-12 22:42:37.000000000","message":"Yeah I don\u0027t have an answer here. An account selector wouldn\u0027t really work here because where would you stick that value? Into clouds.yaml but then who is to say what session to loaded out of your browser.\n\nAll implementations that exist today have this issue including your Go-lang implementation which just utilizes the URL of the keystone server as the cache key.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"eb3008a1a01549aabd070dd56dff5479365c7f95","unresolved":true,"context_lines":[{"line_number":429,"context_line":""},{"line_number":430,"context_line":"        return auth_ref"},{"line_number":431,"context_line":""},{"line_number":432,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":433,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":434,"context_line":""},{"line_number":435,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":1,"id":"759722cb_ae7c972e","line":432,"in_reply_to":"eb2bb1d3_35402d1b","updated":"2026-08-12 23:15:00.000000000","message":"One correction: the current Gophercloud branch does not key only on the Keystone URL. Its key includes a required caller-supplied cache namespace, the Keystone endpoint, identity provider, protocol, and flow. Separate namespaces isolate browser identities. Your broader point is still valid: reusing one namespace after switching the browser account returns the cached identity without reopening the browser. I have clarified that behavior in the documentation.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":315,"context_line":"    redirect_host: str,"},{"line_number":316,"context_line":"    redirect_port: int,"},{"line_number":317,"context_line":"    keystone_origin: str,"},{"line_number":318,"context_line":"    start_flow: ty.Callable[[], None],"},{"line_number":319,"context_line":"    timeout: float \u003d _DEFAULT_TIMEOUT,"},{"line_number":320,"context_line":") -\u003e str:"},{"line_number":321,"context_line":"    \"\"\"Serve the callback endpoint until Keystone posts a token to it."}],"source_content_type":"text/x-python","patch_set":2,"id":"fd6d36b6_d4a1ec6f","line":318,"updated":"2026-08-17 16:34:18.000000000","message":"Use `Callable` from `collections.abc`, not the deprecated alias from `typing`.\n\n(ruff can detect and fix this for us but we need to get rid of the import alias first)","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":false,"context_lines":[{"line_number":315,"context_line":"    redirect_host: str,"},{"line_number":316,"context_line":"    redirect_port: int,"},{"line_number":317,"context_line":"    keystone_origin: str,"},{"line_number":318,"context_line":"    start_flow: ty.Callable[[], None],"},{"line_number":319,"context_line":"    timeout: float \u003d _DEFAULT_TIMEOUT,"},{"line_number":320,"context_line":") -\u003e str:"},{"line_number":321,"context_line":"    \"\"\"Serve the callback endpoint until Keystone posts a token to it."}],"source_content_type":"text/x-python","patch_set":2,"id":"d72e04ae_68a67de0","line":318,"in_reply_to":"fd6d36b6_d4a1ec6f","updated":"2026-08-18 16:07:53.000000000","message":"Done. Used the fully qualified path since that\u0027s how the rest of the code base is.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":527,"context_line":""},{"line_number":528,"context_line":"        return auth_ref"},{"line_number":529,"context_line":""},{"line_number":530,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":531,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":532,"context_line":""},{"line_number":533,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":2,"id":"ceb840fc_71eba8a5","line":530,"updated":"2026-08-17 16:34:18.000000000","message":"I\u0027ve mentioned a few times about not wanting to have this caching logic here in keystoneauth. Out of curiosity, have you looked at the existing caching logic in here (`get_cache_id`, `get_cache_id_elements`, `get_auth_state` / `set_auth_state`). Is there a reason these aren\u0027t suitable? Note that I have no compared these yet as I\u0027m hoping you have.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":527,"context_line":""},{"line_number":528,"context_line":"        return auth_ref"},{"line_number":529,"context_line":""},{"line_number":530,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":531,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":532,"context_line":""},{"line_number":533,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":2,"id":"f0dfee02_7ce042d7","line":530,"in_reply_to":"570109ec_21e7015c","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":true,"context_lines":[{"line_number":527,"context_line":""},{"line_number":528,"context_line":"        return auth_ref"},{"line_number":529,"context_line":""},{"line_number":530,"context_line":"    def _cache_file(self) -\u003e pathlib.Path:"},{"line_number":531,"context_line":"        \"\"\"Return the file the unscoped token for this identity is cached in."},{"line_number":532,"context_line":""},{"line_number":533,"context_line":"        The scope is deliberately not part of the key. The cached token is"}],"source_content_type":"text/x-python","patch_set":2,"id":"570109ec_21e7015c","line":530,"in_reply_to":"ceb840fc_71eba8a5","updated":"2026-08-18 16:07:53.000000000","message":"`get_cache_id` assumes scope. These need to be the unscoped token. Overall from a usability standpoint I want to have one OS_CLOUD that can get a system-scope, domain-scope, or project-scope token so it really should not include scope. I\u0027d love to get some ideas on how we can make this happen.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"edb378d90d9b20f167e7a5570cb1dc312f7ea9ac","unresolved":true,"context_lines":[{"line_number":85,"context_line":"_DEFAULT_REDIRECT_PORT \u003d 9990"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"# How long to wait for the user to complete authentication in their browser."},{"line_number":88,"context_line":"_DEFAULT_TIMEOUT \u003d 60"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"# The body only ever carries a single Keystone token, so anything remotely"},{"line_number":91,"context_line":"# large is not something we sent the user to fetch."}],"source_content_type":"text/x-python","patch_set":4,"id":"de2077df_3fbcab71","line":88,"updated":"2026-08-19 08:30:24.000000000","message":"The 60-second login window matches the existing external plugin, but it is fixed and there is no option for users whose initial SSO/MFA takes longer (I know my auth often takes quite a while when I have to deal with Outlook codes and stuff...) so this has bitten me frequently in the past with other services too","commit_id":"90938c2dbf36899222f896afcb0187f999aeddca"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"a616cf8eb0ee48c081757f768163f5010903d9a8","unresolved":false,"context_lines":[{"line_number":85,"context_line":"_DEFAULT_REDIRECT_PORT \u003d 9990"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"# How long to wait for the user to complete authentication in their browser."},{"line_number":88,"context_line":"_DEFAULT_TIMEOUT \u003d 60"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"# The body only ever carries a single Keystone token, so anything remotely"},{"line_number":91,"context_line":"# large is not something we sent the user to fetch."}],"source_content_type":"text/x-python","patch_set":4,"id":"1d239f8f_d50aa69c","line":88,"in_reply_to":"de2077df_3fbcab71","updated":"2026-08-20 19:35:50.000000000","message":"Done","commit_id":"90938c2dbf36899222f896afcb0187f999aeddca"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"edb378d90d9b20f167e7a5570cb1dc312f7ea9ac","unresolved":false,"context_lines":[{"line_number":389,"context_line":"        )"},{"line_number":390,"context_line":"        self.redirect_host \u003d redirect_host"},{"line_number":391,"context_line":"        self.redirect_port \u003d int(redirect_port)"},{"line_number":392,"context_line":"        self.redirect_uri \u003d ("},{"line_number":393,"context_line":"            f\u0027http://{self.redirect_host}:{self.redirect_port}{_CALLBACK_PATH}\u0027"},{"line_number":394,"context_line":"        )"},{"line_number":395,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"25985e8c_38364a55","line":392,"updated":"2026-08-19 08:30:24.000000000","message":"Non-blocking IPv6 compatibility issue: _assert_loopback() accepts ::1, but redirect_host\u003d\u0027::1\u0027 produces http://::1:9990/auth/websso/ rather than a bracketed IPv6 URI, and the default WSGIServer uses AF_INET and cannot bind it. This only affects an explicit IPv6 callback (or an IPv6-only localhost); the default localhost normally binds 127.0.0.1. Please either reject IPv6 with a clear OptionError or support it end to end.\n\n^^ AI found that, I don\u0027t really think it matters, but figured I\u0027d leave it here for your agent to review :D","commit_id":"90938c2dbf36899222f896afcb0187f999aeddca"}],"keystoneauth1/loading/_plugins/identity/v3.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":623,"context_line":"                        \u0027must be listed in the identity service\\\u0027s \u0027"},{"line_number":624,"context_line":"                        \u0027[federation] trusted_dashboard option.\u0027"},{"line_number":625,"context_line":"                    ),"},{"line_number":626,"context_line":"                ),"},{"line_number":627,"context_line":"                loading.Opt("},{"line_number":628,"context_line":"                    \u0027token-cache\u0027,"},{"line_number":629,"context_line":"                    default\u003dwebsso.CACHE_REUSE,"},{"line_number":630,"context_line":"                    metavar\u003d\u0027|\u0027.join(websso.CACHE_MODES),"},{"line_number":631,"context_line":"                    help\u003d("},{"line_number":632,"context_line":"                        \u0027How to use the on disk cache of the unscoped token. \u0027"},{"line_number":633,"context_line":"                        \u0027\"reuse\", the default, reuses a cached token so that \u0027"},{"line_number":634,"context_line":"                        \u0027rescoping to another project does not require \u0027"},{"line_number":635,"context_line":"                        \u0027authenticating in a browser again. \"refresh\" \u0027"},{"line_number":636,"context_line":"                        \u0027discards any cached token, authenticates again and \u0027"},{"line_number":637,"context_line":"                        \u0027caches the result, which is what to use when the \u0027"},{"line_number":638,"context_line":"                        \u0027cached token is known to be bad. \"disabled\" neither \u0027"},{"line_number":639,"context_line":"                        \u0027reads nor writes the cache.\u0027"},{"line_number":640,"context_line":"                    ),"},{"line_number":641,"context_line":"                ),"},{"line_number":642,"context_line":"                loading.Opt("},{"line_number":643,"context_line":"                    \u0027cache-path\u0027,"},{"line_number":644,"context_line":"                    help\u003d("},{"line_number":645,"context_line":"                        \u0027Directory to store the token cache in. Defaults to a \u0027"},{"line_number":646,"context_line":"                        \u0027platform specific user cache directory.\u0027"},{"line_number":647,"context_line":"                    ),"},{"line_number":648,"context_line":"                ),"},{"line_number":649,"context_line":"            ]"},{"line_number":650,"context_line":"        )"},{"line_number":651,"context_line":"        return options"}],"source_content_type":"text/x-python","patch_set":2,"id":"9d192b4d_31b9dc20","line":648,"range":{"start_line":626,"start_character":18,"end_line":648,"end_character":18},"updated":"2026-08-17 16:34:18.000000000","message":"As noted elsewhere, I don\u0027t think these options belong in keystoneauth.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[{"line_number":623,"context_line":"                        \u0027must be listed in the identity service\\\u0027s \u0027"},{"line_number":624,"context_line":"                        \u0027[federation] trusted_dashboard option.\u0027"},{"line_number":625,"context_line":"                    ),"},{"line_number":626,"context_line":"                ),"},{"line_number":627,"context_line":"                loading.Opt("},{"line_number":628,"context_line":"                    \u0027token-cache\u0027,"},{"line_number":629,"context_line":"                    default\u003dwebsso.CACHE_REUSE,"},{"line_number":630,"context_line":"                    metavar\u003d\u0027|\u0027.join(websso.CACHE_MODES),"},{"line_number":631,"context_line":"                    help\u003d("},{"line_number":632,"context_line":"                        \u0027How to use the on disk cache of the unscoped token. \u0027"},{"line_number":633,"context_line":"                        \u0027\"reuse\", the default, reuses a cached token so that \u0027"},{"line_number":634,"context_line":"                        \u0027rescoping to another project does not require \u0027"},{"line_number":635,"context_line":"                        \u0027authenticating in a browser again. \"refresh\" \u0027"},{"line_number":636,"context_line":"                        \u0027discards any cached token, authenticates again and \u0027"},{"line_number":637,"context_line":"                        \u0027caches the result, which is what to use when the \u0027"},{"line_number":638,"context_line":"                        \u0027cached token is known to be bad. \"disabled\" neither \u0027"},{"line_number":639,"context_line":"                        \u0027reads nor writes the cache.\u0027"},{"line_number":640,"context_line":"                    ),"},{"line_number":641,"context_line":"                ),"},{"line_number":642,"context_line":"                loading.Opt("},{"line_number":643,"context_line":"                    \u0027cache-path\u0027,"},{"line_number":644,"context_line":"                    help\u003d("},{"line_number":645,"context_line":"                        \u0027Directory to store the token cache in. Defaults to a \u0027"},{"line_number":646,"context_line":"                        \u0027platform specific user cache directory.\u0027"},{"line_number":647,"context_line":"                    ),"},{"line_number":648,"context_line":"                ),"},{"line_number":649,"context_line":"            ]"},{"line_number":650,"context_line":"        )"},{"line_number":651,"context_line":"        return options"}],"source_content_type":"text/x-python","patch_set":2,"id":"6da623d4_0c3fe07d","line":648,"range":{"start_line":626,"start_character":18,"end_line":648,"end_character":18},"in_reply_to":"9d192b4d_31b9dc20","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"}],"keystoneauth1/tests/unit/identity/test_identity_v3_websso.py":[{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"8ae81b5c_725dd0f6","updated":"2026-08-17 16:34:18.000000000","message":"I\u0027ll note I had a hard time reading through this and ended up mostly just skimming it. It looks comprehensive, but assuming these are AI-generated there\u0027s probably a lot of tests in here that are technically valid but not all that useful and just add bloat. I\u0027d appreciate it if you could weed out some of the lower value tests and consider ways to streamline what\u0027s left (via tools like `TestCase.subTest`) if possible, before this is no longer draft","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"e921e004_cff94195","in_reply_to":"8ae81b5c_725dd0f6","updated":"2026-08-18 16:07:53.000000000","message":"Done some consolidation here.","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"cba4aa4c0271be2c305435348b468f3838fbbcee","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"350520a1_45dc5be2","in_reply_to":"e921e004_cff94195","updated":"2026-08-18 20:36:44.000000000","message":"Done","commit_id":"4c1a22b125b36b28a25b6c05e07b2a0bbdd64c91"}],"pyproject.toml":[{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"f6491094e0bbb60d02e5b3581fc6ed6353ea660d","unresolved":true,"context_lines":[{"line_number":75,"context_line":"v3multifactor \u003d \"keystoneauth1.loading._plugins.identity.v3:MultiFactor\""},{"line_number":76,"context_line":"v3oauth2clientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential\""},{"line_number":77,"context_line":"v3oauth2mtlsclientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2mTlsClientCredential\""},{"line_number":78,"context_line":"v3websso \u003d \"keystoneauth1.loading._plugins.identity.v3:WebSSO\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"[tool.setuptools.packages.find]"},{"line_number":81,"context_line":"include \u003d [\"keystoneauth1\"]"}],"source_content_type":"text/x-toml","patch_set":1,"id":"8c45b2c6_1b86e97d","line":78,"updated":"2026-08-12 22:01:22.000000000","message":"keystoneauth-websso already registers keystoneauth1.plugin/v3websso. If both distributions are installed, Stevedore 1.20 (still permitted by requirements.txt) raises MultipleMatches; current Stevedore logs a conflict and chooses the last-discovered entry point, so which implementation runs is not a stable contract. Add release-note migration guidance requiring the external package to be removed when upgrading.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":15334,"name":"Stephen Finucane","display_name":"stephenfin","email":"stephenfin@redhat.com","username":"sfinucan"},"change_message_id":"4e04fe72c36b5271d6e257702a30ae998ddc2726","unresolved":true,"context_lines":[{"line_number":75,"context_line":"v3multifactor \u003d \"keystoneauth1.loading._plugins.identity.v3:MultiFactor\""},{"line_number":76,"context_line":"v3oauth2clientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential\""},{"line_number":77,"context_line":"v3oauth2mtlsclientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2mTlsClientCredential\""},{"line_number":78,"context_line":"v3websso \u003d \"keystoneauth1.loading._plugins.identity.v3:WebSSO\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"[tool.setuptools.packages.find]"},{"line_number":81,"context_line":"include \u003d [\"keystoneauth1\"]"}],"source_content_type":"text/x-toml","patch_set":1,"id":"c2a5c0f6_62b7a070","line":78,"in_reply_to":"21301f6f_8c22c8ac","updated":"2026-08-17 16:34:18.000000000","message":"Note that recent\u0027ish versions of stevedore (5.6.0 or later) support conflict resolution. We are using this in OSC as part of the neutron stadium migration and should be able to use it here also.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"a616cf8eb0ee48c081757f768163f5010903d9a8","unresolved":false,"context_lines":[{"line_number":75,"context_line":"v3multifactor \u003d \"keystoneauth1.loading._plugins.identity.v3:MultiFactor\""},{"line_number":76,"context_line":"v3oauth2clientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential\""},{"line_number":77,"context_line":"v3oauth2mtlsclientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2mTlsClientCredential\""},{"line_number":78,"context_line":"v3websso \u003d \"keystoneauth1.loading._plugins.identity.v3:WebSSO\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"[tool.setuptools.packages.find]"},{"line_number":81,"context_line":"include \u003d [\"keystoneauth1\"]"}],"source_content_type":"text/x-toml","patch_set":1,"id":"db2c33f1_1d9f9ccb","line":78,"in_reply_to":"7bbdbd9d_59f77d00","updated":"2026-08-20 19:35:50.000000000","message":"I\u0027ll write a separate patch for adding conflict resolution to ksa.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"3f7b083b5dc8c69168ba829fef9019b56b9cc0b4","unresolved":true,"context_lines":[{"line_number":75,"context_line":"v3multifactor \u003d \"keystoneauth1.loading._plugins.identity.v3:MultiFactor\""},{"line_number":76,"context_line":"v3oauth2clientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential\""},{"line_number":77,"context_line":"v3oauth2mtlsclientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2mTlsClientCredential\""},{"line_number":78,"context_line":"v3websso \u003d \"keystoneauth1.loading._plugins.identity.v3:WebSSO\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"[tool.setuptools.packages.find]"},{"line_number":81,"context_line":"include \u003d [\"keystoneauth1\"]"}],"source_content_type":"text/x-toml","patch_set":1,"id":"c0536930_b0a727d2","line":78,"in_reply_to":"8c45b2c6_1b86e97d","updated":"2026-08-12 22:42:37.000000000","message":"This was the suggestion by @stephenfin@redhat.com to use the name of the protocol provided by Keystone.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"change_message_id":"eb3008a1a01549aabd070dd56dff5479365c7f95","unresolved":true,"context_lines":[{"line_number":75,"context_line":"v3multifactor \u003d \"keystoneauth1.loading._plugins.identity.v3:MultiFactor\""},{"line_number":76,"context_line":"v3oauth2clientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential\""},{"line_number":77,"context_line":"v3oauth2mtlsclientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2mTlsClientCredential\""},{"line_number":78,"context_line":"v3websso \u003d \"keystoneauth1.loading._plugins.identity.v3:WebSSO\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"[tool.setuptools.packages.find]"},{"line_number":81,"context_line":"include \u003d [\"keystoneauth1\"]"}],"source_content_type":"text/x-toml","patch_set":1,"id":"21301f6f_8c22c8ac","line":78,"in_reply_to":"c0536930_b0a727d2","updated":"2026-08-12 23:15:00.000000000","message":"AI: The standard plugin name makes sense, but it does not resolve duplicate registration when `keystoneauth-websso` is still installed. Supported Stevedore versions can either raise on multiple matches or select one without a stable contract. Unless the external package can provide a transition release without that entry point, the release notes should tell users to remove it when upgrading.\n\nMe: so I think what it\u0027s saying is just that users (like myself) who upgrade to this version after it is released and already have the old websso plugin installed will have it pick randomly between the two (in worst case) or just pick the plugin version (also bad) and debugging would be a PITA to figure out \"oh it isn\u0027t even executing this code path\" because they have overlapping entrypoint names... so it wants a warning when that happens (which I think Stevedore does) but also just a comment in the release-notes to call it out so users can be aware they need to remove the old websso plugin package. I guess I\u0027d treat this as a nitpick, but it is a good callout and the \"fix\" is trivial, just a line in the reno file.","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"f69011b0ec1bffef88739c524c099159e521403c","unresolved":true,"context_lines":[{"line_number":75,"context_line":"v3multifactor \u003d \"keystoneauth1.loading._plugins.identity.v3:MultiFactor\""},{"line_number":76,"context_line":"v3oauth2clientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2ClientCredential\""},{"line_number":77,"context_line":"v3oauth2mtlsclientcredential \u003d \"keystoneauth1.loading._plugins.identity.v3:OAuth2mTlsClientCredential\""},{"line_number":78,"context_line":"v3websso \u003d \"keystoneauth1.loading._plugins.identity.v3:WebSSO\""},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"[tool.setuptools.packages.find]"},{"line_number":81,"context_line":"include \u003d [\"keystoneauth1\"]"}],"source_content_type":"text/x-toml","patch_set":1,"id":"7bbdbd9d_59f77d00","line":78,"in_reply_to":"c2a5c0f6_62b7a070","updated":"2026-08-18 16:07:53.000000000","message":"I couldn\u0027t really figure out how to use it from the stevedore docs. Got an example you can share?","commit_id":"59aec85557604ac405eea19aa02e07d4f2a645fa"}]}
