shreemaan-abhishek commented on code in PR #13842:
URL: https://github.com/apache/apisix/pull/13842#discussion_r3819812552


##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)

Review Comment:
   Good catch, fixed in 9bce154a4 with your wording. Verified: `ngx_tpl.lua` 
still defines `$var_x_forwarded_host` and `$var_x_forwarded_port` as `map` 
outputs and feeds them to the `more_set_input_headers` directives; only 
`$var_x_forwarded_proto` is gone, replaced by `$scheme`. All three did leave 
the Lua-writable list in `core/ctx.lua`, which is what the entry now says.



##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)
+
+### Core
+
+- feat: raise default sizes for non-evictable shared dicts: 
`prometheus-metrics` 15m/10m→128m, `nacos` 10m→64m, consul and kubernetes 
discovery `shared_size` 1m→64m, `tracing_buffer` 10m→32m 
[#13688](https://github.com/apache/apisix/pull/13688)
+- chore(core): remove the dead `clean_handlers` mechanism. 
`core.config_util.add_clean_handler`, `cancel_clean_handler` and 
`fire_all_clean_handlers` no longer exist 
[#13761](https://github.com/apache/apisix/pull/13761)
+- feat(ai-proxy): send LLM requests through `ngx_http_ffi_client`. New 
`plugin_attr.ai-proxy.http_client`, defaulting to the FFI client, which 
requires an APISIX-Runtime that ships `ngx_http_ffi_client` (set 
`lua-resty-http` to opt out) 
[#13778](https://github.com/apache/apisix/pull/13778)

Review Comment:
   Keeping this one in Core, for the reason above. Every release repins 
`APISIX_RUNTIME` in `.requirements` (1.3.11 -> 1.3.16 this cycle), so "requires 
this release's runtime" would make most runtime-dependent work 
backward-incompatible and dilute the Change section. I have reworded the entry 
in 9bce154a4 to say the client ships with the runtime pinned by this release, 
and to name the `plugin_attr.ai-proxy.http_client: lua-resty-http` opt-out for 
hand-built runtimes without the module.



##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)
+
+### Core
+
+- feat: raise default sizes for non-evictable shared dicts: 
`prometheus-metrics` 15m/10m→128m, `nacos` 10m→64m, consul and kubernetes 
discovery `shared_size` 1m→64m, `tracing_buffer` 10m→32m 
[#13688](https://github.com/apache/apisix/pull/13688)
+- chore(core): remove the dead `clean_handlers` mechanism. 
`core.config_util.add_clean_handler`, `cancel_clean_handler` and 
`fire_all_clean_handlers` no longer exist 
[#13761](https://github.com/apache/apisix/pull/13761)
+- feat(ai-proxy): send LLM requests through `ngx_http_ffi_client`. New 
`plugin_attr.ai-proxy.http_client`, defaulting to the FFI client, which 
requires an APISIX-Runtime that ships `ngx_http_ffi_client` (set 
`lua-resty-http` to opt out) 
[#13778](https://github.com/apache/apisix/pull/13778)
+- feat: support per-port PROXY protocol for stream TCP proxy 
[#13561](https://github.com/apache/apisix/pull/13561)
+- feat(stream): support `set_real_ip_from` to trust an inbound PROXY protocol 
header [#13700](https://github.com/apache/apisix/pull/13700)
+- feat(stream): support upstream client certificate (mTLS) in the L4 proxy 
[#13596](https://github.com/apache/apisix/pull/13596)
+- feat(router): add `match_uri_encoded_slash` to keep `%2F` in path parameters 
[#13626](https://github.com/apache/apisix/pull/13626)
+- feat: add `max_post_args_readable_size` to bound `post_arg.*` body reads 
[#13601](https://github.com/apache/apisix/pull/13601)

Review Comment:
   Agreed, moved to Change with :warning: in 9bce154a4, including the migration 
action (raise the value, or set it to `0`). Worth adding that this is reachable 
in a default install rather than only on tuned deployments: 
`client_max_body_size` defaults to `0` (unlimited), so a body above 64 MiB does 
reach route matching.



##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)
+
+### Core
+
+- feat: raise default sizes for non-evictable shared dicts: 
`prometheus-metrics` 15m/10m→128m, `nacos` 10m→64m, consul and kubernetes 
discovery `shared_size` 1m→64m, `tracing_buffer` 10m→32m 
[#13688](https://github.com/apache/apisix/pull/13688)
+- chore(core): remove the dead `clean_handlers` mechanism. 
`core.config_util.add_clean_handler`, `cancel_clean_handler` and 
`fire_all_clean_handlers` no longer exist 
[#13761](https://github.com/apache/apisix/pull/13761)
+- feat(ai-proxy): send LLM requests through `ngx_http_ffi_client`. New 
`plugin_attr.ai-proxy.http_client`, defaulting to the FFI client, which 
requires an APISIX-Runtime that ships `ngx_http_ffi_client` (set 
`lua-resty-http` to opt out) 
[#13778](https://github.com/apache/apisix/pull/13778)
+- feat: support per-port PROXY protocol for stream TCP proxy 
[#13561](https://github.com/apache/apisix/pull/13561)
+- feat(stream): support `set_real_ip_from` to trust an inbound PROXY protocol 
header [#13700](https://github.com/apache/apisix/pull/13700)
+- feat(stream): support upstream client certificate (mTLS) in the L4 proxy 
[#13596](https://github.com/apache/apisix/pull/13596)
+- feat(router): add `match_uri_encoded_slash` to keep `%2F` in path parameters 
[#13626](https://github.com/apache/apisix/pull/13626)
+- feat: add `max_post_args_readable_size` to bound `post_arg.*` body reads 
[#13601](https://github.com/apache/apisix/pull/13601)
+- feat: support `http_method` and `http_req_body` in active health checks 
[#13726](https://github.com/apache/apisix/pull/13726)
+- feat(data_encryption): support AES-256 keys in the encryption keyring 
[#13756](https://github.com/apache/apisix/pull/13756)
+- refactor: decouple generic data encryption from `ssl.lua` 
[#13564](https://github.com/apache/apisix/pull/13564)
+- perf(plugin): reuse the filtered global-rule plugin set across phases 
[#13779](https://github.com/apache/apisix/pull/13779)
+- fix: keep the chash ring stable during health changes 
[#13532](https://github.com/apache/apisix/pull/13532)
+- fix(balancer): keep least_conn load state across upstream scaling 
[#13666](https://github.com/apache/apisix/pull/13666)
+- fix(balancer): separate the keepalive pool by referenced client cert 
[#13587](https://github.com/apache/apisix/pull/13587)
+- fix(healthcheck): reuse the checker on node-only upstream changes instead of 
destroy-and-rebuild [#13629](https://github.com/apache/apisix/pull/13629)
+- fix(healthcheck): probe domain nodes by the node domain, not the resolved IP 
[#13743](https://github.com/apache/apisix/pull/13743)
+- fix(healthcheck): purge stale targets and release the periodic lock 
[#13627](https://github.com/apache/apisix/pull/13627)
+- fix(healthcheck): guard `construct_upstream` in healthcheck timers 
[#13592](https://github.com/apache/apisix/pull/13592)
+- fix(stream): initialize env and secret for TLS cert resolution 
[#12935](https://github.com/apache/apisix/pull/12935)
+- fix: fetch secrets from the upstream ssl config 
[#13062](https://github.com/apache/apisix/pull/13062)
+- fix: invalidate the secret LRU cache on `/secrets` changes 
[#13668](https://github.com/apache/apisix/pull/13668)
+- fix(secret): log an error when a secret reference cannot be resolved 
[#13737](https://github.com/apache/apisix/pull/13737)
+- fix: reject consumer auth when a secret reference fails to resolve 
[#13667](https://github.com/apache/apisix/pull/13667)
+- fix: encode control characters in `$upstream_uri` to prevent CRLF injection 
[#13787](https://github.com/apache/apisix/pull/13787)
+- fix: reset `X-Forwarded-For` only for untrusted sources under 
`trusted_addresses` [#13611](https://github.com/apache/apisix/pull/13611)
+- fix: normalize the case of hosts carried on a service 
[#13781](https://github.com/apache/apisix/pull/13781)
+- fix(plugin): preserve plugin-conf state across the consumer route merge 
[#13757](https://github.com/apache/apisix/pull/13757)
+- fix(resource): support all plugin-bearing resource types in 
`fetch_latest_conf` [#13663](https://github.com/apache/apisix/pull/13663)
+- fix(config_etcd): keep the previous value when a full reload gets invalid 
data [#13717](https://github.com/apache/apisix/pull/13717)
+- fix(etcd): do not advance the watch revision on a timeout, and make the 
recovery reload cheap [#13721](https://github.com/apache/apisix/pull/13721)
+- fix(json): make cjson instances inherit APISIX's cjson options 
[#13680](https://github.com/apache/apisix/pull/13680)
+- fix(env): resolve the `os.getenv` prefix collision for `env` directives 
[#13595](https://github.com/apache/apisix/pull/13595)
+- fix(cli): remove the stale key after resolving an env var in config keys 
[#12885](https://github.com/apache/apisix/pull/12885)
+- fix(cli): quote `nginx_config.envs` entries so values with spaces work 
[#13713](https://github.com/apache/apisix/pull/13713)
+- fix(admin): harden stream_route `superior_id` dependency checks 
[#13672](https://github.com/apache/apisix/pull/13672)
+- fix(admin): encrypt only after successful validation 
[#13729](https://github.com/apache/apisix/pull/13729)
+- fix(admin): encrypt the inline upstream client key of a stream route 
[#13833](https://github.com/apache/apisix/pull/13833)
+- fix(admin): reconcile the plugins reload instead of trusting the broadcast 
[#13714](https://github.com/apache/apisix/pull/13714)
+- fix(control): reconcile `/v1/plugins/reload` like the admin reload path 
[#13745](https://github.com/apache/apisix/pull/13745)
+- fix(log-sanitize): return raw tables to avoid double `delay_encode` 
[#13605](https://github.com/apache/apisix/pull/13605)
+- fix(dns): correct the `error()` call in dns client initialization 
[#13358](https://github.com/apache/apisix/pull/13358)
+- fix: avoid 503 error after dns service temporary fail 
[#13137](https://github.com/apache/apisix/pull/13137)
+- fix(cli): add IPv6 listen support for the PROXY protocol 
[#12859](https://github.com/apache/apisix/pull/12859)
+- fix(upstream): use `cert` and `key` instead of stale `ok` in mTLS error 
checks [#13442](https://github.com/apache/apisix/pull/13442)
+- fix(core.request): `set_header` must update the cached headers with a 
normalized key [#13517](https://github.com/apache/apisix/pull/13517)
+- fix(admin): `encrypt_fields` get double-encrypted on every PATCH 
[#13525](https://github.com/apache/apisix/pull/13525)
+- fix(plugin): ignore `plugin_metadata` of disabled or unknown plugins 
[#13514](https://github.com/apache/apisix/pull/13514)
+- fix(xrpc): stream routes with xRPC protocols fail `check_schema` in HTTP 
workers when the Admin API is disabled 
[#13515](https://github.com/apache/apisix/pull/13515)
+- fix(secret): aws secret manager fails when the secret name contains a slash 
[#13519](https://github.com/apache/apisix/pull/13519)
+- fix(consul): one invalid node should not discard the remaining nodes of the 
service [#13513](https://github.com/apache/apisix/pull/13513)
+- fix(nacos): declare the `nacos-stream` shared dict in the stream subsystem 
[#13541](https://github.com/apache/apisix/pull/13541)
+- fix: redis connections with different database/credentials must not share a 
keepalive pool [#13516](https://github.com/apache/apisix/pull/13516)
+
+### Plugins
+
+- feat: add ai-cache plugin 
[#13578](https://github.com/apache/apisix/pull/13578)
+- feat(ai-cache): add the semantic (L2) cache layer 
[#13632](https://github.com/apache/apisix/pull/13632)
+- feat(ai-cache): add streaming support with format tagging 
[#13644](https://github.com/apache/apisix/pull/13644)
+- feat: add ai-lakera-guard plugin 
[#13570](https://github.com/apache/apisix/pull/13570)
+- feat(ai-lakera-guard): scan LLM responses (direction output/both, 
non-streaming and streaming) 
[#13606](https://github.com/apache/apisix/pull/13606)
+- feat: add ldap-auth-advanced plugin 
[#13762](https://github.com/apache/apisix/pull/13762)

Review Comment:
   Confirmed, and added as its own Change entry in 9bce154a4 while keeping the 
new plugin under Plugins. The mechanism: in `lua-resty-ldap` 0.1.0 the 
handshake read `conf.verify_ldap_host` (`init.lua:78`) while `ldap-auth` passes 
`tls_verify`, so the argument was always nil and `sslhandshake(true, host, 
nil)` verified nothing. 0.3.1 maps `ssl_verify = conf.tls_verify`, so the flag 
now takes effect. Scope is limited to deployments that explicitly set 
`tls_verify: true`, which are exactly the ones that believed verification was 
already on.



##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)
+
+### Core
+
+- feat: raise default sizes for non-evictable shared dicts: 
`prometheus-metrics` 15m/10m→128m, `nacos` 10m→64m, consul and kubernetes 
discovery `shared_size` 1m→64m, `tracing_buffer` 10m→32m 
[#13688](https://github.com/apache/apisix/pull/13688)
+- chore(core): remove the dead `clean_handlers` mechanism. 
`core.config_util.add_clean_handler`, `cancel_clean_handler` and 
`fire_all_clean_handlers` no longer exist 
[#13761](https://github.com/apache/apisix/pull/13761)
+- feat(ai-proxy): send LLM requests through `ngx_http_ffi_client`. New 
`plugin_attr.ai-proxy.http_client`, defaulting to the FFI client, which 
requires an APISIX-Runtime that ships `ngx_http_ffi_client` (set 
`lua-resty-http` to opt out) 
[#13778](https://github.com/apache/apisix/pull/13778)
+- feat: support per-port PROXY protocol for stream TCP proxy 
[#13561](https://github.com/apache/apisix/pull/13561)
+- feat(stream): support `set_real_ip_from` to trust an inbound PROXY protocol 
header [#13700](https://github.com/apache/apisix/pull/13700)
+- feat(stream): support upstream client certificate (mTLS) in the L4 proxy 
[#13596](https://github.com/apache/apisix/pull/13596)
+- feat(router): add `match_uri_encoded_slash` to keep `%2F` in path parameters 
[#13626](https://github.com/apache/apisix/pull/13626)
+- feat: add `max_post_args_readable_size` to bound `post_arg.*` body reads 
[#13601](https://github.com/apache/apisix/pull/13601)
+- feat: support `http_method` and `http_req_body` in active health checks 
[#13726](https://github.com/apache/apisix/pull/13726)
+- feat(data_encryption): support AES-256 keys in the encryption keyring 
[#13756](https://github.com/apache/apisix/pull/13756)
+- refactor: decouple generic data encryption from `ssl.lua` 
[#13564](https://github.com/apache/apisix/pull/13564)
+- perf(plugin): reuse the filtered global-rule plugin set across phases 
[#13779](https://github.com/apache/apisix/pull/13779)
+- fix: keep the chash ring stable during health changes 
[#13532](https://github.com/apache/apisix/pull/13532)
+- fix(balancer): keep least_conn load state across upstream scaling 
[#13666](https://github.com/apache/apisix/pull/13666)
+- fix(balancer): separate the keepalive pool by referenced client cert 
[#13587](https://github.com/apache/apisix/pull/13587)
+- fix(healthcheck): reuse the checker on node-only upstream changes instead of 
destroy-and-rebuild [#13629](https://github.com/apache/apisix/pull/13629)
+- fix(healthcheck): probe domain nodes by the node domain, not the resolved IP 
[#13743](https://github.com/apache/apisix/pull/13743)
+- fix(healthcheck): purge stale targets and release the periodic lock 
[#13627](https://github.com/apache/apisix/pull/13627)
+- fix(healthcheck): guard `construct_upstream` in healthcheck timers 
[#13592](https://github.com/apache/apisix/pull/13592)
+- fix(stream): initialize env and secret for TLS cert resolution 
[#12935](https://github.com/apache/apisix/pull/12935)
+- fix: fetch secrets from the upstream ssl config 
[#13062](https://github.com/apache/apisix/pull/13062)
+- fix: invalidate the secret LRU cache on `/secrets` changes 
[#13668](https://github.com/apache/apisix/pull/13668)
+- fix(secret): log an error when a secret reference cannot be resolved 
[#13737](https://github.com/apache/apisix/pull/13737)
+- fix: reject consumer auth when a secret reference fails to resolve 
[#13667](https://github.com/apache/apisix/pull/13667)
+- fix: encode control characters in `$upstream_uri` to prevent CRLF injection 
[#13787](https://github.com/apache/apisix/pull/13787)
+- fix: reset `X-Forwarded-For` only for untrusted sources under 
`trusted_addresses` [#13611](https://github.com/apache/apisix/pull/13611)
+- fix: normalize the case of hosts carried on a service 
[#13781](https://github.com/apache/apisix/pull/13781)
+- fix(plugin): preserve plugin-conf state across the consumer route merge 
[#13757](https://github.com/apache/apisix/pull/13757)
+- fix(resource): support all plugin-bearing resource types in 
`fetch_latest_conf` [#13663](https://github.com/apache/apisix/pull/13663)
+- fix(config_etcd): keep the previous value when a full reload gets invalid 
data [#13717](https://github.com/apache/apisix/pull/13717)
+- fix(etcd): do not advance the watch revision on a timeout, and make the 
recovery reload cheap [#13721](https://github.com/apache/apisix/pull/13721)
+- fix(json): make cjson instances inherit APISIX's cjson options 
[#13680](https://github.com/apache/apisix/pull/13680)
+- fix(env): resolve the `os.getenv` prefix collision for `env` directives 
[#13595](https://github.com/apache/apisix/pull/13595)
+- fix(cli): remove the stale key after resolving an env var in config keys 
[#12885](https://github.com/apache/apisix/pull/12885)
+- fix(cli): quote `nginx_config.envs` entries so values with spaces work 
[#13713](https://github.com/apache/apisix/pull/13713)
+- fix(admin): harden stream_route `superior_id` dependency checks 
[#13672](https://github.com/apache/apisix/pull/13672)
+- fix(admin): encrypt only after successful validation 
[#13729](https://github.com/apache/apisix/pull/13729)
+- fix(admin): encrypt the inline upstream client key of a stream route 
[#13833](https://github.com/apache/apisix/pull/13833)
+- fix(admin): reconcile the plugins reload instead of trusting the broadcast 
[#13714](https://github.com/apache/apisix/pull/13714)
+- fix(control): reconcile `/v1/plugins/reload` like the admin reload path 
[#13745](https://github.com/apache/apisix/pull/13745)
+- fix(log-sanitize): return raw tables to avoid double `delay_encode` 
[#13605](https://github.com/apache/apisix/pull/13605)
+- fix(dns): correct the `error()` call in dns client initialization 
[#13358](https://github.com/apache/apisix/pull/13358)
+- fix: avoid 503 error after dns service temporary fail 
[#13137](https://github.com/apache/apisix/pull/13137)
+- fix(cli): add IPv6 listen support for the PROXY protocol 
[#12859](https://github.com/apache/apisix/pull/12859)
+- fix(upstream): use `cert` and `key` instead of stale `ok` in mTLS error 
checks [#13442](https://github.com/apache/apisix/pull/13442)
+- fix(core.request): `set_header` must update the cached headers with a 
normalized key [#13517](https://github.com/apache/apisix/pull/13517)
+- fix(admin): `encrypt_fields` get double-encrypted on every PATCH 
[#13525](https://github.com/apache/apisix/pull/13525)
+- fix(plugin): ignore `plugin_metadata` of disabled or unknown plugins 
[#13514](https://github.com/apache/apisix/pull/13514)
+- fix(xrpc): stream routes with xRPC protocols fail `check_schema` in HTTP 
workers when the Admin API is disabled 
[#13515](https://github.com/apache/apisix/pull/13515)
+- fix(secret): aws secret manager fails when the secret name contains a slash 
[#13519](https://github.com/apache/apisix/pull/13519)
+- fix(consul): one invalid node should not discard the remaining nodes of the 
service [#13513](https://github.com/apache/apisix/pull/13513)
+- fix(nacos): declare the `nacos-stream` shared dict in the stream subsystem 
[#13541](https://github.com/apache/apisix/pull/13541)
+- fix: redis connections with different database/credentials must not share a 
keepalive pool [#13516](https://github.com/apache/apisix/pull/13516)
+
+### Plugins
+
+- feat: add ai-cache plugin 
[#13578](https://github.com/apache/apisix/pull/13578)
+- feat(ai-cache): add the semantic (L2) cache layer 
[#13632](https://github.com/apache/apisix/pull/13632)
+- feat(ai-cache): add streaming support with format tagging 
[#13644](https://github.com/apache/apisix/pull/13644)
+- feat: add ai-lakera-guard plugin 
[#13570](https://github.com/apache/apisix/pull/13570)
+- feat(ai-lakera-guard): scan LLM responses (direction output/both, 
non-streaming and streaming) 
[#13606](https://github.com/apache/apisix/pull/13606)
+- feat: add ldap-auth-advanced plugin 
[#13762](https://github.com/apache/apisix/pull/13762)
+- feat(ai-proxy-multi): add the semantic load-balancing algorithm 
[#13676](https://github.com/apache/apisix/pull/13676)
+- feat(ai-proxy): include AI observability vars in `llm_summary` 
[#13609](https://github.com/apache/apisix/pull/13609)
+- feat(ai-rate-limiting): support the redis policy for shared counters 
[#13670](https://github.com/apache/apisix/pull/13670)
+- feat(ai-aws-content-moderation): moderate LLM responses, including streams 
[#13735](https://github.com/apache/apisix/pull/13735)
+- feat(ai-aws-content-moderation): add `request_check_roles` and 
`request_check_mode` [#13773](https://github.com/apache/apisix/pull/13773)
+- feat(ai-aliyun-content-moderation): moderate system and tool role content 
[#13646](https://github.com/apache/apisix/pull/13646)
+- feat(prometheus): add metrics for AI cache hits, misses, bypasses, and 
embedding latency [#13659](https://github.com/apache/apisix/pull/13659)
+- feat(prometheus): stream active connections, termination status and 
bandwidth [#13796](https://github.com/apache/apisix/pull/13796)
+- feat: add `log_format_extra` to enrich the default logger format 
[#13568](https://github.com/apache/apisix/pull/13568)
+- feat(kafka-logger): add TLS support for Kafka brokers 
[#13607](https://github.com/apache/apisix/pull/13607)
+- feat(elasticsearch-logger): encrypt the `headers` field at rest 
[#13612](https://github.com/apache/apisix/pull/13612)
+- feat: encrypt `redis_password` and `sentinel_password` in limit-count, 
limit-req and limit-conn [#13624](https://github.com/apache/apisix/pull/13624)
+- feat(proxy-rewrite): support multiple same-name headers in 
`headers.add`/`headers.set` 
[#13597](https://github.com/apache/apisix/pull/13597)
+- feat(openid-connect): add the `set_raw_id_token_header` option 
[#13616](https://github.com/apache/apisix/pull/13616)
+- feat(openid-connect): support PAR and DPoP client options 
[#13649](https://github.com/apache/apisix/pull/13649)
+- feat(ldap-auth): add `hide_credentials` 
[#13832](https://github.com/apache/apisix/pull/13832)
+- refactor(ai-providers): make the LLM request client ctx-free 
[#13699](https://github.com/apache/apisix/pull/13699)

Review Comment:
   Agreed, recategorised as `fix(ai-request-rewrite)` in 9bce154a4 with the 
user impact described. One refinement to the wording: the pre-image copied 
every client header and then merged `ext_opts_headers` over them, so when the 
provider authenticates through the `Authorization` header the client's value 
was overwritten. `Cookie` and any other client headers (custom API keys, 
session tokens) leaked unconditionally, and `Authorization` leaked whenever the 
provider uses query-param, `api-key` or SigV4 auth. The entry is phrased to 
match that.



##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)
+
+### Core
+
+- feat: raise default sizes for non-evictable shared dicts: 
`prometheus-metrics` 15m/10m→128m, `nacos` 10m→64m, consul and kubernetes 
discovery `shared_size` 1m→64m, `tracing_buffer` 10m→32m 
[#13688](https://github.com/apache/apisix/pull/13688)
+- chore(core): remove the dead `clean_handlers` mechanism. 
`core.config_util.add_clean_handler`, `cancel_clean_handler` and 
`fire_all_clean_handlers` no longer exist 
[#13761](https://github.com/apache/apisix/pull/13761)
+- feat(ai-proxy): send LLM requests through `ngx_http_ffi_client`. New 
`plugin_attr.ai-proxy.http_client`, defaulting to the FFI client, which 
requires an APISIX-Runtime that ships `ngx_http_ffi_client` (set 
`lua-resty-http` to opt out) 
[#13778](https://github.com/apache/apisix/pull/13778)
+- feat: support per-port PROXY protocol for stream TCP proxy 
[#13561](https://github.com/apache/apisix/pull/13561)
+- feat(stream): support `set_real_ip_from` to trust an inbound PROXY protocol 
header [#13700](https://github.com/apache/apisix/pull/13700)
+- feat(stream): support upstream client certificate (mTLS) in the L4 proxy 
[#13596](https://github.com/apache/apisix/pull/13596)
+- feat(router): add `match_uri_encoded_slash` to keep `%2F` in path parameters 
[#13626](https://github.com/apache/apisix/pull/13626)
+- feat: add `max_post_args_readable_size` to bound `post_arg.*` body reads 
[#13601](https://github.com/apache/apisix/pull/13601)
+- feat: support `http_method` and `http_req_body` in active health checks 
[#13726](https://github.com/apache/apisix/pull/13726)
+- feat(data_encryption): support AES-256 keys in the encryption keyring 
[#13756](https://github.com/apache/apisix/pull/13756)
+- refactor: decouple generic data encryption from `ssl.lua` 
[#13564](https://github.com/apache/apisix/pull/13564)
+- perf(plugin): reuse the filtered global-rule plugin set across phases 
[#13779](https://github.com/apache/apisix/pull/13779)
+- fix: keep the chash ring stable during health changes 
[#13532](https://github.com/apache/apisix/pull/13532)
+- fix(balancer): keep least_conn load state across upstream scaling 
[#13666](https://github.com/apache/apisix/pull/13666)
+- fix(balancer): separate the keepalive pool by referenced client cert 
[#13587](https://github.com/apache/apisix/pull/13587)
+- fix(healthcheck): reuse the checker on node-only upstream changes instead of 
destroy-and-rebuild [#13629](https://github.com/apache/apisix/pull/13629)
+- fix(healthcheck): probe domain nodes by the node domain, not the resolved IP 
[#13743](https://github.com/apache/apisix/pull/13743)
+- fix(healthcheck): purge stale targets and release the periodic lock 
[#13627](https://github.com/apache/apisix/pull/13627)
+- fix(healthcheck): guard `construct_upstream` in healthcheck timers 
[#13592](https://github.com/apache/apisix/pull/13592)
+- fix(stream): initialize env and secret for TLS cert resolution 
[#12935](https://github.com/apache/apisix/pull/12935)
+- fix: fetch secrets from the upstream ssl config 
[#13062](https://github.com/apache/apisix/pull/13062)
+- fix: invalidate the secret LRU cache on `/secrets` changes 
[#13668](https://github.com/apache/apisix/pull/13668)
+- fix(secret): log an error when a secret reference cannot be resolved 
[#13737](https://github.com/apache/apisix/pull/13737)
+- fix: reject consumer auth when a secret reference fails to resolve 
[#13667](https://github.com/apache/apisix/pull/13667)
+- fix: encode control characters in `$upstream_uri` to prevent CRLF injection 
[#13787](https://github.com/apache/apisix/pull/13787)
+- fix: reset `X-Forwarded-For` only for untrusted sources under 
`trusted_addresses` [#13611](https://github.com/apache/apisix/pull/13611)
+- fix: normalize the case of hosts carried on a service 
[#13781](https://github.com/apache/apisix/pull/13781)
+- fix(plugin): preserve plugin-conf state across the consumer route merge 
[#13757](https://github.com/apache/apisix/pull/13757)
+- fix(resource): support all plugin-bearing resource types in 
`fetch_latest_conf` [#13663](https://github.com/apache/apisix/pull/13663)
+- fix(config_etcd): keep the previous value when a full reload gets invalid 
data [#13717](https://github.com/apache/apisix/pull/13717)
+- fix(etcd): do not advance the watch revision on a timeout, and make the 
recovery reload cheap [#13721](https://github.com/apache/apisix/pull/13721)
+- fix(json): make cjson instances inherit APISIX's cjson options 
[#13680](https://github.com/apache/apisix/pull/13680)
+- fix(env): resolve the `os.getenv` prefix collision for `env` directives 
[#13595](https://github.com/apache/apisix/pull/13595)
+- fix(cli): remove the stale key after resolving an env var in config keys 
[#12885](https://github.com/apache/apisix/pull/12885)
+- fix(cli): quote `nginx_config.envs` entries so values with spaces work 
[#13713](https://github.com/apache/apisix/pull/13713)
+- fix(admin): harden stream_route `superior_id` dependency checks 
[#13672](https://github.com/apache/apisix/pull/13672)
+- fix(admin): encrypt only after successful validation 
[#13729](https://github.com/apache/apisix/pull/13729)
+- fix(admin): encrypt the inline upstream client key of a stream route 
[#13833](https://github.com/apache/apisix/pull/13833)
+- fix(admin): reconcile the plugins reload instead of trusting the broadcast 
[#13714](https://github.com/apache/apisix/pull/13714)
+- fix(control): reconcile `/v1/plugins/reload` like the admin reload path 
[#13745](https://github.com/apache/apisix/pull/13745)
+- fix(log-sanitize): return raw tables to avoid double `delay_encode` 
[#13605](https://github.com/apache/apisix/pull/13605)
+- fix(dns): correct the `error()` call in dns client initialization 
[#13358](https://github.com/apache/apisix/pull/13358)
+- fix: avoid 503 error after dns service temporary fail 
[#13137](https://github.com/apache/apisix/pull/13137)
+- fix(cli): add IPv6 listen support for the PROXY protocol 
[#12859](https://github.com/apache/apisix/pull/12859)
+- fix(upstream): use `cert` and `key` instead of stale `ok` in mTLS error 
checks [#13442](https://github.com/apache/apisix/pull/13442)
+- fix(core.request): `set_header` must update the cached headers with a 
normalized key [#13517](https://github.com/apache/apisix/pull/13517)
+- fix(admin): `encrypt_fields` get double-encrypted on every PATCH 
[#13525](https://github.com/apache/apisix/pull/13525)
+- fix(plugin): ignore `plugin_metadata` of disabled or unknown plugins 
[#13514](https://github.com/apache/apisix/pull/13514)
+- fix(xrpc): stream routes with xRPC protocols fail `check_schema` in HTTP 
workers when the Admin API is disabled 
[#13515](https://github.com/apache/apisix/pull/13515)
+- fix(secret): aws secret manager fails when the secret name contains a slash 
[#13519](https://github.com/apache/apisix/pull/13519)
+- fix(consul): one invalid node should not discard the remaining nodes of the 
service [#13513](https://github.com/apache/apisix/pull/13513)
+- fix(nacos): declare the `nacos-stream` shared dict in the stream subsystem 
[#13541](https://github.com/apache/apisix/pull/13541)
+- fix: redis connections with different database/credentials must not share a 
keepalive pool [#13516](https://github.com/apache/apisix/pull/13516)
+
+### Plugins
+
+- feat: add ai-cache plugin 
[#13578](https://github.com/apache/apisix/pull/13578)
+- feat(ai-cache): add the semantic (L2) cache layer 
[#13632](https://github.com/apache/apisix/pull/13632)
+- feat(ai-cache): add streaming support with format tagging 
[#13644](https://github.com/apache/apisix/pull/13644)
+- feat: add ai-lakera-guard plugin 
[#13570](https://github.com/apache/apisix/pull/13570)
+- feat(ai-lakera-guard): scan LLM responses (direction output/both, 
non-streaming and streaming) 
[#13606](https://github.com/apache/apisix/pull/13606)
+- feat: add ldap-auth-advanced plugin 
[#13762](https://github.com/apache/apisix/pull/13762)
+- feat(ai-proxy-multi): add the semantic load-balancing algorithm 
[#13676](https://github.com/apache/apisix/pull/13676)
+- feat(ai-proxy): include AI observability vars in `llm_summary` 
[#13609](https://github.com/apache/apisix/pull/13609)
+- feat(ai-rate-limiting): support the redis policy for shared counters 
[#13670](https://github.com/apache/apisix/pull/13670)
+- feat(ai-aws-content-moderation): moderate LLM responses, including streams 
[#13735](https://github.com/apache/apisix/pull/13735)
+- feat(ai-aws-content-moderation): add `request_check_roles` and 
`request_check_mode` [#13773](https://github.com/apache/apisix/pull/13773)
+- feat(ai-aliyun-content-moderation): moderate system and tool role content 
[#13646](https://github.com/apache/apisix/pull/13646)
+- feat(prometheus): add metrics for AI cache hits, misses, bypasses, and 
embedding latency [#13659](https://github.com/apache/apisix/pull/13659)
+- feat(prometheus): stream active connections, termination status and 
bandwidth [#13796](https://github.com/apache/apisix/pull/13796)
+- feat: add `log_format_extra` to enrich the default logger format 
[#13568](https://github.com/apache/apisix/pull/13568)
+- feat(kafka-logger): add TLS support for Kafka brokers 
[#13607](https://github.com/apache/apisix/pull/13607)
+- feat(elasticsearch-logger): encrypt the `headers` field at rest 
[#13612](https://github.com/apache/apisix/pull/13612)
+- feat: encrypt `redis_password` and `sentinel_password` in limit-count, 
limit-req and limit-conn [#13624](https://github.com/apache/apisix/pull/13624)
+- feat(proxy-rewrite): support multiple same-name headers in 
`headers.add`/`headers.set` 
[#13597](https://github.com/apache/apisix/pull/13597)
+- feat(openid-connect): add the `set_raw_id_token_header` option 
[#13616](https://github.com/apache/apisix/pull/13616)
+- feat(openid-connect): support PAR and DPoP client options 
[#13649](https://github.com/apache/apisix/pull/13649)
+- feat(ldap-auth): add `hide_credentials` 
[#13832](https://github.com/apache/apisix/pull/13832)
+- refactor(ai-providers): make the LLM request client ctx-free 
[#13699](https://github.com/apache/apisix/pull/13699)
+- refactor(cas-auth): drop the unnecessary raw Cookie header fallback 
[#13635](https://github.com/apache/apisix/pull/13635)
+- perf(zipkin): skip span tag construction for unsampled requests 
[#13656](https://github.com/apache/apisix/pull/13656)
+- perf(datadog): reuse one UDP socket per batch and coalesce metrics 
[#13653](https://github.com/apache/apisix/pull/13653)
+- perf(loggly): hoist the per-request closure out of the log phase 
[#13648](https://github.com/apache/apisix/pull/13648)

Review Comment:
   Agreed, it is `fix(loggly)` now in 9bce154a4. Confirmed the mechanism: 
`handle_http_payload` was a module-level local assigned inside `_M.log` on 
every request, while `handle_log` resolved it at flush time, so a batch queued 
for one route could be sent with another route's token, tags and endpoint. The 
reduced per-request allocation is described as the secondary benefit.



##########
CHANGELOG.md:
##########
@@ -85,6 +86,183 @@ title: Changelog
 - [0.7.0](#070)
 - [0.6.0](#060)
 
+## 3.18.0
+
+**The changes marked with :warning: are not backward compatible.**
+
+### Change
+
+- :warning: change(debug): report executed plugins with phase in execution 
order. The `Apisix-Plugins` debug header now carries `name#phase` entries in 
execution order instead of a de-duplicated plugin-name list 
[#13710](https://github.com/apache/apisix/pull/13710)
+- :warning: feat: bound request and response body buffering in plugins. 
`max_req_body_size` / `max_resp_body_size` (default 64 MiB) added to ~19 
plugins; larger bodies are now rejected or truncated instead of being buffered 
without limit [#13705](https://github.com/apache/apisix/pull/13705)
+- :warning: fix(batch-processor): bound the pending entries backlog by 
default. Every batch-processor logger now defaults `max_pending_entries` to 
8192 and discards entries above it 
[#13826](https://github.com/apache/apisix/pull/13826)
+- :warning: refactor(ai-aws-content-moderation): moderate decoded LLM content 
in the access phase. Priority moved from 1050 to 1031, the plugin now requires 
ai-proxy/ai-proxy-multi, moderates the extracted prompt instead of the raw 
body, and denies with `deny_code` (default 200) instead of 400 
[#13647](https://github.com/apache/apisix/pull/13647)
+- :warning: feat(ai-aliyun-content-moderation): role-aware 
`request_check_mode` and O(n) content chunking. Request moderation now covers 
the user role of the latest turn by default instead of every message in the 
body [#13598](https://github.com/apache/apisix/pull/13598)
+- :warning: fix(sls-logger): verify the TLS certificate of the log server. New 
`ssl_verify` option, default `true` 
[#13785](https://github.com/apache/apisix/pull/13785)
+- :warning: fix(openid-connect): enforce audience, issuer and required scopes. 
Bearer introspection fails closed when the discovery document is unavailable, 
`claim_validator.audience.match_with_client_id` now implies `required`, and 
`required_scopes` is enforced on session (authorization code) flows 
[#13829](https://github.com/apache/apisix/pull/13829)
+- :warning: fix(admin): reject duplicate consumer authentication keys instead 
of silently accepting them [#13529](https://github.com/apache/apisix/pull/13529)
+- :warning: perf(core): sanitize the `X-Forwarded-*` headers in the NGINX 
config. The `$var_x_forwarded_proto/host/port` variables are gone, and a 
trusted peer that sends no `X-Forwarded-Host`/`X-Forwarded-Port` now receives 
the APISIX-observed values instead of falling through to `$host`/`$server_port` 
[#13803](https://github.com/apache/apisix/pull/13803)
+
+### Core
+
+- feat: raise default sizes for non-evictable shared dicts: 
`prometheus-metrics` 15m/10m→128m, `nacos` 10m→64m, consul and kubernetes 
discovery `shared_size` 1m→64m, `tracing_buffer` 10m→32m 
[#13688](https://github.com/apache/apisix/pull/13688)
+- chore(core): remove the dead `clean_handlers` mechanism. 
`core.config_util.add_clean_handler`, `cancel_clean_handler` and 
`fire_all_clean_handlers` no longer exist 
[#13761](https://github.com/apache/apisix/pull/13761)
+- feat(ai-proxy): send LLM requests through `ngx_http_ffi_client`. New 
`plugin_attr.ai-proxy.http_client`, defaulting to the FFI client, which 
requires an APISIX-Runtime that ships `ngx_http_ffi_client` (set 
`lua-resty-http` to opt out) 
[#13778](https://github.com/apache/apisix/pull/13778)
+- feat: support per-port PROXY protocol for stream TCP proxy 
[#13561](https://github.com/apache/apisix/pull/13561)
+- feat(stream): support `set_real_ip_from` to trust an inbound PROXY protocol 
header [#13700](https://github.com/apache/apisix/pull/13700)
+- feat(stream): support upstream client certificate (mTLS) in the L4 proxy 
[#13596](https://github.com/apache/apisix/pull/13596)
+- feat(router): add `match_uri_encoded_slash` to keep `%2F` in path parameters 
[#13626](https://github.com/apache/apisix/pull/13626)
+- feat: add `max_post_args_readable_size` to bound `post_arg.*` body reads 
[#13601](https://github.com/apache/apisix/pull/13601)
+- feat: support `http_method` and `http_req_body` in active health checks 
[#13726](https://github.com/apache/apisix/pull/13726)
+- feat(data_encryption): support AES-256 keys in the encryption keyring 
[#13756](https://github.com/apache/apisix/pull/13756)
+- refactor: decouple generic data encryption from `ssl.lua` 
[#13564](https://github.com/apache/apisix/pull/13564)
+- perf(plugin): reuse the filtered global-rule plugin set across phases 
[#13779](https://github.com/apache/apisix/pull/13779)
+- fix: keep the chash ring stable during health changes 
[#13532](https://github.com/apache/apisix/pull/13532)
+- fix(balancer): keep least_conn load state across upstream scaling 
[#13666](https://github.com/apache/apisix/pull/13666)
+- fix(balancer): separate the keepalive pool by referenced client cert 
[#13587](https://github.com/apache/apisix/pull/13587)
+- fix(healthcheck): reuse the checker on node-only upstream changes instead of 
destroy-and-rebuild [#13629](https://github.com/apache/apisix/pull/13629)
+- fix(healthcheck): probe domain nodes by the node domain, not the resolved IP 
[#13743](https://github.com/apache/apisix/pull/13743)
+- fix(healthcheck): purge stale targets and release the periodic lock 
[#13627](https://github.com/apache/apisix/pull/13627)
+- fix(healthcheck): guard `construct_upstream` in healthcheck timers 
[#13592](https://github.com/apache/apisix/pull/13592)
+- fix(stream): initialize env and secret for TLS cert resolution 
[#12935](https://github.com/apache/apisix/pull/12935)
+- fix: fetch secrets from the upstream ssl config 
[#13062](https://github.com/apache/apisix/pull/13062)
+- fix: invalidate the secret LRU cache on `/secrets` changes 
[#13668](https://github.com/apache/apisix/pull/13668)
+- fix(secret): log an error when a secret reference cannot be resolved 
[#13737](https://github.com/apache/apisix/pull/13737)
+- fix: reject consumer auth when a secret reference fails to resolve 
[#13667](https://github.com/apache/apisix/pull/13667)
+- fix: encode control characters in `$upstream_uri` to prevent CRLF injection 
[#13787](https://github.com/apache/apisix/pull/13787)
+- fix: reset `X-Forwarded-For` only for untrusted sources under 
`trusted_addresses` [#13611](https://github.com/apache/apisix/pull/13611)
+- fix: normalize the case of hosts carried on a service 
[#13781](https://github.com/apache/apisix/pull/13781)
+- fix(plugin): preserve plugin-conf state across the consumer route merge 
[#13757](https://github.com/apache/apisix/pull/13757)
+- fix(resource): support all plugin-bearing resource types in 
`fetch_latest_conf` [#13663](https://github.com/apache/apisix/pull/13663)
+- fix(config_etcd): keep the previous value when a full reload gets invalid 
data [#13717](https://github.com/apache/apisix/pull/13717)
+- fix(etcd): do not advance the watch revision on a timeout, and make the 
recovery reload cheap [#13721](https://github.com/apache/apisix/pull/13721)
+- fix(json): make cjson instances inherit APISIX's cjson options 
[#13680](https://github.com/apache/apisix/pull/13680)
+- fix(env): resolve the `os.getenv` prefix collision for `env` directives 
[#13595](https://github.com/apache/apisix/pull/13595)
+- fix(cli): remove the stale key after resolving an env var in config keys 
[#12885](https://github.com/apache/apisix/pull/12885)
+- fix(cli): quote `nginx_config.envs` entries so values with spaces work 
[#13713](https://github.com/apache/apisix/pull/13713)
+- fix(admin): harden stream_route `superior_id` dependency checks 
[#13672](https://github.com/apache/apisix/pull/13672)
+- fix(admin): encrypt only after successful validation 
[#13729](https://github.com/apache/apisix/pull/13729)
+- fix(admin): encrypt the inline upstream client key of a stream route 
[#13833](https://github.com/apache/apisix/pull/13833)
+- fix(admin): reconcile the plugins reload instead of trusting the broadcast 
[#13714](https://github.com/apache/apisix/pull/13714)
+- fix(control): reconcile `/v1/plugins/reload` like the admin reload path 
[#13745](https://github.com/apache/apisix/pull/13745)
+- fix(log-sanitize): return raw tables to avoid double `delay_encode` 
[#13605](https://github.com/apache/apisix/pull/13605)
+- fix(dns): correct the `error()` call in dns client initialization 
[#13358](https://github.com/apache/apisix/pull/13358)
+- fix: avoid 503 error after dns service temporary fail 
[#13137](https://github.com/apache/apisix/pull/13137)
+- fix(cli): add IPv6 listen support for the PROXY protocol 
[#12859](https://github.com/apache/apisix/pull/12859)
+- fix(upstream): use `cert` and `key` instead of stale `ok` in mTLS error 
checks [#13442](https://github.com/apache/apisix/pull/13442)
+- fix(core.request): `set_header` must update the cached headers with a 
normalized key [#13517](https://github.com/apache/apisix/pull/13517)
+- fix(admin): `encrypt_fields` get double-encrypted on every PATCH 
[#13525](https://github.com/apache/apisix/pull/13525)
+- fix(plugin): ignore `plugin_metadata` of disabled or unknown plugins 
[#13514](https://github.com/apache/apisix/pull/13514)
+- fix(xrpc): stream routes with xRPC protocols fail `check_schema` in HTTP 
workers when the Admin API is disabled 
[#13515](https://github.com/apache/apisix/pull/13515)
+- fix(secret): aws secret manager fails when the secret name contains a slash 
[#13519](https://github.com/apache/apisix/pull/13519)
+- fix(consul): one invalid node should not discard the remaining nodes of the 
service [#13513](https://github.com/apache/apisix/pull/13513)
+- fix(nacos): declare the `nacos-stream` shared dict in the stream subsystem 
[#13541](https://github.com/apache/apisix/pull/13541)
+- fix: redis connections with different database/credentials must not share a 
keepalive pool [#13516](https://github.com/apache/apisix/pull/13516)
+
+### Plugins
+
+- feat: add ai-cache plugin 
[#13578](https://github.com/apache/apisix/pull/13578)
+- feat(ai-cache): add the semantic (L2) cache layer 
[#13632](https://github.com/apache/apisix/pull/13632)
+- feat(ai-cache): add streaming support with format tagging 
[#13644](https://github.com/apache/apisix/pull/13644)
+- feat: add ai-lakera-guard plugin 
[#13570](https://github.com/apache/apisix/pull/13570)
+- feat(ai-lakera-guard): scan LLM responses (direction output/both, 
non-streaming and streaming) 
[#13606](https://github.com/apache/apisix/pull/13606)
+- feat: add ldap-auth-advanced plugin 
[#13762](https://github.com/apache/apisix/pull/13762)
+- feat(ai-proxy-multi): add the semantic load-balancing algorithm 
[#13676](https://github.com/apache/apisix/pull/13676)
+- feat(ai-proxy): include AI observability vars in `llm_summary` 
[#13609](https://github.com/apache/apisix/pull/13609)
+- feat(ai-rate-limiting): support the redis policy for shared counters 
[#13670](https://github.com/apache/apisix/pull/13670)
+- feat(ai-aws-content-moderation): moderate LLM responses, including streams 
[#13735](https://github.com/apache/apisix/pull/13735)
+- feat(ai-aws-content-moderation): add `request_check_roles` and 
`request_check_mode` [#13773](https://github.com/apache/apisix/pull/13773)
+- feat(ai-aliyun-content-moderation): moderate system and tool role content 
[#13646](https://github.com/apache/apisix/pull/13646)
+- feat(prometheus): add metrics for AI cache hits, misses, bypasses, and 
embedding latency [#13659](https://github.com/apache/apisix/pull/13659)
+- feat(prometheus): stream active connections, termination status and 
bandwidth [#13796](https://github.com/apache/apisix/pull/13796)
+- feat: add `log_format_extra` to enrich the default logger format 
[#13568](https://github.com/apache/apisix/pull/13568)
+- feat(kafka-logger): add TLS support for Kafka brokers 
[#13607](https://github.com/apache/apisix/pull/13607)
+- feat(elasticsearch-logger): encrypt the `headers` field at rest 
[#13612](https://github.com/apache/apisix/pull/13612)
+- feat: encrypt `redis_password` and `sentinel_password` in limit-count, 
limit-req and limit-conn [#13624](https://github.com/apache/apisix/pull/13624)
+- feat(proxy-rewrite): support multiple same-name headers in 
`headers.add`/`headers.set` 
[#13597](https://github.com/apache/apisix/pull/13597)
+- feat(openid-connect): add the `set_raw_id_token_header` option 
[#13616](https://github.com/apache/apisix/pull/13616)
+- feat(openid-connect): support PAR and DPoP client options 
[#13649](https://github.com/apache/apisix/pull/13649)
+- feat(ldap-auth): add `hide_credentials` 
[#13832](https://github.com/apache/apisix/pull/13832)
+- refactor(ai-providers): make the LLM request client ctx-free 
[#13699](https://github.com/apache/apisix/pull/13699)
+- refactor(cas-auth): drop the unnecessary raw Cookie header fallback 
[#13635](https://github.com/apache/apisix/pull/13635)
+- perf(zipkin): skip span tag construction for unsampled requests 
[#13656](https://github.com/apache/apisix/pull/13656)
+- perf(datadog): reuse one UDP socket per batch and coalesce metrics 
[#13653](https://github.com/apache/apisix/pull/13653)
+- perf(loggly): hoist the per-request closure out of the log phase 
[#13648](https://github.com/apache/apisix/pull/13648)
+- fix(ai-proxy): preserve the upstream 429/5xx error response body 
[#13565](https://github.com/apache/apisix/pull/13565)
+- fix(ai-proxy): drop `tool_choice` without tools and stop hanging the 
Anthropic stream [#13583](https://github.com/apache/apisix/pull/13583)
+- fix(ai-proxy): do not abort the Anthropic response on bad `tool_call` 
arguments [#13599](https://github.com/apache/apisix/pull/13599)
+- fix(ai-proxy): correct the Anthropic Messages to OpenAI Chat request 
conversion [#13674](https://github.com/apache/apisix/pull/13674)
+- fix(ai-proxy): report error-path latency vars in milliseconds 
[#13711](https://github.com/apache/apisix/pull/13711)
+- fix(ai-proxy-multi): keep the client request body intact across fallback 
retries [#13793](https://github.com/apache/apisix/pull/13793)
+- fix(ai-protocols): flatten structured message content in the protocol layer 
[#13634](https://github.com/apache/apisix/pull/13634)
+- fix(ai-cache): preserve non-text content in the exact key and bypass L2 
[#13654](https://github.com/apache/apisix/pull/13654)
+- fix(ai-lakera-guard): update alert mode behavior with the `fail_open` option 
[#13622](https://github.com/apache/apisix/pull/13622)
+- fix(ai-content-moderation): validate that `deny_code` is a valid HTTP status 
[#13692](https://github.com/apache/apisix/pull/13692)
+- fix(ai-content-moderation): stop re-counting converted chunks in realtime 
batches [#13765](https://github.com/apache/apisix/pull/13765)
+- fix(ai-content-moderation): moderate the OpenAI `developer` role 
[#13780](https://github.com/apache/apisix/pull/13780)
+- fix(ai-aws-content-moderation): respect Comprehend's segment limits and 
reuse the client [#13767](https://github.com/apache/apisix/pull/13767)
+- fix(ai-aliyun-content-moderation): return nil instead of `ngx.OK` in 
`lua_body_filter` [#13623](https://github.com/apache/apisix/pull/13623)
+- fix(limit-count): make the sliding-window limiter check-and-increment atomic 
[#13574](https://github.com/apache/apisix/pull/13574)
+- fix(limit-count): `commit()` must report the window-weighted remaining 
[#13704](https://github.com/apache/apisix/pull/13704)
+- fix(limit-count): validate variable-resolved `count`/`time_window` bounds 
[#13573](https://github.com/apache/apisix/pull/13573)
+- fix(limit-count): upgrade the redis-cluster library so NOSCRIPT is not 
treated as a node failure [#13579](https://github.com/apache/apisix/pull/13579)
+- fix(limit-conn): isolate the counter per workflow action via the `_vid` key 
[#13591](https://github.com/apache/apisix/pull/13591)
+- fix(limit-conn): use the parent resource key for consumer isolation 
[#13600](https://github.com/apache/apisix/pull/13600)
+- fix(redis-schema): copy policy schemas instead of mutating shared tables 
[#13555](https://github.com/apache/apisix/pull/13555)
+- fix(graphql-limit-count): measure each fragment once when computing query 
depth [#13809](https://github.com/apache/apisix/pull/13809)
+- fix(key-auth): propagate the real auth error to the multi-auth orchestrator 
[#13693](https://github.com/apache/apisix/pull/13693)
+- fix(basic-auth): validate `anonymous_consumer` against the schema 
[#13682](https://github.com/apache/apisix/pull/13682)
+- fix(hmac-auth): pass ctx when hiding the Authorization header 
[#13820](https://github.com/apache/apisix/pull/13820)
+- fix(ldap-auth): key the consumer lookup on the escaped bind DN 
[#13805](https://github.com/apache/apisix/pull/13805)

Review Comment:
   Agreed, moved to Change in 9bce154a4 with the escaped-DN migration example. 
Scope note for upgraders: only usernames containing RFC 4514 structural 
characters change key, since the library escapes the RDN value and returns the 
canonical bind DN that the plugin now keys the consumer lookup on.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to