feat(agent-bff): validate top-level list and count against capabilities#1759
Open
Conversation
Wire the capabilities validator into the top-level list and count handlers so filter/sort/projection are checked before the agent call. List passes filter+sort+projection; count passes only the filter. Adds a Zendesk regression pinning that an unsupported operator on stripeEmail is rejected early with 400 invalid_filter_operator and the field's normalized operators, with no agent call. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment on lines
+69
to
+74
| function resolveCapabilities(deps: RequestHandlerDeps): Promise<CapabilitiesResult> { | ||
| return deps.store.getCapabilities( | ||
| deps.collection, | ||
| createAgentCapabilitiesFetcher({ agentUrl: deps.agentUrl, token: deps.token }), | ||
| ); | ||
| } |
There was a problem hiding this comment.
🟡 Medium data/data-routes-middleware.ts:69
resolveCapabilities calls deps.store.getCapabilities directly, so when the capability fetch hits a transport failure or agent 5xx on a cache miss, the raw error reaches the generic error middleware as 500 internal_error instead of the 502 network_error / 503 agent_unavailable mapping that callAgent applies everywhere else. Wrap the fetch in callAgent so capability-endpoint failures preserve the agent error contract.
Suggested change
| function resolveCapabilities(deps: RequestHandlerDeps): Promise<CapabilitiesResult> { | |
| return deps.store.getCapabilities( | |
| deps.collection, | |
| createAgentCapabilitiesFetcher({ agentUrl: deps.agentUrl, token: deps.token }), | |
| ); | |
| } | |
| +function resolveCapabilities(deps: RequestHandlerDeps): Promise<CapabilitiesResult> { | |
| + return callAgent( | |
| + () => deps.store.getCapabilities( | |
| + deps.collection, | |
| + createAgentCapabilitiesFetcher({ agentUrl: deps.agentUrl, token: deps.token }), | |
| + ), | |
| + deps.logger, | |
| + ); | |
| +} |
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/agent-bff/src/data/data-routes-middleware.ts around lines 69-74:
`resolveCapabilities` calls `deps.store.getCapabilities` directly, so when the capability fetch hits a transport failure or agent 5xx on a cache miss, the raw error reaches the generic error middleware as `500 internal_error` instead of the `502 network_error` / `503 agent_unavailable` mapping that `callAgent` applies everywhere else. Wrap the fetch in `callAgent` so capability-endpoint failures preserve the agent error contract.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Wires the capabilities validator into the top-level list and count handlers in
agent-bff, so a request's filter/sort/projection is validated against the agent's real capabilities before the agent call — catching unsupported operators early with a structured error instead of discovering them late.Changes
data-routes-middleware.tshandleListvalidatesfilter+sort+projection;handleCountvalidates thefilteronly (the count contract carries no sort/projection).store/agentUrl/token; a sharedresolveCapabilitieshelper builds the token-bound fetcher and reads the capabilities cache.read-model-store.ts— sharpened the deferred-TOCTOUTODOto name both halves of the race (the middleware read-model snapshot + the in-flight capabilities fetch). Comment-only, no behavior change.stripeEmail/Equalregression using a raw snake_case fixture so the validator's snake→Pascal normalization path is exercised (returns400 invalid_filter_operatorwithvalidOperators= the field's supported operators, no agent call).Notes
Verification
tsc --noEmitclean; changed files lint clean.@forestadmin/agent-bffsuite: 671/671 passing.Fixes PRD-676
🤖 Generated with Claude Code
Note
Validate list and count requests against agent capabilities before forwarding in agent-bff
resolveCapabilitieshelper in data-routes-middleware.ts that fetches capabilities for the current collection via the read-model store and an agent-backed fetcher.handleListnow validates filter operators, sort fields, and projection fields against capabilities before invoking the agent; invalid requests are rejected locally.handleCountvalidates the filter against capabilities before invoking the agent.RequestHandlerDepsis extended withstore,agentUrl, andtokento support capability lookups.📊 Macroscope summarized b34a423. 2 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.