Project

General

Profile

Actions

Feature #48

closed
RA

Feature #24: Implémenter un hook pour la création automatique de tickets Redmine depuis les scans Trivy et Semgrep

Présentation & sécurité : endpoint POST /scan-results, validation, permissions + doc

Feature #48: Présentation & sécurité : endpoint POST /scan-results, validation, permissions + doc

Added by Redmine Admin about 2 months ago. Updated about 2 months ago.

Status:
Shipped
Priority:
Normal
Assignee:
-
Start date:
06/11/2026
Due date:
% Done:

0%

Estimated time:
spec_ref:

conversation:21#24

build_status:
build_number:
ci_run_url:
scan_status:
scan_report_url:
deploy_status:
preprod_url:
deployed_at:
branch:
feat/48-scan-results-endpoint
pr_url:
https://github.com/omdev-tech/PipeLiner-Client/pull/28
security_key:
severity:
paused:

Description

Couche présentation de `api/` : endpoint `POST /scan-results` acceptant Trivy et Semgrep (discrimination de la source), invoquant le cas d'usage `CreateTicketsFromScan`. Validation stricte des payloads (schémas Pydantic, rejet malformé/abusif, anti-injection sur les champs réinjectés dans titre/description). Permissions : seul le projet concerné crée des tickets (secret webhook + contrôle `project_key`). Réponse = résumé (créés / ignorés-doublons / régressions), pas de 500 sur payload invalide (400) ni sur Redmine dégradé. Documentation : formats Trivy/Semgrep, logique anti-doublons/régression, prérequis `security_key`. TDD (tests d'API, Redmine mocké via respx).

## Critères d'acceptation
- `POST /scan-results` accepte Trivy et Semgrep et déclenche le cas d'usage.
- Payloads malformés/abusifs rejetés (400) ; champs réinjectés assainis (anti-injection).
- Permissions vérifiées (secret webhook + `project_key`) ; accès non autorisé refusé (401/403).
- Réponse résumé créés/doublons/régressions ; pas de 500 sur payload invalide ni Redmine dégradé.
- Documentation livrée ; tests d'API verts ; ruff + mypy passent.

Estimation : M. Dépend de : « Domaine & application … » + « Infrastructure Redmine … ».


Files

qa-48-scan-results-proof.txt (4.21 KB) qa-48-scan-results-proof.txt Redmine Admin, 06/11/2026 08:09 PM

RA Updated by Redmine Admin about 2 months ago Actions #1

  • Status changed from Submitted to Spec
  • spec_ref updated (diff)

Finalisé dev-ready (spec_ref posé, Submitted→Spec). Unité présentation & sécurité de l'épopée #24, déjà entièrement décrite. Dépend de #47 (infrastructure Redmine). Build en dernier dans la chaîne #46→#47→#48.

RA Updated by Redmine Admin about 2 months ago Actions #2

  • Status changed from Spec to In development

RA Updated by Redmine Admin about 2 months ago Actions #3

  • Status changed from In development to QA
  • branch set to feat/48-scan-results-endpoint
  • pr_url set to https://github.com/omdev-tech/PipeLiner-Client/pull/28

PR ouverte vers `dev` : https://github.com/omdev-tech/PipeLiner-Client/pull/28

Couche présentation livrée (#48) :
- `POST /scan-results` accepte Trivy et Semgrep (discrimination de la source) et déclenche `CreateTicketsFromScan` (#46) via `RedmineScanTicketAdapter` (#47).
- Validation Pydantic stricte (énum `tool`, `project_key` contraint à un slug, `extra=forbid`, `report` objet) → **400** sur payload malformé/abusif ; anti-injection sur `project_key`.
- Permissions : secret webhook `X-Webhook-Secret` (absent/faux → **401**, secret vide = désactivé) + `project_key` lié à un projet Redmine (inconnu/non lié → **403**).
- Réponse = résumé créés/doublons/régressions ; **pas de 500** sur payload invalide (→400) ni sur Redmine dégradé (→ enveloppe 200 `degraded`).
- Documentation : `docs/superpowers/specs/2026-06-11-scan-results-webhook.md` (formats Trivy/Semgrep, anti-doublons/régression, prérequis `security_key`).

Gate vert : pytest 438 passed / 2 skipped (×2 sur pgvector:pg16, idempotent), ruff OK, mypy OK. Branché sur `origin/dev` (dépend de #47).

Statut : In development → QA.

RA Updated by Redmine Admin about 2 months ago Actions #5

**Rapport QA — VERDICT : PASS** (5/5 critères d'acceptation OK)

Test de fumée backend exécuté sur la branche `feat/48-scan-results-endpoint` (commit f247858, PR #28). Aucune UI à exercer (ticket backend-only) → preuve = suites de tests. Aucun secret/token/mot de passe n'a été inclus dans la preuve (valeurs de fixture caviardées).

**Gate backend** (Postgres `pgvector:pg16` éphémère + `alembic upgrade head`) :
- `pytest -q` (suite complète) : **438 passed, 2 skipped** — conforme au baseline dev-run.
- `ruff check .` : All checks passed.
- `mypy src` : Success, no issues found in 116 source files.

**Smoke test ciblé** — `tests/test_scan_results_api.py` : **15/15 PASSED**.

**Critères d'acceptation → résultat :**
- [OK] `POST /scan-results` accepte Trivy **et** Semgrep et déclenche `CreateTicketsFromScan` (#46) via l'adaptateur #47 — `test_trivy_creates_ticket_and_summarizes`, `test_semgrep_is_accepted`.
- [OK] Payloads malformés/abusifs rejetés en **400** (jamais 422/500) ; anti-injection sur `project_key` (slug contraint) — `test_unknown_tool_is_400`, `test_extra_top_level_key_is_400`, `test_injection_project_key_is_400`, `test_report_not_an_object_is_400`, `test_non_json_body_is_400`.
- [OK] Permissions : header webhook manquant/mauvais → **401** (et instance non configurée → webhook désactivé) ; `project_key` inconnu/non-lié à Redmine → **403** — `test_missing_secret_is_401`, `test_wrong_secret_is_401`, `test_empty_configured_secret_disables_webhook`, `test_unknown_project_key_is_403`, `test_unlinked_project_is_403`.
- [OK] Réponse = résumé créés/doublons/régressions — `test_trivy_creates_ticket_and_summarizes`, `test_open_duplicate_is_deduped`, `test_resolved_ticket_is_regression`.
- [OK] Pas de 500 sur Redmine dégradé : **200** schéma-valide avec `degraded: true` — `test_degraded_redmine_returns_200_envelope`.
- [OK] Documentation livrée : `docs/superpowers/specs/2026-06-11-scan-results-webhook.md` (formats Trivy/Semgrep, logique anti-doublons/régression, prérequis `security_key`).

**Preuve technique jointe :** `qa-48-scan-results-proof.txt`.

Statut maintenu en **QA** (promotion preprod = autre agent).

RA Updated by Redmine Admin about 2 months ago Actions #6

  • Status changed from QA to Shipped

Shipped to production (master build #65). `POST /scan-results` endpoint (Trivy+Semgrep, strict validation→400, webhook-secret + project_key permissions, summary response, degraded Redmine→200). QA PASS. With #47 this completes epic #24's scan→ticket hook backend (domain #46 + infra #47 + presentation #48 all live).

Actions

Also available in: PDF Atom