)]}'
{
  "log": [
    {
      "commit": "e24126528683cc2514ae9681c3893c2822b5d7cb",
      "tree": "d7f11af7e1002c23981a9f5ea42b341aff19e142",
      "parents": [
        "77b6efcf3378de3511d79de6efa2955a0b51d53b"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Thu Jul 23 13:43:07 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 23 13:43:07 2026 -0500"
      },
      "message": "Document `HTTPHdr` methods for #13420 review (#13422)\n\n* Document HTTP methods for #13420 review\n\n* Make changes requested by Brian Neradt\n\n  Put brief sentence on opening line\n  Use in/out/in,out parameter markers\n  Clarify that `@` headers are also included in length"
    },
    {
      "commit": "77b6efcf3378de3511d79de6efa2955a0b51d53b",
      "tree": "62b80dabb27602653fb2b53a81f63fccdc195e95",
      "parents": [
        "4b55a4d5689f66c414c798a82119128c8dd56592"
      ],
      "author": {
        "name": "Sergey Blekher",
        "email": "287965768+blurman-ai@users.noreply.github.com",
        "time": "Tue Jul 21 01:15:07 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 17:15:07 2026 -0500"
      },
      "message": "Remove unused RemapProcessor.h include from RemapPlugins.h (#13403)\n\nRemapPlugins.h includes RemapProcessor.h, and RemapProcessor.h includes\nRemapPlugins.h back, forming an include cycle. RemapPlugins.h does not use\nRemapProcessor: the class derives from Continuation and its members are\nHttpTransact::State, URL and HTTPHdr, none of which come from RemapProcessor.h.\n\nEverything RemapPlugins.h needs already arrives through its other includes\n(EventSystem.h, HttpTransact.h, RemapPluginInfo.h), which are also the only\nthings RemapProcessor.h contributed to the include closure. Removing the\ninclude breaks the cycle with no call-site changes."
    },
    {
      "commit": "4b55a4d5689f66c414c798a82119128c8dd56592",
      "tree": "b5d10c94b23b23234612d685fee25a119036c515",
      "parents": [
        "9e7a5785b85904a7b8001a96b8c3d40a4ebbc216"
      ],
      "author": {
        "name": "Bryan Call",
        "email": "bcall@apache.org",
        "time": "Mon Jul 20 15:12:59 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 17:12:59 2026 -0500"
      },
      "message": "doc: fix Via decoder ring URL (/tools/via moved to /via.html) (#13399)\n\nThe Via decoder ring page moved from /tools/via to /via.html on the\nproject website, leaving the documented URL returning 404. Update the\nreferences in the FAQ and records documentation to the new location."
    },
    {
      "commit": "9e7a5785b85904a7b8001a96b8c3d40a4ebbc216",
      "tree": "a35ac353273a0f1c1ebbd9d633c367ab2d79c68e",
      "parents": [
        "e015a607bc84fca7671eff5c256e15fb07271417"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jul 20 15:28:03 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 15:28:03 2026 -0500"
      },
      "message": "AI agent instruction updates (#13335)\n\nAI coding guidance does not fully reflect project conventions, which can\nlead agents toward inconsistent names and less maintainable tests.\n\nThis aligns the instructions with established AuTest, Python, and C++\npractices. It also documents both private-member prefix styles and the\ncommunity preference for `_` in new files."
    },
    {
      "commit": "e015a607bc84fca7671eff5c256e15fb07271417",
      "tree": "502f5910a192e01ac22ae5bb440bd5760d049ad9",
      "parents": [
        "a92d8babb71c72e1e55f706c795a540be67c496b"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jul 20 15:24:39 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 15:24:39 2026 -0500"
      },
      "message": "jax_fingerprint.test.py: address log wait flakiness (#13324)\n\nThe jax_fingerprint AuTest split its log verification between a\nbroad await for the method name and a later file-content assertion for\nthe fingerprint line. On CI, that can still leave the final assertion\nobserving the log before the fingerprint entry has been proven present.\n\nThis makes the await check the fingerprint-shaped log entry directly\nand keeps the file-content assertion on the same pattern, so each\nvariant both waits for and verifies the exact log content it needs.\n\nFixes: #13300"
    },
    {
      "commit": "a92d8babb71c72e1e55f706c795a540be67c496b",
      "tree": "8a3d1dd71dc05d83b65ec0c9f752f3b70161d594",
      "parents": [
        "5fc8ad3585e267e966670743a0f20e885638ec32"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jul 20 15:23:54 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 15:23:54 2026 -0500"
      },
      "message": "Preserve client port in transaction logs (#13379)\n\nClient source ports could be logged as zero when the live inbound\nconnection was cleared before transaction log marshalling. This\nobscured the effective client endpoint in access logs.\n\nThis reads the port from the effective client endpoint retained by\nHttpSM, keeping it available after connection cleanup."
    },
    {
      "commit": "5fc8ad3585e267e966670743a0f20e885638ec32",
      "tree": "b7a99a44eaaf22eae8c74f8f10c0a79854a7e8b4",
      "parents": [
        "110b5442a77b3f04bb9b694fb01abeea821c6438"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jul 20 15:04:45 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 15:04:45 2026 -0500"
      },
      "message": "Avoid Diags lock for syslog output (#13398)\n\nSyslog-only diagnostics take the same mutex used to serialize file\noutput, adding avoidable contention when many threads report a shared\nfailure.\n\nThis limits the diagnostics mutex to FILE-backed destinations and\nremoves the obsolete FreeBSD exception because syslog provides its own\nthread safety.\n\nFixes: #7374"
    },
    {
      "commit": "110b5442a77b3f04bb9b694fb01abeea821c6438",
      "tree": "92d4f0fac5fcb209e5772b52fc258928d91b1597",
      "parents": [
        "c64d786be619a2e6e8f3f0d5e01d2ac68ba21a81"
      ],
      "author": {
        "name": "Javid Khan",
        "email": "dxbjavid@gmail.com",
        "time": "Mon Jul 20 22:02:18 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 11:32:18 2026 -0500"
      },
      "message": "copy only len_in bytes in the escapify no-escape path (#13404)"
    },
    {
      "commit": "c64d786be619a2e6e8f3f0d5e01d2ac68ba21a81",
      "tree": "ecf7a0b882516036456d647795667481b27bd591",
      "parents": [
        "116e66396042d865d3f513f4fad259614e6afbb3"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jul 20 11:27:20 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 11:27:20 2026 -0500"
      },
      "message": "ssl: remove the dead SSL_HOOK_OP_TERMINATE op (#13407)\n\nNo code has ever assigned hookOpRequested this value: the introducing\ncommit (TS-3006, 2014) only wrote it to an example plugin\u0027s own struct,\nand the public TSSslVConnOp API that could have set it was removed in\n2016 (TS-4658). A hook rejects a handshake via\nTSVConnReenableEx(TS_EVENT_ERROR) instead, so drop the enumerator and\nits unreachable arm in sslServerHandShakeEvent()."
    },
    {
      "commit": "116e66396042d865d3f513f4fad259614e6afbb3",
      "tree": "3048ee2ad06acf1cf42dec3184af6bb9caa846ca",
      "parents": [
        "b1465b4e0b464021972b15581579c5fdd1ac66fe"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jul 20 10:31:54 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 10:31:54 2026 -0500"
      },
      "message": "Cache: fix cached-header HdrHeap growth on repeated 304 revalidation (#13405)\n\nA hot, frequently-revalidated cached object grows its cached response\nheader\u0027s HdrHeap without bound until marshal_length crosses the aggregation\nfragment limit (AGG_SIZE), after which the cache write can never commit and\nthe object stays frozen stale.\n\nmerge_and_update_headers_for_cache_update unconditionally deleted\nAge/ETag/Expires before re-merging. A deleted MIMEField slot is not reclaimed\nuntil its whole field block empties, so each revalidation stranded a dead slot.\nDelete a caching header only when the 304 omits it; when the 304 carries it,\nlet the merge overwrite the field in place.\n\nmerge_response_header_with_cached_header used a sticky dups_seen flag that,\nonce any response field had a duplicate, forced every later single-valued field\ndown a field_create append path. Reconcile each field name independently,\noverwriting cached slots in place and trimming surplus values, so the merge is\nidempotent.\n\nAdd regression tests asserting bounded cached-header heap growth across\nrepeated merges (including the caller\u0027s conditional-delete sequence over cooked\ncaching headers), and a hidden [.merge-bench] microbenchmark comparing the new\nmerge against the previous implementation."
    },
    {
      "commit": "b1465b4e0b464021972b15581579c5fdd1ac66fe",
      "tree": "c99246025c6c99af523e2ea2738af3c7a2be3ad2",
      "parents": [
        "03652e4928a0c18cc7256e1dfaed7e7001abf5db"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Mon Jul 20 10:11:30 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 20 10:11:30 2026 -0500"
      },
      "message": "Improve testing and documentation for server firewall marks (#13385)\n\n* Improve docs for `TSHttpTxnServerPacketMarkSet`\n\n* Add AuTest for `TSHttpTxnServerPacketMarkSet`"
    },
    {
      "commit": "03652e4928a0c18cc7256e1dfaed7e7001abf5db",
      "tree": "88d2f2ff8fed443fd02c0510c6fa94385e796e2d",
      "parents": [
        "f7f1d830387f017591b8ac3d194414e1743d6fd1"
      ],
      "author": {
        "name": "Miles Libbey",
        "email": "mlibbey@apache.org",
        "time": "Sat Jul 18 16:45:30 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 16:45:30 2026 -0700"
      },
      "message": "prefetch: admit --fetch-query requests only when the key is present (#13370)\n\nWith --fetch-query configured, the front-end/first-pass gate set\nhandleFetch\u003dtrue whenever the query key was *configured*, not when the\nrequest carried it. So every request whose path matched no\nfetch-path-pattern was admitted anyway, ran the pattern replace, failed,\nand logged ERROR \"failed to process the pattern\" -- while scheduling no\nprefetch at all (BgFetch runs only on the success path).\n\nAdmit only when the request\u0027s query actually contains the key, matched\nas a \"\u003ckey\u003e\u003d\" parameter rather than a substring (which could hit another\nparameter\u0027s name or value). The same parameter test is now used by the\nhasValidQuery branch selector and the query-branch loop as well."
    },
    {
      "commit": "f7f1d830387f017591b8ac3d194414e1743d6fd1",
      "tree": "84852b3cdbb8fed98ce01425f937594e893f7452",
      "parents": [
        "154d8b00619b2c80c88857943fa10b09b0b516be"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Fri Jul 17 12:35:56 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 12:35:56 2026 -0500"
      },
      "message": "Handle webp_transform input robustly (#13390)\n\nEmpty or mislabeled image responses need consistent handling by the\nwebp_transform plugin. These inputs should pass through unchanged while\nvalid images continue to be converted normally.\n\nThis checks the expected image signature before conversion and preserves\nthe original body and content type whenever conversion is bypassed.\nReplay coverage exercises empty, invalid, and valid image bodies."
    },
    {
      "commit": "154d8b00619b2c80c88857943fa10b09b0b516be",
      "tree": "ff0a0db00c798a70bb97eb9eef51d48e5377693d",
      "parents": [
        "4efc34477e3523f27f906ceb8f82abe9f500e183"
      ],
      "author": {
        "name": "Masakazu Kitajo",
        "email": "maskit@apache.org",
        "time": "Thu Jul 16 11:56:04 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 11:56:04 2026 -0600"
      },
      "message": "Hard-enforce max_active_streams_in at HTTP/2 stream creation (#13386)\n\nproxy.config.http2.max_active_streams_in has only adjusted the advertised SETTINGS_MAX_CONCURRENT_STREAMS, leaving the proxy unable to bound buffered response memory against clients that open streams faster than the advisory throttle reacts. It now also carries a finite default so the cap is no longer effectively unlimited.\n\nThe new knob proxy.config.http2.max_active_streams_policy_in selects enforcement. Value 0 keeps the advisory behavior that lowers advertised concurrency to proxy.config.http2.min_concurrent_streams_in. Value 1 refuses new inbound streams with REFUSED_STREAM once the process-wide active-stream count reaches the limit and leaves the advertised value untouched, so the min_concurrent_streams_in reduction that disrupts some clients no longer applies.\n\nmax_active_streams_in now defaults to 200000 rather than 0. Operators should size it to their available memory budget; set it to 0 to disable the cap.\n\nRefusal happens after HPACK decoding so the dynamic table stays in sync with the client and the connection survives. proxy.process.http2.max_active_streams_exceeded_in counts each refusal."
    },
    {
      "commit": "4efc34477e3523f27f906ceb8f82abe9f500e183",
      "tree": "d6b7d7c7058669c7cc503643881d2d9db8f542e1",
      "parents": [
        "05c958a8db881288c9288e6a78dcff67818761d5"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Thu Jul 16 09:53:26 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 16 09:53:26 2026 -0500"
      },
      "message": "Generalize client packet mark test (#13384)\n\n* Add util file for packet mark test plugin\n\nThis introduces common utilities to make it easy to add a\nserver-side packet mark test.\n\n* Generalize packet mark AuTest name\n\n* Ensure header value is null-terminated"
    },
    {
      "commit": "05c958a8db881288c9288e6a78dcff67818761d5",
      "tree": "8c1e6f17f77ebc3f6ae43a16ae511cafc389d5c9",
      "parents": [
        "1f34fdafd96f0506edc3bd18098fc54c0800345a"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Wed Jul 15 07:21:14 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 15 07:21:14 2026 -0500"
      },
      "message": "Improve testing and documentation for client firewall marks (#13383)\n\n* Improve docs for `TSHttpTxnClientPacketMarkSet`\n\n* Add AuTest for `TSHttpTxnClientPacketMarkSet`\n\n* Make changes requested by Brian Neradt\n\n  Allow PACKET_MARK in sock_option_flag_in\n  Mention `CAP_NET_RAW` in docstring"
    },
    {
      "commit": "1f34fdafd96f0506edc3bd18098fc54c0800345a",
      "tree": "335ca034cead7a708066cf9ed7744713855dfe86",
      "parents": [
        "bd0700b7ab310a77fb9743ea7390ac90577be67b"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Tue Jul 14 09:14:27 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 14 09:14:27 2026 -0500"
      },
      "message": "Reject over-long unix socket paths in server_ports (#13356)\n\n* Reject over-long unix socket paths in server_ports\n\nA path longer than sun_path (108 bytes including the terminator) was\nsilently truncated, and left unterminated, since strncpy writes no\nterminator when it truncates, so ATS bound a listener on the wrong\nfilesystem path with nothing telling the operator the configured path\nwas too long.\n\nReject the path at configuration parse with a Warning naming the\nlimit, and make UnAddr\u0027s string constructors always null-terminate."
    },
    {
      "commit": "bd0700b7ab310a77fb9743ea7390ac90577be67b",
      "tree": "83eef7eed60990bd6fe9548a2f07d8744e022e9d",
      "parents": [
        "dcbd1eedb7f7c0918fce1385917742794b01841a"
      ],
      "author": {
        "name": "Leif Hedstrom",
        "email": "zwoop@apache.org",
        "time": "Tue Jul 14 12:39:13 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 14 12:39:13 2026 +0200"
      },
      "message": "cripts: build against fmt 11+ (incl. 12.x) (#13375)\n\nfmt 11 dropped fmt::format/vformat from fmt/core.h; include fmt/format.h\ninstead, and use fmt::format directly to avoid a deprecated format_string\nconversion. Still builds on fmt 8.1+."
    },
    {
      "commit": "dcbd1eedb7f7c0918fce1385917742794b01841a",
      "tree": "cd66a232411905ba1f7f7df2aa10a4f3677846e1",
      "parents": [
        "d1d02c3f2638554fff3eed95de01fa778aecf10b"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Tue Jul 14 10:56:25 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jul 14 10:56:25 2026 +0900"
      },
      "message": "Use ts::bravo::shared_mutex for host status lock (#13367)\n\nHostStatus lookups sit on the parent-selection hot path and are\noverwhelmingly reads, so replace the ink_rwlock with the reader-biased\nBRAVO shared_mutex for better read scaling under contention. Readers\ntake ts::bravo::shared_lock (Token-aware); writers use std::scoped_lock."
    },
    {
      "commit": "d1d02c3f2638554fff3eed95de01fa778aecf10b",
      "tree": "def70daa66de723127a180b9b15e7582d7954bd9",
      "parents": [
        "01ed4876a4e433d28ef8419a0759df7cfcab0b47"
      ],
      "author": {
        "name": "Phong Nguyen",
        "email": "phongn@gmail.com",
        "time": "Mon Jul 13 15:29:08 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 13 15:29:08 2026 -0700"
      },
      "message": "Fix CLFUS RAM cache value metric broken by integer division (#13233)\n\nPR #11733 rewrote the CACHE_VALUE_HITS_SIZE cast so static_cast\u003cfloat\u003e\nwraps the whole quotient, making (hits + 1) / (size + overhead) integer\ndivision. It truncates to 0 for normal object sizes, zeroing the value\nmetric and collapsing CLFUS to FIFO: no promote-on-hit, no clock second\nchance, and no value-based ghost re-admission.\n\nBind the cast to the numerator to restore floating-point division, and\nadd the ram_cache_clfus_value regression test as a guard (it fails on\nthe pre-fix macro and passes after)."
    },
    {
      "commit": "01ed4876a4e433d28ef8419a0759df7cfcab0b47",
      "tree": "f678d36aee00fc98cec85da117f4c3e84a8f2b43",
      "parents": [
        "e3dc7e76c3555be938ed0ec1a05b6952eff65cec"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jul 13 16:15:49 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 13 16:15:49 2026 -0500"
      },
      "message": "Refresh default TLS context on secret update (#13342)\n\nDefault server certificate secret updates could rebuild the TLS\ncontexts for CN/SAN lookups while leaving the default/no-SNI context\npointing at the old SSL_CTX. Operators could update cert material on\ndisk and through the secret API, but new handshakes without a more\nspecific match could still serve the stale certificate.\n\nThis updates runtime context refresh to cover address/default lookup\nentries owned by the same ssl_multicert policy and retains the\ndefault context while callers create new TLS sessions. This also adds\nan AuTest that updates a plugin-loaded default certificate and\nverifies the next no-SNI handshake sees the new certificate.\n\nFixes: #9562"
    },
    {
      "commit": "e3dc7e76c3555be938ed0ec1a05b6952eff65cec",
      "tree": "a83ad116dd3fff8eeb3f712180c8d58a822a318f",
      "parents": [
        "108568b254d3f3030fc624e76e5eac32b36a5263"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jul 13 13:40:05 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 13 12:40:05 2026 -0500"
      },
      "message": "stale_response.test.py: address log wait flakiness (#13323)\n\nThe stale_response log checks can run before every directive that\nthey later assert has been written. Waiting for one marker with a\nsleep-based process leaves the final content checks exposed to ATS log\nflush timing when both stale directives are expected.\n\nThis replaces the sleep-based watcher with explicit await runs for each\ndirective being asserted. The test now waits for the matching\nstale-while-revalidate and stale-if-error entries before performing the\nfinal log content checks.\n\nFixes: #13301"
    },
    {
      "commit": "108568b254d3f3030fc624e76e5eac32b36a5263",
      "tree": "8146cccc1c72a6a5ed1b3a04dba7017fe616de28",
      "parents": [
        "caf9c87097d7231e74e536337c78eb4eba306ba5"
      ],
      "author": {
        "name": "Masakazu Kitajo",
        "email": "maskit@apache.org",
        "time": "Mon Jul 13 10:15:17 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 13 10:15:17 2026 -0600"
      },
      "message": "docs: document the wipe_field_value logging filter (#13374)\n\n* docs: document the wipe_field_value logging filter\n\nAdd a dedicated section describing how the wipe_field_value log\nfilter masks query parameter values, including that it matches\nparameter names rather than values. The worked example is taken\nfrom the existing log-filter autest so the shown output matches\nwhat Traffic Server actually produces.\n\n* Address copilot comments"
    },
    {
      "commit": "caf9c87097d7231e74e536337c78eb4eba306ba5",
      "tree": "919b7fd47fcd9f86475dde037181c0e17e0d9db0",
      "parents": [
        "364668f365a6be7fe0b9619d345ecdc8a3b2ecab"
      ],
      "author": {
        "name": "Masakazu Kitajo",
        "email": "maskit@apache.org",
        "time": "Mon Jul 13 10:14:18 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 13 10:14:18 2026 -0600"
      },
      "message": "autest: skip async handshake test when plugin is absent (#13372)\n\nThe async_handshake test plugin is only built with OpenSSL\n(TS_USE_TLS_ASYNC). SkipUnless does not evaluate its conditions where\nit appears; it only registers them for the framework to check later,\nso the test file keeps executing and PrepareTestPlugin ran at load\ntime and raised a ValueError when the plugin was missing, reported as\na test exception instead of a skip. Guard the call on file existence\nso the test skips cleanly on non-OpenSSL builds."
    },
    {
      "commit": "364668f365a6be7fe0b9619d345ecdc8a3b2ecab",
      "tree": "a4602347473dae60e3b8799b9473db440059e45a",
      "parents": [
        "a9e26aa45387087b40063db05212713456925bd3"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jul 11 19:01:57 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 11 19:01:57 2026 -0500"
      },
      "message": "authproxy: strip request-body framing from auth sub-requests (#13333)\n\nThe head/range/redirect auth transforms copy the whole client request and\nthen force it bodyless (method override + Content-Length: 0) to probe the\nauth server, but left Transfer-Encoding, Trailer, and Expect in place. A\nchunked or Expect: 100-continue client request therefore produced a\nself-contradictory sub-request: a bodyless HEAD/GET still advertising a body.\n\nATS honors the framing and sets up a request-body tunnel for a body that\nnever arrives, stalling the probe until the inactivity timeout; and\nproxy.config.http.reject_head_with_content rejects a HEAD that declares\ncontent outright. Strip Transfer-Encoding, Trailer, and Expect when\nnormalizing the sub-request to bodyless."
    },
    {
      "commit": "a9e26aa45387087b40063db05212713456925bd3",
      "tree": "9ca784b99054536aa6dd2558b58f0fe7aa72b81f",
      "parents": [
        "7c4fc5b7305db97db99922f7d6fb9cce547abe21"
      ],
      "author": {
        "name": "Masakazu Kitajo",
        "email": "maskit@apache.org",
        "time": "Thu Jul 09 12:09:29 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 09 12:09:29 2026 -0600"
      },
      "message": "jax_fingerprint: Reduce allocations and gate methods at build time (#13338)\n\n* jax_fingerprint: Reduce allocations and gate methods at build time\n\nTrim per-connection memory work in the hybrid (global + remap) setup\nby collapsing the per-connection table of fingerprint contexts to an\ninline structure and by passing fingerprints into the context without\nan intermediate copy. Lookup behavior is unchanged.\n\nAdd ENABLE_JAX_METHODS as the configure-time switch for which\nfingerprint methods are compiled in. CMake derives the per-method\npreprocessor defines, the dispatcher table in plugin.cc, and the slot\ncount of the inline context table from the same list. An empty list\nor an unknown method directory fails at configure time.\n\nInclude a developer README covering the per-method file layout, the\nbuild-time switches, and the naming rules that the CMake glob relies\non.\n\n* Address copilot comments"
    },
    {
      "commit": "7c4fc5b7305db97db99922f7d6fb9cce547abe21",
      "tree": "acf3544a0a7a1d1f75e573924c050f19cd4514e9",
      "parents": [
        "f3dea0beda7bb302fc65ebca71acde140e210ba4"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Wed Jul 08 13:14:23 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 08 13:14:23 2026 -0500"
      },
      "message": "tls_renegotiation autest: gate the detection-line check to OpenSSL (#13371)\n\nBoringSSL rejects a peer-initiated renegotiation inside the library\nbefore ATS\u0027s SSL info callback runs -- SSL_get_state() there only ever\nreturns SSL_ST_INIT or SSL_ST_OK, never SSL_ST_RENEGOTIATE -- so the\n\"trying to renegotiate from the client\" line is never logged and the\nContainsExpression fails on BoringSSL (Apache CI stays green because it\nruns OpenSSL). The crash-safety check still runs on every SSL library;\nonly the detection-line assertion is now OpenSSL-only."
    },
    {
      "commit": "f3dea0beda7bb302fc65ebca71acde140e210ba4",
      "tree": "d959e9998d171e1a12bb2bdaf29bee2bfa7335d2",
      "parents": [
        "082e87545eeeb6141b492d833d298dab2f9e03d5"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Wed Jul 08 07:56:08 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 08 07:56:08 2026 +0900"
      },
      "message": "Restore cqssrt log field dropped by the 11-Dev merge (#13337)\n\nThe cqssrt (client_req_ssl_resumption_type) log field added in #12404\nwas silently dropped from master by the 11-Dev integration merge\n(#12983, 8415cef661). A criss-cross merge resolution removed its\nregistration in Log.cc and the LogAccess marshal path, while the\nsupporting HttpUserAgent::get_client_ssl_resumption_type() machinery\nsurvived, leaving that accessor as dead code with no caller.\n\nRe-register the field and re-add the marshal function plus the\nTransactionLogData bridge accessor so the orphaned machinery is wired\nback into the log system. Declare it as sINT (it marshals a single\nint), not the original dINT, matching the type/marshal-framing fix in\n#13223."
    },
    {
      "commit": "082e87545eeeb6141b492d833d298dab2f9e03d5",
      "tree": "645c8057a5cc767272a719ba4ff5d5a06ca4da87",
      "parents": [
        "7426868811c84ff96604c76a499488abc81007cc"
      ],
      "author": {
        "name": "Javid Khan",
        "email": "dxbjavid@gmail.com",
        "time": "Tue Jul 07 05:45:12 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 19:15:12 2026 -0500"
      },
      "message": "Track remaining length while decoding qpack header block (#13361)"
    },
    {
      "commit": "7426868811c84ff96604c76a499488abc81007cc",
      "tree": "98a0457eea72be9e5aa505144cd6d71a2dbbc5c1",
      "parents": [
        "f92e5bf680969ea6a3592d446a6bcc452617e431"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jul 06 17:26:54 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 17:26:54 2026 -0500"
      },
      "message": "Add USDT to iocore/net, iocore/cache, http, http2 (#13344)\n\nAdd USDT probes to the following:\n\n- iocore/net: socket read/write, read/write disable, reenable,\n  do_io_close, inactivity timeout, TLS read\n- iocore/cache: read-while-writer attach, produce, starve, writer close\n- proxy/http: tunnel producer/consumer/flow-control, add consumer,\n  chunk decode, UA abort, transfer setup, background fill\n- proxy/http2: send-window/write-buffer block, data frame, window\n  update, RST_STREAM sent/received\n\nThe existing probes only mark one-shot lifecycle milestones; these\ncover the steady-state body-transfer and flow-control phases. They\ncompile to no-ops unless built with -DENABLE_PROBES\u003dON."
    },
    {
      "commit": "f92e5bf680969ea6a3592d446a6bcc452617e431",
      "tree": "935aa902d84949903499d63be346b1f65f430c5e",
      "parents": [
        "16c434c28251804ac8022950cbbe913a6a866b4a"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jul 06 17:25:24 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 17:25:24 2026 -0500"
      },
      "message": "rate_limit: don\u0027t update metrics when a selector has no `metrics:` block (#13343)\n\nA selector configured without a `metrics:` block should be a metrics no-op.\nIt isn\u0027t: _metrics is value-initialized to 0, but incrementMetric() only\nsuppresses the update when an entry equals the TS_ERROR (-1) sentinel that\nmetric_helper() uses for \"not registered\". So the guard never fires and every\nqueue/reject/expire/resume calls TSStatIntIncrement() on an unregistered ID.\n(It currently lands on the reserved bad_id slot, so it is absorbed rather than\nfatal -- but the plugin still should not emit anything.)\n\nDefault _metrics to TS_ERROR in the constructor so incrementMetric() stays a\nno-op until metrics are actually registered."
    },
    {
      "commit": "16c434c28251804ac8022950cbbe913a6a866b4a",
      "tree": "b1d5a526ea1fa98e278daaa4b59d510467790278",
      "parents": [
        "66845d68778062fe02cef685d6dabeea4b2266f4"
      ],
      "author": {
        "name": "mmustafasenoglu",
        "email": "mmustafasenoglu0@gmail.com",
        "time": "Mon Jul 06 19:13:19 2026 +0300"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 11:13:19 2026 -0500"
      },
      "message": "docs: add call condition note for TSUrlHostGet (#13313)\n\n* docs: add call condition note for TSUrlHostGet\n\nAdd a note to the TSUrlHostGet documentation indicating that it should\nonly be called after TS_HTTP_POST_REMAP_HOOK. For earlier hooks like\nTS_HTTP_READ_REQUEST_HDR_HOOK, TSHttpHdrHostGet should be used instead.\n\nFixes #5742\n\n* docs: fix unknown interpreted text role data\n\nReplace :data: with double backticks for hook names, consistent\nwith the rest of the documentation.\n\nFixes #5742\n\n* docs: trigger CI for TSUrlHostGet call condition note\n\n* docs: document TSHttpHdrUrlGet hook availability, fix redirect_1 to use TSHttpHdrHostGet\n\n- TSHttpHdrUrlGet: add note that URL components may not be available at\n  early hooks, recommend TSHttpHdrHostGet for reliable host retrieval\n- TSUrlHostGet: add call condition note (TS_HTTP_POST_REMAP_HOOK onwards)\n  and cross-reference to TSHttpHdrHostGet\n- TSHttpHdrHostGet: add cross-references to TSHttpHdrUrlGet and TSUrlHostGet\n- redirect_1: replace TSHttpHdrUrlGet+TSUrlHostGet with TSHttpHdrHostGet\n  which works correctly at TS_HTTP_READ_REQUEST_HDR_HOOK\n\n* fix(docs): replace :c:macro: with double backticks for TS_HTTP_READ_REQUEST_HDR_HOOK\n\n* fix(docs): replace :c:macro: with double backticks for TS_HTTP_READ_REQUEST_HDR_HOOK\n\n* fix(docs): replace :c:macro: with double backticks for TS_HTTP_READ_REQUEST_HDR_HOOK\n\n* fix: restore TSHttpHdrHostGet docs content and add cross-references\n\n- Restored accidentally emptied TSHttpHdrHostGet.en.rst\n- Added call condition note explaining TSHttpHdrHostGet vs TSUrlHostGet\n- Added See Also cross-references to related APIs\n\nFixes docs build warning reported by JosiahWI\n\n* fix: add trailing newline to redirect_1.cc\n\n* fix: restore upstream license header formatting\n\n* fix: restore upstream license header formatting\n\n* fix: restore upstream license header formatting\n\n* fix: restore upstream license header in redirect_1.cc\n\n* fix: restore license header and fix broken string literal\n\n* fix: restore blank line after title underline\n\n* fix: add blank line between title and Synopsis\n\n* fix: apply code changes on top of upstream cleanly\n\n* fix: restore redirect_1.cc with correct API changes\n\n* fix: restore redirect_1.cc with correct TSHttpHdrHostGet usage\n\n* fix: apply TSHttpHdrHostGet changes cleanly on upstream\n\n* fix: restore blank line between title and Synopsis\n\n---------\n\nCo-authored-by: Mustafa Senoglu \u003cmustafa@senoglu.local\u003e"
    },
    {
      "commit": "66845d68778062fe02cef685d6dabeea4b2266f4",
      "tree": "843375f65ff18210f9f44174f319485456f05677",
      "parents": [
        "a24dd801712d0ab1df4a6858b93f148a01203ae7"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jul 04 19:45:26 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 04 19:45:26 2026 -0500"
      },
      "message": "traffic_crashlog: emit a well-formed report when the backtrace is empty (#13360)\n\nServerBacktrace() reports success but yields no frames when the\ntarget\u0027s thread list is unreadable -- e.g. a fast-aborting target has\nalready exited by the time the forked helper attaches. The success\ncheck only tested for a null trace, so an empty-but-non-null trace\nfell into the success path and produced a report with no backtrace\nand no explanation. Require a non-empty trace before treating\nServerBacktrace as having succeeded, so the empty case falls through\nto the existing in-process-backtrace and diagnostic-message fallback."
    },
    {
      "commit": "a24dd801712d0ab1df4a6858b93f148a01203ae7",
      "tree": "72d6c6b5283bba7475120eb1d7c1eae2ac4e3d9f",
      "parents": [
        "77725182a55f5248d3985d67a617c94478547619"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Fri Jul 03 08:10:06 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 03 08:10:06 2026 +0900"
      },
      "message": "Cleanup: remove unused functions related connect attempts (#13357)"
    },
    {
      "commit": "77725182a55f5248d3985d67a617c94478547619",
      "tree": "dd846e06aca0771bc8a4d5c1fc370572db9cb143",
      "parents": [
        "82c4de1609a7f25a4e9fbd71e5a7d07b24495ea7"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Thu Jul 02 16:05:01 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jul 02 16:05:01 2026 +0900"
      },
      "message": "Fix Proxy-Protocol log field symbols (#13345)"
    },
    {
      "commit": "82c4de1609a7f25a4e9fbd71e5a7d07b24495ea7",
      "tree": "c3daf4000aed419d97c7d8473a899885cc77dbef",
      "parents": [
        "18d7a9df2739ec6371203b4078d968c01c3ae6cc"
      ],
      "author": {
        "name": "Evan Zelkowitz",
        "email": "eze@apache.org",
        "time": "Wed Jul 01 15:26:43 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 01 15:26:43 2026 -0600"
      },
      "message": "Throttle OCSP cert-status error instead of logging on every handshake (#13312)\n\nssl_callback_ocsp_stapling() emitted an Error on every TLS handshake when\na cert\u0027s OCSP response was missing or expired, which could flood error.log.\nUse SiteThrottledError so ops are still alerted at Error severity but the\nmessage is rate-limited per call site (default 60s) with a suppressed-count.\n\nCo-authored-by: Evan Zelkowitz \u003ce_zelkowitz@apple.com\u003e"
    },
    {
      "commit": "18d7a9df2739ec6371203b4078d968c01c3ae6cc",
      "tree": "ac3af6472b49b0a19abe5ce1592144070a889ad9",
      "parents": [
        "8ef57470b86942dbf3641b75ff48d20d10a9f07a"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Mon Jun 29 11:06:21 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 29 11:06:21 2026 -0500"
      },
      "message": "Avoid JSONRPC client write spins (#13329)\n\nJSONRPC clients use nonblocking Unix sockets, so a full peer receive\nbuffer can make write return EAGAIN. The old retry loop treated that\nlike EINTR and immediately retried forever, which could hang the\njsonrpc server tests during large request and restart coverage.\n\nThis waits for socket write readiness before retrying transient\nbackpressure and reports ETIMEDOUT when the readiness wait expires,\nwhile preserving readiness poll errors. This also adds a regression\ntest that fills a socketpair and verifies that the helper returns with\nthat timeout signal instead of spinning."
    },
    {
      "commit": "8ef57470b86942dbf3641b75ff48d20d10a9f07a",
      "tree": "ede375d1b222e26cf28cd698285336990cc62192",
      "parents": [
        "a2c55e3dbe918b229981074c6c81a92b5534c88f"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jun 29 08:11:50 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 29 08:11:50 2026 -0500"
      },
      "message": "USDT: normalize names for STATE_ENTER (#13346)"
    },
    {
      "commit": "a2c55e3dbe918b229981074c6c81a92b5534c88f",
      "tree": "8131d7597d508b2046b525263aa1eaff1029e6f6",
      "parents": [
        "f31bfc58446886f24f297f0f500e56cc3b364213"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Fri Jun 26 19:49:09 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 26 19:49:09 2026 -0500"
      },
      "message": "Expand client IP debug logging test coverage (#13290)\n\nBefore this patch, the client ip debug logging test only covered one\nHTTP transaction, so regressions across protocols or persistent client\nsessions could pass unnoticed.\n\nThis converts the test to replay-driven coverage for HTTP, HTTPS, and\nHTTP/2, with an HTTP/3 scenario enabled when QUICHE is available. Each\nreplay sends multiple transactions on one client connection and checks\nthat all four request and response header dumps include per-transaction\nmarkers.\n\nThis test found no issues, thus this is a test-only patch."
    },
    {
      "commit": "f31bfc58446886f24f297f0f500e56cc3b364213",
      "tree": "3b7ab29be4811e51b6669b6a7e9424a2c0f69197",
      "parents": [
        "4fabae0c7299a45f4d448e9a8e6de0917b2416c9"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Fri Jun 26 08:18:26 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 26 08:18:26 2026 +0900"
      },
      "message": "Self-Describing Binary Log Format (v3) (#13231)\n\n* Self-describing binary log format (LogBuffer v3)\n\nPublish each field\u0027s type in a per-segment schema so a generic reader can\ndecode a .blog from the file alone, without an embedded ATS symbol-to-type\ntable that must track the writer in lockstep. The per-field code is\nLogField::Type serialized directly (now an enum class : uint8_t with INVALID\u003d0\nreserved and sINT..IP \u003d 1..4 as the frozen wire codes); a static_assert pins\nthe values. This relies on each field\u0027s declared type matching its marshalled\nframing, which the parent commit (\"Fix mismatched sINT/dINT log field types\")\nestablishes.\n\nReaders (LogBufferIterator, logcat, logstats, the ASCII output paths) accept\nboth v2 and v3 segments, sizing the header read to the on-disk version, so a v3\nbuild keeps decoding logs written by an older one. Integer values stay in host\nbyte order, as in v2 (no endianness change). The public TSLogType enum is given\nthe same values as LogField::Type so TSLogFieldRegister can static_cast between\nthem; static_asserts in InkAPI.cc (the only TU that sees both) pin the\nalignment so a future reorder fails to compile.\n\nThe writer version is per-LogObject: logging.yaml \"binary_log_version: 2\"\npins a binary log to the pre-v3 layout (no schema, shorter header) so a\nnot-yet-upgraded downstream parser keeps working during a migration; the\ndefault is v3.\n\nDecoding untrusted .blog input is bounded: LogBufferIterator validates\ndata_offset and each entry against the segment, and the JSON decoder validates\nthe schema offset alignment and cross-checks field_count against the symbol\nlist.\n\n* Address Copilot\u0027s comment\n\n* Address Copilot\u0027s comment\n\n* Cleanup\n\n* Fix logcat for AuTest\n\n* Range-check untrusted .blog offsets before pointer arithmetic\n\nfmt_fieldlist() and fmt_fieldtypes() form a pointer from a header\noffset read off disk; an out-of-range value makes the pointer\narithmetic undefined behavior even if never dereferenced. Guard\nboth against byte_count."
    },
    {
      "commit": "4fabae0c7299a45f4d448e9a8e6de0917b2416c9",
      "tree": "e5f3deacc152968987da26fdf0c15966edc3564d",
      "parents": [
        "3ce2acfbc6cf287e49638c4b054f48711c09a7e7"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Fri Jun 26 07:52:16 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 26 07:52:16 2026 +0900"
      },
      "message": "Annotate BRAVO locks for thread-safety analysis (#13330)\n\n* Annotate BRAVO locks for thread-safety analysis\n\nEnabling -Wthread-safety tree-wide surfaced findings in Bravo.h on\nmacOS, where libc++ marks the underlying std::shared_mutex as a\ncapability: the wrapper acquires and releases it across method\nboundaries and on fast/slow-path branches the analyzer cannot follow.\nFedora CI uses libstdc++, which does not annotate std types, so it\nnever saw these.\n\nMake ts::bravo::shared_mutex_impl a real capability so the contract is\nchecked on every Clang, not papered over on one std lib; its\nlock-driving bodies are the trusted implementation and stay exempted,\nmatching the ts::shared_mutex pattern. Make the reader guard a rigid\nscoped capability -- acquire in constructor, release in destructor,\nno copy/move/defer/release -- which the analysis tracks with no\nexemption; the movable std::shared_lock-style forms it replaced could\nnot be tracked, and no caller used them. Restructure the unit test\u0027s\ntry-lock asserts so the acquire gates a branch.\n\n* Reset BRAVO Token on entry to harden slow-path unlock\n\nlock_shared/try_lock_shared assigned the Token only on the fast path,\nso a reused non-zero Token surviving into a slow-path acquisition would\nmake unlock_shared release a reader slot instead of the underlying\nmutex. Clear it on entry to enforce the documented 0-init contract."
    },
    {
      "commit": "3ce2acfbc6cf287e49638c4b054f48711c09a7e7",
      "tree": "2532ec4d964ecbcb76437e60e5969e88a3d9de4e",
      "parents": [
        "87cf5ec24cedc2dd95a33fdb743f3421d10824a1"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Thu Jun 25 11:59:38 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 25 11:59:38 2026 -0500"
      },
      "message": "tests: add TLS gold tests (#13306)\n\nIncrease autest coverage with the following tests:\n\n- TLS renegotiation, rejected by default and allowed when configured\n- the TLS record-size clamp, checked against on-the-wire record sizes\n- a failed outbound TLS origin connection surfaced as a 5xx\n- a TLS origin that resets the connection mid-request-body"
    },
    {
      "commit": "87cf5ec24cedc2dd95a33fdb743f3421d10824a1",
      "tree": "f6c1949675bfed0a4375553495e090babc7fdb52",
      "parents": [
        "c179b6b9bbc0853d2a184296ec38a37b5032e4c4"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Thu Jun 25 09:44:40 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 25 09:44:40 2026 -0500"
      },
      "message": "Downgrade inbound H2 stream error log (#13316)\n\nMalformed client HTTP/2 streams can produce noisy error-level\ndiagnostics even though the malformed parse details are now available\nin transaction logs via apache/trafficserver#13059.\n\nThis downgrades the inbound rcv_frame stream-error diagnostic to\nHttp2StreamDebug while leaving outbound stream creation errors at Error\nlevel. This also updates the malformed request AuTest to look for the\ndebug diagnostic in traffic.out and relies on Http2StreamDebug to include\nthe session and stream identifiers."
    },
    {
      "commit": "c179b6b9bbc0853d2a184296ec38a37b5032e4c4",
      "tree": "eb7c994ec8378cce6cb32c053fb08dfc478720de",
      "parents": [
        "b85ebd8709ac16ca8cdae5372bab38fc7b90e148"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Thu Jun 25 09:44:00 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 25 09:44:00 2026 -0500"
      },
      "message": "slice_prefetch.test.py: address cache.log flakiness (#13322)\n\nBackground slice prefetch requests can log around the client\ntransactions. A run can therefore contain the expected cache records\nwhile still failing an ordered cache.log gold comparison.\n\nThis replaces the full-file gold comparison with per-entry log\nassertions that verify the expected cache and prefetch records\nindependently of ordering, then removes the unused gold file.\n\nFixes: #13311"
    },
    {
      "commit": "b85ebd8709ac16ca8cdae5372bab38fc7b90e148",
      "tree": "9b4813065fe0089a63fa2da3116588440055a12a",
      "parents": [
        "00adbb80764c2a91209d1090ba9b7562ee7ad375"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Wed Jun 24 23:13:31 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 23:13:31 2026 -0500"
      },
      "message": "TLS: Fix memory leaks in cert load and OCSP stapling (#13318)\n\nSeveral error and early-return paths in the TLS server certificate loading\nand OCSP stapling code omit cleanup and leak native objects.  Most are gated\non misconfiguration (bad or unreadable cert files) or allocation failure, so\nthey accumulate slowly rather than on every handshake.\n\n1. setClientCertCACerts leaked the X509_STORE when X509_STORE_load_locations\n   failed; the store is only adopted by SSL_set0_verify_cert_store on success.\n   This fires per handshake on the sni.yaml verify_client path when the CA\n   file or directory is bad.  It also now skips the load when X509_STORE_new\n   returns null, which would otherwise crash on allocation failure.\n2. SSLNetVConnection::populate leaked the migrated SSL object when the base\n   populate failed: the source VC has already relinquished ownership, so the\n   SSL must be freed when this VC does not adopt it.\n3. load_certs leaked the leaf certificate on the mid-chain failure returns\n   (bad intermediate chain, private key, or CA file).  The leaf is now held\n   in a scoped_X509 so every path releases it.\n4. _prep_ssl_ctx and SSLCreateServerContext leaked already-parsed leaves when\n   load_certs_and_cross_reference_names failed partway, because the X509_free\n   drain was skipped on the early return.\n5. set_session_id_context leaked the client CA name stack on the digest error\n   paths that run before ownership is handed to the SSL_CTX.\n6. ssl_callback_ocsp_stapling ignored the OCSP-response set result and leaked\n   the buffer on failure.  On BoringSSL it now uses SSL_set_ocsp_response,\n   which copies the cached buffer and needs no per-handshake allocation; on\n   OpenSSL it checks SSL_set_tlsext_status_ocsp_resp and frees on failure.\n7. stapling_refresh_response leaked the duplicated OCSP CERTID when\n   TS_OCSP_request_add0_id failed."
    },
    {
      "commit": "00adbb80764c2a91209d1090ba9b7562ee7ad375",
      "tree": "f10b673bcfad2da2e03b37e914954dbad6af2eb4",
      "parents": [
        "9fe25cef35e85fa0c9b2698bf03bf03f352430ee"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Wed Jun 24 20:43:27 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 20:43:27 2026 -0500"
      },
      "message": "Clarify HttpSM cache action cleanup (#13327)\n\nDescribe what cancel_pending_action() does in the Coverity suppression rationale. The helper cancels pending cache work and clears tracked pointers rather than only setting flags."
    },
    {
      "commit": "9fe25cef35e85fa0c9b2698bf03bf03f352430ee",
      "tree": "81da1f5ccf1a28aa5a03fdba51802a723e8f8f12",
      "parents": [
        "8f33dbf76b81e82ff541af58457619ed95e26f89"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Wed Jun 24 20:43:15 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 20:43:15 2026 -0500"
      },
      "message": "Fix stale_response FORCE_SIE enum (#13326)\n\nGive the FORCE_SIE test mode its own enum value so the stale-if-error rows are not aliases of FORCE_SWR. Add a load-time guard to catch future duplicate OptionType values before the autest runs."
    },
    {
      "commit": "8f33dbf76b81e82ff541af58457619ed95e26f89",
      "tree": "80174dc7abccc01fb0c95345da5a2b6c38b7ef2e",
      "parents": [
        "e8a0dd868edcb0185d38fc3570f8f0b0faf3a575"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Wed Jun 24 20:39:52 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 20:39:52 2026 -0500"
      },
      "message": "HttpSM.cc: fix cache read end milestone order (#13325)\n\nThe log-milestone-fields AuTest intermittently logged a valid\nTCP_MEM_HIT with hit_proc rendered as unset. That field is computed from\nTS_MILESTONE_UA_BEGIN_WRITE minus TS_MILESTONE_CACHE_OPEN_READ_END, so\nthe failing logs showed the client write-begin milestone could be\nobserved before the cache open-read end milestone on a fast cache-hit\npath.\n\nThe cache had already delivered the open-read result in\nstate_cache_open_read(), so that ordering pointed at milestone stamping\nrather than an actual cache sequencing problem.\nTS_MILESTONE_CACHE_OPEN_READ_END was marked after cache-open-read state\nhandling, and that handling can advance into cache serving and stamp\nTS_MILESTONE_UA_BEGIN_WRITE first.\n\nThis records TS_MILESTONE_CACHE_OPEN_READ_END in the terminal\ncache-open-read handling paths before they can advance to later\ntransaction milestones. The compatibility-key retry path is left\nunstamped so the retried lookup owns a coherent cache-read begin/end\npair."
    },
    {
      "commit": "e8a0dd868edcb0185d38fc3570f8f0b0faf3a575",
      "tree": "2fa63d6a8e7efbad1b332b84b04d257ba2179272",
      "parents": [
        "b8ada6fe06dd4e2161d8480a1a1fc75346a43153"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Wed Jun 24 20:38:37 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 20:38:37 2026 -0500"
      },
      "message": "pqsi-pqsp.test.py: address log order flakiness (#13321)\n\nThe miss and hit transactions can flush to the custom log in either\norder. A valid cache-hit result can therefore fail when only the first\nline is normalized before the full-file comparison.\n\nThis waits for both expected records, normalizes the variable client\nendpoint wherever it appears, and sorts the two-record output before\ncomparing it with the sorted gold file.\n\nFixes: #13319"
    },
    {
      "commit": "b8ada6fe06dd4e2161d8480a1a1fc75346a43153",
      "tree": "aa7f8b16b8bd3e4988a0c9ed1ec5043e14e21ac3",
      "parents": [
        "3b04db3474c674aa286c9b3406e00a649ea50783"
      ],
      "author": {
        "name": "Phong Nguyen",
        "email": "phongn@gmail.com",
        "time": "Wed Jun 24 10:34:59 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 12:34:59 2026 -0500"
      },
      "message": "Use ls-hpack\u0027s fast Huffman decoder for HPACK/QPACK strings (#13259)\n\nWhen the home-grown Huffman codec was replaced with vendored LiteSpeed ls-hpack code (#12357), only the conservative 4-bit FSM decoder (lshpack_dec_huff_decode_full) was ported — although huff-tables.h has carried the 64K-entry table for upstream\u0027s fast decoder all along. This PR ports the fast decoder (lshpack_dec_huff_decode, from ls-hpack v2.3.5) and switches huffman_decode() to it.\n\nThe fast decoder consumes 16 bits of input per table lookup and emits up to 3 bytes, falling back to the FSM decoder for the rare codes longer than 16 bits. HPACK and QPACK share the wrapper through xpack_decode_string(), so both HTTP/2 and HTTP/3 header decoding benefit. No new memory footprint: the hdecs table has been compiled into the binary since the original vendoring."
    },
    {
      "commit": "3b04db3474c674aa286c9b3406e00a649ea50783",
      "tree": "5090550ec18a1bf0593b75dc1bbd8626c61d4d93",
      "parents": [
        "2b6dce0314f32f95860fcef3acaef8397aeb2cc4"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Wed Jun 24 12:28:49 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 12:28:49 2026 -0500"
      },
      "message": "Fix redirected cache write without write VC (#13309)\n\nRedirected transactions can retain CACHE_WL_SUCCESS after the concrete\ncache write VC has been cleared. When a later response reaches cache\nwrite setup, we crash dereferencing the missing write VC.\n\nThis only reuses a redirected cache write when the prepared write VC is\nstill available. Otherwise, this resets the write state so ATS prepares\na fresh cache write. The added test simply adds some coverage around the\nscenario but is not a true regression test. That is, the test still\npasses without the src/ code change.\n\nThis addresses a crash in the cache write setup path:\n\n```\n#0 HttpSM::setup_cache_write_transfer(...)\n#1 HttpSM::perform_cache_write_action()\n#2 HttpSM::handle_api_return()\n#3 HttpSM::state_api_callout()\n#4 HttpSM::state_api_callback()\n#5 TSHttpTxnReenable()\n#6 EscalateResponse()\n```"
    },
    {
      "commit": "2b6dce0314f32f95860fcef3acaef8397aeb2cc4",
      "tree": "c8e0ca32506ed8b192e5db900e300f20a1c03282",
      "parents": [
        "e1a1f151783be8c1fb1d34fb93174a99ef66ff62"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Tue Jun 23 22:11:59 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 22:11:59 2026 -0500"
      },
      "message": "Introduce Clang Thread Safety Analysis, and apply it to two subsystems (#13310)\n\nAdd TS_* annotation macros (tsutil/ts_thread_safety.h) wrapping Clang\u0027s\n-Wthread-safety attributes, so a lock\u0027s contract -- which mutex guards\nwhich data, which lock a function requires its caller to hold -- can be\nexpressed in the type system and proved at build time. They expand to\nnothing off Clang: no runtime cost, and a no-op for GCC.\n\nAdd annotated lock types for the analysis to track: ts::mutex with\nts::lock_guard, and ts::shared_mutex (already ATS\u0027s own rwlock) marked\nas a capability with ts::write_guard / ts::read_guard. Annotated code\ntakes its locks through these because the std:: RAII wrappers are too\nflexible -- deferred locking, move, adopt/release -- for the analysis to\ntrack, and ATS does not need that flexibility. The guard names mirror\nstd::lock_guard\u0027s rigid acquire-in-constructor / release-in-destructor\nRAII rather than implying std::unique_lock\u0027s flexibility.\n\nAdd the ENABLE_THREAD_SAFETY_ANALYSIS option (Clang-only, on by default\nas a warning) and THREAD_SAFETY_ANALYSIS_AS_ERROR, which the CI and\nbranch presets enable so violations are errors that gate merges while\nlocal and dev builds stay warnings. Install the new headers with the\nrest of tsutil, and add a unit test compiled with the analysis enabled\nas a worked example. Skip FreeBSD: its libc annotates the pthread\nprimitives themselves, so -Wthread-safety there flags ATS\u0027s existing\nhand-rolled mutex wrappers (tscore/ink_mutex.h and others) tree-wide;\nbringing FreeBSD into the gate needs those legacy wrappers made\nanalysis-clean first.\n\nApply the analysis to two subsystems:\n\nMetrics::Storage: valid(), lookup(IdType) and name() read\n_cur_blob/_cur_off/_blobs with no lock held, while create()/createSpan()/\ncurrent() access the same fields under the mutex (rename() likewise read\nthem before locking). A single Storage is shared by all threads, so a\nmetric registered at runtime -- a plugin TSStatCreate or a config reload\n-- advances those fields while live traffic reads them: a data race.\nTake the mutex on every access and mark the fields guarded by it; the\nreads that were missing a lock take it exclusively, matching the existing\nlocked paths.\n\nSSLOriginSessionCache: the origin session map and queue are reachable\nfrom every thread; mark them guarded by the cache mutex so the compiler\nenforces the locking that was previously only convention. Replace the\nhand-rolled lock witness on remove_oldest_session (a std::unique_lock\nparameter checked with owns_lock()) with a compile-time TS_REQUIRES\nprecondition."
    },
    {
      "commit": "e1a1f151783be8c1fb1d34fb93174a99ef66ff62",
      "tree": "8b8f63fa3ec9407e648ca3383a04570b4794c2cd",
      "parents": [
        "6757a9e99a2d0b5f4e18590cbc8e7a41236757a4"
      ],
      "author": {
        "name": "Phong Nguyen",
        "email": "phongn@gmail.com",
        "time": "Tue Jun 23 16:57:55 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 08:57:55 2026 +0900"
      },
      "message": "Add in a vendor copy of Google Highway (#13228)"
    },
    {
      "commit": "6757a9e99a2d0b5f4e18590cbc8e7a41236757a4",
      "tree": "5ea3f65c18fb933053119332fff83046698fac5f",
      "parents": [
        "9ebcdd2c6d1f8bdf35f12fc40f0921d14a2c92b2"
      ],
      "author": {
        "name": "Phong Nguyen",
        "email": "phongn@gmail.com",
        "time": "Tue Jun 23 15:48:15 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 07:48:15 2026 +0900"
      },
      "message": "Fix LRU RAM cache seen filter never engaging below 100% full (#13234)\n\nproxy.config.cache.ram_cache.use_seen_filter values above 1 are\ndocumented to turn on the seen filter once the cache is (N-1)/N full\n(2 \u003d 50%, 3 \u003d 67%, ... 9 \u003d 90%). The threshold was written as\nbytes \u003e\u003d max_bytes * (1 - (1 / N)) with N an int, so 1 / N is integer\ndivision and evaluates to 0 for every N \u003e 1; the test became\nbytes \u003e\u003d max_bytes and the filter only engaged when completely full.\nA scan could therefore pollute a half-full cache.\n\nRewrite the comparison as bytes * N \u003e\u003d max_bytes * (N - 1), which is\nexact in integer arithmetic and overflow-safe at realistic cache\nsizes. Add ram_cache_lru_seen_filter, which fails on the old form\n(20/20 unseen keys admitted at 60% full) and passes on the fix (0/20).\n\nCo-authored-by: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "9ebcdd2c6d1f8bdf35f12fc40f0921d14a2c92b2",
      "tree": "4c320137ab710f91d5ed33297b16753dc1f5a0f5",
      "parents": [
        "edc35b31ca3888483f0475d4139c8a6917ebd9fa"
      ],
      "author": {
        "name": "Phong Nguyen",
        "email": "phongn@gmail.com",
        "time": "Tue Jun 23 15:46:51 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 07:46:51 2026 +0900"
      },
      "message": "Update FastLZ to b1342da (#13230)\n\n* Update FastLZ to b1342da\n\n* Add copyright to the NOTICE"
    },
    {
      "commit": "edc35b31ca3888483f0475d4139c8a6917ebd9fa",
      "tree": "898249363e90bbc40c2b3bee28058f51ec6a1daa",
      "parents": [
        "bdb24cfd93e1c6e9a27a4d03b126121d085596da"
      ],
      "author": {
        "name": "Phong Nguyen",
        "email": "phongn@gmail.com",
        "time": "Tue Jun 23 15:36:48 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 24 07:36:48 2026 +0900"
      },
      "message": "Add S3-FIFO RAM cache eviction algorithm (ram_cache.algorithm \u003d 2) (#13255)\n\n* Add S3-FIFO RAM cache eviction algorithm (ram_cache.algorithm \u003d 2)\n\nS3-FIFO (Yang et al., SOSP 2023) is a FIFO-based eviction policy: a\nsmall admission queue and a main queue (a 2-bit clock), plus a ghost\nqueue of recently evicted keys. The small queue and ghost filter\none-hit-wonders, giving scan resistance and strong hit rates on CDN\nand key-value workloads at low cost -- a hit needs no list reordering.\n\nSelectable as ram_cache.algorithm \u003d 2 alongside CLFUS (0) and LRU (1).\nThe policy is byte-budgeted; its eviction metadata (the ghost included,\nbounded by object size and an entry-count cap) is accounted within\nram_cache.size so total memory stays within the configured budget. Like\nLRU and CLFUS it enforces one resident copy per key (a put with a new\naux key discards the stale one) and allocates entries from a per-thread\nProxyAllocator (Thread.h).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e\n\n* Fix ghost capacity calculation truncation order\n\nCo-authored-by: Copilot Autofix powered by AI \u003c175728472+Copilot@users.noreply.github.com\u003e\n\n* Make S3-FIFO RAM cache tunables configurable via records.yaml\n\nThe S3-FIFO queue split, ghost bounds, and promotion threshold were\ncompile-time constants. Expose them as\nproxy.config.cache.ram_cache.s3fifo.{main_percent,ghost_size_percent,\nghost_mem_percent,promote_threshold} so operators can tune the policy\nwithout a rebuild; the defaults match the paper and the prior behavior.\n\nEach setting carries a RECC_INT range in RecordsConfig.cc, so an\nout-of-range value is rejected at config load with a warning and the\ndocumented default is used in its place -- the same guard every other\nRAM cache record relies on, rather than a bespoke clamp. The admin\nguide and the ram_cache regression test (a non-default \"tuned\" pass)\nare updated to cover the new settings.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e\n\n* Add entry for S3-FIFO into NOTICE\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Copilot Autofix powered by AI \u003c175728472+Copilot@users.noreply.github.com\u003e"
    },
    {
      "commit": "bdb24cfd93e1c6e9a27a4d03b126121d085596da",
      "tree": "7b3cb5d5b9531aa3b7de237a526e223257901484",
      "parents": [
        "f097d9214b64087295df4e0e18109da07007ecd5"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Tue Jun 23 16:59:35 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 16:59:35 2026 -0500"
      },
      "message": "Fix set-status crash inside if/endif at remap time (#13052)"
    },
    {
      "commit": "f097d9214b64087295df4e0e18109da07007ecd5",
      "tree": "04100a6ab8446341fd3afa278b7604ff3e71eabe",
      "parents": [
        "ad5728ca9c4b7f84abc5ce5a95bb17396b3a975a"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 16:54:36 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 16:54:36 2026 -0500"
      },
      "message": "Revert \"Downgrade H2 stream error log (#13298)\" (#13315)\n\nThis reverts commit b79c0f824aa96340f8a3bf3e77211489b77d512a.\n\nClaude noticed that there are two messages like this, and this is the wrong one. I thought \"new_transaction\", chosen by Codex, made sense. But we really want the one in Http2ConnectionState::rcv_frame for inbound client errors."
    },
    {
      "commit": "ad5728ca9c4b7f84abc5ce5a95bb17396b3a975a",
      "tree": "181ef231b02eb56910184ad26062f283aa922a04",
      "parents": [
        "bd785f4bd79194836985d01c7637cd6bd45a3c5d"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 14:30:28 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 14:30:28 2026 -0500"
      },
      "message": "Fix pending HostDB DNS queue removal race (#13294)\n\nA crash was observed while HostDB was probing pending DNS state for a\nrequest, with the stack unwinding through the DNS lookup path:\n\n    #4 swoc::bwf::ExternalNames::operator()(...)\n       at libswoc_1.5.15/include/swoc/bwf_base.h:610\n    #7 HostDBContinuation::do_dns(...)\n       at src/iocore/hostdb/HostDB.cc:1352\n    #11 probe(...)\n       at src/iocore/hostdb/HostDB.cc:581\n\nThe core showed an obviously corrupted ExternalNames this pointer while\nHostDB was allocating a continuation from the pending DNS path. The local\nsignal cleanup path could edit the pending-DNS queue without the bucket\nlock, leaving stale revalidation readers able to walk links while they\nwere being changed.\n\nThis routes that cleanup through the locked pending-DNS removal helper\nand uses its result to decide whether the continuation still owns\nself-cleanup. This keeps queue membership checks and removals\nsynchronized without changing the timeout path\u0027s lifetime behavior."
    },
    {
      "commit": "bd785f4bd79194836985d01c7637cd6bd45a3c5d",
      "tree": "b8e61eafe81b91108f8c0c632c9ef69192a7d3b2",
      "parents": [
        "70bb3c1281c406ea2cf7a573182177efade1f498"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Tue Jun 23 13:30:47 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 13:30:47 2026 -0500"
      },
      "message": "Use fixture listener in test_EventSystem (#13308)\n\nThis removes the Catch2 listener from test_EventSystem.cc, using\nthe identical listener from inkevent_test_fixtures.h instead.\n\nThere is a similar listener in the IOBuffer test, but it is not an\nexact duplicate (it calls `LibRecordsConfigInit`)."
    },
    {
      "commit": "70bb3c1281c406ea2cf7a573182177efade1f498",
      "tree": "7a94b750ec1e1827a0981ac633c7612a56626aac",
      "parents": [
        "468e76405a932efa55332a9ff70745e0a04c3b35"
      ],
      "author": {
        "name": "Masakazu Kitajo",
        "email": "maskit@apache.org",
        "time": "Tue Jun 23 12:27:35 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:27:35 2026 -0600"
      },
      "message": "Add cache mechanism to certificate compression (#13284)\n\n* Add cache mechanism to certificate compression\n\nCurrent implementation recompressed the cert chain on every TLS\nhandshake. Now cached on the first handshake per certificatees.\nCash gets invalidated when the OCSP staple refreshes.\n\nNew setting: proxy.config.ssl.server.cert_compression.cache (default 1).\nBoringSSL only -- OpenSSL caches internally with no opt-out, so the\nflag has no effect there.\n\n* Check TS_HAS_CERT_COMPRESSION_CALLBACKS instead of TS_HAS_CERT_COMPRESSION\n\n* Address copilot comments\n\n* Address copilot comments\n\n* Address copilot comments\n\n* Address copilot comments\n\n* Address unused param warnings"
    },
    {
      "commit": "468e76405a932efa55332a9ff70745e0a04c3b35",
      "tree": "4c56647d2d234d4076eb010bb4d886a249dc0aa6",
      "parents": [
        "094c755d7d2c503187e569a5df0d047453573125"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 12:57:58 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:57:58 2026 -0500"
      },
      "message": "redo_cache_lookup: move to examples; fix `fallback` lifetime (#13209)\n\nThe redo_cache_lookup plugin kept the fallback URL as a pointer into\nthe plugin.config argv storage. That storage can be released after\nplugin initialization, leaving cache-lookup-complete callbacks to\ndereference stale memory.\n\nThis copies the parsed fallback URL into plugin-owned storage and\npasses its owned bytes to TSHttpTxnRedoCacheLookup.\n\nAlso, while investigating this, it looks like this plugin was made\nsimply to demonstrate the use of TSHttpTxnRedoCacheLookup rather than\nbeing a production-useful plugin. The initial commit says as much and\nthere is no customer-facing documentation for this plugin. As such, I\u0027m\nmoving this to the examples plugin."
    },
    {
      "commit": "094c755d7d2c503187e569a5df0d047453573125",
      "tree": "9618a267a3efdf1f8ab040aba2a769fa80b37c61",
      "parents": [
        "46413e8303cd8467c4f8267fb529e00e0472b58e"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 12:57:11 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:57:11 2026 -0500"
      },
      "message": "Add TSMutex lock guard (#13188)\n\nPlugin code that protects small critical sections with TSMutex has to pair\nevery early return with a matching unlock. That pattern is easy to get wrong\nand makes the intended lock lifetime harder to see.\n\nThis adds a small TSMutexLockGuard helper to the plugin API and uses it in\nplugin code where the mutex naturally stays locked until a return path."
    },
    {
      "commit": "46413e8303cd8467c4f8267fb529e00e0472b58e",
      "tree": "a1a68bff4f1d48aef7a53bd35af8c92faf60d191",
      "parents": [
        "a8daf9994faba16c3b4cbfe21e724d048124731f"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 12:56:43 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:56:43 2026 -0500"
      },
      "message": "header_rewrite: Improve URL Error messages (#13261)\n\nOld log:\nERROR: [header_rewrite] Rule not supported at this hook\n\nNew log:\nERROR: [header_rewrite] Rule not supported at hook\u003dTS_HTTP_READ_RESPONSE_HDR_HOOK: %{TO-URL:URL} in /tmp/sb/header_rewrite_unsupported_url_hook/unsupported_url_hook.conf:18"
    },
    {
      "commit": "a8daf9994faba16c3b4cbfe21e724d048124731f",
      "tree": "89faa62a0eb6c1d58e5e9e8f9ea14df7bfd53268",
      "parents": [
        "b79c0f824aa96340f8a3bf3e77211489b77d512a"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 12:56:05 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:56:05 2026 -0500"
      },
      "message": "Fix server entry cleanup after request tunnel setup (#13295)\n\nA crash was observed while an HTTP/2 stream finished sending an\norigin request header and started the client request body tunnel:\n\n    #0 HttpSM::state_send_server_request_header(...)\n       at src/proxy/http/HttpSM.cc:2176\n    #1 HttpSM::main_handler(...)\n       at src/proxy/http/HttpSM.cc:2731\n    #5 Http2Stream::signal_write_event(...)\n       at src/proxy/http2/Http2Stream.cc:954\n\nThe core had server_entry \u003d\u003d nullptr at the vc_type check after the\nrequest-body tunnel setup. The tunnel can synchronously abort the chain\nand clean up the server VC before returning.\n\nThis checks whether the server entry still exists after setting up the\nrequest body tunnel or transform tunnel. When setup already cleaned it\nup, the state handler stops before installing a response-read handler\non a null entry."
    },
    {
      "commit": "b79c0f824aa96340f8a3bf3e77211489b77d512a",
      "tree": "881ee32cf44d9276eba705620217cd448640d66e",
      "parents": [
        "422d770f3fe29f47f21695c2a1346835ea9a93a3"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 12:55:14 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:55:14 2026 -0500"
      },
      "message": "Downgrade H2 stream error log (#13298)\n\nMalformed HTTP/2 parse errors can hit this path during normal\nbad-client traffic, and logging each one at ERROR keeps diags noisy.\nPR #13059 now emits transaction log entries for these malformed\nrequests, so operators can diagnose the rejected request without this\ndefault error log noise.\n\nThis downgrades the stream creation failure message to the existing\nHTTP/2 session debug path. Operators can still enable the http2_cs\ndebug tag when they need the protocol-level detail."
    },
    {
      "commit": "422d770f3fe29f47f21695c2a1346835ea9a93a3",
      "tree": "705b64fce390a5881d10094e03f7c62348e6ec57",
      "parents": [
        "4c69f8582b3005fca44c79d5fc0f189f032ddb72"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 23 12:43:51 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 12:43:51 2026 -0500"
      },
      "message": "Test TLS async without ENGINE (#13264)\n\nSome OpenSSL builds expose the async APIs ATS needs while disabling\nthe legacy ENGINE interface. The previous async handshake coverage\ndepended on a test-only dynamic ENGINE just to make OpenSSL suspend\nduring the TLS handshake, leaving those builds without the async-path\nAuTest coverage.\n\nThis replaces the ENGINE plugin with a test plugin that pauses the\ncurrent OpenSSL async job from a TLS certificate hook. This keeps the\ntest focused on ATS\u0027s SSL_ERROR_WANT_ASYNC handling while avoiding the\ndeprecated ENGINE API and dynamic ENGINE availability checks."
    },
    {
      "commit": "4c69f8582b3005fca44c79d5fc0f189f032ddb72",
      "tree": "17e7e82a87396e87b1767c2e503abaf40a7b893c",
      "parents": [
        "990bd049aa67b2293c3334f8a28b9f80c2eb650b"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jun 22 22:17:49 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 22 22:17:49 2026 -0500"
      },
      "message": "ci: modernize the coverage helper script (#13305)\n\nRework ci/coverage to drive an out-of-source CMake build and an optional\nautest run (AUTEST\u003d\u0027*/tls/*\u0027 or AUTEST\u003dall) when gathering coverage, and\nreport via gcov/gcovr."
    },
    {
      "commit": "990bd049aa67b2293c3334f8a28b9f80c2eb650b",
      "tree": "6335b91bac1b2afbb259407e82de57e8b06c1610",
      "parents": [
        "9b098746d75c6c88a35c519f48b45fb901b0f348"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jun 22 17:46:30 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 22 17:46:30 2026 -0500"
      },
      "message": "Add per-plugin workload counters (#13278)\n\nAdd per-plugin metrics that allow us to track how much work each plugin is doing\nby counting their invocations, intercept bytes, and intercept transfers.\n\nAdd proxy.process.plugin.\u003cname\u003e.{invocations,bytes, transfers}, keyed by the\nplugin DSO basename and bounded by the number of loaded plugins.\n\nGlobal plugins load via raw dlopen and previously carried no identity, so they\nare given a PluginThreadContext around TSPluginInit; the continuations they\ncreate then carry plugin identity the same way remap plugins already do."
    },
    {
      "commit": "9b098746d75c6c88a35c519f48b45fb901b0f348",
      "tree": "af6d77567e92972eeb21a3256f712a1bad0ee798",
      "parents": [
        "ec72cf41dadf4876be0e83addbb91d8ddf104290"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Mon Jun 22 17:43:27 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 22 17:43:27 2026 -0500"
      },
      "message": "dns: destruct HostEnt on free to fix SRV vector leak (#13307)\n\ndnsBufAllocator used ClassAllocator\u003cHostEnt, false\u003e, so freeing a\nHostEnt skipped its destructor. HostEnt embeds an SRVHosts whose\nstd::vector\u003cSRV\u003e owns heap storage, and alloc() placement-news a\nfresh empty vector over the recycled block, orphaning the previous\nbuffer. Each recycle of a HostEnt that held SRV records leaked one\nvector buffer.\n\nUse the default Destruct_on_free\u003dtrue so ~HostEnt runs on free."
    },
    {
      "commit": "ec72cf41dadf4876be0e83addbb91d8ddf104290",
      "tree": "706f129b2e0f0ea9788c88cddd0a30ffd6567f00",
      "parents": [
        "a344dec29c5463f5b6d3f4dba5c61947b50fd94c"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Tue Jun 23 06:59:49 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 06:59:49 2026 +0900"
      },
      "message": "cache: apply per-volume settings on first start after clear (#13252)\n\nPer-volume tuning (ram_cache, ram_cache_size, ram_cache_cutoff,\navg_obj_size, fragment_size) was only copied onto the CacheVol when\nmatching an existing on-disk volume, so volumes created fresh (e.g.\nthe first start after a cache clear) ignored the config until the\nnext restart. Apply the settings in one pass after all CacheVols\nexist.\n\nExtend cache_volume_features to verify the settings take effect via\nper-volume metrics."
    },
    {
      "commit": "a344dec29c5463f5b6d3f4dba5c61947b50fd94c",
      "tree": "34e3af42af728991df820315bab1d4e6d5acdae7",
      "parents": [
        "1e109ce2d47d6a7c523d8116afc265699ff686d5"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Mon Jun 22 12:54:38 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 22 12:54:38 2026 -0500"
      },
      "message": "Add unit tests for `Continuation` logic (#13283)\n\n* Add unit tests for `Continuation` logic\n\nThis change was generated by Claude Opus 4.7 from API contracts I have not yet\nopened PRs for. It does not touch existing files other than one CMakeLists.txt,\nso it is low-risk.\n\nI reviewed each test case and they are good. I have not reviewed code semantics\ncarefully for correctness. The default delay for the `CountingContinuation` wait\nis five seconds; I think a wait with a timeout is an acceptable way to test\nthis, and five seconds should be plenty. If an event scheduled to run immediately\ndoesn\u0027t call back the associated continuation within five seconds, that\u0027s\nprobably unacceptable performance and worth failing the test for. :D"
    },
    {
      "commit": "1e109ce2d47d6a7c523d8116afc265699ff686d5",
      "tree": "242b8793949b34ddf61c5cf6d8d1028193ca6683",
      "parents": [
        "8e36c2810315953af8fca88f5f666ebfb4c5c247"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jun 20 20:58:40 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 20:58:40 2026 -0500"
      },
      "message": "compress: count uncompressed input bytes (#13287)\n\nAdd proxy.process.plugin.compress.bytes_in to track the volume of data the\ncompress plugin processes.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "8e36c2810315953af8fca88f5f666ebfb4c5c247",
      "tree": "bf4d587e3418245ee843340a11dd59484418eb36",
      "parents": [
        "c6ec3adbb3e44ee47068112b16908e54cc6b22d7"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jun 20 16:01:50 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 16:01:50 2026 -0500"
      },
      "message": "net: count application bytes in read_bytes for TLS (#13282)\n\nOn TLS connections, net.read_bytes was only counting some bytes for the\nhandshake, and none of the incoming ciphertext.  This is neither intuitive\nnor consistent with net.write_bytes.\n\nThe fix for now is to make it symmetric with net.write_bytes.  Count the\nplaintext bytes for TLS.  This means not counting the handshake bytes.\n\nFor a long term fix, I plan to add more comprehensive metrics for TLS."
    },
    {
      "commit": "c6ec3adbb3e44ee47068112b16908e54cc6b22d7",
      "tree": "cad19b9e99a60decda6b3b81dd8ebce80153aac7",
      "parents": [
        "9eac80fc2d9af95cd37716dceed39e4bfe58c5e2"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jun 20 16:00:53 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 16:00:53 2026 -0500"
      },
      "message": "header_rewrite: count operators and conditions run (#13286)\n\nThe per-hook invocation count cannot tell a small ruleset from a large one,\nso it does not reflect how much work header_rewrite does per transaction.\nAdd proxy.process.plugin.header_rewrite.{operators,conditions}, incremented\nin the inline Operator::do_exec and Condition::do_eval chain walkers, to make\nthat workload visible.  do_eval short-circuits, so only conditions actually\nevaluated are counted.  The counters are created once, from both TSPluginInit\nand TSRemapInit."
    },
    {
      "commit": "9eac80fc2d9af95cd37716dceed39e4bfe58c5e2",
      "tree": "e690ac6d774f9472913651fb8a831bf4a603e5e0",
      "parents": [
        "92112e1b8ac31030c150f321e98392e7766b503f"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jun 20 15:59:54 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 15:59:54 2026 -0500"
      },
      "message": "tools/clang-format.sh: cache clang-format in the common git dir (#13302)\n\nclang-format.sh located its download cache with `git rev-parse\n--absolute-git-dir`, which in a linked worktree is the per-worktree git\ndir (.git/worktrees/\u003cname\u003e) rather than the shared .git.  clang-format\nis installed once under the common dir, so in a worktree the pre-commit\nhook and the format target could not find it and failed with \"No\nclang-format found\".\n\nResolve the common git dir instead, matching how CMakeLists.txt already\ncomputes GIT_COMMON_DIR.  It is made absolute with `cd ... \u0026\u0026 pwd`\nrather than `git rev-parse --path-format\u003dabsolute`, avoiding a\ndependency on git 2.31+; that --path-format form was removed in #11495\nover a cmake 3.28 incompatibility.\n\nThe no-argument default target now uses `git rev-parse --show-toplevel`\nso a bare run inside a worktree formats that worktree, not the main\ncheckout.\n\nCo-authored-by: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "92112e1b8ac31030c150f321e98392e7766b503f",
      "tree": "3ea220a3a0e4e4555763d9764be93d0c5ac1439b",
      "parents": [
        "a17e04af3b5c7bf6803daecd579fa40fda038ab8"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jun 20 08:54:42 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 08:54:42 2026 -0500"
      },
      "message": "header_rewrite: Fix a leak and truncation in set-body-from (#13303)\n\nTwo related fixes in the header_rewrite set-body-from operator\u0027s createRequestString():\n\nMemory leak. The request URL was fetched with TSUrlStringGet(), which returns a TSmalloc()-allocated buffer the caller owns, but it was never freed. Every non-internal transaction matching a set-body-from rule leaked one URL-sized allocation, growing unbounded over time. Free it, mirroring the existing owned-pointer handling in ConditionUrl.\n\nTruncation / buffer over-read. snprintf() returns the length it would have written, not the number of bytes actually written, and that value can exceed the 256-byte req_buf. Passing it to TSFetchUrl() as the request length reads past the stack buffer when a URL overflows. The request has always been capped at 256 bytes — snprintf() only ever writes that much into req_buf — so this changes nothing for requests that fit; it just returns TS_ERROR on overflow instead of over-reading. (Raised by Copilot review.)"
    },
    {
      "commit": "a17e04af3b5c7bf6803daecd579fa40fda038ab8",
      "tree": "47ec0314b69fa9904e6225dd2c77ece0ad11bf3e",
      "parents": [
        "7766ce2cc9a8e58a247201d6a3ce7b1d3e895a59"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Sat Jun 20 08:46:43 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 08:46:43 2026 -0500"
      },
      "message": "tests: give cripts ATS startup a longer readiness window (#13304)"
    },
    {
      "commit": "7766ce2cc9a8e58a247201d6a3ce7b1d3e895a59",
      "tree": "59664d70b50620a683eac2010e2bb9af609a5280",
      "parents": [
        "46346ba4020f15a1e8e2e92b43baa51bf6df0f31"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Fri Jun 19 17:45:42 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 17:45:42 2026 -0500"
      },
      "message": "TLS: count handshake signatures by key type (#13289)\n\nA full TLS handshake runs an asymmetric signature whose cost depends on the\nserver key type -- RSA being far heavier than ECDSA.  Count those signatures\nby key type to make that work visible; resumed handshakes skip the signature.\n\nAlso add proxy.process.ssl.connections_closed, incremented once per SSL_free,\nto track TLS connection teardown volume.\n\nNew counters:\n  * proxy.process.ssl.handshake_sign_rsa / _ecdsa / _other\n  * proxy.process.ssl.connections_closed"
    },
    {
      "commit": "46346ba4020f15a1e8e2e92b43baa51bf6df0f31",
      "tree": "bb84ccc2423fa16379993bb470ff70fc8f23220a",
      "parents": [
        "70859231d86c384dd8b038e0a58a280c274bf8a9"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Fri Jun 19 12:53:42 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 12:53:42 2026 -0500"
      },
      "message": "logging: add a marshalled-bytes counter (#13277)\n\nAdds proxy.process.log.marshalled_bytes, a counter that helps with estimating the cost of logging on an ATS instance."
    },
    {
      "commit": "70859231d86c384dd8b038e0a58a280c274bf8a9",
      "tree": "8e3710af6e28d4793dd8017bd8ac00c50d0228a7",
      "parents": [
        "3c000b304dea10dac2b7fb66c08e09a61c72e8dc"
      ],
      "author": {
        "name": "Damian Meden",
        "email": "dmeden@apache.org",
        "time": "Fri Jun 19 11:06:35 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 11:06:35 2026 +0200"
      },
      "message": "Add `Test.AddConfigReload()` autest extension (#13075)\n\n* Add Test.AddConfigReload() autest extension\n\nReplace the fragile pattern of fire-and-forget `traffic_ctl config\nreload` followed by sleep/log-grepping with a deterministic helper\nthat uses monitor mode (`-m`) to block until completion and validates\nreload tasks via the get_reload_config_status JSONRPC endpoint.\n\nThe extension supports expected exit codes (success/fail/timeout/any),\ntask presence and absence assertions, per-task status validation,\ncustom tokens, and a delay_start parameter for filesystem timestamp\nsensitivity.\n\nMigrate 21 existing tests to use the new helper, removing manual\nsleep synchronization and When.FileContains polling. Add an optional\nfilename parameter to ConfigReloadTask so sub-tasks carry their\nassociated config file for precise identification in test assertions.\n\nIncludes RST documentation for the new extension API.\n\n\nts::time_parser accepts space-separated duration strings like\n\"11 hours 30m\", but without shell quoting, such values would be split\ninto multiple argv tokens and break the reload command. Apply\n_shell_quote consistently (matching token and data handling right\nabove).\n\n* Address some PR comments.\n- remove wait_reload.sh\n- include ssl multicert filename on quic reload handling."
    },
    {
      "commit": "3c000b304dea10dac2b7fb66c08e09a61c72e8dc",
      "tree": "87832a84a34cef6aedcb8deb83ede82d6eb3ff55",
      "parents": [
        "95a13a552d02a5f4621a3c10127b7f16b4b47780"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Fri Jun 19 07:23:52 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jun 19 07:23:52 2026 +0900"
      },
      "message": "traffic_crashlog: fix false-positive crash logs on clean shutdown (#13296)\n\n* traffic_crashlog: fix false-positive crash logs on clean shutdown\n\nThe crash log helper is parked with SIGSTOP and armed with\nPR_SET_PDEATHSIG\u003dSIGCONT, so the kernel resumes it whenever\ntraffic_server exits, not only on a crash. It used getppid() to tell a\ncrash from a plain exit, but that is racy: PR_SET_PDEATHSIG fires on the\nforking thread\u0027s death, which can occur while the parent pid is still\nalive, so a normal SIGTERM shutdown could emit an empty crash log.\n\nReplace the getppid() guess with a socket handshake: a real crash writes\nthe signal number to the helper, while any other exit closes the socket\nso the helper reads EOF and exits quietly. FD_CLOEXEC keeps that EOF\nreliable against later fork+exec children.\n\n* Address Copilot\u0027s comment"
    },
    {
      "commit": "95a13a552d02a5f4621a3c10127b7f16b4b47780",
      "tree": "6cecf872ed2f541eaf23955e1552b04bb71371f3",
      "parents": [
        "2441fa711474b334e66b376e78b1a333a5e6041b"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Thu Jun 18 16:13:16 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 18 16:13:16 2026 -0500"
      },
      "message": "ProxyProtocol: free pp_info heap on NetVConnection recycle (#13293)\n\nNetVConnection embeds a ProxyProtocol by value, and a PROXY v2 header parsed\nby has_proxy_protocol() heap-allocates ProxyProtocol::additional_data (the TLV\nblob) plus the tlv map. The NetVConnection ClassAllocators are\nDestruct_on_free\u003dfalse, so ~ProxyProtocol never runs when a VC is recycled and\nUnixNetVConnection::clear() did not release pp_info -- the next placement-new on\nthe recycled slot abandoned the buffer and map nodes, leaking once per recycled\nconnection that carried a PROXY v2 header. Behind a PROXY-protocol load\nbalancer that is every inbound connection.\n\nAdd ProxyProtocol::reset() and call it from UnixNetVConnection::clear() (the\nsingle recycle chokepoint for the Unix, SSL and QUIC VCs). reset() swaps the\nmembers with empty containers rather than clear()ing them, because clear()\nretains capacity that the recycle would still abandon.\n\nCo-authored-by: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "2441fa711474b334e66b376e78b1a333a5e6041b",
      "tree": "a8bdae511b4646b0c28c627f72ce10e5a0657092",
      "parents": [
        "309d832ddf1874bbe7b672b274b3a5c89328621c"
      ],
      "author": {
        "name": "Serris Santos",
        "email": "serrisnlew@gmail.com",
        "time": "Thu Jun 18 12:31:47 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 18 12:31:47 2026 -0700"
      },
      "message": "Cripts: make URL::Query copyable via deep-copy of _state (#13269)"
    },
    {
      "commit": "309d832ddf1874bbe7b672b274b3a5c89328621c",
      "tree": "7deaf707730164d532c929bef034bc84b4574b8f",
      "parents": [
        "4b6f79035141c3904c889ff83f0b68dff5209f53"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Thu Jun 18 10:41:21 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 18 10:41:21 2026 -0500"
      },
      "message": "Fix txn_box unused find result (#13291)\n\nClang 22 treats the ignored std::unordered_map::find result in the\ntxn_box unit perf test as a warning, and the project builds with\nwarnings promoted to errors. The test therefore fails to compile even\nthough the lookup is intentionally only being timed.\n\nThis explicitly discards the lookup result in the benchmark lambda and\ncorrects the printed label to describe the lookup operation."
    },
    {
      "commit": "4b6f79035141c3904c889ff83f0b68dff5209f53",
      "tree": "0c54ffc89b823c1e4dd743132bdbc8b977cbe49a",
      "parents": [
        "fb102991e75c89ec846d7c2f37667b4ba7f39650"
      ],
      "author": {
        "name": "Bryan Call",
        "email": "bcall@apache.org",
        "time": "Wed Jun 17 08:23:16 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 17 08:23:16 2026 -0700"
      },
      "message": "Fix incorrect errno short names on FreeBSD/macOS in bwf::Errno (#13240)\n\nbwf::Errno used a single Linux-numbered table indexed by raw errno, so\nother platforms printed the wrong name (e.g. ETIMEDOUT\u003d60 logged as\nENOSTR on FreeBSD/macOS). Replace it with a per-platform table built\nfrom each OS\u0027s \u003cerrno.h\u003e, add guarded tests, and #error on unsupported\nplatforms."
    },
    {
      "commit": "fb102991e75c89ec846d7c2f37667b4ba7f39650",
      "tree": "46fd2a4d6056c478a6358d8321c1b73b8afb0f94",
      "parents": [
        "113f5fbb1667df56799e9878c71d6cd286695a49"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Wed Jun 17 06:52:12 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jun 17 06:52:12 2026 +0900"
      },
      "message": "Fix connect attempt retries (#13102)\n\n* Fix connect attempt retries\n\n* Fix table format"
    },
    {
      "commit": "113f5fbb1667df56799e9878c71d6cd286695a49",
      "tree": "14bb1c76985902cede56cd5fcb3b357bde25bf3a",
      "parents": [
        "1a10d127a7dee3eb73abaaec3322ab871c9c54af"
      ],
      "author": {
        "name": "Mo Chen",
        "email": "mochen@apache.org",
        "time": "Tue Jun 16 13:08:27 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 13:08:27 2026 -0500"
      },
      "message": "Fix hdrHeap/hdrStrHeap allocator inuse metric underflow (#13218)\n\nThe hdrHeap and hdrStrHeap allocators are plain Allocator globals whose\nobjects are allocated with no constructor arguments, so THREAD_ALLOC\nresolves to the non-templated thread_alloc(Allocator \u0026, ProxyAllocator \u0026)\noverload. Unlike the templated overload, it did not call\nincrement_for_alloc() when reusing an object from the per-thread\nfreelist, while THREAD_FREE always decremented inuse on the way in.\n\nThe counted frees therefore outran the counted allocs and\nproxy.process.allocator.inuse.{hdrHeap,hdrStrHeap} marched negative,\nwrapping around as a huge uint64 value. Other allocators use\nClassAllocator (the templated path) and were unaffected.\n\nAccount for the freelist reuse in the non-templated overload so the two\npaths stay symmetric, and add a regression test that cycles a block\nthrough the freelist and asserts inuse stays balanced and never dips\nbelow its starting value.\n\nCo-Authored-By: Claude Opus 4.8 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "1a10d127a7dee3eb73abaaec3322ab871c9c54af",
      "tree": "9a72e5ce5144a4a4290be6d6c14486fed1990e10",
      "parents": [
        "52a124bcd543f6889ba26af582a9d9927b7f7e6e"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Tue Jun 16 12:30:22 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 12:30:22 2026 -0500"
      },
      "message": "Remove TsBuffer.h (#13281)\n\nFixes #1570.\n\nThis removes the unused `ConstBuffer` class. The header was not\nincluded anywhere. The only mention of `ConstBuffer` in the docs\nis in the history of `TextView`. Therefore, that mention has\nbeen preserved."
    },
    {
      "commit": "52a124bcd543f6889ba26af582a9d9927b7f7e6e",
      "tree": "176134252be60e0d8084f02302425398cd42a3e1",
      "parents": [
        "08470e9a6baac67d4f85620a221becc7bbe9a312"
      ],
      "author": {
        "name": "Robert Clendenin",
        "email": "rclendenin@apple.com",
        "time": "Tue Jun 16 10:15:35 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 10:15:35 2026 -0500"
      },
      "message": "Fix tsapi build with ENABLE_PROBES\u003dON (#13276)\n\nCache headers transitively pull in \u003cts/ats_probe.h\u003e via P_CacheDir.h.\nWhen ENABLE_PROBES\u003dON, ENABLE_SYSTEMTAP_PROBES is defined and\nats_probe.h `#include \u003csys/sdt.h\u003e`. tsapi\u0027s include path didn\u0027t have\nlib/systemtap, so the build failed.\n\nMirror what tscore already does (src/tscore/CMakeLists.txt:110), gated\non ENABLE_PROBES so the dependency only attaches when probes are\nactually enabled."
    },
    {
      "commit": "08470e9a6baac67d4f85620a221becc7bbe9a312",
      "tree": "fdda5018b65bf7d73a87ea9f011b4c1652f796f8",
      "parents": [
        "dd38491fd5ae9aeaa1dee414bcc7359efcc2247a"
      ],
      "author": {
        "name": "Brian Neradt",
        "email": "brian.neradt@gmail.com",
        "time": "Tue Jun 16 09:41:09 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 09:41:09 2026 -0500"
      },
      "message": "Enable probes in Fedora C++20 CI (#13280)\n\nFedora CI runs the C++20 preset rather than the base Fedora preset, so\nprobe coverage drifted out of that build even though ci-fedora had the\noption enabled.\n\nThis makes the C++20 preset inherit the Fedora preset and keeps only the\nC++ standard override locally, so shared Fedora CI settings stay in one\nplace."
    },
    {
      "commit": "dd38491fd5ae9aeaa1dee414bcc7359efcc2247a",
      "tree": "304f9f98dd1c08e08c74e3a1e3e85b25bde21f0d",
      "parents": [
        "36b8649f3467e2780bec0c09f66b467d442a648a"
      ],
      "author": {
        "name": "Brian Olsen",
        "email": "brian_olsen2@comcast.com",
        "time": "Tue Jun 16 06:25:34 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 06:25:34 2026 -0600"
      },
      "message": "Fix bounds check in CacheVC::scanObject (#13263)"
    },
    {
      "commit": "36b8649f3467e2780bec0c09f66b467d442a648a",
      "tree": "b1f3cecb876881daf9ebff0ec13ab6d02f7d9bd5",
      "parents": [
        "a2e02e144912302811338d67abcc1ead224795a7"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Tue Jun 16 09:21:07 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 09:21:07 2026 +0900"
      },
      "message": "Fix mismatched log field types more (#13256)"
    },
    {
      "commit": "a2e02e144912302811338d67abcc1ead224795a7",
      "tree": "b2e36128a39f61312aed7828b5571d983b02bfc0",
      "parents": [
        "51ba3a4def82c06803842ae8d47dd366222739a6"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Mon Jun 15 18:10:56 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 15 18:10:56 2026 -0500"
      },
      "message": "Remove unused EThread members (#13268)\n\nThis removes the following members:\n- EThread::diskHandler\n- EThread::aio_ops"
    },
    {
      "commit": "51ba3a4def82c06803842ae8d47dd366222739a6",
      "tree": "b9180f0975379b73f6ff915352fbc852e1804f7f",
      "parents": [
        "e79182f7e22423fca5e60b9903c3a9a104b5ac13"
      ],
      "author": {
        "name": "Masaori Koshiba",
        "email": "masaori@apache.org",
        "time": "Mon Jun 15 08:41:11 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 15 08:41:11 2026 +0900"
      },
      "message": "Fix truncated HTTP version in log field unmarshalling (#13236)\n\n* Fix truncated HTTP version in log field unmarshalling\n\nunmarshal_http_version did not advance the buffer pointer past the\nminor-version digits before computing the output length, so logged\nHTTP versions dropped the minor number (\"HTTP/1.\" instead of\n\"HTTP/1.1\"). This is a regression from #11437, which changed val_len\nto a pointer subtraction without advancing past the second integer.\n\n* Remove dead LogAccess marshal/unmarshal declarations\n\nThese functions have no callers, and several are declared without\never being defined; none are paired with a log field:\n\n- unmarshal_http_text: no marshal counterpart; referenced only by\n  its own declaration and (former) definition.\n- marshal_milestone_fmt_squid/_netscape/_date/_time: declared but\n  never defined. Only _fmt_sec and _fmt_ms are implemented and used;\n  the date/time/netscape/squid formatting happens at unmarshal time.\n- unmarshal_client_protocol_stack: declared but never defined or\n  wired into any log field.\n\n* Add test cases for 2.0 and 3.0"
    },
    {
      "commit": "e79182f7e22423fca5e60b9903c3a9a104b5ac13",
      "tree": "324b933f95778ccf0d1662850c44c85a440b9a10",
      "parents": [
        "77253da933af73970c16727bd08c99f126e2f88f"
      ],
      "author": {
        "name": "Masakazu Kitajo",
        "email": "maskit@apache.org",
        "time": "Thu Jun 11 14:32:15 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 11 14:32:15 2026 -0600"
      },
      "message": "authproxy: Release client request handle in StateAuthorized (#13258)\n\nTSHttpTxnClientReqGet was not paired with TSHandleMLocRelease, unlike\nevery other call site in this file. The handle is a top-level\nHTTP_HEADER mloc so the release is effectively a no-op today, but\nmatching the documented API contract avoids surprises if the SDK\nimplementation ever changes."
    },
    {
      "commit": "77253da933af73970c16727bd08c99f126e2f88f",
      "tree": "6ecaf8a038d26500a3f3ecf7fa25bc5b11d3ab14",
      "parents": [
        "30d8fcad44a7cb9945cf55db722e5737c357e406"
      ],
      "author": {
        "name": "JosiahWI",
        "email": "41302989+JosiahWI@users.noreply.github.com",
        "time": "Tue Jun 09 20:43:20 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 20:43:20 2026 -0500"
      },
      "message": "Fix compilation under `LOOP_CHECK_MODE` (#13250)\n\nIn earlier work, `vol` was renamed to `stripe` throughout the cache.\nA few occurences of `vol` were missed because they are conditionally compiled.\nThis patch renames `vol` to `stripe` within code switched by the\n`LOOP_CHECK_MODE` definition."
    },
    {
      "commit": "30d8fcad44a7cb9945cf55db722e5737c357e406",
      "tree": "81298e88891588009657949f91912b9552e03b29",
      "parents": [
        "b5fe66966dfc49b962dff864689bdd6dbcf1b704"
      ],
      "author": {
        "name": "craigt",
        "email": "c@gryning.com",
        "time": "Tue Jun 09 17:41:55 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 18:41:55 2026 -0500"
      },
      "message": "ocsp: add single-cert stapling fast path and certinfo RAII (#13229)\n\n* ocsp: add single-cert stapling fast path and certinfo RAII\n\nSkip the SSL_get_certificate() lookup and X509_cmp() DER re-parse in the\nstapling callback when an SSL_CTX has a single certificate. The shortcut\nis gated to non-dual-cert builds; under HAVE_NATIVE_DUAL_CERT_SUPPORT a\nCTX can hold multiple certs where only one has OCSP info, so map size\nalone cannot identify the negotiated cert.\n\nGive certinfo a constructor/destructor so its resources are managed by\nRAII, and allocate it with make_unique. This consolidates the cleanup\nthat was duplicated across certinfo_map_free and the init error path,\nand fixes two pre-existing leaks (cid and the BoringSSL cert ref) plus\nan error path that could delete a certinfo_map still owned by the\nSSL_CTX.\n\n* ocsp: make certinfo map own values via unique_ptr\n\nSwitch the per-SSL_CTX certinfo map to store std::unique_ptr\u003ccertinfo\u003e\nso ownership is explicit and the value cleanup is handled by RAII. This\nremoves the manual delete in certinfo_map_free and closes a leak window\nat the insert site: the old release()-then-insert dropped the pointer if\nthe key already existed or the insert threw, whereas emplace with a move\nonly transfers ownership once insertion succeeds."
    },
    {
      "commit": "b5fe66966dfc49b962dff864689bdd6dbcf1b704",
      "tree": "8c568e44e751642ac0df865544d6f68091e9c172",
      "parents": [
        "d9ce07e332f7bb1f75972c8043c525af3c8b52b8"
      ],
      "author": {
        "name": "craigt",
        "email": "c@gryning.com",
        "time": "Tue Jun 09 17:41:22 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 18:41:22 2026 -0500"
      },
      "message": "Reduce TLS handshake contention on SSLCertContext (#13098)\n\n* Reduce TLS handshake contention on SSLCertContext\n\nReplace std::mutex with ts::bravo::shared_mutex on SSLCertContext\nto allow true reader concurrency for getCtx() on the TLS handshake\nhot path. setCtx() (config reload only) takes an exclusive lock.\n\nMemory trade-off: BRAVO uses 256 cache-line-aligned reader slots\n(~16 KB per mutex) vs ~40 bytes for std::mutex or ~56 bytes for\nstd::shared_mutex on Linux. For 256 certificates this is ~4 MB\n(vs 10 KB / 14 KB), a modest cost relative to the SSL_CTX objects\nthemselves but worth noting for deployments with many certs.\n\n* Replace BRAVO with std::shared_mutex for SSLCertContext\n\nSwitch from ts::bravo::shared_mutex to std::shared_mutex. The\ncontention pattern (short bursts, not sustained) doesn\u0027t benefit\nfrom BRAVO\u0027s per-thread slots, and std::shared_mutex avoids the\n~16 KB per-mutex memory overhead."
    },
    {
      "commit": "d9ce07e332f7bb1f75972c8043c525af3c8b52b8",
      "tree": "4b3f1af81e84bd20aaea5063ef3c26796f46ffca",
      "parents": [
        "b71ea748f2bc3524cf7ecf0080181c06aff92b78"
      ],
      "author": {
        "name": "Leif Hedstrom",
        "email": "zwoop@apache.org",
        "time": "Tue Jun 09 14:50:29 2026 -0600"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 09 14:50:29 2026 -0600"
      },
      "message": "Reduce TLS write-path overhead (#13202)\n\n* Reduce TLS write-path syscalls by coalescing records\n\nA response split across many small IOBuffer blocks issued one\nSSL_write -- and thus one TLS record and often one write() syscall --\nper block. Gather the blocks into a per-thread scratch buffer (bounded\nto one max TLS record) and issue a single SSL_write, so a fragmented\nbuffer yields one record and one write(). Contiguous blocks still write\nin place, preserving the dynamic record-sizing ramp and prior behavior.\n\n* Address Copilot\u0027s review\n\nDrop the redundant per-iteration read_avail() walk in the TLS write\npath. towrite is already bounded by read_avail() in the caller\n(write_to_net_io), so use towrite - total_written directly and avoid\nre-walking the IOBufferBlock chain (O(n)) on the write hot path.\n\n* Address review comments on TLS write-path\n\nRephrase gather_buf rationale to cite SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER\n(per Mo) and add an ink_assert enforcing the towrite \u003c\u003d read_avail()\nprecondition (per Josiah) so the O(1) hot-path computation is verified\nin debug builds."
    }
  ],
  "next": "b71ea748f2bc3524cf7ecf0080181c06aff92b78"
}
