veylant/internal/compliance/types.go
2026-02-23 13:35:04 +01:00

102 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package compliance implements the GDPR Article 30 processing registry,
// EU AI Act risk classification, PDF report generation, and GDPR rights APIs.
package compliance
import (
"errors"
"time"
)
// ErrNotFound is returned when a processing entry is not found.
var ErrNotFound = errors.New("compliance entry not found")
// ProcessingEntry represents one record in the GDPR Article 30 processing registry.
type ProcessingEntry struct {
ID string `json:"id"`
TenantID string `json:"tenant_id"`
UseCaseName string `json:"use_case_name"`
LegalBasis string `json:"legal_basis"`
Purpose string `json:"purpose"`
DataCategories []string `json:"data_categories"`
Recipients []string `json:"recipients"`
Processors []string `json:"processors"`
RetentionPeriod string `json:"retention_period"`
SecurityMeasures string `json:"security_measures"`
ControllerName string `json:"controller_name"`
// AI Act fields (E9-02)
RiskLevel string `json:"risk_level"` // minimal|limited|high|forbidden|""
AiActAnswers map[string]bool `json:"ai_act_answers,omitempty"` // q1..q5
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// ErasureRecord is an immutable audit record for GDPR Art. 17 erasure requests.
type ErasureRecord struct {
ID string `json:"erasure_id"`
TenantID string `json:"tenant_id"`
TargetUser string `json:"user_id"`
RequestedBy string `json:"requested_by"`
Reason string `json:"reason"`
RecordsDeleted int `json:"records_deleted"`
Status string `json:"status"`
CreatedAt time.Time `json:"timestamp"`
}
// LegalBasisLabels maps legal_basis values to human-readable French labels.
var LegalBasisLabels = map[string]string{
"consent": "Consentement (Art. 6.1.a)",
"contract": "Exécution d'un contrat (Art. 6.1.b)",
"legal_obligation": "Obligation légale (Art. 6.1.c)",
"vital_interests": "Intérêts vitaux (Art. 6.1.d)",
"public_task": "Mission d'intérêt public (Art. 6.1.e)",
"legitimate_interest": "Intérêt légitime (Art. 6.1.f)",
}
// RiskLabels maps risk_level values to human-readable labels.
var RiskLabels = map[string]string{
"minimal": "Risque minimal",
"limited": "Risque limité",
"high": "Haut risque",
"forbidden": "Interdit",
}
// AiActQuestions defines the 5 EU AI Act classification questions.
// Keys q1..q5 correspond to the ai_act_answers JSONB field.
var AiActQuestions = []struct {
Key string
Label string
}{
{"q1", "Le système prend-il des décisions autonomes affectant des droits légaux ou des situations similaires des personnes ?"},
{"q2", "Implique-t-il une identification biométrique ou une reconnaissance des émotions ?"},
{"q3", "Est-il utilisé dans des décisions critiques (médical, justice, emploi, crédit) ?"},
{"q4", "Traite-t-il des catégories spéciales de données (santé, biométrie, origine raciale) ?"},
{"q5", "La transparence sur l'utilisation de l'IA est-elle indispensable au consentement éclairé ?"},
}
// ScoreRisk computes the EU AI Act risk level from questionnaire answers.
//
// Scoring rules:
// - 0 "yes" → minimal
// - 12 "yes" → limited
// - 34 "yes" → high
// - 5 "yes" → forbidden
func ScoreRisk(answers map[string]bool) string {
yes := 0
for _, v := range answers {
if v {
yes++
}
}
switch {
case yes == 5:
return "forbidden"
case yes >= 3:
return "high"
case yes >= 1:
return "limited"
default:
return "minimal"
}
}