Repository navigation
fix(frontend): never offer Approve without the purchase amount - #497
Merged
Merged
Conversation
buildApprovalDetailsBody caught every getPurchaseDetails failure, and the empty-recommendations case, and returned a one-sentence body with no upfront cost or savings. Both callers (the email deep-link and the History and approval-queue Approve buttons) then opened the confirm dialog with a live "Approve purchase" button, so a 403, 404 or network error asked the user to commit money without showing how much. The builder now rejects in those cases. The deep-link shows a sticky error toast and leaves the page without opening the dialog; the History button shows an error toast and re-enables the row so the user can retry. The backend approves the stored execution without an amount check, so the modal is the only place the amount is shown before the commitment. Closes #247
Contributor
|
Warning Review limit reached
This review includes 9 billable files and costs up to $2.25.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 10 minutes for your next included review. View limit detailsLimit details: You’ve used all 2 included reviews currently available. Your 57 included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (9)
Comment |
This was referenced Oct 17, 2026
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
The approval modal no longer offers Approve purchase when it cannot show the amount being committed.
buildApprovalDetailsBodyused to catch everygetPurchaseDetailsfailure (403, 404, network error), and also the empty-recommendationscase, and return a one-sentence body with no upfront cost, savings or per-recommendation table. Both callers then opened the confirm dialog with a live Approve button:frontend/src/purchases-deeplink.ts: the email approval linkfrontend/src/history.ts: the inline Approve button in Purchase History and the approval-queue cardWhy
Approving executes a cloud commitment. The backend
approvePurchase(internal/api/handler_purchases.go) approves the stored execution by ID and does not check an expected amount, so the modal is the only place the user sees the amount before committing.How
buildApprovalDetailsBodynow rejects when the details fail to load or contain no recommendations. Failures of the optionallistAccountsandgetDeploymentInfocalls still degrade gracefully, as before.role="alert") saying the purchase cannot be approved without showing the amount, includes the cause, says to open the link again to retry, moves the page to/purchases, and does not open the dialog. The cancel deep-link does not change.runHistoryRowActionre-enables the row's buttons, so clicking Approve again is the retry. Cancel does not change..approval-details-fallbackCSS rule.Verification
Commands, run from
frontend/at the head commit:npm ci && npm run typecheck: cleannpx jest --watchman=false: 92 suites passed; 3036 tests passed, 1 skipped (that skip was already there)npx eslinton the touched files: no issuesnpm run build: compiled with the same single webpack warning as beforenpx playwright test tests-e2e/history-action-confirmation.spec.ts: 11 passed. The suite is hermetic, with API calls mocked throughpage.routeagainst the production bundle.New regression tests and their results without the fix (source files reverted to
origin/main, tests kept):purchases-deeplink.test.ts: two tests for the deep-link approve handler, run against the real toast and confirm dialog (details fetch rejects with a 403; details have no recommendations). Without the fix both fail because the dialog opens with Approve and the handler waits on it (Exceeded timeout of 5000 ms).history-approve-button.test.ts: the same two cases for the History button. Without the fix:expect(confirmDialog).not.toHaveBeenCalled(),Received number of calls: 1.history-action-confirmation.spec.ts(Playwright): the first details GET returns 403. The test asserts the alert is visible, no modal opens and the button is enabled again; it then retries, sees$1,200in the modal and approves. Without the fix:expect(locator).toContainText(expected) failed ... element(s) not found.Existing fixtures changed: they mocked
recommendations: [](or leftgetPurchaseDetailsunmocked, inhistory-approval-queue.test.ts) and expected the dialog to open. They now return one priced recommendation.Fixture-based evidence: the jest and Playwright runs mock the network. I did not run the change against a live backend.
For the reviewer
view:purchases, or whose account scope excludes the execution, gets a 403 or 404 fromGET /api/purchases/{id}. Before this change they could approve without seeing the amount. Now they cannot approve from the link at all. This is what the issue asks for, but it is a real change for those users.Closes #247