)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"617bc05b2e8063243983a5d1508ee1124f303796","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"fb9cddb0_8fba9ba7","updated":"2026-05-14 00:07:43.000000000","message":"recheck","commit_id":"1ce814d9d06ecaa0c752ac552f05d9c3be41aea1"},{"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":"682524164ecdc9f92dac57bd1616a5599db0b111","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":17,"id":"20695d7b_44de2a79","updated":"2026-08-19 09:18:43.000000000","message":"This is great, I love it!","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"}],"swift/common/middleware/request_trace.py":[{"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":"682524164ecdc9f92dac57bd1616a5599db0b111","unresolved":true,"context_lines":[{"line_number":65,"context_line":"        self.key \u003d conf.get(\u0027trace_key\u0027)"},{"line_number":66,"context_line":"        self.trace_name \u003d conf.get(\u0027trace_name\u0027, \u0027swift\u0027)"},{"line_number":67,"context_line":"        self.trace_name \u003d \"%s %d\" % (self.trace_name, os.getpid())"},{"line_number":68,"context_line":"        self.allowed_digests \u003d conf.get("},{"line_number":69,"context_line":"            \u0027allowed_digests\u0027, DEFAULT_ALLOWED_DIGESTS.split())"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        # grab the tracer module"}],"source_content_type":"text/x-python","patch_set":17,"id":"ca75eb84_b13e1b40","line":68,"updated":"2026-08-19 09:18:43.000000000","message":"`filter_factory` calls `get_allowed_digests()` and writes the result back into conf before constructing this class, so `__init__` receives a pre-validated value through that path. Anything that constructs `RequestTraceMiddleware` directly, every unit test that does not go through `filter_factory`, any operator tooling, skips that step and `self.allowed_digests` ends up as a raw string.\n\nI asked Claude to write a test and I was able to confirm in a SAIO machine:\n\n```python\n    conf \u003d {\u0027allowed_digests\u0027: \u0027sha256 sha512\u0027}\n    mw \u003d RequestTraceMiddleware(app, conf)\n    # mw.allowed_digests \u003d\u003d \u0027sha256 sha512\u0027  (str, unvalidated)\n\n    factory \u003d filter_factory({\u0027allowed_digests\u0027: \u0027sha256 sha512\u0027})\n    mw2 \u003d factory(app)\n    # mw2.allowed_digests \u003d\u003d [\u0027sha256\u0027, \u0027sha512\u0027]  (list, validated)\n```\n\nThis then becomes possible:\n\n\u0027sha\u0027 in \u0027sha256 sha512\u0027   → True   ← false positive\n\u0027sha2\u0027 in \u0027sha256 sha512\u0027  → True   ← false positive\n\nPossible fix — move the validation call inside `__init__`, following the pattern used by tempurl and formpost:\n\n```python\n    self.allowed_digests \u003d get_allowed_digests(\n        conf.get(\u0027allowed_digests\u0027, \u0027 \u0027.join(DEFAULT_ALLOWED_DIGESTS))\n    )\n```\n\nThen `filter_factory` no longer needs to pre-process `allowed_digests` before construction.","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"1ab6424b9b120215ac1f80a009ba2f925e1cafee","unresolved":true,"context_lines":[{"line_number":65,"context_line":"        self.key \u003d conf.get(\u0027trace_key\u0027)"},{"line_number":66,"context_line":"        self.trace_name \u003d conf.get(\u0027trace_name\u0027, \u0027swift\u0027)"},{"line_number":67,"context_line":"        self.trace_name \u003d \"%s %d\" % (self.trace_name, os.getpid())"},{"line_number":68,"context_line":"        self.allowed_digests \u003d conf.get("},{"line_number":69,"context_line":"            \u0027allowed_digests\u0027, DEFAULT_ALLOWED_DIGESTS.split())"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"        # grab the tracer module"}],"source_content_type":"text/x-python","patch_set":17,"id":"ba046e3b_e9b25ae1","line":68,"in_reply_to":"ca75eb84_b13e1b40","updated":"2026-08-24 07:49:53.000000000","message":"Agreed, thanks — confirmed here:\n                                                                                                                                 \n      direct construction -\u003e \u0027sha256 sha512\u0027 (str)   \u0027sha\u0027 accepted? True                                                        \n      via filter_factory  -\u003e [\u0027sha256\u0027, \u0027sha512\u0027]                                                                                                                                                                                                             \n\nI\u0027ve moved the validation into __init__ following the tempurl pattern as you\nsuggested, so anything constructing the middleware directly gets a validated\nset. One existing assertion in test_config was pinning the old unvalidated\nvalue, so I\u0027ve updated that too.","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"}],"swift/common/trace/__init__.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"a87612d8e71df1b84ba763722d8c05da8c443f86","unresolved":true,"context_lines":[{"line_number":92,"context_line":"        yield"},{"line_number":93,"context_line":""},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"def trace_spawn(env, func, *args, **kwargs):"},{"line_number":96,"context_line":"    \"\"\""},{"line_number":97,"context_line":"    ``eventlet.spawn`` that carries the current span into the green thread."},{"line_number":98,"context_line":""}],"source_content_type":"text/x-python","patch_set":17,"id":"6a3be639_c5b1355e","line":95,"updated":"2026-08-13 01:33:43.000000000","message":"I do wonder if something like this needs to move into concurrency namespace, there is a weird overlap here.","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"},{"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":"682524164ecdc9f92dac57bd1616a5599db0b111","unresolved":true,"context_lines":[{"line_number":385,"context_line":"        if wsgi_name in call_stack:"},{"line_number":386,"context_line":"            wsgi_name \u003d \"%s_%d\" % ("},{"line_number":387,"context_line":"                wsgi_name, len([i for i in call_stack"},{"line_number":388,"context_line":"                                if i.startswith(wsgi_name)]))"},{"line_number":389,"context_line":"        call_stack.append(wsgi_name)"},{"line_number":390,"context_line":"        with tracer.start_as_current_span(wsgi_name,"},{"line_number":391,"context_line":"                                          end_on_exit\u003dFalse) as span:"}],"source_content_type":"text/x-python","patch_set":17,"id":"06ee37d0_09067cb5","line":388,"range":{"start_line":388,"start_character":35,"end_line":388,"end_character":47},"updated":"2026-08-19 09:18:43.000000000","message":"Suggestion: The call_stack deduplication counts entries where `i.startswith(wsgi_name)`. If a short middleware class name is a prefix of another (e.g. \u0027Trace\u0027 and \u0027TraceMiddleware\u0027 both present in the stack), instances of the shorter name would be miscounted. My suggestion is to replace with `i \u003d\u003d wsgi_name` for strict equality.","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"1ab6424b9b120215ac1f80a009ba2f925e1cafee","unresolved":true,"context_lines":[{"line_number":385,"context_line":"        if wsgi_name in call_stack:"},{"line_number":386,"context_line":"            wsgi_name \u003d \"%s_%d\" % ("},{"line_number":387,"context_line":"                wsgi_name, len([i for i in call_stack"},{"line_number":388,"context_line":"                                if i.startswith(wsgi_name)]))"},{"line_number":389,"context_line":"        call_stack.append(wsgi_name)"},{"line_number":390,"context_line":"        with tracer.start_as_current_span(wsgi_name,"},{"line_number":391,"context_line":"                                          end_on_exit\u003dFalse) as span:"}],"source_content_type":"text/x-python","patch_set":17,"id":"48a70a17_b021f103","line":388,"range":{"start_line":388,"start_character":35,"end_line":388,"end_character":47},"in_reply_to":"06ee37d0_09067cb5","updated":"2026-08-24 07:49:53.000000000","message":"You\u0027re right that the prefix match is wrong, thank you — \u0027Trace\u0027 shouldn\u0027t be counted as an appearance of \u0027TraceMiddleware\u0027.                                                                                                                                                                                                              \n\nI think strict equality on its own might not be quite enough though. Once a name has been suffixed it no longer equals the bare name, so the third appearance of a middleware gets counted as though it were the second:                                                                                                                                                                             \n\n      startswith          three occurrences: [\u0027Foo\u0027, \u0027Foo_1\u0027, \u0027Foo_2\u0027]                                                                                                                                                                                        \n      equals              three occurrences: [\u0027Foo\u0027, \u0027Foo_1\u0027, \u0027Foo_1\u0027]  \u003c- clash                                                                                                                                                                              \n      exact-or-suffixed   three occurrences: [\u0027Foo\u0027, \u0027Foo_1\u0027, \u0027Foo_2\u0027]                                                                                                                                                                                        \n\n      startswith          prefix case: [\u0027Trace\u0027, \u0027TraceMiddleware\u0027, \u0027Trace_2\u0027]                                                                                                                                                                                \n      equals              prefix case: [\u0027Trace\u0027, \u0027TraceMiddleware\u0027, \u0027Trace_1\u0027]                                                                                                                                                                                \n      exact-or-suffixed   prefix case: [\u0027Trace\u0027, \u0027TraceMiddleware\u0027, \u0027Trace_1\u0027]                                                                                                                                                                                \n\nTwo spans sharing a name rather defeats the purpose, so I\u0027ve gone for counting entries that are either the bare name or that name followed by _\u003cdigits\u003e. That gives your fix for the prefix case and keeps repeats unique. Tests cover both, and the repeat one fails against strict equality so it shouldn\u0027t regress.\n\nLet me know if you\u0027d rather it were done another way — happy to change it 👍","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"},{"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":"e1353021790879bd6dc17543e3d9846c695221f8","unresolved":true,"context_lines":[{"line_number":385,"context_line":"        if wsgi_name in call_stack:"},{"line_number":386,"context_line":"            wsgi_name \u003d \"%s_%d\" % ("},{"line_number":387,"context_line":"                wsgi_name, len([i for i in call_stack"},{"line_number":388,"context_line":"                                if i.startswith(wsgi_name)]))"},{"line_number":389,"context_line":"        call_stack.append(wsgi_name)"},{"line_number":390,"context_line":"        with tracer.start_as_current_span(wsgi_name,"},{"line_number":391,"context_line":"                                          end_on_exit\u003dFalse) as span:"}],"source_content_type":"text/x-python","patch_set":17,"id":"fb592a3c_f649419d","line":388,"range":{"start_line":388,"start_character":35,"end_line":388,"end_character":47},"in_reply_to":"48a70a17_b021f103","updated":"2026-08-25 10:46:53.000000000","message":"You\u0027re right, and thanks for thinking it through further than my suggestion did and also for the thorough response. Your fix looks good to me!","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"}],"swift/obj/server.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"a87612d8e71df1b84ba763722d8c05da8c443f86","unresolved":true,"context_lines":[{"line_number":365,"context_line":"        # trace context would graft a span onto a closed trace"},{"line_number":366,"context_line":"        async_headers \u003d HeaderKeyDict(headers_out)"},{"line_number":367,"context_line":"        for header in get_trace_headers(request.environ):"},{"line_number":368,"context_line":"            async_headers.pop(header, None)"},{"line_number":369,"context_line":"        data \u003d {\u0027op\u0027: op, \u0027account\u0027: account, \u0027container\u0027: container,"},{"line_number":370,"context_line":"                \u0027obj\u0027: obj, \u0027headers\u0027: async_headers, \u0027db_state\u0027: db_state}"},{"line_number":371,"context_line":"        if redirect_data:"}],"source_content_type":"text/x-python","patch_set":17,"id":"fe50991e_585bd9da","line":368,"updated":"2026-08-13 01:33:43.000000000","message":"Don\u0027t like pushing extra trace knowledge into obj server, but not sure what else to do. Maybe a prune headers helper 🤷","commit_id":"a2ea47c4e5abed09f723e2ca1b6a44935d595838"}]}
