Example output
Example: from rough notes to a Jira-ready ticket
Below is the kind of input a Business Analyst typically has after a short call, and the ticket and specification baticket produces from it. Nothing was tidied up beforehand.
1. The input: raw meeting notes
Shorthand, a missing decision, and a security requirement buried in the middle.
notes.txt
call w/ Marta (product) + Piotr (support), 14.09 - ppl keep forgetting pw, support gets ~40 tickets/week just for resets - want "forgot password" on login page - email w/ link, link valid short time (1h? Marta said "an hour is fine") - don't reveal if email exists!! (security asked for this last audit) - new pw min 10 chars, same rules as registration - after reset -> log them in? Piotr: no, send them to login w/ success msg - rate limit? not discussed
2. The ticket: TICKET_CONTENT.md
Five fixed sections — context, goal, user stories and Given/When/Then acceptance criteria, each scenario in its own block so it pastes cleanly into Jira, Linear or Azure DevOps.
TICKET_CONTENT.md
# [BE/FE] Self-service password reset by email ## 1. 🔵 Business context & user stories Support handles around 40 password-reset requests a week. Letting users reset their own password removes that load and unblocks users immediately. ## 2. 🎯 High-level goal Users who forget their password can set a new one on their own from the login page, without contacting support. The flow must not reveal whether an email address has an account. Success means password-reset tickets to support drop to near zero. ## 3. 👤 User stories - As a registered user, I want to request a password reset link from the login page, so that I can regain access without contacting support. - As a registered user, I want to set a new password from that link, so that I can log in again. - As a support agent, I want users to reset passwords themselves, so that I can focus on real issues. ## 4. 🟩 Acceptance criteria ``` Scenario 1: Request a reset link for an existing account Given: a registered user on the login page When: they click "Forgot password?" and submit their email address Then: the API responds 200 And: an email with a single-use reset link valid for 1 hour is sent And: the page shows "If an account exists for this email, we've sent a link." ``` ``` Scenario 2: Request a reset link for an unknown email Given: an email address with no account When: it is submitted on the "Forgot password" form Then: the API responds 200 with the same body as Scenario 1 And: no email is sent ``` ``` Scenario 3: Set a new password Given: a valid, unused reset link When: the user submits a new password of at least 10 characters Then: the password is updated and the link is invalidated And: the user is redirected to the login page with "Your password has been changed." ``` ``` Scenario 4: Expired or used link Given: a reset link older than 1 hour, or one already used When: the user opens it Then: the page shows "This link has expired" with an option to request a new one ``` ``` Scenario 5: Unit tests — token handling Given: the token service When: a token is created, verified, expired and reused Then: only an unexpired, unused token verifies successfully ``` ## 5. 📄 Full specification See the accompanying SPECIFICATION.md for full detail.
3. The specification: SPECIFICATION.md (excerpt)
The full detail lives here, including the API contract with validation rules — and the questions the notes left open, instead of guesses.
SPECIFICATION.md
# [BE/FE] Self-service password reset by email
## Scope
- "Forgot password?" link on the login page.
- Request form that emails a single-use reset link valid for 1 hour.
- Reset form that sets a new password using the registration password rules.
- Neutral responses that never reveal whether an account exists.
## API
**Endpoint:** `POST /api/v1/auth/forgot-password`
**Request body (JSON):**
```json
{ "email": "string" }
```
**Validation**
| Field | Rules | Error message |
|---|---|---|
| email | required, email | "Enter a valid email address." |
**Endpoint:** `POST /api/v1/auth/reset-password`
**Request body (JSON):**
```json
{ "token": "string", "password": "string" }
```
| Field | Rules | Error message |
|---|---|---|
| password | required, minLength 10 | "Your password must be at least 10 characters long." |
## Missing / to confirm
- Rate limiting for reset requests was not discussed — confirm limits with security.
- Should existing sessions be signed out after a password change?