No-login decision links and Slack buttons stop working when another step of the approval changes

Description

Problem

Every change that creates a new version of a running approval gives all of its steps new ids: changing the approver or the email address of a step, and updating a step from a work item field. Decision links sent by email with "Enable actions without login" and Slack decision buttons point to the old step id. After such a change they stop working for every approver of that approval, not only for the changed step: the approver sees "You cannot perform this action. This step has already been completed." although their step still waits for their decision.

External approver links (AP-2530) already handle this: they decide on the approver's step that waits for a decision in the current version of the approval.

Change

  • After a new version of the approval, a no-login decision link of an Atlassian user and a Slack decision button decide on the step of the current version that waits for that person's decision: as the approver of a user step, a member of a group step, a voter or moderator of a vote step, or a delegate.

  • When that person no longer has such a step:

    • the step they were asked about was decided: "You cannot perform this action. This step has already been completed.";

    • they were replaced as the approver: "This link is no longer valid because the approver of this step was changed." (Slack: "This button is no longer valid...").

  • Links and buttons of approvals without a version change behave as today.

Fixes included

  • Step lineage: each approval step keeps a lineage across versions. Email links (Atlassian users without login, external approvers, Web API login links) and Slack buttons decide only on the continuation of their own step, never on another step of the same approver.

  • A replaced approver, or a member removed from a work item field group, is told the approver changed; a step that was decided, or decided and later removed, answers that it was already completed.

  • Slack: after a work item field update or an approver change from the panel, only the messages of removed or replaced approvers, and of steps skipped by the change, are marked Reassigned; everyone else keeps their buttons. Later decisions update the original Slack messages, including messages still waiting in the delivery queue when the change happened.

  • Field-change emails link each added approver to their own step.

  • Queued requests of a replaced or removed approver are superseded when the approval gets a new version.

  • The removal email names the step the user was removed from.

  • Watcher Slack messages keep getting decision updates after a new version.

  • The You chose prompt on the decision page also shows after a new version.

  • Known limits:

    • Links and buttons whose step was replaced by a version change made before the deploy decide only when the approver has exactly one matching step in the approval and it waits (that can be another step of theirs); otherwise they answer that the step is already completed.

    • A Slack message sent at the exact moment of a version change keeps working when clicked, but later decisions do not update it.

    • A field-group request queued as a single Jira notification (Jira notification mechanism, no chat) still goes to the old member list, including a removed member.

Acceptance criteria

  • On an approval with two steps waiting in parallel, changing the approver of one step leaves the other approver's earlier email link and Slack button working; the decision is recorded on their step.

  • The replaced approver's link and Slack button show that the approver was changed.

  • A delegate's link keeps working after the approver of another step is changed.

  • A vote link keeps working after another step's approver is changed, and still respects the voting deadline.

  • After a step is decided, its links show that the step was already completed, also after a version change.

Manual tester notes

  • Jira and Confluence, "Enable action buttons in notifications" and "Enable actions without login" on: start an approval with two user steps in a parallel group, then change the first step's approver from the panel. The second approver decides from their earlier email: the decision is recorded. The first approver's earlier link says the approver was changed, and their Slack message shows Reassigned.

  • Same setup, but the first approver also has a later step: their earlier link of the first step says the approver was changed and does not decide the later step.

  • Slack, same scenario: the second approver clicks their earlier button. The decision is recorded and the original message shows it. Deciding in Jira or Confluence instead also updates the original message.

  • Jira, a step from a multi-user work item field plus another waiting step: add a user, and the new user's email link and Slack buttons decide on their own step; remove a user, and only that user's Slack message shows Reassigned while the other approvers' buttons and earlier links keep working.

  • Jira, a field-group step (users treated as a group) with Ann and Ben: remove Ben from the field. Ben's earlier link and button say the approver was changed; Ann's still decide.

  • Vote in a parallel group: change another step's approver, then vote from the earlier button or email. The vote is recorded; after the voting deadline they say voting is closed.

  • A step decided before an approver change: its earlier link and button say the step was already completed.

  • Field group step: one member decides, an unrelated change creates a new version, then that member is removed from the field. Their first decision link says the step is already completed.

  • A member removed from a field group step clicks an old Slack button or opens an old vote modal after a second version change: the message says the approver changed. A removed member notified one by one (email, Slack) gets no pending request email after the removal; this does not apply to a field group notified as one Jira notification.