Group and vote steps: group steps that cannot reach their vote counts, and a voting deadline fixed on the definition

Description

Depends on (merged to dev first): AP-2450 (excluded users refused on group steps), AP-2449 (GroupVotesField; field group membership changes continue the approval through continueAfterStepsChange), AP-2380 (Rovo, GroupStepProgress, VotingDeadline, RecipientsByRole, votes refused after the deadline), AP-2466 (vote step "Period after the step starts", computed when the step starts; server check of the period).

Problem

  1. A group step can stay "In progress" for good.

    • The step needs a number of votes "to pass" and "to fail" (1 to 999). The editor only checks that both are at least 1, the server nothing; neither is compared with the group size.

    • Each member votes once. An approval counts towards "to pass", a rejection towards "to fail", an abstain towards both. The step ends only when one of the two numbers is reached.

    • When everyone who can vote has voted and neither number is reached, nothing ends the step: "to pass" is higher than the number of voters (group of 3, 5 to pass, all approve), or the votes split (group of 2, 2 to pass, 2 to fail, one approves, one rejects). Exclusions (the approval creator, chosen users, users from work item fields in Jira) lower the number of voters, so a definition that worked can start to get stuck.

    • Reminders reach no member, Rovo shows the step as waiting for a decision, and group steps cannot be reassigned. Only a decision deadline (Incomplete), a membership change, the parallel group ending without the step, or rerunning or deleting the approval moves it on.

    • The votes fields are also shown for Notification steps, where they have no effect: on group steps and, in Jira, on work item user field steps with "Treat users as a group".

  2. The vote step "Voting deadline" can be a fixed date and time saved on the definition. Every approval started from the definition gets the same date. AP-2466 adds "Period after the step starts", which gives every approval its own deadline; the fixed date stays an option and stored dates are not migrated.

    • After that date, every new approval opens a vote step whose voting is already closed. Voters are still asked to vote (the Jira notification shows the past deadline), but a vote is refused with "Voting on step '…' closed at …", and the moderator gets "voting expired" right away and decides with no votes. Rovo hides the vote and does not remind voters.

    • The "must be in the future" check runs only in the vote step form. The definition can still be saved with the past date; the step itself cannot be saved again (for any change) until the date is moved or cleared. The Web API accepts any date.

    • Parametrize approval has no option to change the deadline.

Group and vote steps exist in both products; the behaviour is the same in Jira and Confluence.

Change

  1. Group steps that cannot reach "to pass" or "to fail".

    • Members who can vote: group members who are not excluded and have not voted. While any of them is left, the step waits as today. When none is left and neither number is reached:

      • only approvals and abstains, at least one approval: the step is approved;

      • only rejections and abstains, at least one rejection: the step is rejected;

      • in both cases Activity says the required number exceeded the voters ("Approved by all 3 members who could vote; 5 approvals were required") and the approval continues as after any decision;

      • otherwise (approvals and rejections, only abstains as in decision 4, or no votes) the step is blocked.

    • A blocked step stays in progress. The approval panel, approvals lists, approval details and Rovo show the reason, e.g. "Blocked: needs 5 approvals, 3 members can vote".

    • The user who started the approval gets one notification when the step becomes blocked, delivered like the "Approval incomplete" (deadline) message (ApprovalLifecycleNotification). Decision 1 settles its text.

    • A blocked step can be decided in the app UI, with a required comment: the starter can reject it, and approve it only when not excluded from the step (exclusions exist to stop self-approval); global admins can approve or reject it. Nobody else, never JSM customers, and not when the approval can no longer be decided (archived, outdated, deadline passed). Activity records "Decided for a blocked group by " with the comment, and the approval continues as after any decision. Deciding creates no new approval version (only step changes, such as a reassignment, do).

    • The block clears by itself when a membership change makes a number reachable again; a membership change can also end the step as above. The starter is notified again only if it blocks again.

    • A decision deadline, when set, still makes the approval Incomplete (ExpirationScheduler), blocked or not.

    • The check runs after each vote, when the step starts and when members change (in Jira, groups from a work item user field follow field changes). Live Jira and Confluence groups send no event on member changes: they are checked when the app re-reads them for pending approvers (PendingApproverReconciliationScheduler, every 12 hours). The check reuses members the app already reads; no extra Atlassian calls.

    • The votes fields (GroupVotesField) are hidden for Notification steps, on group steps and on user field steps with "Treat users as a group".

    • The definition editor warns when "to pass" or "to fail" is higher than the current number of members of a chosen group (after exclusions). It does not block saving: the group can change before the approval starts.

    • The server checks the same bounds (1 to 999) for every saved definition, from the editor and the Web API.

  2. A fixed voting deadline that has passed.

    • A vote step that starts with its fixed deadline already passed behaves as decided in decision 5.

    • The server checks that a fixed date is in the future when the definition is saved, in the editor and in the Web API.

