Aller au contenu principal

Validation humaine

Principe

Toute action marquée requires_approval = true déclenche un workflow en deux temps.

Flux

IA demande une action


ThaliaValidationService::request()

├── Crée enregistrement thalia_pending_actions (status: pending)
├── Envoie alerte interne aux approbateurs (AlertService)
└── Retourne réponse 202 à l'IA :
{
"status": "pending_approval",
"token": "abc123xyz",
"expires_in": 300,
"poll_url": "/api/v2/thalia/actions/abc123xyz"
}

L'IA polle GET /api/v2/thalia/actions/{token}
└── status: pending | approved | rejected | expired

Approbateur humain :
├── Accède à /thalia/admin/pending
├── Voit le détail de l'action
└── Clique Approuver ou Rejeter
├── approved → action exécutée
├── rejected → message de refus renvoyé à l'IA
└── expired → TTL dépassé, action annulée

ThaliaValidationService

// Créer une demande
$action = $validation->request(
tool: 'infrastructure.vms.action',
params: ['vm_id' => 42, 'action' => 'stop'],
description: "L'IA souhaite arrêter la VM prd-db-01",
ttlSeconds: 300,
);

// Approuver
$validation->approve($action, approvedBy: $user);

// Rejeter
$validation->reject($action, reason: "VM de production, arrêt non autorisé");

// Vérifier le statut (polling)
$validation->status($token);
// → pending | approved | rejected | expired

Table thalia_pending_actions

CREATE TABLE thalia_pending_actions (
id BIGSERIAL PRIMARY KEY,
token VARCHAR(64) UNIQUE NOT NULL,
tool VARCHAR(100) NOT NULL,
params JSONB NOT NULL,
description TEXT NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
requested_by VARCHAR(100),
approved_by INTEGER REFERENCES users(id),
rejected_reason TEXT,
result JSONB,
expires_at TIMESTAMP NOT NULL,
approved_at TIMESTAMP,
executed_at TIMESTAMP,
created_at TIMESTAMP,
updated_at TIMESTAMP
);

Interface admin

Page /thalia/admin/pending :

  • Liste des actions en attente avec couleur par urgence
  • Détail complet : outil, paramètres, contexte, heure d'expiration
  • Boutons Approuver / Rejeter avec champ raison
  • Filtres par statut et par outil

Commande d'expiration

# À lancer toutes les minutes via le scheduler
php artisan thalia:expire-pending-actions

Sans cette commande, la table thalia_pending_actions grossit indéfiniment.