Passer au contenu principal
Lorsqu’une règle Firewall renvoie le verdict pending_approval, la passerelle met l’appel d’outil en attente et notifie votre propre système d’approbation hors-bande. Cette notification est un POST HTTP signé — le payload de webhook firewall — et cette page documente sa forme exacte afin que vous puissiez vérifier la signature, router l’événement, et reposter votre décision. C’est le pendant asynchrone du flux d’approbation en console décrit sur la page Firewall. Le chemin console (un relecteur clique approuver/rejeter) ne nécessite aucun webhook. Le webhook sert quand vous voulez qu’une machine — votre propre bot de ticketing, action Slack, ou runtime d’agent — résolve la mise en attente. Les deux chemins sont first-writer-wins, donc vous pouvez les exécuter côte à côte.
Le webhook est un signal de routage best-effort, pas le canal HITL faisant autorité. Le long-poll propre à l’agent sur GET /api/v1/firewall/approvals/:id est le filet de sécurité — si une notification est perdue ou si votre endpoint est brièvement indisponible, l’appel en attente apparaît quand même dans la console et se résout normalement. Le webhook permet simplement à une machine de réagir plus vite qu’un humain ne le ferait.

1. Le payload de webhook firewall en un coup d’œil

OrcaRouter POSTe une enveloppe JSON vers l’URL que vous configurez, signée avec un secret partagé. Voici une livraison complète — en-têtes et corps :
POST /your-approval-endpoint HTTP/1.1
Content-Type: application/json
X-Orca-Event: firewall.approval.pending
X-Orca-Signature: sha256=9f86d0818988...c2c9a3e1b4d7

{
  "event": "firewall.approval.pending",
  "workspace_id": 42,
  "occurred_at": "2026-06-09T12:00:00.123456789Z",
  "data": {
    "approval_id": "665f1a2b3c4d5e6f7a8b9c0d",
    "tool_name": "db.export",
    "request_id": "req_01J9X...",
    "conversation_id": "conv_8f2a...",
    "policy_id": 7,
    "rule_id": 31
  }
}
L’enveloppe est de la même forme qu’OrcaRouter utilise pour chaque événement signé, afin qu’un seul récepteur puisse router de nombreux types d’événements à partir de X-Orca-Event sans parser le corps.

2. Champs de l’enveloppe

Toujours firewall.approval.pending pour une mise en attente d’approbation. Reflété dans l’en-tête X-Orca-Event afin que vous puissiez router avant de parser le corps.
L’id entier de l’espace de travail dont la politique a mis l’appel en attente. Utile quand un seul endpoint reçoit des webhooks de plusieurs espaces de travail.
Horodatage RFC 3339 / UTC (précision nanoseconde) du moment où la passerelle a mis l’approbation en file. Parsable par tout outillage d’événements standard.
Le bloc dont votre callback a besoin pour résoudre le point de contrôle. Champs en §3.

3. Le payload data

Le bloc data porte tout ce qui est nécessaire pour router et résoudre la mise en attente — délibérément aucun argument d’outil. Le webhook est un signal de routage ; le contexte complet de l’appel (outil, args, la règle qui s’est déclenchée) vit dans l’onglet Approvals de la console et le log d’audit, où il est contrôlé par les accès.
ChampTypeSignification
approval_idstringL’id contre lequel vous postez votre décision.
tool_namestringL’outil en attente, par ex. db.export.
request_idstringLa requête de relais qui a déclenché la mise en attente.
conversation_idstringL’id de conversation / session de l’agent.
policy_idintLa politique firewall qui a matché.
rule_idintLa règle qui a renvoyé pending_approval.
Besoin des arguments ou de la clause correspondante pour prendre la décision ? Lisez-les depuis l’onglet Approvals de la console (Developer+), ou faites interroger par votre agent GET /api/v1/firewall/approvals/:id avec son token de passerelle. Le webhook ne transporte intentionnellement jamais d’args sur le réseau.

4. Vérifier la signature

