oscerd opened a new pull request, #26445: URL: https://github.com/apache/camel/pull/26445
## What Adds `evaluationMode=wasm`, evaluating a WebAssembly bundle in-process, **alongside** the existing REST client rather than replacing it. ## Why now The component docs recorded WASM as deliberately deferred because the artifact was at 0.0.6. That is no longer true: - `com.styra.opa:opa-java-wasm` **1.1.0** (2026-06), Apache-2.0, on Maven Central - its runtime is `run.endive:runtime` — [bytecodealliance/endive](https://github.com/bytecodealliance/endive), **pure Java** (it compiles WASM to JVM bytecode via ASM). No native libraries, no platform classifiers, so no ppc64le/s390x constraint - `opa build -t wasm` is supported by the `openpolicyagent/opa:1.9.0-static` image the component's ITs already use ## Why additive rather than a replacement They are complementary, not competing: | | `rest` | `wasm` | |---|---|---| | Policy source | a server, centrally managed | a bundle built with your app | | Updates | bundle polling, live | rebuild and redeploy | | Decision logs | yes | none | | Latency | a round-trip per exchange | in-process | | Unreachable PDP | a real failure mode | cannot happen | Dropping REST would lose decision logging, bundle distribution and central policy management — a capability regression for the sidecar deployment most OPA users run. `rest` stays the default, so existing routes are untouched. ## How the engines are kept honest `OpaPolicyEvaluator` becomes an abstract base owning **everything a route observes** — input building, verdict reading, decision headers, fail-closed handling — with a single hook, `evaluateDecision(input)`. `OpaRestEvaluator` and `OpaWasmEvaluator` supply only that. The engines *cannot* diverge on anything visible to a route, rather than being two implementations hoped to stay in step. **One place this needed real care.** A spike against a compiled bundle showed: ``` allow(alice) = [{"result":true}] decision(alice) = [{"result":{"allow":true,"reasons":[]}}] decision(mallory) = [] ← undefined, not [{"result":false}] ``` The WASM ABI represents an undefined rule as an **empty array**, where the REST client raises an error. Unwrapped naively that becomes `null` → a **deny**, while the same policy and input under `rest` **aborts the exchange**. An empty array therefore throws, so the base class turns it into the identical fail-closed error. `failsClosedOnAnUndefinedDecisionJustLikeTheRestEngine` locks it. ## Thread safety is not optional `OpaPolicy` carries mutable input/data and is not thread-safe — the library ships `OpaPolicyPool` precisely for this — while a Camel producer is invoked concurrently. A shared instance would interleave input between exchanges and corrupt decisions under load, which a functional test would never catch. Each exchange borrows an instance; `poolSize` (default 8) bounds concurrent evaluation, and there is a test driving 128 exchanges across 16 threads asserting every verdict matched its own input. ## Usability `policyBundle` accepts a `file:`, `classpath:` or `http:` location holding either the `bundle.tar.gz` that `opa build` emits **or** a bare `.wasm` — the tarball is what an operator will actually have. `entrypoint` defaults to the policy path, which is the name `opa build -e` gives it, while remaining separately settable because an entrypoint is a build-time artefact and not a data path. ## Testing 7 new tests (47 in the module): allow, deny, decision-object, the undefined-decision consistency case, the tarball form, fail-fast when `policyBundle` is missing, and the concurrency test. Full reactor build green, with catalog and both DSL mirrors regenerated. ## Known gap, tracked The `.wasm` fixtures are **committed binaries**, which is exactly what **CAMEL-24742** argues against — nothing checks they still agree with the `authz.rego` beside them. They are here only so this mode is testable now; a README records their provenance and the regeneration command, and 24742 should delete both files once test-infra compiles them. **CAMEL-24743** covers gating `serverUrl`/`bearerToken`/`failOpen` and the health checks, which have no meaning in `wasm` mode. `main` only. Additive; `rest` remains the default. _Claude Code on behalf of @oscerd_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
