)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a100ba2e949434576f431245932f25ea85f7141b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"37bab352_310e5511","updated":"2026-08-24 14:25:54.000000000","message":"second thoughts...I\u0027m pushing a squash for this patch and suggesting we might treat the combination of squashes as a separate follow-on clean up patch?","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"e302684c_e8cc4111","updated":"2026-08-24 11:48:47.000000000","message":"will squash","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6c093a4fb178fee5be2e36e56ae79c0c7dae116b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"808ba49b_28215779","updated":"2026-08-24 19:56:17.000000000","message":"we should squash in the rest and take it further","commit_id":"50dda879f4a9d916b87157bca6164094b3c97fca"}],"swift/common/middleware/s3api/s3response.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":true,"context_lines":[{"line_number":141,"context_line":"                if is_swift3_sysmeta(_server_type, key):"},{"line_number":142,"context_line":"                    # To be compatible with older swift3, translate swift3"},{"line_number":143,"context_line":"                    # sysmeta to s3api sysmeta here"},{"line_number":144,"context_line":"                    key \u003d sysmeta_prefix(_server_type) + \\"},{"line_number":145,"context_line":"                        key[len(\u0027x-%s-sysmeta-swift3-\u0027 % _server_type):]"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"                    if key not in s3_sysmeta_headers:"}],"source_content_type":"text/x-python","patch_set":1,"id":"7f40060f_94032b67","side":"PARENT","line":144,"range":{"start_line":144,"start_character":26,"end_line":144,"end_character":40},"updated":"2026-08-24 11:48:47.000000000","message":"this was so potentially confusing","commit_id":"8c3f615c9f9b3d361e7e6f14552f7717376f1081"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":true,"context_lines":[{"line_number":130,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":131,"context_line":"        swob.Response.__init__(self, *args, **kwargs)"},{"line_number":132,"context_line":""},{"line_number":133,"context_line":"        s3api_sysmeta_headers \u003d swob.HeaderKeyDict()"},{"line_number":134,"context_line":"        sw_headers \u003d swob.HeaderKeyDict()"},{"line_number":135,"context_line":"        headers \u003d HeaderKeyDict()"},{"line_number":136,"context_line":"        self.is_slo \u003d False"}],"source_content_type":"text/x-python","patch_set":1,"id":"eef8b525_e8b63da2","line":133,"updated":"2026-08-24 11:48:47.000000000","message":"thanks","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":true,"context_lines":[{"line_number":192,"context_line":""},{"line_number":193,"context_line":"        # Used for pure swift header handling at the request layer"},{"line_number":194,"context_line":"        self.sw_headers \u003d sw_headers"},{"line_number":195,"context_line":"        self.sysmeta_headers \u003d s3api_sysmeta_headers"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":"    @classmethod"},{"line_number":198,"context_line":"    def from_swift_resp(cls, sw_resp):"}],"source_content_type":"text/x-python","patch_set":1,"id":"c2fa2b1d_103eeb88","line":195,"updated":"2026-08-24 11:48:47.000000000","message":"I\u0027d love to go one step further and rename the class variable to ``s3api_sysmeta_headers``. We could keep an alias for backwards compat and those who like to live with ambiguity.","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"}],"swift/common/middleware/s3api/utils.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":true,"context_lines":[{"line_number":51,"context_line":"    return sysmeta_prefix(resource) + name"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"def s3api_object_sysmeta_header(name):"},{"line_number":55,"context_line":"    \"\"\""},{"line_number":56,"context_line":"    Returns the ``s3api`` namespace object system metadata header for the given"},{"line_number":57,"context_line":"    name."}],"source_content_type":"text/x-python","patch_set":1,"id":"71f7e14a_a9cf9d2c","side":"PARENT","line":54,"updated":"2026-08-24 11:48:47.000000000","message":"oh did I only use it once. maybe I was mimicing ``swift3_object_sysmeta_header``","commit_id":"8c3f615c9f9b3d361e7e6f14552f7717376f1081"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":true,"context_lines":[{"line_number":33,"context_line":"MULTIUPLOAD_SUFFIX \u003d \u0027+segments\u0027"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"def s3api_sysmeta_prefix(resource):"},{"line_number":37,"context_line":"    \"\"\""},{"line_number":38,"context_line":"    Returns the system metadata prefix for given resource type."},{"line_number":39,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":1,"id":"d10a5c9f_68ee631f","line":36,"updated":"2026-08-24 11:48:47.000000000","message":"love it. I wanted to change this but told myself it was scope creep, but if you\u0027re on board then I am!","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a100ba2e949434576f431245932f25ea85f7141b","unresolved":true,"context_lines":[{"line_number":37,"context_line":"    \"\"\""},{"line_number":38,"context_line":"    Returns the system metadata prefix for given resource type."},{"line_number":39,"context_line":"    \"\"\""},{"line_number":40,"context_line":"    return get_sys_meta_prefix(resource) + \u0027s3api-\u0027"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"def s3api_sysmeta_header(resource, name):"}],"source_content_type":"text/x-python","patch_set":1,"id":"936b18ac_39e9c7e2","line":40,"updated":"2026-08-24 14:25:54.000000000","message":"this change broke a test (see below)\n\nQuestion is, should we retain leniency for out of tree callers?\n\n```\nFound it. It\u0027s a behaviour change in s3api_sysmeta_prefix().\n\nBefore (swift/common/middleware/s3api/utils.py):\ndef sysmeta_prefix(resource):\n    if resource.lower() \u003d\u003d \u0027object\u0027:\n        return \u0027x-object-sysmeta-s3api-\u0027\n    else:\n        return \u0027x-container-sysmeta-s3api-\u0027   # anything not \u0027object\u0027 -\u003e container\n\nAfter the commit:\ndef s3api_sysmeta_prefix(resource):\n    return get_sys_meta_prefix(resource) + \u0027s3api-\u0027   # \u0027x-\u003cresource\u003e-sysmeta-s3api-\u0027\n\nThe old version silently coerced any non-object resource string to container; the new one takes the resource name literally.\n\nThe test setup in test/unit/common/middleware/s3api/__init__.py:302-304 registers the sticky ACL for /v1/AUTH_test/authenticated with resource\u003d\u0027bucket\u0027:\n\nauthenticated_headers \u003d _gen_test_headers(\n    self.default_owner, [Grant(AuthenticatedUsers(), \u0027READ\u0027)],\n    \u0027bucket\u0027)\n\nThat now encodes to x-bucket-sysmeta-s3api-acl (verified) instead of x-container-sysmeta-s3api-acl. So the container response carries no recognised ACL header, S3Response parses an empty \u003cAccessControlList/\u003e (visible in the captured output), and the READ check fails → 403 instead of 200.\n\nTwo ways to fix:\n\n1. Fix the test — \u0027bucket\u0027 looks like a typo that the lenient old helper masked; every other call in that setup passes \u0027container\u0027 or \u0027object\u0027. Changing it to \u0027container\u0027 (or just dropping the third arg, since it defaults to \u0027container\u0027) restores the intended header.\n2. Restore leniency in the helper — keep the object/else coercion, but that re-introduces the silent mis-spelling tolerance the commit was deliberately removing, and get_sys_meta_prefix would also then accept \u0027account\u0027 oddly.\n```","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b61cb4f4d2dd308dc6f2806b6662e86df1c24205","unresolved":true,"context_lines":[{"line_number":51,"context_line":"# Keep the original short spellings as compatibility aliases. They are also"},{"line_number":52,"context_line":"# useful when this module supplies the S3API namespace."},{"line_number":53,"context_line":"sysmeta_prefix \u003d s3api_sysmeta_prefix"},{"line_number":54,"context_line":"sysmeta_header \u003d s3api_sysmeta_header"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"def is_s3api_sysmeta(server_type, name):"}],"source_content_type":"text/x-python","patch_set":1,"id":"6ee9bb0d_e8de8973","line":54,"updated":"2026-08-24 11:48:47.000000000","message":"fair enough but I might change the usages in test_s3response","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a100ba2e949434576f431245932f25ea85f7141b","unresolved":true,"context_lines":[{"line_number":51,"context_line":"# Keep the original short spellings as compatibility aliases. They are also"},{"line_number":52,"context_line":"# useful when this module supplies the S3API namespace."},{"line_number":53,"context_line":"sysmeta_prefix \u003d s3api_sysmeta_prefix"},{"line_number":54,"context_line":"sysmeta_header \u003d s3api_sysmeta_header"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"def is_s3api_sysmeta(server_type, name):"}],"source_content_type":"text/x-python","patch_set":1,"id":"fe676fc6_1b2577e8","line":54,"in_reply_to":"6ee9bb0d_e8de8973","updated":"2026-08-24 14:25:54.000000000","message":"and other places","commit_id":"a07c4a3733a09ad26f02c27d44443ce058d9dc2c"}]}