Chaque livraison est signée afin que vous puissiez rejeter les contrefaçons. L’en-tête de signature est :
X-Orca-Signature: sha256=<hex HMAC-SHA256(secret, raw_body)>
secret est le secret de webhook d’approbation que vous fixez sur l’espace de travail et raw_body correspond aux octets exacts du corps de la requête. Calculez le HMAC sur les octets bruts — re-sérialiser le JSON parsé changera les espaces et cassera la comparaison. Vérifiez en temps constant :
import hmac, hashlib

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)
La signature de webhook sortante ne couvre que le corps. Le callback entrant que vous repostez (§6) signe approval_id + un saut de ligne + le corps — une construction différente, à dessein, afin qu’une signature capturée ne puisse pas être rejouée entre approbations. Ne réutilisez pas une seule routine de signature pour les deux directions.

5. Configurer le webhook

L’URL de destination et le secret partagé sont des réglages d’espace de travail — fixez-les une fois dans la console (ou via l’API de réglages ; Developer+). Aucune intervention d’opérateur et rien à déployer.
1

Définir l'URL et le secret

Dans les réglages Firewall, définissez votre endpoint HTTPS comme URL de webhook d’approbation et un secret partagé fort. L’URL doit être https:// — les destinations en clair sont rejetées — et le secret est write-only (il n’est jamais renvoyé à la lecture ; la réponse de réglages indique seulement s’il en existe un).
2

Rédiger une règle pending_approval

Ajoutez une règle Firewall dont le verdict est pending_approval (ou utilisez le preset HITL). Voir Règles du Firewall.
3

Recevoir et vérifier

Votre endpoint reçoit le POST signé au prochain appel mis en attente. Vérifiez la signature (§4), puis résolvez via le callback ou faites-la remonter pour un humain.
Un appel en attente fonctionne encore avec aucun webhook configuré — il apparaît simplement dans la console pour qu’un humain le résolve. Et si vous fixez une URL mais pas de secret, la passerelle saute entièrement le dispatch, parce que l’endpoint de callback n’accepte que des requêtes signées : une notification que vous ne pourriez pas authentifier en retour serait inutile.

6. Le callback : résoudre la mise en attente

Pour approuver ou rejeter par machine, repostez vers :
POST /api/v1/firewall/approvals/:id/callback
avec le même :id que vous avez reçu comme approval_id, signé avec le même secret partagé. Le corps est une décision :
BODY='{"decision":"approved","reason":"ticket OPS-4821 approved by on-call"}'
SIG="sha256=$(printf '%s\n%s' "$APPROVAL_ID" "$BODY" \
  | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"

curl https://api.orcarouter.ai/api/v1/firewall/approvals/$APPROVAL_ID/callback \
  -H "Content-Type: application/json" \
  -H "X-Orca-Signature: $SIG" \
  -d "$BODY"
Champ du corpsRequisValeurs
decisionouiapproved ou rejected
reasonnonNote en texte libre, enregistrée dans le log d’audit.
Une décision approved laisse passer la prochaine tentative de l’agent une fois — l’agent re-soumet l’appel d’origine avec un en-tête à usage unique X-OrcaRouter-Firewall-Approval. Une décision rejected maintient l’appel bloqué.
La résolution est idempotente et first-writer-wins. Si un humain a déjà résolu la mise en attente depuis la console — ou si un callback en double arrive — l’endpoint renvoie 200 avec already_resolved: true et la décision d’origine tient. Sûr à réessayer.

7. États d’approbation

Un appel en attente traverse ces états ; votre callback pilote la transition hors de pending :
ÉtatSignification
pendingEn attente d’une décision (l’état au moment du webhook).
approvedRésolu — l’appel sous contrôle peut procéder une fois.
rejectedRésolu — l’appel sous contrôle reste bloqué.
expiredLa mise en attente a expiré sans décision.

8. Références associées

Firewall — flux HITL

Comment pending_approval met un appel en attente et l’agent re-soumet avec l’en-tête d’approbation à usage unique.

Codes d'erreur

firewall_approval_pending et les autres réponses HTTP du firewall.

Glossaire des verdicts

Chaque verdict firewall, y compris pending_approval.

API Firewall

La référence complète des routes console + passerelle.
Pour savoir comment les mises en attente s’inscrivent dans le modèle de contrôle plus large, voir Modes d’application et Appels d’outils dangereux.