Decisions needed

  1. Fix 1: the starter's "step blocked" message: a new editable message template (Jira and Confluence defaults), or a fixed text first? Recommended: the template, like every other message to the starter.

  2. Fix 1: decide a blocked step also through Web API v2 decisions and Rovo, or only in the app UI first? Recommended: the app UI only; Rovo shows the blocked state and who can decide it.

  3. Fix 1: handle parallel groups that split without a result here too? Recommended: no, a separate ticket; parallel group rules (required steps, modes) differ.

  4. Fix 1: no one left to vote and only abstains. a) Blocked. b) Approved, the order used today when one abstain reaches both numbers. c) Rejected. Recommended: a), nobody took a position, so the starter decides.

  5. Fix 2: a vote step starts and its fixed deadline has already passed.

    • a) Voting stays open without a deadline; the moderator is told the deadline was ignored.

    • b) The approval cannot be started, with a message naming the step.

    • c) Voting stays closed, as today, and only the moderator is notified: the start notification follows the rule of VotingDeadlineand Rovo's RecipientsByRole.

    Recommended: a). Starting must not fail because of a stale date, and voters must not be asked to vote on a closed vote.

Out of scope

  • Removing a step from a running approval: the step removal ticket.

  • Parallel groups that split without a result, unless decision 3 says otherwise.

  • The voting deadline timer is kept in memory; a server restart before the deadline drops the moderator's "voting expired" message.

Acceptance criteria

  • Group of 3, 5 to pass, 5 to fail: all approve, the step is approved and Activity says 5 were required; two reject and one abstains, it is rejected.

  • Group of 2, 2 to pass, 2 to fail: one approves, one rejects; the step is blocked, every view listed above shows the reason, and the starter gets one notification.

  • The starter rejects a blocked step with a comment; the approval continues. Without a comment it is refused.

  • A starter excluded from the step can reject but not approve; one not excluded can approve. A global admin can do both; another user cannot.

  • Jira, group from a work item field: adding a user clears the block; removing the only member who had not voted ends the step as above. A blocked approval becomes Incomplete when its decision deadline passes.

  • Notification group steps and Notification user field steps with "Treat users as a group" show no votes fields.

  • The editor warns when "to pass" or "to fail" exceeds the group size and still saves; 0 or 1000 is refused, from the editor and the Web API.

  • A vote step whose fixed deadline passed before it starts follows decision 5, and voters are not asked to vote on a closed vote.

  • A definition with a fixed voting deadline in the past cannot be saved, from the editor or the Web API.

Manual tester notes

  • Use groups of 2 or 3 users; repeat the group cases with the approval creator in the group, excluded and not.

  • Check the blocked reason in the work item panel, the approvals list, the approval details and in Rovo, and the starter's notification on each enabled channel.

  • Live group: remove the last member who has not voted; the step changes at the next pending approver refresh (up to 12 hours; ask for a shorter interval on qa).

  • Deadline: definitions saved before the release with a past and a future fixed date; a fixed date a few minutes away on a vote step that starts after it.

  • Repeat a group case and the deadline case in Confluence.