Confirm decisions with a personal PIN
Description
Problem
Anyone using an approver's open Jira or Confluence session, or holding a forwarded email with action buttons, can decide in the approver's name. AP-385 lets admins require a code sent by email, which proves access to the mailbox but adds an email round trip to every decision. Teams that sign approvals electronically (for example under 21 CFR Part 11) want decisions confirmed with something only the deciding person knows: a personal PIN entered when deciding.
Change
Settings
-
Decision confirmation > Settings (first tab of the admin page; global admins, Jira and Confluence) gets the method PIN, next to Disabled (default), One-time code (AP-385) and Authenticator app (AP-730). One method per site.
-
Scope, shown while a method is chosen: Enabled (on by default in every definition, a definition can turn it off) or Required (every definition, none can turn it off).
-
Definition editor: one "Confirm decisions" checkbox, shown while a method is chosen, on by default; locked on with "Required in Decision confirmation > Settings" in its tooltip under Required, saved only under Enabled. No per-step option and no option on the Parametrize form.
-
Settings > General > Web API: "Skip decision confirmation for Web API decisions" covers the PIN. It is shown while Web API decisions are on and a method is chosen.
-
Switching to another method keeps everyone's PIN; it applies again when the method is PIN.
A decision needs a PIN when the method is PIN, the scope is Required or the approval's definition had "Confirm decisions" on when the approval started, and an Atlassian user decides the step: user, group and vote steps and work item user and group field steps. The setting is read when someone decides, so a change reaches running approvals at once; reruns read the definition again; older approvals count as on. It applies to everyone who decides, each with their own PIN: approvers, delegates, group members, voters, the vote moderator and JSM customers in the portal, for Approve, Consent, Reject, Abstain and Vote. Admin actions (start, rerun, reassign, archive, delete) need no PIN.
Email approvers (email steps, work item email field steps) have no account for a PIN: they confirm with AP-385's emailed code, marked "Confirmed with a one-time code instead of a PIN".
The PIN
-
Exactly 4 digits. Refused as too easy to guess: one digit four times (1111), four digits in a row up or down (1234, 4321), a repeated pair (1212).
-
Setting the first PIN, changing it and resetting a forgotten or locked PIN are one action: the person enters the new PIN twice, the app emails a 6-digit code, and the PIN is saved once the code is entered. There is no field for the current PIN and no reset link. The code follows AP-385's rules and delivery (10 minutes, works once, 5 wrong entries, a new code after 60 seconds, hourly and daily limits). The email says the code sets a new Approval Path PIN and what to do if the person did not ask for it.
-
5 wrong PIN entries in a row lock the PIN, wherever they were entered. A locked PIN is refused until the person sets a new one; a right PIN resets the count. When the PIN locks, the app emails the person (a failed email does not change the lock).
-
The PIN is stored only as a keyed hash: nobody, admins included, can read it. It is never logged or shown, and it is entered only on the app's pages in Jira and Confluence and on the app's email action page.
Personal > PIN
-
New item "PIN" (New badge) in the Personal section of the app sidebar, in Jira and Confluence, for every user, shown while the method is PIN.
-
It shows "You have not set a PIN yet.", "Your PIN was set on 26 Oct 2026, 14:44." or "Your PIN was locked on 28 Oct 2026, 09:12 after 5 wrong entries. Set a new PIN to decide on approvals that require it.", and offers "Set a PIN" or "Set a new PIN": "New PIN", "Confirm PIN", "Send code", the code field, "Send a new code" after 60 seconds, and "Save PIN".
-
JSM portal customers cannot reach the page; they set their PIN in the decision dialog.
Where the PIN is asked
-
Panel (Jira work item, JSM portal, Confluence page, approvals list details), list row actions, the Confluence home feed, and links from emails and chat that open the work item or page: the "Confirm your decision" dialog asks for the PIN and shows what is being confirmed. A wrong PIN shows the attempts left. With no PIN or a locked PIN the dialog shows the set-PIN form ("Forgot your PIN?" opens it as well); once the new PIN is saved, the decision is confirmed with it.
-
Bulk decisions: one PIN entry covers every selected approval that needs it, asked in the bulk dialog after the comments, which lists the approvals. Approvals found to need a PIN only on submit are left undecided and a second dialog asks for them.
-
Email action buttons and Web API step links: the page they open asks for the PIN in a masked field and never decides when it opens. It checks that the link's person still decides on the step before checking the PIN, so an outdated or forwarded link cannot be used to guess it. With no PIN or a locked PIN, the page says so and links to the work item or page.
-
Slack and Teams: decision buttons on approvals that need a PIN record nothing and reply that the decision needs the PIN in Jira (Confluence), with the link. The PIN never passes through a chat.
-
Rovo: refuses with the link to the work item or page. Its lists say which approvals need a PIN; it never asks for one.
-
Web API: refuses with
PIN_CONFIRMATION_REQUIREDunless "Skip decision confirmation for Web API decisions" is on; then the decision is recorded and marked "PIN confirmation skipped". -
When a PIN turns out to be needed only on submit (a page loaded before the setting changed), the decision is refused and the dialog opens. A single decision that is refused anyway (approval completed, archived, incomplete, outdated or past its deadline, or a required comment missing) is refused before the PIN is checked, so it costs no attempt; a bulk decision checks the PIN once before deciding.
Activity
-
The panel's step details and Activity show a lock icon with "Confirmed with a PIN", "Confirmed with a one-time code instead of a PIN" for email approvers, or an open lock with "PIN confirmation skipped" for Web API decisions under the skip option; per member and voter in the step details, and for group and vote rows by AP-385's rule (skipped when any decision skipped it, otherwise confirmed).
-
The Activity CSV "Confirmation" column, shared by every method, says PIN, One-time code instead of PIN or PIN skipped. AP-730's confirmation log records PIN decisions, wrong PINs, new PINs and locks.
Decisions
-
A PIN is saved only after a code emailed to the account is entered, so someone using an unattended session cannot set or replace it, and a forwarded link cannot reach the PIN form at all.
-
One method per site: while the method is PIN, a decision asks only for the PIN, never for an emailed code too.
-
PIN entry only on the app's pages: Slack has no masked input, and a reusable secret would pass through the chat provider's servers. Rovo, as for codes, never asks.
-
Wrong entries count per person across all places of one app: Jira and Confluence keep separate PINs and counts. Someone holding a forwarded email link can lock the approver's PIN; the approver then sets a new one by email. Five wrong guesses in a row, with a right PIN resetting the count, is worth that.
-
The hash key derives from the app's own secret, not from the per-site secret, which changes on every app upgrade. A copy of the database alone does not reveal PINs. After the app secret is rotated, existing PINs count as not set and people set a new one.
-
Scope Enabled or Required with an opt-out per definition; no per-step or per-approval option. A per-step option can come later if customers ask.
Out of scope
-
An admin view or reset of users' PINs, PIN expiry, other PIN lengths.
-
PINs for email approvers (separate ticket); they confirm with an emailed code.
-
An entry in Jira's profile menu (Forge personal settings page).
-
Webhook payloads, JQL and the Approval Status field.
Acceptance criteria
-
Method not PIN: no channel asks for a PIN and Personal > PIN is hidden. Only global admins change the setting.
-
Method PIN, scope Enabled, definition checked: the panel, list, bulk, home feed and email action page ask for the PIN on every people step; a wrong PIN is refused with the attempts left; the right PIN records the decision and Activity shows "Confirmed with a PIN". A definition with "Confirm decisions" cleared asks for nothing. Scope Required: every approval asks.
-
Email approvers get an emailed code under PIN, marked "Confirmed with a one-time code instead of a PIN".
-
A PIN is saved only with the right emailed code. 4 digits only, trivial PINs refused, both entries must match.
-
5 wrong entries in a row, in any mix of places, lock the PIN; a locked PIN is refused even when right; setting a new PIN unlocks it. The person gets the lock email.
-
A person without a PIN can set one from the decision dialog, also as a JSM customer in the portal, and then decide.
-
Delegates, group members, voters and the moderator each enter their own PIN.
-
A bulk decision of 25 approvals, some needing a PIN, asks for the PIN once and records all of them.
-
Slack and Teams record nothing on such approvals and reply with the link; Rovo refuses with the link; the Web API refuses with
PIN_CONFIRMATION_REQUIRED, or with the skip option on records the decision marked "PIN confirmation skipped". -
A crafted request cannot decide on an approval that needs a PIN without the person's right PIN, cannot check or set another person's PIN, and cannot set a PIN without the emailed code.
-
No PIN appears in logs, URLs, the app's stored emails, chat payloads or API responses.
Manual tester notes
-
Code emails for setting a PIN: from Personal > PIN in Jira (Direct email, Jira notification and Slack mechanisms: the page reads the account's address in every case) and Confluence, and from the decision dialog on a work item, in the JSM portal and on a Confluence page; a user whose email the app cannot read (expect the "could not send" message and an instance error).
-
JSM customer with portal-only access (no Jira license), under the Jira notification and Direct email mechanisms: the code for setting a PIN and the lock email arrive in the customer's inbox. Check the inbox, not the dialog: Jira answers success even when it drops a recipient. (Jira notifications reached a portal-only customer on wd-test-1, 2026-10-28, on a request they reported and on one they are not part of.)
-
Reassign a step, and change a work item user field, on an approval that needs a PIN: the new approver is asked.
-
Switch the method from PIN to another and back: PINs are kept and asked again.
-
Lock: 5 wrong entries spread over the panel, the email action page and a bulk decision; the lock email arrives; setting a new PIN unlocks; a forwarded email link used by someone else locks the approver's PIN.
-
Browsers (including Firefox, where the field falls back to a password field) and password managers: the PIN fields do not offer to save or fill a password; phones show a numeric keypad.
-
Method switched to PIN while a panel is open: the stale panel gets the refusal and the dialog.
-
A panel left open while the approval is completed elsewhere: a wrong PIN costs no attempt and the panel shows the approval's state.
-
Definition editor: "Confirm decisions" shown only while a method is chosen, locked on under Required; email approvers under PIN get an emailed code on the approver portal, email links and Slack.
-
Slack on desktop and phone, Teams (after AP-2146), Rovo single and batch decisions: the Jira texts never name Confluence and the Confluence texts never name Jira.
-
Two backend nodes: wrong entries on both count toward one lock.