Skip to content

feat(api-sheriff): implement request pipeline data plane#76

Merged
OliverWolffGIP merged 28 commits into
mainfrom
feature/plan-04-request-pipeline
Jul 19, 2026
Merged

feat(api-sheriff): implement request pipeline data plane#76
OliverWolffGIP merged 28 commits into
mainfrom
feature/plan-04-request-pipeline

Conversation

@OliverWolffGIP

@OliverWolffGIP OliverWolffGIP commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements doc/plan/04-request-pipeline.adoc in full: the D1-D5/D3b request pipeline design
decisions and the plan doc's Work Breakdown. This lands the framework-agnostic pipeline core
(security headers/CORS, basic checks, route selection, verb gate, thorough checks), offline
bearer validation via TokenValidator, the zero-trust forward policy (TCP-peer gate +
forwarded-header regeneration), streamed dispatch/response with backpressure and stream-aware
retry, the Vert.x catch-all edge with edge hardening on virtual threads, the D4 event system
and RFC 9457 error mapping, the ADR-0005 framework-agnostic ArchUnit gate, and the full IT
suite + WRK benchmark. It also removes the Plan-01 placeholder gateway resource.

Changes

Pipeline core (api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/)

  • SecurityHeadersStage, BasicChecksStage, RouteSelectionStage, VerbGateStage,
    ThoroughChecksStage, PipelineRequest
  • CanonicalPathGuard (GW-01 single-canonical-path invariant) and FramingGate
    (GW-02 anti-smuggling gate)

Auth (api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/)

  • AuthenticationStage, GatewayValidator, TokenValidatorProducer wiring the existing
    TokenSheriff 0.9.2 TokenValidator for offline bearer validation

