fix(request): send filter syntax the UAR API accepts - #73
Merged
Merged
Conversation
`grant request list --state`, `--result` and `--priority` all returned HTTP 400 BAD_REQUEST. Two defects in the filter builder: - a lone condition was wrapped a second time, emitting `((requestState eq PENDING))`; the API only accepts `(requestState eq PENDING)` - the priority operand was quoted, emitting `(priority eq 'High')`; the API only accepts `(priority eq High)` Both confirmed against the live API. Two or more conditions still get the single outer wrap, `((a) and (b))`, which the API accepts. `TestRequestList_ParamsFromFlags` had pinned the broken double-wrapped string, so the suite passed for the wrong reason; that expectation is corrected and `TestRequestList_FilterSyntaxMatchesLiveAPI` now pins the exact string for every flag combination.
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped to filter-string construction, matches the documented live API behavior, and is covered by updated and newly added tests.
Pull request overview
This PR fixes grant request list filtered queries by aligning the generated UAR OData filter string with what the live API actually accepts, restoring functionality for --state, --result, and --priority.
Changes:
- Add
combineFiltersto avoid emitting an invalid double-wrapped filter when only one condition is present. - Remove single-quote wrapping from the
--priorityoperand so enum values are sent unquoted. - Update and add tests to pin the live-API-accepted filter syntax, and record the fix in the changelog.
File summaries
| File | Description |
|---|---|
| docs/mutation-ledger.md | Updates mutation ledger line references to match the shifted code after the fix. |
| cmd/request_list.go | Fixes filter construction (no redundant outer parens for single conditions; unquoted priority). |
| cmd/request_args_test.go | Corrects the previously wrong expectation and adds a dedicated filter-syntax regression test suite. |
| CHANGELOG.md | Documents the user-visible fix for filtered grant request list invocations. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
The bug
grant request list --state,--resultand--priorityall failed with HTTP 400 BAD_REQUEST against the live UAR API. Every filtered invocation of the command was broken; unfilteredgrant request listworked.Measured against the live API
(requestState eq PENDING)((requestState eq PENDING))(requestState eq 'PENDING')((requestState eq 'PENDING'))(priority eq High)(priority eq 'High')(requestResult eq APPROVED)((requestState eq FINISHED) and (priority eq High))So the API requires unquoted operand values, and single parentheses around a lone condition. The outer wrap is correct only when combining two or more conditions.
The API spec (
Access Requests API.json,GET /workflows/requestsfilter) agrees on the shape — "filter expressions must be complete within parentheses" — but its own example quotes string operands, which the live API rejects for these enum fields. The measured table wins.The two defects, both in
cmd/request_list.goparams.Filter = "(" + strings.Join(filters, " and ") + ")"wrapped unconditionally. With one filter,filters[0]is already parenthesised, so it emitted((requestState eq PENDING))→ 400.--prioritywas built asfmt.Sprintf("(priority eq '%s')", v)→ 400.--stateand--resultwere already unquoted.The fix
A
combineFiltershelper: zero conditions → empty, one → emitted bare, two or more → wrapped once. Priority loses its quotes.Filter strings now produced:
--state PENDING(requestState eq PENDING)--result APPROVED(requestResult eq APPROVED)--priority High(priority eq High)--state FINISHED --priority High((requestState eq FINISHED) and (priority eq High))--state FINISHED --result APPROVED --priority Low((requestState eq FINISHED) and (requestResult eq APPROVED) and (priority eq Low))An existing test had pinned the broken format
cmd/request_args_test.goassertedwantFilt: "((requestState eq PENDING))"— the exact string the API rejects. The suite was green on a command that could not work: a test passing for the wrong reason. That expectation is corrected, not preserved.New
TestRequestList_FilterSyntaxMatchesLiveAPIpins the exact filter string for every flag combination, with the measured table reproduced in a doc comment so the next person does not have to rediscover it.Other builders of this syntax (checked, not churned)
cmd/request_picker.go— passesscope.filterthrough; correct.cmd/request_finalize.go—(requestState eq PENDING); single, bare, unquoted. Correct.cmd/request_cancel.go—((requestState eq STARTING) or (requestState eq RUNNING) or (requestState eq PENDING)); three conditions under one wrap, unquoted. Correct and consistent with the fixed rule.request_list.gowas the only wrong one. Left the three literals alone rather than routing them through the helper — they are already in the right shape and the churn would not be paid for.One extrapolation worth flagging
The live table verifies the flat join for two conditions. Three conditions (
((a) and (b) and (c))) is an extrapolation from that; the spec's own example nests binary pairs instead ((((a) and (b)) and (c))). Left-associativeandparsing makes the flat form near-certain, andcmd/request_cancel.goalready ships a working three-condition flator, but it has not been directly measured withand.Verification
gofmt -s -l .empty;go build ./...,go test -race -count=1 ./...,go test -shuffle=on -count=1 ./...,go test -tags=integration -count=1 ./cmd,golangci-lint run— all exit 0.