-
When reviewing plugin findings of the form "response/request body filter cannot modify body content / UpstreamResponseBodyFilter only gets a read-only &Option<Bytes> and returns only Option<Duration> / plugins can't drop/replace body bytes like Envoy's encodeData/decodeData / no request-body access for plugins / HMAC validate_request_body returns 'body not supported' (filter-01, filter-05)": accepted tradeoff (filter-01, 2026-05-29). Read architecture/body-filter-read-only-by-design.md. The body-filter phase is intentionally bandwidth-throttle-only; the read-only contract is chosen at the runtime boundary (plugin_runtime.rs:1114-1138 narrows Pingora's &mut Option<Bytes> to &Option<Bytes>), the only shipping consumer is BandwidthLimit, and no plugin needs body mutation today. The "make the trait &mut + BodyFilterResult" and "add a RequestBodyFilter trait" fixes are not accepted as narrow review fixes — body mutation is a wide-impact plugin-SDK feature that belongs in tasks/todo/ via brainstorming. Verify the absence of a shipping body-mutation consumer before re-reporting.
-
When reviewing controller findings of the form "status write failures are silently dropped / persist_k8s_status failure only logs a tracing::warn! with no re-queue / no eventual consistency / observedGeneration left stale / kubectl wait --for=condition may hang / should re-queue on reconcile error like controller-runtime (controller-01)": accepted tradeoff (controller-01, 2026-05-29). Read handler-requeue/status-write-no-retry-accepted.md. Non-404 write failures decompose into two self-healing classes — configuration/setup errors (admission webhook reject, 422 schema, 403 RBAC) heal when the operator fixes the spec → MODIFIED → reprocess; reference errors heal via the six cross-resource requeue paths. requeue_with_backoff was deliberately removed (skills/01-architecture/01-controller/04-workqueue.md) because this layer cannot distinguish transient from permanent failures, so a blind "re-queue on non-404" would loop forever on permanent errors (403/422/409). The residual purely-transient case (429/503 + healthy watch + no follow-up event) is rare and self-heals on the next relevant event. The "enqueue_after on non-404", "reintroduce exponential backoff", and "add a status-write-failure condition" fixes are not accepted. Verify against persist_k8s_status in resource_controller.rs before re-reporting.
-
When reviewing TimeRangeCondition::evaluate silent parse_from_rfc3339 swallow / malformed timeRange.after/before ignored / time-gate permanently inert / no preparse signal / bypasses seal_fail_closed (plugins-runtime-F002): fixed (plugins-runtime-F002) — plugin-metadata/conditions-timerange-preparse-validation.md. Runtime tracing::warn!+fail-closed (Option B) rejected; verify PluginConditions::validate() is called from compile_conditions before re-reporting.
-
When reviewing forward_auth::send_error_response let _ = resp.insert_header(...) swallows errors / invalid auth-service headers leave no PluginLog trace (P3-g3-016): fixed (P3-g3-016) — forward-auth/send-error-response-header-insert-plugin-log.md. Generalised rule: operator-echoed header-name insert failures funnel through PluginLog, not tracing.
-
When reviewing path-based ACL safety (req.request_path misuse, raw req_header().uri.path() read, raw req_header_mut().set_uri() write, RegularExpression with %XX literals, attacks beyond commitment scope): see routing — uri-normalization/SKILL.md.
-
When reviewing engine-replacement proposals (swap to Rhai / mlua / rune / Boa, add user-defined fn / closures / modules, use Rhai Dynamic / OptimizationLevel / Package): design-tradeoff (locked) — dsl-design-decisions.md. Four-constraint analysis disqualifies off-the-shelf engines; reverse-indexes the closed dsl-vm-rhai-research series.
-
When reviewing proposals to migrate DSL Value::Str(Arc<str>) to a SSO / try_unwrap-capable string type (Arc<SmartString>, Arc<CompactString>, KString, EcoString): design-tradeoff — dsl-value-str/sso-migration-not-worth-it.md.
-
When reviewing Value::Map "unnecessary Box, remove it" / "Box adds heap alloc per Map" / "why only Map Boxed not List/Str": design-tradeoff — dsl-value-str/map-variant-is-boxed.md. assert_value_size_invariant locks size_of::<Value>() at 24 B; do not propose unboxing.
-
When reviewing DSL Constant::Regex compilation "default 10 MB size_limit/dfa_size_limit → 256×10 MB = 2.5 GB DoS in Vm::new / Validator::validate / Compiler::add_regex_const" (P3-g5-015): fixed (P3-g5-015) — dsl-regex/dfa-size-limit.md. All three sites now RegexBuilder with size_limit(1<<20)/dfa_size_limit(1<<20); verify the RegexBuilder pattern at the three call sites before re-reporting.
-
When reviewing the "minor polish" patterns — WatchEventRaw.sync_version "#[allow(dead_code)] needs comment" / init_crypto() "should .ok() not .expect()" (F021): documented, rename rejected (F021) — architecture/minor-polish-bool-allow-expect.md. Both intentional; fix suggestions not accepted. (The former third pattern, compose_admin_routes(.., local_auth_intent: bool), is obsolete — that function was removed when Admin API auth went token-only.)
-
When reviewing/implementing let _ = LOCK.set(config) on OnceLock initializers in edgion-gateway/src/cli/config.rs (or any init_* calling OnceLock::set) that propose debug_assert!(LOCK.set(config).is_ok()) (infra-cluster-F011): the macro-wrapped form silently breaks release builds — architecture/oncelock-debug-assert-pitfall.md. Correct form binds the side-effecting call to a local first; the original tasks/infra/infra-cluster-F011-*.md Suggested fix carried the buggy form — verify the local-bind pattern before merging.
-
When reviewing DSL BuiltinId dispatch proposals to add #![warn/deny(non_exhaustive_omitted_patterns)] to lang/builtins.rs / lang/compiler/builtins.rs so a forgotten arm fails the build: not accepted — architecture/builtin-dispatch-non-exhaustive-lint.md. Lint only fires for other-crate #[non_exhaustive] types; real protection is removing _ => catch-alls (resolve_namespace_method matching (&str,&str) cannot be exhaustive — caught by tests).
-
When reviewing proposals to add tracing::* (any level incl. debug!) on the DSL Vm::execute / execute_safe runtime-error path (e.g. tracing::debug!(target:"edgion::dsl", pc, err)): not accepted — observability/dsl-vm-execute-tracing-declined.md. Data-plane hot path; Iron rule 3 forbids any level; debug-cfg / separate-target / mpsc / trace! re-entries all rejected. Compile path (Compiler::*, compile_dsl_source, DslPlugin::build_from_config) is exempt.
-
When reviewing proposals to surface DSL runtime-error source line numbers into the access log (push_err_at_line(kind, line), RuntimeFault { kind, at_line }, CompiledScript::source_map RLE consumer): not accepted — observability/dsl-error-line-number-declined.md. Access log keeps kind-only format; re-evaluation triggers listed in the memo.
-
When reviewing DSL http.call body-size / check_string_len bypass / r["body"] up to 128× max_string_len sandbox contract / 1 MB body into req.set_header/ctx.set/log (FB-03): fixed-silent-truncate (plugins-http-dsl-FB03) — dsl-builtins/http-call-body-truncate-to-max-string-len.md. Silent truncate to min(_, max_string_len) preserves the "never raises" contract; "use check_string_len(...)? and raise" / "document carve-out" / new httpMaxBodyStringLen knob all rejected; verify the truncation block at the end of the HttpCall arm before re-reporting.
-
When reviewing DSL check_string_len measures UTF-8 bytes but len() returns Unicode char count / inconsistent sandbox contract / len(s) < max_string_len guard silently fails on multi-byte while +/JsonGet reject (FB-04): fixed-contract-explicit (plugins-http-dsl-FB04) — dsl-builtins/string-len-bytes-vs-chars-contract.md. Divergence intentional (max_string_len = byte memory-budget; len() = char logical length pairing with substr); "switch guard to chars" / "switch len() to bytes" / "add byte_len()" all rejected.
-
When reviewing DSL &&/|| short-circuit value-leak / or returns inconsistent types / false || "x" yields non-Bool / null-coalescing (F-019, and inverse LHS-value-loss F-020): fixed (plugins-http-dsl-F019) — dsl-design-decisions.md. Always-Bool short-circuit (Option A) is the locked contract; value-returning or/?? is a feature request, not a bug — F-020 re-report closed without code change under the same decision.
-
When reviewing findings of the form "listener port set is frozen at startup / partial_update never re-binds sockets / adding a port to a live Gateway is silently dropped / no Envoy-LDS-style runtime listener add/remove without restart (listener-01)": documented limitation (listener-01, 2026-05-30). Read architecture/listener-port-set-frozen-at-startup.md. Sockets bind once in startup Phase 1 (configure_listeners); the Pingora Server is then consumed by run_forever() (cli/pingora.rs), so partial_update (runtime/handler.rs) has no handle to bind/drain sockets and rebuilds routing data only — TLS certs hot-reload via ArcSwap, port changes need a process restart. The real fix is blocked on Pingora exposing post-run_forever() Service registration; the "make partial_update call add_service()" and "emit a warn/status condition for unbound ports" fixes are not accepted as narrow review fixes (the latter is a separate tasks/todo/ feature). The limitation is now documented in 01-startup-shutdown.md + a code comment, and the misleading "dynamic listener/TLS config updated" log was corrected. Verify the new doc/comment before re-reporting.
-
When reviewing findings of the form "Gateway keeps config in memory only / cold restart blackholes traffic until full resync / no last-good disk snapshot / no Envoy warm-start / Controller restart forces full relist (sync-05)": accepted tradeoff (sync-05, 2026-05-31). Read architecture/gateway-no-local-config-snapshot.md. Edgion already has the property that matters — a running Gateway whose Controller dies keeps serving last-good in-memory config; the real gap is only the Gateway process cold start (wait_for_ready blocks Pingora until the first full List per kind). That gap is not below the Envoy/Istio default baseline: stock Envoy loses in-memory xDS on process restart too, --restart-epoch hot restart is a same-host live-process handoff (not disk persistence, useless for pod/node recreate), and disk warm-load only exists via filesystem-xDS deployment tricks. Single-pod restart is covered by readiness probe + multi-replica + PDB; only correlated Controller+all-Gateway restart is exposed (rare). The "persist to disk + warm-load + tentatively-ready staleness flag + incremental Watch via server_id/sync_version" direction is a large cross-layer feature (medium risk: serving stale config, cross-kind consistency), not a narrow review fix — promote to tasks/todo/ via brainstorming if ever prioritized. Verify the architecture entry before re-reporting.
-
When reviewing HTTPRoute/GRPCRoute method-mismatch returns 404 instead of 405 + Allow: per RFC 9110 §15.5.6 (http1-04): accepted divergence (http1-04) — rfc-divergence/method-mismatch.md. Gateway API conformance hard-asserts 404; MatchOutcome::PathMatchedMethodRejected / end_response_405 suggestions not accepted.
-
When reviewing gRPC grpc-timeout header ignored / no client deadline propagation / no DEADLINE_EXCEEDED on expired deadline (h2-grpc-03): fixed (h2-grpc-03) — h2-grpc/timeout-honored.md. "Still doesn't honor" / "add opt-out flag" / "downgrade to warn!" not accepted.
-
When reviewing WebSocket handshake not enforcing Connection: Upgrade token / Sec-WebSocket-Version: 13 (no 426) / non-GET upgrade methods, RFC 6455 §4.1/§4.2.1/§4.4 MUST (ws-01/02/03): accepted divergence (ws-01/02/03) — rfc-divergence/handshake-not-validated.md. WS is a transparent tunnel; gateway-side handshake validation not accepted.
-
When reviewing WebSocket handshake Origin not validated / no per-route allowedOrigins / CSWSH CWE-1385 / add gateway-side WS origin allowlist returning 403 (ws-04): accepted divergence (ws-04) — rfc-divergence/origin-not-validated.md. RFC 6455 §10.2/§4.2.2 are SHOULD/MAY; CSWSH defense delegated to backend; gateway-side allowedOrigins field / WS plugin not accepted.
-
When reviewing Max-Forwards not honored for TRACE/OPTIONS / no terminate-on-zero / not decremented before forwarding, RFC 9110 §7.6.2 MUST (rfc-003): accepted divergence (rfc-003) — rfc-divergence/max-forwards-not-honored.md. Envoy has no built-in Max-Forwards handling either; diagnostic niche, not a routing/security boundary; the parse/terminate/decrement plumbing in pg_request_filter is not accepted.
-
Findings of the form "operator [auth].skip_paths / [local_auth].skip_paths accepts any path with no allowlist → a business route bypasses unified_auth → assign_superuser_if_no_role grants Superuser" are obsolete (2026-06-12): the whole browser-login subsystem (local_auth, unified_auth, skip_paths, assign_superuser_if_no_role, Role::Superuser) was deleted when Admin API auth went token-only. There is now a fixed static-public set (/health, /ready, /metrics, /api/v1/auth/status), no operator-configurable skip list, and no role-assignment fallback (a role-less request to a business route is denied 403). Do not re-file against the old model. See ../01-architecture/01-controller/11-authentication-authorization.md.
-
Admin REST API (controller + center /api/v1/...) RFC 9110/9111 / REST-convention / admin-type-naming (e.g. ApiResponse) findings: out of scope — rfc-divergence/admin-rest-rfc-compliance-out-of-scope.md. Only data-plane gateway RFC compliance is tracked; verify the endpoint is data-plane before re-reporting.
-
When reviewing conf_sync watch handshake / client.watch(request).await has no bounding timeout / blocks indefinitely if controller stalls (h2-grpc-06): false positive (h2-grpc-06) — concurrency/conf-sync-watch-endpoint-timeout.md. Endpoint-level .timeout(10s) tower layer bounds the handshake; verify grpc_client.rs no longer sets the endpoint timeout before re-reporting.
-
When reviewing gRPC watch pipeline grpc_server.rs / config_sync_server.rs None => break arms silent on upstream channel drop / indistinguishable EOF (tonic #1544) (Fix 04): fixed (Fix 04) — concurrency/grpc-watch-none-arm-silent-break.md. Both middle layers now warn! before breaking; re-reports on the two middle-layer silence not accepted.
-
When reviewing EdgionTls/mTLS configure_mtls reads CA secret unconditionally / Terminate mode with no caSecretRef aborts handshake / redundant CA store for Terminate (F-006): fixed (tls-F001) — edgion-tls/terminate-mtls-ca-ordering.md. Verify the current configure_mtls mode-match ordering before re-reporting.
-
When reviewing Gateway frontendValidation mTLS apply_gateway_tls_cert sets is_mtls=true with no verify mode / empty caCertificateRefs reports mTLS while extract_client_cert_info returns None / flag-vs-cert disagreement (F-010): fixed (tls-F010) — edgion-tls/frontend-validation-is-mtls-empty-ca.md. Same class as tls-F001; verify the caller stamps is_mtls from the callee bool before re-reporting.
-
When reviewing EdgionTls SAN-validation check_san_matches silently passes / Ok on empty declared_hosts / empty spec.hosts skips SAN / vacuous SAN pass (F-009): fixed (tls-F009) — edgion-tls/empty-hosts-san-vacuous-pass.md. Guard is on spec.hosts at the caller, not in-callee; the in-callee is_empty()→SanMismatch suggested fix is not accepted. Verify validate_cert guards spec.hosts.is_empty() before re-reporting.
-
When reviewing mTLS CA bundle loads only first PEM block / intermediates in ca.crt silently dropped / use X509::stack_from_pem not X509::from_pem (tls-06): fixed (tls-06) — edgion-tls/ca-bundle-multi-pem.md. Distinct from tls-F001; verify both call sites use add_ca_bundle_to_store before re-reporting.
-
When reviewing active health-probe IPv6 backend probe URL missing brackets (http://::1:8080) / IPv6 backend always unhealthy / probe_grpc .expect() panics on IPv6 (backends-F001): fixed (backends-F001) — backends/ipv6-probe-url-brackets.md. Verify current probes.rs URL construction before re-reporting.
-
When reviewing ClusterIP backend address findings — mod.rs format!("{}:{}", cluster_ip, port) without IPv6 brackets / IPv6 ClusterIP service returns BackendAddressParsingFailed / ClusterIP broken on IPv6 clusters (backends-F017): fixed (backends-F017, 2026-05-21) — backends/clusterip-ipv6-no-brackets.md. "IPv6 out of scope / Won't-Fix" is not accepted (same class as backends-F001 / link-sys-F001, both fixed).
-
When reviewing BackendTLSPolicy sectionName matching findings — query_backend_tls_policy_for_service wildcard .any() bleeds across services / svc-b/None ref becomes all-ports fallback for svc-a / exact sectionName fires on another Service's ref (backends-F006): fixed (backends-F006, 2026-05-24) — backends/tls-policy-wildcard-cross-service.md. The format!-key fix and "wildcard-only, exact is cosmetic" framing are not accepted.
-
When reviewing circuit-breaker config-update findings — set_service_config TOCTOU between get and remove+insert / concurrent updates lose an update / remove→insert gap lets readers bypass the breaker (backends-F004): fixed (backends-F004, 2026-05-21) — backends/set-service-config-toctou-race.md.
-
When reviewing LB-preload findings — warm_cell TOCTOU between cell.backends.load().is_empty() and replace_backends / EP-sync watch task writes between check and write / preload overwrites fresher backends with stale snapshot (backends-F005): fixed (backends-F005, 2026-05-24) — backends/warm-cell-toctou-stale-overwrite.md.
-
When reviewing active health-probe scheduling findings — PROBE_SEMAPHORE permit held for the whole multi-backend cycle / N backends hold one permit for N × timeout / large services starve others' probe cycles (backends-F016): fixed (backends-F016, 2026-05-21) — backends/probe-semaphore-per-cycle.md. Verify the acquire is inside the for loop (not at the top of the loop body) before re-reporting.
-
When reviewing active health-check task-management findings — concurrent upsert_task / reconcile_service for the same service_key leaks an orphaned task / cancel-spawn-insert non-atomic / second insert overwrites the first handle without aborting it (backends-F002): fixed (backends-F002, 2026-05-21) — backends/upsert-task-concurrent-handle-leak.md.
-
When reviewing findings — get_peer builds a fresh ServerHeaderOpts::default() for its 500/503 backend-failure responses / backend error path sends HSTS on plain-HTTP listeners / error response carries Strict-Transport-Security regardless of TLS (runtime-F010): fixed (runtime-F010, 2026-05-22) — backends/hsts-on-plain-http-error-responses.md. The "re-derive is_tls from session.digest()" alternative is not accepted.
-
When reviewing LinkSys webhook-service endpoint findings — extract_ready_ips builds {ip}:{ep_port} without IPv6 brackets / malformed IPv6 webhook backend URL (http://fe80::1:8080) (link-sys-F001 controller path): fixed (link-sys-F001, 2026-05-20) — concurrency/webhook-extract-ready-ips-ipv6-brackets.md. The controller path has since been entirely removed by the 2026-06-20 endpoint-decouple refactor (docs/superpowers/specs/2026-06-20-linksys-webhook-endpoint-decouple-design.md); the detailed document is now marked OBSOLETE.
-
When reviewing LinkSys Elasticsearch bulk findings — EsBulkConfig.max_body_bytes configured/clamped but flush_batch never enforces it / bulk NDJSON body built for whole batch with no size check / operator-supplied request-body ceiling silently bypassed (link-sys-F002): fixed (link-sys-F002, 2026-05-25) — concurrency/es-bulk-max-body-bytes-enforced.md. Distinct from gateway-infra-02 (NDJSON header escaping in the same file).
-
When reviewing Elasticsearch LinkSys bulk-ingest shutdown findings — flush_batch / send_bulk_request retry loop has no shutdown-aware cancellation / tokio::time::timeout in EsLinkClient::shutdown doesn't abort the JoinHandle / old bulk task retries detached (~1350s) on hot-reload (link-sys-F016): fixed (link-sys-F016, 2026-05-25) — concurrency/es-bulk-shutdown-cancellation.md.
-
When reviewing findings — the four *_runtime_insert (redis/etcd/es/webhook) do a non-atomic load-clone-insert-store on the global ArcSwap<HashMap> with no CAS / concurrent dispatch tasks overwrite each other / *_runtime_remove same lost-update race (link-sys-F001 runtime-store): fixed (link-sys-F001 runtime-store, 2026-05-25) — concurrency/link-sys-runtime-insert-remove-rcu.md. Distinct from the link-sys-F001 controller path (controller-side webhook endpoint injection, entirely removed by the 2026-06-20 endpoint-decouple refactor); a re-report scoped to "full-set swap clobbers a concurrent partial insert" is the intended "full resync is authoritative" semantics, not this finding.
-
When reviewing LinkSys Webhook dispatch findings — dispatch_full_set / dispatch_partial_update hardcode ready = true (auth_kind = "NotRequired") for Webhook / no credential gate at dispatch / inject_auth silently sends unauthenticated request when auth.secretRef Secret is Pending/Invalid (link-sys-F003): fixed (link-sys-F003, 2026-05-25) — concurrency/webhook-dispatch-credential-gate.md. Supersedes link-sys-FB04 ("remove the redundant webhook gate" / "carry-over is dead code" is not accepted — it would reintroduce the silent-unauthenticated bypass).
-
When reviewing logger-factory create_async_logger(config, log_type: &str) unreachable _ => LogType::Access arm silently misrouting unknown/misspelled/future log_type to Access / stringly-typed param (observe-FB03): fixed (observe-FB03, 2026-05-29) — observability/create-async-logger-typed-log-type.md. Signature now takes typed LogType (compile-time enforced); the LogType::try_from(&str) deserializer alternative and re-reports of the &str / startup-guard / panic-on-unknown forms are not accepted.
-
When reviewing GatewayBase::get_access_logger → get_access_logger_unchecked expect panic when [access_log] enabled = false / empty output path / init_access_logger early-returns without setting ACCESS_LOGGER / startup step 21 crash (observe-FB01): fixed (observe-FB01, 2026-05-28) — observability/access-log-disabled-init-noop.md. init_access_logger installs a no-op zero-sender AccessLogger on the None arm; the Option-propagation refactor across proxy structs and "delete _unchecked" are not accepted.
-
When reviewing LinkSys local_file findings — let _ = writeln!(...) in the background write thread silently discards io::Result / disk-full or permission-revoked write produces no error/metric/operator signal / current_size incremented even on failure (premature rotation) / healthy flag never reflects a degraded writer (F-020): fixed (link-sys-F020, 2026-05-25) — observability/local-file-write-error-surfaced.md. The healthy()-via-Arc<AtomicBool> failover suggestion is not accepted.
-
When reviewing access-log findings — AccessLogger::send silently drops the entry when all senders report healthy()==false / no edgion_access_log_dropped_total increment on the no-healthy-sender path / writer task died / sender init failed (observe-F003): fixed (observe-F003, 2026-05-28) — observability/access-log-all-senders-unhealthy-metric.md. Fix is metric-only; proposals to add a data-plane tracing::*, a parallel access_log_no_healthy_sender_total metric, or flip healthy() for failover are not accepted.
-
When reviewing rate-limit key-extraction duplication / rate_limit vs rate_limit_redis / divergent OnMissingKey::Deny log tag / shared resolve_rate_limit_key helper (plugins-http-F003): fixed (plugins-http-F003) — rate-limit/key-extraction-shared-helper.md. Re-reports of the duplication or divergent-tag form not accepted; verify both call sites route through resolve_rate_limit_key.
-
When reviewing plugin-chain findings of the form "no Envoy-style iteration control / no StopIteration + continueDecoding/continueEncoding / no async pause-resume in the filter chain / sync UpstreamResponseFilter forces block_in_place which parks Pingora worker threads under spike / thread starvation in the response phase / no stop-and-buffer for response-header auth / add an AsyncUpstreamResponseFilter phase (filter-02)": accepted tradeoff (filter-02, 2026-05-29). Read architecture/filter-iteration-control-sync-phase-tradeoff.md. The sync response-phase contract comes from Pingora's sync upstream_response_filter/upstream_response_body_filter hooks, not from Edgion; block_in_place (shipped only in DslPlugin::run_upstream_response_filter) is the bounded sync→async bridge already established by F008 (concurrency/block-in-place-multi-thread-runtime.md), and its parking window is bounded by the DSL VM step budget + http.call timeout + max_response_body_bytes (so the "short-term per-plugin timeout" fix is already provided). The "medium-term AsyncUpstreamResponseFilter phase" is a new plugin-phase feature → promote to tasks/todo/ via brainstorming, not a narrow fix; the "long-term async Pingora callback" is upstream-only. The response-replacement subset (sync ErrResponse only logged via check_response_stage_terminate, plugin_runtime.rs:1190) is tracked by the sibling filter-04. Re-reports of the iteration-control / thread-starvation form are not accepted; verify the sync trait contract in traits/upstream_response_filter.rs before re-reporting.
-
When reviewing rate-limit response-header injection duplication / rate_limit vs rate_limit_redis X-RateLimit-* branching / shared write_rate_limit_headers helper (plugins-http-F004): accepted tradeoff (plugins-http-F004) — rate-limit/header-injection-duplication.md. Re-reports of the extract-shared-header-helper / unify-Retry-After / add-reset-to-Redis-allow forms not accepted.
-
When reviewing ldap_auth discriminated "Deny bad password" access-log tag as a username-enumeration oracle (plugins-http-F006): FALSE POSITIVE; tag renamed for convention only (plugins-http-F006) — ldap-auth/discriminated-error-log-tags.md. Re-reports framing it as an enumeration leak not accepted; re-open only if ldap_auth moves to search-then-bind.
-
When reviewing DSL http.call httpBlockPrivateIps / is_ssrf_blocked_ip_literal IP-literal-only guard / DNS-name target bypass / misleading flag name (plugins-http-dsl-F018): accepted tradeoff (F-018) — ssrf/dsl-http-call-ip-literal-only.md. Re-reports of the DNS-name-bypass form not accepted; re-open only on a real SSRF report or when connection-level IP-pinning exists. Distinct from the fixed sibling F-012.
-
When reviewing DSL http.call redirect SSRF / no per-hop block_private_ips re-check / 302 to 169.254.169.254 bypass / Policy::limited(10) first-hop-only (plugins-http-dsl-F012): fixed (plugins-http-dsl-F012) — ssrf/dsl-http-call-redirect-per-hop.md. Re-reports of the per-hop-bypass form not accepted; DNS-name hops are the F-018 tradeoff, not a regression.
-
When reviewing check_redis_link_names i - argc bytecode-position heuristic / multi-instruction sibling-arg misalign / valid config rejected via seal_fail_closed → 500 (plugins-http-dsl-F015): fixed (plugins-http-dsl-F015) — dsl-builtins/redis-link-check-positional-heuristic.md. Re-reports of the misalign / false-positive-500 form not accepted; verify the is_single_push_op window guard.
-
When reviewing gateway Bearer WWW-Authenticate lacking error= / error_description= per RFC 6750 §3.1 / OAuth clients can't distinguish invalid-token from no-creds (cookie-auth-02): fixed (cookie-auth-02 + rfc-refactor-cookie-auth-01) — jwt-auth/bearer-www-authenticate-error-attributes.md. Re-reports asking to attach invalid_token to the OIDC 401 path, add a separate error_description, or reclassify jwt_auth InvalidCredentials as 500 are not accepted.
-
When reviewing hostname_matches_listener wildcard ends_with case-sensitivity / mixed-case *.Example.com listener hostname matches nothing / listener hostname stored verbatim vs lowercased request host (gateway-routes-03): fixed (gateway-routes-03) — architecture/route-architecture-consistency.md (inconsistencies row 7). Re-reports of the case-sensitive form not accepted; verify hostname_matches_listener wildcard branch + ListenerEntry hostname normalization.
-
When reviewing IPv4-mapped IPv6 SSRF bypass of classify_backend_addr / ::ffff:127.0.0.1 or ::ffff:169.254.169.254 not blocked / IPv6 branch only matches ::1 + fe80::/10 (backends-F003): fixed (backends-F003) — ssrf/ipv4-mapped-ipv6.md. Re-reports of the ::ffff: mapped form not accepted; a re-report scoped to the ::a.b.c.d compat form is an accepted-tradeoff close, not a code fix.
-
When reviewing append_request_header first-existing-value-only / drops additional same-name request header entries / multi-value collapsed to first-value,appended (F-001): fixed (F-001) — http1/append-request-header-multi-value.md. Re-reports not accepted; verify append_request_header uses append_header.
-
When reviewing plugin Set-Cookie via set_response_header / CSRF/OIDC/DSL ctx.set cookie wipes upstream Set-Cookie / PendingHeaderOp::Set::apply insert_header replace-all / two cookie writers overwrite (gateway-plugins-02): fixed (gateway-plugins-02) — csrf/set-cookie-append.md. Response-side sibling of F-001. Re-reports not accepted; verify the four writers use append_response_header.
-
When reviewing match_sni / match_route returns first of many / same-hostname SNI collision picks non-deterministic cert or route / TLS winner flips across HashMap-order rebuilds (F-007): fixed for all three TLS/SNI matchers (tls-F007) — edgion-tls/cross-gateway-sni-collision-deterministic.md. Re-reports not accepted for any of the three; verify the rebuild path sorts colliding slots.
-
When reviewing RequestRedirectFilter::build_location drops the query string / Gateway API RequestRedirect loses ?returnTo=... / Location only scheme://host:port/path (redirect-FB01): fixed (redirect-FB01) — redirect/query-string-dropped.md. Re-reports of the drop form not accepted; verify build_location appends the query.
-
When reviewing redirect host.split(':').next() IPv6-unaware port strip / [::1]:8443 becomes [ / malformed https://[/... Location for IPv6-literal Host (redirect-F001): fixed (redirect-F001) — redirect/host-split-ipv6-literal.md. Re-reports of the split(':')/missing-bracket form not accepted; verify both sites call host_without_port.
-
When reviewing resolve_domain format!("{}:{}", domain, port) handing an unbracketed IPv6 literal (::1:9090) to lookup_host / fragile IPv6-literal DNS resolution (net-F001): fixed (net-F001) — backends/resolve-domain-ipv6-literal.md. Same IPv6-authority class as backends-F001/F017/link-sys-F001/redirect-F001; re-reports not accepted, verify resolve_domain short-circuits literals first.
-
When reviewing TLS passthrough PROXY-protocol-v2 dst built from bare IP (format!("{addr}:{port}") over info.addr) / IPv6 passthrough advertises 0.0.0.0:0 in PP2 (passthrough-F001): fixed (passthrough-F001) — edgion-tls/pp2-dst-bare-ip.md. Re-reports of the bare-IP/missing-bracket form not accepted.
-
When reviewing UDP-route get_or_create_session binding upstream socket to 0.0.0.0:0 / IPv4-only socket / send_to EINVAL drops every IPv6-backend packet (udp-F017): fixed (udp-F017) — backends/session-bind-address-family.md. Bind-family variant of the IPv6 class; re-reports of the IPv4-only-bind form not accepted.
-
When reviewing end_response_grpc_unimplemented / end_response_grpc_unavailable passing HTTP 501/503 sentinel into send_grpc_error_three_frame / introduce a typed GrpcStatus enum (refactor-h2-grpc-02): accepted as-is, refactor declined (refactor-h2-grpc-02) — h2-grpc/h2-grpc-sentinel-refactor-declined.md. Not an RFC divergence; enum-everywhere refactor not accepted.
-
When reviewing gRPC GrpcMatchEngine::match_route propagating deep_match Err via ? at every priority tier / single deep_match Err aborts whole match / asymmetric with HTTP try_route_deep_match (gateway-routes-06): fixed (gateway-routes-06) — architecture/route-architecture-consistency.md (Inconsistencies row #6). Re-reports of the abort-on-first-deep-match-Err form not accepted; verify call sites use try_route_deep_match_unit.
-
When reviewing OIDC resolve_session_secret / resolve_client_secret Some("") silently bypassing the resolved secret and falling through to the Secret store / two-level Some(..) + !is_empty() ambiguity / flatten to Option::filter (F-B03): not-a-bug, accepted tradeoff (F-B03) — oidc/resolved-secret-empty-fallthrough.md. Re-reports proposing the flatten/validation fixes not accepted; verify read_secret_utf8 still filters empties.
-
When reviewing store_claims_in_ctx / store_payload_in_ctx flowing JWT/JWE claims unfiltered into the access log / jwt_claims/oidc_claims/jwe_payload flatten into access-log JSON via #[serde(flatten)] ctx_map (gateway-plugins-03): fixed (gateway-plugins-03) — ctx-set/claims-access-log-filter.md. The access-log projection is now deny-by-default (AllowlistedCtx gated by the per-route edgion.io/log-ctx-keys / edgion.io/log-keys type: ctx opt-in); the sensitive-key blocklist remains as defense-in-depth. Re-reports of the unfiltered-flatten form not accepted.
-
When reviewing build_peer_from_lb_selection inlining upstream.tls = if use_tls {..} instead of calling record_tls_to_upstream / LB paths keep a second hand-rolled TLS-metadata write (backends-F007): fixed (backends-F007) — backends/build-peer-tls-helper-dedup.md. Re-reports of the duplicate-inline form not accepted.
-
When reviewing build_client_cert_key and build_client_cert_key_from_secret sharing an identical PEM-parse block / secret.data → X509::from_pem + PKey logic fixed twice / extract parse_cert_key_from_secret_data (backends-F008): fixed (backends-F008) — backends/build-client-cert-key-dedup.md. Re-reports of the duplicate-block form not accepted.
-
When reviewing LB-preload collect_http_routes/grpc/tcp/udp/tls in preload.rs having five byte-for-byte identical bodies / extract a generic helper or trait (backends-F009): fixed (backends-F009) — backends/preload-collect-routes-macro.md. Trait/generic-helper fix not accepted; re-reports of the five-identical-copies form not accepted.
-
When reviewing set_service_config constructing Arc<ServiceCbState> with an identical field list in both the Occupied-changed swap and the Vacant insert / two insert sites duplicate the struct literal (backends-F010): fixed (backends-F010) — backends/service-cb-state-new-ctor.md. Re-reports of the duplicate-literal form not accepted; verify ServiceCbState::new exists.
-
When reviewing DSL plugin bytecode deserialized + validated twice per hot-reload / validate_config and resolve_parts both call resolve_script / double base64 decode + double Validator scan / cache CompiledScript between validation and construction (plugins-http-dsl-F010): accepted tradeoff (plugins-http-dsl-F010) — architecture/dsl-validate-construct-double-resolve.md. De-dup fix suggestions not accepted; verify the two-path design first.
-
When reviewing remove_task being a dead one-line wrapper that unconditionally delegates to cancel_task / redundant private health-check task helpers / inline into single caller (backends-F011): fixed (backends-F011) — backends/remove-task-dead-wrapper.md. Both the dead-wrapper form and the inverse "add a dedicated remove method" (without real cleanup logic) not accepted; verify manager.rs has no remove_task.
-
When reviewing select_backend_by_policy being a trivial dead-wrapper delegating to select_from_endpoint_slice with identical args / its doc just restates the callee / Service vs ServiceEndpointSlice branches look different but aren't (backends-F012): fixed (backends-F012) — lb/select-backend-by-policy-dead-wrapper.md. Re-reports of the dead-wrapper form not accepted; verify selector.rs has no select_backend_by_policy.
-
When reviewing get_backends_for_service falling back to port 8080 via unwrap_or(8080) when no EndpointSlice declares a port / baked-in 8080 magic constant misdirects traffic / no warning log when no port found (backends-F013): fixed (backends-F013) — backends/ep-slice-no-port-fail-closed.md. The suggested tracing::warn! is not accepted (data-plane hot path, would flood per-QPS — observability is the access-log 500); re-reports of the 8080-default or missing-log form not accepted, verify the no-port branch returns Vec::new().
-
When reviewing consistent-hash extract_hash_key ConsistentHashOn::Arg percent-encoded / +-spaced arg-name match (backends-F014): fixed (backends-F014) — backends/consistent-hash-arg-percent-encoded-name.md.
-
When reviewing BackendTLSPolicyStore::update rebuild-strategy complexity comment / drops avg-target-refs (R) factor / incremental-vs-full crossover (backends-F015): fixed (backends-F015) — backends/backend-tls-policy-rebuild-strategy-comment.md. The issue's A < P/10 ≈ A < R wording is also rejected.
-
When reviewing ConsistentHashRing::select per-request HashSet allocation / seen set on the ConsistentHash LB hot path (lb-F003): fixed (lb-F003) — lb/consistent-hash-ring-seenset-no-heap.md.
-
When reviewing RrCore::select / ChCore::select duplicated addr-resolution / health-filter closure / ChCore double addr_map (lb-F009): fixed (lb-F009) — lb/rr-ch-core-shared-resolve-helper.md.
-
When reviewing ConsistentHashRing::select charging max_iterations per ring slot / duplicate vnodes of a high-weight unhealthy backend exhaust budget / steps += 1 before the dup-backend check (lb-F004): fixed (lb-F004) — lb/consistent-hash-duplicate-node-budget.md. The literal self.backends.len() early-exit suggestion is rejected (termination safety).
-
When reviewing EdgionBackend::update_ewma u64 EWMA-multiply overflow / promote-to-u128-or-cap-latency (lb-F001): fixed (lb-F001) — lb/update-ewma-u128-intermediate.md. The 60s latency-cap suggestion is specifically rejected.
-
When reviewing PolicyStore::remove_by_route unconditional per-entry ServiceLbPolicy clone in the DashMap::retain closure / O(N) wasted clones per route deletion (lb-F008): fixed (lb-F008) — lb/policy-store-remove-by-route-no-clone.md.
-
When reviewing session-affinity token CRC32 / pre-computable / forgeable / no HMAC / no MAC (lb-F011): documented (lb-F011) — lb/crc32-session-affinity-not-a-security-boundary.md. The HMAC upgrade is not accepted.
-
When reviewing ServiceSelectorCell single build_lock serializing first-build across all four policy slots / replace with per-slot Mutex/OnceLock (lb-F010): accepted tradeoff (lb-F010) — lb/build-lock-single-mutex-intentional.md. Re-reports not accepted absent a profiling trace showing real warm-up serialization.
-
When reviewing controller Admin API update_namespaced / update_cluster persisting body metadata.name without checking the URL path name / PUT body-name desync / processor-restart duplicates (controller-02): fixed (controller-02) — architecture/update-namespaced-reject-body-name-mismatch.md.
-
When reviewing LinkSys webhook-auth WebhookAuth::Hmac silent no-op in inject_auth / auth.type=hmac registers but sends unsigned / no upsert-time guard (link-sys-F005): fixed (link-sys-F005) — webhook-key/webhook-auth-hmac-fail-closed-upsert-guard.md. Full HMAC signing intentionally not implemented.
-
When reviewing LinkSys ES bulk_ingest_loop empty-endpoints panic / out-of-bounds endpoints[0] / endpoints: [] CRD silently kills the bulk task (link-sys-FB01): fixed (link-sys-FB01) — concurrency/es-bulk-ingest-empty-endpoints-fail-closed.md.
-
When reviewing Etcd LinkSys start_health_monitor reconnect backoff no jitter / deterministic exponential / thundering herd across pods (link-sys-F004): fixed (link-sys-F004) — concurrency/etcd-reconnect-backoff-jitter.md.
-
When reviewing LinkSys webhook rate-limit SlidingWindowCounter::try_acquire check-then-increment TOCTOU over-admission (link-sys-F006): fixed (link-sys-F006) — concurrency/sliding-window-check-then-increment.md. The optimistic fetch_add+fetch_sub rollback suggestion is rejected.
-
When reviewing LinkSys local-file log-rotation LocalFileWriter RotationStrategy::Size check gated behind the rotation_check_interval timer / active file overshoots max_size (link-sys-F010): fixed (link-sys-F010) — concurrency/local-file-per-batch-size-rotation.md.
-
When reviewing LinkSys webhook WebhookManager::get taking a tokio::sync::RwLock read().await per outbound call / hot-path lock overhead / ArcSwap pattern inconsistency (link-sys-F011): accepted tradeoff (link-sys-F011) — concurrency/webhook-manager-rwlock-intentional.md. The ArcSwap+Mutex migration and make-get-sync suggestions are not accepted.
-
When reviewing LinkSys dispatch redundancy / duplicate per-provider match arms / copy-pasted credential-readiness prelude (tls_ok/auth/ready) / collapse match into generic dispatch_one + LifecycleAction (link-sys-F008): fixed (link-sys-F008, 2026-05-25) — architecture/link-sys-dispatch-extract-function.md. Prelude folded into credential_readiness<M> (runtime/store.rs); the collapse-the-match suggestion is NOT accepted (distinct SystemConfig variants/client types/auth resolvers, divergent full-set vs partial-update lifecycles); subsumed by link-sys-F013. Re-reports of the duplicate-prelude / collapse-the-match form are not accepted; verify both functions call credential_readiness before re-reporting.
-
When reviewing LinkSys dispatch extract-function / readability findings — per-provider dispatch_full_set_<provider> extraction / remove the eight new_*_map/preserved_*_keys locals / unify dispatch_full_set + dispatch_partial_update (link-sys-F013): accepted tradeoff (link-sys-F013, 2026-05-25) — architecture/link-sys-dispatch-extract-function.md. The credential-readiness prelude was already extracted by F008; per-provider-function and unify-the-two-functions are NOT accepted (eight locals are structural to single-pass-then-swap-all; the two functions have genuinely different control flow). Readability-only on the config-sync path. Re-reports of the per-provider-extraction / unify-dispatch form are not accepted.
-
When reviewing ConfHandler redundancy — GatewayClassHandler/EdgionGatewayConfigHandler partial_update duplicate the RwLock<HashMap> three-arm add/update/remove loop / pattern copied across routes/plugins/backends / extract a generic SimpleMapConfHandler<T> with on_add/on_update hooks (infra-cluster-F012): accepted tradeoff (infra-cluster-F012, 2026-05-28) — architecture/conf-handler-simple-map-pattern.md. Re-evaluate only on a third exact-shape handler, genuine log-schema drift, or a new mandatory ConfHandler<T> method. Re-reports of the "extract SimpleMapConfHandler<T>" / "this pattern is copied across routes/plugins/backends" form are not accepted; verify routes/* actual shape and absence of a third simple-map handler before re-reporting.
-
When reviewing LinkSys webhook call.rs extract-function / readability — webhook_call retry-loop Ok(resp) arm mixes retry-on-status / passive health / success classification / size-capped body read / extract execute_attempt + handle_ok_response returning ControlFlow (link-sys-F015): accepted tradeoff (link-sys-F015, 2026-05-25) — architecture/webhook-call-extract-function.md. Readability-only; "single owner of all record_passive_result" is overstated (4 call sites, helper absorbs only 2). Re-evaluate only if a new Ok-arm branch needs distinct health tracking. Re-reports of the extract-execute_attempt/handle_ok_response form are not accepted.
-
When reviewing LinkSys webhook webhook_call full-body-read findings — full body via resp.bytes() before the size check / maxResponseBytes enforced only after buffering / no Content-Length pre-check / read_body_limited truncates after buffering (link-sys-F019): fixed (link-sys-F019, 2026-05-25) — concurrency/webhook-full-body-read-before-size-check.md. Re-reports of the "full body buffered before size check / no Content-Length pre-check" form are not accepted; verify webhook_call calls stream_body_capped before re-reporting.
-
When reviewing DSL http.call full-body-read findings — call_builtin_http reads full body via resp.bytes().await before truncating / max_response_body_bytes enforced only after buffering / dsl_http_client() has no content_length limit / large-response memory exhaustion (plugins-http-dsl-F007): fixed (plugins-http-dsl-F007, 2026-05-26) — dsl-builtins/http-call-full-body-read-before-truncate.md. Re-reports of the "full body buffered before truncation / no streaming read / add content_length" form are not accepted; verify call_builtin_http uses resp.bytes_stream() before re-reporting.
-
When reviewing DSL compiler findings — Compiler::leave_scope hard assert! panics in release / compiler-internal invariant break unwinds the preparse Tokio task / should return Result per graceful-degrade (plugins-http-dsl-F006; related pop().unwrap() underflow plugins-http-dsl-F013): fixed (plugins-http-dsl-F006, 2026-05-26) — architecture/compiler-leave-scope-assert.md. Re-reports of the leave_scope assert-panic or pop().unwrap() underflow-panic form are not accepted; verify leave_scope returns Result and loop pop sites use ok_or_else before re-reporting.
-
When reviewing DslPlugin::run_upstream_response_filter tokio::task::block_in_place panics on current_thread runtime / switch to spawn_blocking / undocumented multi-thread-runtime constraint (plugins-http-dsl-F008): documented, refactor rejected (plugins-http-dsl-F008, 2026-05-26) — concurrency/block-in-place-multi-thread-runtime.md. spawn_blocking not accepted (non-'static/non-Send session/log borrows); panic-guard not accepted (data-plane hot path). Re-reports of the panic / spawn_blocking / undocumented form are not accepted; verify the method doc comment before re-reporting.
-
When reviewing OIDC handle_callback repeated 502-vs-401 dispatch across callback.rs + request_filter_impl.rs / extract send_oidc_error / collapse the seven 502-vs-401 arms (plugins-http-F010): fixed (plugins-http-F010, 2026-05-26) — architecture/oidc-send-error-extract-function.md. Accepted leaf extraction; request_filter_impl.rs:187 intentionally NOT folded (502-only, falls through to unauth_action; folding sends spurious 401). Re-reports of "extract send_oidc_error" are moot; "also fold in the 7th site at :187" is not accepted; verify the helper exists before re-reporting.
-
When reviewing UDPRoute stream-plugin findings — edgion.io/edgion-stream-plugins silently ignored on UDPRoute / stream_plugin_runtime never populated/read / no wiring at any layer / a UDPRoute stream plugin never runs with no warning or status (udp-F012 / F-012): fixed (udp-F012, 2026-05-26) — architecture/udproute-stream-plugins-annotation-wiring.md. Re-reports of the silently-ignored / never-wired form are not accepted; verify handle_client_packet calls check_stream_plugins and initialize_route resolves the store key before re-reporting.
-
When reviewing plugin_runtime.rs four add_from_* builders repeating ~315 lines of identical loop scaffolding / extract generic add_plugins_inner<E,CF,AF> with closures / on_enabled callback for the CORS cache / collapse each to a 1–2 line wrapper (plugins-runtime-F003): accepted tradeoff, refactor rejected (plugins-runtime-F003, 2026-05-26) — architecture/add-from-builders-duplication.md. Re-evaluate only on real drift, a fifth pipeline stage, or invalid_plugins/seal_fail_closed contract changes. Re-reports of the add_plugins_inner / on_enabled / split-by-stage forms are not accepted.
-
When reviewing DSL BuiltinId::UrlDecode decoding + as space (form-urlencoded) vs the url_decode name implying RFC 3986 / path-ACL bypass risk / rename to form_decode / split into url_decode+form_decode / add a path_decode sibling (plugins-http-dsl-F021): documented, rename/split rejected (plugins-http-dsl-F021, 2026-05-26) — dsl-builtins/url-decode-form-semantics.md. Locked to mirror uri_utils::url_decode; bounded by docs + in-source rationale. Re-evaluate only on a production allowlist-bypass incident, uri_utils::url_decode being rewritten to RFC 3986, or a separate brainstormed path-decode task. Re-reports of the rename / split / path-decode-sibling form are not accepted; verify the in-source comment and api-reference §url_decode warning before re-reporting.
-
When reviewing TCP/TLS/UDP Global*RouteManagers::rebuild_all_listener_managers/rebuild_affected_listener_managers — merge rebuild_all+rebuild_affected into Mode::All|Affected, fold HTTP/gRPC in, inline PGIS, drop the active-but-no-routes clear-pass, add a per-family clear closure, and re-reports that rebuild_all retains stale ArcSwap<*RouteTable> for active listeners that lost all routes (l4-routes-rebuild-helper-F007): fixed (l4-routes-rebuild-helper-F007, 2026-05-28) — architecture/l4-rebuild-helper-clear-pass.md. Re-reports of the rejected forms above are not accepted; verify the current l4_rebuild.rs shape and the tcp|tls|udp/routes_mgr.rs wrappers before re-reporting.
-
When reviewing conf-sync start_watch holding grpc_client.write().await across the full list gRPC round-trip / async-write → cache_data sync-write nested deadlock trap / clone the client under a brief critical section then drop before the RPC (conf-sync F-003): fixed (conf-sync F-003, 2026-05-28) — concurrency/async-write-lock-across-rpc.md. Re-reports of "AsyncRwLock write guard held across a network call" on cloneable client types are not accepted unless the client cannot be cloned AND the lock has live waiters other than the current task; verify the clone-and-drop pattern before re-reporting.
-
When reviewing conf-sync ClientCache::start_watch applying the 2s+0..3s backoff/jitter on the outer-loop iteration after a break 'watch_block server-id-change / asymmetric vs start_watch_server_meta's server_switched+continue skip / add server_switched to skip the sleep on intentional switch (conf-sync F-004): accepted tradeoff, fix rejected (conf-sync F-004, 2026-05-28) — concurrency/relist-backoff-on-server-switch-intentional.md. Jitter is the load-bearing thundering-herd absorber under 17×N_gateway fanout. Re-evaluate only on a profiling trace showing the sleep dominates reconvergence, collapse to a single multiplexed stream, or a controller admission-spread signal. Re-reports of the asymmetric / mirror-continue form are not accepted; verify the 17×-per-gateway fanout before re-reporting.
-
When reviewing sticky-session Set-Cookie missing on a replaced response / build_response_local_reply discards the upstream response header / session-persistence cookie lost when a response-phase plugin returns ErrResponse / sticky cookie not carried over onto a local or error reply (filter-04c #2): accepted-as-designed (filter-04c #2, 2026-06-09) — architecture/local-reply-drops-sticky-set-cookie.md. Session persistence injects Set-Cookie directly onto the upstream header (append_header, not via pending_response_header_ops); build_response_local_reply only drains the pending-ops queue onto the fresh reply — the upstream header is discarded, so the sticky cookie is intentionally lost on a replaced response, matching Envoy. The pending-ops carry-over (filter-04c) is deliberately scoped to pending_response_header_ops only. Re-reports of the missing-cookie-on-replaced-response form are not accepted; verify the code comment at the injection site in pg_upstream_response_filter.rs before re-reporting.
-
When reviewing proposals to add a gateway_retries_total{reason} Prometheus counter at the retry decision sites (pg_fail_to_connect.rs, pg_upstream_response_filter.rs, pg_error_while_proxy.rs) / per-retry counter / retry-rate-by-reason metric (route-03): declined by design (route-03, 2026-06-10) — observability/retry-counter-metric-declined.md. Retry rate by reason is access-log aggregation over backend_context.upstreams[].err (one entry per attempt, every Edgion-decided retry stamps a reason label); per-reason hot-path counters fail the metrics pre-add check. Label-free or per-try-timeout-only variants are rejected the same way.
-
When reviewing "the retry loop ignores client disconnect / no downstream-liveness abort during the backoff sleep or connect window / client pays for attempts × backendRequest of abandoned upstream work" (route-03): accepted tradeoff, log-only (route-03, 2026-06-11) — routing/retry-client-disconnect-log-only.md. Pingora h1 already aborts in-flight attempts on downstream EOF within ~60ms (empirically verified); the blind window is backoff+connect only, observed via ClientClosed (499_01) + upstreams.length > 1 aggregation. Re-open only with new evidence (material remaining-window log analysis, or a cheap Pingora downstream-liveness API).
-
When reviewing "per-try-timeout has no gRPC (GRPCRoute) e2e test / the GRPCRoute per-try path is unverified / mid-body or deadline-transition per-try cases are untested" (route-05): HTTP gaps filled, gRPC e2e is an accepted skip (route-05, 2026-06-12) — routing/per-try-timeout-test-coverage.md. The mid-body response_written guard, per-I/O trickle precision, and deadline-transition are now pinned by HTTP e2e cases (per_try_timeout.rs); the data-plane per-try path (configure_peer_timeouts / error_while_proxy Case 1.5) is protocol-shared, so the gRPC-only parse/fallback delta is left to inspection. Re-open only if the gRPC per-try path forks from HTTP, or a gRPC-specific per-try bug surfaces.
-
When reviewing conf_sync plaintext / secret-in-transit findings (resolved Secrets shipped over a plaintext Controller→Gateway channel when conf_sync_security is omitted): accepted interim, risk-reduced not closed — architecture/conf-sync-plaintext-default-observable.md. The omitted-security path is now observable (ERROR log + system_error_state{reason="plaintext_default"} on both client and server) and the shipped manifests + default integration stack default to mTLS; fail-close was rejected (conf_sync is data-plane critical and there is no cert bootstrap yet). Re-open when cert bootstrap (#13) lands, conf_sync stops carrying resolved Secrets, or an in-pod loopback hop is introduced.