Skip to content

bug(purchases): approved AWS purchase vanishes from History — 'approved'/'running' execution statuses hidden by the History list (P0) #621

Description

@cristim

Symptom

User approved an AWS purchase from the dashboard and it immediately disappeared from Purchase History. Not "failed", not "completed" — gone.

Root cause (structural)

The History view (internal/api/handler_history.go) builds its list from two sources:

  1. Completed purchases from the purchase_history table (rendered as completed).
  2. Non-completed purchase_executions rows whose status is in:
    var historyExecutionStatuses = []string{"pending", "notified", "failed", "expired", "cancelled"}

This list excludes approved, running, and paused. The exclusion was justified by #372's assumption that approval executes synchronously: an Approve click drives the row approved -> completed (lands in purchase_history) or approved -> failed (stays, shown) all inside one HTTP request, so approved is "only ever transient".

That assumption breaks under interruption. Manager.ApproveAndExecute (internal/purchase/approvals.go) persists status approved before calling executeAndFinalize, and only finalizeExecution (internal/purchase/manager.go) flips it to completed/failed after executePurchase returns. If the synchronous execution does not finish inside the request, the row stays persisted as approved:

  • Lambda timeout — AWS RI/SP purchase calls are slow; a multi-rec or multi-account approval can exceed the function timeout.
  • Panic / crash mid-execution.

A row left in approved (or running/paused) is in neither purchase_history nor historyExecutionStatuses, so it silently vanishes from the UI. For a financial action this is the worst failure mode: the user can't tell whether the purchase went through, and may re-approve / re-purchase.

Secondary contributing path

Even on the happy path, savePurchaseHistory (internal/purchase/execution.go:449) logs and swallows a failed SavePurchaseHistory insert, while the execution is still marked completed. A failed history write (constraint/type mismatch — recall the recent #255 MonthlyCost-nullable and #453 ServiceDetails churn) also yields a completed-but-invisible purchase.

Fix

  1. Stop hiding in-flight/stuck states: add approved, running, paused to historyExecutionStatuses so an approval that hasn't finalized stays visible (rendered with its real status, e.g. "approving..." / "in progress"). The render path already has case "approved", "completed": handling in annotateApproved, so only the query filter needs widening.
  2. Dedup against purchase_history so a completed execution row and its purchase_history row don't both show (key on execution ID / commitment ID).
  3. Don't let a completed purchase be invisible: either surface a completed execution row that has no matching purchase_history row, or make the SavePurchaseHistory failure at execution.go:449 transition the execution to a visible state (not silently completed).
  4. Add a regression test: an execution persisted as approved/running appears in the History list; a completed execution whose history write failed is not silently dropped.

Diagnostic to confirm in prod

For the user's vanished purchase, check either:

  • DB: SELECT status FROM purchase_executions WHERE execution_id = '<id>' — if it's approved or running, this is the timeout/crash path.
  • Lambda logs around the approval for Failed to save history / AUDIT LOSS / a timeout, which would indicate the secondary path.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions