Skip to content

Ticket template — section by section

The Securitize ticket template has six sections. General description is always rendered; Acceptance Criteria is mandatory for most types and optional for Epic; four are optional with three valid states.

# General description       ← mandatory
# Acceptance Criteria        ← mandatory in BDD for Bug/Task/Story/custom; optional and free-form for Epic
# How to test                ← optional
# Figma url                  ← optional
# Screenshots                ← optional (special: always placeholder if used — see below)
# Technical notes            ← optional

Optional section states (fill / placeholder / skip)

For each optional section the user picks one of three states:

State What renders When to use
Fill it now Header + content the user provided The user has the information at hand.
Leave as TBD placeholder Header + _TBD — to be added._ The user wants to remember to complete it later in Jira (Figma URL pending, screenshots not yet captured, etc.).
Skip entirely Nothing — the header is omitted The section does not apply to this ticket at all.

Never produce an empty header. If a section has no content and no placeholder, drop it.

Language

The ticket body is always written in English, regardless of the language the user uses in chat. This is the Securitize convention. The workflow drafts in English and shows for confirmation. See index.md → "Language — chat vs. ticket body".

Title

Not part of the body — it goes in the Jira summary field.

  • Format: [TAG1][TAG2] <descriptive title>.
  • Tags: optional, free-form, in square brackets at the start. Each team picks its own conventions; some teams don't use tags. The workflow does not validate or normalize.
  • Length: 60–70 characters max, tags included.
  • Style: one line, no trailing period, sentence case.
  • Auto-generation: the workflow produces a draft from the General description and shows it to the user for confirmation or edit. The user can rewrite freely as long as it fits the length limit.

Examples: - [BE] Redirect to /mfa-setup when MFA is expired - [FE][bug] Empty state flickers on dashboard load - Move issuer KYC retry from 5m to 15m (no tags)

# General description

Mandatory. A short summary that explains: - What the ticket is about (the problem or the goal). - Why it matters (motivation, business or technical context). - Scope — what is in, what is out.

Keep it tight: 3–8 lines for most tickets. If the description is longer than 15 lines, the ticket is probably too big.

Example:

When a user's MFA token expires (>24h since last verification) they currently land on /dashboard and see broken UI because protected API calls return 401. The expected behavior is a redirect to /mfa-setup so the user can re-establish MFA.

In scope: the redirect logic in the dashboard route. Out of scope: the MFA setup flow itself, which already exists.

# Acceptance Criteria

Behavior depends on issue type.

For Bug / Task / Story / project-specific custom types — MANDATORY in BDD.

At least one scenario in BDD format (Given / When / Then). See bdd-acceptance-criteria.md for the full guide on writing good AC. The workflow renders each scenario as:

## Scenario N: <short title>
- **Given** ...
- **When** ...
- **Then** ...
- **And** ... (optional)

A ticket usually has 2–4 scenarios. More than 6 is a sign the ticket should be split.

For Epic — OPTIONAL and NOT BDD.

Epics describe the goal of a feature; testable behavior lives in the child Stories/Tasks. If the user wants to include AC on an Epic, render it as a free-form bulleted list of high-level goals/outcomes — do not coerce into Given/When/Then. Three states apply (fill / TBD placeholder / skip); if skipped, omit the Acceptance Criteria header entirely from the Epic. See issue-types.mdEpic.

# How to test

Optional. QA tips for verifying the behavior. Useful when the test setup is non-obvious. Common content:

  • Test data per environment (dev / rc / sandbox / prod): which accounts, which records, which feature flags are on.
  • Specific accounts to use (e.g. "investor account qa+mfa-expired@securitize.io in rc").
  • Feature flags that need to be on or off.
  • Edge cases worth checking explicitly.
  • Expected error messages the QA engineer should see when triggering negative paths.

See how-to-test-tips.md for more on what tends to be useful.

Example:

dev

  • User: qa+mfa-expired@securitize.io
  • Flag mfa-enforce must be on (it is by default in dev).

rc

  • User: qa+mfa-expired@securitize.io (mirrored from dev).

Edge cases: - Token exactly at the 24h boundary — should NOT redirect. - User without an MFA-capable device — should redirect to /mfa-setup and surface the "no devices" message.

# Figma url

Optional, three states. A single link to the Figma file or frame relevant to this ticket. Multiple links are fine if they are all on-topic. Common pattern: the user wants to add the link but doesn't have it ready — use the placeholder state.

Filled example:

https://www.figma.com/file/abc123/Onboarding?node-id=42

Placeholder state (renders when the user wants to remember to add it later):

# Figma url

_TBD — to be added._

# Screenshots

Optional, special. The Atlassian MCP cannot upload files — there is no tool in the current Atlassian MCP surface that attaches images to a Jira issue. Therefore, when the user wants screenshots, the workflow always renders this section as a placeholder and tells the user to attach the files manually via the Jira UI after creation.

What the user sees:

Want to attach screenshots? I can't upload them from here, but I'll leave a TBD placeholder so you can attach them in Jira after creation. Yes / skip.

What renders in the ticket (placeholder state):

# Screenshots

_TBD — to be attached manually in Jira after the ticket is created._

If the user says skip, the section is omitted entirely. The "fill it now" state does not apply here — there is no way to embed an image from chat.

# Technical notes

Optional. Implementation context for whoever picks up the ticket. Common content:

  • Libraries or services likely to be touched.
  • Tradeoffs or open design decisions.
  • Related tickets, PRs, or commits.
  • Known constraints (e.g. "the redirect must preserve the query string").
  • Stacktraces, error logs, or relevant code snippets — these often live better here than in the General description.

Example:

The redirect logic should live in the auth-guard middleware in apps/dashboard/src/middleware/auth-guard.ts. There is a similar redirect for unverified users — keep them consistent.

Stacktrace from production:

AuthError: token_expired at validateToken (auth-guard.ts:47)
    at handleRequest (server.ts:88)

Related: ON-1102 (the previous attempt that was reverted).

Order in the rendered ticket

The workflow renders sections in this exact order:

  1. General description
  2. Acceptance Criteria
  3. How to test (if present)
  4. Figma url (if present)
  5. Screenshots (if present)
  6. Technical notes (if present)

Whole-ticket worked example

# General description

When a user's MFA token expires (>24h since last verification) they currently land on `/dashboard` and see broken UI because protected API calls return 401. Redirect to `/mfa-setup` so the user can re-establish MFA before reaching protected routes.

# Acceptance Criteria

## Scenario 1: MFA-expired user is redirected to setup
- **Given** a logged-in user whose MFA token expired more than 24h ago
- **When** the user navigates to `/dashboard`
- **Then** the user is redirected to `/mfa-setup`
- **And** the original target URL is preserved as a query param

## Scenario 2: User without MFA devices sees the error message
- **Given** a logged-in user with expired MFA and no registered MFA devices
- **When** the user navigates to `/dashboard`
- **Then** the user is redirected to `/mfa-setup`
- **And** the page shows the "no MFA devices registered" message

# How to test

### dev
- User: `qa+mfa-expired@securitize.io`
- Flag `mfa-enforce` must be on (default in dev).

# Technical notes

The redirect should live in `apps/dashboard/src/middleware/auth-guard.ts`. There is a similar redirect for unverified users — keep them consistent.

Related: ON-1102 (the previous attempt that was reverted).