Forward policy (api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/)

  • ForwardPolicyStage, TcpPeerGate (zero-trust TCP-peer gate against Plan 03's CIDR set)

Edge / dispatch (api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/)

  • DispatchStage, ResponseStage, RouteRuntimeAssembler, GatewayEdgeRoute,
    StreamAwareRetryGate, UpstreamFailureMapper, EdgeHardeningOptions

Routing / boot assembly (api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/)

  • RouteRuntime, RouteMatcher, HttpProtocolProcessor, ProtocolProcessor,
    ProtocolProcessorRegistry

Events and error contract (api-sheriff/src/main/java/de/cuioss/sheriff/api/events/)

  • EventCategory, EventType, GatewayEventCounter, GatewayException (D4 event system,
    RFC 9457 error edge)

Config (api-sheriff/src/main/java/de/cuioss/sheriff/api/config/)

  • RouteTableBuilder, ConfigLoader, ResolvedRoute, TopologyResolver, ConfigValidator,
    ValidationRule

Quarkus wiring (api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/)

  • ApiSheriffProducer, ConfigModelReflection, ConfigProducer, GatewayExceptionMapper,
    GatewayReadinessCheck, SheriffMetrics (five sheriff_* meters, readiness reusing
    token-sheriff-validation-quarkus health checks)

Cleanup

  • Removed the Plan-01 placeholder GatewayResource implementation in favor of the pipeline
    entry point (ApiSheriff); ApiSheriffLogMessages documented in doc/LogMessages.adoc

Docs

  • doc/architecture.adoc, doc/configuration.adoc, doc/LogMessages.adoc updated to reflect
    implementation deviations discovered during the build

Benchmarks

  • benchmarks/src/main/resources/wrk-scripts/bearer_proxied_benchmark.sh and
    bearer_proxied_check.lua: bearer-validated proxied-route WRK benchmark

Integration tests (integration-tests/src/test/java/de/cuioss/sheriff/api/integration/)

  • BearerValidationIT, ErrorContractIT, GracefulShutdownIT, MetricsIT, PipelineVerbIT
    against the compose stack (per-verb echo assertions, real-Keycloak bearer, error codes,
    SIGTERM drain, /q/metrics)

ArchUnit gate

  • api-sheriff/src/test/java/de/cuioss/sheriff/api/arch/FrameworkAgnosticArchTest.java
    (ADR-0005: framework-agnostic packages carry no Quarkus/Vert.x/CDI/MicroProfile/Micrometer
    imports)

Test Plan

  • Quality gate (verify -Ppre-commit) passed
  • Full verify (verify) passed
  • Coverage >= 80% on new packages (verify -Pcoverage)
  • Module tests (api-sheriff) passed
  • Integration tests (verify -Pintegration-tests -pl integration-tests -am) passed
  • Benchmark profile (verify -Pbenchmark -pl benchmarks -am) built successfully
  • Manual testing completed (if applicable)

Related Issues

None.


Generated by plan-finalize skill

Summary by CodeRabbit

  • New Features
    • Introduced a streamed gateway request pipeline with security hardening, offline bearer-token validation (missing/invalid/scope errors), deny-by-default forwarding, and streamed upstream dispatch with stream-aware retry gating.
    • Added RFC 9457 application/problem+json error responses, plus gateway readiness reporting and Prometheus metrics (requests, durations, errors, upstream timing, security events).
    • Added transport edge hardening defaults (header/line/chunk limits, idle timeout, admission/drain bounds) and more granular upstream circuit-breaker/timeout error mapping.
  • Bug Fixes
    • Strengthened enforcement of canonical-path normalization, anti-smuggling framing, verb/allowed-path checks, and request body size limits.
  • Removed
    • Removed the public /api/health and /api/info endpoints.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @OliverWolffGIP, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@OliverWolffGIP, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository: cuioss/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c85f55f5-7efb-4bc2-ad70-107868261338

📥 Commits

Reviewing files that changed from the base of the PR and between 4e103be and 7444282.

📒 Files selected for processing (109)
  • api-sheriff/pom.xml
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/ApiSheriff.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/ApiSheriffLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/AuthenticationStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/GatewayValidator.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/TokenValidatorProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/ConfigLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/RouteTableBuilder.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/load/ConfigLoader.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/model/ResolvedRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/topology/TopologyResolver.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/validation/ConfigValidator.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/validation/rule/ValidationRule.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/DispatchStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/EdgeHardeningOptions.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/GatewayEdgeRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/ResponseStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/RouteRuntimeAssembler.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/StreamAwareRetryGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/UpstreamFailureMapper.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/EventCategory.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/EventType.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayEventCounter.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayException.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/ForwardPolicyStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/TcpPeerGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/GatewayResource.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/proxy/ProxyLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/proxy/ProxyRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/BasicChecksStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/CanonicalPathGuard.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/FramingGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/PipelineRequest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/RouteSelectionStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/ThoroughChecksStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/VerbGateStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ApiSheriffProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ConfigModelReflection.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ConfigProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/GatewayExceptionMapper.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/GatewayReadinessCheck.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/SheriffMetrics.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/HttpProtocolProcessor.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/ProtocolProcessor.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/ProtocolProcessorRegistry.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/RouteMatcher.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/RouteRuntime.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/package-info.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/ApiSheriffTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/arch/FrameworkAgnosticArchTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/auth/AuthenticationStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/auth/TokenValidatorProducerTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/RouteTableBuilderTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/load/ConfigLoaderTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/load/EnvSecretResolverTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/model/ConfigModelContractTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/topology/TopologyResolverTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/validation/ConfigValidatorTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/DispatchStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/EdgeHardeningTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/GatewayEdgePipelineTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/GatewayEdgeRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/ResponseStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/RouteRuntimeAssemblerTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/StreamAwareRetryGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/UpstreamFailureMapperTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/events/EventTypeTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/events/GatewayEventCounterTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/forward/ForwardPolicyStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/forward/TcpPeerGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/gateway/GatewayResourceTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/gateway/proxy/ProxyRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/BasicChecksStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/CanonicalPathGuardTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/FramingGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/RouteSelectionStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/ThoroughChecksStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/VerbGateStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/ConfigFailFastTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/ConfigProducerTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/GatewayExceptionMapperTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/routing/RouteRuntimeTest.java
  • benchmarks/src/main/resources/wrk-scripts/bearer_proxied_benchmark.sh
  • benchmarks/src/main/resources/wrk-scripts/bearer_proxied_check.lua
  • benchmarks/src/test/java/de/cuioss/sheriff/api/wrk/benchmark/BearerProxiedRouteBenchmarkTest.java
  • doc/LogMessages.adoc
  • doc/architecture.adoc
  • doc/configuration.adoc
  • integration-tests/src/main/docker/sheriff-config/endpoints/httpbin.yaml
  • integration-tests/src/main/docker/sheriff-config/endpoints/secure.yaml
  • integration-tests/src/main/docker/sheriff-config/gateway.yaml
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/ApiSheriffIntegrationIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/BaseIntegrationTest.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/BearerValidationIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/ConfigLoadedIntegrationIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/ErrorContractIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/GracefulShutdownIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/MetricsIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/PipelineVerbIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/ProxyIntegrationIT.java
📝 Walkthrough

Walkthrough

The legacy proxy and health resources are replaced by a staged Vert.x gateway with route compilation, request hardening, bearer validation, zero-trust forwarding, resilient streaming dispatch, RFC 9457 errors, metrics, readiness checks, integration tests, and benchmark coverage.

Changes

Gateway data plane

Layer / File(s) Summary
Resolved contracts and route runtime
api-sheriff/src/main/java/de/cuioss/sheriff/api/{events,routing,config}/...
Adds typed gateway events, exceptions, counters, protocol processors, route matchers, immutable runtime routes, and materialized forwarding policy.
Inbound pipeline and forwarding policy
api-sheriff/src/main/java/de/cuioss/sheriff/api/{pipeline,forward}/...
Adds request carriers and ordered stages for security headers, framing, canonical paths, route selection, verb checks, thorough validation, trusted-peer handling, and allow-listed forwarding.
Bearer authentication
api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/...
Adds offline bearer-token validation, scope enforcement, CDI qualification, and JWKS-backed token-validator production.
Runtime edge and upstream handling
api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/...
Adds route assembly, admission and drain handling, streamed request dispatch, retry gating, failure mapping, response relay, transport hardening, and catch-all routing.
Quarkus adapters and observability
api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/...
Adds RFC 9457 exception mapping, readiness reporting, Micrometer metrics, and related Maven dependencies.
Validation and integration coverage
api-sheriff/src/test/..., integration-tests/...
Adds unit, architecture, edge, pipeline, authentication, error-contract, graceful-shutdown, metrics, and verb-forwarding tests while removing legacy proxy/resource tests.
Benchmarks and documentation
benchmarks/..., doc/...
Adds bearer-route WRK scripts and validation, and documents logging, hardening defaults, and implementation deviations.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • cuioss/API-Sheriff#60: Shares the configuration and route-resolution pipeline extended here with effectiveForward.
  • cuioss/API-Sheriff#72: Modifies the legacy ProxyRoute implementation that this change replaces.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: implementing the api-sheriff request pipeline data plane.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the interim reverse-proxy edge with a fully implemented, framework-agnostic request pipeline (stages 0-7) for the API Sheriff gateway, introducing edge hardening, offline bearer-token validation, zero-trust forwarding, metrics, and readiness probes. The review feedback highlights several critical improvements: lazily resolving the TokenValidator using Instance to prevent startup crashes when token validation is omitted; unwrapping ExecutionException in DispatchStage so client-side breaches do not incorrectly trip the circuit breaker; rejecting multiple Content-Length headers in FramingGate to mitigate HTTP request smuggling; and checking response.headWritten() in failRelay to avoid runtime exceptions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/AuthenticationStage.java Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (3)
api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayEventCounter.java (1)

21-72: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Use LongAdder with a pre-populated EnumMap to eliminate hot-path contention.

While ConcurrentHashMap with AtomicLong is thread-safe, AtomicLong is susceptible to CAS contention under high concurrency, and computeIfAbsent adds unnecessary map-lookup overhead on every request. Since the number of EventType values is small and fixed, pre-populating an EnumMap with LongAdder instances provides wait-free, zero-allocation increments that scale perfectly on the Vert.x event loop.

⚡ Proposed performance optimization
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAdder;
 
 /**
  * Thread-safe, lock-free in-process event counter, modelled on {`@code` token-sheriff}'s
  * {`@code` SecurityEventCounter}. It feeds the metrics and error-mapping edges without
  * pulling in a broker, an observer bus, or a Micrometer dependency — keeping the
  * {`@code` events} package framework-agnostic (ADR-0005).
  * <p>
- * Increments use {`@link` ConcurrentHashMap#computeIfAbsent} plus
- * {`@link` AtomicLong#incrementAndGet}, so concurrent callers never block one another.
+ * Increments use a pre-populated {`@link` EnumMap} and
+ * {`@link` LongAdder#increment}, so concurrent callers never block one another.
  *
  * `@author` API Sheriff Team
  * `@since` 1.0
  */
 public final class GatewayEventCounter {
 
-    private final ConcurrentHashMap<EventType, AtomicLong> counters = new ConcurrentHashMap<>();
+    private final EnumMap<EventType, LongAdder> counters = new EnumMap<>(EventType.class);
+
+    public GatewayEventCounter() {
+        for (EventType type : EventType.values()) {
+            counters.put(type, new LongAdder());
+        }
+    }
 
     /**
      * Atomically increments the counter for the given event type.
      *
      * `@param` eventType the event to count
      */
     public void increment(EventType eventType) {
-        counters.computeIfAbsent(eventType, key -> new AtomicLong()).incrementAndGet();
+        counters.get(eventType).increment();
     }
 
     /**
      * `@param` eventType the event to query
      * `@return` the current count for {`@code` eventType}, or {`@code` 0} if never incremented
      */
     public long getCount(EventType eventType) {
-        AtomicLong current = counters.get(eventType);
-        return current == null ? 0L : current.get();
+        return counters.get(eventType).sum();
     }
 
     /**
      * `@return` an unmodifiable point-in-time snapshot of all non-zero counters
      */
     public Map<EventType, Long> getCounters() {
         Map<EventType, Long> snapshot = new EnumMap<>(EventType.class);
-        counters.forEach((eventType, value) -> snapshot.put(eventType, value.get()));
+        counters.forEach((eventType, value) -> {
+            long sum = value.sum();
+            if (sum > 0) {
+                snapshot.put(eventType, sum);
+            }
+        });
         return Collections.unmodifiableMap(snapshot);
     }
 
     /**
      * Resets every counter to zero. Intended for tests and controlled restarts.
      */
     public void reset() {
-        counters.clear();
+        counters.values().forEach(LongAdder::reset);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayEventCounter.java`
around lines 21 - 72, Replace the ConcurrentHashMap<EventType, AtomicLong>
storage in GatewayEventCounter with a pre-populated EnumMap<EventType,
LongAdder>, initializing one adder for every EventType during construction.
Update increment, getCount, getCounters, and reset to use the pre-populated
adders while preserving zero counts and the existing unmodifiable snapshot
contract.
benchmarks/src/main/resources/wrk-scripts/bearer_proxied_benchmark.sh (1)

39-46: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Unconditional -k disables TLS verification even if KEYCLOAK_TOKEN_URL is overridden.

curl -sk mints the token while sending client_secret/username/password, with certificate validation disabled. This is acceptable against the default local self-signed Keycloak, but since KEYCLOAK_TOKEN_URL is env-overridable, pointing it at a non-local endpoint silently reuses the same insecure flag, exposing benchmark credentials to MITM.

🔒 Suggested direction
+CURL_CA_OPT="${KEYCLOAK_CA_BUNDLE:+--cacert ${KEYCLOAK_CA_BUNDLE}}"
+CURL_INSECURE_OPT="${KEYCLOAK_INSECURE:+-k}"
 TOKEN_RESPONSE="$(curl -sk -X POST "${KEYCLOAK_TOKEN_URL}" \
+TOKEN_RESPONSE="$(curl -s ${CURL_CA_OPT} ${CURL_INSECURE_OPT} -X POST "${KEYCLOAK_TOKEN_URL}" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     ...
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/src/main/resources/wrk-scripts/bearer_proxied_benchmark.sh` around
lines 39 - 46, Update the token acquisition curl invocation in the bearer
benchmark script to avoid unconditionally disabling TLS verification for the
environment-overridable KEYCLOAK_TOKEN_URL. Preserve support for the default
local self-signed Keycloak through an explicit, narrowly scoped configuration
while ensuring overridden or non-local endpoints use certificate validation.

Source: Linters/SAST tools

api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java (1)

166-227: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

These readiness tests only cover single-call semantics — consider adding a repeated-call() case.

Given the lifecycle question raised on GatewayReadinessCheck (Instance.get()/destroy pairing), a test that invokes check.call() multiple times against the same FakeValidatorInstance and asserts on call-count/resolution behavior would help pin down the intended lifecycle contract once the underlying producer scope is confirmed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java`
around lines 166 - 227, Add a repeated-call readiness test alongside the
existing GatewayReadinessCheck tests, invoking check.call() multiple times with
the same FakeValidatorInstance and asserting the expected call count and
resolution behavior. Use the test to define the intended Instance.get()/destroy
lifecycle contract while preserving the existing single-call status and data
assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/DispatchStage.java`:
- Around line 121-133: Update dispatch and the awaitDispatch retry flow so each
retry uses a fresh request-body stream rather than reusing the consumed
requestBody captured by the lambda. Preserve the existing zero-byte/idempotent
retry behavior, and ensure every upstream attempt attaches a newly replayable or
recreated ReadStream before calling request.send.

In `@api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/GatewayEdgeRoute.java`:
- Around line 251-265: Update handle in GatewayEdgeRoute to handle
virtualThreadExecutor.execute rejection by releasing the admission permit and
decrementing inFlight when process(ctx) cannot be scheduled. Preserve the
existing end-handler cleanup for successfully submitted requests, and ensure the
rejected request is completed or rejected through the established response path.
- Around line 16-79: Update the Content-Length lookup in GatewayEdgeRoute to
replace the deprecated HttpServerRequest.getHeader call with
raw.headers().get("Content-Length"), preserving the existing request-processing
behavior.
- Around line 543-561: Update guardFor so the circuit-breaker name includes
shape.retryEnabled() in addition to the upstream host and port, producing
distinct names for resilience configurations with different retry settings. Use
this updated name consistently for the breaker configuration and
upstreamFailureMapper.recordBreakerTransition callback.

In
`@api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayException.java`:
- Around line 36-37: Update the eventType field declaration in GatewayException
to remove the transient modifier, preserving its serialization so getEventType()
remains available after deserialization.

In
`@api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/BasicChecksStage.java`:
- Around line 99-109: Update validateParameters to validate each query parameter
name as well as its values, mirroring validateHeaders(). Use the parameter-name
pipeline exposed by pipelines (if available from cui-http), and preserve the
existing UrlSecurityException handling through rejected(violation).

In
`@api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStage.java`:
- Around line 83-101: The applyCors method must recognize a configured "*"
allowed origin while preserving the restriction that wildcard origins are only
valid when credentials are disabled. Update its origin-acceptance check to allow
either the literal request origin or the wildcard configuration, and emit the
appropriate Access-Control-Allow-Origin value for wildcard requests; retain the
existing credential and preflight header behavior.

In `@api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/DispatchStageTest.java`:
- Around line 164-170: Add the test-scoped
io.smallrye:smallrye-fault-tolerance-standalone dependency to the module pom so
retryGuard() can create a Guard in plain unit tests without the missing SmallRye
Fault Tolerance SPI implementation.

---

Nitpick comments:
In
`@api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayEventCounter.java`:
- Around line 21-72: Replace the ConcurrentHashMap<EventType, AtomicLong>
storage in GatewayEventCounter with a pre-populated EnumMap<EventType,
LongAdder>, initializing one adder for every EventType during construction.
Update increment, getCount, getCounters, and reset to use the pre-populated
adders while preserving zero counts and the existing unmodifiable snapshot
contract.

In
`@api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java`:
- Around line 166-227: Add a repeated-call readiness test alongside the existing
GatewayReadinessCheck tests, invoking check.call() multiple times with the same
FakeValidatorInstance and asserting the expected call count and resolution
behavior. Use the test to define the intended Instance.get()/destroy lifecycle
contract while preserving the existing single-call status and data assertions.

In `@benchmarks/src/main/resources/wrk-scripts/bearer_proxied_benchmark.sh`:
- Around line 39-46: Update the token acquisition curl invocation in the bearer
benchmark script to avoid unconditionally disabling TLS verification for the
environment-overridable KEYCLOAK_TOKEN_URL. Preserve support for the default
local self-signed Keycloak through an explicit, narrowly scoped configuration
while ensuring overridden or non-local endpoints use certificate validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: cuioss/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d5b6c9f-cbf6-42d6-94da-09eddd298897

📥 Commits

Reviewing files that changed from the base of the PR and between a4c0b03 and 5181e57.

📒 Files selected for processing (100)
  • api-sheriff/pom.xml
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/ApiSheriff.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/ApiSheriffLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/AuthenticationStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/GatewayValidator.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/TokenValidatorProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/ConfigLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/RouteTableBuilder.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/load/ConfigLoader.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/model/ResolvedRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/topology/TopologyResolver.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/validation/ConfigValidator.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/config/validation/rule/ValidationRule.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/DispatchStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/EdgeHardeningOptions.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/GatewayEdgeRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/ResponseStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/RouteRuntimeAssembler.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/StreamAwareRetryGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/UpstreamFailureMapper.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/EventCategory.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/EventType.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayEventCounter.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayException.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/ForwardPolicyStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/TcpPeerGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/forward/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/GatewayResource.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/proxy/ProxyLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/proxy/ProxyRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/BasicChecksStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/CanonicalPathGuard.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/FramingGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/PipelineRequest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/RouteSelectionStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/ThoroughChecksStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/VerbGateStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ApiSheriffProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ConfigModelReflection.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ConfigProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/GatewayExceptionMapper.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/GatewayReadinessCheck.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/SheriffMetrics.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/HttpProtocolProcessor.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/ProtocolProcessor.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/ProtocolProcessorRegistry.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/RouteMatcher.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/RouteRuntime.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/routing/package-info.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/ApiSheriffTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/arch/FrameworkAgnosticArchTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/auth/AuthenticationStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/RouteTableBuilderTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/load/ConfigLoaderTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/load/EnvSecretResolverTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/model/ConfigModelContractTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/topology/TopologyResolverTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/config/validation/ConfigValidatorTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/DispatchStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/EdgeHardeningTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/GatewayEdgeRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/ResponseStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/RouteRuntimeAssemblerTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/StreamAwareRetryGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/UpstreamFailureMapperTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/events/EventTypeTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/events/GatewayEventCounterTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/forward/ForwardPolicyStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/forward/TcpPeerGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/gateway/GatewayResourceTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/gateway/proxy/ProxyRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/BasicChecksStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/CanonicalPathGuardTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/FramingGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/RouteSelectionStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/VerbGateStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/ConfigFailFastTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/ConfigProducerTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/GatewayExceptionMapperTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/routing/RouteRuntimeTest.java
  • benchmarks/src/main/resources/wrk-scripts/bearer_proxied_benchmark.sh
  • benchmarks/src/main/resources/wrk-scripts/bearer_proxied_check.lua
  • benchmarks/src/test/java/de/cuioss/sheriff/api/wrk/benchmark/BearerProxiedRouteBenchmarkTest.java
  • doc/LogMessages.adoc
  • doc/architecture.adoc
  • doc/configuration.adoc
  • integration-tests/src/main/docker/sheriff-config/endpoints/secure.yaml
  • integration-tests/src/main/docker/sheriff-config/gateway.yaml
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/BearerValidationIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/ErrorContractIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/GracefulShutdownIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/MetricsIT.java
  • integration-tests/src/test/java/de/cuioss/sheriff/api/integration/PipelineVerbIT.java
💤 Files with no reviewable changes (9)
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/GatewayResource.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/package-info.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/proxy/ProxyLogMessages.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/ApiSheriff.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ApiSheriffProducer.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/ApiSheriffTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/gateway/proxy/ProxyRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/gateway/GatewayResourceTest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/gateway/proxy/ProxyRoute.java

Comment thread api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayException.java Outdated
OliverWolffGIP added a commit that referenced this pull request Jul 19, 2026
Resolve the accepted PR-review findings across the data plane:

- Auth (TASK-27): inject the gateway TokenValidator lazily via
  Instance<TokenValidator> in GatewayEdgeRoute and resolve it through a
  Provider in AuthenticationStage, so a config with only require:none routes
  never touches the validator producer and cannot crash boot when
  token_validation is absent.
- Dispatch (TASK-28): narrow guardedDispatch's inner catch to
  ExecutionException and unwrap its cause so the breaker's
  skipOn/abortOn(GatewayException) rules see the real client-side rejection;
  refuse a retry re-entry that would reuse the already-subscribed one-shot
  request-body stream (explicit failure instead of a silent stall).
- Framing (TASK-29): reject multiple Content-Length headers and a
  comma-separated Content-Length value per RFC 7230 3.3.2 (request smuggling)
  before the CL+TE coexistence check.
- Edge (TASK-30): guard failRelay's setStatusCode with !headWritten(); release
  the admission permit and decrement in-flight when the virtual-thread executor
  rejects a dispatch; include retryEnabled in the circuit-breaker name to avoid
  a duplicate-name collision for same-host:port routes.
- Events (TASK-31): drop the misleading transient modifier on
  GatewayException.eventType.
- Pipeline (TASK-32): validate query-parameter names as well as values in
  BasicChecksStage; honor a configured wildcard CORS origin in
  SecurityHeadersStage by reflecting the presented origin.

Extends unit coverage for each fix (lazy validator resolution,
ExecutionException unwrap + one-shot-stream retry refusal, duplicate/comma
Content-Length, parameter-name rejection, CORS wildcard/exact/disallowed origins).

Co-Authored-By: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStageTest.java (1)

82-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert preflight headers and add coverage for credentials.

The corsStage helper configures allowedMethods(List.of("GET", "POST")) and takes an allowCredentials parameter, but the tests do not assert Access-Control-Allow-Methods on preflight responses, and there is no test verifying Access-Control-Allow-Credentials when it is enabled.

Consider adding assertions for these CORS headers to ensure the stage's full behavior is verified and protected against regressions.

➕ Proposed coverage additions

Update the preflight test to assert the allowed methods:

     // Assert
     assertEquals("https://any.example", request.responseHeaders().get(ACAO));
+    assertEquals("GET, POST", request.responseHeaders().get("Access-Control-Allow-Methods"));
     assertTrue(request.shortCircuitStatus().isPresent(), "a CORS preflight must short-circuit");

And consider adding a new test for credentials:

    `@Test`
    `@DisplayName`("emits Access-Control-Allow-Credentials when enabled")
    void exactOriginMatchWithCredentials() {
        // Arrange
        SecurityHeadersStage stage = corsStage(List.of("https://ok.example"), true);
        PipelineRequest request = corsRequest(HttpMethod.GET, "https://ok.example", false);

        // Act
        stage.process(request);

        // Assert
        assertEquals("https://ok.example", request.responseHeaders().get(ACAO));
        assertEquals("true", request.responseHeaders().get("Access-Control-Allow-Credentials"));
    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStageTest.java`
around lines 82 - 96, Add assertions in wildcardPreflightShortCircuits for the
configured Access-Control-Allow-Methods value, including GET and POST. Add a
separate test covering corsStage with allowCredentials enabled and an exact
origin, asserting both the reflected ACAO and Access-Control-Allow-Credentials
set to true.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStageTest.java`:
- Around line 82-96: Add assertions in wildcardPreflightShortCircuits for the
configured Access-Control-Allow-Methods value, including GET and POST. Add a
separate test covering corsStage with allowCredentials enabled and an exact
origin, asserting both the reflected ACAO and Access-Control-Allow-Credentials
set to true.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: cuioss/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6efcdba4-a2ec-45e6-b628-ebed19df9db1

📥 Commits

Reviewing files that changed from the base of the PR and between d39c496 and 4e103be.

📒 Files selected for processing (19)
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/auth/AuthenticationStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/DispatchStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/EdgeHardeningOptions.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/GatewayEdgeRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayException.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/BasicChecksStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/FramingGate.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStage.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ConfigProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/GatewayReadinessCheck.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/SheriffMetrics.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/auth/AuthenticationStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/DispatchStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/GatewayEdgeRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/RouteRuntimeAssemblerTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/BasicChecksStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/FramingGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStageTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java
💤 Files with no reviewable changes (2)
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/EdgeHardeningOptions.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/SheriffMetrics.java
🚧 Files skipped from review as they are similar to previous changes (13)
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/events/GatewayException.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/FramingGateTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/pipeline/BasicChecksStageTest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/ConfigProducer.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/quarkus/GatewayReadinessCheck.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/DispatchStageTest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/SecurityHeadersStage.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/quarkus/SheriffMetricsTest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/pipeline/BasicChecksStage.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/GatewayEdgeRouteTest.java
  • api-sheriff/src/test/java/de/cuioss/sheriff/api/edge/RouteRuntimeAssemblerTest.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/GatewayEdgeRoute.java
  • api-sheriff/src/main/java/de/cuioss/sheriff/api/edge/DispatchStage.java

OliverWolffGIP and others added 24 commits July 19, 2026 17:17
Add the cui-http 2.1.0 dependency (security filtering + forwarded-header
resolver), its generators-classifier attack-database test artifact,
quarkus-smallrye-fault-tolerance for the per-route resilience guard, and
ArchUnit for the framework-agnostic package-boundary gate.

FrameworkAgnosticArchTest enforces ADR-0005: config.model, config.validation,
events, forward, and pipeline carry no framework imports. The routing package
is deliberately excluded (it holds the shared Vert.x HttpClient and SmallRye FT
guard by design, per operator resolution 2026-07-19). A negative-control test
asserts the gate fails on a genuine framework dependency.

Co-Authored-By: Claude <noreply@anthropic.com>
…red logging

Add the framework-agnostic events package: EventCategory (failure impact
groups naming the RFC 9457 problem type), EventType (each event's category and
HTTP status per the architecture.adoc error contract), the lock-free
GatewayEventCounter, and the typed GatewayException. Add ApiSheriffLogMessages
(DSL-style LogRecords, INFO/WARN/ERROR ranges; security WARNs record failure
type and route only, never the raw payload). Add GatewayExceptionMapper
rendering GatewayException as application/problem+json and normalizing
TokenValidationException to TOKEN_MISSING/TOKEN_INVALID.

Tests cover the lock-free counter, every error-contract row's status and
problem+json shape, and the token-validation translation. The events package
stays framework-free under the ADR-0005 arch-gate.

Co-Authored-By: Claude <noreply@anthropic.com>
…ect dedup

Add the routing package: RouteRuntime (the immutable per-route compiled model
holding the shared Vert.x HttpClient and per-route SmallRye FT guard by design),
RouteMatcher (prefix/method/host/header AND-matching), and the
ProtocolProcessor/HttpProtocolProcessor/ProtocolProcessorRegistry triad (HTTP
reused for GraphQL; gRPC/WebSocket rejected at boot). Add the edge
RouteRuntimeAssembler compiling the frozen RouteTable and deduplicating heavy
collaborators via injected factories: one SecurityConfiguration per filter shape,
one client per upstream tuple, one guard per resilience shape. Session auth and
unsupported protocols fail boot with CONFIG_INVALID.

The routing and edge packages are deliberately framework-coupled and excluded
from the ADR-0005 arch-gate (operator resolution 2026-07-19). Tests prove shape
dedup, tuple-scoped client sharing, boot rejection, and order preservation.

Co-Authored-By: Claude <noreply@anthropic.com>
Implements the framework-agnostic request pipeline (deliverables 4-5):
- PipelineRequest agnostic carrier + stages 0-3 (security headers/CORS,
  cui-http basic checks yielding the single canonical path, route
  selection, verb gate) with D3b GW-01 canonical-path and GW-02 framing
  anti-smuggling hardening
- Stage 4 offline bearer-token validation (AuthenticationStage +
  qualified TokenValidatorProducer) with 401/403 semantics
- Reuses the cui-http attack databases and token-sheriff test generators
  for adversarial coverage
Add ForwardPolicyStage and TcpPeerGate implementing the deny-by-default
upstream projection: allow-listed headers/query, regenerated X-Forwarded-*
(and RFC 7239 Forwarded on emit:both), and drop of inbound forwarding
headers from untrusted immediate TCP peers (ADR-0003).

Tests prove drop-and-regenerate semantics for both emit modes and that
spoofed forwarding headers from untrusted peers are ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…onse

Streamed upstream dispatch over the route's shared Vert.x HttpClient through its
SmallRye Fault-Tolerance guard, with a byte-capped request-body stream, stream-aware
retry gate, error-contract failure mapping, and the backpressured response relay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
Materialize each route's deny-by-default forward allowlist (headers_allow /
query_allow / set_headers) once at boot: add effectiveForward to ResolvedRoute
(RouteTableBuilder anchor-inheritance path) and to RouteRuntime (populated by
RouteRuntimeAssembler), so stage 5 consumes an already-resolved ForwardConfig
per route instead of re-deriving it. Operator RE-SCOPE resolution 2026-07-19.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…aceholders

Add GatewayEdgeRoute: a catch-all Vert.x data-plane route that runs stages 0-7 per request on a virtual thread, including stage 5 (zero-trust forward policy) using each route's resolved effectiveForward plus the global forwarded block (boot-parsed trusted_proxies + emit mode). Assemble routes at boot via RouteRuntimeAssembler with real Vert.x-client, SmallRye-Guard, and SecurityConfiguration factories, a shared SecurityEventCounter, a default SecurityConfiguration, ForwardedHeaderResolver, TcpPeerGate, and GatewayEventCounter. Render rejections as RFC 9457 problem+json.

Add EdgeHardeningOptions: an HttpServerOptionsCustomizer applying max header size, max initial-line length, max chunk size, and idle timeout, plus a pre-dispatch admission cap and a bounded graceful SIGTERM drain.

Carry effectiveAllowedPaths on RouteRuntime so stage 3 enforces the per-route allowed_paths whitelist (a gateway concept absent from cui-http SecurityConfiguration).

Remove the Plan-01 placeholders (ApiSheriff, ApiSheriffProducer, GatewayResource, ProxyRoute, ProxyLogMessages, their package-infos and tests) now that the real edge is wired. Retain quarkus-resteasy (documented in the pom): the JAX-RS GatewayExceptionMapper and token-sheriff-client-quarkus's RFC 9457 mapper still need the JAX-RS runtime.

The pre-commit OpenRewrite gate applied a one-time module-wide import-group separator normalization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
Add GatewayEdgeRouteTest (clean boot assembly over an empty route table,
catch-all registered last, fail-fast on session auth and unsupported
protocols, bounded graceful drain) and EdgeHardeningTest (header/line/chunk
transport bounds on both listeners, idle-timeout reap, admission cap, and a
drain timeout below the Quarkus shutdown window). Completes deliverable 8's
module-test coverage; the placeholder tests were removed with their
production targets in the preceding edge-wiring commit.

Co-Authored-By: Claude <noreply@anthropic.com>
Add SheriffMetrics registering the architecture.adoc meter names
(sheriff_requests_total, sheriff_request_duration_seconds,
sheriff_errors_total, sheriff_security_events_total,
sheriff_upstream_duration_seconds) and GatewayReadinessCheck reflecting
config-loaded plus JWKS/validator status, with SheriffMetricsTest
covering meter names and the readiness UP/DOWN/not-applicable branches.
…ack (D10)

Add PipelineVerbIT (verb gate + 405-not-forwarded), BearerValidationIT
(missing/malformed bearer -> 401, upstream=0), ErrorContractIT (RFC 9457
problem+json on 404/405/401, upstream=0), GracefulShutdownIT (liveness/
readiness UP + concurrent in-flight completion), and MetricsIT (Prometheus
exposition on the management port). Add a self-contained bearer route to the
mounted gateway config (secure anchor + file-JWKS token_validation, no
Keycloak dependency) so the bearer-rejection scenarios are exercisable.
Full stack run is the -Pintegration-tests CI profile (skipITs by default).
Add bearer_proxied_benchmark.sh (mints a benchmark-realm access token and
drives the bearer-protected /secure route through wrk) and its companion
bearer_proxied_check.lua (sends the token, folds non-2xx + socket errors,
and fails the run non-zero above the WRK_MAX_ERROR_RATE threshold).
BearerProxiedRouteBenchmarkTest asserts the WRK output runs and reports
through the parser and that the shipped scripts carry the bearer wiring and
the error-rate gate. The live run is the -Pbenchmark profile's job.
…iations (D12)

Trim LogMessages.adoc to the records actually emitted (drop the removed
PROXY route-registered/upstream-failed entries; the config subsystem's
ConfigLogMessages records are the emitted set). Record the fixed edge-
hardening transport defaults (header/request-line/chunk caps, idle reap,
admission cap 2048, drain 25s) doc-first in configuration.adoc. Add an
Implementation Deviations section to architecture.adoc capturing the
not-yet-wired metrics emission, the unemitted data-plane log catalogue,
and the rejection-only integration bearer coverage.
GatewayEdgeRoute now records the request, per-route duration, error, and
upstream-duration meters end-to-end: recordRequest and recordRequestDuration
fire once per served request from the single end-of-response hook (covering
success, short-circuit, and rendered-failure paths), recordError keys
categorized failures by route + EventCategory, and recordUpstreamDuration
times the downstream dispatch. The metrics route label uses the config-fixed
route id, or the bounded "<no-route>" value for unmatched requests, and the
status_family bucket keeps status-label cardinality fixed.

Adds SheriffMetrics.statusFamily(int) as the bounded status-family classifier
(unit-tested in SheriffMetricsTest) and strengthens MetricsIT to assert the
sheriff_* meters appear with their bounded route/status_family labels on
/q/metrics after proxied traffic. The architecture.adoc deviation note is
narrowed to the one remaining gap: sheriff_security_events_total is not yet
bridged from the cui-http SecurityEventCounter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…otal end-to-end

Register one Micrometer FunctionCounter per UrlSecurityFailureType over the
boot-shared cui-http SecurityEventCounter, wired from GatewayEdgeRoute, so the
fifth sheriff_* meter (sheriff_security_events_total{failure_type}) is emitted
end-to-end with bounded label cardinality. Replaces the unused recordSecurityEvent
recorder with the binder. Extends SheriffMetricsTest for the binder, strengthens
MetricsIT to assert the meter appears and moves after a security-filter rejection,
and removes the now-obsolete deviation note from architecture.adoc — all five
sheriff_* meters are now wired end-to-end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
Settlement commit for deliverable 8 — OpenRewrite import/format normalization
applied by the end-of-phase quality-gate sweep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
… classes

Settlement commit for deliverable 9 — OpenRewrite import/format normalization
applied by the end-of-phase quality-gate sweep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…k test

Settlement commit for deliverable 11 — OpenRewrite import/format normalization
applied by the end-of-phase quality-gate sweep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…peline

Remove two dead package-private methods surfaced by the finalize
simplification pass (ByteCappedBodyStream.bytesSeen, FramingGate.protectedHeaders).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
GatewayEdgeRoute.guardFor() added a SmallRye withRetry() for retry-enabled
routes without ever consulting StreamAwareRetryGate, so a retry could
re-send a non-idempotent request or one whose body bytes had already
streamed upstream (the duplicate-side-effect hazard the design forbids).

DispatchStage now tracks the attempt index and the running body-bytes-sent
count across guarded re-entries and vets every retry re-entry (never the
first attempt) against the gate. A disallowed re-entry aborts by re-raising
the first attempt's failure as a mapped GatewayException, honoured by the
existing abortOn(GatewayException.class) contract — no duplicate upstream
request is issued. Breaker/timeout semantics are unchanged.

Tests prove an idempotent GET with zero body bytes is retried, a POST is
not retried, and an idempotent request that streamed a body byte is not
retried (via upstream-attempt counting).

Co-Authored-By: Claude <noreply@anthropic.com>
…LogRecord ID collisions

ApiSheriffLogMessages catalogued the security-relevant WARN records the plan-04
design (D4) requires -- cui-http filter violations and circuit-breaker open/close
transitions -- but none were ever invoked in production, an OWASP A09
(insufficient logging/alerting) gap for a security-focused gateway. Wire
SECURITY_FILTER_VIOLATION into GatewayEdgeRoute's GatewayException handling and
CIRCUIT_BREAKER_OPEN/CLOSED into UpstreamFailureMapper.recordBreakerTransition(),
plus ROUTE_TABLE_COMPILED at boot.

Activating the dormant records surfaced a latent identifier collision: this
catalogue and ConfigLogMessages share the "ApiSheriff" log prefix but were
authored independently, colliding at several IDs. Remove the genuinely dead,
duplicate entries (INFO.CONFIG_LOADED, WARN.AUTH_WEAKENED, ERROR.CONFIG_INVALID,
ERROR.UNSUPPORTED_ROUTE) per the project's pre-1.0 rule, renumber
CIRCUIT_BREAKER_OPEN/CLOSED to clear the remaining collision, and document the
disjoint-range invariant plus the newly-active entries in doc/LogMessages.adoc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…CI resolution

CI on PR 76 failed 14 api-sheriff tests with two distinct cold-resolution
classpath gaps that the warm local marshalld daemon masked:

1. token-sheriff-validation declares jjwt-api/impl/jackson at test scope, so
   they do not transitively reach api-sheriff. The generators test-jar's
   TestTokenHolder uses Jwts.SIG (jjwt-api 0.12+) and needs jjwt-impl +
   jjwt-jackson at test runtime, producing NoClassDefFoundError
   io/jsonwebtoken/Jwts$SIG on a fresh resolution. Fixes AuthenticationStageTest
   (x5) and GatewayEdgeRouteTest (x6). Added the three artifacts at test scope;
   version inherited from token-sheriff-bom (0.13.0).

2. DispatchStageTest RetryGating (x3) builds a Guard via Guard.create() outside
   any CDI/Quarkus runtime; SpiAccess then ServiceLoader-resolves a SmallRye
   Fault Tolerance Spi. quarkus-smallrye-fault-tolerance ships only the CDI Spi
   (registered via CDI beans, not META-INF/services), so a plain JUnit run finds
   none. Added io.smallrye:smallrye-fault-tolerance-standalone at test scope
   (Quarkus-BOM version 6.11.1) to supply the non-CDI Spi.

Both are test-scope runtime pieces of already-approved stacks (token-sheriff,
quarkus-smallrye-fault-tolerance). integration-tests needs no change — its CI
failure was a downstream -am reactor consequence of the api-sheriff test phase
failing. All 443 api-sheriff tests pass; cold resolution proven via
dependency:tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…h assertNull

javac 25 on CI rejects assertEquals(null, response.path(...)) as ambiguous
across the jspecify-annotated JUnit overloads; assertNull states the intent
directly and compiles on every matrix JDK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
…TP/1.1 framing

The containerized native gateway dropped or corrupted proxied response bodies and
returned 500 on the first bearer request. Four edge defects plus stale Plan-01
integration tests are fixed:

- GatewayEdgeRoute.dispatchAndRelay ran the response relay directly on the virtual
  thread; hop it back onto the request event loop like every other terminal path so
  the HttpServerResponse mutations and the pipeTo subscription are event-loop-bound.
- DispatchStage pauses the upstream response the instant its head arrives so a small
  body cannot fully arrive and end before the deferred pipeTo subscribes ("Response
  already ended").
- ResponseStage re-establishes body framing after hop-by-hop stripping: Content-Length
  is end-to-end (only Transfer-Encoding is hop-by-hop), so preserve it, or stream
  chunked when absent. An HTTP/1.1 client otherwise received Content-Length: 0 and an
  empty body (HTTP/2 was unaffected, masking the defect).
- TokenValidatorProducer disables audience validation when an issuer declares no
  audience, so the lazily-built @GatewayValidator bean no longer throws on the first
  bearer request (500 -> 401).

Integration fixtures/tests reconciled to the new deny-by-default pipeline: the httpbin
route forwards the exercised query params + Content-Type; stale /api/* ApiSheriff
assertions removed; redundant Proxy/ConfigLoaded forward tests folded into
PipelineVerbIT (ProxyIntegrationIT deleted).

Full integration-tests profile green (23/23); quality-gate and verify green (455/455).
OliverWolffGIP and others added 4 commits July 19, 2026 17:17
Resolve the accepted PR-review findings across the data plane:

- Auth (TASK-27): inject the gateway TokenValidator lazily via
  Instance<TokenValidator> in GatewayEdgeRoute and resolve it through a
  Provider in AuthenticationStage, so a config with only require:none routes
  never touches the validator producer and cannot crash boot when
  token_validation is absent.
- Dispatch (TASK-28): narrow guardedDispatch's inner catch to
  ExecutionException and unwrap its cause so the breaker's
  skipOn/abortOn(GatewayException) rules see the real client-side rejection;
  refuse a retry re-entry that would reuse the already-subscribed one-shot
  request-body stream (explicit failure instead of a silent stall).
- Framing (TASK-29): reject multiple Content-Length headers and a
  comma-separated Content-Length value per RFC 7230 3.3.2 (request smuggling)
  before the CL+TE coexistence check.
- Edge (TASK-30): guard failRelay's setStatusCode with !headWritten(); release
  the admission permit and decrement in-flight when the virtual-thread executor
  rejects a dispatch; include retryEnabled in the circuit-breaker name to avoid
  a duplicate-name collision for same-host:port routes.
- Events (TASK-31): drop the misleading transient modifier on
  GatewayException.eventType.
- Pipeline (TASK-32): validate query-parameter names as well as values in
  BasicChecksStage; honor a configured wildcard CORS origin in
  SecurityHeadersStage by reflecting the presented origin.

Extends unit coverage for each fix (lazy validator resolution,
ExecutionException unwrap + one-shot-stream retry refusal, duplicate/comma
Content-Length, parameter-name rejection, CORS wildcard/exact/disallowed origins).

Co-Authored-By: Claude <noreply@anthropic.com>
…ew fixes

OpenRewrite import/format normalization applied by the final quality-gate
sweep over the review-fix commit (TASK-27..32).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
Fix the 8 new-code reliability bugs at root cause:
- S3655 unguarded Optional.get: TokenValidatorProducer (ifPresentOrElse),
  GatewayReadinessCheck and RouteMatcher (capture the Optional in a local so
  the isEmpty/isPresent guard and the get() share one reference).
- S2637/S2583 in GatewayEdgeRoute: parseMethod now returns Optional<HttpMethod>
  (never null from the @NullMarked method), which also removes the always-false
  method==null dead branch; renderProblem's nullable request/eventType params
  are annotated @nullable so the null checks are legitimate, not dead.
- S6218 TcpPeerGate.Cidr: hold the network address as an immutable List<Byte>
  instead of a byte[] so the record's equals/hashCode/toString are content-aware.

Lift unit-test coverage of the edge request pipeline (Sonar sees only unit JaCoCo):
- GatewayEdgePipelineTest boots the edge over a live Vert.x front server and a
  local stub upstream, driving real HTTP through stages 0-7: happy-path forward
  with echo assertions, streamed POST body, 404 unmatched, 405 verb, 400 filter
  reject, 401 bearer missing/invalid, and CORS preflight.
- ThoroughChecksStageTest covers divergent per-route filters, allowed_paths
  (wildcard + miss), and the body-cap fast-reject.
- TokenValidatorProducerTest covers the config-driven build and failure paths.

Concentrated uncovered lines drop from 409 to 98 across the pipeline classes
(ThoroughChecksStage 5%->98.5%, TokenValidatorProducer 0%->93.9%, GatewayEdgeRoute
13%->73.7%, DispatchStage->93.4%, ResponseStage->92%). No production behavior
weakened for testability.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ByJaCDmwjrCug2LK6FbEB
@OliverWolffGIP
OliverWolffGIP force-pushed the feature/plan-04-request-pipeline branch from fae99b3 to 7444282 Compare July 19, 2026 15:17
@OliverWolffGIP
OliverWolffGIP added this pull request to the merge queue Jul 19, 2026
Merged via the queue into main with commit 9c47959 Jul 19, 2026
24 checks passed
@OliverWolffGIP
OliverWolffGIP deleted the feature/plan-04-request-pipeline branch July 19, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant