oscerd opened a new pull request, #27480:
URL: https://github.com/apache/camel/pull/27480
CAMEL-25404: make an `ai-tool` `authorizationPolicy` denial observable.
## Background
The `ai-tool` `authorizationPolicy` (CAMEL-24831, 4.23.0) wraps the route's
**outer** processor — the guard runs in
front of the route, agreed with @davsclaus on #27332. That placement is
deliberate: a denial is caught *before* the
route's unit of work, `AiToolExecutor` maps it to
`AiToolResult.AuthorizationDenied` and relays a clean refusal to the
model (never a tool result, never a stack trace). The side effect is an
observability gap: because the deny never
enters the route, it fires no `ExchangeFailed` event, no route span and no
metric — it was only logged at `WARN`. That
gap was explicitly deferred to this follow-up.
## What this changes
Keep the deliberate outer placement and the model-facing behaviour exactly
as they are; make the denial **observable**
by emitting a `CamelEvent` on every deny:
- new `AiToolAuthorizationDeniedEvent` — a `CamelEvent` of `Type.Custom` (so
it does not pollute generic exchange
lifecycle metrics) that is also a `CamelEvent.FailureEvent`. It carries
the denied tool name, the tool exchange (for
correlation — route id / exchange id), and the
`CamelAuthorizationException` the policy raised;
- `AiToolExecutor.authorizationDenied(...)` now fires it through
`exchange.getContext().getManagementStrategy().notify(...)`, in addition
to the existing `WARN` log and the unchanged
`AuthorizationDenied` refusal.
Operators register an `EventNotifier` to count / log / alert on denials
(e.g. drive a micrometer counter) without
changing what the model sees. Firing is best-effort and follows the same
pattern as `camel-openai`'s agentic lifecycle
events: nothing is published when no `EventNotifier` is registered, and a
failure to notify is swallowed so it can never
affect the refusal.
This is the event+counter option from the issue. The alternative — moving
the guard **inside** the route so a deny
flows through `onException`/tracing — was not taken: it would reverse the
deliberate outer placement and risk changing
the model-facing behaviour (the route's error handler could transform or
mask the deny), which the issue explicitly
rules out.
## Tests & docs
- `AiToolAuthorizationDeniedEventTest` — a deny (policy throws, and policy
sets the exception) fires exactly one event
with the right tool name / exchange / cause **and** still returns
`AuthorizationDenied`; a normal route error and a
successful call fire **no** event.
- `ai-tool-component.adoc` documents the event under a new *Observing
denials* section (with the catalog mirror
regenerated).
No public API change, no new dependency, no behaviour change for existing
users (purely additive observability), so no
upgrade-guide entry. `main` only.
---
_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]