Skip to content

fix(errors): refuse issue moves from a state the client no longer sees - #2322

Merged
Makisuo merged 2 commits into
mainfrom
fix/issue-transition-expected-state
Nov 6, 2026
Merged

Makisuo merged 2 commits into
mainfrom
fix/issue-transition-expected-state

fix(errors): take no lease on a lost move, keep same-state moves no-ops

b21da45
Select commit
Loading
Failed to load commit list.
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."

  • transitionIssue refuses a request whose expectedState no longer matches, before any write
  • acquireLease takes whileState, so a move that lost its race writes no lease
  • ErrorIssueTransitionError becomes an HttpTaggedError (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
  • applyTransition filters $.workflowState.in_(...from), so a change landing after the check still 409s (ErrorIssueWorkflowService.ts:649)
  • HttpTaggedError passes policy.status as the tag error's httpApiStatus, 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.