Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ il n'est pas encore la plateforme différenciante du Master Prompt V5 (Wave 2/3)
| **9. Notifications** | ✅ (cœur) | `pkg/notify`, `notification_service`, `notification_handler`, centre de notifs frontend. | Canaux **Email (Resend/SMTP), Slack, Webhook signé** non prouvés live. Webhooks sortants à vérifier. |
| **10. IA Advisor** | 🟡 | **Fondation `pkg/ai` créée** (10/07, 1er vrai client LLM du repo : interface `Advisor`, `ClaudeAdvisor` sur `anthropics/anthropic-sdk-go` modèle `claude-opus-4-8`, `TemplateAdvisor` fallback). `ai_risk_predictor_service`, `recommendation_service`. | Les use cases V5 (analyze/mitigations/deduplicate/prioritize/narrative/executive-summary), l'`AIAdvisorTab` dans le RiskDrawer, le streaming, le cache/rate-limit IA : **non faits** (stubs sans provider). Chemin `ClaudeAdvisor` non prouvé live (pas de clé). |
| **11. Reporting & Export** | 🟡 | `pkg/report` (PDF `fpdf`, **conformité + Board Report ✅**), export CSV risques (`export_risks.go`), `export_handler`. | Pas de `pkg/export` async (jobs Redis, XLSX `excelize`, MinIO/S3, TTL). **Templates officiels COBAC/BCEAO/ISO/PCI ❌.** `ReportsPage.tsx` = maquette non câblée. |
| **12. Compliance Frameworks** | ✅ (moteur + couverture large) | Moteur M1 vérifié live ; **9 référentiels cités et importables** : ISO 27001:2022 (93) + **NIST CSF 2.0 (22 catégories)** + **CIS Controls v8 (18)** + **PCI DSS 4.0 (12 exigences)** + **HIPAA Security Rule (22 standards, cit. 45 CFR §164)** + **SOC 2 / AICPA TSC (51 : CC1–CC9 + A/C/PI/P)** + BCEAO (35) + ANTIC-CM (25) + COBAC (45) — chacun cité article/section par contrôle (`TestNoOrphanControls` + counts). Architecture plugin : un fichier `pkg/compliance/catalog_*.go` + `register()` → le catalogue remonte automatiquement dans `GET /compliance/catalogs` et devient importable, **zéro changement handler/frontend**. Frameworks **tenant-scoped** (migration 0030). **Gestion complète (13/07)** : créer/importer/supprimer référentiel + contrôle (RBAC), **personnalisation** (référentiel vierge + contrôle ad-hoc, vérifié live), preuve en chip cliquable, **progression temps réel**, **seuil de preuve obligatoire (mode strict, back+front)**. **Prouvé live 16/07** : les 10 catalogues listés avec bons comptes ; import SOC 2 (51) + NIST (22) ; contrôle ad-hoc CUSTOM-1 ; capture de l'écran Conformité (8 référentiels/288 contrôles). | Frameworks V5 restants (DORA, NIS2, GDPR JSON…) ; **cross-mapping ❌**, gap-analysis partiel ; catalogues modélisés au niveau catégorie/exigence (sous-contrôles ajoutables en ad-hoc) ; 1 placeholder (`cm-loi-2024-017`, texte non fourni). |
| **12. Compliance Frameworks** | ✅ (moteur + couverture large + audits + gap + remédiation) | Moteur M1 vérifié live ; **16 référentiels cités et importables** : ISO 27001:2022 (93) + **ISO/IEC 27005:2022 (19, processus de gestion du risque)** + **ISO 31000:2018 (22, principes/cadre/processus)** + **NIST CSF 2.0 (22)** + **NIST SP 800-53 Rev.5 (20 familles)** + **CIS Controls v8 (18)** + **PCI DSS 4.0 (12)** + **HIPAA Security Rule (22, cit. 45 CFR §164)** + **SOC 2 / AICPA TSC (51)** + **RGPD / UE 2016/679 (22 articles, FR)** + **DORA / UE 2022/2554 (19, 5 piliers, FR)** + **NIS2 / UE 2022/2555 (12, art. 21 mesures, FR)** + **SOX 2002 (10, sections + ITGC)** + BCEAO (35) + ANTIC-CM (25) + COBAC (45) — chacun cité article/section par contrôle (`TestNoOrphanControls` + `TestExpectedControlCounts`). Architecture plugin : un fichier `pkg/compliance/catalog_*.go` + `register()` → le catalogue remonte automatiquement dans `GET /compliance/catalogs` et devient importable, **zéro changement handler/frontend**. Frameworks **tenant-scoped** (migration 0030). **Gestion complète** : créer/importer/supprimer référentiel + contrôle (RBAC), **personnalisation** (référentiel vierge + contrôle ad-hoc), preuve en chip cliquable, **progression temps réel**, **seuil de preuve obligatoire (mode strict)**. **Analyse d'écarts (Gap Analysis) ✅ (16/07, branche `feature/compliance-management`)** : `GET /compliance/gap-analysis` (tous référentiels ou 1) → contrôles non satisfaits + roll-ups par référentiel ; page dédiée (jauge, filtres, écarts groupés) branchée sur le bouton « Voir les écarts » (auparavant inerte) ; « Remédier » par écart. **Audits ✅** : `domain.ComplianceAudit` (interne/externe/certification/surveillance ; planifié→en cours→terminé/annulé ; portée référentiel/programme ; auditeur/périmètre/résumé/score/dates), CRUD `/compliance/audits`, page de planification/exécution/historique. **Plans de remédiation ✅** : `domain.RemediationPlan` lié à un contrôle (l'écart) + à l'audit d'origine ; priorité/statut/assignation/échéance ; CRUD `/compliance/remediations`, page de suivi. **Auto-génération depuis un audit terminé ✅ (17/07)** : `POST /compliance/audits/:id/generate-remediations` ouvre un plan pour chaque écart du référentiel de l'audit (priorité déduite : not_implemented→high, in_progress→medium ; idempotent — saute les écarts déjà couverts) ; bouton « Remédier » par audit → toast créés/ignorés → registre. **Cross-mapping entre référentiels ✅ (17/07)** : `domain.ControlMapping` (crosswalk non-dirigé tenant-scoped entre deux contrôles + relation équivalent/partiel/lié), repo Gorm (Exists bidirectionnel, isolation tenant), use cases (Create = double garde cross-tenant + refus self/doublon, List enrichi, Delete) → `GET/POST /compliance/control-mappings` + `DELETE /:mappingId` ; section « Correspondances » dans le drawer de contrôle (lier vers un autre référentiel). **OpenAPI ✅ (17/07)** : gap-analysis/audits/remédiation/mappings dans `docs/openapi.yaml` (schémas + paths + `required`), types régénérés, `types/compliance.ts` re-pointé contract-first (enums dérivés). **Prouvé live 16-17/07** : 17 catalogues (16 dispo + 1 placeholder) bons comptes ; import DORA (19) ; gap-analysis (tous : 326 contrôles/274 écarts ; DORA 19/19/0 %) ; audit create→complete ; auto-remédiation 19 créés (201)→re-run 19 ignorés (idempotent) ; cross-mapping create 201/self-link 400/doublon inverse 409/list symétrique/delete 204 ; audit programme-wide→400. | Catalogues modélisés au niveau catégorie/exigence (sous-contrôles ajoutables en ad-hoc) ; 1 placeholder (`cm-loi-2024-017`, texte non fourni) ; cross-mapping = liens manuels (pas de crosswalk curé pré-rempli ISO↔NIST). |
| **13. Asset Management** | ✅ (inventaire + criticité + **dépendances** + historique, prouvé live 16/07) | M3 : Clean Architecture rétrofitée, snapshots historiques, criticité→Score Engine. `features/assets`. **Gestion centralisée complète (16/07, branche `feat/asset-dependency-mapping`)** : (1) **inventaire** étendu à la taxonomie GRC (Server/Application/Cloud/Database/SaaS/Storage/Network/Laptop/**Data/User/Supplier**) — icônes + chips de filtre ; (2) **classification par criticité** (déjà là, → Score Engine) ; (3) **cartographie des dépendances entre actifs** — nouveau modèle `AssetDependency` (arête dirigée tenant-scoped, 8 types de relation), repo+use cases (Create/List/Delete, gardes self-ref/doublon/cross-tenant, cascade à la suppression d'actif), handler `/asset-dependencies`, OpenAPI, `Asset Universe` **rebranché sur données réelles** (fixtures supprimées) avec éditeur de dépendances (ajout/retrait) dans le panneau ; (4) **historique des modifications** enfin exposé dans l'UI live (bouton « Historique » sur la modale d'édition → `AssetHistoryDrawer`). Preuves live : graph 7 actifs · 7 liens rendu, inventaire 11 types, endpoints 201/409/404/204, cascade + snapshot vérifiés. | Les 4 autres vues Universe (topology/bubbles/hierarchy) restent « coming soon ». Matching CVE via CPE dépend du CTI/Scanner (déjà câblé, item 21). |

### 1.2 Fonctionnalités avancées — Module 14.1 à 14.18 (le **moat** vs Vanta/Drata)
Expand Down
61 changes: 61 additions & 0 deletions backend/cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/opendefender/openrisk/internal/application/auth"
"github.com/opendefender/openrisk/internal/application/board"
"github.com/opendefender/openrisk/internal/application/compliance"
"github.com/opendefender/openrisk/internal/application/complianceaudit"
appmitigation "github.com/opendefender/openrisk/internal/application/mitigation"
notificationapp "github.com/opendefender/openrisk/internal/application/notification"
"github.com/opendefender/openrisk/internal/application/risk"
Expand Down Expand Up @@ -153,6 +154,9 @@ func main() {
// Directed edges of the asset dependency graph ("cartographie des
// dépendances"). Tenant-scoped; both endpoints reference assets.
&domain.AssetDependency{},
// Cross-framework control crosswalks ("cross-mapping entre référentiels").
// Tenant-scoped undirected links between two compliance controls.
&domain.ControlMapping{},
&domain.RiskHistory{},
&domain.CustomField{},
&domain.CustomFieldTemplate{},
Expand Down Expand Up @@ -204,6 +208,10 @@ func main() {
// sets it (a bare map[string]interface{} has no driver.Valuer).
&domain.Notification{},
&domain.NotificationPreference{},
// Compliance audits ("Audits" — plan/execute/history) and remediation
// plans ("Plans de remédiation" — close a gap, assign, track). Tenant-scoped.
&domain.ComplianceAudit{},
&domain.RemediationPlan{},
); err != nil {
log.Fatalf("Database Migration Failed: %v", err)
}
Expand Down Expand Up @@ -643,6 +651,11 @@ func main() {
deleteEvidenceUC := compliance.NewDeleteEvidenceUseCase(complianceRepo, fileStorage)
downloadEvidenceUC := compliance.NewDownloadEvidenceUseCase(complianceRepo, fileStorage)
getProgressUC := compliance.NewGetComplianceProgressUseCase(complianceRepo)
getGapAnalysisUC := compliance.NewGetGapAnalysisUseCase(complianceRepo)
controlMappingRepo := repository.NewGormControlMappingRepository(database.DB)
createMappingUC := compliance.NewCreateControlMappingUseCase(controlMappingRepo, complianceRepo)
listMappingsUC := compliance.NewListControlMappingsUseCase(controlMappingRepo, complianceRepo)
deleteMappingUC := compliance.NewDeleteControlMappingUseCase(controlMappingRepo)
listCatalogsUC := compliance.NewListCatalogsUseCase()
importCatalogUC := compliance.NewImportCatalogUseCase(complianceRepo)
// M4 — official compliance report (PDF). Reuses userRepo/orgRepo (declared
Expand All @@ -653,6 +666,8 @@ func main() {
createControlUC, getControlUC, listControlsUC, updateControlUC, deleteControlUC,
createEvidenceUC, listEvidencesUC, deleteEvidenceUC, downloadEvidenceUC,
getProgressUC, listCatalogsUC, importCatalogUC, generateReportUC,
getGapAnalysisUC,
createMappingUC, listMappingsUC, deleteMappingUC,
)

// NOTE: these routes sit under `protected`, whose base middleware (middleware.Protected,
Expand Down Expand Up @@ -685,6 +700,14 @@ func main() {
protected.Get("/compliance/frameworks/:frameworkId", complianceFrameworkRead, complianceHandler.GetFramework)
protected.Delete("/compliance/frameworks/:frameworkId", complianceFrameworkDelete, complianceHandler.DeleteFramework)
protected.Get("/compliance/frameworks/:frameworkId/progress", complianceControlRead, complianceHandler.GetProgress)
// Gap analysis ("analyse d'écarts") — every unsatisfied control across the
// tenant's frameworks (optional ?framework_id= scopes to one).
protected.Get("/compliance/gap-analysis", complianceControlRead, complianceHandler.GetGapAnalysis)
// Cross-framework control mappings ("cross-mapping entre référentiels"). Static
// path — no :param collision with /compliance/controls/:controlId.
protected.Get("/compliance/control-mappings", complianceControlRead, complianceHandler.ListControlMappings)
protected.Post("/compliance/control-mappings", complianceControlUpdate, complianceHandler.CreateControlMapping)
protected.Delete("/compliance/control-mappings/:mappingId", complianceControlUpdate, complianceHandler.DeleteControlMapping)
// Official compliance report (PDF, 1-click) — reads a tenant's controls/evidence, same tier as reading them.
protected.Get("/compliance/frameworks/:frameworkId/report", complianceControlRead, complianceHandler.GenerateReport)
protected.Get("/compliance/frameworks/:frameworkId/controls", complianceControlRead, complianceHandler.ListControls)
Expand All @@ -697,6 +720,44 @@ func main() {
protected.Get("/compliance/evidences/:evidenceId/download", complianceEvidenceRead, complianceHandler.DownloadEvidence)
protected.Delete("/compliance/evidences/:evidenceId", complianceEvidenceDelete, complianceHandler.DeleteEvidence)

// -------------------------------------------------------------------------
// Compliance audits ("Audits") + remediation plans ("Plans de remédiation").
// One Gorm repo backs both aggregates. New permission strings — admin/root
// hold "*" so they're granted; a future Profile rule can open them per-role.
// -------------------------------------------------------------------------
complianceAuditRepo := repository.NewGormComplianceAuditRepository(database.DB)
complianceAuditHandler := handlers.NewComplianceAuditHandler(
complianceaudit.NewCreateAuditUseCase(complianceAuditRepo),
complianceaudit.NewListAuditsUseCase(complianceAuditRepo),
complianceaudit.NewGetAuditUseCase(complianceAuditRepo),
complianceaudit.NewUpdateAuditUseCase(complianceAuditRepo),
complianceaudit.NewDeleteAuditUseCase(complianceAuditRepo),
complianceaudit.NewCreateRemediationUseCase(complianceAuditRepo, complianceRepo),
complianceaudit.NewListRemediationsUseCase(complianceAuditRepo, complianceRepo),
complianceaudit.NewUpdateRemediationUseCase(complianceAuditRepo),
complianceaudit.NewDeleteRemediationUseCase(complianceAuditRepo),
complianceaudit.NewGenerateRemediationsFromAuditUseCase(complianceAuditRepo, complianceAuditRepo, complianceRepo),
)
complianceAuditRead := middleware.RequirePermission("compliance:audits:read")
complianceAuditWrite := middleware.RequirePermission("compliance:audits:write")
complianceRemediationRead := middleware.RequirePermission("compliance:remediations:read")
complianceRemediationWrite := middleware.RequirePermission("compliance:remediations:write")

// Static paths — registered as siblings of /compliance/frameworks etc.; no
// dynamic :segment under /compliance would greedily catch "audits"/"remediations".
protected.Get("/compliance/audits", complianceAuditRead, complianceAuditHandler.ListAudits)
protected.Post("/compliance/audits", complianceAuditWrite, complianceAuditHandler.CreateAudit)
protected.Get("/compliance/audits/:id", complianceAuditRead, complianceAuditHandler.GetAudit)
protected.Patch("/compliance/audits/:id", complianceAuditWrite, complianceAuditHandler.UpdateAudit)
protected.Delete("/compliance/audits/:id", complianceAuditWrite, complianceAuditHandler.DeleteAudit)
// One-click: open a remediation plan for every open gap under the audit's framework.
protected.Post("/compliance/audits/:id/generate-remediations", complianceRemediationWrite, complianceAuditHandler.GenerateRemediations)

protected.Get("/compliance/remediations", complianceRemediationRead, complianceAuditHandler.ListRemediations)
protected.Post("/compliance/remediations", complianceRemediationWrite, complianceAuditHandler.CreateRemediation)
protected.Patch("/compliance/remediations/:id", complianceRemediationWrite, complianceAuditHandler.UpdateRemediation)
protected.Delete("/compliance/remediations/:id", complianceRemediationWrite, complianceAuditHandler.DeleteRemediation)

// =========================================================================
// Board Report (M4, second half — see ROADMAP.md §3 M4).
// Monthly, non-technical board-of-directors report: aggregates the tenant's
Expand Down
Loading
Loading