Repository navigation
fix(errors): refuse issue moves from a state the client no longer sees - #2322
Merged
Merged
Maple Review Bot / Maple / review
succeeded
Nov 6, 2026 in 1m 59s
Confidence 10/10 · No issues found
🟢 Confidence 10/10 · safe to merge. The guard is checked before the lease and applyTransition re-checks the state atomically; lease and apply are still separate transactions (pre-existing).
no findings · 1/1 new units observable
Adds an optional expectedState to issue transitions on the API, the v2 endpoint and the issue surfaces, so a stale client gets a 409 that writes nothing, plus a lease guard and a 409-typed HttpTaggedError for the UI. Reads correctly; I found no defect."
transitionIssuerefuses a request whoseexpectedStateno longer matches, before any writeacquireLeasetakeswhileState, so a move that lost its race writes no leaseErrorIssueTransitionErrorbecomes anHttpTaggedError(409, public message) the toast can read- Issue page and errors list send the state they show and re-read on 409
What was checked
applyTransitionfilters$.workflowState.in_(...from), so a change landing after the check still 409s (ErrorIssueWorkflowService.ts:649)HttpTaggedErrorpassespolicy.statusas the tag error'shttpApiStatus, so the internal wire fields and status are unchanged- 409 messages interpolate two enum values only: no user text, note or identifier reaches the span or the toast
Observability coverage: 1 of 1 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
Issue transition refusal on stale expectedState (internal + v2 handlers) |
request-scoped handler branch | yes | runs inside the existing ErrorsService.transitionIssue Effect.fn span and returns a typed 409 in the error channel |
b21da45 · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
Loading