Skip to content

feat: unified VendorRiskScore — fuse gap analysis + contract review + questionnaire into one score per vendor #416

Description

@AndreLiar

Fusionner les 3 méthodes de due diligence en un score de risque unique par vendor, pondéré preuve > déclaration (sert le moat profondeur — cf. Product Vision). doragrc / questionnaire-only ne peut pas faire ça (il ne lit pas les preuves).

Les 3 signaux (déjà 0-100 dans le code)

Source Champ existant → 0-100
Gap analysis DORA Assessment.results.overallRisk (High/Medium/Low) + gaps[].gapLevel High=0 · Medium=50 · Low=100 (déjà dans AssessmentRepository.getComplianceScore)
Contract review Art 30 Assessment.clauseSignoffs[].gapLevel (covered/partial/missing) % clauses : covered=1 · partial=0.5 · missing=0
Questionnaire VendorQuestionnaire.overallScore (0-100) + questions[].score déjà 0-100

La fusion — VendorRiskScore

Pas une moyenne bête. 4 règles :

  1. Pondérer preuve > déclaration : départ 0.40·Docs + 0.35·Contrat + 0.25·Questionnaire (calibrer via E1).
  2. Confiance = n/3 signaux présents : afficher « 72 — basé sur 2/3 sources » ; renormaliser sur les signaux présents.
  3. Fraîcheur / décroissance : signaux anciens pèsent moins (réutiliser memoryDecayQueue).
  4. Overlay « gap critique » : une clause Art 30 critique (audit, exit, sous-traitance) missing → flag rouge par-dessus la moyenne (une moyenne cache un trou critique).

→ Sortie : score 0-100 + niveau de confiance (n/3) + flags critiques.

Usage selon le statut vendor (dépend de #409 niveau 2)

Statut Rôle du score Action
under-review Décision GO/NO-GO (signer ?) seuil < X ou clause critique manquante → ne pas signer ; pousse à collecter les sources manquantes ; alimente la décision de risque (proceed/conditional/reject)
active Monitoring continu tendance → alertes de dégradation ; cadence de ré-évaluation (nextReviewDate) ; alimente RoI + concentration
exited Historique gelé exclu des moyennes/alertes ; conservé pour audit trail (offboarding responsable)

→ « under-review = le score décide · active = il surveille · exited = il archive ».

Crochets d'implémentation

  • getVendorRiskScore(workspaceId) — étendre le pattern de AssessmentRepository.getComplianceScore pour tirer les 3 sources
  • Normalisation contract-coverage (% clauses) + réutiliser VendorQuestionnaire.overallScore
  • Pondération + confiance (n/3) + overlay flags critiques
  • Décroissance par fraîcheur (memoryDecayQueue)
  • Gating par seuil branché sur vendorStatus (feat(ux): rendre le cycle de vie vendor réel (under-review → active → exited) + dates de contrat conditionnelles #409) + la décision de risque
  • UI : badge score + confiance + flags sur la carte vendor / risk register
  • Calibrer les poids via E1 (éval) — golden dataset

Dépendances

Réf code

  • backend/repositories/AssessmentRepository.js (getComplianceScore) · models/Assessment.js (results.overallRisk, clauseSignoffs[].gapLevel) · models/VendorQuestionnaire.js (overallScore, questions[].score)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions