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.