)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ad06d4c2b5bbcf6912af589e3f94049cc23c8f22","unresolved":true,"context_lines":[{"line_number":20,"context_line":"request body has matched the supplied checksum. Return the checksum on"},{"line_number":21,"context_line":"PUT responses, and on whole-object GET/HEAD responses when the client"},{"line_number":22,"context_line":"requests x-amz-checksum-mode: ENABLED. Return checksum metadata on"},{"line_number":23,"context_line":"CopyObject requests aswell."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"For objects with versioning enabled, this patch adds the ability for"},{"line_number":26,"context_line":"footer callbacks to be automatically passed onto the hidden container"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"f6979cbe_f245fcf2","line":23,"updated":"2026-07-16 16:10:33.000000000","message":"s/aswell/as well","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c63ac75b45a4aee449aacd462f259b27b1d1b1c8","unresolved":false,"context_lines":[{"line_number":20,"context_line":"request body has matched the supplied checksum. Return the checksum on"},{"line_number":21,"context_line":"PUT responses, and on whole-object GET/HEAD responses when the client"},{"line_number":22,"context_line":"requests x-amz-checksum-mode: ENABLED. Return checksum metadata on"},{"line_number":23,"context_line":"CopyObject requests aswell."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"For objects with versioning enabled, this patch adds the ability for"},{"line_number":26,"context_line":"footer callbacks to be automatically passed onto the hidden container"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"cec86e92_75b03ac0","line":23,"in_reply_to":"f6979cbe_f245fcf2","updated":"2026-07-16 18:34:49.000000000","message":"Done","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ad06d4c2b5bbcf6912af589e3f94049cc23c8f22","unresolved":true,"context_lines":[{"line_number":33,"context_line":"AWS S3 upload checksum behavior:"},{"line_number":34,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"APIImpact"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"Change-Id: Ie957413640289c458db35c6e65dbdc0e71652322"},{"line_number":39,"context_line":"Signed-off-by: Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"942d84ba_2b62f613","line":36,"updated":"2026-07-16 16:10:33.000000000","message":"what are those ``APIImpact``?","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c63ac75b45a4aee449aacd462f259b27b1d1b1c8","unresolved":false,"context_lines":[{"line_number":33,"context_line":"AWS S3 upload checksum behavior:"},{"line_number":34,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"APIImpact"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"Change-Id: Ie957413640289c458db35c6e65dbdc0e71652322"},{"line_number":39,"context_line":"Signed-off-by: Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"f4f7d19d_e696337c","line":36,"in_reply_to":"942d84ba_2b62f613","updated":"2026-07-16 18:34:49.000000000","message":"I\u0027ve updated the commit message to denote what is changes to the API since new response headers are emitted.","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"629ce0d8b7dbd1e1ff4e6bfff96e31ef5e09ae86","unresolved":false,"context_lines":[{"line_number":33,"context_line":"AWS S3 upload checksum behavior:"},{"line_number":34,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"APIImpact"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"Change-Id: Ie957413640289c458db35c6e65dbdc0e71652322"},{"line_number":39,"context_line":"Signed-off-by: Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"f93070bf_ad75cf3e","line":36,"in_reply_to":"f4f7d19d_e696337c","updated":"2026-07-16 18:37:46.000000000","message":"https://docs.openstack.org/contributors/common/git.html\nThe following footers are optional; however, their use is recommended if they are applicable to the patch:\n\nThe APIImpact footer contains a comment about why the change impacts a public HTTP API. Put APIImpact on a line by itself. Use this footer to indicate that the patch impacts a public HTTP API. When this footer is included in a commit message, the API_Working_Group can use it to help find relevant reviews.","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ad06d4c2b5bbcf6912af589e3f94049cc23c8f22","unresolved":true,"context_lines":[{"line_number":35,"context_line":""},{"line_number":36,"context_line":"APIImpact"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"Change-Id: Ie957413640289c458db35c6e65dbdc0e71652322"},{"line_number":39,"context_line":"Signed-off-by: Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"9239885b_441a9606","line":38,"updated":"2026-07-16 16:10:33.000000000","message":"if Codex/Claude was used, please add ``Assisted-By: \u003ctool-name\u003e [model-version]`` per Openstack requirement: https://docs.openstack.org/cinder/latest/contributor/commit-messages.html","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c63ac75b45a4aee449aacd462f259b27b1d1b1c8","unresolved":false,"context_lines":[{"line_number":35,"context_line":""},{"line_number":36,"context_line":"APIImpact"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"Change-Id: Ie957413640289c458db35c6e65dbdc0e71652322"},{"line_number":39,"context_line":"Signed-off-by: Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"777284f8_d7e00697","line":38,"in_reply_to":"9239885b_441a9606","updated":"2026-07-16 18:34:49.000000000","message":"Done!","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1ba1ac1734e59a9fd4cb6f47aa534fdae8e12155","unresolved":true,"context_lines":[{"line_number":22,"context_line":"requests x-amz-checksum-mode: ENABLED. Return checksum metadata on"},{"line_number":23,"context_line":"CopyObject requests as well."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"CopyObject checksum computation is not supported, so when a client"},{"line_number":26,"context_line":"provides a x-amz-checksum-algorithm header on a CopyObject request,"},{"line_number":27,"context_line":"we deny the request."},{"line_number":28,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":54,"id":"d6b4b0be_b7c17bbd","line":25,"updated":"2026-08-06 16:56:38.000000000","message":"all ``CopyObject`` related sentences were removed. even though re-calculation on copy is going to be done in a follow-up patch, we still need to describe what current behaviors will be with this patch.\n\nI think they are:\n   - Source checksum, no requested algorithm: 200; copies checksum metadata without recalculation; no checksum in CopyObjectResult.\n   - Different algorithm requested: 200; requested algorithm is ignored and source checksum metadata remains.\n   - Source without checksum, no algorithm: 200; no checksum is created, unlike AWS’s default CRC64NVME; but will be supported later.","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":22,"context_line":"requests x-amz-checksum-mode: ENABLED. Return checksum metadata on"},{"line_number":23,"context_line":"CopyObject requests as well."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"CopyObject checksum computation is not supported, so when a client"},{"line_number":26,"context_line":"provides a x-amz-checksum-algorithm header on a CopyObject request,"},{"line_number":27,"context_line":"we deny the request."},{"line_number":28,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":54,"id":"70642e6e_49b72236","line":25,"in_reply_to":"061c338c_ae6e961b","updated":"2026-08-06 22:19:30.000000000","message":"This is great! Thank you for this!, I\u0027ll squash this in and update the commit message to note stuff to not expect.","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b1916a42dcbab8b9e9e28969e80f2afc57d8c446","unresolved":true,"context_lines":[{"line_number":22,"context_line":"requests x-amz-checksum-mode: ENABLED. Return checksum metadata on"},{"line_number":23,"context_line":"CopyObject requests as well."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"CopyObject checksum computation is not supported, so when a client"},{"line_number":26,"context_line":"provides a x-amz-checksum-algorithm header on a CopyObject request,"},{"line_number":27,"context_line":"we deny the request."},{"line_number":28,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":54,"id":"061c338c_ae6e961b","line":25,"in_reply_to":"d6b4b0be_b7c17bbd","updated":"2026-08-06 19:54:57.000000000","message":"and this patch needs test cases on those scenarios, even though it doesn\u0027t support re-calculation for copy yet. see \"1000035: sq? add test cases on checksum inheritence for server side copy. | https://review.opendev.org/c/openstack/swift/+/1000035\"","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1ba1ac1734e59a9fd4cb6f47aa534fdae8e12155","unresolved":true,"context_lines":[{"line_number":26,"context_line":"the versioned object is actually stored in, ensuring checksum sysmeta"},{"line_number":27,"context_line":"can be stored alongside the object body."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"The S3 API behavior changes for non-MPU objects:"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":32,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"806252b7_bccbad01","line":29,"updated":"2026-08-06 16:56:38.000000000","message":"also needs a line to describe that s3api checksum persistence won\u0027t be turned on as default if user doesn\u0027t supply checksum headers (which aws s3 does).","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":26,"context_line":"the versioned object is actually stored in, ensuring checksum sysmeta"},{"line_number":27,"context_line":"can be stored alongside the object body."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"The S3 API behavior changes for non-MPU objects:"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":32,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"901ac843_9e8d708a","line":29,"updated":"2026-08-06 15:45:39.000000000","message":"nit: might be useful to explicitly state that this patch does not persist checksums for MPUs","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":26,"context_line":"the versioned object is actually stored in, ensuring checksum sysmeta"},{"line_number":27,"context_line":"can be stored alongside the object body."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"The S3 API behavior changes for non-MPU objects:"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":32,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"d125f067_adc483d7","line":29,"in_reply_to":"806252b7_bccbad01","updated":"2026-08-06 22:19:30.000000000","message":"I\u0027ll include this!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":26,"context_line":"the versioned object is actually stored in, ensuring checksum sysmeta"},{"line_number":27,"context_line":"can be stored alongside the object body."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"The S3 API behavior changes for non-MPU objects:"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":32,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"9b484486_5f25a475","line":29,"in_reply_to":"901ac843_9e8d708a","updated":"2026-08-06 22:19:30.000000000","message":"Yea I think that is good, if we look at the patches as on their own","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":33,"context_line":""},{"line_number":34,"context_line":"* Whole-object GetObject and HeadObject requests return the stored"},{"line_number":35,"context_line":"  checksum (e.g x-amz-checksum-* and x-amz-checksum-type)"},{"line_number":36,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"* Unsupported x-amz-checksum-mode values (e.g anything NOT \u0027ENABLED\u0027)"},{"line_number":39,"context_line":"  return InvalidArgument."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"dcd9ed67_b8147e33","line":36,"updated":"2026-08-06 15:45:39.000000000","message":"compat test needed for a ranged request","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":33,"context_line":""},{"line_number":34,"context_line":"* Whole-object GetObject and HeadObject requests return the stored"},{"line_number":35,"context_line":"  checksum (e.g x-amz-checksum-* and x-amz-checksum-type)"},{"line_number":36,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"* Unsupported x-amz-checksum-mode values (e.g anything NOT \u0027ENABLED\u0027)"},{"line_number":39,"context_line":"  return InvalidArgument."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"48bf31b3_3d93fd17","line":36,"in_reply_to":"dcd9ed67_b8147e33","updated":"2026-08-06 22:19:30.000000000","message":"Thanks for the catch!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":36,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"* Unsupported x-amz-checksum-mode values (e.g anything NOT \u0027ENABLED\u0027)"},{"line_number":39,"context_line":"  return InvalidArgument."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"AWS S3 object integrity overview:"},{"line_number":42,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"b1577ef8_8af97783","line":39,"updated":"2026-08-06 15:45:39.000000000","message":"did you manage to write a compat test that sends anything other than ENABLED? I cannot persuade boto3 to use a different value :(","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":36,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"* Unsupported x-amz-checksum-mode values (e.g anything NOT \u0027ENABLED\u0027)"},{"line_number":39,"context_line":"  return InvalidArgument."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"AWS S3 object integrity overview:"},{"line_number":42,"context_line":"https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":59,"id":"2f655fc9_612578e5","line":39,"in_reply_to":"b1577ef8_8af97783","updated":"2026-08-06 22:19:30.000000000","message":"Ahhh yes we should have testing for this too! It looks like we can manipulate the headers before the request is sent in `boto3` with events https://docs.aws.amazon.com/botocore/latest/topics/events.html\n```\nevent_name \u003d \u0027before-call.s3.GetObject\u0027\nself.client.meta.events.register(\n  event_name, function_that_changes_x_amz_checksum_mode)\n```\n\nI guess `boto3` makes this tricky on purpose 😅","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"e69a95d39db76bb63c7ce0dbf1279728d6e384ad","unresolved":true,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"This patch does not add support for checksums on MPUs, meaning if"},{"line_number":33,"context_line":"a client tries to create a MPU with a x-amz-checksum-algorithm header"},{"line_number":34,"context_line":"or Upload a part with a checksum, then no checksum metadata with be"},{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":69,"id":"e100a309_bcb544d9","line":34,"updated":"2026-08-11 12:20:34.000000000","message":"typo here, should be \"no checksum *will* be persisted\"","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"964ac133bf12e9cb028d7905935205d08cdb5625","unresolved":false,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"This patch does not add support for checksums on MPUs, meaning if"},{"line_number":33,"context_line":"a client tries to create a MPU with a x-amz-checksum-algorithm header"},{"line_number":34,"context_line":"or Upload a part with a checksum, then no checksum metadata with be"},{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":69,"id":"30c4791e_be27afda","line":34,"in_reply_to":"8e40255a_d12c5165","updated":"2026-08-19 23:43:30.000000000","message":"Done","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"91de517bef747ac16ff22ccb3f21a62ec646b2f2","unresolved":true,"context_lines":[{"line_number":31,"context_line":""},{"line_number":32,"context_line":"This patch does not add support for checksums on MPUs, meaning if"},{"line_number":33,"context_line":"a client tries to create a MPU with a x-amz-checksum-algorithm header"},{"line_number":34,"context_line":"or Upload a part with a checksum, then no checksum metadata with be"},{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":69,"id":"8e40255a_d12c5165","line":34,"in_reply_to":"e100a309_bcb544d9","updated":"2026-08-11 19:32:38.000000000","message":"Oh thakns for catching this!, fixed!","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":32,"context_line":"This patch does not add support for checksums on MPUs, meaning if"},{"line_number":33,"context_line":"a client tries to create a MPU with a x-amz-checksum-algorithm header"},{"line_number":34,"context_line":"or Upload a part with a checksum, then no checksum metadata will be"},{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"},{"line_number":38,"context_line":"copy requests like CopyObject and UploadPartCopy. This means that"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"8aa55378_1efa0ed6","line":35,"range":{"start_line":35,"start_character":11,"end_line":35,"end_character":53},"updated":"2026-08-21 16:03:49.000000000","message":"nit: don\u0027t make promises in commit messages; it is sufficient to point out that this patch doesn\u0027t include that.","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":32,"context_line":"This patch does not add support for checksums on MPUs, meaning if"},{"line_number":33,"context_line":"a client tries to create a MPU with a x-amz-checksum-algorithm header"},{"line_number":34,"context_line":"or Upload a part with a checksum, then no checksum metadata will be"},{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"},{"line_number":38,"context_line":"copy requests like CopyObject and UploadPartCopy. This means that"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"205d04a8_040c45a3","line":35,"range":{"start_line":35,"start_character":11,"end_line":35,"end_character":53},"in_reply_to":"8aa55378_1efa0ed6","updated":"2026-08-21 20:10:41.000000000","message":"Yep I think thats good, will do!","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"},{"line_number":38,"context_line":"copy requests like CopyObject and UploadPartCopy. This means that"},{"line_number":39,"context_line":"if a copy is done a object that has checksum metadata, Swift will"},{"line_number":40,"context_line":"inherit the sysmeta from that source. Also if a client sends"},{"line_number":41,"context_line":"x-amz-checksum-algorithm on a CopyObject request, Swift will"},{"line_number":42,"context_line":"not use that checksum for anything. This is future support."},{"line_number":43,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"0d10e7fd_5335e0b0","line":40,"range":{"start_line":38,"start_character":50,"end_line":40,"end_character":36},"updated":"2026-08-21 16:03:49.000000000","message":"the language is little strange here: the *destination object* will inherit the checksum metadata","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":35,"context_line":"persisted. This will be implemented in future patches"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"This patch also does not add support for checksum recomputation on"},{"line_number":38,"context_line":"copy requests like CopyObject and UploadPartCopy. This means that"},{"line_number":39,"context_line":"if a copy is done a object that has checksum metadata, Swift will"},{"line_number":40,"context_line":"inherit the sysmeta from that source. Also if a client sends"},{"line_number":41,"context_line":"x-amz-checksum-algorithm on a CopyObject request, Swift will"},{"line_number":42,"context_line":"not use that checksum for anything. This is future support."},{"line_number":43,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"76949231_9f0be000","line":40,"range":{"start_line":38,"start_character":50,"end_line":40,"end_character":36},"in_reply_to":"0d10e7fd_5335e0b0","updated":"2026-08-21 20:10:41.000000000","message":"I think this is more straightforward","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":50,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":51,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Whole and ranged object GetObject and HeadObject requests return"},{"line_number":54,"context_line":"  the stored checksum (e.g x-amz-checksum-* and x-amz-checksum-type)"},{"line_number":55,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":56,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"00ca42a4_d3a8ba4b","line":53,"range":{"start_line":53,"start_character":12,"end_line":53,"end_character":18},"updated":"2026-08-21 16:03:49.000000000","message":"is this true? IIUC S3Response omits the headers if the request has a range","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":true,"context_lines":[{"line_number":50,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":51,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Whole and ranged object GetObject and HeadObject requests return"},{"line_number":54,"context_line":"  the stored checksum (e.g x-amz-checksum-* and x-amz-checksum-type)"},{"line_number":55,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":56,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"a7e7ac94_87f65903","line":53,"range":{"start_line":53,"start_character":12,"end_line":53,"end_character":18},"in_reply_to":"00ca42a4_d3a8ba4b","updated":"2026-08-21 20:10:41.000000000","message":"Oh good catch! will update the commit message, thanks!","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":50,"context_line":"* Successful PutObject requests with a validated x-amz-checksum-*"},{"line_number":51,"context_line":"  value return that checksum and x-amz-checksum-type: FULL_OBJECT."},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"* Whole and ranged object GetObject and HeadObject requests return"},{"line_number":54,"context_line":"  the stored checksum (e.g x-amz-checksum-* and x-amz-checksum-type)"},{"line_number":55,"context_line":"  when x-amz-checksum-mode: ENABLED is requested."},{"line_number":56,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":76,"id":"d9c67ebf_f97ef32e","line":53,"range":{"start_line":53,"start_character":12,"end_line":53,"end_character":18},"in_reply_to":"00ca42a4_d3a8ba4b","updated":"2026-08-21 20:10:41.000000000","message":"Yes S3Response omits the headers, thanks for the catch! Will update the commit message to reflect","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"4bbdbae3676bc264ae5f4fbf4ad6b3137ccac062","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"2c37decb_46de0dc6","updated":"2026-06-09 13:53:56.000000000","message":"Looks pretty good to me, but please see my inline comment.","commit_id":"1b912f91b63174a730697c8c0591ba2e8581a2c0"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"ab7abaf22dffecc0c9b790425b172643fc4ed89f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"9a3824fc_0296bed9","updated":"2026-06-17 23:30:17.000000000","message":"I mentioned it over on https://review.opendev.org/c/openstack/swift/+/993193 but I think it\u0027d be better to get the MD5 and SHA512 support into a separate patch. Certainly, as things stand, it\u0027s unfortunate that it isn\u0027t called out in *any* of the commit messages.","commit_id":"769d4f8b5ecd3672b9964697e0388e29916ec731"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"cfeefb4a_44c877af","updated":"2026-06-17 00:00:40.000000000","message":"sorry I didn\u0027t get further on this; FWIW all my initial attempts at agent assisted review of this change were VERY positive.  I think this tells us some important information:\n\n1) the commit message is good!  we know what we\u0027re doing and why\n2) the change works!  we store checksums in sysmeta - we return them on reads; that\u0027s huge!\n3) it\u0027s well tested!  I mean, it would probably be appropriate to add some s3api/functests - but for translating sysmeta headers the `status, headers, body \u003d self.call_s3api(req)` style unitests are actually really great.\n\nAs I worked my way through the diff I found some patterns that may not be blockers - but in aggregate may add up to some important material improvements to maintainability that might make these 700 new lines \"better\"\n\nThere was also some \"issue\" with noqa usedforsecurity md5 that kept popping up and I haven\u0027t had a chance to look into:\n\n```\n# Orchestrator Summary: Gerrit 991516 PS12\n\nChange: https://review.opendev.org/c/openstack/swift/+/991516\nTitle: s3api: User Checksum Persistence for Full Object Uploads\nPatch set: 12\nRef: refs/changes/16/991516/12\nCommit: 769d4f8b5ecd3672b9964697e0388e29916ec731\nParent: bab1688e2c91cb9866c714ee77bb8c45f6885e7b\nSlot: vsaio-1\n\nRecommendation: -1\n\n## Finding\n\n`swift/common/middleware/s3api/s3request.py:110` newly accepts\n`x-amz-checksum-md5` by mapping it to Swift\u0027s `md5` helper, but\n`_get_checksum_hasher()` calls that helper without `usedforsecurity\u003dFalse`.\nSwift\u0027s helper defaults to `usedforsecurity\u003dTrue` in\n`swift/common/utils/base.py:32-39`, unlike existing integrity-MD5 callers\nsuch as `S3Request.check_md5()`.\n\nConcrete failure path: on a Python/OpenSSL build that rejects MD5 for security\nuse, an S3 PUT with `x-amz-checksum-md5` reaches\n`S3Request.__init__() -\u003e _validate_checksum_headers() -\u003e\n_get_checksum_hasher(\u0027x-amz-checksum-md5\u0027)`. The MD5 constructor exception is\nnot caught by `_get_checksum_hasher()`, so S3API\u0027s top-level exception handler\nreturns `500 InternalError` before the object PUT reaches Swift.\n\nAcceptance condition: either use a non-security MD5 wrapper, e.g.\n`lambda: md5(usedforsecurity\u003dFalse)`, with focused coverage for MD5 checksum\nvalidation and persistence, or remove `x-amz-checksum-md5` from the supported\nchecksum table until it can be supported deliberately.\n\n## Non-Blocking Notes\n\n- The main CRC/SHA full-object checksum persistence path is coherent and has\n  direct unit coverage for successful PUT persistence, mismatch\n  non-persistence, copy exclusion, GET/HEAD checksum-mode gating, range/304\n  suppression, and sysmeta-to-response translation.\n- Algorithm-surface tests for `sha512` and known-unsupported `xxhash*` entries\n  would make the broadened checksum table easier to maintain.\n- I downgraded the defensive worker\u0027s duplicate byte-normalization concern in\n  `_remember_checksum()` to a cleanup note. It is unreachable from the current\n  production caller but does not create a concrete bad outcome.\n\n```\n\n... so I\u0027m posting what I have and I\u0027ll keep on it!","commit_id":"769d4f8b5ecd3672b9964697e0388e29916ec731"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"ab7abaf22dffecc0c9b790425b172643fc4ed89f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"a4de6471_4447829e","in_reply_to":"cfeefb4a_44c877af","updated":"2026-06-17 23:30:17.000000000","message":"\u003e There was also some \"issue\" with noqa usedforsecurity md5 that kept popping up and I haven\u0027t had a chance to look into\n\nYeah, it\u0027s telling you that this isn\u0027t going to work on a FIPS-enabled system. We have in-process func tests that run on that config (look for the `-fips` suffix on the jobs); we should probably make sure there\u0027s at least one test under `test/func` that exercises MD5 as s3api checksum.","commit_id":"769d4f8b5ecd3672b9964697e0388e29916ec731"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":25,"id":"849f0a47_c1b11de8","updated":"2026-06-30 23:51:02.000000000","message":"I wanted to push up what I got; honestly I have made enough time to actually PLAY with this change to say if I think it should merge or not - so i\u0027m only posting the stuff I\u0027ve seen/found that I would want to look at more.  Sorry.\n\n```\n# Nits\n\n- `swift/common/middleware/s3api/s3request.py:1637`: the\n  `get_checksum_headers` docstring could state that it returns `{}` before the\n  checksum has been fully validated.\n- `swift/common/middleware/s3api/s3response.py:130`: the helper docstring\n  could say it decides whether stored checksum sysmeta should be exposed as S3\n  checksum headers.\n- `test/unit/common/middleware/s3api/test_s3request.py:1662`: typo,\n  \"since no header to provided\" should be \"since no checksum header was\n  provided.\"\n```","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dc717074059fd84f9cbc4ab9e9f3082744ed1dc2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"36aa56f1_bb2823c1","updated":"2026-07-02 15:09:37.000000000","message":"I may be wrong but voting -1 to ensure the concern about versioning is flagged up","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ad06d4c2b5bbcf6912af589e3f94049cc23c8f22","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":37,"id":"e0bd347d_fdc606c8","updated":"2026-07-16 16:10:33.000000000","message":"this patch says \"User Checksum Persistence for Full Object Uploads\", but it covers MPU segment PUT accidentally, see my comments and test case.","commit_id":"7c52b631f5b0ff7385ebb9d6b8945fdb3d6d9617"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c63ac75b45a4aee449aacd462f259b27b1d1b1c8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":37,"id":"84904a26_0ec979f6","in_reply_to":"467c1451_0840eb35","updated":"2026-07-16 18:34:49.000000000","message":"Sqaushed in https://review.opendev.org/c/openstack/swift/+/991516/38\nThanks!","commit_id":"7c52b631f5b0ff7385ebb9d6b8945fdb3d6d9617"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"7ad9e8b55c6873a10482f48c6587338886f49421","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":37,"id":"467c1451_0840eb35","in_reply_to":"e0bd347d_fdc606c8","updated":"2026-07-16 17:02:11.000000000","message":"see test case and proposed fix at: https://review.opendev.org/c/openstack/swift/+/997623","commit_id":"7c52b631f5b0ff7385ebb9d6b8945fdb3d6d9617"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"eab4f2f634742a340710f8822161b2dccaf0e242","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"693c5bd7_e70f8c2e","updated":"2026-07-16 19:13:12.000000000","message":"Added handling for case when POST ?delete` checksum callbacks can pollute versioned delete markers.\n\nThanks Clay and Codex!","commit_id":"66562ca79f57f52f34cc17487020652b4611f619"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":44,"id":"22747d86_8d3ecc43","updated":"2026-07-22 01:29:15.000000000","message":"The core design is sound and good implementation in general, ``-1`` because two edge cases identified for CopyObject.","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":45,"id":"6cc0ac59_2dc64e5c","updated":"2026-07-22 17:00:18.000000000","message":"Handling for x-amz-checksum-algorithm header in CopyObject request finished and fixed race condition for stale checksum metadata in CopyObject request.","commit_id":"d6bd5b38f367e70690be6178835908b61565a373"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"1cb3f60937811ef6d7054beadbf1b61179810245","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"5dd3bc21_8f89eb76","updated":"2026-07-24 18:30:53.000000000","message":"With the addition of throwing 501 on x-amz-checksum-algorithm on CopyObject requests, we should make this optional. Moving into a different patch","commit_id":"af40d2205789c4df20dcad5d78b7319d35f9937f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"8ad9826b63dc1605eef6be115d46dd3e308d3485","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"839c62ba_2344369c","in_reply_to":"5dd3bc21_8f89eb76","updated":"2026-07-27 17:01:24.000000000","message":"No, don\u0027t do this nate, more S3 likeness is better!","commit_id":"af40d2205789c4df20dcad5d78b7319d35f9937f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"107c8ddb0ef0a2d0edfefc5a65978aa3dd218354","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":48,"id":"0fe03611_ba792c51","updated":"2026-07-24 19:21:54.000000000","message":"Removed throwing errors when client provides x-amz-checksum-mode: \u003cANYTHING-NOT-\u0027ENABLED\u0027\u003e aswell","commit_id":"10b524acd843f58d34d2e39e1a2233a530212ffa"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f53fb482f29dc21cae6eb510b2083b525d8b0cf9","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":54,"id":"bc58b394_e5baeb43","updated":"2026-07-29 21:58:46.000000000","message":"Nice work, each iteration is getting better and closer!\n\nAfter reading the CopyObject description from https://docs.aws.amazon.com/AmazonS3/latest/userguide/copy-object.html#copy-object-checksums, I found it says\n```\nWhen copying objects, you can choose to use a different checksum algorithm for the object. Whether you\nchoose to use the same algorithm or a new one, Amazon S3 calculates a new checksum value after the object\nis copied. Amazon S3 doesn\u0027t directly copy the value of the checksum. All copied objects without \nchecksums and specified destination checksum algorithms automatically gain a CRC-64NVME checksum \nalgorithm.\n```\nthat means aws doesn’t copy checksum, but automatically calculate a CRC-64NVME checksum if user doesn’t specify one.\n\nSo for full object upload, #2 and #3 are the gaps in terms of compatibility.\n\n1. if source has checksum, no algorithm requested, the current result is same despite different behavior: AWS recalculates using the source, swift copies algorithm/type and value.\n2. Different algorithm requested: AWS calculates using requested algorithm, swift (current patch) returns “501 Not Implemented”\n3. Source has no checksum, no algorithm requested: AWS calculates CRC64NVME, while swift  (current patch) stores/returns no checksum\n\nI feel even full object upload needs the support of checksum re-calculation for copy-object, would like to hear what other core reviewers think.","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"47b03f18b11a78ec32cb15b01c24f2c51855ee41","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":54,"id":"4ec6a3c3_4df22bbb","in_reply_to":"81d0febe_2352e12e","updated":"2026-07-31 20:23:11.000000000","message":"See 999457: s3api: Recompute Checksums for CopyObject and UploadPartCopy | https://review.opendev.org/c/openstack/swift/+/999457","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ae040053f6e786ffa7e5df93d7ef7fd75417e007","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":54,"id":"81d0febe_2352e12e","in_reply_to":"bc58b394_e5baeb43","updated":"2026-07-30 21:21:59.000000000","message":"I think the best source of action as we discussed is to move all checksum persistence relating to copying into its own patch so we can add copy checksum recomputation.\n\nThough this means that objects that are created with checksum sysmeta and then are copied, will have checksum metadata that may not be accurate to their value (specifically in UploadCopyPart range requests)","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":59,"id":"cde59477_0d9ddedc","updated":"2026-08-06 15:45:39.000000000","message":"@Nate nice work. IME the s3api code and S3Request in particular is not easy to work with; kudos for plumbing in a working new feature.\n\nI haven\u0027t yet gone through the tests but it all seems to work. Most of my comments concern the structure of the code; it\u0027s because of my experience in S3Request that I\u0027d like to push for cleaner/simpler approach to the new method/interfaces. I\u0027ve left suggestions here for you to review and take *as you see fit*: https://review.opendev.org/c/openstack/swift/+/999988","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b1916a42dcbab8b9e9e28969e80f2afc57d8c446","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":59,"id":"e9245150_18dbc68a","updated":"2026-08-06 19:54:57.000000000","message":"We would still need test cases to verify the current checksum inherence behaviors, since re-calculation on server side copy is a standalone patch. \n\nSee related test cases at: \"1000035: sq? add test cases on checksum inheritence for server side copy. | https://review.opendev.org/c/openstack/swift/+/1000035\". \n\nand the patch \"999457: s3api: Recompute Checksums for CopyObject and UploadPartCopy | https://review.opendev.org/c/openstack/swift/+/999457\" can remove/update those test cases since it has test cases to cover those scenarios with different behaviors.","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":59,"id":"bd7f7a7c_9a56dc1b","in_reply_to":"2740abe8_5fdd75c3","updated":"2026-08-10 15:43:21.000000000","message":"Darn! It must have been a rebase issue, sorry! Thanks for catching this!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":59,"id":"2740abe8_5fdd75c3","in_reply_to":"8f56d4dc_92bcc51b","updated":"2026-08-08 00:48:06.000000000","message":"not sure why those tests were removed again in patchset 66","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4f630d71fb72d8951d3742c8d76ed1bb28f5922b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":59,"id":"556a1631_2e20798e","in_reply_to":"bd7f7a7c_9a56dc1b","updated":"2026-08-10 19:15:14.000000000","message":"Done","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":59,"id":"8f56d4dc_92bcc51b","in_reply_to":"e9245150_18dbc68a","updated":"2026-08-06 22:19:30.000000000","message":"I agree! Lets squash em in! Thank you so much for this!!!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":61,"id":"c622a712_d55f5ded","updated":"2026-08-06 22:19:30.000000000","message":"@alistairncoles@gmail.com I squashed in your patch 999988: sq? fixups for s3api checksum persistence | https://review.opendev.org/c/openstack/swift/+/999988 and added some compat tests for ranged requests, thanks for this!\n\n@jhuo@nvidia.com I also squashed in your patch 1000035: sq? add test cases on checksum inheritence for server side copy. | https://review.opendev.org/c/openstack/swift/+/1000035 , I\u0027ll update the future 999457: s3api: Recompute Checksums for CopyObject and UploadPartCopy | https://review.opendev.org/c/openstack/swift/+/999457 to remove/update them.\n\nI also updated the commit message to address no checksum mpus, no default checksums, and no checksum copy support.","commit_id":"3dc002b4683eea6405b0861aa869e88b436b4479"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":66,"id":"c2a87c95_bbcf44b4","updated":"2026-08-08 00:48:06.000000000","message":"there are still a few test scenarios missing in this patch:\n1. SDK-generated aws-chunked trailer, PUT echo, then HEAD/GET persistence.\n2. Zero-byte ordinary PUT with Content-Length: 0\n3. Version overwrites using different algorithms, and verify both historical versions plus the latest.\n4. S3 checksum persistence through the encryption pipeline, since both middlewares will install footer callback, we need to make sure both will succeed.\n\nsee those new tests at \"sq? more tests | https://review.opendev.org/c/openstack/swift/+/1000167\"","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a34d499787da38f221469b9f394f0a7b543b1dba","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":66,"id":"894e987c_8300c36d","in_reply_to":"92aaee53_24a47d06","updated":"2026-08-10 18:26:48.000000000","message":"Yes!! 😃","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":66,"id":"ed419083_6de132d9","in_reply_to":"c2a87c95_bbcf44b4","updated":"2026-08-10 15:43:21.000000000","message":"I think these are all great tests!\nI am KINDA skeptical on:\n\u003e SDK-generated aws-chunked trailer, PUT echo, then HEAD/GET persistence.\n\n\nSince we cannot really test this locally in a SAIO, though I think its fine because we can still point this test at some production system, so I am fine with this.","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"2b693ca2e77b2d5c7cb1e7d440e62ae69c4590af","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":66,"id":"c65ec6a3_084ffc31","in_reply_to":"c2a87c95_bbcf44b4","updated":"2026-08-10 01:39:09.000000000","message":"for the first case \"SDK-generated aws-chunked trailer, PUT echo, then HEAD/GET persistence\", initially I added a test ``test_sdk_generated_aws_chunked_trailer_persistence`` in test/s3api/test_object_checksums.py, but that test would be skipped in zuul because zuul won\u0027t run HTTPS/TLS by default I think. So I am working on a new test called ``test_strm_unsgnd_pyld_trl_with_trailer_persistence`` in test/s3api/test_input_errors.py, will upload later.","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f298a94707f3b8206bbb52a7b02b60d417621770","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":66,"id":"92aaee53_24a47d06","in_reply_to":"ed419083_6de132d9","updated":"2026-08-10 18:03:52.000000000","message":"we would prefer to have test running in the zuul instead of being skipped, check out this: 1000359: sq? use a determined setup to run aws-chunked request with checksum | https://review.opendev.org/c/openstack/swift/+/1000359","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":67,"id":"7185edb4_3288ab91","updated":"2026-08-10 15:43:21.000000000","message":"I\u0027ve squashed in 1000167: sq? more tests | https://review.opendev.org/c/openstack/swift/+/1000167\n\nThanks for this!","commit_id":"5019ee3b720270fec440c05b2171681059197127"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4f630d71fb72d8951d3742c8d76ed1bb28f5922b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":68,"id":"812ac4be_839529ed","updated":"2026-08-10 19:15:14.000000000","message":"I am aware that there is new discussion in MPU checksum patch and it may lead to refactoring in ``s3request.py`` of this patch. ``+1`` because the current form of this patch works in terms of functionalities and good coverages of test cases.","commit_id":"4a37a6dcc1103391c4883d37e79ed938084a0560"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"61fdd214c1b5fba0ef80de0cb410c22aba8b6f45","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":69,"id":"37c87868_420fec96","updated":"2026-08-10 23:35:35.000000000","message":"In regards to the refactor, the big changes are:\n\n- Moves checksum-persistence opt-in to `ObjectController`.\n\n- Adds explicit persist_request_checksum(checksum_type) request behavior.\n\n- Installs footer callback only when persist_request_checksum(...) is called.\n\nThis I feel is going to to help with the seperation of concerns that should exists between the `S3Request` and the controllers.","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"e69a95d39db76bb63c7ce0dbf1279728d6e384ad","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":69,"id":"46edb630_455588b6","updated":"2026-08-11 12:20:34.000000000","message":"The core design is great and all major open threads appear to be addressed. Good test coverage. I added two small comments but overall looks good to me.","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"91de517bef747ac16ff22ccb3f21a62ec646b2f2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":70,"id":"6a72e976_55b925c4","updated":"2026-08-11 19:32:38.000000000","message":"In later patches, we add a `checksum.py` module, though since the MPU patch is going to add a lot of checksum checking code and whatnot, it might be better to introduce it earlier","commit_id":"f17e481e43ed67aa12c4a11be3ae2ee5386ff0d9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"bd8c8f13f05a76446a6afadd5c5ccad2ff87cfdb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":75,"id":"41808a87_01f6e4ff","updated":"2026-08-20 00:00:50.000000000","message":"recheck","commit_id":"9775ca346ed14aec2b73086e0bf702ee56d015a2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":76,"id":"8651124f_106c1479","updated":"2026-08-21 16:03:49.000000000","message":"suggestion here sq? object controller can install checksum resp headers  https://review.opendev.org/c/openstack/swift/+/1001845\n\nI realise this ^^^ may not hold up in the face of later MPU changes but I\u0027d like to explore the better separation","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":78,"id":"799b1d03_7ea80bf1","updated":"2026-08-21 20:10:41.000000000","message":"OK this patchset takes the 1001845: sq? object controller can install checksum resp headers | https://review.opendev.org/c/openstack/swift/+/1001845 point of view being seperation of concerns, which works out better for the request and response classes doing less now! Some tests were removed in `test_s3response.py` because of this, but coverage is added by `test_obj.py`","commit_id":"f4f6abd3d40b743bc28846210baea1304be9777d"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"2964d28fed3b158d756465e204017af7b533d1b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":82,"id":"db9190de_319f2da9","updated":"2026-08-25 13:37:05.000000000","message":"90% of the patch are tests - and I didn\u0027t reviewed them all yet. Code in swift/ LGTM.","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6290d449798b3f5b185f1af3e31205b9652045b1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":82,"id":"16752115_ccc27b0e","updated":"2026-08-25 17:46:23.000000000","message":"Rebased to fix merge conflicts.\n\nI need to look over the tests.\n\nI satisfied myself that the checksums are not copied, now that we have the s3api copy hook removing *all* sysmeta from the copy path. Verified using https://review.opendev.org/c/openstack/swift/+/1002364 (no need to squash that in)","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c447a2ef02b5b918e6db8ebdfc189307d0bde06b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":82,"id":"ac325aa2_c5910e15","in_reply_to":"16752115_ccc27b0e","updated":"2026-08-25 23:05:51.000000000","message":"I\u0027m gonna squash this in b/c its at the bottom of the chain and a new merge conflict has arised 😀","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"29f79f5152ff8ee99b2fb3c159f7d299f01efdf4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":82,"id":"bd86b5ab_872809e9","in_reply_to":"ac325aa2_c5910e15","updated":"2026-08-25 23:34:16.000000000","message":"Actually.... its more of a follow up... we leave alone","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c447a2ef02b5b918e6db8ebdfc189307d0bde06b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":83,"id":"acf56959_a03789fa","updated":"2026-08-25 23:05:51.000000000","message":"Though I don\u0027t want to get rid of the +1 from @alistairncoles@gmail.com, we cannot merge anyways cause of conflicts 🙃","commit_id":"3efbd20e1996455bcbad415a2b7794789cac731d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2d8e0129e333b59e5c293c0da00041eac367e033","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":83,"id":"4975f3fb_9ed251db","updated":"2026-08-25 17:46:40.000000000","message":"a","commit_id":"3efbd20e1996455bcbad415a2b7794789cac731d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6f86a40071135bc1ee5d159805f46d380cd46cd5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"a4aacf58_914e5ef2","updated":"2026-08-27 12:16:10.000000000","message":"I have some func/probe test follow up here that gave me confidence about this patch 1002364: tests: check s3 checksum sysmeta is not copied | https://review.opendev.org/c/openstack/swift/+/1002364","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"7de4f17fdacea5f10bef638239511adeecaf14fd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"92fdd539_bbfbaaaa","updated":"2026-08-27 10:38:52.000000000","message":"I proposed a short follow up to clean up tests: 1002624: s3api: Tidy up checksum persistence tests | https://review.opendev.org/c/openstack/swift/+/1002624","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"385b77046e54eb9483abaa3dcce7624b4c02dae7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"76f77480_254cba92","updated":"2026-08-27 10:54:46.000000000","message":"I\u0027m happy with this but don\u0027t feel I can +2/merge because (a) I have had quite a lot of input and (b) I have not fully reviewed the tests.","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"c4031303b924113f70d9ac7f963fcf13042c233e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"c2dfb6c3_e40b55a2","updated":"2026-08-27 12:02:01.000000000","message":"No blocker from my side. I\u0027m close to a +2.\n\nThere are a few minor issues with the tests; I proposed a cleanup in 1002624: s3api: Tidy up checksum persistence tests | https://review.opendev.org/c/openstack/swift/+/1002624.\n\nOne minor issue on the compatibility page, see my inline comment.","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"75cbcab5111e121ae73c008099ad6af30037c510","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":87,"id":"2b2aaabf_d58247b2","updated":"2026-08-27 05:56:36.000000000","message":"This change mainly removes the need for passing in a checksum type to enable persistence. We will just write down the type at all type, and the type will be FULL_OBJECT. This makes things easier to follow","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"5790b23809da5449dfee584f0e60532c5ac703bb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":88,"id":"4544234e_037743e4","updated":"2026-08-31 16:32:12.000000000","message":"For reference, I used the following on my SAIO after enabling encryption in the proxy:\n\n```\necho hello \u003e obj\naws --endpoint-url http://localhost:8080 s3api create-bucket --bucket sample\naws --endpoint-url http://localhost:8080 s3api put-object --bucket sample --key obj --body obj --checksum-algorithm CRC32\nfind /srv/ -name \"*.data\" -mmin -5\nswift-object-info \u003cfilename\u003e\n```","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"7d0706a66f21456700543dadce7b82f9fea24b3f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":88,"id":"ec956817_6b0c5994","updated":"2026-08-31 16:00:26.000000000","message":"Found an issue, please have a look inline","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8131b1e48565ad07696e55ce3534fbc4f7983d65","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":88,"id":"858405a9_6bcb7e8c","updated":"2026-08-31 05:15:28.000000000","message":"nice code polishing after my previous +1, add mine back","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a707a9fcbb97b78a8d17d2442c77f0155d93d2d2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":88,"id":"8a34a795_d9e0c42e","updated":"2026-08-28 12:07:54.000000000","message":"restoring my vote after the rebase","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3cc5eaf83b8dd84d7dc6d679d59b48ddc8d3807e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":98,"id":"edf69f8d_b17b5a86","updated":"2026-09-19 20:02:19.000000000","message":"recheck retry limit","commit_id":"8674aad0b5b7d859bff8a917a40cf82f4e8925cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"0f58328bf0127e8f8cef7b1f5b6c4f07e3087c25","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":99,"id":"24dfc7fc_de7c8097","updated":"2026-10-02 00:18:41.000000000","message":"checksum patches need a feature flag:\n1. to avoid using sentinel in the follow-up MPU patches; MPU checksum persistence patch uses an upload_id based sentinel to identify cases that old-proxy-server (prior to s3api copy-hook) does range copy and create incorrect checksum. The upload_id based sentinel would be stored just for upgrade purpose, this piece of metadata stored on disk becomes meaningless after upgrade.\n2. checksum value will be encrypted when saved, there are some scenarios would run into similar rolling upgrade issues with the encryption implementation (e.g. also the old-proxy prior to s3api copy-hook), this feature flag will fix those too.","commit_id":"e91979b4adbd5384a4272d6ff11fc1e6205dcd30"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":101,"id":"0104c387_b2fe2ee7","updated":"2026-10-07 04:11:56.000000000","message":"Created common helper functions, or combined some tests together with subTest, and readability of those tests actually have been improved quite a lot.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"84a2cb66fd1e3d7d14e244059726986083f4eb66","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":107,"id":"35ffad21_4d5c4092","updated":"2026-10-29 06:03:51.000000000","message":"Looks good to me. I know I\u0027m not an s3api expert, but looking good, and with the encryption header registry as a parent, nice.","commit_id":"f7d7645298093e84f6260affe893f699a891ca64"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":108,"id":"3a947f81_b1ea120f","updated":"2026-10-30 18:13:29.000000000","message":"review still in progress, no blockers found yet, but some questions","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":109,"id":"c5d82266_5cf50ad0","updated":"2026-11-03 12:47:48.000000000","message":"@jhuo@nvidia.com I think it would be worth us making a plan for documentation of upgrade procedures in one place that is very obvious to a deployer.","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"272f9eaded850ca5883b2935429dadfd89c3021f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":109,"id":"a2b48a68_d45da189","updated":"2026-11-02 05:14:43.000000000","message":"I have local changes to address the those ``doc`` comments, no code changes, will push up tomorrow.","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"c325b7caf9dce11db8dcc50ee2a87bfe5212b634","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":109,"id":"5684fe99_4be777d7","updated":"2026-10-30 23:58:34.000000000","message":"some straight forward code rearrangement to avoid conflicts with other standing gerrit patches","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"doc/saio/swift/proxy-server.conf":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0b157087ff79ea460607c8e6c644447fa545b327","unresolved":true,"context_lines":[{"line_number":89,"context_line":"# To enable, add the s3api middleware to the pipeline before tempauth"},{"line_number":90,"context_line":"[filter:s3api]"},{"line_number":91,"context_line":"use \u003d egg:swift#s3api"},{"line_number":92,"context_line":"allow_store_checksums \u003d true"},{"line_number":93,"context_line":"s3_acl \u003d yes"},{"line_number":94,"context_line":"check_bucket_owner \u003d yes"},{"line_number":95,"context_line":"cors_preflight_allow_origin \u003d *"}],"source_content_type":"text/plain","patch_set":109,"id":"126ac1b5_58493643","line":92,"updated":"2026-11-02 13:12:43.000000000","message":"in other places, and throughout development, we have referred to \"checksum persistence\"; store_checksums seems anomalous\n\nFor example, this seems like an unnecessary naming inconsistency:\n\n```\ndef _require_checksum_persistence(self):\n        if not self.cluster_info.get(\u0027s3api\u0027, {}).get(\n                \u0027allow_store_checksums\u0027, False)\n```\n\nFWIW, I would prefer the config option to be ``allow_checksum_persistence`` because it\u0027s what I have as ingrained thinking and IMHO more grammatically correct as a phrase (but I could be wrong on that!)","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"doc/source/s3_compat.rst":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"c4031303b924113f70d9ac7f963fcf13042c233e","unresolved":true,"context_lines":[{"line_number":28,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":29,"context_line":"| `PUT Object Copy`_                             | Core-API         | Yes          |"},{"line_number":30,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":31,"context_line":"| `Object checksums`_                            | Core-API         | Yes          |"},{"line_number":32,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":33,"context_line":"| `DELETE Object`_                               | Core-API         | Yes          |"},{"line_number":34,"context_line":"+------------------------------------------------+------------------+--------------+"}],"source_content_type":"text/x-rst","patch_set":87,"id":"5c46bf34_8a01c861","line":31,"updated":"2026-08-27 12:02:01.000000000","message":"Not a blocker, but this is not fully correct - the commit message itself lists cases that are not supported yet. A user looking at this table when the later patches are not merged yet does not know about this.\n\nFrom the commit msg:\n\n\u003e     \"This patch does not add support for checksums on MPUs, ...\"\n\u003e     \" This patch also does not add support for checksum recomputation on copy requests like CopyObject and UploadPartCopy\"\n\u003e     \"This patch also does not add support for default checksums\"\n\nMight be worth an entry in the footnote.","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":28,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":29,"context_line":"| `PUT Object Copy`_                             | Core-API         | Yes          |"},{"line_number":30,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":31,"context_line":"| `Object checksums`_                            | Core-API         | Yes          |"},{"line_number":32,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":33,"context_line":"| `DELETE Object`_                               | Core-API         | Yes          |"},{"line_number":34,"context_line":"+------------------------------------------------+------------------+--------------+"}],"source_content_type":"text/x-rst","patch_set":87,"id":"116ebeb2_3d99e64f","line":31,"in_reply_to":"08504bf7_0df03186","updated":"2026-09-11 10:33:53.000000000","message":"I\u0027ve incorporated similar to Nate\u0027s https://review.opendev.org/c/openstack/swift/+/1002706 in the next patchset of this change.","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7f71f8ebd624907864facd984796cef19179b815","unresolved":true,"context_lines":[{"line_number":28,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":29,"context_line":"| `PUT Object Copy`_                             | Core-API         | Yes          |"},{"line_number":30,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":31,"context_line":"| `Object checksums`_                            | Core-API         | Yes          |"},{"line_number":32,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":33,"context_line":"| `DELETE Object`_                               | Core-API         | Yes          |"},{"line_number":34,"context_line":"+------------------------------------------------+------------------+--------------+"}],"source_content_type":"text/x-rst","patch_set":87,"id":"08504bf7_0df03186","line":31,"in_reply_to":"5c46bf34_8a01c861","updated":"2026-08-27 22:50:10.000000000","message":"Good point... I throw a patch up to clean this up\nSee 1002706: docs: document s3api object checksum support | https://review.opendev.org/c/openstack/swift/+/1002706","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8acecfe01ff9d0c2d837fe4ada255c3aad4616ba","unresolved":true,"context_lines":[{"line_number":119,"context_line":"* Persistence of a validated checksum for `Complete Multipart Upload`_ and"},{"line_number":120,"context_line":"  `Upload Part`_ requests."},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"* Re-calculation of checksum values during `PUT Object Copy`_ and"},{"line_number":123,"context_line":"  `Upload Part Copy`_ requests."},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"* Inclusion of the per-object checksum algorithm and type in bucket listing"}],"source_content_type":"text/x-rst","patch_set":98,"id":"51f7bd04_e874bf71","line":122,"updated":"2026-09-21 17:46:20.000000000","message":"we should also extend this sentence to exclude ``swift api range copy``.\ne.g. this is the case we discussed in the past\n```\nDuring a rolling upgrade, Swift API range COPY requests on normal objects with\nstored S3 checksums through old proxies that lack the S3API copy hook. These\nproxies can copy the source checksum onto a partial destination object. A later\nS3 GET or HEAD with checksum mode enabled can then return an incorrect checksum.\n```","commit_id":"8674aad0b5b7d859bff8a917a40cf82f4e8925cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"c6212ddfac1008588495beaa1b3765bfeb67c7da","unresolved":false,"context_lines":[{"line_number":119,"context_line":"* Persistence of a validated checksum for `Complete Multipart Upload`_ and"},{"line_number":120,"context_line":"  `Upload Part`_ requests."},{"line_number":121,"context_line":""},{"line_number":122,"context_line":"* Re-calculation of checksum values during `PUT Object Copy`_ and"},{"line_number":123,"context_line":"  `Upload Part Copy`_ requests."},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"* Inclusion of the per-object checksum algorithm and type in bucket listing"}],"source_content_type":"text/x-rst","patch_set":98,"id":"a90d6887_3d7249c2","line":122,"in_reply_to":"51f7bd04_e874bf71","updated":"2026-10-02 00:24:55.000000000","message":"Acknowledged","commit_id":"8674aad0b5b7d859bff8a917a40cf82f4e8925cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0b157087ff79ea460607c8e6c644447fa545b327","unresolved":true,"context_lines":[{"line_number":28,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":29,"context_line":"| `PUT Object Copy`_                             | Core-API         | Yes          |"},{"line_number":30,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":31,"context_line":"| `Object checksums`_                            | Core-API         | Partial      |"},{"line_number":32,"context_line":"+------------------------------------------------+------------------+--------------+"},{"line_number":33,"context_line":"| `DELETE Object`_                               | Core-API         | Yes          |"},{"line_number":34,"context_line":"+------------------------------------------------+------------------+--------------+"}],"source_content_type":"text/x-rst","patch_set":109,"id":"99c581ed_a70d7ccd","line":31,"updated":"2026-11-02 13:12:43.000000000","message":"we need to have a note at least that this depends on config","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":true,"context_lines":[{"line_number":100,"context_line":"  fixed-length body and a checksum trailer on a SigV4 ``aws-chunked`` body."},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* Optional persistence of a validated checksum for a `PUT Object`_ request."},{"line_number":103,"context_line":"  Set ``allow_store_checksums \u003d true`` in ``[filter:s3api]`` to enable it."},{"line_number":104,"context_line":"  The default is ``false``. When enabled, the checksum header is returned"},{"line_number":105,"context_line":"  with the `PUT Object`_ response along with"},{"line_number":106,"context_line":"  ``x-amz-checksum-type: FULL_OBJECT``. S3API registers the checksum value as"}],"source_content_type":"text/x-rst","patch_set":109,"id":"7f925824_bd0fef1d","line":103,"updated":"2026-11-03 12:47:48.000000000","message":"I think it would be great to have ONE place in deployment guidelines where enabling checksum persistence, and sensitive sysmeta, is documented, but I don\u0027t think it should be in this doc whose scope is to enumerate compatibility. It\u0027s not obvious to me that a deployer would be expected to read *this* doc before upgrading a cluster.\n\nLet\u0027s figure out where we document upgrade considerations, and then reference that from here. Perhaps in doc/source/deployment_guide.rst ?\n\nSo something like:\n```\nOnce `checksum persistence`_ has been enabled, persistence of a validated...\n```","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":true,"context_lines":[{"line_number":103,"context_line":"  Set ``allow_store_checksums \u003d true`` in ``[filter:s3api]`` to enable it."},{"line_number":104,"context_line":"  The default is ``false``. When enabled, the checksum header is returned"},{"line_number":105,"context_line":"  with the `PUT Object`_ response along with"},{"line_number":106,"context_line":"  ``x-amz-checksum-type: FULL_OBJECT``. S3API registers the checksum value as"},{"line_number":107,"context_line":"  :ref:`sensitive sysmeta \u003csensitive_sysmeta\u003e` even when persistence is off."},{"line_number":108,"context_line":"  Before you enable it, upgrade all applicable proxy and internal applications"},{"line_number":109,"context_line":"  that read, write, or copy these objects. Keep S3API registration and COPY"},{"line_number":110,"context_line":"  cleanup in each applicable process. Drain old workers, then enable the"}],"source_content_type":"text/x-rst","patch_set":109,"id":"fe99c69c_bc82af45","line":107,"range":{"start_line":106,"start_character":40,"end_line":107,"end_character":76},"updated":"2026-11-03 12:47:48.000000000","message":"This is a Swift implementation detail, not related to compatibility.","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":true,"context_lines":[{"line_number":109,"context_line":"  that read, write, or copy these objects. Keep S3API registration and COPY"},{"line_number":110,"context_line":"  cleanup in each applicable process. Drain old workers, then enable the"},{"line_number":111,"context_line":"  option and reload the applications. Disabling the option stops new checksum"},{"line_number":112,"context_line":"  writes. Existing checksum reads, decryption, and COPY protection continue."},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"* Return of a checksum header with a `GET Object`_ or `HEAD Object`_ response"},{"line_number":115,"context_line":"  when the client sends ``x-amz-checksum-mode: ENABLED`` and the checksum has"}],"source_content_type":"text/x-rst","patch_set":109,"id":"89b45201_3fc0cfb2","line":112,"updated":"2026-11-03 12:47:48.000000000","message":"IIRC we already have documentation for the upgrade process. We should have that in one place only. IMHO it is not necessary in this doc whose scope is to enumerate compatibility.","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"etc/proxy-server.conf-sample":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":638,"context_line":"use \u003d egg:swift#s3api"},{"line_number":639,"context_line":"# Write a validated checksum on a new PUT Object. The default is false."},{"line_number":640,"context_line":"# Enable only after all proxy and internal applications that read, write, or"},{"line_number":641,"context_line":"# copy these objects have the checksum code and old workers have drained."},{"line_number":642,"context_line":"# allow_store_checksums \u003d false"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"# s3api setup:"}],"source_content_type":"application/octet-stream","patch_set":108,"id":"80164151_bbd97c23","line":641,"range":{"start_line":641,"start_character":7,"end_line":641,"end_character":20},"updated":"2026-10-30 18:13:29.000000000","message":"doc: \u0027these objects\u0027 - which subset of objects is this referring to? It might be clearer just to say \u0027objects\u0027","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":638,"context_line":"use \u003d egg:swift#s3api"},{"line_number":639,"context_line":"# Write a validated checksum on a new PUT Object. The default is false."},{"line_number":640,"context_line":"# Enable only after all proxy and internal applications that read, write, or"},{"line_number":641,"context_line":"# copy these objects have the checksum code and old workers have drained."},{"line_number":642,"context_line":"# allow_store_checksums \u003d false"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"# s3api setup:"}],"source_content_type":"application/octet-stream","patch_set":108,"id":"a55288c1_8b8aef67","line":641,"range":{"start_line":641,"start_character":30,"end_line":641,"end_character":72},"updated":"2026-10-30 18:13:29.000000000","message":"doc: we should just refer to ONE place where the upgrade process is documented","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"}],"swift/common/middleware/s3api/checksum.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cb05607806df3f56bee1aed1d2684a1589320bb7","unresolved":true,"context_lines":[{"line_number":54,"context_line":"def checksum_sysmeta_headers(checksum_header, checksum_value, checksum_type):"},{"line_number":55,"context_line":"    \"\"\"Return object sysmeta for a calculated or validated checksum.\"\"\""},{"line_number":56,"context_line":"    return {"},{"line_number":57,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027): checksum_header,"},{"line_number":58,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027): checksum_value,"},{"line_number":59,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027): checksum_type,"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":70,"id":"f6b236a3_67469234","line":57,"updated":"2026-08-14 16:09:50.000000000","message":"Instinctively I would expect us to be persisting the *algorithm* e.g. ``crc32c`` rather than the header ``x-amz-checksum-crc32c`` because:\n\n(a) it\u0027s more compact\n(b) there\u0027s places (MPU) where we actually receive ``x-amz-checksum-algorithm`` (or similar) so it feels like it is the algorithm that is the universal reference internally.\n\nbut I realise that means a whole bunch of churn (or does it? have we successfully encapsulated the sysmeta read and write?)","commit_id":"f17e481e43ed67aa12c4a11be3ae2ee5386ff0d9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"964ac133bf12e9cb028d7905935205d08cdb5625","unresolved":false,"context_lines":[{"line_number":54,"context_line":"def checksum_sysmeta_headers(checksum_header, checksum_value, checksum_type):"},{"line_number":55,"context_line":"    \"\"\"Return object sysmeta for a calculated or validated checksum.\"\"\""},{"line_number":56,"context_line":"    return {"},{"line_number":57,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027): checksum_header,"},{"line_number":58,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027): checksum_value,"},{"line_number":59,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027): checksum_type,"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":70,"id":"9bfa5005_38dc3cc9","line":57,"in_reply_to":"39420c82_c028edfa","updated":"2026-08-19 23:43:30.000000000","message":"Done","commit_id":"f17e481e43ed67aa12c4a11be3ae2ee5386ff0d9"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"d14655845ee7db8a3e8931e0a2cfbf5e3b46c7b9","unresolved":true,"context_lines":[{"line_number":54,"context_line":"def checksum_sysmeta_headers(checksum_header, checksum_value, checksum_type):"},{"line_number":55,"context_line":"    \"\"\"Return object sysmeta for a calculated or validated checksum.\"\"\""},{"line_number":56,"context_line":"    return {"},{"line_number":57,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027): checksum_header,"},{"line_number":58,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027): checksum_value,"},{"line_number":59,"context_line":"        sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027): checksum_type,"},{"line_number":60,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":70,"id":"39420c82_c028edfa","line":57,"in_reply_to":"f6b236a3_67469234","updated":"2026-08-17 15:14:03.000000000","message":"I think we have some errors that return `x-amz-checksum-crc32c` instead of just the algorithm, but i THINK we have abstract all the writing of sysmeta to these functions we really don\u0027t care if the header or algorithm gets written.\n\nI think we can move to writing just the algorithm. It will help us in the future when we look over this again I think too.","commit_id":"f17e481e43ed67aa12c4a11be3ae2ee5386ff0d9"}],"swift/common/middleware/s3api/controllers/multi_upload.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"615fc81b531b3893be515c6974fbc9cc0a47a743","unresolved":false,"context_lines":[{"line_number":66,"context_line":"import time"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"from swift.common import constraints"},{"line_number":69,"context_line":"from swift.common.swob import Range, bytes_to_wsgi, normalize_etag, \\"},{"line_number":70,"context_line":"    wsgi_quote, wsgi_to_str, parse_date_header"},{"line_number":71,"context_line":"from swift.common.utils import json, public, reiterate, md5"},{"line_number":72,"context_line":"from swift.common.utils.timestamp import Timestamp, NormalTimestamp"}],"source_content_type":"text/x-python","patch_set":37,"id":"632416d5_04a1267f","line":69,"updated":"2026-07-16 16:54:52.000000000","message":"pep8: F401 \u0027swift.common.swob.parse_date_header\u0027 imported but unused","commit_id":"7c52b631f5b0ff7385ebb9d6b8945fdb3d6d9617"}],"swift/common/middleware/s3api/controllers/obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":41,"context_line":"    def _purge_checksum_response_headers(self, resp):"},{"line_number":42,"context_line":"        for key in list(resp.headers):"},{"line_number":43,"context_line":"            if key.lower().startswith(\u0027x-amz-checksum-\u0027):"},{"line_number":44,"context_line":"                del resp.headers[key]"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def _gen_head_range_resp(self, req_range, resp):"},{"line_number":47,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":11,"id":"c8de5409_1df34d52","line":44,"updated":"2026-06-17 00:00:40.000000000","message":"it seems like most of the `x-amz-checksum` prefix stuff in s3request was buried on the request object - somewhat strange to see the object controller manipulating the `resp` object\u0027s headers directly instead of through an interface that encapsulates the checksum knowledge between the s3request and s3response objects.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    def _purge_checksum_response_headers(self, resp):"},{"line_number":42,"context_line":"        for key in list(resp.headers):"},{"line_number":43,"context_line":"            if key.lower().startswith(\u0027x-amz-checksum-\u0027):"},{"line_number":44,"context_line":"                del resp.headers[key]"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    def _gen_head_range_resp(self, req_range, resp):"},{"line_number":47,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":11,"id":"e784ab0e_871deb67","line":44,"in_reply_to":"c8de5409_1df34d52","updated":"2026-06-22 23:53:33.000000000","message":"I agree, these headers should instead only be manipulated in `S3Request` or `S3Response`","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":98,"context_line":"                \u0027object_versioning\u0027 not in get_swift_info():"},{"line_number":99,"context_line":"            raise S3NotImplemented()"},{"line_number":100,"context_line":"        part_number \u003d req.validate_part_number(check_max\u003dFalse)"},{"line_number":101,"context_line":"        checksum_mode_enabled \u003d req.checksum_mode_enabled()"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"        query \u003d {}"},{"line_number":104,"context_line":"        if version_id is not None:"}],"source_content_type":"text/x-python","patch_set":11,"id":"40439eb9_3aa08440","line":101,"updated":"2026-06-17 00:00:40.000000000","message":"\u003e how many new abstractions have we added to the req class?\n\nturns out quite a few - and there was some pre-existing once you have to know too!\n\n\u003e what\u0027s the difference between `has_checksum_to_validate` and `checksum_mode_enabled`?\n\nstrangely I read s3request diff and I still don\u0027t know the answer to this question - I\u0027d have to study it.  I think since this is a GET request the \"x-amz-checksum-mode: enabled\" header just says if you want your response to include the extra stored checksum metadata or not.\n\ni.e. GET doesn\u0027t supply a \"checksum_to_validate\" but the way it spells \"checksum_mode_enabled\" is the same as PUT (and just has a different semantic meaning)","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":98,"context_line":"                \u0027object_versioning\u0027 not in get_swift_info():"},{"line_number":99,"context_line":"            raise S3NotImplemented()"},{"line_number":100,"context_line":"        part_number \u003d req.validate_part_number(check_max\u003dFalse)"},{"line_number":101,"context_line":"        checksum_mode_enabled \u003d req.checksum_mode_enabled()"},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"        query \u003d {}"},{"line_number":104,"context_line":"        if version_id is not None:"}],"source_content_type":"text/x-python","patch_set":11,"id":"5197247f_6711f7d4","line":101,"in_reply_to":"40439eb9_3aa08440","updated":"2026-06-22 23:53:33.000000000","message":"\u003e I think since this is a GET request the \"x-amz-checksum-mode: enabled\" header just says if you want your response to include the extra stored checksum metadata or not.\n\nYea that\u0027s correct, and `has_checksum_to_validate` is true when the request includes a client-supplied checksum that Swift is going to validate against the request body\n\nI think it could be more clear if the variable `has_checksum_to_validate` is changed to `validates_client_checksum` to denote the difference that we are getting something from the client to verify and change `checksum_mode_enabled` to `has_checksum_mode_header` to denote that we search for some request header.\n\nWhat would be even better would be if the controller didn\u0027t deal with the checksum mode at all since it is a `x-amz-checksum` type of header meaning it should be validated just like the other `x-amz-checksum` headers (like `x-amz-sdk-checksum-algorithm` and `x-amz-checksum-type` are in the `S3Request` object","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":140,"context_line":"            if \u0027response-\u0027 + key in req.params:"},{"line_number":141,"context_line":"                resp.headers[key] \u003d req.params[\u0027response-\u0027 + key]"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"        if not (checksum_mode_enabled and resp.status_int \u003d\u003d HTTP_OK):"},{"line_number":144,"context_line":"            self._purge_checksum_response_headers(resp)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        return resp"}],"source_content_type":"text/x-python","patch_set":11,"id":"5af30fb4_fbb63333","line":143,"updated":"2026-06-17 00:00:40.000000000","message":"on L141 we\u0027re using req.params\n\nI think the confusing part of \"why are we doing the `checksum_mode_enabled \u003d req.checksum_mode_enabled()` some 40 lines away\" is the `InvalidRequest` side-effect.\n\nI think:\n\n```\nchecksum_mode_enabled \u003d self.validate_checksum_mode_header()\n```\n\nwould be more obvious.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":140,"context_line":"            if \u0027response-\u0027 + key in req.params:"},{"line_number":141,"context_line":"                resp.headers[key] \u003d req.params[\u0027response-\u0027 + key]"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"        if not (checksum_mode_enabled and resp.status_int \u003d\u003d HTTP_OK):"},{"line_number":144,"context_line":"            self._purge_checksum_response_headers(resp)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        return resp"}],"source_content_type":"text/x-python","patch_set":11,"id":"5c7f1c30_55e139b6","line":143,"in_reply_to":"5af30fb4_fbb63333","updated":"2026-06-22 23:53:33.000000000","message":"I agree with this, though see comment #101 about moving validation logic to `S3Request`","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":141,"context_line":"                resp.headers[key] \u003d req.params[\u0027response-\u0027 + key]"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"        if not (checksum_mode_enabled and resp.status_int \u003d\u003d HTTP_OK):"},{"line_number":144,"context_line":"            self._purge_checksum_response_headers(resp)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        return resp"},{"line_number":147,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"eb8ebf9a_dd0b8797","line":144,"updated":"2026-06-17 00:00:40.000000000","message":"why do we have to *purge* sysmeta - can we just \"only translate sysmeta into user-namespace if user requests them\"","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":141,"context_line":"                resp.headers[key] \u003d req.params[\u0027response-\u0027 + key]"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"        if not (checksum_mode_enabled and resp.status_int \u003d\u003d HTTP_OK):"},{"line_number":144,"context_line":"            self._purge_checksum_response_headers(resp)"},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"        return resp"},{"line_number":147,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"0d6502d7_755d814c","line":144,"in_reply_to":"eb8ebf9a_dd0b8797","updated":"2026-06-22 23:53:33.000000000","message":"We can wrap the logic from `S3Response` to only add the headers if the request needs the headers. Something like:\n```python\n        checksum_header \u003d s3_sysmeta_headers.get(\n            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))\n        checksum_value \u003d s3_sysmeta_headers.get(\n            sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))\n        checksum_type \u003d s3_sysmeta_headers.get(\n            sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027))\n        if (checksum_header and checksum_value and\n                self._request_needs_checksum_response_headers()):\n            headers[checksum_header] \u003d checksum_value\n            if checksum_type:\n                headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type\n```","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":156,"context_line":"            req_range \u003d req.headers[\u0027range\u0027]"},{"line_number":157,"context_line":"            resp \u003d self._gen_head_range_resp(req_range, resp)"},{"line_number":158,"context_line":"            if resp.status_int !\u003d HTTP_OK:"},{"line_number":159,"context_line":"                self._purge_checksum_response_headers(resp)"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"        return resp"},{"line_number":162,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"169b8975_67244a50","line":159,"updated":"2026-06-17 00:00:40.000000000","message":"are we adding the headers back in again in `_gen_head_range_resp` or just being overly defensive?  I supposed it\u0027s possible - and now I\u0027d have to look.\n\nBecause if there\u0027s a diff hunk here that when reverted doesn\u0027t cause tests to blow up there\u0027s two possible changes you could make:\n\n1) add a test that shows why the hunk is needed\n2) remove the un-needed hunk\n\nIf we\u0027re sprinkling \"if isinstance(bytes)\" and \"if status in (400, 500): remove_headers()\" all over the code \"just in case\" we\u0027re not doing ourselves a favor.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":156,"context_line":"            req_range \u003d req.headers[\u0027range\u0027]"},{"line_number":157,"context_line":"            resp \u003d self._gen_head_range_resp(req_range, resp)"},{"line_number":158,"context_line":"            if resp.status_int !\u003d HTTP_OK:"},{"line_number":159,"context_line":"                self._purge_checksum_response_headers(resp)"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"        return resp"},{"line_number":162,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"facda1cf_c6e74e06","line":159,"in_reply_to":"169b8975_67244a50","updated":"2026-06-22 23:53:33.000000000","message":"What AWS does:\n```bash\njohn@doe:~$ printf \u0027hello\u0027 \u003e /tmp/s3-checksum-body\njohn@doe:~$ aws s3api put-object \\\n  --bucket s3checksumtest \\\n  --key checksum-head-range-test \\\n  --body /tmp/s3-checksum-body \\\n  --checksum-algorithm CRC32\n{\n    \"ETag\": \"\\\"5d41402abc4b2a76b9719d911017c592\\\"\",\n    \"ChecksumCRC32\": \"NhCmhg\u003d\u003d\",\n    \"ChecksumType\": \"FULL_OBJECT\",\n    \"ServerSideEncryption\": \"AES256\"\n}\njohn@doe:~$ aws s3api head-object \\\n  --bucket s3checksumtest \\\n  --key checksum-head-range-test \\\n  --checksum-mode ENABLED\n{\n    \"AcceptRanges\": \"bytes\",\n    \"LastModified\": \"2026-06-22T21:09:20+00:00\",\n    \"ContentLength\": 5,\n    \"ChecksumCRC32\": \"NhCmhg\u003d\u003d\",\n    \"ChecksumType\": \"FULL_OBJECT\",\n    \"ETag\": \"\\\"5d41402abc4b2a76b9719d911017c592\\\"\",\n    \"ContentType\": \"binary/octet-stream\",\n    \"ServerSideEncryption\": \"AES256\",\n    \"Metadata\": {}\n}\njohn@doe:~$ aws s3api head-object \\\n  --bucket s3checksumtest \\\n  --key checksum-head-range-test \\\n  --checksum-mode ENABLED \\\n  --range bytes\u003d0-3\n{\n    \"AcceptRanges\": \"bytes\",\n    \"LastModified\": \"2026-06-22T21:09:20+00:00\",\n    \"ContentLength\": 4,\n    \"ETag\": \"\\\"5d41402abc4b2a76b9719d911017c592\\\"\",\n    \"ContentType\": \"binary/octet-stream\",\n    \"ContentRange\": \"bytes 0-3/5\",\n    \"ServerSideEncryption\": \"AES256\",\n    \"Metadata\": {}\n}\n\n```\n\nTLDR:\nWe should remove the hunk since logic to add the checksum headers will be in `S3Response`\n\nThe Not TLDR:\nIf an AWS client performs a request that represents a full object (full HEAD or GET request),then it omits the checksum. We should follow this so we should omit the headers and add a test to denote the behavior. Thankfully, some test do exist! Though, they use `purge`, but i\u0027ll change them to `omit` for clarity.\n\nThere is an edge case that when a user makes a range request, but the range is just the same as the full object, then we still need to include the header.\n\n```bash\njohn@doe:~$ aws s3api head-object   --bucket s3checksumtest   --key checksum-head-range-test   --checksum-mode ENABLED   --range bytes\u003d0-4\n{\n    \"AcceptRanges\": \"bytes\",\n    \"LastModified\": \"2026-06-22T21:09:20+00:00\",\n    \"ContentLength\": 5,\n    \"ChecksumCRC32\": \"NhCmhg\u003d\u003d\",\n    \"ChecksumType\": \"FULL_OBJECT\",\n    \"ETag\": \"\\\"5d41402abc4b2a76b9719d911017c592\\\"\",\n    \"ContentType\": \"binary/octet-stream\",\n    \"ContentRange\": \"bytes 0-4/5\",\n    \"ServerSideEncryption\": \"AES256\",\n    \"Metadata\": {}\n}\n```\n\nBut to handle this we would have to add a check (like a regex) in `S3Response` to parse the `ContentRange` field which may be not needed to such a small piece","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":187,"context_line":"        if not is_copy_request and req.has_checksum_to_validate():"},{"line_number":188,"context_line":"            req.persist_checksum_sysmeta_after_validation()"},{"line_number":189,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":190,"context_line":"        if not is_copy_request and req.has_checksum_to_validate():"},{"line_number":191,"context_line":"            # Swift does not echo newly persisted sysmeta headers on PUT, so"},{"line_number":192,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":193,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."}],"source_content_type":"text/x-python","patch_set":11,"id":"69344dc6_1cd8593b","line":190,"updated":"2026-06-17 00:00:40.000000000","message":"the double `if not is_copy and req.has_checksum` around the `get_response` looks dumb","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":187,"context_line":"        if not is_copy_request and req.has_checksum_to_validate():"},{"line_number":188,"context_line":"            req.persist_checksum_sysmeta_after_validation()"},{"line_number":189,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":190,"context_line":"        if not is_copy_request and req.has_checksum_to_validate():"},{"line_number":191,"context_line":"            # Swift does not echo newly persisted sysmeta headers on PUT, so"},{"line_number":192,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":193,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."}],"source_content_type":"text/x-python","patch_set":11,"id":"0b80ff04_1a1bffb9","line":190,"in_reply_to":"69344dc6_1cd8593b","updated":"2026-06-22 23:53:33.000000000","message":"Acknowledged","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":true,"context_lines":[{"line_number":160,"context_line":"        return self.GETorHEAD(req)"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"    @public"},{"line_number":163,"context_line":"    def PUT(self, req):"},{"line_number":164,"context_line":"        \"\"\""},{"line_number":165,"context_line":"        Handle PUT Object and PUT Object (Copy) request"},{"line_number":166,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":44,"id":"edb683f2_c26a0f86","line":163,"updated":"2026-07-22 01:29:15.000000000","message":"during offline discussions, @nmartes@NVIDIA.com has identified one gap in his ObjectCopy implementation: CopyObject silently ignores ``x-amz-checksum-algorithm``:\n\nChecksum-value parsing deliberately excludes that header at s3request.py:1501, but the CopyObject controller never handles it. With a CRC32 source and ``X-Amz-Checksum-Algorithm: SHA256``, it would be a 200 response: stored the source CRC32 metadata, returned ChecksumCRC32 checksum, instead of recomputed SHA256.\n\nand he found AWS specifies that CopyObject preserves the source algorithm by default but allows the caller to select a different one. AWS CopyObject documentation (https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)\n\nI think it\u0027s okay to not implement re-computation using the requested algorithm, but we should reject the header if it\u0027s not supported. Silently succeeding with a contradictory checksum is unsafe for clients relying on integrity metadata. please also add corresponding test cases.","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[{"line_number":160,"context_line":"        return self.GETorHEAD(req)"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"    @public"},{"line_number":163,"context_line":"    def PUT(self, req):"},{"line_number":164,"context_line":"        \"\"\""},{"line_number":165,"context_line":"        Handle PUT Object and PUT Object (Copy) request"},{"line_number":166,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":44,"id":"38fc20b4_a353d3d7","line":163,"in_reply_to":"634fcaa7_38dd240a","updated":"2026-07-22 17:00:18.000000000","message":"Done","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"dcdffadc6ca94a0293e01d1a238d2025cb8c8078","unresolved":true,"context_lines":[{"line_number":160,"context_line":"        return self.GETorHEAD(req)"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"    @public"},{"line_number":163,"context_line":"    def PUT(self, req):"},{"line_number":164,"context_line":"        \"\"\""},{"line_number":165,"context_line":"        Handle PUT Object and PUT Object (Copy) request"},{"line_number":166,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":44,"id":"634fcaa7_38dd240a","line":163,"in_reply_to":"edb683f2_c26a0f86","updated":"2026-07-22 15:41:10.000000000","message":"I think we also should reject the header, silent success is not a good thing","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":true,"context_lines":[{"line_number":171,"context_line":"            raise InvalidArgument(\u0027x-amz-copy-source-range\u0027,"},{"line_number":172,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":173,"context_line":"                                  \u0027Illegal copy header\u0027)"},{"line_number":174,"context_line":"        source_resp \u003d req.check_copy_source(self.app)"},{"line_number":175,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":176,"context_line":"            # can\u0027t setdefault because it can be None for some reason"},{"line_number":177,"context_line":"            req.headers[\u0027Content-Type\u0027] \u003d \u0027binary/octet-stream\u0027"}],"source_content_type":"text/x-python","patch_set":44,"id":"5a931c41_61ad5202","line":174,"updated":"2026-07-22 01:29:15.000000000","message":"``check_copy_source(self.app)`` issues a HEAD on the source object and returns the S3Response as source_resp. this return value is now captured and passed downstream","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[{"line_number":171,"context_line":"            raise InvalidArgument(\u0027x-amz-copy-source-range\u0027,"},{"line_number":172,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":173,"context_line":"                                  \u0027Illegal copy header\u0027)"},{"line_number":174,"context_line":"        source_resp \u003d req.check_copy_source(self.app)"},{"line_number":175,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":176,"context_line":"            # can\u0027t setdefault because it can be None for some reason"},{"line_number":177,"context_line":"            req.headers[\u0027Content-Type\u0027] \u003d \u0027binary/octet-stream\u0027"}],"source_content_type":"text/x-python","patch_set":44,"id":"c6dcc0a0_547a5c81","line":174,"in_reply_to":"5a931c41_61ad5202","updated":"2026-07-22 17:00:18.000000000","message":"Acknowledged","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":true,"context_lines":[{"line_number":175,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":176,"context_line":"            # can\u0027t setdefault because it can be None for some reason"},{"line_number":177,"context_line":"            req.headers[\u0027Content-Type\u0027] \u003d \u0027binary/octet-stream\u0027"},{"line_number":178,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":181,"context_line":"            resp.append_copy_resp_body(\u0027CopyObjectResult\u0027, source_resp)"}],"source_content_type":"text/x-python","patch_set":44,"id":"4e2e6e23_95122e28","line":178,"updated":"2026-07-22 01:29:15.000000000","message":"Swift\u0027s native copy semantics copy the source\u0027s object sysmeta (including the s3api checksum-header/checksum-value/checksum-type sysmeta) onto the destination, so persistence on the destination is inherited, not recomputed.","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[{"line_number":175,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"},{"line_number":176,"context_line":"            # can\u0027t setdefault because it can be None for some reason"},{"line_number":177,"context_line":"            req.headers[\u0027Content-Type\u0027] \u003d \u0027binary/octet-stream\u0027"},{"line_number":178,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 in req.headers:"},{"line_number":181,"context_line":"            resp.append_copy_resp_body(\u0027CopyObjectResult\u0027, source_resp)"}],"source_content_type":"text/x-python","patch_set":44,"id":"ab126be9_d10f1e4a","line":178,"in_reply_to":"4e2e6e23_95122e28","updated":"2026-07-22 17:00:18.000000000","message":"Acknowledged","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"32936b0f40800f00d0b2ccd3b63ce44f409f19ad","unresolved":false,"context_lines":[{"line_number":170,"context_line":"                \u0027X-Amz-Checksum-Algorithm\u0027 in req.headers:"},{"line_number":171,"context_line":"            raise S3NotImplemented("},{"line_number":172,"context_line":"                \u0027CopyObject checksum calculation is not \u0027"},{"line_number":173,"context_line":"                                        \u0027supported.\u0027)"},{"line_number":174,"context_line":"        if all(h in req.headers"},{"line_number":175,"context_line":"               for h in (\u0027X-Amz-Copy-Source\u0027, \u0027X-Amz-Copy-Source-Range\u0027)):"},{"line_number":176,"context_line":"            raise InvalidArgument(\u0027x-amz-copy-source-range\u0027,"}],"source_content_type":"text/x-python","patch_set":45,"id":"b40087ae_17620e67","line":173,"updated":"2026-07-22 17:57:02.000000000","message":"pep8: E131 continuation line unaligned for hanging indent","commit_id":"d6bd5b38f367e70690be6178835908b61565a373"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f53fb482f29dc21cae6eb510b2083b525d8b0cf9","unresolved":true,"context_lines":[{"line_number":172,"context_line":"                \u0027CopyObject checksum calculation is not \u0027"},{"line_number":173,"context_line":"                \u0027supported.\u0027)"},{"line_number":174,"context_line":"        if all(h in req.headers"},{"line_number":175,"context_line":"               for h in (\u0027X-Amz-Copy-Source\u0027, \u0027X-Amz-Copy-Source-Range\u0027)):"},{"line_number":176,"context_line":"            raise InvalidArgument(\u0027x-amz-copy-source-range\u0027,"},{"line_number":177,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":178,"context_line":"                                  \u0027Illegal copy header\u0027)"}],"source_content_type":"text/x-python","patch_set":54,"id":"1ba509e1_e08bed99","line":175,"updated":"2026-07-29 21:58:46.000000000","message":"Here rejects ``X-Amz-Copy-Source-Range`` but leaves an ordinary ``Range`` header intact. so with ``Range`` header, copy middleware performs the partial GET while copying the source sysmeta, and destination object retains the full-source checksum for the partial body. Then as the result, later a checksum-enabled GET therefore would advertise a checksum that cannot validate its object.\n\nsee the test case at: https://review.opendev.org/c/openstack/swift/+/999182, and its failure demonstrates this issue. \n```\n\u003e               sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027)])\nE       AssertionError: \u0027NSRBwg\u003d\u003d\u0027 !\u003d \u0027OYFwOg\u003d\u003d\u0027\nE       - NSRBwg\u003d\u003d\nE       + OYFwOg\u003d\u003d\n```\n\nnormal s3api users won\u0027t do this, since ``Range`` is not a documented CopyObject parameter. we probably don\u0027t need to worry about this, other than saying this is some kind of wild behaviror? If this patch adds checksum recalculation for ObjectCopy, then this issue will be gone by its own.","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ae040053f6e786ffa7e5df93d7ef7fd75417e007","unresolved":true,"context_lines":[{"line_number":172,"context_line":"                \u0027CopyObject checksum calculation is not \u0027"},{"line_number":173,"context_line":"                \u0027supported.\u0027)"},{"line_number":174,"context_line":"        if all(h in req.headers"},{"line_number":175,"context_line":"               for h in (\u0027X-Amz-Copy-Source\u0027, \u0027X-Amz-Copy-Source-Range\u0027)):"},{"line_number":176,"context_line":"            raise InvalidArgument(\u0027x-amz-copy-source-range\u0027,"},{"line_number":177,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":178,"context_line":"                                  \u0027Illegal copy header\u0027)"}],"source_content_type":"text/x-python","patch_set":54,"id":"1d0554bb_2162fe94","line":175,"in_reply_to":"1ba509e1_e08bed99","updated":"2026-07-30 21:21:59.000000000","message":"This lead to us finding some unexpected behavior, thanks! Since we hav a patch to block it from happening (999336: s3api: reject Range header on CopyObject | https://review.opendev.org/c/openstack/swift/+/999336), we probably don\u0027t need add this test.","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":false,"context_lines":[{"line_number":172,"context_line":"                \u0027CopyObject checksum calculation is not \u0027"},{"line_number":173,"context_line":"                \u0027supported.\u0027)"},{"line_number":174,"context_line":"        if all(h in req.headers"},{"line_number":175,"context_line":"               for h in (\u0027X-Amz-Copy-Source\u0027, \u0027X-Amz-Copy-Source-Range\u0027)):"},{"line_number":176,"context_line":"            raise InvalidArgument(\u0027x-amz-copy-source-range\u0027,"},{"line_number":177,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":178,"context_line":"                                  \u0027Illegal copy header\u0027)"}],"source_content_type":"text/x-python","patch_set":54,"id":"9f5fb4b2_7d2aea90","line":175,"in_reply_to":"1d0554bb_2162fe94","updated":"2026-08-21 16:03:49.000000000","message":"Done","commit_id":"05b475672c3576c886939d6426e36416a2f7a392"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"385b77046e54eb9483abaa3dcce7624b4c02dae7","unresolved":true,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        return resp"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    def _resp_needs_checksum_headers(self, req, resp, part_number):"},{"line_number":81,"context_line":"        \"\"\""},{"line_number":82,"context_line":"        Return whether stored checksum sysmeta should be exposed as"},{"line_number":83,"context_line":"        x-amz-checksum-* response headers for this request."}],"source_content_type":"text/x-python","patch_set":87,"id":"6155fe75_5b964102","line":80,"updated":"2026-08-27 10:54:46.000000000","message":"nit: this does not check if the req is a GET or HEAD, but then it is only called from ``GETorHEAD`` so doesn\u0027t need to, but I wonder if it is even worth breaking out to another method??","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"7f71f8ebd624907864facd984796cef19179b815","unresolved":true,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        return resp"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    def _resp_needs_checksum_headers(self, req, resp, part_number):"},{"line_number":81,"context_line":"        \"\"\""},{"line_number":82,"context_line":"        Return whether stored checksum sysmeta should be exposed as"},{"line_number":83,"context_line":"        x-amz-checksum-* response headers for this request."}],"source_content_type":"text/x-python","patch_set":87,"id":"b67b0d3b_74bbb96e","line":80,"in_reply_to":"6155fe75_5b964102","updated":"2026-08-27 22:50:10.000000000","message":"I think it looks prettier to say\n\n\"Hey if we need to send the checksum headers, lets add them!\"\n\nInstead of maybe a comment followed by the cases...","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        return resp"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"    def _resp_needs_checksum_headers(self, req, resp, part_number):"},{"line_number":81,"context_line":"        \"\"\""},{"line_number":82,"context_line":"        Return whether stored checksum sysmeta should be exposed as"},{"line_number":83,"context_line":"        x-amz-checksum-* response headers for this request."}],"source_content_type":"text/x-python","patch_set":87,"id":"5df76826_802b16f4","line":80,"in_reply_to":"b67b0d3b_74bbb96e","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"385b77046e54eb9483abaa3dcce7624b4c02dae7","unresolved":true,"context_lines":[{"line_number":196,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":197,"context_line":"                                  \u0027Illegal copy header\u0027)"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 not in req.headers:"},{"line_number":200,"context_line":"            req.enable_checksum_persistence()"},{"line_number":201,"context_line":"        req.check_copy_source(self.app)"},{"line_number":202,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"}],"source_content_type":"text/x-python","patch_set":87,"id":"cc5477bc_3b53fe8d","line":199,"updated":"2026-08-27 10:54:46.000000000","message":"nit: worth a comment: \"we do not yet support checksum re-calculation while copying\"","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":196,"context_line":"                                  req.headers[\u0027X-Amz-Copy-Source-Range\u0027],"},{"line_number":197,"context_line":"                                  \u0027Illegal copy header\u0027)"},{"line_number":198,"context_line":""},{"line_number":199,"context_line":"        if \u0027X-Amz-Copy-Source\u0027 not in req.headers:"},{"line_number":200,"context_line":"            req.enable_checksum_persistence()"},{"line_number":201,"context_line":"        req.check_copy_source(self.app)"},{"line_number":202,"context_line":"        if not req.headers.get(\u0027Content-Type\u0027):"}],"source_content_type":"text/x-python","patch_set":87,"id":"f6c4cf5f_10cfbb95","line":199,"in_reply_to":"cc5477bc_3b53fe8d","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"16cec9a84556f1f83754b71c5530c500e58ea988","unresolved":true,"context_lines":[{"line_number":203,"context_line":"            # can\u0027t setdefault because it can be None for some reason"},{"line_number":204,"context_line":"            req.headers[\u0027Content-Type\u0027] \u003d \u0027binary/octet-stream\u0027"},{"line_number":205,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":206,"context_line":"        # Swift does not echo newly persisted sysmeta headers in PUT responses,"},{"line_number":207,"context_line":"        # so inject the checksum response headers based on the sysmeta sent"},{"line_number":208,"context_line":"        # with the request. The request will have this sysmeta if"},{"line_number":209,"context_line":"        # req.enable_checksum_persistence was called."}],"source_content_type":"text/x-python","patch_set":88,"id":"44caa101_90fc9634","line":206,"updated":"2026-09-10 20:56:18.000000000","message":"This bugs me a little -- I don\u0027t like that there\u0027s metadata that\u0027s *only* accessible *via the S3 API*.\n\nBut at the same time, I understand that trying to build out persistent checksums as a Swift feature *first* and then building the S3 feature *on top* is going to take a while, even if it better matches what we\u0027ve done historically...","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"c6212ddfac1008588495beaa1b3765bfeb67c7da","unresolved":false,"context_lines":[{"line_number":203,"context_line":"            # can\u0027t setdefault because it can be None for some reason"},{"line_number":204,"context_line":"            req.headers[\u0027Content-Type\u0027] \u003d \u0027binary/octet-stream\u0027"},{"line_number":205,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":206,"context_line":"        # Swift does not echo newly persisted sysmeta headers in PUT responses,"},{"line_number":207,"context_line":"        # so inject the checksum response headers based on the sysmeta sent"},{"line_number":208,"context_line":"        # with the request. The request will have this sysmeta if"},{"line_number":209,"context_line":"        # req.enable_checksum_persistence was called."}],"source_content_type":"text/x-python","patch_set":88,"id":"01df5129_016e255c","line":206,"in_reply_to":"44caa101_90fc9634","updated":"2026-10-02 00:24:55.000000000","message":"Acknowledged","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"c325b7caf9dce11db8dcc50ee2a87bfe5212b634","unresolved":false,"context_lines":[{"line_number":144,"context_line":"            if \u0027response-\u0027 + key in req.params:"},{"line_number":145,"context_line":"                resp.headers[key] \u003d req.params[\u0027response-\u0027 + key]"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"        if (normalize_checksum_mode(req.headers.get(\u0027x-amz-checksum-mode\u0027))"},{"line_number":148,"context_line":"                \u003d\u003d \u0027ENABLED\u0027"},{"line_number":149,"context_line":"                and \u0027range\u0027 not in req.headers"},{"line_number":150,"context_line":"                and part_number is None"}],"source_content_type":"text/x-python","patch_set":109,"id":"83368572_9e9d0595","line":147,"updated":"2026-10-30 23:58:34.000000000","message":"it\u0027s actually a structural improvement to move this code block at here, only add checksum headers after the controller has finished its status and error decisions","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f67e9e911f1e0bc8890b2b35c99cbc5fd20e848d","unresolved":true,"context_lines":[{"line_number":198,"context_line":"        resp \u003d req.get_response(self.app)"},{"line_number":199,"context_line":"        # Swift does not echo newly persisted sysmeta headers in PUT responses,"},{"line_number":200,"context_line":"        # so inject the checksum response headers based on the sysmeta sent"},{"line_number":201,"context_line":"        # with the request. The request will have this sysmeta if"},{"line_number":202,"context_line":"        # req.enable_checksum_persistence was called."},{"line_number":203,"context_line":"        if req.checksum_sysmeta_footers:"},{"line_number":204,"context_line":"            resp.headers.update("},{"line_number":205,"context_line":"                checksum_sysmeta_to_response_headers("}],"source_content_type":"text/x-python","patch_set":109,"id":"02ef14fe_219003c8","line":202,"range":{"start_line":201,"start_character":28,"end_line":202,"end_character":52},"updated":"2026-11-03 14:41:51.000000000","message":"not true with the way the patch is written at the moment: it also requires allow_store_checksums to be set true, and that check is hidden inside enable_checksum_persistence\n\nBut I propose we should move the check to the caller at line 191 and then this comment will be correct","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"swift/common/middleware/s3api/s3api.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"beae5ac145cfce25631f75f5ef7d0ab819f51523","unresolved":false,"context_lines":[{"line_number":608,"context_line":"    register_sensitive_header(\u0027authorization\u0027)"},{"line_number":609,"context_line":"    register_sensitive_param(\u0027Signature\u0027)"},{"line_number":610,"context_line":"    register_sensitive_param(\u0027X-Amz-Signature\u0027)"},{"line_number":611,"context_line":"    register_sensitive_sysmeta("},{"line_number":612,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"},{"line_number":613,"context_line":""},{"line_number":614,"context_line":"    def s3api_filter(app):"}],"source_content_type":"text/x-python","patch_set":108,"id":"961a4f2f_70c5edbd","line":611,"updated":"2026-10-30 03:56:06.000000000","message":"switched to use the simplified interface","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"}],"swift/common/middleware/s3api/s3checksum.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"402ca73c548bfd26cea2056c3493f2b330bf59f9","unresolved":true,"context_lines":[{"line_number":88,"context_line":"    return {"},{"line_number":89,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":90,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":91,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027sensitive-checksum-value\u0027):"},{"line_number":92,"context_line":"            checksum_value,"},{"line_number":93,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027): checksum_type,"},{"line_number":94,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":90,"id":"5b445a1a_835698b7","line":91,"updated":"2026-09-10 12:33:11.000000000","message":"This becomes `x-object-sysmeta-s3api-sensitive-checksum-value`, but the required prefix for the encryption middleware is `x-object-sysmeta-sensitive-`. We need to use `get_object_sensitive_sysmeta(\u0027s3api-checksum-value\u0027)` here","commit_id":"f6f50ed0336c4218058fc28c70f88eb572b3f690"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":88,"context_line":"    return {"},{"line_number":89,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":90,"context_line":"            normalize_checksum_algorithm(checksum_algorithm),"},{"line_number":91,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027sensitive-checksum-value\u0027):"},{"line_number":92,"context_line":"            checksum_value,"},{"line_number":93,"context_line":"        s3api_sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027): checksum_type,"},{"line_number":94,"context_line":"    }"}],"source_content_type":"text/x-python","patch_set":90,"id":"461c4f88_8d03bdd1","line":91,"in_reply_to":"5b445a1a_835698b7","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"f6f50ed0336c4218058fc28c70f88eb572b3f690"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cf0b4791efa7497f96232e1210ca23fbad190907","unresolved":true,"context_lines":[{"line_number":146,"context_line":"        self._checksum_hasher \u003d checksum_hasher"},{"line_number":147,"context_line":"        self.checksum_key \u003d checksum_key"},{"line_number":148,"context_line":"        self._checksum_source \u003d checksum_source"},{"line_number":149,"context_line":"        self._matching_checksum \u003d None"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    @property"},{"line_number":152,"context_line":"    def matching_checksum(self):"}],"source_content_type":"text/x-python","patch_set":96,"id":"ec766bbc_e4dff185","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":31},"updated":"2026-09-18 10:37:39.000000000","message":"later in the patch chain this attribute is set even when there is no client-provided checksum to match, so the name becomes inaccurate.\n\nI suggest we name this simply ``checksum`` or ``checksum_value``","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"94039f50ee8339f6ca4daf959e8c8cce602f1b8c","unresolved":false,"context_lines":[{"line_number":146,"context_line":"        self._checksum_hasher \u003d checksum_hasher"},{"line_number":147,"context_line":"        self.checksum_key \u003d checksum_key"},{"line_number":148,"context_line":"        self._checksum_source \u003d checksum_source"},{"line_number":149,"context_line":"        self._matching_checksum \u003d None"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    @property"},{"line_number":152,"context_line":"    def matching_checksum(self):"}],"source_content_type":"text/x-python","patch_set":96,"id":"2107fbef_e376b12c","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":31},"in_reply_to":"ec766bbc_e4dff185","updated":"2026-09-19 13:16:50.000000000","message":"Done","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cf0b4791efa7497f96232e1210ca23fbad190907","unresolved":true,"context_lines":[{"line_number":149,"context_line":"        self._matching_checksum \u003d None"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    @property"},{"line_number":152,"context_line":"    def matching_checksum(self):"},{"line_number":153,"context_line":"        \"\"\"Return the supplied checksum after it matches the input.\"\"\""},{"line_number":154,"context_line":"        return self._matching_checksum"},{"line_number":155,"context_line":""}],"source_content_type":"text/x-python","patch_set":96,"id":"02a614c9_a94b9e50","line":152,"range":{"start_line":152,"start_character":8,"end_line":152,"end_character":25},"updated":"2026-09-18 10:37:39.000000000","message":"this does not need to be a property\n\nalso same comment as above re. the name \"matching\"","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"94039f50ee8339f6ca4daf959e8c8cce602f1b8c","unresolved":false,"context_lines":[{"line_number":149,"context_line":"        self._matching_checksum \u003d None"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    @property"},{"line_number":152,"context_line":"    def matching_checksum(self):"},{"line_number":153,"context_line":"        \"\"\"Return the supplied checksum after it matches the input.\"\"\""},{"line_number":154,"context_line":"        return self._matching_checksum"},{"line_number":155,"context_line":""}],"source_content_type":"text/x-python","patch_set":96,"id":"3bb9de33_17a6c57b","line":152,"range":{"start_line":152,"start_character":8,"end_line":152,"end_character":25},"in_reply_to":"02a614c9_a94b9e50","updated":"2026-09-19 13:16:50.000000000","message":"Done","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"395f0a8a568a5c66fa59f18010db4a119a5790b8","unresolved":false,"context_lines":[{"line_number":95,"context_line":"SIGV4_CHUNK_MIN_SIZE \u003d 8192"},{"line_number":96,"context_line":"SERVICE \u003d \u0027s3\u0027  # useful for mocking out in tests"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"def _unsupported_checksum_hasher():"},{"line_number":99,"context_line":"    raise NotImplementedError"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"CHECKSUMS_BY_HEADER \u003d {"}],"source_content_type":"text/x-python","patch_set":8,"id":"b6c25b43_02895c1a","line":98,"updated":"2026-06-06 01:13:09.000000000","message":"pep8: E302 expected 2 blank lines, found 1","commit_id":"8fd44112727ae3feb953f47db6258bfdb3bdea93"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"395f0a8a568a5c66fa59f18010db4a119a5790b8","unresolved":false,"context_lines":[{"line_number":98,"context_line":"def _unsupported_checksum_hasher():"},{"line_number":99,"context_line":"    raise NotImplementedError"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"CHECKSUMS_BY_HEADER \u003d {"},{"line_number":102,"context_line":"    \u0027x-amz-checksum-crc32\u0027: checksum.crc32,"},{"line_number":103,"context_line":"    \u0027x-amz-checksum-crc32c\u0027: checksum.crc32c,"},{"line_number":104,"context_line":"    \u0027x-amz-checksum-crc64nvme\u0027: checksum.crc64nvme,"}],"source_content_type":"text/x-python","patch_set":8,"id":"bfb86ac0_83c85aff","line":101,"updated":"2026-06-06 01:13:09.000000000","message":"pep8: E305 expected 2 blank lines after class or function definition, found 1","commit_id":"8fd44112727ae3feb953f47db6258bfdb3bdea93"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"4bbdbae3676bc264ae5f4fbf4ad6b3137ccac062","unresolved":true,"context_lines":[{"line_number":1634,"context_line":"        if not self._validated_checksum:"},{"line_number":1635,"context_line":"            return {}"},{"line_number":1636,"context_line":"        return {"},{"line_number":1637,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":1638,"context_line":"                self._validated_checksum[\u0027algorithm\u0027],"},{"line_number":1639,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027):"},{"line_number":1640,"context_line":"                self._validated_checksum[\u0027header\u0027],"}],"source_content_type":"text/x-python","patch_set":9,"id":"334a44c1_0502dacd","line":1637,"range":{"start_line":1637,"start_character":0,"end_line":1637,"end_character":2},"updated":"2026-06-09 13:53:56.000000000","message":"Looks like checksum-algorithm is not used all (besides tests)?","commit_id":"1b912f91b63174a730697c8c0591ba2e8581a2c0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"0d571b4df2708f1562275eb3b627118848e50cc9","unresolved":false,"context_lines":[{"line_number":1634,"context_line":"        if not self._validated_checksum:"},{"line_number":1635,"context_line":"            return {}"},{"line_number":1636,"context_line":"        return {"},{"line_number":1637,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":1638,"context_line":"                self._validated_checksum[\u0027algorithm\u0027],"},{"line_number":1639,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027):"},{"line_number":1640,"context_line":"                self._validated_checksum[\u0027header\u0027],"}],"source_content_type":"text/x-python","patch_set":9,"id":"a83bb27d_dda91008","line":1637,"range":{"start_line":1637,"start_character":0,"end_line":1637,"end_character":2},"in_reply_to":"285b80e2_cc0774ab","updated":"2026-06-09 21:31:57.000000000","message":"Marked as resolved.","commit_id":"1b912f91b63174a730697c8c0591ba2e8581a2c0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"5acdcd2383da4b3101cf924578bc2ebc5bbd0a16","unresolved":true,"context_lines":[{"line_number":1634,"context_line":"        if not self._validated_checksum:"},{"line_number":1635,"context_line":"            return {}"},{"line_number":1636,"context_line":"        return {"},{"line_number":1637,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-algorithm\u0027):"},{"line_number":1638,"context_line":"                self._validated_checksum[\u0027algorithm\u0027],"},{"line_number":1639,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027):"},{"line_number":1640,"context_line":"                self._validated_checksum[\u0027header\u0027],"}],"source_content_type":"text/x-python","patch_set":9,"id":"285b80e2_cc0774ab","line":1637,"range":{"start_line":1637,"start_character":0,"end_line":1637,"end_character":2},"in_reply_to":"334a44c1_0502dacd","updated":"2026-06-09 18:05:19.000000000","message":"Yes this is true, we COULD infer the algorithm from the checksum-header, but checksum-algorithm is some algorithm that Swift provides so if for whatever reason we need to recompute/revalidate the checksum of this object, we can pull this header and just compare it too known checksum functions and use the `.name` field that belongs to them.\n\nBut since this really ins\u0027t needed, we can probably just discard this.","commit_id":"1b912f91b63174a730697c8c0591ba2e8581a2c0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1149,"context_line":"                verify_checksum \u003d False"},{"line_number":1150,"context_line":""},{"line_number":1151,"context_line":"            if checksum_key and verify_checksum:"},{"line_number":1152,"context_line":"                self._checksum_to_validate \u003d True"},{"line_number":1153,"context_line":"                self._install_checksumming_input_wrapper("},{"line_number":1154,"context_line":"                    checksum_hasher, checksum_key, checksum_source)"},{"line_number":1155,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"15633d3f_bc6a3131","line":1152,"updated":"2026-06-17 00:00:40.000000000","message":"I don\u0027t LOVE this state tracking cache - I feel like there could be a subtle bug where header\u0027s on a request object get mutated and this gets out of sync\n\nI wonder if we could keep the state on the ChecksumingInputWrapper - because any call to `wsgi.input.read()` forever taints the state of the request object by consuming the bytes from the network there\u0027s \"no going back\" once you read from .input - so up until then you could in-theory still install some checksum headers into the request object\u0027s header dict - but once you read .input either you\u0027re going to capture/calculate every chunk from read or not\n\nSo in the end asking `wsgi.input.what_was_the_matching_checksum_if_any()` un-conditionally in the updater_footers callback would be the least ambigous.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":1149,"context_line":"                verify_checksum \u003d False"},{"line_number":1150,"context_line":""},{"line_number":1151,"context_line":"            if checksum_key and verify_checksum:"},{"line_number":1152,"context_line":"                self._checksum_to_validate \u003d True"},{"line_number":1153,"context_line":"                self._install_checksumming_input_wrapper("},{"line_number":1154,"context_line":"                    checksum_hasher, checksum_key, checksum_source)"},{"line_number":1155,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"fcca363d_45526904","line":1152,"in_reply_to":"15633d3f_bc6a3131","updated":"2026-06-22 23:53:33.000000000","message":"I agree with this and it makes the code cleaner to keep them together.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1628,"context_line":"            \u0027algorithm\u0027: checksum_hash_func.name,"},{"line_number":1629,"context_line":"            \u0027header\u0027: header,"},{"line_number":1630,"context_line":"            \u0027value\u0027: value,"},{"line_number":1631,"context_line":"        }"},{"line_number":1632,"context_line":""},{"line_number":1633,"context_line":"    def _checksum_sysmeta_headers(self, checksum_type):"},{"line_number":1634,"context_line":"        if not self._validated_checksum:"}],"source_content_type":"text/x-python","patch_set":11,"id":"228088a5_3077d0a3","line":1631,"updated":"2026-06-17 00:00:40.000000000","message":"so we pass the input wrapper a callback so that it can update a backref on the request object... I don\u0027t *love* this design, but it might just be the \"least worse\" option given the current abstraction boundaries and code flow.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":1628,"context_line":"            \u0027algorithm\u0027: checksum_hash_func.name,"},{"line_number":1629,"context_line":"            \u0027header\u0027: header,"},{"line_number":1630,"context_line":"            \u0027value\u0027: value,"},{"line_number":1631,"context_line":"        }"},{"line_number":1632,"context_line":""},{"line_number":1633,"context_line":"    def _checksum_sysmeta_headers(self, checksum_type):"},{"line_number":1634,"context_line":"        if not self._validated_checksum:"}],"source_content_type":"text/x-python","patch_set":11,"id":"3566162a_cb3e6f27","line":1631,"in_reply_to":"228088a5_3077d0a3","updated":"2026-06-22 23:53:33.000000000","message":"Instead, if we keep the checksum state tied to `wsgi.input` (like the comment on L1152 says), then we can get rid of the callback function","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1643,"context_line":"        }"},{"line_number":1644,"context_line":""},{"line_number":1645,"context_line":"    def has_checksum_to_validate(self):"},{"line_number":1646,"context_line":"        return self._checksum_to_validate"},{"line_number":1647,"context_line":""},{"line_number":1648,"context_line":"    def checksum_mode_enabled(self):"},{"line_number":1649,"context_line":"        checksum_mode \u003d self.headers.get(\u0027x-amz-checksum-mode\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"55c4c58b_e6357d25","line":1646,"updated":"2026-06-17 00:00:40.000000000","message":"this seems like some pretty thin redirection - it\u0027s not helpful to grow two new abstractions/concepts that do the same thing.\n\nIf you want `req.checksum_to_validate` to be private/read-only the correct python-ism is `@property` for the public attribute that has the same name:\n\n```\n@property\ndef checksum_to_validate(self):\n    return self._checksum_to_validate\n```\n\nbut honestly I\u0027m not sure that the whole property shouldn\u0027t \"just\" be a read-only view over ~`_validate_checksum_headers`\n\nIt would be best if we could try and localize the access/validation of checksum metadata on write requests somewhere rather than having disparate methods relying on state captured during `__init__` staying consistent with the request objects header values across possible mutation as the object is pass around the various controllers.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":1643,"context_line":"        }"},{"line_number":1644,"context_line":""},{"line_number":1645,"context_line":"    def has_checksum_to_validate(self):"},{"line_number":1646,"context_line":"        return self._checksum_to_validate"},{"line_number":1647,"context_line":""},{"line_number":1648,"context_line":"    def checksum_mode_enabled(self):"},{"line_number":1649,"context_line":"        checksum_mode \u003d self.headers.get(\u0027x-amz-checksum-mode\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"0225c0c7_4e9a1026","line":1646,"in_reply_to":"55c4c58b_e6357d25","updated":"2026-06-22 23:53:33.000000000","message":"Acknowledged","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1650,"context_line":"        if checksum_mode is None:"},{"line_number":1651,"context_line":"            return False"},{"line_number":1652,"context_line":"        if checksum_mode !\u003d \u0027ENABLED\u0027:"},{"line_number":1653,"context_line":"            raise InvalidArgument(\u0027x-amz-checksum-mode\u0027, checksum_mode)"},{"line_number":1654,"context_line":"        return True"},{"line_number":1655,"context_line":""},{"line_number":1656,"context_line":"    def get_checksum_headers("}],"source_content_type":"text/x-python","patch_set":11,"id":"eebaebae_4cd9e885","line":1653,"updated":"2026-06-17 00:00:40.000000000","message":"this seems like a pretty decent \"read-only-view over specific contextual headers\" - once we\u0027ve established this sort of abstraction on the review object the \"smell\" becomes anyone ever looking at or setting `x-amx-checksum-mode` in headers directly.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":1650,"context_line":"        if checksum_mode is None:"},{"line_number":1651,"context_line":"            return False"},{"line_number":1652,"context_line":"        if checksum_mode !\u003d \u0027ENABLED\u0027:"},{"line_number":1653,"context_line":"            raise InvalidArgument(\u0027x-amz-checksum-mode\u0027, checksum_mode)"},{"line_number":1654,"context_line":"        return True"},{"line_number":1655,"context_line":""},{"line_number":1656,"context_line":"    def get_checksum_headers("}],"source_content_type":"text/x-python","patch_set":11,"id":"bbab7459_c6daf4e8","line":1653,"in_reply_to":"eebaebae_4cd9e885","updated":"2026-06-22 23:53:33.000000000","message":"Acknowledged","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1654,"context_line":"        return True"},{"line_number":1655,"context_line":""},{"line_number":1656,"context_line":"    def get_checksum_headers("},{"line_number":1657,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        Get the checksum headers tied to the current request."},{"line_number":1660,"context_line":"        :param checksum_type: The type of checksum to add to the response."}],"source_content_type":"text/x-python","patch_set":11,"id":"89933b6f_dce61392","line":1657,"updated":"2026-06-17 00:00:40.000000000","message":"anytime I see a kwarg my natural response is to question:\n\n1) does ANYONE call this method w/ or w/o this parm\n2) do real callers in code that matters (not tests) *actually* sometimes call this method w/ AND w/o specifying this value\n3) should they?\n\n^ so you might notice a new method starting life with a \"optional\" kwarg generates a LOT of review work; better to create methods with the inputs they require and use them as prescribed.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":1654,"context_line":"        return True"},{"line_number":1655,"context_line":""},{"line_number":1656,"context_line":"    def get_checksum_headers("},{"line_number":1657,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        Get the checksum headers tied to the current request."},{"line_number":1660,"context_line":"        :param checksum_type: The type of checksum to add to the response."}],"source_content_type":"text/x-python","patch_set":11,"id":"74d15a38_626f4022","line":1657,"in_reply_to":"89933b6f_dce61392","updated":"2026-06-22 23:53:33.000000000","message":"After looking at this again, it does seem that there are only every 3 cases for the type\n- FULL_OBJECT\n- COMPOSITE\n- Something else (which would only be passed in make fake callers)\n\nWe can move this function to not have an optional param.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1672,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1673,"context_line":"        \"\"\""},{"line_number":1674,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"}],"source_content_type":"text/x-python","patch_set":11,"id":"c7bca516_07804eb2","line":1675,"updated":"2026-06-17 00:00:40.000000000","message":"\"if validation fails\" - we probably should have returned an error and this method will never be called, right?\n\nThis reads like \"if validation fails we ignore the checksum headers\"","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"964ac133bf12e9cb028d7905935205d08cdb5625","unresolved":false,"context_lines":[{"line_number":1672,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1673,"context_line":"        \"\"\""},{"line_number":1674,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"}],"source_content_type":"text/x-python","patch_set":11,"id":"637b40b9_d559c743","line":1675,"in_reply_to":"5d508367_b1d7aba5","updated":"2026-08-19 23:43:30.000000000","message":"Done","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":1672,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1673,"context_line":"        \"\"\""},{"line_number":1674,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"}],"source_content_type":"text/x-python","patch_set":11,"id":"6e8c3d7a_377a87f6","line":1675,"in_reply_to":"696efd46_af145b79","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"131d8f7d48d3706c83b284c01816578a6c7582b8","unresolved":true,"context_lines":[{"line_number":1672,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1673,"context_line":"        \"\"\""},{"line_number":1674,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"}],"source_content_type":"text/x-python","patch_set":11,"id":"5d508367_b1d7aba5","line":1675,"in_reply_to":"6e8c3d7a_377a87f6","updated":"2026-07-01 21:29:39.000000000","message":"Marked as unresolved.","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":true,"context_lines":[{"line_number":1672,"context_line":"            self, checksum_type\u003dCHECKSUM_TYPE_FULL_OBJECT):"},{"line_number":1673,"context_line":"        \"\"\""},{"line_number":1674,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"}],"source_content_type":"text/x-python","patch_set":11,"id":"696efd46_af145b79","line":1675,"in_reply_to":"c7bca516_07804eb2","updated":"2026-06-22 23:53:33.000000000","message":"You are right, if validation fails we do ignore the checksum headers. If validation fails, an error is already thrown by ChecksummingInput:\n```python\n        if error:\n            self.close()\n            # Since we don\u0027t return the last chunk, the PUT never completes\n            raise S3InputChecksumMismatch(self._checksum_hasher.name.upper())\n```\n\nSo if we throw an error in `persist_checksum_sysmeta_after_validation`, it would be strange I think","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"},{"line_number":1679,"context_line":"            return"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        original_callback \u003d self.environ.get(\u0027swift.callback.update_footers\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"a8cddddf_beac21cd","line":1678,"updated":"2026-06-17 00:00:40.000000000","message":"so this is saying that if a user doesn\u0027t specify the checksum to validate no footer update gets installed - I think this would have to change if we ever start doing NVME64-by-default-unless-otherwise-specified the way that s3api does.\n\n^ and that\u0027s ok, most of the time it\u0027s better to code to the current contract","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"405a8558d9c1ef4d0c8b2790830714740780840d","unresolved":false,"context_lines":[{"line_number":1675,"context_line":"        If validation fails, no checksum sysmeta will exist."},{"line_number":1676,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1677,"context_line":"        \"\"\""},{"line_number":1678,"context_line":"        if not self._checksum_to_validate:"},{"line_number":1679,"context_line":"            return"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        original_callback \u003d self.environ.get(\u0027swift.callback.update_footers\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"e39d675d_811208d8","line":1678,"in_reply_to":"a8cddddf_beac21cd","updated":"2026-06-22 23:53:33.000000000","message":"I think what would be done in that moment would be on checksum header validation, we swap empty `x-amz-checksum-*` headers with `x-amz-checksum-crc64nvme` and logic would play out normally","commit_id":"80c64b1e4c6cf0ce59cb27d0459e77718a1a730f"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5651e7237d467f58af2443e5cd31812613edcf7f","unresolved":false,"context_lines":[{"line_number":66,"context_line":"    S3InputMalformedTrailer, S3InputMissingSecret, \\"},{"line_number":67,"context_line":"    S3InputSHA256Mismatch, S3InputChecksumMismatch, \\"},{"line_number":68,"context_line":"    S3InputChecksumTrailerInvalid"},{"line_number":69,"context_line":"from swift.common.middleware.s3api.utils import utf8encode, \\"},{"line_number":70,"context_line":"    S3Timestamp, mktime, MULTIUPLOAD_SUFFIX, CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":71,"context_line":"from swift.common.middleware.s3api.subresource import decode_acl, encode_acl"},{"line_number":72,"context_line":"from swift.common.middleware.s3api.utils import sysmeta_header, \\"}],"source_content_type":"text/x-python","patch_set":13,"id":"7d405ed5_b8c0e37c","line":69,"updated":"2026-06-23 01:01:52.000000000","message":"pep8: F401 \u0027swift.common.middleware.s3api.utils.CHECKSUM_TYPE_FULL_OBJECT\u0027 imported but unused","commit_id":"76ae43392dcc96ed1bcfdd57c7a7bfc58fb48cfe"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":1618,"context_line":""},{"line_number":1619,"context_line":"    def _checksum_sysmeta_headers(self, checksum, checksum_type):"},{"line_number":1620,"context_line":"        if not checksum:"},{"line_number":1621,"context_line":"            return {}"},{"line_number":1622,"context_line":"        return {"},{"line_number":1623,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027):"},{"line_number":1624,"context_line":"                checksum[\u0027header\u0027],"}],"source_content_type":"text/x-python","patch_set":25,"id":"a4d2a2f8_d3639dae","line":1621,"updated":"2026-06-30 23:51:02.000000000","message":"I\u0027ve been trying to get my agents to find and call out this sort of stuff:\n\n```\n## 2. `_checksum_sysmeta_headers()` has an unreachable falsey-checksum branch\n\nFile/line: `swift/common/middleware/s3api/s3request.py:1619`\n\nConcrete failure path:\n\n`_checksum_sysmeta_headers()` starts with `if not checksum: return {}`. The\nonly production caller is the nested `update_footers()` callback in\n`persist_checksum_sysmeta_after_validation()`, and that caller already checks\n`if checksum:` before calling the helper. The worker found no real caller that\npasses `None`, `{}`, or another falsey value into this helper.\n\nWhy it matters:\n\nThis is duplicated defensive behavior in the persistence path for the new\nstored object metadata. The worker classified it as a blocking defensive\ncontract issue because the branch tolerates a state the implementation does\nnot produce and no focused test proves.\n\nAcceptance condition:\n\nRemove the falsey branch and keep the reachability decision in the caller. If\nfalsey checksums are intended input, add a real caller/state and focused test\nfor that exact state.\n```\n\nwhat do yo think!?","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":true,"context_lines":[{"line_number":1618,"context_line":""},{"line_number":1619,"context_line":"    def _checksum_sysmeta_headers(self, checksum, checksum_type):"},{"line_number":1620,"context_line":"        if not checksum:"},{"line_number":1621,"context_line":"            return {}"},{"line_number":1622,"context_line":"        return {"},{"line_number":1623,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027):"},{"line_number":1624,"context_line":"                checksum[\u0027header\u0027],"}],"source_content_type":"text/x-python","patch_set":25,"id":"e35b3f21_94e97859","line":1621,"in_reply_to":"a4d2a2f8_d3639dae","updated":"2026-07-01 17:11:33.000000000","message":"I agree with this since we don\u0027t have a production caller doing the checksum for us already","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":1618,"context_line":""},{"line_number":1619,"context_line":"    def _checksum_sysmeta_headers(self, checksum, checksum_type):"},{"line_number":1620,"context_line":"        if not checksum:"},{"line_number":1621,"context_line":"            return {}"},{"line_number":1622,"context_line":"        return {"},{"line_number":1623,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027):"},{"line_number":1624,"context_line":"                checksum[\u0027header\u0027],"}],"source_content_type":"text/x-python","patch_set":25,"id":"3aaff24b_5cc0032c","line":1621,"in_reply_to":"e35b3f21_94e97859","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":1651,"context_line":"    def persist_checksum_sysmeta_after_validation(self, checksum_type):"},{"line_number":1652,"context_line":"        \"\"\""},{"line_number":1653,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1654,"context_line":"        If validation fails, we will ignore checksum headers and"},{"line_number":1655,"context_line":"        no checksum sysmeta will exist."},{"line_number":1656,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1657,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":25,"id":"5dac1986_da2bdabd","line":1654,"updated":"2026-06-30 23:51:02.000000000","message":"so it\u0027s not \"we will ignore\" it\u0027s \"this method relies on another part of the system to ensure correctness\" - that\u0027s not \"ignore\" that\u0027s \"spooky action at distance\" but called out in a docstring as a scary sounding failure mode.\n\n```\nYes, that docstring is misleading if read literally.\n\nThe code does not ignore a failed checksum and write the object without\nchecksum sysmeta. On mismatch,\ninstances/vsaio-2/swift/swift/common/middleware/s3api/s3request.py:289 closes\nthe input and raises S3InputChecksumMismatch;\ninstances/vsaio-2/swift/swift/common/middleware/s3api/s3request.py:2235 maps\nthat to BadDigest. The controller never gets a successful response from\nreq.get_response().\n\nThe test confirms the intended behavior:\ninstances/vsaio-2/swift/test/unit/common/middleware/s3api/test_obj.py:1305\nexpects 400 BadDigest, no checksum response headers, and\ninstances/vsaio-2/swift/test/unit/common/middleware/s3api/ test_obj.py:1310\nasserts the object was not uploaded.\n\nBetter wording would be:\n\nIf checksum validation fails, the PUT fails before a matching checksum is\nrecorded, so no checksum sysmeta is persisted.\n\nSo: behavior looks correct; the docstring wording is sloppy enough to comment\non.\n```","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":true,"context_lines":[{"line_number":1651,"context_line":"    def persist_checksum_sysmeta_after_validation(self, checksum_type):"},{"line_number":1652,"context_line":"        \"\"\""},{"line_number":1653,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1654,"context_line":"        If validation fails, we will ignore checksum headers and"},{"line_number":1655,"context_line":"        no checksum sysmeta will exist."},{"line_number":1656,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1657,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":25,"id":"cb52c2bf_0a713595","line":1654,"in_reply_to":"5dac1986_da2bdabd","updated":"2026-07-01 17:11:33.000000000","message":"I think this comment is much better.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":1651,"context_line":"    def persist_checksum_sysmeta_after_validation(self, checksum_type):"},{"line_number":1652,"context_line":"        \"\"\""},{"line_number":1653,"context_line":"        Install a callback to persist checksum sysmeta after validation."},{"line_number":1654,"context_line":"        If validation fails, we will ignore checksum headers and"},{"line_number":1655,"context_line":"        no checksum sysmeta will exist."},{"line_number":1656,"context_line":"        :param checksum_type: The type of checksum to persist."},{"line_number":1657,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":25,"id":"bcb2b6b2_5b82d198","line":1654,"in_reply_to":"cb52c2bf_0a713595","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":1665,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1666,"context_line":"                    checksum, checksum_type))"},{"line_number":1667,"context_line":""},{"line_number":1668,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1669,"context_line":""},{"line_number":1670,"context_line":"    def _validate_headers(self):"},{"line_number":1671,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":25,"id":"20fa3637_1faf8666","line":1668,"updated":"2026-06-30 23:51:02.000000000","message":"I\u0027m really worried I may have steered you wrong in a previous review, the existence of this environ key is the trigger to force the object controller in MIME PUT mode - which has some implications for replicated PUTs with precomputed checksum header values:\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/proxy/controllers/obj.py#L1089\n\n```\n## 1. Checksum-free S3 PUTs now require metadata-footer backend support\n\nFile/line:\n\n- `swift/common/middleware/s3api/controllers/obj.py:176-178`\n- `swift/common/middleware/s3api/s3request.py:1658-1668`\n- `swift/proxy/controllers/obj.py:1088-1097`\n- `swift/proxy/controllers/obj.py:2103-2121`\n\nConcrete failure path:\n\nAn ordinary non-copy S3 object PUT with no `x-amz-checksum-*` header and no\nchecksum trailer reaches `ObjectController.PUT`. The patch calls\n`req.persist_checksum_sysmeta_after_validation(CHECKSUM_TYPE_FULL_OBJECT)` for\nevery non-copy PUT, even when `_validate_checksum_headers()` found no checksum\ninput. That helper unconditionally sets\n`environ[\u0027swift.callback.update_footers\u0027]`.\n\nThe Swift subrequest copies that environ into the proxy request. In the\nreplicated proxy path, `_make_putter()` selects `MIMEPutter` solely because\n`swift.callback.update_footers` exists. `MIMEPutter.connect()` then sends\n`X-Backend-Obj-Metadata-Footer: yes` and raises `FooterNotSupported()` when the\nobject server 100-continue response does not include\n`X-Obj-Metadata-Footer: yes`. If too few putters connect, `_check_min_conn()`\nreturns `HTTPServiceUnavailable`. So a checksum-free S3 PUT can fail as 503\nbefore sending the object body, despite no client use of the new checksum\nfeature.\n\nWhy it matters:\n\nThis broadens the backend compatibility contract for ordinary S3 PUTs. Existing\nproxy tests at `test/unit/proxy/controllers/test_obj.py:1630-1704` define\nno-footer PUTs as regular `Putter` requests with no\n`X-Backend-Obj-Metadata-Footer`, no MIME boundary, and no multiphase header.\nThe new s3api no-checksum test verifies no checksum sysmeta or response\nheaders, but it does not assert that the Swift subrequest avoids the footer\ncallback or the proxy metadata-footer path.\n\nAcceptance condition:\n\nDo not install `swift.callback.update_footers` for non-copy S3 PUTs unless the\nrequest actually has a checksum header or checksum trailer that can be\nvalidated and persisted. Add focused evidence that no-checksum S3 PUTs keep the\nregular proxy PUT path, while checksum header/trailer PUTs still use footers\nand persist checksum sysmeta only after successful validation.\n```\n\n^ FWIW this analysis is over-emphasizing old swifts that might not have been upgraded to support the x-backend-obj-metadata-footer: yes continue header - the real issue is the request structure wrapping performance implication; which maybe isn\u0027t THAT big of deal - but it\u0027s un-necessary overhead that may be easy enough to avoid by only installing the callback when we need it","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":true,"context_lines":[{"line_number":1665,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1666,"context_line":"                    checksum, checksum_type))"},{"line_number":1667,"context_line":""},{"line_number":1668,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1669,"context_line":""},{"line_number":1670,"context_line":"    def _validate_headers(self):"},{"line_number":1671,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":25,"id":"64ae7cda_708cc640","line":1668,"in_reply_to":"20fa3637_1faf8666","updated":"2026-07-01 17:11:33.000000000","message":"I agree that would not needed overhead. A small fix we could have would be to update the call in the s3api object controller #176\n```\nif not is_copy_request and req.has_checksum_to_validate():\n    req.persist_checksum_sysmeta_after_validation(CHECKSUM_TYPE_FULL_OBJECT)\n```\n\nAnd have some function maybe something like:\n```\ndef has_checksum_to_validate(self):\n    return hasattr(self.environ[\u0027wsgi.input\u0027], \u0027get_matching_checksum\u0027)\n```\n\nThough this would mean if the caller does not use `req.has_checksum_to_validate()` before calling `req.persist_checksum_sysmeta_after_validation`, then we could be in for some trouble. I think to avoid this possibility, we make `persist_checksum_sysmeta_after_validation` a private function so that we don\u0027t have the chance for a caller to put a footer call without proper checking.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":1665,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1666,"context_line":"                    checksum, checksum_type))"},{"line_number":1667,"context_line":""},{"line_number":1668,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1669,"context_line":""},{"line_number":1670,"context_line":"    def _validate_headers(self):"},{"line_number":1671,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":25,"id":"09a9a580_e5f345c9","line":1668,"in_reply_to":"64ae7cda_708cc640","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dc717074059fd84f9cbc4ab9e9f3082744ed1dc2","unresolved":true,"context_lines":[{"line_number":1678,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1679,"context_line":"                    checksum, checksum_type))"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"    def _validate_headers(self):"},{"line_number":1684,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":28,"id":"2dbe95ba_708cc89a","line":1681,"updated":"2026-07-02 15:09:37.000000000","message":"I don\u0027t think this callback gets copied to subrequests https://github.com/openstack/swift/blob/ae4186bdb64c83455278010c6f965353ea126ff6/swift/common/wsgi.py#L1326 which is significant if versioning is enabled because the actual data is PUT to a versions container using a subrequest https://github.com/openstack/swift/blob/master/swift/common/middleware/versioned_writes/object_versioning.py#L317, so I think the checksum sysmeta would not get appended to footers in that case.\n\nTim\u0027s original patch had some workaround for this is in versioning https://review.opendev.org/c/openstack/swift/+/909801/47/swift/common/middleware/versioned_writes/object_versioning.py \n\nI\u0027d suggest adding a functional and/or s3 compat test for checksum persistence with versioning and seeing what the outcome is.","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526990f301132aba4070cbe796ae24a64db09f2d","unresolved":true,"context_lines":[{"line_number":1678,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1679,"context_line":"                    checksum, checksum_type))"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"    def _validate_headers(self):"},{"line_number":1684,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":28,"id":"31b68a83_987edf96","line":1681,"in_reply_to":"2dbe95ba_708cc89a","updated":"2026-07-02 16:19:37.000000000","message":"update: Tim\u0027s patch had some changes in test/s3api/test_versioning.py","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"1041019dbf834d57a83318a0127cec6276b07cc6","unresolved":true,"context_lines":[{"line_number":1678,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1679,"context_line":"                    checksum, checksum_type))"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"    def _validate_headers(self):"},{"line_number":1684,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":28,"id":"530c7d71_53ca58b3","line":1681,"in_reply_to":"31b68a83_987edf96","updated":"2026-07-06 15:43:25.000000000","message":"I added the changes from the [original patch](https://review.opendev.org/c/openstack/swift/+/909801/47/swift/common/middleware/versioned_writes/object_versioning.py), with tests to match. Though, I\u0027m not really sure what would be a better solution to adding listing metadata for s3 checksums besides overriding a header from the container listing information. And we also don\u0027t have systags either...","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a40b971fe5d1b4ef1a45005fd0fe6c1e3590169f","unresolved":true,"context_lines":[{"line_number":1678,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1679,"context_line":"                    checksum, checksum_type))"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"    def _validate_headers(self):"},{"line_number":1684,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":28,"id":"9a123851_7c33cbf1","line":1681,"in_reply_to":"50f23bed_04148f5d","updated":"2026-07-06 19:45:40.000000000","message":"Disregard listing information, will stay out of scope.","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a85a057a7923a4db91dab91b78b8b3b3a0771d2f","unresolved":true,"context_lines":[{"line_number":1678,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1679,"context_line":"                    checksum, checksum_type))"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"    def _validate_headers(self):"},{"line_number":1684,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":28,"id":"50f23bed_04148f5d","line":1681,"in_reply_to":"530c7d71_53ca58b3","updated":"2026-07-06 15:55:49.000000000","message":"See https://review.opendev.org/c/openstack/swift/+/991516/32/swift/common/middleware/versioned_writes/object_versioning.py#333","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"d0f906201eaffe9201bdc63f40b5d6498c6cfa0e","unresolved":false,"context_lines":[{"line_number":1678,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1679,"context_line":"                    checksum, checksum_type))"},{"line_number":1680,"context_line":""},{"line_number":1681,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"    def _validate_headers(self):"},{"line_number":1684,"context_line":"        if \u0027CONTENT_LENGTH\u0027 in self.environ:"}],"source_content_type":"text/x-python","patch_set":28,"id":"a63ef1e1_ae7fae53","line":1681,"in_reply_to":"9a123851_7c33cbf1","updated":"2026-07-07 16:38:18.000000000","message":"Resolved","commit_id":"0fbac0e5da2ff369d647373f88f15c4404244143"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ad06d4c2b5bbcf6912af589e3f94049cc23c8f22","unresolved":true,"context_lines":[{"line_number":1143,"context_line":"                    checksum_hasher, checksum_key, checksum_source)"},{"line_number":1144,"context_line":"                if self.method in (\u0027PUT\u0027, \u0027POST\u0027) and \\"},{"line_number":1145,"context_line":"                        \u0027X-Amz-Copy-Source\u0027 not in self.headers:"},{"line_number":1146,"context_line":"                    self._persist_checksum_metadata_after_validation("},{"line_number":1147,"context_line":"                        self._checksum_type_for_request_sysmeta())"},{"line_number":1148,"context_line":""},{"line_number":1149,"context_line":"        # Lock in string-to-sign now, before we start messing with query params"}],"source_content_type":"text/x-python","patch_set":36,"id":"e020dffa_cab94c8c","line":1146,"updated":"2026-07-16 16:10:33.000000000","message":"same here, MPU UploadPart ``PUT ?partNumber\u003dN\u0026uploadId\u003dX`` with a per-part ``x-amz-checksum-* header`` is a PUT with no copy source, so MPU UploadPart will persist ``checksum-type: FULL_OBJECT`` as sysmeta on the segment object.","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c63ac75b45a4aee449aacd462f259b27b1d1b1c8","unresolved":false,"context_lines":[{"line_number":1143,"context_line":"                    checksum_hasher, checksum_key, checksum_source)"},{"line_number":1144,"context_line":"                if self.method in (\u0027PUT\u0027, \u0027POST\u0027) and \\"},{"line_number":1145,"context_line":"                        \u0027X-Amz-Copy-Source\u0027 not in self.headers:"},{"line_number":1146,"context_line":"                    self._persist_checksum_metadata_after_validation("},{"line_number":1147,"context_line":"                        self._checksum_type_for_request_sysmeta())"},{"line_number":1148,"context_line":""},{"line_number":1149,"context_line":"        # Lock in string-to-sign now, before we start messing with query params"}],"source_content_type":"text/x-python","patch_set":36,"id":"039c22c8_47b74e83","line":1146,"in_reply_to":"e020dffa_cab94c8c","updated":"2026-07-16 18:34:49.000000000","message":"Acknowledged","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ad06d4c2b5bbcf6912af589e3f94049cc23c8f22","unresolved":true,"context_lines":[{"line_number":2332,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2333,"context_line":"            if method in (\u0027PUT\u0027, \u0027POST\u0027) and \\"},{"line_number":2334,"context_line":"                    \u0027X-Amz-Copy-Source\u0027 not in self.headers:"},{"line_number":2335,"context_line":"                resp.headers.update(self._checksum_response_headers("},{"line_number":2336,"context_line":"                    self._checksum_type_for_request_sysmeta()))"},{"line_number":2337,"context_line":"            return resp"},{"line_number":2338,"context_line":""}],"source_content_type":"text/x-python","patch_set":36,"id":"0a370994_2027f5dc","line":2335,"updated":"2026-07-16 16:10:33.000000000","message":"A MPU UploadPart ``PUT ?partNumber\u003dN\u0026uploadId\u003dX`` with a per-part ``x-amz-checksum-*`` header is a PUT with no copy source, so it slips through and MPU UploadPart will end up see ``x-amz-checksum-type: FULL_OBJECT`` in the response.\n\nFor MPU, the type (FULL_OBJECT/COMPOSITE) is a whole-object/MPU-level concept, not a per-part one.","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c63ac75b45a4aee449aacd462f259b27b1d1b1c8","unresolved":false,"context_lines":[{"line_number":2332,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2333,"context_line":"            if method in (\u0027PUT\u0027, \u0027POST\u0027) and \\"},{"line_number":2334,"context_line":"                    \u0027X-Amz-Copy-Source\u0027 not in self.headers:"},{"line_number":2335,"context_line":"                resp.headers.update(self._checksum_response_headers("},{"line_number":2336,"context_line":"                    self._checksum_type_for_request_sysmeta()))"},{"line_number":2337,"context_line":"            return resp"},{"line_number":2338,"context_line":""}],"source_content_type":"text/x-python","patch_set":36,"id":"b2a2cadc_90c361aa","line":2335,"in_reply_to":"0a370994_2027f5dc","updated":"2026-07-16 18:34:49.000000000","message":"I agree with this, thanks for catching it! The changes from https://review.opendev.org/c/openstack/swift/+/997623 fix this and I\u0027ll make sure to update expected behavior in child patches.","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":264,"context_line":"        self._checksum_source \u003d checksum_source"},{"line_number":265,"context_line":"        self._matching_checksum \u003d None"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    def get_matching_checksum(self):"},{"line_number":268,"context_line":"        return self._matching_checksum"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"    def chunk_update(self, chunk, eof, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":59,"id":"2aef70df_278e216b","line":267,"updated":"2026-08-06 15:45:39.000000000","message":"this can be a property rather than a method","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":264,"context_line":"        self._checksum_source \u003d checksum_source"},{"line_number":265,"context_line":"        self._matching_checksum \u003d None"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"    def get_matching_checksum(self):"},{"line_number":268,"context_line":"        return self._matching_checksum"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"    def chunk_update(self, chunk, eof, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":59,"id":"7ce8b5e9_18bb37ee","line":267,"in_reply_to":"2aef70df_278e216b","updated":"2026-08-06 22:19:30.000000000","message":"I agree","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":295,"context_line":"                    \u0027algorithm\u0027: self._checksum_hasher.name,"},{"line_number":296,"context_line":"                    \u0027header\u0027: self._checksum_key,"},{"line_number":297,"context_line":"                    \u0027value\u0027: b64digest,"},{"line_number":298,"context_line":"                }"},{"line_number":299,"context_line":"        else:"},{"line_number":300,"context_line":"            # the underlying wsgi.Input stops reading at content-length so we"},{"line_number":301,"context_line":"            # don\u0027t expect to reach this clause, but just in case..."}],"source_content_type":"text/x-python","patch_set":59,"id":"474afac6_0540c46f","line":298,"updated":"2026-08-06 15:45:39.000000000","message":"why is this a dict? the b64digest can just be an attribute of the ChecksummingInput, and the other items already are (or are accessible via attributes).\n\nThere\u0027s no need to copy values into a dict, and in the process it introduces another naming system. We don\u0027t need a different objet (a dict) to pass around when we have checksumming_input and it\u0027s hasher","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":295,"context_line":"                    \u0027algorithm\u0027: self._checksum_hasher.name,"},{"line_number":296,"context_line":"                    \u0027header\u0027: self._checksum_key,"},{"line_number":297,"context_line":"                    \u0027value\u0027: b64digest,"},{"line_number":298,"context_line":"                }"},{"line_number":299,"context_line":"        else:"},{"line_number":300,"context_line":"            # the underlying wsgi.Input stops reading at content-length so we"},{"line_number":301,"context_line":"            # don\u0027t expect to reach this clause, but just in case..."}],"source_content_type":"text/x-python","patch_set":59,"id":"c64826b1_e9998801","line":298,"in_reply_to":"474afac6_0540c46f","updated":"2026-08-06 22:19:30.000000000","message":"Yea this is a really good point, I\u0027ll update this to just be attributes","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1168,"context_line":"                if self._should_handle_request_checksum(self.method):"},{"line_number":1169,"context_line":"                    self._persist_checksum_metadata_after_validation("},{"line_number":1170,"context_line":"                        checksumming_input,"},{"line_number":1171,"context_line":"                        self._checksum_type_for_request_sysmeta())"},{"line_number":1172,"context_line":""},{"line_number":1173,"context_line":"        # Lock in string-to-sign now, before we start messing with query params"},{"line_number":1174,"context_line":"        self.environ[\u0027s3api.auth_details\u0027] \u003d {"}],"source_content_type":"text/x-python","patch_set":59,"id":"5b252e61_db0c6cb4","line":1171,"range":{"start_line":1171,"start_character":24,"end_line":1171,"end_character":65},"updated":"2026-08-06 15:45:39.000000000","message":"why pass the result of a zero-argument call to self as an arg to a call to self, ``_persist_checksum_metadata_after_validation`` can just call ``self._checksum_type_for_request_sysmeta()``, making a simpler interface and less for a human to track through the call chain","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1168,"context_line":"                if self._should_handle_request_checksum(self.method):"},{"line_number":1169,"context_line":"                    self._persist_checksum_metadata_after_validation("},{"line_number":1170,"context_line":"                        checksumming_input,"},{"line_number":1171,"context_line":"                        self._checksum_type_for_request_sysmeta())"},{"line_number":1172,"context_line":""},{"line_number":1173,"context_line":"        # Lock in string-to-sign now, before we start messing with query params"},{"line_number":1174,"context_line":"        self.environ[\u0027s3api.auth_details\u0027] \u003d {"}],"source_content_type":"text/x-python","patch_set":59,"id":"9cb73560_8f52ec4b","line":1171,"range":{"start_line":1171,"start_character":24,"end_line":1171,"end_character":65},"in_reply_to":"5b252e61_db0c6cb4","updated":"2026-08-06 22:19:30.000000000","message":"I agree!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1646,"context_line":"        self.environ[\u0027wsgi.input\u0027] \u003d checksumming_input"},{"line_number":1647,"context_line":"        return checksumming_input"},{"line_number":1648,"context_line":""},{"line_number":1649,"context_line":"    def _should_handle_request_checksum(self, method):"},{"line_number":1650,"context_line":"        \"\"\""},{"line_number":1651,"context_line":"        Whether S3 user-checksum sysmeta should be persisted for, and echoed"},{"line_number":1652,"context_line":"        on, this write. Limited to whole-object writes handled by the object"}],"source_content_type":"text/x-python","patch_set":59,"id":"b43029d8_3e74515d","line":1649,"range":{"start_line":1649,"start_character":9,"end_line":1649,"end_character":39},"updated":"2026-08-06 15:45:39.000000000","message":"could this be renamed ``_should_persist_request_checksum`` ? \"handle\" is a bit vague and it suggests that we might not *verify* checksums, which we definitely do","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1646,"context_line":"        self.environ[\u0027wsgi.input\u0027] \u003d checksumming_input"},{"line_number":1647,"context_line":"        return checksumming_input"},{"line_number":1648,"context_line":""},{"line_number":1649,"context_line":"    def _should_handle_request_checksum(self, method):"},{"line_number":1650,"context_line":"        \"\"\""},{"line_number":1651,"context_line":"        Whether S3 user-checksum sysmeta should be persisted for, and echoed"},{"line_number":1652,"context_line":"        on, this write. Limited to whole-object writes handled by the object"}],"source_content_type":"text/x-python","patch_set":59,"id":"23f796d5_783a1082","line":1649,"range":{"start_line":1649,"start_character":9,"end_line":1649,"end_character":39},"in_reply_to":"b43029d8_3e74515d","updated":"2026-08-06 22:19:30.000000000","message":"Yea I think `persist` is better here","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        return (self.is_object_request and"},{"line_number":1660,"context_line":"                self.controller is ObjectController and"},{"line_number":1661,"context_line":"                method in (\u0027PUT\u0027, \u0027POST\u0027) and"},{"line_number":1662,"context_line":"                \u0027X-Amz-Copy-Source\u0027 not in self.headers and"},{"line_number":1663,"context_line":"                \u0027delete\u0027 not in self.params and"},{"line_number":1664,"context_line":"                \u0027uploadId\u0027 not in self.params)"}],"source_content_type":"text/x-python","patch_set":59,"id":"5e7a18af_c143454a","line":1661,"range":{"start_line":1661,"start_character":34,"end_line":1661,"end_character":40},"updated":"2026-08-06 15:45:39.000000000","message":"I removed \u0027POST\u0027 and no s3api unit tests fail. What request type is this covering? AFAICT checksums are ONLY verified for ``POST?delete``, and ``?delete`` is disallowed below","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        return (self.is_object_request and"},{"line_number":1660,"context_line":"                self.controller is ObjectController and"},{"line_number":1661,"context_line":"                method in (\u0027PUT\u0027, \u0027POST\u0027) and"},{"line_number":1662,"context_line":"                \u0027X-Amz-Copy-Source\u0027 not in self.headers and"},{"line_number":1663,"context_line":"                \u0027delete\u0027 not in self.params and"},{"line_number":1664,"context_line":"                \u0027uploadId\u0027 not in self.params)"}],"source_content_type":"text/x-python","patch_set":59,"id":"4b5be5fb_a558f8ea","line":1661,"range":{"start_line":1661,"start_character":34,"end_line":1661,"end_character":40},"in_reply_to":"5e7a18af_c143454a","updated":"2026-08-06 22:19:30.000000000","message":"Yea good point, `?delete` covers more than enough for this. I could see something for MPUs, but we already block `uploadId` too\n\nOh! it was this\nhttps://docs.aws.amazon.com/AmazonS3/latest/developerguide/RESTObjectPOST.html\n\nBut Swift does not support POST uploads via S3... best to just purge this and add it later.","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1667,"context_line":"        \"\"\""},{"line_number":1668,"context_line":"        Return the checksum type to persist for request checksum sysmeta."},{"line_number":1669,"context_line":"        \"\"\""},{"line_number":1670,"context_line":"        return CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":1671,"context_line":""},{"line_number":1672,"context_line":"    def _checksum_sysmeta_headers(self, checksum, checksum_type):"},{"line_number":1673,"context_line":"        headers \u003d {"}],"source_content_type":"text/x-python","patch_set":59,"id":"478fb0dd_3fb9457d","line":1670,"updated":"2026-08-06 15:45:39.000000000","message":"ok, I guess this may change later to have more than one possible return value","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1667,"context_line":"        \"\"\""},{"line_number":1668,"context_line":"        Return the checksum type to persist for request checksum sysmeta."},{"line_number":1669,"context_line":"        \"\"\""},{"line_number":1670,"context_line":"        return CHECKSUM_TYPE_FULL_OBJECT"},{"line_number":1671,"context_line":""},{"line_number":1672,"context_line":"    def _checksum_sysmeta_headers(self, checksum, checksum_type):"},{"line_number":1673,"context_line":"        headers \u003d {"}],"source_content_type":"text/x-python","patch_set":59,"id":"cca85601_d57845f1","line":1670,"in_reply_to":"478fb0dd_3fb9457d","updated":"2026-08-06 22:19:30.000000000","message":"Yes in the future, we might return `None`, for a `UploadPart` request for instance","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1676,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027):"},{"line_number":1677,"context_line":"                checksum[\u0027value\u0027],"},{"line_number":1678,"context_line":"        }"},{"line_number":1679,"context_line":"        if checksum_type:"},{"line_number":1680,"context_line":"            headers[sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027)] \u003d \\"},{"line_number":1681,"context_line":"                checksum_type"},{"line_number":1682,"context_line":"        return headers"}],"source_content_type":"text/x-python","patch_set":59,"id":"1030f0f3_0cc652cb","line":1679,"range":{"start_line":1679,"start_character":11,"end_line":1679,"end_character":24},"updated":"2026-08-06 15:45:39.000000000","message":"when is this ever not True?\n\nno s3api unit tests fail if I remove this condition","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1676,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027):"},{"line_number":1677,"context_line":"                checksum[\u0027value\u0027],"},{"line_number":1678,"context_line":"        }"},{"line_number":1679,"context_line":"        if checksum_type:"},{"line_number":1680,"context_line":"            headers[sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027)] \u003d \\"},{"line_number":1681,"context_line":"                checksum_type"},{"line_number":1682,"context_line":"        return headers"}],"source_content_type":"text/x-python","patch_set":59,"id":"bc891d13_babcfa6e","line":1679,"range":{"start_line":1679,"start_character":11,"end_line":1679,"end_character":24},"in_reply_to":"1030f0f3_0cc652cb","updated":"2026-08-06 22:19:30.000000000","message":"This kinda plays with 993193: s3api: Checksum Persistence on MPUs | https://review.opendev.org/c/openstack/swift/+/993193 , as we don\u0027t store the checksum type on `UploadPart` requests","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1681,"context_line":"                checksum_type"},{"line_number":1682,"context_line":"        return headers"},{"line_number":1683,"context_line":""},{"line_number":1684,"context_line":"    def _validate_checksum_mode_header(self):"},{"line_number":1685,"context_line":"        checksum_mode \u003d self.headers.get(\u0027x-amz-checksum-mode\u0027)"},{"line_number":1686,"context_line":"        if checksum_mode is None or checksum_mode \u003d\u003d \u0027ENABLED\u0027:"},{"line_number":1687,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":59,"id":"f0fff2de_857a0e1a","line":1684,"updated":"2026-08-06 15:45:39.000000000","message":"nit: this breaks up the flow of the header generation methodsuuu, could move down to be adjacent with ``_validate_headers``","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1681,"context_line":"                checksum_type"},{"line_number":1682,"context_line":"        return headers"},{"line_number":1683,"context_line":""},{"line_number":1684,"context_line":"    def _validate_checksum_mode_header(self):"},{"line_number":1685,"context_line":"        checksum_mode \u003d self.headers.get(\u0027x-amz-checksum-mode\u0027)"},{"line_number":1686,"context_line":"        if checksum_mode is None or checksum_mode \u003d\u003d \u0027ENABLED\u0027:"},{"line_number":1687,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":59,"id":"4cda26bc_f40edbf5","line":1684,"in_reply_to":"f0fff2de_857a0e1a","updated":"2026-08-06 22:19:30.000000000","message":"Yep good callout, thanks!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1700,"context_line":"        if not checksum:"},{"line_number":1701,"context_line":"            return {}"},{"line_number":1702,"context_line":"        headers \u003d {checksum[\u0027header\u0027]: checksum[\u0027value\u0027]}"},{"line_number":1703,"context_line":"        if checksum_type:"},{"line_number":1704,"context_line":"            headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":1705,"context_line":"        return headers"},{"line_number":1706,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"cf16ed58_53a9a1f8","line":1703,"range":{"start_line":1703,"start_character":8,"end_line":1703,"end_character":24},"updated":"2026-08-06 15:45:39.000000000","message":"as above - can this be False?","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1700,"context_line":"        if not checksum:"},{"line_number":1701,"context_line":"            return {}"},{"line_number":1702,"context_line":"        headers \u003d {checksum[\u0027header\u0027]: checksum[\u0027value\u0027]}"},{"line_number":1703,"context_line":"        if checksum_type:"},{"line_number":1704,"context_line":"            headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":1705,"context_line":"        return headers"},{"line_number":1706,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"265c28fe_e75629d0","line":1703,"range":{"start_line":1703,"start_character":8,"end_line":1703,"end_character":24},"in_reply_to":"cf16ed58_53a9a1f8","updated":"2026-08-06 22:19:30.000000000","message":"Same thing here, this can only be false once `UploadPart` requests come into the mix. You know I am thinking for this patch, we remove this guard and then add it later...\n\nYea it looks like your squash patch removes the guards... thanks!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1702,"context_line":"        headers \u003d {checksum[\u0027header\u0027]: checksum[\u0027value\u0027]}"},{"line_number":1703,"context_line":"        if checksum_type:"},{"line_number":1704,"context_line":"            headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":1705,"context_line":"        return headers"},{"line_number":1706,"context_line":""},{"line_number":1707,"context_line":"    def _persist_checksum_metadata_after_validation("},{"line_number":1708,"context_line":"            self, checksumming_input, checksum_type):"}],"source_content_type":"text/x-python","patch_set":59,"id":"77935b73_142fa16f","line":1705,"updated":"2026-08-06 15:45:39.000000000","message":"S3Response also has code to translate from checksum sysmeta to response headers. Let\u0027s have a single shared translator in utils.py","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":true,"context_lines":[{"line_number":1702,"context_line":"        headers \u003d {checksum[\u0027header\u0027]: checksum[\u0027value\u0027]}"},{"line_number":1703,"context_line":"        if checksum_type:"},{"line_number":1704,"context_line":"            headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":1705,"context_line":"        return headers"},{"line_number":1706,"context_line":""},{"line_number":1707,"context_line":"    def _persist_checksum_metadata_after_validation("},{"line_number":1708,"context_line":"            self, checksumming_input, checksum_type):"}],"source_content_type":"text/x-python","patch_set":59,"id":"d84a89b7_94ef90f7","line":1705,"in_reply_to":"77935b73_142fa16f","updated":"2026-08-06 22:19:30.000000000","message":"I agree, that would be better","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"14ba31dc00e4da5c6e6b93feb40f5e563b56af20","unresolved":false,"context_lines":[{"line_number":1702,"context_line":"        headers \u003d {checksum[\u0027header\u0027]: checksum[\u0027value\u0027]}"},{"line_number":1703,"context_line":"        if checksum_type:"},{"line_number":1704,"context_line":"            headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":1705,"context_line":"        return headers"},{"line_number":1706,"context_line":""},{"line_number":1707,"context_line":"    def _persist_checksum_metadata_after_validation("},{"line_number":1708,"context_line":"            self, checksumming_input, checksum_type):"}],"source_content_type":"text/x-python","patch_set":59,"id":"adc31a48_aac2a01c","line":1705,"in_reply_to":"d84a89b7_94ef90f7","updated":"2026-08-06 22:19:54.000000000","message":"Done","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1722,"context_line":"            checksum \u003d checksumming_input.get_matching_checksum()"},{"line_number":1723,"context_line":"            if checksum:"},{"line_number":1724,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1725,"context_line":"                    checksum, checksum_type))"},{"line_number":1726,"context_line":"                self._persisted_checksum \u003d checksum"},{"line_number":1727,"context_line":""},{"line_number":1728,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"}],"source_content_type":"text/x-python","patch_set":59,"id":"aa7fedf4_20eab396","line":1725,"updated":"2026-08-06 15:45:39.000000000","message":"IMHO there\u0027s unnecessary and confusing use of different data structures and names:\n * ``checksum`` here is actually a dict\n * checksumming_input is sufficient, no need to replace it with a dict to pass to ``_checksum_sysmeta_headers``","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1722,"context_line":"            checksum \u003d checksumming_input.get_matching_checksum()"},{"line_number":1723,"context_line":"            if checksum:"},{"line_number":1724,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1725,"context_line":"                    checksum, checksum_type))"},{"line_number":1726,"context_line":"                self._persisted_checksum \u003d checksum"},{"line_number":1727,"context_line":""},{"line_number":1728,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"}],"source_content_type":"text/x-python","patch_set":59,"id":"ab575889_b8923d38","line":1725,"in_reply_to":"aa7fedf4_20eab396","updated":"2026-08-06 22:19:30.000000000","message":"I agree here, it is confusing","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1723,"context_line":"            if checksum:"},{"line_number":1724,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1725,"context_line":"                    checksum, checksum_type))"},{"line_number":1726,"context_line":"                self._persisted_checksum \u003d checksum"},{"line_number":1727,"context_line":""},{"line_number":1728,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1729,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"eef4e1e5_49ee10ab","line":1726,"updated":"2026-08-06 15:45:39.000000000","message":"this is stashed so that response headers can be updated later, which is fine, but if we instead stash the sysmeta headers that were just generated then we can share a symeta-to-response-header translator with S3Response rather than having the duplicating ``_checksum_response_headers`` method in S3Request.\n\nIn fact, why not just compose the response headers right here and stash them? As a human maintainer I get to see the whole inbound/outbound picture in one place.","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1723,"context_line":"            if checksum:"},{"line_number":1724,"context_line":"                footers.update(self._checksum_sysmeta_headers("},{"line_number":1725,"context_line":"                    checksum, checksum_type))"},{"line_number":1726,"context_line":"                self._persisted_checksum \u003d checksum"},{"line_number":1727,"context_line":""},{"line_number":1728,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1729,"context_line":""}],"source_content_type":"text/x-python","patch_set":59,"id":"fd796dab_9f0ed40c","line":1726,"in_reply_to":"eef4e1e5_49ee10ab","updated":"2026-08-06 22:19:30.000000000","message":"I think that is the best solution","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a34d499787da38f221469b9f394f0a7b543b1dba","unresolved":true,"context_lines":[{"line_number":1654,"context_line":"        self.environ[\u0027wsgi.input\u0027] \u003d checksumming_input"},{"line_number":1655,"context_line":"        return checksumming_input"},{"line_number":1656,"context_line":""},{"line_number":1657,"context_line":"    def _should_persist_request_checksum(self):"},{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        Whether S3 user-checksum sysmeta should be persisted for, and echoed"},{"line_number":1660,"context_line":"        on, this write. Limited to whole-object writes handled by the object"}],"source_content_type":"text/x-python","patch_set":68,"id":"5d3afefd_4da2c96a","line":1657,"range":{"start_line":1657,"start_character":0,"end_line":1657,"end_character":47},"updated":"2026-08-10 18:26:48.000000000","message":"After a talk with @alistairncoles@gmail.com @cschwede@nvidia.com and @jhuo@nvidia.com, it is probably best to move controller specific code outside of `S3Request`... we can probably tear is function up, make S3Request persist checksums by default, and have controller classes override that normal persistence in the event a client.","commit_id":"4a37a6dcc1103391c4883d37e79ed938084a0560"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"b614f6d2a6ff1663526c09680bded9309be73eee","unresolved":true,"context_lines":[{"line_number":1654,"context_line":"        self.environ[\u0027wsgi.input\u0027] \u003d checksumming_input"},{"line_number":1655,"context_line":"        return checksumming_input"},{"line_number":1656,"context_line":""},{"line_number":1657,"context_line":"    def _should_persist_request_checksum(self):"},{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        Whether S3 user-checksum sysmeta should be persisted for, and echoed"},{"line_number":1660,"context_line":"        on, this write. Limited to whole-object writes handled by the object"}],"source_content_type":"text/x-python","patch_set":68,"id":"94138a33_18ebffc7","line":1657,"range":{"start_line":1657,"start_character":0,"end_line":1657,"end_character":47},"in_reply_to":"5d3afefd_4da2c96a","updated":"2026-08-10 18:29:37.000000000","message":"\u003e S3Request persist checksums by default\n\nUPDATE probably a \"deny all except ...\" kind of rule would be better","commit_id":"4a37a6dcc1103391c4883d37e79ed938084a0560"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3324f3bc79a529eaa99eb5ba318e7748d631210a","unresolved":false,"context_lines":[{"line_number":1654,"context_line":"        self.environ[\u0027wsgi.input\u0027] \u003d checksumming_input"},{"line_number":1655,"context_line":"        return checksumming_input"},{"line_number":1656,"context_line":""},{"line_number":1657,"context_line":"    def _should_persist_request_checksum(self):"},{"line_number":1658,"context_line":"        \"\"\""},{"line_number":1659,"context_line":"        Whether S3 user-checksum sysmeta should be persisted for, and echoed"},{"line_number":1660,"context_line":"        on, this write. Limited to whole-object writes handled by the object"}],"source_content_type":"text/x-python","patch_set":68,"id":"40d39e6c_79d062e1","line":1657,"range":{"start_line":1657,"start_character":0,"end_line":1657,"end_character":47},"in_reply_to":"94138a33_18ebffc7","updated":"2026-08-10 23:38:54.000000000","message":"Done","commit_id":"4a37a6dcc1103391c4883d37e79ed938084a0560"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1589,"context_line":""},{"line_number":1590,"context_line":"    def persist_request_checksum(self, checksum_type):"},{"line_number":1591,"context_line":"        \"\"\""},{"line_number":1592,"context_line":"        Enable checksum persistence with the supplied checksum type"},{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":76,"id":"3ddcf2e3_08d161b8","line":1592,"range":{"start_line":1592,"start_character":8,"end_line":1592,"end_character":35},"updated":"2026-08-21 16:03:49.000000000","message":"this sounds like a great name for this method ;-) \n\nthe method doesn\u0027t take an immediate action, it enables a future action","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":1589,"context_line":""},{"line_number":1590,"context_line":"    def persist_request_checksum(self, checksum_type):"},{"line_number":1591,"context_line":"        \"\"\""},{"line_number":1592,"context_line":"        Enable checksum persistence with the supplied checksum type"},{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":76,"id":"9080a6dd_574afc2e","line":1592,"range":{"start_line":1592,"start_character":8,"end_line":1592,"end_character":35},"in_reply_to":"3ddcf2e3_08d161b8","updated":"2026-08-21 20:10:41.000000000","message":"I agree, \u0027enable\u0027 does not define immediate action like `persist` does, this is better","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1591,"context_line":"        \"\"\""},{"line_number":1592,"context_line":"        Enable checksum persistence with the supplied checksum type"},{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        self._request_checksum_type \u003d checksum_type"},{"line_number":1597,"context_line":"        # We really only want to insert a footer"}],"source_content_type":"text/x-python","patch_set":76,"id":"12ffbc03_7f1d7025","line":1594,"updated":"2026-08-21 16:03:49.000000000","message":"nit: we usually have a blank line before the params\n\nditto elsewhere","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":1591,"context_line":"        \"\"\""},{"line_number":1592,"context_line":"        Enable checksum persistence with the supplied checksum type"},{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        self._request_checksum_type \u003d checksum_type"},{"line_number":1597,"context_line":"        # We really only want to insert a footer"}],"source_content_type":"text/x-python","patch_set":76,"id":"a059d7d2_8e5c613c","line":1594,"in_reply_to":"12ffbc03_7f1d7025","updated":"2026-08-21 20:10:41.000000000","message":"Noted, will do","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        self._request_checksum_type \u003d checksum_type"},{"line_number":1597,"context_line":"        # We really only want to insert a footer"},{"line_number":1598,"context_line":"        # callback if actually need to, so insert it here"},{"line_number":1599,"context_line":"        if self._checksumming_input is not None:"}],"source_content_type":"text/x-python","patch_set":76,"id":"ed85c157_6058b672","line":1596,"range":{"start_line":1596,"start_character":8,"end_line":1596,"end_character":51},"updated":"2026-08-21 16:03:49.000000000","message":"this doesn\u0027t need to be a class attribute, it can just be passed through to the callback\n\nAlso, will it ever not be CHECKSUM_TYPE_FULL_OBJECT in future patches i.e. does MPU use this method? ChecksummingInput only calculate a full checksum, so I\u0027m not sure what the implication of this being any other than full would be. \n\nIn fact, the method could be called ``enable_full_checksum_persistence`` perhaps?","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":true,"context_lines":[{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        self._request_checksum_type \u003d checksum_type"},{"line_number":1597,"context_line":"        # We really only want to insert a footer"},{"line_number":1598,"context_line":"        # callback if actually need to, so insert it here"},{"line_number":1599,"context_line":"        if self._checksumming_input is not None:"}],"source_content_type":"text/x-python","patch_set":76,"id":"f7a6ae1e_5b7b097c","line":1596,"range":{"start_line":1596,"start_character":8,"end_line":1596,"end_character":51},"in_reply_to":"ed85c157_6058b672","updated":"2026-08-21 20:10:41.000000000","message":"\u003e this doesn\u0027t need to be a class attribute, it can just be passed through to the callback\n\nYes I agree with this\n\n\u003e Also, will it ever not be CHECKSUM_TYPE_FULL_OBJECT in future patches\n\nYes there are cases where the checksum type may be something other than `FULL_OBJECT` for instance, UploadPart. Since this `enable_checksum_persistence` works at the individual request level, and not the MPU as a whole, then we need to decide what checksum type to persist with this object. For MPUs, when we need to persist checksums with parts, we will want to pass in the checksum type of `None` because the checksum type is defined at the MPU level, not the part level.\n\n\u003e  ChecksummingInput only calculate a full checksum\nSure this is true, but the type may not pertain to \"what does this checksum represent. For normal objects, yes its always `FULL_OBJECT`, but for parts, that type is defined at the MPU level.","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6290d449798b3f5b185f1af3e31205b9652045b1","unresolved":false,"context_lines":[{"line_number":1593,"context_line":"        if this S3Request has a checksum that can be persisted."},{"line_number":1594,"context_line":"        :param checksum_type: The type of the checksum we are persisting"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        self._request_checksum_type \u003d checksum_type"},{"line_number":1597,"context_line":"        # We really only want to insert a footer"},{"line_number":1598,"context_line":"        # callback if actually need to, so insert it here"},{"line_number":1599,"context_line":"        if self._checksumming_input is not None:"}],"source_content_type":"text/x-python","patch_set":76,"id":"9c9ac822_596fc927","line":1596,"range":{"start_line":1596,"start_character":8,"end_line":1596,"end_character":51},"in_reply_to":"f7a6ae1e_5b7b097c","updated":"2026-08-25 17:46:23.000000000","message":"Acknowledged","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1600,"context_line":"            self._persist_checksum_metadata_after_validation("},{"line_number":1601,"context_line":"                self._checksumming_input)"},{"line_number":1602,"context_line":""},{"line_number":1603,"context_line":"    def _persist_checksum_metadata_after_validation(self, checksumming_input):"},{"line_number":1604,"context_line":"        \"\"\""},{"line_number":1605,"context_line":"        Install a callback to persist checksum metadata after validation."},{"line_number":1606,"context_line":"        If checksum validation fails, the PUT fails before a matching checksum"}],"source_content_type":"text/x-python","patch_set":76,"id":"a7ccfd04_13350319","line":1603,"range":{"start_line":1603,"start_character":8,"end_line":1603,"end_character":51},"updated":"2026-08-21 16:03:49.000000000","message":"``_install_checksum_footers_callback`` would say exactly what it does ;-)","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":1600,"context_line":"            self._persist_checksum_metadata_after_validation("},{"line_number":1601,"context_line":"                self._checksumming_input)"},{"line_number":1602,"context_line":""},{"line_number":1603,"context_line":"    def _persist_checksum_metadata_after_validation(self, checksumming_input):"},{"line_number":1604,"context_line":"        \"\"\""},{"line_number":1605,"context_line":"        Install a callback to persist checksum metadata after validation."},{"line_number":1606,"context_line":"        If checksum validation fails, the PUT fails before a matching checksum"}],"source_content_type":"text/x-python","patch_set":76,"id":"69319bb0_4803ff08","line":1603,"range":{"start_line":1603,"start_character":8,"end_line":1603,"end_character":51},"in_reply_to":"a7ccfd04_13350319","updated":"2026-08-21 20:10:41.000000000","message":"Yes this is a better name I think!","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1616,"context_line":"                original_callback(footers)"},{"line_number":1617,"context_line":"            if checksumming_input.matching_checksum:"},{"line_number":1618,"context_line":"                sysmeta_headers \u003d checksum_sysmeta_headers("},{"line_number":1619,"context_line":"                    checksum_algorithm_from_header("},{"line_number":1620,"context_line":"                        checksumming_input.checksum_key),"},{"line_number":1621,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1622,"context_line":"                    self._request_checksum_type)"},{"line_number":1623,"context_line":"                footers.update(sysmeta_headers)"}],"source_content_type":"text/x-python","patch_set":76,"id":"117b04b3_3c070577","line":1620,"range":{"start_line":1619,"start_character":20,"end_line":1620,"end_character":56},"updated":"2026-08-21 16:03:49.000000000","message":"I could imagine having a ``ChecksummingInput.algorithm`` property that makes this translation as a convenience to make this simpler","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":1616,"context_line":"                original_callback(footers)"},{"line_number":1617,"context_line":"            if checksumming_input.matching_checksum:"},{"line_number":1618,"context_line":"                sysmeta_headers \u003d checksum_sysmeta_headers("},{"line_number":1619,"context_line":"                    checksum_algorithm_from_header("},{"line_number":1620,"context_line":"                        checksumming_input.checksum_key),"},{"line_number":1621,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1622,"context_line":"                    self._request_checksum_type)"},{"line_number":1623,"context_line":"                footers.update(sysmeta_headers)"}],"source_content_type":"text/x-python","patch_set":76,"id":"f5c96255_f8761167","line":1620,"range":{"start_line":1619,"start_character":20,"end_line":1620,"end_character":56},"in_reply_to":"117b04b3_3c070577","updated":"2026-08-21 20:10:41.000000000","message":"Yea I think that could be good too","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1621,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1622,"context_line":"                    self._request_checksum_type)"},{"line_number":1623,"context_line":"                footers.update(sysmeta_headers)"},{"line_number":1624,"context_line":"                self._checksum_response_headers \u003d \\"},{"line_number":1625,"context_line":"                    checksum_sysmeta_to_response_headers(sysmeta_headers)"},{"line_number":1626,"context_line":""},{"line_number":1627,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"}],"source_content_type":"text/x-python","patch_set":76,"id":"4ab59ce2_fddb84a5","line":1624,"range":{"start_line":1624,"start_character":22,"end_line":1624,"end_character":47},"updated":"2026-08-21 16:03:49.000000000","message":"maybe there is precedence, but its seems unfortunate that the S3Request class is storing response headers...I think we could have it store the sysmeta headers it sent and then have the object controller install the response headers...see sq patch","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":1621,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1622,"context_line":"                    self._request_checksum_type)"},{"line_number":1623,"context_line":"                footers.update(sysmeta_headers)"},{"line_number":1624,"context_line":"                self._checksum_response_headers \u003d \\"},{"line_number":1625,"context_line":"                    checksum_sysmeta_to_response_headers(sysmeta_headers)"},{"line_number":1626,"context_line":""},{"line_number":1627,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"}],"source_content_type":"text/x-python","patch_set":76,"id":"d5b4f9cf_f179f81a","line":1624,"range":{"start_line":1624,"start_character":22,"end_line":1624,"end_character":47},"in_reply_to":"4ab59ce2_fddb84a5","updated":"2026-08-21 20:10:41.000000000","message":"\u003e but its seems unfortunate that the S3Request class is storing response headers...\n\nI agree it is a bit counter-intuitive for a request class to be manipulating the response class.","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":2270,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":2271,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2272,"context_line":"            if self.checksum_response_headers:"},{"line_number":2273,"context_line":"                resp.headers.update(self.checksum_response_headers)"},{"line_number":2274,"context_line":"            return resp"},{"line_number":2275,"context_line":""},{"line_number":2276,"context_line":"        err_msg \u003d resp.body"}],"source_content_type":"text/x-python","patch_set":76,"id":"d5151ee5_07138bf3","line":2273,"updated":"2026-08-21 16:03:49.000000000","message":"alternatively the object controller could do this?","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":2270,"context_line":"            # inject the checksum response headers after validation succeeds."},{"line_number":2271,"context_line":"            # GET/HEAD responses use the stored sysmeta echoed from Swift."},{"line_number":2272,"context_line":"            if self.checksum_response_headers:"},{"line_number":2273,"context_line":"                resp.headers.update(self.checksum_response_headers)"},{"line_number":2274,"context_line":"            return resp"},{"line_number":2275,"context_line":""},{"line_number":2276,"context_line":"        err_msg \u003d resp.body"}],"source_content_type":"text/x-python","patch_set":76,"id":"8a2dbd51_b738a0b1","line":2273,"in_reply_to":"d5151ee5_07138bf3","updated":"2026-08-21 20:10:41.000000000","message":"I could see that argument, would remove concerns for what the request class should be doing.","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6290d449798b3f5b185f1af3e31205b9652045b1","unresolved":true,"context_lines":[{"line_number":1048,"context_line":"        self._signing_timestamp \u003d None"},{"line_number":1049,"context_line":"        self._checksumming_input \u003d None"},{"line_number":1050,"context_line":"        self.checksum_sysmeta_headers \u003d None"},{"line_number":1051,"context_line":"        self._request_checksum_type \u003d None"},{"line_number":1052,"context_line":"        self.access_key, self.signature \u003d self._parse_auth_info()"},{"line_number":1053,"context_line":"        self.bucket_in_host \u003d parse_host(self.environ,"},{"line_number":1054,"context_line":"                                         self.conf.storage_domains)"}],"source_content_type":"text/x-python","patch_set":82,"id":"dc7d0d74_60f7ed22","line":1051,"range":{"start_line":1051,"start_character":8,"end_line":1051,"end_character":42},"updated":"2026-08-25 17:46:23.000000000","message":"this is not used","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3c456075f1e53c99da490dd8f9e9abf595cf04bd","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"        self._signing_timestamp \u003d None"},{"line_number":1049,"context_line":"        self._checksumming_input \u003d None"},{"line_number":1050,"context_line":"        self.checksum_sysmeta_headers \u003d None"},{"line_number":1051,"context_line":"        self._request_checksum_type \u003d None"},{"line_number":1052,"context_line":"        self.access_key, self.signature \u003d self._parse_auth_info()"},{"line_number":1053,"context_line":"        self.bucket_in_host \u003d parse_host(self.environ,"},{"line_number":1054,"context_line":"                                         self.conf.storage_domains)"}],"source_content_type":"text/x-python","patch_set":82,"id":"06497825_025cf4cf","line":1051,"range":{"start_line":1051,"start_character":8,"end_line":1051,"end_character":42},"in_reply_to":"c5197a11_5525e1ca","updated":"2026-08-25 23:44:29.000000000","message":"Done","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c447a2ef02b5b918e6db8ebdfc189307d0bde06b","unresolved":true,"context_lines":[{"line_number":1048,"context_line":"        self._signing_timestamp \u003d None"},{"line_number":1049,"context_line":"        self._checksumming_input \u003d None"},{"line_number":1050,"context_line":"        self.checksum_sysmeta_headers \u003d None"},{"line_number":1051,"context_line":"        self._request_checksum_type \u003d None"},{"line_number":1052,"context_line":"        self.access_key, self.signature \u003d self._parse_auth_info()"},{"line_number":1053,"context_line":"        self.bucket_in_host \u003d parse_host(self.environ,"},{"line_number":1054,"context_line":"                                         self.conf.storage_domains)"}],"source_content_type":"text/x-python","patch_set":82,"id":"c5197a11_5525e1ca","line":1051,"range":{"start_line":1051,"start_character":8,"end_line":1051,"end_character":42},"in_reply_to":"dc7d0d74_60f7ed22","updated":"2026-08-25 23:05:51.000000000","message":"Will clean up","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6290d449798b3f5b185f1af3e31205b9652045b1","unresolved":true,"context_lines":[{"line_number":1623,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1624,"context_line":"                    checksum_type)"},{"line_number":1625,"context_line":"                footers.update(sysmeta_headers)"},{"line_number":1626,"context_line":"                self.checksum_sysmeta_headers \u003d sysmeta_headers"},{"line_number":1627,"context_line":""},{"line_number":1628,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1629,"context_line":""}],"source_content_type":"text/x-python","patch_set":82,"id":"7c98d18a_b95d84cd","line":1626,"range":{"start_line":1626,"start_character":21,"end_line":1626,"end_character":45},"updated":"2026-08-25 17:46:23.000000000","message":"nit: might be clearer to name this ``self.checksum_sysmeta_footers``\n\nalso s/symeta_headers/sysmeta_footers/\n\nWhen I was looking at the obj.py change I found myself thinking \"why don\u0027t we just pass all the req headers to ``checksum_sysmeta_to_response_headers`` rather than just the ``checksum_sysmeta_headers ``. But then I reminded myself that these are not part of req.headers, they are footers !?!","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"c447a2ef02b5b918e6db8ebdfc189307d0bde06b","unresolved":true,"context_lines":[{"line_number":1623,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1624,"context_line":"                    checksum_type)"},{"line_number":1625,"context_line":"                footers.update(sysmeta_headers)"},{"line_number":1626,"context_line":"                self.checksum_sysmeta_headers \u003d sysmeta_headers"},{"line_number":1627,"context_line":""},{"line_number":1628,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1629,"context_line":""}],"source_content_type":"text/x-python","patch_set":82,"id":"a3e48631_1e645d28","line":1626,"range":{"start_line":1626,"start_character":21,"end_line":1626,"end_character":45},"in_reply_to":"7c98d18a_b95d84cd","updated":"2026-08-25 23:05:51.000000000","message":"Yea I think self.checksum_sysmeta_footers could be better","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"3c456075f1e53c99da490dd8f9e9abf595cf04bd","unresolved":false,"context_lines":[{"line_number":1623,"context_line":"                    checksumming_input.matching_checksum,"},{"line_number":1624,"context_line":"                    checksum_type)"},{"line_number":1625,"context_line":"                footers.update(sysmeta_headers)"},{"line_number":1626,"context_line":"                self.checksum_sysmeta_headers \u003d sysmeta_headers"},{"line_number":1627,"context_line":""},{"line_number":1628,"context_line":"        self.environ[\u0027swift.callback.update_footers\u0027] \u003d update_footers"},{"line_number":1629,"context_line":""}],"source_content_type":"text/x-python","patch_set":82,"id":"28c869da_5712b9e2","line":1626,"range":{"start_line":1626,"start_character":21,"end_line":1626,"end_character":45},"in_reply_to":"a3e48631_1e645d28","updated":"2026-08-25 23:44:29.000000000","message":"Done","commit_id":"01988bafd63c5584de964956f2701ec717c3199b"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"7d0706a66f21456700543dadce7b82f9fea24b3f","unresolved":true,"context_lines":[{"line_number":1611,"context_line":"        \"\"\""},{"line_number":1612,"context_line":"        original_callback \u003d self.environ.get(\u0027swift.callback.update_footers\u0027)"},{"line_number":1613,"context_line":""},{"line_number":1614,"context_line":"        def update_footers(footers):"},{"line_number":1615,"context_line":"            \"\"\"Persist checksum sysmeta after the body validates.\"\"\""},{"line_number":1616,"context_line":"            if original_callback:"},{"line_number":1617,"context_line":"                original_callback(footers)"}],"source_content_type":"text/x-python","patch_set":88,"id":"e54f308d_9667d481","line":1614,"updated":"2026-08-31 16:00:26.000000000","message":"We are leaking the checksum here when encryption is used - the following meta is stored unencrypted:\n\n```\n  X-Object-Sysmeta-S3Api-Checksum-Algorithm: CRC32\n  X-Object-Sysmeta-S3Api-Checksum-Type: FULL_OBJECT\n  X-Object-Sysmeta-S3Api-Checksum-Value: NjowIA\u003d\u003d\n```\n\nNow there is some opposing info in https://github.com/openstack/swift/blob/master/doc/source/overview_encryption.rst?plain\u003d1#L29 - on the one hand we say etags are encrypted, on the other we do say sysmeta is not.\n\nI think we should encrypt the s3api checksum value as well. \n\nHere is one idea how to fix this: 1003079: crypto: Encrypt sysmeta that is a digest of the object body | https://review.opendev.org/c/openstack/swift/+/1003079\n\nWith this applied on top, metadata looks now like this:\n\n```\n  X-Object-Sysmeta-Crypto-Meta-S3Api-Checksum-Value: 5XFc2lxVaA8\u003d; swift_meta\u003d%7B%22cipher%22%3A+%22AES_CTR_256%22%2C+%22iv%22%3A+%22cUvZtw9ek59qsC7iOL%2Bq3Q%3D%3D%22%7D\n  X-Object-Sysmeta-S3Api-Checksum-Algorithm: CRC32\n  X-Object-Sysmeta-S3Api-Checksum-Type: FULL_OBJECT\n```\n\nWe might need to think if we want to encrypt the used algorith in the same way.","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":1611,"context_line":"        \"\"\""},{"line_number":1612,"context_line":"        original_callback \u003d self.environ.get(\u0027swift.callback.update_footers\u0027)"},{"line_number":1613,"context_line":""},{"line_number":1614,"context_line":"        def update_footers(footers):"},{"line_number":1615,"context_line":"            \"\"\"Persist checksum sysmeta after the body validates.\"\"\""},{"line_number":1616,"context_line":"            if original_callback:"},{"line_number":1617,"context_line":"                original_callback(footers)"}],"source_content_type":"text/x-python","patch_set":88,"id":"c8b66c42_d77468be","line":1614,"in_reply_to":"e54f308d_9667d481","updated":"2026-09-11 10:33:53.000000000","message":"Done - moved to sensitive sysmeta namespace","commit_id":"29817c61f412cf5e2a5f32c4e572200bf6c9a432"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3d7ddac228ad15821d599a8e724605c6f5c81ef4","unresolved":true,"context_lines":[{"line_number":1584,"context_line":"        \"\"\""},{"line_number":1585,"context_line":"        # Only add a footer callback when persistence is on and this request"},{"line_number":1586,"context_line":"        # has a checksum to validate."},{"line_number":1587,"context_line":"        if self.conf.allow_store_checksums and \\"},{"line_number":1588,"context_line":"                self.checksumming_input is not None:"},{"line_number":1589,"context_line":"            self._install_checksum_footers_callback(self.checksumming_input)"},{"line_number":1590,"context_line":""}],"source_content_type":"text/x-python","patch_set":109,"id":"0382c2e0_4d7c5139","line":1587,"range":{"start_line":1587,"start_character":8,"end_line":1587,"end_character":42},"updated":"2026-11-03 14:32:11.000000000","message":"-1 I think we should try to keep business logic outside of S3Request; let the ObjectController decide how requests should be handled and let S3Request just behave as it is instructed.\n\nAs written here, part of the logic (\"X-Amz-Copy-Source\u0027 not in req.headers\") is in ObjectController and part is here.\n\nSee sq? enforce allow_store_checksums in controller  https://review.opendev.org/c/openstack/swift/+/1013896 for change\n\nA similar change may be needed later in the chain.","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"swift/common/middleware/s3api/s3response.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":133,"context_line":"        checksum response headers"},{"line_number":134,"context_line":"        \"\"\""},{"line_number":135,"context_line":"        if self.request is None:"},{"line_number":136,"context_line":"            return False"},{"line_number":137,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027:"},{"line_number":138,"context_line":"            return True"},{"line_number":139,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":25,"id":"358e71db_2e2993df","line":136,"updated":"2026-06-30 23:51:02.000000000","message":"when is this branch true 🤯","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":true,"context_lines":[{"line_number":133,"context_line":"        checksum response headers"},{"line_number":134,"context_line":"        \"\"\""},{"line_number":135,"context_line":"        if self.request is None:"},{"line_number":136,"context_line":"            return False"},{"line_number":137,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027:"},{"line_number":138,"context_line":"            return True"},{"line_number":139,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":25,"id":"8adedea1_9025db59","line":136,"in_reply_to":"358e71db_2e2993df","updated":"2026-07-01 17:11:33.000000000","message":"Probably never 😅","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":133,"context_line":"        checksum response headers"},{"line_number":134,"context_line":"        \"\"\""},{"line_number":135,"context_line":"        if self.request is None:"},{"line_number":136,"context_line":"            return False"},{"line_number":137,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027:"},{"line_number":138,"context_line":"            return True"},{"line_number":139,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":25,"id":"8a9dd51d_c3d85b35","line":136,"in_reply_to":"8adedea1_9025db59","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":216,"context_line":"        if (checksum_header and checksum_value and"},{"line_number":217,"context_line":"                self._req_needs_checksum_response_headers()):"},{"line_number":218,"context_line":"            headers[checksum_header] \u003d checksum_value"},{"line_number":219,"context_line":"            if checksum_type:"},{"line_number":220,"context_line":"                headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"        self.headers \u003d headers"}],"source_content_type":"text/x-python","patch_set":25,"id":"e6d455ad_febb7362","line":219,"updated":"2026-06-30 23:51:02.000000000","message":"yeah I don\u0027t like this branch either - i wonder what your agent would come up with if you plug this acceptance condition in:\n\n```\n## 3. Missing `checksum-type` fallback has no producer state\n\nFile/line: `swift/common/middleware/s3api/s3response.py:219`\n\nConcrete failure path:\n\n`S3Response` emits the stored checksum algorithm/value when\n`checksum-header` and `checksum-value` exist, but only adds\n`x-amz-checksum-type` under `if checksum_type:`. The patch\u0027s writer,\n`S3Request._checksum_sysmeta_headers()`, always writes `checksum-header`,\n`checksum-value`, and `checksum-type` together. The worker found no migration,\ncompatibility, disk, or proxy state that produces only header+value while\nomitting type.\n\nWhy it matters:\n\nThe current branch would silently return an S3 checksum header without\n`x-amz-checksum-type` for an unproven partial metadata shape. That is a new\nwire-format fallback without a named producer or test.\n\nAcceptance condition:\n\nRequire `checksum-type` in the response emission condition, or drop the whole\nchecksum response header set when any member of the persisted sysmeta triplet\nis missing. If the partial state is intentional, name the producer and add a\nfocused test for header+value without type.\n```","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":216,"context_line":"        if (checksum_header and checksum_value and"},{"line_number":217,"context_line":"                self._req_needs_checksum_response_headers()):"},{"line_number":218,"context_line":"            headers[checksum_header] \u003d checksum_value"},{"line_number":219,"context_line":"            if checksum_type:"},{"line_number":220,"context_line":"                headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"        self.headers \u003d headers"}],"source_content_type":"text/x-python","patch_set":25,"id":"273056d6_2e19119f","line":219,"in_reply_to":"d6916808_8d166605","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":true,"context_lines":[{"line_number":216,"context_line":"        if (checksum_header and checksum_value and"},{"line_number":217,"context_line":"                self._req_needs_checksum_response_headers()):"},{"line_number":218,"context_line":"            headers[checksum_header] \u003d checksum_value"},{"line_number":219,"context_line":"            if checksum_type:"},{"line_number":220,"context_line":"                headers[\u0027x-amz-checksum-type\u0027] \u003d checksum_type"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"        self.headers \u003d headers"}],"source_content_type":"text/x-python","patch_set":25,"id":"d6916808_8d166605","line":219,"in_reply_to":"e6d455ad_febb7362","updated":"2026-07-01 17:11:33.000000000","message":"The reason for the `if checksum_type` is because there is a case where a object should not have `x-amz-checksum-type` in its response, and that case is in MPU segments.\n\nTake for instance the response from AWS\n```\n$ aws s3api list-parts --bucket foo --key bar --upload-id abc\n{\n    \"Parts\": [\n        {\n            \"PartNumber\": 1,\n            \"LastModified\": \"2026-07-01T15:53:25+00:00\",\n            \"ETag\": \"\\\"88da5ba4952665e7a2bf1cf6c4c17602\\\"\",\n            \"Size\": 5092,\n            \"ChecksumCRC32\": \"0iUFow\u003d\u003d\"\n        },\n        {\n            \"PartNumber\": 2,\n            \"LastModified\": \"2026-07-01T15:53:35+00:00\",\n            \"ETag\": \"\\\"88da5ba4952665e7a2bf1cf6c4c17602\\\"\",\n            \"Size\": 5092,\n            \"ChecksumCRC32\": \"0iUFow\u003d\u003d\"\n        }\n    ],\n    \"ChecksumAlgorithm\": \"CRC32\",\n    \"StorageClass\": \"STANDARD\",\n    \"ChecksumType\": \"COMPOSITE\"\n}\n```\n\nFor MPU segments, they don\u0027t store the type since the type belongs to the MPU itself and children follow it.\nThough, since this patch does not include a feature, we should move it to the MPU patch in 993193: s3api: User Checksum Persistence on MPUs | https://review.opendev.org/c/openstack/swift/+/993193","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"75ff0edf1cefc51fc94c03062eeb434f23f5036c","unresolved":false,"context_lines":[{"line_number":251,"context_line":""},{"line_number":252,"context_line":"    def append_copy_resp_body(self, controller_name, source_resp):"},{"line_number":253,"context_line":"        \"\"\""},{"line_number":254,"context_line":"        Replace the normal PUT response body with S3 copy-result XML."},{"line_number":255,"context_line":"        \"\"\""},{"line_number":256,"context_line":"        last_modified \u003d S3Timestamp("},{"line_number":257,"context_line":"            swob.parse_date_header(self.headers[\u0027Last-Modified\u0027])"}],"source_content_type":"text/x-python","patch_set":36,"id":"43b73534_b6c45512","line":254,"updated":"2026-11-02 18:04:42.000000000","message":"this refactoring `s/last_modified/source_resp/` seems like a better abstraction to me","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"75ff0edf1cefc51fc94c03062eeb434f23f5036c","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        elem \u003d Element(\u0027Copy%sResult\u0027 % controller_name)"},{"line_number":260,"context_line":"        SubElement(elem, \u0027LastModified\u0027).text \u003d last_modified"},{"line_number":261,"context_line":"        SubElement(elem, \u0027ETag\u0027).text \u003d \u0027\"%s\"\u0027 % self.etag"},{"line_number":262,"context_line":"        if controller_name \u003d\u003d \u0027Object\u0027:"},{"line_number":263,"context_line":"            checksum_header \u003d source_resp.sysmeta_headers.get("},{"line_number":264,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":265,"context_line":"            checksum_value \u003d source_resp.sysmeta_headers.get("}],"source_content_type":"text/x-python","patch_set":36,"id":"e6d53714_612d83ec","line":262,"updated":"2026-11-02 18:04:42.000000000","message":"what else can we copy besides an Object.","commit_id":"199dd9f5d03dbdbea27c712d055eedb709ef83d0"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":true,"context_lines":[{"line_number":261,"context_line":"        SubElement(elem, \u0027ETag\u0027).text \u003d \u0027\"%s\"\u0027 % self.etag"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":"        if result_elem_name \u003d\u003d \u0027CopyObjectResult\u0027:"},{"line_number":264,"context_line":"            checksum_header \u003d source_resp.sysmeta_headers.get("},{"line_number":265,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":266,"context_line":"            checksum_value \u003d source_resp.sysmeta_headers.get("},{"line_number":267,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"}],"source_content_type":"text/x-python","patch_set":44,"id":"72d20016_08bd15fa","line":264,"updated":"2026-07-22 01:29:15.000000000","message":"this ``source_resp`` is the earlier HEAD response before the server side copy actually happens, so a concurrent source overwrite can therefore make the XML report the old checksum while the destination contains the new object.\n\nif an unversioned source changes between those requests(HEAD and the actual COPY), Swift returns checksum A while the destination contains data and checksum B. so copy middleware will do something like this:\n      - Preliminary HEAD: CRC32/OLD\n      - (object overwritten with SHA256/NEW)\n      - Actual copy GET: SHA256/NEW\n      - Destination sysmeta: SHA256/NEW\n      - Returned XML: CRC32/OLD\n\nThe final copy response already contains metadata from the actual GET. ``append_copy_resp_body`` should use checksum fields from ``self.sysmeta_headers`` which is the final response, not ``source_resp``. and also please add a race test for this scenario.","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"dcdffadc6ca94a0293e01d1a238d2025cb8c8078","unresolved":true,"context_lines":[{"line_number":261,"context_line":"        SubElement(elem, \u0027ETag\u0027).text \u003d \u0027\"%s\"\u0027 % self.etag"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":"        if result_elem_name \u003d\u003d \u0027CopyObjectResult\u0027:"},{"line_number":264,"context_line":"            checksum_header \u003d source_resp.sysmeta_headers.get("},{"line_number":265,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":266,"context_line":"            checksum_value \u003d source_resp.sysmeta_headers.get("},{"line_number":267,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"}],"source_content_type":"text/x-python","patch_set":44,"id":"99104b39_5069543c","line":264,"in_reply_to":"72d20016_08bd15fa","updated":"2026-07-22 15:41:10.000000000","message":"Thanks for catching this! Will fix!","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[{"line_number":261,"context_line":"        SubElement(elem, \u0027ETag\u0027).text \u003d \u0027\"%s\"\u0027 % self.etag"},{"line_number":262,"context_line":""},{"line_number":263,"context_line":"        if result_elem_name \u003d\u003d \u0027CopyObjectResult\u0027:"},{"line_number":264,"context_line":"            checksum_header \u003d source_resp.sysmeta_headers.get("},{"line_number":265,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":266,"context_line":"            checksum_value \u003d source_resp.sysmeta_headers.get("},{"line_number":267,"context_line":"                sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"}],"source_content_type":"text/x-python","patch_set":44,"id":"82906726_6cbcc40e","line":264,"in_reply_to":"99104b39_5069543c","updated":"2026-07-22 17:00:18.000000000","message":"Done","commit_id":"a8773ec5f0453328a6b1afa9b1d0bd1a0872ba52"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":208,"context_line":"            # because we don\u0027t actually know how many parts there are.)"},{"line_number":209,"context_line":"            headers[\u0027etag\u0027] +\u003d \u0027-N\u0027"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"        checksum_header \u003d s3_sysmeta_headers.get("},{"line_number":212,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":213,"context_line":"        checksum_value \u003d s3_sysmeta_headers.get("},{"line_number":214,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"},{"line_number":215,"context_line":"        checksum_type \u003d s3_sysmeta_headers.get("},{"line_number":216,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027))"},{"line_number":217,"context_line":"        if (all([checksum_header, checksum_value, checksum_type]) and"},{"line_number":218,"context_line":"                self._req_needs_checksum_response_headers()):"},{"line_number":219,"context_line":"            headers[checksum_header] \u003d checksum_value"}],"source_content_type":"text/x-python","patch_set":59,"id":"e076a974_12f7e7d2","line":216,"range":{"start_line":211,"start_character":8,"end_line":216,"end_character":54},"updated":"2026-08-06 15:45:39.000000000","message":"this feels like it could be in a helper function shared with S3Request","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":208,"context_line":"            # because we don\u0027t actually know how many parts there are.)"},{"line_number":209,"context_line":"            headers[\u0027etag\u0027] +\u003d \u0027-N\u0027"},{"line_number":210,"context_line":""},{"line_number":211,"context_line":"        checksum_header \u003d s3_sysmeta_headers.get("},{"line_number":212,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-header\u0027))"},{"line_number":213,"context_line":"        checksum_value \u003d s3_sysmeta_headers.get("},{"line_number":214,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-value\u0027))"},{"line_number":215,"context_line":"        checksum_type \u003d s3_sysmeta_headers.get("},{"line_number":216,"context_line":"            sysmeta_header(\u0027object\u0027, \u0027checksum-type\u0027))"},{"line_number":217,"context_line":"        if (all([checksum_header, checksum_value, checksum_type]) and"},{"line_number":218,"context_line":"                self._req_needs_checksum_response_headers()):"},{"line_number":219,"context_line":"            headers[checksum_header] \u003d checksum_value"}],"source_content_type":"text/x-python","patch_set":59,"id":"1a590f6e_a3b5d5c7","line":216,"range":{"start_line":211,"start_character":8,"end_line":216,"end_character":54},"in_reply_to":"e076a974_12f7e7d2","updated":"2026-08-06 22:19:30.000000000","message":"I agree, that would make this simpler","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":134,"context_line":"        Return whether this response should expose checksum sysmeta as"},{"line_number":135,"context_line":"        x-amz-checksum-* response headers."},{"line_number":136,"context_line":"        \"\"\""},{"line_number":137,"context_line":"        # Swift does not echo sysmeta in PUT requests, so the S3Request object"},{"line_number":138,"context_line":"        # should inject them manually since the S3Response object does not"},{"line_number":139,"context_line":"        # sysmeta to inject into the response"},{"line_number":140,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027 or self.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":141,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":76,"id":"3adad0fe_df0a35fd","line":138,"range":{"start_line":137,"start_character":10,"end_line":138,"end_character":38},"updated":"2026-08-21 16:03:49.000000000","message":"this method seems to suggest the opposite: for a PUT request the result is False and checksum headers are NOT added to the response","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"9969dab2b7176bb1ed63b9314448ae0805cef819","unresolved":false,"context_lines":[{"line_number":134,"context_line":"        Return whether this response should expose checksum sysmeta as"},{"line_number":135,"context_line":"        x-amz-checksum-* response headers."},{"line_number":136,"context_line":"        \"\"\""},{"line_number":137,"context_line":"        # Swift does not echo sysmeta in PUT requests, so the S3Request object"},{"line_number":138,"context_line":"        # should inject them manually since the S3Response object does not"},{"line_number":139,"context_line":"        # sysmeta to inject into the response"},{"line_number":140,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027 or self.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":141,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":76,"id":"ef0eb89a_b8b9d90a","line":138,"range":{"start_line":137,"start_character":10,"end_line":138,"end_character":38},"in_reply_to":"3adad0fe_df0a35fd","updated":"2026-08-21 20:12:11.000000000","message":"Yea, this wording could be better","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":135,"context_line":"        x-amz-checksum-* response headers."},{"line_number":136,"context_line":"        \"\"\""},{"line_number":137,"context_line":"        # Swift does not echo sysmeta in PUT requests, so the S3Request object"},{"line_number":138,"context_line":"        # should inject them manually since the S3Response object does not"},{"line_number":139,"context_line":"        # sysmeta to inject into the response"},{"line_number":140,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027 or self.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":141,"context_line":"            return False"},{"line_number":142,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":76,"id":"d12fbfd8_3c47a677","line":139,"range":{"start_line":138,"start_character":39,"end_line":139,"end_character":45},"updated":"2026-08-21 16:03:49.000000000","message":"this part isn\u0027t grammatically correct, and I\u0027m not sure what it would be saying that corresponds to the method","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":135,"context_line":"        x-amz-checksum-* response headers."},{"line_number":136,"context_line":"        \"\"\""},{"line_number":137,"context_line":"        # Swift does not echo sysmeta in PUT requests, so the S3Request object"},{"line_number":138,"context_line":"        # should inject them manually since the S3Response object does not"},{"line_number":139,"context_line":"        # sysmeta to inject into the response"},{"line_number":140,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027 or self.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":141,"context_line":"            return False"},{"line_number":142,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"}],"source_content_type":"text/x-python","patch_set":76,"id":"1ff78709_bddc3264","line":139,"range":{"start_line":138,"start_character":39,"end_line":139,"end_character":45},"in_reply_to":"d12fbfd8_3c47a677","updated":"2026-08-21 20:10:41.000000000","message":"Acknowledged","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":137,"context_line":"        # Swift does not echo sysmeta in PUT requests, so the S3Request object"},{"line_number":138,"context_line":"        # should inject them manually since the S3Response object does not"},{"line_number":139,"context_line":"        # sysmeta to inject into the response"},{"line_number":140,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027 or self.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":141,"context_line":"            return False"},{"line_number":142,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":143,"context_line":"            checksum_mode \u003d normalize_checksum_mode("}],"source_content_type":"text/x-python","patch_set":76,"id":"d733e2f1_8f15869f","line":140,"range":{"start_line":140,"start_character":11,"end_line":140,"end_character":23},"updated":"2026-08-21 16:03:49.000000000","message":"IIUC swob.Response.request may be None; probably worth having an early return False is that is the case.","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":137,"context_line":"        # Swift does not echo sysmeta in PUT requests, so the S3Request object"},{"line_number":138,"context_line":"        # should inject them manually since the S3Response object does not"},{"line_number":139,"context_line":"        # sysmeta to inject into the response"},{"line_number":140,"context_line":"        if self.request.method \u003d\u003d \u0027PUT\u0027 or self.request.method \u003d\u003d \u0027POST\u0027:"},{"line_number":141,"context_line":"            return False"},{"line_number":142,"context_line":"        if self.request.method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":143,"context_line":"            checksum_mode \u003d normalize_checksum_mode("}],"source_content_type":"text/x-python","patch_set":76,"id":"0d1d46d5_0563b8f6","line":140,"range":{"start_line":140,"start_character":11,"end_line":140,"end_character":23},"in_reply_to":"d733e2f1_8f15869f","updated":"2026-08-21 20:10:41.000000000","message":"I got a comment from @clay.gerrard@gmail.com some time ago stating that \"when is this None?\"\n\nLooking at some call sites that try this I found one\nhttps://github.com/openstack/swift/blob/d57c078ef2744d0012729bbcb3aaca2c4e5a481d/swift/common/middleware/s3api/controllers/versioning.py#L86\nIn versioning. I\u0027ll add the guard then.","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":146,"context_line":"                return False"},{"line_number":147,"context_line":"            if \u0027range\u0027 in self.request.headers:"},{"line_number":148,"context_line":"                return False"},{"line_number":149,"context_line":"            if \u0027part-number\u0027 in self.request.params:"},{"line_number":150,"context_line":"                return False"},{"line_number":151,"context_line":"            return self.status_int \u003d\u003d HTTP_OK"},{"line_number":152,"context_line":"        return False"}],"source_content_type":"text/x-python","patch_set":76,"id":"4de67a17_437475f6","line":149,"range":{"start_line":149,"start_character":15,"end_line":149,"end_character":28},"updated":"2026-08-21 16:03:49.000000000","message":"might be worth a comment: S3Response\u0027s self.request is the *swift* request (!) so part-number IS the correct spelling of the request param. (s3api uses partNumber)","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":146,"context_line":"                return False"},{"line_number":147,"context_line":"            if \u0027range\u0027 in self.request.headers:"},{"line_number":148,"context_line":"                return False"},{"line_number":149,"context_line":"            if \u0027part-number\u0027 in self.request.params:"},{"line_number":150,"context_line":"                return False"},{"line_number":151,"context_line":"            return self.status_int \u003d\u003d HTTP_OK"},{"line_number":152,"context_line":"        return False"}],"source_content_type":"text/x-python","patch_set":76,"id":"d01f4f77_2b245010","line":149,"range":{"start_line":149,"start_character":15,"end_line":149,"end_character":28},"in_reply_to":"4de67a17_437475f6","updated":"2026-08-21 20:10:41.000000000","message":"Yea I think so too, it also might be good","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":148,"context_line":"                return False"},{"line_number":149,"context_line":"            if \u0027part-number\u0027 in self.request.params:"},{"line_number":150,"context_line":"                return False"},{"line_number":151,"context_line":"            return self.status_int \u003d\u003d HTTP_OK"},{"line_number":152,"context_line":"        return False"},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"    def __init__(self, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":76,"id":"ba71308d_a31f849c","line":151,"range":{"start_line":151,"start_character":12,"end_line":151,"end_character":45},"updated":"2026-08-21 16:03:49.000000000","message":"everything apart from this condition is the about the request, not the response, so it feels like we need ``S3Request.needs_checksum_response_headers`` (the request\u0027s business)\nand then below write:\n\n```\nif self.status_int \u003d\u003d HTTP_OK and self.req.needs_checksum_response_headers():\n    # add checksum resp headers\n    ```","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"9969dab2b7176bb1ed63b9314448ae0805cef819","unresolved":false,"context_lines":[{"line_number":148,"context_line":"                return False"},{"line_number":149,"context_line":"            if \u0027part-number\u0027 in self.request.params:"},{"line_number":150,"context_line":"                return False"},{"line_number":151,"context_line":"            return self.status_int \u003d\u003d HTTP_OK"},{"line_number":152,"context_line":"        return False"},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"    def __init__(self, *args, **kwargs):"}],"source_content_type":"text/x-python","patch_set":76,"id":"5ff27801_69397fed","line":151,"range":{"start_line":151,"start_character":12,"end_line":151,"end_character":45},"in_reply_to":"ba71308d_a31f849c","updated":"2026-08-21 20:12:11.000000000","message":"This has been moved out to the object controller now","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":212,"context_line":"            # because we don\u0027t actually know how many parts there are.)"},{"line_number":213,"context_line":"            headers[\u0027etag\u0027] +\u003d \u0027-N\u0027"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"        checksum_headers \u003d checksum_sysmeta_to_response_headers("},{"line_number":216,"context_line":"            s3_sysmeta_headers)"},{"line_number":217,"context_line":"        if checksum_headers and self._req_needs_checksum_response_headers():"},{"line_number":218,"context_line":"            headers.update(checksum_headers)"}],"source_content_type":"text/x-python","patch_set":76,"id":"58591fc7_8f5fa1bd","line":215,"updated":"2026-08-21 16:03:49.000000000","message":"minor: move this inside the ``if`` clause and simplify the condition; we may not need the checksum_headers dict and the headers.update will be a no-op if it turns out to be empty (which is an uncommon case??)","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":212,"context_line":"            # because we don\u0027t actually know how many parts there are.)"},{"line_number":213,"context_line":"            headers[\u0027etag\u0027] +\u003d \u0027-N\u0027"},{"line_number":214,"context_line":""},{"line_number":215,"context_line":"        checksum_headers \u003d checksum_sysmeta_to_response_headers("},{"line_number":216,"context_line":"            s3_sysmeta_headers)"},{"line_number":217,"context_line":"        if checksum_headers and self._req_needs_checksum_response_headers():"},{"line_number":218,"context_line":"            headers.update(checksum_headers)"}],"source_content_type":"text/x-python","patch_set":76,"id":"aa715ab3_7028221c","line":215,"in_reply_to":"58591fc7_8f5fa1bd","updated":"2026-08-21 20:10:41.000000000","message":"Yes I\u0027d say this is a uncommon case","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":215,"context_line":"        checksum_headers \u003d checksum_sysmeta_to_response_headers("},{"line_number":216,"context_line":"            s3_sysmeta_headers)"},{"line_number":217,"context_line":"        if checksum_headers and self._req_needs_checksum_response_headers():"},{"line_number":218,"context_line":"            headers.update(checksum_headers)"},{"line_number":219,"context_line":""},{"line_number":220,"context_line":"        self.headers \u003d headers"},{"line_number":221,"context_line":""}],"source_content_type":"text/x-python","patch_set":76,"id":"1b6fdb54_a1b2011e","line":218,"updated":"2026-08-21 16:03:49.000000000","message":"it\u0027s unfortunate that we have two places where the checksum response headers are set (here and in the s3request), and both are conditional on the object controller required request behaviours.\n\nI think we could move them both to the object controller, see sq patch","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"9969dab2b7176bb1ed63b9314448ae0805cef819","unresolved":false,"context_lines":[{"line_number":215,"context_line":"        checksum_headers \u003d checksum_sysmeta_to_response_headers("},{"line_number":216,"context_line":"            s3_sysmeta_headers)"},{"line_number":217,"context_line":"        if checksum_headers and self._req_needs_checksum_response_headers():"},{"line_number":218,"context_line":"            headers.update(checksum_headers)"},{"line_number":219,"context_line":""},{"line_number":220,"context_line":"        self.headers \u003d headers"},{"line_number":221,"context_line":""}],"source_content_type":"text/x-python","patch_set":76,"id":"9071fe61_6364b59b","line":218,"in_reply_to":"1b6fdb54_a1b2011e","updated":"2026-08-21 20:12:11.000000000","message":"Squashed in","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"}],"swift/common/middleware/s3api/utils.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"0193c45bce1320a5f7108f88acf9f8e953c3094c","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \u0027x-amz-checksum-sha1\u0027: \u0027ChecksumSHA1\u0027,"},{"line_number":37,"context_line":"    \u0027x-amz-checksum-sha256\u0027: \u0027ChecksumSHA256\u0027,"},{"line_number":38,"context_line":"}"},{"line_number":39,"context_line":"def sysmeta_prefix(resource):"},{"line_number":40,"context_line":"    \"\"\""},{"line_number":41,"context_line":"    Returns the system metadata prefix for given resource type."},{"line_number":42,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":34,"id":"84c7b66d_d4de8210","line":39,"updated":"2026-07-06 21:03:38.000000000","message":"pep8: E302 expected 2 blank lines, found 0","commit_id":"0008d249866a14cdc23cb557c5dba15a95825daf"},{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"e69a95d39db76bb63c7ce0dbf1279728d6e384ad","unresolved":true,"context_lines":[{"line_number":304,"context_line":"    if all([checksum_header, checksum_value, checksum_type]):"},{"line_number":305,"context_line":"        return {checksum_header: checksum_value,"},{"line_number":306,"context_line":"                \u0027x-amz-checksum-type\u0027: checksum_type}"},{"line_number":307,"context_line":"    return None"},{"line_number":308,"context_line":""},{"line_number":309,"context_line":""},{"line_number":310,"context_line":"class S3Timestamp(utils.Timestamp):"}],"source_content_type":"text/x-python","patch_set":69,"id":"eae5791f_d031da25","line":307,"updated":"2026-08-11 12:20:34.000000000","message":"Suggestion: I believe it is a bit more pythonic to return an empty dict here than `None`","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"964ac133bf12e9cb028d7905935205d08cdb5625","unresolved":false,"context_lines":[{"line_number":304,"context_line":"    if all([checksum_header, checksum_value, checksum_type]):"},{"line_number":305,"context_line":"        return {checksum_header: checksum_value,"},{"line_number":306,"context_line":"                \u0027x-amz-checksum-type\u0027: checksum_type}"},{"line_number":307,"context_line":"    return None"},{"line_number":308,"context_line":""},{"line_number":309,"context_line":""},{"line_number":310,"context_line":"class S3Timestamp(utils.Timestamp):"}],"source_content_type":"text/x-python","patch_set":69,"id":"e954e13c_25a3b1ac","line":307,"in_reply_to":"cd3abd85_499165d7","updated":"2026-08-19 23:43:30.000000000","message":"Done","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"91de517bef747ac16ff22ccb3f21a62ec646b2f2","unresolved":true,"context_lines":[{"line_number":304,"context_line":"    if all([checksum_header, checksum_value, checksum_type]):"},{"line_number":305,"context_line":"        return {checksum_header: checksum_value,"},{"line_number":306,"context_line":"                \u0027x-amz-checksum-type\u0027: checksum_type}"},{"line_number":307,"context_line":"    return None"},{"line_number":308,"context_line":""},{"line_number":309,"context_line":""},{"line_number":310,"context_line":"class S3Timestamp(utils.Timestamp):"}],"source_content_type":"text/x-python","patch_set":69,"id":"f56d279e_7d36bbeb","line":307,"in_reply_to":"eae5791f_d031da25","updated":"2026-08-11 19:32:38.000000000","message":"I agree with this, both are falsy too!","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"a7b8244e51cc4ccf08f5c007e3dc2c34993f5ded","unresolved":true,"context_lines":[{"line_number":304,"context_line":"    if all([checksum_header, checksum_value, checksum_type]):"},{"line_number":305,"context_line":"        return {checksum_header: checksum_value,"},{"line_number":306,"context_line":"                \u0027x-amz-checksum-type\u0027: checksum_type}"},{"line_number":307,"context_line":"    return None"},{"line_number":308,"context_line":""},{"line_number":309,"context_line":""},{"line_number":310,"context_line":"class S3Timestamp(utils.Timestamp):"}],"source_content_type":"text/x-python","patch_set":69,"id":"cd3abd85_499165d7","line":307,"in_reply_to":"f56d279e_7d36bbeb","updated":"2026-08-11 19:33:30.000000000","message":"I updated this, and the new code lives in `checksum.py`","commit_id":"3839e321ad05aa4c419f7b0e9558e75482f9072e"}],"swift/common/middleware/versioned_writes/object_versioning.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"c55c01169ccef422262ebff3f06ec31303f18011","unresolved":false,"context_lines":[{"line_number":353,"context_line":"        close_if_possible(put_req.environ[\u0027wsgi.input\u0027])"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"        # check for footers that may have been written"},{"line_number":357,"context_line":"        put_footers \u003d HeaderKeyDict()"},{"line_number":358,"context_line":"        if incoming_footer_callback:"},{"line_number":359,"context_line":"            # NB: *Don\u0027t* use the callback currently installed in"}],"source_content_type":"text/x-python","patch_set":32,"id":"15b496ad_d914019b","line":356,"updated":"2026-07-06 17:15:10.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"a1c0e141d70061a05925747991205d39385afd54"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":383,"context_line":"            # Move the footer callback to the internal PUT that reads the"},{"line_number":384,"context_line":"            # client body. The original request is later reused to write the"},{"line_number":385,"context_line":"            # symlink to the actual object with versioning, and the"},{"line_number":386,"context_line":"            # body-derived footers should not be applied to that symlink PUT."},{"line_number":387,"context_line":"            put_req.environ[footer_key] \u003d req.environ.pop(footer_key)"},{"line_number":388,"context_line":"        req.body \u003d b\u0027\u0027"},{"line_number":389,"context_line":"        # move metadata over, including sysmeta"}],"source_content_type":"text/x-python","patch_set":59,"id":"04e7ac27_db3677c7","line":386,"updated":"2026-08-06 15:45:39.000000000","message":"+1 for the comment","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":383,"context_line":"            # Move the footer callback to the internal PUT that reads the"},{"line_number":384,"context_line":"            # client body. The original request is later reused to write the"},{"line_number":385,"context_line":"            # symlink to the actual object with versioning, and the"},{"line_number":386,"context_line":"            # body-derived footers should not be applied to that symlink PUT."},{"line_number":387,"context_line":"            put_req.environ[footer_key] \u003d req.environ.pop(footer_key)"},{"line_number":388,"context_line":"        req.body \u003d b\u0027\u0027"},{"line_number":389,"context_line":"        # move metadata over, including sysmeta"}],"source_content_type":"text/x-python","patch_set":59,"id":"f655a057_2119cd4e","line":386,"in_reply_to":"04e7ac27_db3677c7","updated":"2026-08-06 22:19:30.000000000","message":"Acknowledged","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":407,"context_line":"            # client body. The original request is later reused to write the"},{"line_number":408,"context_line":"            # symlink to the actual object with versioning, and the"},{"line_number":409,"context_line":"            # body-derived footers should not be applied to that symlink PUT."},{"line_number":410,"context_line":"            put_req.environ[footer_key] \u003d req.environ.pop(footer_key)"},{"line_number":411,"context_line":"        req.body \u003d b\u0027\u0027"},{"line_number":412,"context_line":"        # move metadata over, including sysmeta"},{"line_number":413,"context_line":""}],"source_content_type":"text/x-python","patch_set":76,"id":"facb1dbb_9a74559f","line":410,"updated":"2026-08-21 16:03:49.000000000","message":"this change (and the test) could be broken out into a pre-requisite patch because:\n\n(a) it would make this patch smaller\n(b) the change has potentially wider implications that s3 checksum so useful to have its own entry in git history","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"0f58328bf0127e8f8cef7b1f5b6c4f07e3087c25","unresolved":false,"context_lines":[{"line_number":407,"context_line":"            # client body. The original request is later reused to write the"},{"line_number":408,"context_line":"            # symlink to the actual object with versioning, and the"},{"line_number":409,"context_line":"            # body-derived footers should not be applied to that symlink PUT."},{"line_number":410,"context_line":"            put_req.environ[footer_key] \u003d req.environ.pop(footer_key)"},{"line_number":411,"context_line":"        req.body \u003d b\u0027\u0027"},{"line_number":412,"context_line":"        # move metadata over, including sysmeta"},{"line_number":413,"context_line":""}],"source_content_type":"text/x-python","patch_set":76,"id":"cdc57637_357cc081","line":410,"in_reply_to":"b095dd47_d38cf67c","updated":"2026-10-02 00:18:41.000000000","message":"Done","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":true,"context_lines":[{"line_number":407,"context_line":"            # client body. The original request is later reused to write the"},{"line_number":408,"context_line":"            # symlink to the actual object with versioning, and the"},{"line_number":409,"context_line":"            # body-derived footers should not be applied to that symlink PUT."},{"line_number":410,"context_line":"            put_req.environ[footer_key] \u003d req.environ.pop(footer_key)"},{"line_number":411,"context_line":"        req.body \u003d b\u0027\u0027"},{"line_number":412,"context_line":"        # move metadata over, including sysmeta"},{"line_number":413,"context_line":""}],"source_content_type":"text/x-python","patch_set":76,"id":"b095dd47_d38cf67c","line":410,"in_reply_to":"facb1dbb_9a74559f","updated":"2026-08-21 20:10:41.000000000","message":"I think yes it might be good to have a pre-req patch for this... however I\u0027ve seen cases where we just make the change to a middleware like https://review.opendev.org/c/openstack/swift/+/1001706/5/swift/common/middleware/copy.py\n\nBut I think this case is different in that the copy hook is OPT-IN while this is not, all future requests will do this kind of passing the footer into requests inside the null container. I could see it being cleaner to have this stand on its own\n\nDone, see 1001890: versioning: pass footer callbacks into hidden container | https://review.opendev.org/c/openstack/swift/+/1001890","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"}],"test/functional/__init__.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":456,"context_line":"            \"tempauth\","},{"line_number":457,"context_line":"            \"s3api tempauth\")"},{"line_number":458,"context_line":"        conf.set(\u0027filter:s3api\u0027, \u0027s3_acl\u0027, \u0027true\u0027)"},{"line_number":459,"context_line":"        conf.set(\u0027filter:s3api\u0027, \u0027allow_store_checksums\u0027, \u0027true\u0027)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"        conf.set(\u0027filter:versioned_writes\u0027, \u0027allow_object_versioning\u0027, \u0027true\u0027)"},{"line_number":462,"context_line":""}],"source_content_type":"text/x-python","patch_set":101,"id":"a630643c_453de823","line":459,"updated":"2026-10-07 04:11:56.000000000","message":"this enable zuul to run func tests with checksum persistence enabled.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f2c09540104b795db4cb7479966023ab389fa440","unresolved":true,"context_lines":[{"line_number":456,"context_line":"            \"tempauth\","},{"line_number":457,"context_line":"            \"s3api tempauth\")"},{"line_number":458,"context_line":"        conf.set(\u0027filter:s3api\u0027, \u0027s3_acl\u0027, \u0027true\u0027)"},{"line_number":459,"context_line":"        conf.set(\u0027filter:s3api\u0027, \u0027allow_store_checksums\u0027, \u0027true\u0027)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"        conf.set(\u0027filter:versioned_writes\u0027, \u0027allow_object_versioning\u0027, \u0027true\u0027)"},{"line_number":462,"context_line":""}],"source_content_type":"text/x-python","patch_set":109,"id":"f956051d_4a703041","line":459,"updated":"2026-11-02 18:25:57.000000000","message":"it\u0027s not clear if this is needed given that there are no new tests in ``test/functional``","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ec9de955af1553b0023705b19e69d6b5e57c1397","unresolved":true,"context_lines":[{"line_number":456,"context_line":"            \"tempauth\","},{"line_number":457,"context_line":"            \"s3api tempauth\")"},{"line_number":458,"context_line":"        conf.set(\u0027filter:s3api\u0027, \u0027s3_acl\u0027, \u0027true\u0027)"},{"line_number":459,"context_line":"        conf.set(\u0027filter:s3api\u0027, \u0027allow_store_checksums\u0027, \u0027true\u0027)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"        conf.set(\u0027filter:versioned_writes\u0027, \u0027allow_object_versioning\u0027, \u0027true\u0027)"},{"line_number":462,"context_line":""}],"source_content_type":"text/x-python","patch_set":109,"id":"c6092b1a_1e25b7c2","line":459,"in_reply_to":"f956051d_4a703041","updated":"2026-11-03 06:03:15.000000000","message":"there is an existing one in ``test/functional``, I expanded it to cover more algorithms: https://review.opendev.org/c/openstack/swift/+/1013631","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"test/functional/s3api/test_object.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":770,"context_line":"        exp_sha1 \u003d base64_str(sha1(content).digest())"},{"line_number":771,"context_line":"        req_headers \u003d {\u0027X-Amz-Meta-Foo\u0027: \u0027bar\u0027,"},{"line_number":772,"context_line":"                       \u0027X-Amz-Checksum-Sha1\u0027: exp_sha1,"},{"line_number":773,"context_line":"                       \u0027X-Amz-Checksum-Type\u0027: \u0027FULL_OBJECT\u0027}"},{"line_number":774,"context_line":""},{"line_number":775,"context_line":"        # PUT the source object with custom user metadata"},{"line_number":776,"context_line":"        status, headers, body \u003d \\"}],"source_content_type":"text/x-python","patch_set":96,"id":"bf64a92b_8f8eeafd","line":773,"updated":"2026-10-30 18:13:29.000000000","message":"why did this test change? is it because checksum persistence may not be enabled on the test cluster?","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ec9de955af1553b0023705b19e69d6b5e57c1397","unresolved":true,"context_lines":[{"line_number":770,"context_line":"        exp_sha1 \u003d base64_str(sha1(content).digest())"},{"line_number":771,"context_line":"        req_headers \u003d {\u0027X-Amz-Meta-Foo\u0027: \u0027bar\u0027,"},{"line_number":772,"context_line":"                       \u0027X-Amz-Checksum-Sha1\u0027: exp_sha1,"},{"line_number":773,"context_line":"                       \u0027X-Amz-Checksum-Type\u0027: \u0027FULL_OBJECT\u0027}"},{"line_number":774,"context_line":""},{"line_number":775,"context_line":"        # PUT the source object with custom user metadata"},{"line_number":776,"context_line":"        status, headers, body \u003d \\"}],"source_content_type":"text/x-python","patch_set":96,"id":"fcaa0514_7e7361d4","line":773,"in_reply_to":"a75becc6_df82f65e","updated":"2026-11-03 06:03:15.000000000","message":"``test/functional`` is for cluster functional testing and regression checks, and I still feel we don\u0027t need to repeat every test scenario which already get covered in probe and s3api tests. But I am adding the basic checksum tests into ``test/functional`` at here: https://review.opendev.org/c/openstack/swift/+/1013631/1/test/functional/s3api/test_object.py, and also a squash patch on top of MPU checksum completion patch.","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"126e00751588f9e7e95ba33d0d0e1f1ddd5a02af","unresolved":true,"context_lines":[{"line_number":770,"context_line":"        exp_sha1 \u003d base64_str(sha1(content).digest())"},{"line_number":771,"context_line":"        req_headers \u003d {\u0027X-Amz-Meta-Foo\u0027: \u0027bar\u0027,"},{"line_number":772,"context_line":"                       \u0027X-Amz-Checksum-Sha1\u0027: exp_sha1,"},{"line_number":773,"context_line":"                       \u0027X-Amz-Checksum-Type\u0027: \u0027FULL_OBJECT\u0027}"},{"line_number":774,"context_line":""},{"line_number":775,"context_line":"        # PUT the source object with custom user metadata"},{"line_number":776,"context_line":"        status, headers, body \u003d \\"}],"source_content_type":"text/x-python","patch_set":96,"id":"a75becc6_df82f65e","line":773,"in_reply_to":"bf64a92b_8f8eeafd","updated":"2026-11-02 04:45:26.000000000","message":"The main reason was to keep these tests focused on preserving custom user metadata and avoid duplicate checksum COPY coverage. The PS101 comments explain this:\nhttps://review.opendev.org/c/openstack/swift/+/991516/comment/32fde7a8_07cb4687/\nhttps://review.opendev.org/c/openstack/swift/+/991516/comment/b98fd839_a159c43d/\n\nDisabled checksum persistence was already handled in PS100: _assertChecksumHeaders() selected assertions according to allow_store_checksums in /info. PS102 then removed the checksum additions from these functional tests. It retained the existing S3 CopyObject probe and added test_swift_copy_object_as_regular_object for native Swift COPY.\n\nBoth probes first check the stored checksum algorithm, value, and type on the source through the internal client, then check that the destination has no checksum sysmeta. They skip when allow_store_checksums is not enabled, so the COPY check cannot pass just because the source had no stored checksum.\n\nPUT/GET/HEAD checksum response checks remain in test/s3api/test_object_checksums.py. The existing custom-metadata assertions remain here.","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":false,"context_lines":[{"line_number":770,"context_line":"        exp_sha1 \u003d base64_str(sha1(content).digest())"},{"line_number":771,"context_line":"        req_headers \u003d {\u0027X-Amz-Meta-Foo\u0027: \u0027bar\u0027,"},{"line_number":772,"context_line":"                       \u0027X-Amz-Checksum-Sha1\u0027: exp_sha1,"},{"line_number":773,"context_line":"                       \u0027X-Amz-Checksum-Type\u0027: \u0027FULL_OBJECT\u0027}"},{"line_number":774,"context_line":""},{"line_number":775,"context_line":"        # PUT the source object with custom user metadata"},{"line_number":776,"context_line":"        status, headers, body \u003d \\"}],"source_content_type":"text/x-python","patch_set":96,"id":"13ae9d52_b69146f2","line":773,"in_reply_to":"fcaa0514_7e7361d4","updated":"2026-11-03 12:47:48.000000000","message":"Done","commit_id":"04a9824ad264d15c688ccf435a36299d244f03cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":769,"context_line":"            self.conn.make_request(\u0027PUT\u0027, dst_bucket, dst_obj, headers)"},{"line_number":770,"context_line":"        self.assertEqual(status, 400)"},{"line_number":771,"context_line":""},{"line_number":772,"context_line":"    def test_put_object_copy_preserves_custom_metadata(self):"},{"line_number":773,"context_line":"        obj \u003d \u0027object\u0027"},{"line_number":774,"context_line":"        dst_obj \u003d \u0027object-copy\u0027"},{"line_number":775,"context_line":"        content \u003d b\u0027abcdefghij\u0027"}],"source_content_type":"text/x-python","patch_set":101,"id":"32fde7a8_07cb4687","line":772,"updated":"2026-10-07 04:11:56.000000000","message":"the added changes has nothing to do with ``preserves_custom_metadata``, and those changes are duplicated as ``TestCopySysmeta::test_s3_copy_object_as_regular_object`` in\ntest/probe/test_copy_sysmeta.py. let\u0027s remove those","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":819,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-sha1\u0027, headers)"},{"line_number":820,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":821,"context_line":""},{"line_number":822,"context_line":"    def test_put_object_swift_api_copy_preserves_custom_metadata(self):"},{"line_number":823,"context_line":"        obj \u003d \u0027object\u0027"},{"line_number":824,"context_line":"        dst_obj \u003d \u0027object-copy-native\u0027"},{"line_number":825,"context_line":"        content \u003d b\u0027abcdefghij\u0027"}],"source_content_type":"text/x-python","patch_set":101,"id":"b98fd839_a159c43d","line":822,"updated":"2026-10-07 04:11:56.000000000","message":"ditto. for changes in this test, let\u0027s add ``test_swift_copy_object_as_regular_object`` to  test/probe/test_copy_sysmeta.py, which makes the latter complete and also we can remove changes into this test as well.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"}],"test/probe/test_copy_sysmeta.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"16cec9a84556f1f83754b71c5530c500e58ea988","unresolved":true,"context_lines":[{"line_number":121,"context_line":"            algorithm,"},{"line_number":122,"context_line":"            headers.get(\u0027x-object-sysmeta-s3api-checksum-algorithm\u0027))"},{"line_number":123,"context_line":"        self.assertEqual("},{"line_number":124,"context_line":"            value, headers.get(\u0027x-object-sysmeta-s3api-checksum-value\u0027))"},{"line_number":125,"context_line":"        self.assertEqual("},{"line_number":126,"context_line":"            \u0027FULL_OBJECT\u0027,"},{"line_number":127,"context_line":"            headers.get(\u0027x-object-sysmeta-s3api-checksum-type\u0027))"}],"source_content_type":"text/x-python","patch_set":91,"id":"8514f191_edad2e8e","line":124,"range":{"start_line":124,"start_character":41,"end_line":124,"end_character":54},"updated":"2026-09-10 20:56:18.000000000","message":"Missing a `-sensitive`","commit_id":"1775ed81c45271ab25fcebbc79400d0504ff9448"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":121,"context_line":"            algorithm,"},{"line_number":122,"context_line":"            headers.get(\u0027x-object-sysmeta-s3api-checksum-algorithm\u0027))"},{"line_number":123,"context_line":"        self.assertEqual("},{"line_number":124,"context_line":"            value, headers.get(\u0027x-object-sysmeta-s3api-checksum-value\u0027))"},{"line_number":125,"context_line":"        self.assertEqual("},{"line_number":126,"context_line":"            \u0027FULL_OBJECT\u0027,"},{"line_number":127,"context_line":"            headers.get(\u0027x-object-sysmeta-s3api-checksum-type\u0027))"}],"source_content_type":"text/x-python","patch_set":91,"id":"558ca33d_0470312d","line":124,"range":{"start_line":124,"start_character":41,"end_line":124,"end_character":54},"in_reply_to":"8514f191_edad2e8e","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"1775ed81c45271ab25fcebbc79400d0504ff9448"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":237,"context_line":"        self._swift_copy(source, destination)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # Swift COPY must not retain the source checksum metadata."},{"line_number":240,"context_line":"        self._assert_has_no_checksum_sysmeta(self.container, destination)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"    def test_s3_copy_object_as_regular_object(self):"},{"line_number":243,"context_line":"        self._require_checksum_persistence()"}],"source_content_type":"text/x-python","patch_set":108,"id":"d47193d9_b92bf67a","line":240,"updated":"2026-10-30 18:13:29.000000000","message":"ok , I think this may be replacing the lost assertions in func tests","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":false,"context_lines":[{"line_number":237,"context_line":"        self._swift_copy(source, destination)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # Swift COPY must not retain the source checksum metadata."},{"line_number":240,"context_line":"        self._assert_has_no_checksum_sysmeta(self.container, destination)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"    def test_s3_copy_object_as_regular_object(self):"},{"line_number":243,"context_line":"        self._require_checksum_persistence()"}],"source_content_type":"text/x-python","patch_set":108,"id":"6f572370_ee034808","line":240,"in_reply_to":"d47193d9_b92bf67a","updated":"2026-11-03 12:47:48.000000000","message":"Done","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":240,"context_line":"        self._assert_has_no_checksum_sysmeta(self.container, destination)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"    def test_s3_copy_object_as_regular_object(self):"},{"line_number":243,"context_line":"        self._require_checksum_persistence()"},{"line_number":244,"context_line":"        source \u003d self._make_name(\u0027s3-source-\u0027).decode()"},{"line_number":245,"context_line":"        destination \u003d self._make_name(\u0027s3-copy-\u0027).decode()"},{"line_number":246,"context_line":"        source_sha1 \u003d self._make_s3_obj(source)"}],"source_content_type":"text/x-python","patch_set":108,"id":"643d31df_5ffbbba0","line":243,"updated":"2026-10-30 18:13:29.000000000","message":"+1 good to flag as skipped when there wouldn\u0027t be any checksum sysmeta","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":false,"context_lines":[{"line_number":240,"context_line":"        self._assert_has_no_checksum_sysmeta(self.container, destination)"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"    def test_s3_copy_object_as_regular_object(self):"},{"line_number":243,"context_line":"        self._require_checksum_persistence()"},{"line_number":244,"context_line":"        source \u003d self._make_name(\u0027s3-source-\u0027).decode()"},{"line_number":245,"context_line":"        destination \u003d self._make_name(\u0027s3-copy-\u0027).decode()"},{"line_number":246,"context_line":"        source_sha1 \u003d self._make_s3_obj(source)"}],"source_content_type":"text/x-python","patch_set":108,"id":"432c973b_b443928c","line":243,"in_reply_to":"643d31df_5ffbbba0","updated":"2026-11-03 12:47:48.000000000","message":"Acknowledged","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"}],"test/probe/test_sensitive_sysmeta.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":99,"context_line":"    def test_s3api_checksum_sysmeta_encryption(self):"},{"line_number":100,"context_line":"        if not self.cluster_info.get(\u0027s3api\u0027, {}).get("},{"line_number":101,"context_line":"                \u0027allow_store_checksums\u0027, False):"},{"line_number":102,"context_line":"            self.skipTest(\u0027This test requires allow_store_checksums\u003dtrue\u0027)"},{"line_number":103,"context_line":"        bucket \u003d self._make_name(\u0027bucket-\u0027).decode()"},{"line_number":104,"context_line":"        obj \u003d self._make_name(\u0027object-\u0027).decode()"},{"line_number":105,"context_line":"        body \u003d b\u0027object body\u0027"}],"source_content_type":"text/x-python","patch_set":108,"id":"41f272ca_6b41a4a6","line":102,"updated":"2026-10-30 18:13:29.000000000","message":"follow-on idea: on feature/mpu there is probe test code to support making a custom config internal client. That would allow this test to always run, if all the API calls were made using an internal client with allow_store_checksums enabled.","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"272f9eaded850ca5883b2935429dadfd89c3021f","unresolved":true,"context_lines":[{"line_number":99,"context_line":"    def test_s3api_checksum_sysmeta_encryption(self):"},{"line_number":100,"context_line":"        if not self.cluster_info.get(\u0027s3api\u0027, {}).get("},{"line_number":101,"context_line":"                \u0027allow_store_checksums\u0027, False):"},{"line_number":102,"context_line":"            self.skipTest(\u0027This test requires allow_store_checksums\u003dtrue\u0027)"},{"line_number":103,"context_line":"        bucket \u003d self._make_name(\u0027bucket-\u0027).decode()"},{"line_number":104,"context_line":"        obj \u003d self._make_name(\u0027object-\u0027).decode()"},{"line_number":105,"context_line":"        body \u003d b\u0027object body\u0027"}],"source_content_type":"text/x-python","patch_set":108,"id":"65a3505e_03f35ac5","line":102,"in_reply_to":"41f272ca_6b41a4a6","updated":"2026-11-02 05:14:43.000000000","message":"This patch sets ``allow_store_checksums \u003d true`` in the Zuul probe-test setup, so this probe will run during Gerrit Zuul CI pipeline (I verified them by looking into Zuul CI results). A custom client would be an optional follow-up that lets this probe runs on local test VSAIO with no need to set the config; on the other side, if dev sees a failure in the Zuul CI pipeline with this or other probe test and wants to reproduce it on local VSIAO, he/she should notice that the test was skipped if flag is configured the other way around in local.\n\n```\n\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 short test summary info \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\nSKIPPED [1] test/probe/test_sensitive_sysmeta.py:102: This test requires allow_store_checksums\u003dtrue\n```","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8b0b1341b9650dd91f82a01c8712fdb83d9dcd96","unresolved":false,"context_lines":[{"line_number":99,"context_line":"    def test_s3api_checksum_sysmeta_encryption(self):"},{"line_number":100,"context_line":"        if not self.cluster_info.get(\u0027s3api\u0027, {}).get("},{"line_number":101,"context_line":"                \u0027allow_store_checksums\u0027, False):"},{"line_number":102,"context_line":"            self.skipTest(\u0027This test requires allow_store_checksums\u003dtrue\u0027)"},{"line_number":103,"context_line":"        bucket \u003d self._make_name(\u0027bucket-\u0027).decode()"},{"line_number":104,"context_line":"        obj \u003d self._make_name(\u0027object-\u0027).decode()"},{"line_number":105,"context_line":"        body \u003d b\u0027object body\u0027"}],"source_content_type":"text/x-python","patch_set":108,"id":"fcb89cb1_642e8157","line":102,"in_reply_to":"65a3505e_03f35ac5","updated":"2026-11-03 12:47:48.000000000","message":"Acknowledged","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b758113294e709c4957e984e68f130945de24b04","unresolved":true,"context_lines":[{"line_number":99,"context_line":"    def test_s3api_checksum_sysmeta_encryption(self):"},{"line_number":100,"context_line":"        if not self.cluster_info.get(\u0027s3api\u0027, {}).get("},{"line_number":101,"context_line":"                \u0027allow_store_checksums\u0027, False):"},{"line_number":102,"context_line":"            self.skipTest(\u0027This test requires allow_store_checksums\u003dtrue\u0027)"},{"line_number":103,"context_line":"        bucket \u003d self._make_name(\u0027bucket-\u0027).decode()"},{"line_number":104,"context_line":"        obj \u003d self._make_name(\u0027object-\u0027).decode()"},{"line_number":105,"context_line":"        body \u003d b\u0027object body\u0027"}],"source_content_type":"text/x-python","patch_set":109,"id":"f926ddd1_c5976aed","line":102,"updated":"2026-11-02 18:43:38.000000000","message":"notes to self/not a blocker\n\nthis could alternatively be gated by a conf option in test.conf (same as I have argued for the s3 compat tests) i.e. if your vsaio does not enable checksum persistence, then edit your test.conf to indicate that.\n\nIDK what previous precedents we have about enabling/disabling probe tests on optional features: opt-in vs opt-out. Opt-out is more defensive: CI will always run all tests. (Automatic) Opt-in is more convenient in development.","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"test/s3api/__init__.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":180,"context_line":"    return info if isinstance(info, dict) else {}"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":""},{"line_number":183,"context_line":"def skip_if_checksum_persistence_disabled(func):"},{"line_number":184,"context_line":"    @functools.wraps(func)"},{"line_number":185,"context_line":"    def wrapper(*args, **kwargs):"},{"line_number":186,"context_line":"        s3api_info \u003d get_cluster_info().get(\u0027s3api\u0027)"}],"source_content_type":"text/x-python","patch_set":108,"id":"9c78a68d_a0939fae","line":183,"updated":"2026-10-30 18:13:29.000000000","message":"could these be used by the probe tests as well?","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0b157087ff79ea460607c8e6c644447fa545b327","unresolved":true,"context_lines":[{"line_number":164,"context_line":""},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"@functools.lru_cache()"},{"line_number":167,"context_line":"def get_cluster_info():"},{"line_number":168,"context_line":"    endpoint \u003d get_opt(\u0027endpoint\u0027)"},{"line_number":169,"context_line":"    if not endpoint:"},{"line_number":170,"context_line":"        return {}"}],"source_content_type":"text/x-python","patch_set":109,"id":"9b683c62_cd390968","line":167,"updated":"2026-11-02 13:12:43.000000000","message":"tl;dr re-use existing pattern, see https://review.opendev.org/c/openstack/swift/+/1013509 sq? use config to disable checksum persistence compat tests\n\nI don\u0027t think we can or should do this:\n\n1. Can\u0027t: the /info endpoint behaviour is configurable; operators can choose to not expose info, which IIUC makes the swift cluster be tested as if it were an AWS endpoint. See etc/proxy-server.conf-sample:12\n\n2. Shouldn\u0027t: this is a different pattern to ``skip_if_s3_acl_tests_disabled``; we need to make our lives simpler - *one* pattern for all exceptions.\n\n3. Shouldn\u0027t: as much as possible we should avoid tests skipping in CI. The intent is for an upgraded cluster to persist checksums, so that is what CI should assert. If an operator wants to test a cluster that does not have checksum persistence enable then the op needs to make their own exception. The skip decorator can provide for that but based on a config setting, just like ``skip_if_s3_acl_tests_disabled``. By default, a Swift cluster should be expected to persist checksums.\n\n4. Shouldn\u0027t: I\u0027m not convinced that allow_checksum_persistence is a property that the cluster should advertise in /info, again because it is not intended to be optional. If it IS optional then the compatibility docs should state that (at the moment this patch says checksum persistence is added to the core API compatibility). But I fear we are just making work and complexity that we do not need.\n\nThe problem we have is that we\u0027re using a *feature* flag to enable a safe *upgrade* path, but we don\u0027t really intend for this to be an optional feature. If we could have shipped a checkpoint release to establish the pre-requisite behaviours then we would not be gating the checksum persistence with a feature flag.\n\nI know it\u0027s not ideal, but I think we should just document that when you upgrade to this release, you must follow the upgrade process *including enabling the feature*. If you do not do that then your cluster will not pass compat tests, unless you run them with an exception flag.\n\n(N.B. As this patch stands, an operator MUST ensure at least one of ``expose_info \u003d true`` or ``allow_store_checksums \u003d true`` for compat tests to pass)","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"75ff0edf1cefc51fc94c03062eeb434f23f5036c","unresolved":true,"context_lines":[{"line_number":170,"context_line":"        return {}"},{"line_number":171,"context_line":"    try:"},{"line_number":172,"context_line":"        resp \u003d requests.get("},{"line_number":173,"context_line":"            urllib.parse.urljoin(endpoint, \u0027/info\u0027),"},{"line_number":174,"context_line":"            verify\u003dget_opt(\u0027ca_cert\u0027, True), timeout\u003d10)"},{"line_number":175,"context_line":"        resp.raise_for_status()"},{"line_number":176,"context_line":"        info \u003d resp.json()"}],"source_content_type":"text/x-python","patch_set":109,"id":"f743a7b0_78e7bed9","line":173,"updated":"2026-11-02 18:04:42.000000000","message":"we\u0027re not going to add a `/info` call to the s3api test suite - this will get removed before merge.\n\n1013509: sq? use config to disable checksum persistence compat tests | https://review.opendev.org/c/openstack/swift/+/1013509","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ec9de955af1553b0023705b19e69d6b5e57c1397","unresolved":true,"context_lines":[{"line_number":170,"context_line":"        return {}"},{"line_number":171,"context_line":"    try:"},{"line_number":172,"context_line":"        resp \u003d requests.get("},{"line_number":173,"context_line":"            urllib.parse.urljoin(endpoint, \u0027/info\u0027),"},{"line_number":174,"context_line":"            verify\u003dget_opt(\u0027ca_cert\u0027, True), timeout\u003d10)"},{"line_number":175,"context_line":"        resp.raise_for_status()"},{"line_number":176,"context_line":"        info \u003d resp.json()"}],"source_content_type":"text/x-python","patch_set":109,"id":"5983a976_d79b81dd","line":173,"in_reply_to":"f743a7b0_78e7bed9","updated":"2026-11-03 06:03:15.000000000","message":"yeah, pushed up an implementation to use existing pattern for ``skip_if_checksum_persistence_disabled``, along with other test improvements at https://review.opendev.org/c/openstack/swift/+/1013631","commit_id":"14dfce541460dffc17254ca09eff8563170c29cc"}],"test/s3api/test_input_errors.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":2504,"context_line":""},{"line_number":2505,"context_line":"    @skip_if_checksum_persistence_disabled"},{"line_number":2506,"context_line":"    def test_strm_unsgnd_pyld_trl_with_trailer_persistence(self):"},{"line_number":2507,"context_line":"        obj_name \u003d self.create_name(\u0027aws-chunked-trailer-persistence\u0027)"},{"line_number":2508,"context_line":"        expected_checksum \u003d _crc32(TEST_BODY)"},{"line_number":2509,"context_line":"        chunked_body \u003d b\u0027\u0027.join("},{"line_number":2510,"context_line":"            b\u0027%x\\r\\n%s\\r\\n\u0027 % (len(chunk), chunk)"}],"source_content_type":"text/x-python","patch_set":101,"id":"d988b2b5_6849998b","line":2507,"updated":"2026-10-07 04:11:56.000000000","message":"the setup of this test is exactly same as its neighbors, let\u0027s create a helper function for them.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"}],"test/s3api/test_object_checksums.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"0193c45bce1320a5f7108f88acf9f8e953c3094c","unresolved":false,"context_lines":[{"line_number":374,"context_line":"    EXPECTED \u003d \u0027y/Q5Jg\u003d\u003d\u0027"},{"line_number":375,"context_line":"    INVALID \u003d \u0027y/Q5Jh\u003d\u003d\u0027"},{"line_number":376,"context_line":"    BAD \u003d \u0027z/Q5Jg\u003d\u003d\u0027"},{"line_number":377,"context_line":"    CHECKSUM_FUNC \u003d staticmethod(crc32)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":""},{"line_number":380,"context_line":"class TestObjectChecksumCRC32C(ObjectChecksumMixin, BaseS3TestCaseWithBucket):"}],"source_content_type":"text/x-python","patch_set":34,"id":"285feadb_abc18d00","line":377,"updated":"2026-07-06 21:03:38.000000000","message":"pep8: F821 undefined name \u0027crc32\u0027","commit_id":"0008d249866a14cdc23cb557c5dba15a95825daf"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"0193c45bce1320a5f7108f88acf9f8e953c3094c","unresolved":false,"context_lines":[{"line_number":401,"context_line":"    EXPECTED \u003d \u0027rosUhgp5mIg\u003d\u0027"},{"line_number":402,"context_line":"    INVALID \u003d \u0027rosUhgp5mIh\u003d\u0027"},{"line_number":403,"context_line":"    BAD \u003d \u0027sosUhgp5mIg\u003d\u0027"},{"line_number":404,"context_line":"    CHECKSUM_FUNC \u003d staticmethod(crc64nvme)"},{"line_number":405,"context_line":""},{"line_number":406,"context_line":"    @classmethod"},{"line_number":407,"context_line":"    def setUpClass(cls):"}],"source_content_type":"text/x-python","patch_set":34,"id":"4fe7f7a3_b8e22479","line":404,"updated":"2026-07-06 21:03:38.000000000","message":"pep8: F821 undefined name \u0027crc64nvme\u0027","commit_id":"0008d249866a14cdc23cb557c5dba15a95825daf"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[{"line_number":61,"context_line":"        resp \u003d caught.exception.response"},{"line_number":62,"context_line":"        self.assertEqual(404, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def test_let_sdk_compute(self):"},{"line_number":65,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-sdk\u0027)"},{"line_number":66,"context_line":"        resp \u003d self.client.put_object("},{"line_number":67,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"40ac9f19_6a42ee0e","line":64,"updated":"2026-08-08 00:48:06.000000000","message":"those tests were added when checksum was only checked but not persisted, now we need to validate the response headers in PUT since we are going to persist the checksum, also test HEAD/GET after PUT.\n\nsee updated test case at https://review.opendev.org/c/openstack/swift/+/1000167","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4f630d71fb72d8951d3742c8d76ed1bb28f5922b","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        resp \u003d caught.exception.response"},{"line_number":62,"context_line":"        self.assertEqual(404, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def test_let_sdk_compute(self):"},{"line_number":65,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-sdk\u0027)"},{"line_number":66,"context_line":"        resp \u003d self.client.put_object("},{"line_number":67,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"3e4adcd9_14915572","line":64,"in_reply_to":"103f7334_a224fa3e","updated":"2026-08-10 19:15:14.000000000","message":"Done","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[{"line_number":61,"context_line":"        resp \u003d caught.exception.response"},{"line_number":62,"context_line":"        self.assertEqual(404, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    def test_let_sdk_compute(self):"},{"line_number":65,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-sdk\u0027)"},{"line_number":66,"context_line":"        resp \u003d self.client.put_object("},{"line_number":67,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"103f7334_a224fa3e","line":64,"in_reply_to":"40ac9f19_6a42ee0e","updated":"2026-08-10 15:43:21.000000000","message":"Seem right to me!","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        )"},{"line_number":72,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def test_good_checksum(self):"},{"line_number":75,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-with-algo-header\u0027)"},{"line_number":76,"context_line":"        resp \u003d self.client.put_object("},{"line_number":77,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"5c026170_7388f3ce","line":74,"updated":"2026-08-08 00:48:06.000000000","message":"this test can be combined with new added ``test_full_obj_put_sdk_checksum_algorithm_header``?","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"61fdd214c1b5fba0ef80de0cb410c22aba8b6f45","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        )"},{"line_number":72,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def test_good_checksum(self):"},{"line_number":75,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-with-algo-header\u0027)"},{"line_number":76,"context_line":"        resp \u003d self.client.put_object("},{"line_number":77,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"7d92bbee_171c4608","line":74,"in_reply_to":"566b0ffa_68015170","updated":"2026-08-10 23:35:35.000000000","message":"Oh yea, good point!","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        )"},{"line_number":72,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def test_good_checksum(self):"},{"line_number":75,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-with-algo-header\u0027)"},{"line_number":76,"context_line":"        resp \u003d self.client.put_object("},{"line_number":77,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"fc612776_31cd62db","line":74,"in_reply_to":"5c026170_7388f3ce","updated":"2026-08-10 15:43:21.000000000","message":"Yea I think we can combine these","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"964ac133bf12e9cb028d7905935205d08cdb5625","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        )"},{"line_number":72,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def test_good_checksum(self):"},{"line_number":75,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-with-algo-header\u0027)"},{"line_number":76,"context_line":"        resp \u003d self.client.put_object("},{"line_number":77,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"371daa74_6a54eace","line":74,"in_reply_to":"7d92bbee_171c4608","updated":"2026-08-19 23:43:30.000000000","message":"Done","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4f630d71fb72d8951d3742c8d76ed1bb28f5922b","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        )"},{"line_number":72,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    def test_good_checksum(self):"},{"line_number":75,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-with-algo-header\u0027)"},{"line_number":76,"context_line":"        resp \u003d self.client.put_object("},{"line_number":77,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"566b0ffa_68015170","line":74,"in_reply_to":"fc612776_31cd62db","updated":"2026-08-10 19:15:14.000000000","message":"I think we can remove ``test_full_obj_put_sdk_checksum_algorithm_header``, since ``test_good_checksum`` is expanded and is doing the same thing now?","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[{"line_number":82,"context_line":"        )"},{"line_number":83,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def test_good_checksum_no_algorithm_header(self):"},{"line_number":86,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-no-algo-header\u0027)"},{"line_number":87,"context_line":"        resp \u003d self.client.put_object("},{"line_number":88,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"a3eee038_0cef1e02","line":85,"updated":"2026-08-08 00:48:06.000000000","message":"same, those tests were added when checksum was only checked but not persisted, now we need to validate the response headers in PUT since we are going to persist the checksum, also test HEAD/GET after PUT.","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        )"},{"line_number":83,"context_line":"        self.assertEqual(200, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def test_good_checksum_no_algorithm_header(self):"},{"line_number":86,"context_line":"        obj_name \u003d self.create_name(self.ALGORITHM + \u0027-no-algo-header\u0027)"},{"line_number":87,"context_line":"        resp \u003d self.client.put_object("},{"line_number":88,"context_line":"            Bucket\u003dself.bucket_name,"}],"source_content_type":"text/x-python","patch_set":66,"id":"f4b3b2d9_54813747","line":85,"in_reply_to":"a3eee038_0cef1e02","updated":"2026-08-10 15:43:21.000000000","message":"Acknowledged","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[{"line_number":241,"context_line":"        self.assertEqual(200, complete_mpu_resp["},{"line_number":242,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"    def test_full_obj_put_full_object_checksum_headers(self):"},{"line_number":245,"context_line":"        resp \u003d self.client.put_object("},{"line_number":246,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":247,"context_line":"            Key\u003dself.create_name(\u0027full-obj-\u0027 + self.ALGORITHM.lower()),"}],"source_content_type":"text/x-python","patch_set":66,"id":"fbc25909_48d6d1c6","line":244,"updated":"2026-08-08 00:48:06.000000000","message":"I feel ``test_full_obj_put_full_object_checksum_headers`` and ``test_full_obj_get_full_object_checksum_headers`` and ``test_full_obj_head_full_object_checksum_headers`` can be combined as one. A single test (e.g. test_full_obj_checksum_headers) that PUTs once, then asserts PUT/HEAD/GET headers and parsed fields, would drop the duplicated PUTs and duplicated checks on HEAD/GET.","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4f630d71fb72d8951d3742c8d76ed1bb28f5922b","unresolved":false,"context_lines":[{"line_number":241,"context_line":"        self.assertEqual(200, complete_mpu_resp["},{"line_number":242,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"    def test_full_obj_put_full_object_checksum_headers(self):"},{"line_number":245,"context_line":"        resp \u003d self.client.put_object("},{"line_number":246,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":247,"context_line":"            Key\u003dself.create_name(\u0027full-obj-\u0027 + self.ALGORITHM.lower()),"}],"source_content_type":"text/x-python","patch_set":66,"id":"708de735_4fdbc62c","line":244,"in_reply_to":"3991fa83_d90f1677","updated":"2026-08-10 19:15:14.000000000","message":"Done","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[{"line_number":241,"context_line":"        self.assertEqual(200, complete_mpu_resp["},{"line_number":242,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":"    def test_full_obj_put_full_object_checksum_headers(self):"},{"line_number":245,"context_line":"        resp \u003d self.client.put_object("},{"line_number":246,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":247,"context_line":"            Key\u003dself.create_name(\u0027full-obj-\u0027 + self.ALGORITHM.lower()),"}],"source_content_type":"text/x-python","patch_set":66,"id":"3991fa83_d90f1677","line":244,"in_reply_to":"fbc25909_48d6d1c6","updated":"2026-08-10 15:43:21.000000000","message":"Yea I think we can, since all of them do a PUT anyways","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[{"line_number":315,"context_line":"        resp \u003d caught.exception.response"},{"line_number":316,"context_line":"        self.assertEqual(400, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"    def test_full_obj_put_sdk_checksum_algorithm_header(self):"},{"line_number":319,"context_line":"        resp \u003d self.client.put_object("},{"line_number":320,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":321,"context_line":"            Key\u003dself.create_name(\u0027full-obj-\u0027 + self.ALGORITHM.lower()),"}],"source_content_type":"text/x-python","patch_set":66,"id":"3ebb0b43_2bd79c33","line":318,"updated":"2026-08-08 00:48:06.000000000","message":"this test case can be combined with ``test_good_checksum``? also add validation of HEAD/GET after PUT (could be a command internal test function, like ``_test_HEAD_GET()``).","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[{"line_number":315,"context_line":"        resp \u003d caught.exception.response"},{"line_number":316,"context_line":"        self.assertEqual(400, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"    def test_full_obj_put_sdk_checksum_algorithm_header(self):"},{"line_number":319,"context_line":"        resp \u003d self.client.put_object("},{"line_number":320,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":321,"context_line":"            Key\u003dself.create_name(\u0027full-obj-\u0027 + self.ALGORITHM.lower()),"}],"source_content_type":"text/x-python","patch_set":66,"id":"74f949b3_7d9e39f8","line":318,"in_reply_to":"3ebb0b43_2bd79c33","updated":"2026-08-10 15:43:21.000000000","message":"Seems good to me!, I think maybe `_assert_checksum_persistence` could be better, but still server the same purpose.","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4f630d71fb72d8951d3742c8d76ed1bb28f5922b","unresolved":false,"context_lines":[{"line_number":315,"context_line":"        resp \u003d caught.exception.response"},{"line_number":316,"context_line":"        self.assertEqual(400, resp[\u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":317,"context_line":""},{"line_number":318,"context_line":"    def test_full_obj_put_sdk_checksum_algorithm_header(self):"},{"line_number":319,"context_line":"        resp \u003d self.client.put_object("},{"line_number":320,"context_line":"            Bucket\u003dself.bucket_name,"},{"line_number":321,"context_line":"            Key\u003dself.create_name(\u0027full-obj-\u0027 + self.ALGORITHM.lower()),"}],"source_content_type":"text/x-python","patch_set":66,"id":"bff37604_e9d2023d","line":318,"in_reply_to":"74f949b3_7d9e39f8","updated":"2026-08-10 19:15:14.000000000","message":"Done","commit_id":"160dc4df3597d63c10e26e0985fedd5d6e948872"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"f8ef4c556a9643cb13ed560a04b3f1c14541f067","unresolved":true,"context_lines":[{"line_number":59,"context_line":"        cls.use_tls \u003d cls.client._endpoint.host.startswith(\u0027https:\u0027)"},{"line_number":60,"context_line":"        algorithm \u003d cls.ALGORITHM.lower()"},{"line_number":61,"context_line":"        supported_algorithms \u003d getattr("},{"line_number":62,"context_line":"            botocore.httpchecksum, \u0027_SUPPORTED_CHECKSUM_ALGORITHMS\u0027, ())"},{"line_number":63,"context_line":"        crt_algorithms \u003d getattr("},{"line_number":64,"context_line":"            botocore.httpchecksum, \u0027_CRT_CHECKSUM_ALGORITHMS\u0027, ())"},{"line_number":65,"context_line":"        if (algorithm not in supported_algorithms and not ("}],"source_content_type":"text/x-python","patch_set":87,"id":"b1867208_10571c83","line":62,"updated":"2026-08-27 09:12:46.000000000","message":"So this will silently skip all five TestObjectChecksum* classes in CI if botocore renames/drops these botocore internals. CI stays green and 55 tests are skipped, and we would only notice this by chance.\n\nIf I see this right, we don\u0027t need guards for CRC32, SHA1, SHA256 - all part of the stdlib. So the only ones that need guards are CRC32C and CRC64NVME, and these two are guarded in their own test classes:\n\nhttps://review.opendev.org/c/openstack/swift/+/991516/87/test/s3api/test_object_checksums.py#549\nhttps://review.opendev.org/c/openstack/swift/+/991516/87/test/s3api/test_object_checksums.py#569","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":59,"context_line":"        cls.use_tls \u003d cls.client._endpoint.host.startswith(\u0027https:\u0027)"},{"line_number":60,"context_line":"        algorithm \u003d cls.ALGORITHM.lower()"},{"line_number":61,"context_line":"        supported_algorithms \u003d getattr("},{"line_number":62,"context_line":"            botocore.httpchecksum, \u0027_SUPPORTED_CHECKSUM_ALGORITHMS\u0027, ())"},{"line_number":63,"context_line":"        crt_algorithms \u003d getattr("},{"line_number":64,"context_line":"            botocore.httpchecksum, \u0027_CRT_CHECKSUM_ALGORITHMS\u0027, ())"},{"line_number":65,"context_line":"        if (algorithm not in supported_algorithms and not ("}],"source_content_type":"text/x-python","patch_set":87,"id":"5beec24c_a98e48bc","line":62,"in_reply_to":"b1867208_10571c83","updated":"2026-09-11 10:33:53.000000000","message":"...so I think we can drop all of this new generic setup code?","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"7de4f17fdacea5f10bef638239511adeecaf14fd","unresolved":true,"context_lines":[{"line_number":532,"context_line":"    EXPECTED \u003d \u0027y/Q5Jg\u003d\u003d\u0027"},{"line_number":533,"context_line":"    INVALID \u003d \u0027y/Q5Jh\u003d\u003d\u0027"},{"line_number":534,"context_line":"    BAD \u003d \u0027z/Q5Jg\u003d\u003d\u0027"},{"line_number":535,"context_line":"    CHECKSUM_FUNC \u003d staticmethod(crc32)"},{"line_number":536,"context_line":""},{"line_number":537,"context_line":""},{"line_number":538,"context_line":"class TestObjectChecksumCRC32C(ObjectChecksumMixin, BaseS3TestCaseWithBucket):"}],"source_content_type":"text/x-python","patch_set":87,"id":"a0b5a870_856dd8bc","line":535,"updated":"2026-08-27 10:38:52.000000000","message":"Note to myself and other reviewers: `CHECKSUM_FUNC` is not used in this patch, but in the follow ups.","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":532,"context_line":"    EXPECTED \u003d \u0027y/Q5Jg\u003d\u003d\u0027"},{"line_number":533,"context_line":"    INVALID \u003d \u0027y/Q5Jh\u003d\u003d\u0027"},{"line_number":534,"context_line":"    BAD \u003d \u0027z/Q5Jg\u003d\u003d\u0027"},{"line_number":535,"context_line":"    CHECKSUM_FUNC \u003d staticmethod(crc32)"},{"line_number":536,"context_line":""},{"line_number":537,"context_line":""},{"line_number":538,"context_line":"class TestObjectChecksumCRC32C(ObjectChecksumMixin, BaseS3TestCaseWithBucket):"}],"source_content_type":"text/x-python","patch_set":87,"id":"8b91ce00_38d0ad0b","line":535,"in_reply_to":"a0b5a870_856dd8bc","updated":"2026-09-11 10:33:53.000000000","message":"Done. move it to when it is used","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"}],"test/sample.conf":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":18,"context_line":"# Alternatively, skip those tests by setting this option to False"},{"line_number":19,"context_line":"s3_acl_tests_enabled \u003d True"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# Checksum storage tests require allow_store_checksums \u003d true in the proxy\u0027s"},{"line_number":22,"context_line":"# [filter:s3api] section. Probe and S3API checksum storage tests are skipped if"},{"line_number":23,"context_line":"# allow_store_checksums is false or omitted from the proxy configuration."},{"line_number":24,"context_line":"# S3API tests read this setting from /info. If the endpoint does not expose"}],"source_content_type":"text/plain","patch_set":108,"id":"cdf5da58_95114a62","line":21,"range":{"start_line":21,"start_character":19,"end_line":21,"end_character":62},"updated":"2026-10-30 18:13:29.000000000","message":"this says the opposite of what follows - \u0027true\u0027 is not required, the tests will skip if \u0027false\u0027.\n\nalternative:\n\n```\nS3API checksum persistence compatibility tests, and some probe tests, are skipped if a GET to the endpoint\u0027s /info path does not report that allow_store_checksums \u003d true. To have these tests run, specify allow_store_checksums \u003d true in the proxy-server.conf [filter:s3api] section. These tests always run if the endpoint does not support the /info path (e.g. an AWS S3 endpoint).\n```","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"31f9da6ac6bf1d7878df52765ece0aee038842cb","unresolved":true,"context_lines":[{"line_number":19,"context_line":"s3_acl_tests_enabled \u003d True"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# Checksum storage tests require allow_store_checksums \u003d true in the proxy\u0027s"},{"line_number":22,"context_line":"# [filter:s3api] section. Probe and S3API checksum storage tests are skipped if"},{"line_number":23,"context_line":"# allow_store_checksums is false or omitted from the proxy configuration."},{"line_number":24,"context_line":"# S3API tests read this setting from /info. If the endpoint does not expose"},{"line_number":25,"context_line":"# the S3API settings (e.g. an AWS S3 endpoint), these tests run."}],"source_content_type":"text/plain","patch_set":108,"id":"242256a0_7138391f","line":22,"range":{"start_line":22,"start_character":26,"end_line":22,"end_character":31},"updated":"2026-10-30 18:13:29.000000000","message":"see comment in probe test - we might be able to make the probe test always run with a custom internal client","commit_id":"29c0474c08edc13f968ea04d29962b0c29da4400"}],"test/unit/common/middleware/s3api/__init__.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":115,"context_line":"            \u0027check_bucket_owner\u0027: False,"},{"line_number":116,"context_line":"            \u0027force_swift_request_proxy_log\u0027: False,"},{"line_number":117,"context_line":"            \u0027allow_multipart_uploads\u0027: True,"},{"line_number":118,"context_line":"            \u0027allow_store_checksums\u0027: True,"},{"line_number":119,"context_line":"            \u0027min_segment_size\u0027: 5242880,"},{"line_number":120,"context_line":"            \u0027log_level\u0027: \u0027debug\u0027"},{"line_number":121,"context_line":"        }"}],"source_content_type":"text/x-python","patch_set":101,"id":"d00b80a2_1300df32","line":118,"updated":"2026-10-07 04:11:56.000000000","message":"this enable all s3api unit test to run with checksum persistence by default.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"}],"test/unit/common/middleware/s3api/test_multi_delete.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":true,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        status, headers, body \u003d self.call_s3api(req)"},{"line_number":181,"context_line":"        self.assertEqual(status.split()[0], \u0027200\u0027)"},{"line_number":182,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, req.environ)"},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"        delete_call \u003d self.swift.call_list[-1]"},{"line_number":185,"context_line":"        self.assertEqual(\u0027DELETE\u0027, delete_call.method)"}],"source_content_type":"text/x-python","patch_set":39,"id":"e66306b6_1d272099","line":182,"updated":"2026-07-22 01:29:15.000000000","message":"make sure those headers won\u0027t be in the response\n```\n        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)\n        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)\n```","commit_id":"66562ca79f57f52f34cc17487020652b4611f619"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[{"line_number":179,"context_line":""},{"line_number":180,"context_line":"        status, headers, body \u003d self.call_s3api(req)"},{"line_number":181,"context_line":"        self.assertEqual(status.split()[0], \u0027200\u0027)"},{"line_number":182,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, req.environ)"},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"        delete_call \u003d self.swift.call_list[-1]"},{"line_number":185,"context_line":"        self.assertEqual(\u0027DELETE\u0027, delete_call.method)"}],"source_content_type":"text/x-python","patch_set":39,"id":"8ca667cc_7cf50788","line":182,"in_reply_to":"e66306b6_1d272099","updated":"2026-07-22 17:00:18.000000000","message":"Acknowledged","commit_id":"66562ca79f57f52f34cc17487020652b4611f619"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1b9240f1edcf1e70caa4d562c1d3882c51b7e0d2","unresolved":true,"context_lines":[{"line_number":183,"context_line":""},{"line_number":184,"context_line":"        delete_call \u003d self.swift.call_list[-1]"},{"line_number":185,"context_line":"        self.assertEqual(\u0027DELETE\u0027, delete_call.method)"},{"line_number":186,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, delete_call.env)"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"    def test_object_multi_DELETE(self):"},{"line_number":189,"context_line":"        self.swift.register(\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/Key1\u0027,"}],"source_content_type":"text/x-python","patch_set":39,"id":"d8a30c2d_ab127c9e","line":186,"updated":"2026-07-22 01:29:15.000000000","message":"and those sysmeta won\u0027t be stored.\n```\n        for key in (\u0027X-Object-Sysmeta-S3Api-Checksum-Header\u0027,\n                    \u0027X-Object-Sysmeta-S3Api-Checksum-Value\u0027,\n                    \u0027X-Object-Sysmeta-S3Api-Checksum-Type\u0027):\n            self.assertNotIn(key, call.headers)\n            self.assertNotIn(key, call.footers)\n```","commit_id":"66562ca79f57f52f34cc17487020652b4611f619"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"625369149cdb57d0b2bc698ba3074a1a3a323a95","unresolved":false,"context_lines":[{"line_number":183,"context_line":""},{"line_number":184,"context_line":"        delete_call \u003d self.swift.call_list[-1]"},{"line_number":185,"context_line":"        self.assertEqual(\u0027DELETE\u0027, delete_call.method)"},{"line_number":186,"context_line":"        self.assertNotIn(\u0027swift.callback.update_footers\u0027, delete_call.env)"},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"    def test_object_multi_DELETE(self):"},{"line_number":189,"context_line":"        self.swift.register(\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/Key1\u0027,"}],"source_content_type":"text/x-python","patch_set":39,"id":"9637382e_45fc185b","line":186,"in_reply_to":"d8a30c2d_ab127c9e","updated":"2026-07-22 17:00:18.000000000","message":"Acknowledged","commit_id":"66562ca79f57f52f34cc17487020652b4611f619"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"7de4f17fdacea5f10bef638239511adeecaf14fd","unresolved":true,"context_lines":[{"line_number":190,"context_line":"                    \u0027X-Object-Sysmeta-S3Api-Checksum-Value\u0027,"},{"line_number":191,"context_line":"                    \u0027X-Object-Sysmeta-S3Api-Checksum-Type\u0027):"},{"line_number":192,"context_line":"            self.assertNotIn(key, delete_call.headers)"},{"line_number":193,"context_line":"            self.assertNotIn(key, delete_call.footers)"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    def test_object_multi_DELETE(self):"},{"line_number":196,"context_line":"        self.swift.register(\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/Key1\u0027,"}],"source_content_type":"text/x-python","patch_set":87,"id":"8fbb6bb0_e49ff114","line":193,"updated":"2026-08-27 10:38:52.000000000","message":"This assertNotIn testing the footers can never fail. FakeSwift validates the checksum while reading the body (https://review.opendev.org/c/openstack/swift/+/991516/87/test/unit/common/middleware/helpers.py#335), and raises if it does not match. That happens before the footers are updated (https://review.opendev.org/c/openstack/swift/+/991516/87/test/unit/common/middleware/helpers.py#347)","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":190,"context_line":"                    \u0027X-Object-Sysmeta-S3Api-Checksum-Value\u0027,"},{"line_number":191,"context_line":"                    \u0027X-Object-Sysmeta-S3Api-Checksum-Type\u0027):"},{"line_number":192,"context_line":"            self.assertNotIn(key, delete_call.headers)"},{"line_number":193,"context_line":"            self.assertNotIn(key, delete_call.footers)"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    def test_object_multi_DELETE(self):"},{"line_number":196,"context_line":"        self.swift.register(\u0027DELETE\u0027, \u0027/v1/AUTH_test/bucket/Key1\u0027,"}],"source_content_type":"text/x-python","patch_set":87,"id":"8600d568_26fae47a","line":193,"in_reply_to":"8fbb6bb0_e49ff114","updated":"2026-09-11 10:33:53.000000000","message":"this test seems to be asserting that a DELETE call does not pass on any checksum headers or footers?","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"}],"test/unit/common/middleware/s3api/test_obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fa53a0e6a29b2fdff32cda213fec6fdc0fbdc11f","unresolved":true,"context_lines":[{"line_number":1155,"context_line":""},{"line_number":1156,"context_line":"    def assert_no_checksum_sysmeta(self, headers):"},{"line_number":1157,"context_line":"        for name in (\u0027checksum-header\u0027, \u0027checksum-value\u0027, \u0027checksum-type\u0027):"},{"line_number":1158,"context_line":"            self.assertNotIn(sysmeta_header(\u0027object\u0027, name), headers)"},{"line_number":1159,"context_line":""},{"line_number":1160,"context_line":"    def assert_no_checksum_response_headers(self, headers):"},{"line_number":1161,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"}],"source_content_type":"text/x-python","patch_set":12,"id":"f97fba9f_b2cff286","line":1158,"updated":"2026-06-17 00:00:40.000000000","message":"I don\u0027t *generally* like assert helpers; they\u0027re not *BAD* for DRYing out test code but there\u0027s something really wonderful about a test that asserts on a literal right in your face:\n\n\n```\nself.assertEqual(swift_api_subrequest.headers, {\n  \u0027X-Object-Sysmeta-S3api-Checksum-Value\u0027: b64_checksum,\n  \u0027X-Object-Sysmeta-S3api-Checksum-Header\u0027: \u0027x-amz-checksum-32\u0027,\n  \u0027X-Object-Sysmeta-S3api-Checksum-type\u0027: \u0027CRC32\u0027,\n})\n```\n\n^ or, you know... whatever they are - like I can\u0027t tell what they *actually* are from reading these tests through all their helper layers.","commit_id":"769d4f8b5ecd3672b9964697e0388e29916ec731"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"0a359a676c868b8dd65838ee775d6748771e164b","unresolved":false,"context_lines":[{"line_number":1155,"context_line":""},{"line_number":1156,"context_line":"    def assert_no_checksum_sysmeta(self, headers):"},{"line_number":1157,"context_line":"        for name in (\u0027checksum-header\u0027, \u0027checksum-value\u0027, \u0027checksum-type\u0027):"},{"line_number":1158,"context_line":"            self.assertNotIn(sysmeta_header(\u0027object\u0027, name), headers)"},{"line_number":1159,"context_line":""},{"line_number":1160,"context_line":"    def assert_no_checksum_response_headers(self, headers):"},{"line_number":1161,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"}],"source_content_type":"text/x-python","patch_set":12,"id":"ef5a28b3_c59a3a93","line":1158,"in_reply_to":"f97fba9f_b2cff286","updated":"2026-06-23 15:33:33.000000000","message":"Acknowledged","commit_id":"769d4f8b5ecd3672b9964697e0388e29916ec731"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":163,"context_line":"            if method \u003d\u003d \u0027GET\u0027:"},{"line_number":164,"context_line":"                self.assertEqual(self.object_body, body)"},{"line_number":165,"context_line":"            else:"},{"line_number":166,"context_line":"                self.assertEqual(b\u0027\u0027, body)"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    def test_object_GET_checksum_mode_enabled_range_omits_checksum_headers("},{"line_number":169,"context_line":"            self):"}],"source_content_type":"text/x-python","patch_set":25,"id":"be56d06c_f1c69152","line":166,"updated":"2026-06-30 23:51:02.000000000","message":"`for method in (GET, ...): if method \u003d\u003d \u0027GET\u0027`\n\n^ this is anti-pattern, it\u0027s clearly testing two things there\u0027s no good reason for them to be in the same test and you can *tell* because there\u0027s actually two different assertion branches - what are you going to add POST to the list above?  with that repsonse not have a body?  what maintaince value does writing this test provide besides making it harder for reviewers to read.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ec8aee0b04cea073a2d649b94af43388a17ee16d","unresolved":false,"context_lines":[{"line_number":163,"context_line":"            if method \u003d\u003d \u0027GET\u0027:"},{"line_number":164,"context_line":"                self.assertEqual(self.object_body, body)"},{"line_number":165,"context_line":"            else:"},{"line_number":166,"context_line":"                self.assertEqual(b\u0027\u0027, body)"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    def test_object_GET_checksum_mode_enabled_range_omits_checksum_headers("},{"line_number":169,"context_line":"            self):"}],"source_content_type":"text/x-python","patch_set":25,"id":"5ffdca4e_bcdcf17b","line":166,"in_reply_to":"bc0e2c18_0b1c13f1","updated":"2026-07-01 21:29:08.000000000","message":"Marked as resolved.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":true,"context_lines":[{"line_number":163,"context_line":"            if method \u003d\u003d \u0027GET\u0027:"},{"line_number":164,"context_line":"                self.assertEqual(self.object_body, body)"},{"line_number":165,"context_line":"            else:"},{"line_number":166,"context_line":"                self.assertEqual(b\u0027\u0027, body)"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    def test_object_GET_checksum_mode_enabled_range_omits_checksum_headers("},{"line_number":169,"context_line":"            self):"}],"source_content_type":"text/x-python","patch_set":25,"id":"bc0e2c18_0b1c13f1","line":166,"in_reply_to":"be56d06c_f1c69152","updated":"2026-07-01 17:11:33.000000000","message":"I agree here, since this test is not really going to be changed, and for ease of reading for reviewers, I\u0027ll move this to two verbose tests","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":192,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":193,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    def test_object_HEAD_checksum_mode_enabled_range_omits_checksum_headers("},{"line_number":196,"context_line":"            self):"},{"line_number":197,"context_line":"        swift_headers \u003d dict(self.response_headers)"},{"line_number":198,"context_line":"        swift_headers.update({"}],"source_content_type":"text/x-python","patch_set":25,"id":"56b4694d_f642a5cc","line":195,"updated":"2026-06-30 23:51:02.000000000","message":"haha, look here we got it right!","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":false,"context_lines":[{"line_number":192,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-crc32\u0027, headers)"},{"line_number":193,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":194,"context_line":""},{"line_number":195,"context_line":"    def test_object_HEAD_checksum_mode_enabled_range_omits_checksum_headers("},{"line_number":196,"context_line":"            self):"},{"line_number":197,"context_line":"        swift_headers \u003d dict(self.response_headers)"},{"line_number":198,"context_line":"        swift_headers.update({"}],"source_content_type":"text/x-python","patch_set":25,"id":"69498986_f503f475","line":195,"in_reply_to":"56b4694d_f642a5cc","updated":"2026-07-01 17:11:33.000000000","message":"Acknowledged","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2820ddfe96856511be725ab4866ad6f49713e8ba","unresolved":true,"context_lines":[{"line_number":220,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def test_object_GETorHEAD_checksum_mode_part_number_omits_checksum("},{"line_number":223,"context_line":"            self):"},{"line_number":224,"context_line":"        for method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":225,"context_line":"            swift_headers \u003d dict(self.response_headers)"},{"line_number":226,"context_line":"            swift_headers.update({"}],"source_content_type":"text/x-python","patch_set":25,"id":"9d71c454_160654db","line":223,"updated":"2026-06-30 23:51:02.000000000","message":"I could imagine a test setup that explores a variety of request params for a given consistent set of mocked sysmeta, or this style of straight and to the point named behiavor style tests\n\nI\u0027m less enthused about a hybrid approach that sometimes uses loops to combine concepts and sometimes uses seperate tests for keep assertions linear.","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"4a96b7f886c3f087a097ab1861605102c01d88ba","unresolved":false,"context_lines":[{"line_number":220,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":221,"context_line":""},{"line_number":222,"context_line":"    def test_object_GETorHEAD_checksum_mode_part_number_omits_checksum("},{"line_number":223,"context_line":"            self):"},{"line_number":224,"context_line":"        for method in (\u0027GET\u0027, \u0027HEAD\u0027):"},{"line_number":225,"context_line":"            swift_headers \u003d dict(self.response_headers)"},{"line_number":226,"context_line":"            swift_headers.update({"}],"source_content_type":"text/x-python","patch_set":25,"id":"81cf7d8a_7dd3f297","line":223,"in_reply_to":"9d71c454_160654db","updated":"2026-07-01 17:11:33.000000000","message":"Acknowledged","commit_id":"fb609cd4cb20e962b204d16db02534529b4a04b1"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"1ba1ac1734e59a9fd4cb6f47aa534fdae8e12155","unresolved":true,"context_lines":[{"line_number":1347,"context_line":"            \u0027X-Object-Sysmeta-S3Api-Checksum-Type\u0027: \u0027FULL_OBJECT\u0027,"},{"line_number":1348,"context_line":"        })"},{"line_number":1349,"context_line":""},{"line_number":1350,"context_line":"    def test_object_PUT_v4_no_checksum_sysmeta_or_response_headers(self):"},{"line_number":1351,"context_line":"        req \u003d Request.blank("},{"line_number":1352,"context_line":"            \u0027/bucket/object\u0027,"},{"line_number":1353,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027PUT\u0027},"}],"source_content_type":"text/x-python","patch_set":59,"id":"c19b63d4_ea3c2b70","line":1350,"updated":"2026-08-06 16:56:38.000000000","message":"this test explicitly expects no checksum metadata or response headers when no checksum is supplied in PUT request, but this is NOT what AWS S3 does:\n\nhttps://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity-upload.html\n\n```\nBecause S3 has default integrity protections, if objects are uploaded without a checksum, S3 automatically attaches the recommended full object CRC-64/NVME (CRC64NVME) checksum algorithm to the object.\n```\n\nand @nmartes@NVIDIA.com has a patch to turn checksum on as default: https://review.opendev.org/c/openstack/swift/+/994571.","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1347,"context_line":"            \u0027X-Object-Sysmeta-S3Api-Checksum-Type\u0027: \u0027FULL_OBJECT\u0027,"},{"line_number":1348,"context_line":"        })"},{"line_number":1349,"context_line":""},{"line_number":1350,"context_line":"    def test_object_PUT_v4_no_checksum_sysmeta_or_response_headers(self):"},{"line_number":1351,"context_line":"        req \u003d Request.blank("},{"line_number":1352,"context_line":"            \u0027/bucket/object\u0027,"},{"line_number":1353,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027PUT\u0027},"}],"source_content_type":"text/x-python","patch_set":59,"id":"4ecdb9e8_4f2328e1","line":1350,"in_reply_to":"c19b63d4_ea3c2b70","updated":"2026-08-06 22:19:30.000000000","message":"Yep, once we get around to that patch, we will just remove this test and add a new one to expect the default.","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b1916a42dcbab8b9e9e28969e80f2afc57d8c446","unresolved":true,"context_lines":[{"line_number":1493,"context_line":"        # AWS seems to tolerate this so we should, too"},{"line_number":1494,"context_line":"        do_test(\u0027some/source\u0027)"},{"line_number":1495,"context_line":""},{"line_number":1496,"context_line":"    def test_object_PUT_copy_checksum_no_sysmeta_or_response_headers(self):"},{"line_number":1497,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(b\u0027\u0027).digest())"},{"line_number":1498,"context_line":"        status, headers, _body \u003d self._test_object_PUT_copy("},{"line_number":1499,"context_line":"            swob.HTTPOk, put_header\u003d{"}],"source_content_type":"text/x-python","patch_set":59,"id":"2a738054_9f19a6bb","line":1496,"updated":"2026-08-06 19:54:57.000000000","message":"since the test pipeline in this test is ``S3API -\u003e FakeAuthApp -\u003e FakeSwift`` and no copy middleware is installed, this checksum test only proves that S3API does not install its request-body checksum persistence callback for CopyObject; it does NOT prove what checksum metadata the real copy middleware ultimately places on the destination.\n\nprobably better to rename it as ``test_object_PUT_copy_checksum_does_not_install_footer_callback``","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1493,"context_line":"        # AWS seems to tolerate this so we should, too"},{"line_number":1494,"context_line":"        do_test(\u0027some/source\u0027)"},{"line_number":1495,"context_line":""},{"line_number":1496,"context_line":"    def test_object_PUT_copy_checksum_no_sysmeta_or_response_headers(self):"},{"line_number":1497,"context_line":"        crc \u003d base64.b64encode(checksum.crc32(b\u0027\u0027).digest())"},{"line_number":1498,"context_line":"        status, headers, _body \u003d self._test_object_PUT_copy("},{"line_number":1499,"context_line":"            swob.HTTPOk, put_header\u003d{"}],"source_content_type":"text/x-python","patch_set":59,"id":"f83a3ad7_691408e1","line":1496,"in_reply_to":"2a738054_9f19a6bb","updated":"2026-08-06 22:19:30.000000000","message":"Yea I agree, this is a much better name","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"09a53f91f5da9cd0521ee1ad04b6b229513fb2d8","unresolved":true,"context_lines":[{"line_number":1548,"context_line":"        self.assertNotIn("},{"line_number":1549,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.footers)"},{"line_number":1550,"context_line":""},{"line_number":1551,"context_line":"    def test_object_PUT_copy_inherits_source_checksum_sysmeta(self):"},{"line_number":1552,"context_line":"        source_body \u003d b\u0027actual copied source bytes\u0027"},{"line_number":1553,"context_line":"        source_checksum \u003d base64.b64encode("},{"line_number":1554,"context_line":"            checksum.crc32(source_body).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":65,"id":"6ba3b00b_ee5b4cd4","line":1551,"updated":"2026-08-08 00:48:06.000000000","message":"why remove all those tests to cover the checksum inheritance behaviors on copy?","commit_id":"2a399a7328c6410517d78baa0662023103d8daa2"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"f298a94707f3b8206bbb52a7b02b60d417621770","unresolved":false,"context_lines":[{"line_number":1548,"context_line":"        self.assertNotIn("},{"line_number":1549,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.footers)"},{"line_number":1550,"context_line":""},{"line_number":1551,"context_line":"    def test_object_PUT_copy_inherits_source_checksum_sysmeta(self):"},{"line_number":1552,"context_line":"        source_body \u003d b\u0027actual copied source bytes\u0027"},{"line_number":1553,"context_line":"        source_checksum \u003d base64.b64encode("},{"line_number":1554,"context_line":"            checksum.crc32(source_body).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":65,"id":"41c45e2f_d81c5dcb","line":1551,"in_reply_to":"6a27f870_d7b95219","updated":"2026-08-10 18:03:52.000000000","message":"Done","commit_id":"2a399a7328c6410517d78baa0662023103d8daa2"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"fb390802a41ed73d99701679af48e88135b6ea85","unresolved":true,"context_lines":[{"line_number":1548,"context_line":"        self.assertNotIn("},{"line_number":1549,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.footers)"},{"line_number":1550,"context_line":""},{"line_number":1551,"context_line":"    def test_object_PUT_copy_inherits_source_checksum_sysmeta(self):"},{"line_number":1552,"context_line":"        source_body \u003d b\u0027actual copied source bytes\u0027"},{"line_number":1553,"context_line":"        source_checksum \u003d base64.b64encode("},{"line_number":1554,"context_line":"            checksum.crc32(source_body).digest()).decode(\u0027ascii\u0027)"}],"source_content_type":"text/x-python","patch_set":65,"id":"6a27f870_d7b95219","line":1551,"in_reply_to":"6ba3b00b_ee5b4cd4","updated":"2026-08-10 15:43:21.000000000","message":"I\u0027ll throw them back in, thanks!","commit_id":"2a399a7328c6410517d78baa0662023103d8daa2"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"7de4f17fdacea5f10bef638239511adeecaf14fd","unresolved":true,"context_lines":[{"line_number":1615,"context_line":"        self.assertNotIn("},{"line_number":1616,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027, call.footers)"},{"line_number":1617,"context_line":"        self.assertNotIn("},{"line_number":1618,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.footers)"},{"line_number":1619,"context_line":""},{"line_number":1620,"context_line":"    def _test_object_PUT_copy(self, head_resp, put_header\u003dNone,"},{"line_number":1621,"context_line":"                              src_path\u003d\u0027/some/source\u0027):"}],"source_content_type":"text/x-python","patch_set":87,"id":"3848966f_0e6fdfd1","line":1618,"updated":"2026-08-27 10:38:52.000000000","message":"This assertNotIn testing the footers can never fail. FakeSwift validates the checksum while reading the body (https://review.opendev.org/c/openstack/swift/+/991516/87/test/unit/common/middleware/helpers.py#335), and raises if it does not match. That happens before the footers are updated (https://review.opendev.org/c/openstack/swift/+/991516/87/test/unit/common/middleware/helpers.py#347)","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":1615,"context_line":"        self.assertNotIn("},{"line_number":1616,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027, call.footers)"},{"line_number":1617,"context_line":"        self.assertNotIn("},{"line_number":1618,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.footers)"},{"line_number":1619,"context_line":""},{"line_number":1620,"context_line":"    def _test_object_PUT_copy(self, head_resp, put_header\u003dNone,"},{"line_number":1621,"context_line":"                              src_path\u003d\u0027/some/source\u0027):"}],"source_content_type":"text/x-python","patch_set":87,"id":"7c929941_bb1c5d2a","line":1618,"in_reply_to":"3848966f_0e6fdfd1","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"f8ef4c556a9643cb13ed560a04b3f1c14541f067","unresolved":true,"context_lines":[{"line_number":1656,"context_line":"        return self.call_s3api(req)"},{"line_number":1657,"context_line":""},{"line_number":1658,"context_line":"    def _register_object_copy_source(self, source_body,"},{"line_number":1659,"context_line":"                                     checksum_headers\u003dNone):"},{"line_number":1660,"context_line":"        \"\"\"Register a source object and enable the real copy middleware.\"\"\""},{"line_number":1661,"context_line":"        account \u003d \u0027test:tester\u0027"},{"line_number":1662,"context_line":"        grants \u003d [Grant(User(account), \u0027FULL_CONTROL\u0027)]"}],"source_content_type":"text/x-python","patch_set":87,"id":"b07568a5_162cad66","line":1659,"updated":"2026-08-27 09:12:46.000000000","message":"Looks like `checksum_headers` is never used, not in this patch, not in any of the follow ups?","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"c4031303b924113f70d9ac7f963fcf13042c233e","unresolved":true,"context_lines":[{"line_number":1656,"context_line":"        return self.call_s3api(req)"},{"line_number":1657,"context_line":""},{"line_number":1658,"context_line":"    def _register_object_copy_source(self, source_body,"},{"line_number":1659,"context_line":"                                     checksum_headers\u003dNone):"},{"line_number":1660,"context_line":"        \"\"\"Register a source object and enable the real copy middleware.\"\"\""},{"line_number":1661,"context_line":"        account \u003d \u0027test:tester\u0027"},{"line_number":1662,"context_line":"        grants \u003d [Grant(User(account), \u0027FULL_CONTROL\u0027)]"}],"source_content_type":"text/x-python","patch_set":87,"id":"a966b562_9fc6f2f8","line":1659,"in_reply_to":"9627f5ed_8b78ac76","updated":"2026-08-27 12:02:01.000000000","message":"\u003e hmmm, do we have unit tests that set checksum sysmeta headers on the source and assert they are not copied?\n\nWe don\u0027t - removed them in 1002624: s3api: Tidy up checksum persistence tests | https://review.opendev.org/c/openstack/swift/+/1002624, tests passing.","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":1656,"context_line":"        return self.call_s3api(req)"},{"line_number":1657,"context_line":""},{"line_number":1658,"context_line":"    def _register_object_copy_source(self, source_body,"},{"line_number":1659,"context_line":"                                     checksum_headers\u003dNone):"},{"line_number":1660,"context_line":"        \"\"\"Register a source object and enable the real copy middleware.\"\"\""},{"line_number":1661,"context_line":"        account \u003d \u0027test:tester\u0027"},{"line_number":1662,"context_line":"        grants \u003d [Grant(User(account), \u0027FULL_CONTROL\u0027)]"}],"source_content_type":"text/x-python","patch_set":87,"id":"ce71287b_7630dd21","line":1659,"in_reply_to":"a966b562_9fc6f2f8","updated":"2026-09-11 10:33:53.000000000","message":"squashed in that patch ^^^","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"385b77046e54eb9483abaa3dcce7624b4c02dae7","unresolved":true,"context_lines":[{"line_number":1656,"context_line":"        return self.call_s3api(req)"},{"line_number":1657,"context_line":""},{"line_number":1658,"context_line":"    def _register_object_copy_source(self, source_body,"},{"line_number":1659,"context_line":"                                     checksum_headers\u003dNone):"},{"line_number":1660,"context_line":"        \"\"\"Register a source object and enable the real copy middleware.\"\"\""},{"line_number":1661,"context_line":"        account \u003d \u0027test:tester\u0027"},{"line_number":1662,"context_line":"        grants \u003d [Grant(User(account), \u0027FULL_CONTROL\u0027)]"}],"source_content_type":"text/x-python","patch_set":87,"id":"9627f5ed_8b78ac76","line":1659,"in_reply_to":"b07568a5_162cad66","updated":"2026-08-27 10:54:46.000000000","message":"hmmm, do we have unit tests that set checksum sysmeta headers on the source and assert they are not copied?\n\nI know I added some functional tests here (which needs rebasing) https://review.opendev.org/c/openstack/swift/+/1002364","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":618,"context_line":"        self.assertNotIn(\u0027x-amz-checksum-type\u0027, headers)"},{"line_number":619,"context_line":"        self.assertEqual(self.object_body, body)"},{"line_number":620,"context_line":""},{"line_number":621,"context_line":"    def test_object_HEAD_checksum_mode_enabled_without_checksum_sysmeta(self):"},{"line_number":622,"context_line":"        self.swift.register("},{"line_number":623,"context_line":"            \u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket/object\u0027,"},{"line_number":624,"context_line":"            swob.HTTPOk, self.response_headers, None)"}],"source_content_type":"text/x-python","patch_set":101,"id":"815a0b5b_d401a021","line":621,"updated":"2026-10-07 04:11:56.000000000","message":"a lot of new tests added in this file can be combined easily using subTest(), and avoid those duplicate setups.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"}],"test/unit/common/middleware/s3api/test_s3checksum.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"ff3a71a381282c83f34c3aacdfd2757797cbed0e","unresolved":true,"context_lines":[{"line_number":95,"context_line":"            BytesIO(b\u0027\u0027), 0, checksum.crc32(),"},{"line_number":96,"context_line":"            \u0027x-amz-checksum-crc32\u0027, checksum_source)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"        self.assertEqual(b\u0027\u0027, wrapped.read())"},{"line_number":99,"context_line":"        self.assertFalse(wrapped.wsgi_input.closed)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def test_missing_checksum_source(self):"}],"source_content_type":"text/x-python","patch_set":87,"id":"02627b03_e9894e24","line":98,"updated":"2026-08-27 09:43:29.000000000","message":"I think it would be good to add `self.assertEqual(expected_checksum, wrapped.matching_checksum)` here","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":95,"context_line":"            BytesIO(b\u0027\u0027), 0, checksum.crc32(),"},{"line_number":96,"context_line":"            \u0027x-amz-checksum-crc32\u0027, checksum_source)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"        self.assertEqual(b\u0027\u0027, wrapped.read())"},{"line_number":99,"context_line":"        self.assertFalse(wrapped.wsgi_input.closed)"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    def test_missing_checksum_source(self):"}],"source_content_type":"text/x-python","patch_set":87,"id":"e9605ff7_21394b32","line":98,"in_reply_to":"02627b03_e9894e24","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"}],"test/unit/common/middleware/s3api/test_s3request.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1609,"context_line":"            \u0027header\u0027: \u0027x-amz-checksum-crc32\u0027,"},{"line_number":1610,"context_line":"            \u0027value\u0027: expected_checksum,"},{"line_number":1611,"context_line":"        }, checksumming_input.get_matching_checksum())"},{"line_number":1612,"context_line":"        self.assertIsNone(sigv4_req._persisted_checksum)"},{"line_number":1613,"context_line":"        footers \u003d {}"},{"line_number":1614,"context_line":"        sigv4_req.environ[\u0027swift.callback.update_footers\u0027](footers)"},{"line_number":1615,"context_line":"        self.assertEqual("}],"source_content_type":"text/x-python","patch_set":59,"id":"563422ba_61447bb0","line":1612,"updated":"2026-08-06 15:45:39.000000000","message":"it\u0027s unfortunate that these tests are making assertions about nonpublic attributes of the class; maybe we can think of a better way to validate expected behaviour; I hope to spend some more time reviewing the tests","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1609,"context_line":"            \u0027header\u0027: \u0027x-amz-checksum-crc32\u0027,"},{"line_number":1610,"context_line":"            \u0027value\u0027: expected_checksum,"},{"line_number":1611,"context_line":"        }, checksumming_input.get_matching_checksum())"},{"line_number":1612,"context_line":"        self.assertIsNone(sigv4_req._persisted_checksum)"},{"line_number":1613,"context_line":"        footers \u003d {}"},{"line_number":1614,"context_line":"        sigv4_req.environ[\u0027swift.callback.update_footers\u0027](footers)"},{"line_number":1615,"context_line":"        self.assertEqual("}],"source_content_type":"text/x-python","patch_set":59,"id":"3297ec29_a8e44436","line":1612,"in_reply_to":"563422ba_61447bb0","updated":"2026-08-06 22:19:30.000000000","message":"I am thinking that we can just move to looking at the function that uses `req._persisted_checksum` instead of calling it directly","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92d5e0de0ef3b0807d99024cb78a98406fd8dbec","unresolved":true,"context_lines":[{"line_number":1611,"context_line":"        }, checksumming_input.get_matching_checksum())"},{"line_number":1612,"context_line":"        self.assertIsNone(sigv4_req._persisted_checksum)"},{"line_number":1613,"context_line":"        footers \u003d {}"},{"line_number":1614,"context_line":"        sigv4_req.environ[\u0027swift.callback.update_footers\u0027](footers)"},{"line_number":1615,"context_line":"        self.assertEqual("},{"line_number":1616,"context_line":"            checksumming_input.get_matching_checksum(),"},{"line_number":1617,"context_line":"            sigv4_req._persisted_checksum)"}],"source_content_type":"text/x-python","patch_set":59,"id":"9c96381a_406e7fd1","line":1614,"updated":"2026-08-06 15:45:39.000000000","message":"footers value is not asserted","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"23255b6aca79451dba0743d305b869fbcd58d9f7","unresolved":false,"context_lines":[{"line_number":1611,"context_line":"        }, checksumming_input.get_matching_checksum())"},{"line_number":1612,"context_line":"        self.assertIsNone(sigv4_req._persisted_checksum)"},{"line_number":1613,"context_line":"        footers \u003d {}"},{"line_number":1614,"context_line":"        sigv4_req.environ[\u0027swift.callback.update_footers\u0027](footers)"},{"line_number":1615,"context_line":"        self.assertEqual("},{"line_number":1616,"context_line":"            checksumming_input.get_matching_checksum(),"},{"line_number":1617,"context_line":"            sigv4_req._persisted_checksum)"}],"source_content_type":"text/x-python","patch_set":59,"id":"c397d1be_8ac01f71","line":1614,"in_reply_to":"9c96381a_406e7fd1","updated":"2026-08-06 22:19:30.000000000","message":"Thanks for the catch!","commit_id":"d08b5c3c3c8b5d837bcf07eb01fe5eecdfb13058"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8f75dceebd80ad3ea1f6d88cb01656dc3a0c014f","unresolved":true,"context_lines":[{"line_number":1635,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027:"},{"line_number":1636,"context_line":"                footers[\u0027x-object-sysmeta-s3api-checksum-algorithm\u0027],"},{"line_number":1637,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027:"},{"line_number":1638,"context_line":"                footers[\u0027x-object-sysmeta-s3api-checksum-type\u0027],"},{"line_number":1639,"context_line":"        }, {"},{"line_number":1640,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-value\u0027: expected_checksum,"},{"line_number":1641,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027:"}],"source_content_type":"text/x-python","patch_set":76,"id":"388aab8b_2a29bea5","line":1638,"updated":"2026-08-21 16:03:49.000000000","message":"why are we building another dict with the same keys and values? this should be just passing ``footers`` as an arg (and for consistency it should be the second arg, with the expected value being the first arg.\n\nsame elsewhere","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"natemartes09@gmail.com","username":"nmartes"},"change_message_id":"ac00c745f04e96098e9264874561b75212ee98f2","unresolved":false,"context_lines":[{"line_number":1635,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027:"},{"line_number":1636,"context_line":"                footers[\u0027x-object-sysmeta-s3api-checksum-algorithm\u0027],"},{"line_number":1637,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027:"},{"line_number":1638,"context_line":"                footers[\u0027x-object-sysmeta-s3api-checksum-type\u0027],"},{"line_number":1639,"context_line":"        }, {"},{"line_number":1640,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-value\u0027: expected_checksum,"},{"line_number":1641,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027:"}],"source_content_type":"text/x-python","patch_set":76,"id":"d5e19526_637ae40a","line":1638,"in_reply_to":"388aab8b_2a29bea5","updated":"2026-08-21 20:10:41.000000000","message":"Yea I think it would be cleaner too","commit_id":"9323c90d9b7cde08d79147e3c56aff22bb153b3b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":1708,"context_line":"                                 sigv4_req.checksum_sysmeta_footers)"},{"line_number":1709,"context_line":"                self.assertEqual(exp_footers, footers)"},{"line_number":1710,"context_line":""},{"line_number":1711,"context_line":"    def test_crc32_no_persist_sysmeta(self):"},{"line_number":1712,"context_line":"        body \u003d b\u0027abcdefghijklmnopqrstuvwxyz\\n\u0027"},{"line_number":1713,"context_line":"        sigv4_req \u003d self._test_sig_v4_unsigned_payload("},{"line_number":1714,"context_line":"            body\u003dbody,"}],"source_content_type":"text/x-python","patch_set":101,"id":"c9db6e09_6f098940","line":1711,"updated":"2026-10-07 04:11:56.000000000","message":"a few tests can be combined with same setups. e.g. this one can be combined with test_sig_v4_unsgnd_pyld_no_crc_ok","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"}],"test/unit/common/middleware/s3api/test_versioning.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"f8ef4c556a9643cb13ed560a04b3f1c14541f067","unresolved":true,"context_lines":[{"line_number":220,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027, call.headers)"},{"line_number":221,"context_line":"        self.assertNotIn("},{"line_number":222,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.headers)"},{"line_number":223,"context_line":"        self.assertNotIn("},{"line_number":224,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-value\u0027, call.footers)"},{"line_number":225,"context_line":"        self.assertNotIn("},{"line_number":226,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027, call.footers)"}],"source_content_type":"text/x-python","patch_set":87,"id":"f1b67f1f_f5ff7ca2","line":223,"updated":"2026-08-27 09:12:46.000000000","message":"These three `assertNotIn` can never fail. `FakeSwift` valideas the checksum while reading the body (https://review.opendev.org/c/openstack/swift/+/991516/87/test/unit/common/middleware/helpers.py#335), and raises if it does not match. That happens before the footers are updated (https://review.opendev.org/c/openstack/swift/+/991516/87/test/unit/common/middleware/helpers.py#347)","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"60ed343a2c4f271f6f50c8593fb9a2e443f98253","unresolved":false,"context_lines":[{"line_number":220,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027, call.headers)"},{"line_number":221,"context_line":"        self.assertNotIn("},{"line_number":222,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-type\u0027, call.headers)"},{"line_number":223,"context_line":"        self.assertNotIn("},{"line_number":224,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-value\u0027, call.footers)"},{"line_number":225,"context_line":"        self.assertNotIn("},{"line_number":226,"context_line":"            \u0027x-object-sysmeta-s3api-checksum-algorithm\u0027, call.footers)"}],"source_content_type":"text/x-python","patch_set":87,"id":"81ea3d4e_597eda53","line":223,"in_reply_to":"f1b67f1f_f5ff7ca2","updated":"2026-09-11 10:33:53.000000000","message":"Done","commit_id":"0d8600b29cf4e451b90695d1f0afcd8bb5f31aa7"}],"tools/playbooks/saio_single_node_setup/add_s3api.yaml":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"9348860f728d10a45aafe07ccf451fd522091d01","unresolved":false,"context_lines":[{"line_number":35,"context_line":"          path: \"/etc/swift/proxy-server.conf\""},{"line_number":36,"context_line":"          section: \"filter:s3api\""},{"line_number":37,"context_line":"          option: \"allow_store_checksums\""},{"line_number":38,"context_line":"          value: \"true\""},{"line_number":39,"context_line":"      become: true"}],"source_content_type":"text/x-yaml","patch_set":101,"id":"5590434b_58764e4d","line":38,"updated":"2026-10-07 04:11:56.000000000","message":"this enable zuul to run probe tests with checksum persistence enabled.","commit_id":"70875b56f72b93e83d16af59e69f5163831d6478"}]}
