Feature #72
closedDisplay vuln severity chip on the ticket list + detail (read severity field 13) — extends #24/#70
0%
conversation:scan-severity-display
Description
**Lié à :** #24/#70 · **Surface :** Client-Dashboard fullstack (`api/` + `src/`)
Afficher la **sévérité** des tickets de sécurité sur la liste + le détail du ticketing, sur le modèle exact du tag `bf-disagree` (#51). Le ticketing lit Redmine **directement** (pas l'aggregator) — donc pas de changement aggregator.
**Backend (`api/`)** :
- `domain/redmine/value_objects.py` : `RedmineField.SEVERITY = 13` (le champ custom `severity` existe sur le Redmine live, liste critical/high/medium/low).
- `domain/tasks/value_objects.py` : ajouter `severity: str | None` à `TaskSummary` (et `TaskDetail`).
- `application/task_board.py` `_to_summary`/`_to_detail` : `severity=fields.get(RedmineField.SEVERITY)` (déjà fetché avec les autres custom fields).
- `presentation/api/tasks.py` : ajouter `severity: str | None` à `TaskSummaryOut` (+ detail). Aucun nouvel appel upstream.
**Frontend (`src/`)** :
- Un atome `SeverityTag` (puce colorée : critical/high/medium/low) réutilisant les tokens de couleur de sévérité existants (cf. modules Security Ops / SOUPs ; pas de nouvelle couleur), rendu dans `TaskRow` (liste) et `TaskDetailPane` (détail) quand `task.severity` est défini — exactement comme `BfDisagreeTag`.
- i18n dans `en.ts` uniquement.
## Critères d'acceptation
- `TaskSummaryOut.severity` exposé depuis le champ custom 13 (multi-tenant, pas d'appel upstream).
- Puce de sévérité colorée affichée sur la liste ET le détail quand le ticket a une sévérité.
- FR/EN (`en.ts`) ; réutilise les tokens existants. Gate vert : backend (pytest/ruff/mypy) + frontend (vitest/tsc/eslint/build). TDD.