Skip to content

Catalogue d'événements push — Plugins

Liste exhaustive des events que les plugins poussent vers StormeoOS, organisés par type.

Pour les webhooks émis par StormeoOS vers les souscripteurs externes (clients API), voir ../webhooks/public-api-webhooks.md.

Format d'un event

Tous les events suivent la structure :

json
{
  "type": "<event_type>",
  "siteUrl": "https://acme.fr",
  "platform": "wordpress",     // ou "prestashop"
  "occurredAt": "2026-04-27T10:00:00.000Z",
  "data": { ... }              // payload spécifique au type
}

Envoyés via POST /api/plugin/v2/security-event ou POST /api/plugin/sync-content selon la nature.

Headers requis : X-Stormeo-API-Key, X-Stormeo-Signature, X-Stormeo-Timestamp (HMAC obligatoire >= seuils).

Events de contenu

content.post.saved

Émis sur save_post WP / actionObjectCMSPageAddAfter PS.

json
{
  "type": "content.post.saved",
  "data": {
    "postId": 42,
    "postType": "post",
    "title": "Nouveau billet",
    "status": "publish",
    "modifiedBy": 1,
    "permalink": "https://acme.fr/blog/nouveau-billet"
  }
}

content.post.deleted

Émis sur delete_post WP.

json
{
  "type": "content.post.deleted",
  "data": { "postId": 42, "postType": "post" }
}

content.media.added

Émis sur attachment_added WP / upload PS.

json
{
  "type": "content.media.added",
  "data": {
    "attachmentId": 123,
    "filename": "photo.jpg",
    "mime": "image/jpeg",
    "sizeBytes": 245760
  }
}

content.comment.posted

Émis sur comment_post WP.

json
{
  "type": "content.comment.posted",
  "data": {
    "commentId": 99,
    "postId": 42,
    "approved": false,
    "ipAddress": "1.2.3.4",
    "userAgent": "..."
  }
}

Les emails commenters sont hashés SHA-256 avant push (RGPD).

Events e-commerce (WooCommerce / PrestaShop)

wc.order.created / ps.order.created

json
{
  "type": "wc.order.created",
  "data": {
    "orderId": 1042,
    "orderNumber": "WC-1042",
    "total": "129.00",
    "currency": "EUR",
    "status": "pending",
    "customerEmailHash": "sha256:..."
  }
}

wc.order.status_changed

json
{
  "type": "wc.order.status_changed",
  "data": {
    "orderId": 1042,
    "fromStatus": "pending",
    "toStatus": "processing"
  }
}

wc.product.stock_changed

json
{
  "type": "wc.product.stock_changed",
  "data": {
    "productId": 88,
    "sku": "ACME-001",
    "previousStock": 12,
    "newStock": 11
  }
}

wc.product.created / wc.product.updated

json
{
  "type": "wc.product.updated",
  "data": {
    "productId": 88,
    "name": "T-shirt logo",
    "price": "29.00",
    "status": "publish"
  }
}

Events de sécurité

security.login.failed

Émis sur wp_login_failed WP / hook back-office PS.

json
{
  "type": "security.login.failed",
  "data": {
    "userLogin": "admin",
    "ipAddress": "1.2.3.4",
    "userAgent": "...",
    "reason": "incorrect_password"
  }
}

security.login.success

json
{
  "type": "security.login.success",
  "data": {
    "userId": 1,
    "userLogin": "admin",
    "ipAddress": "1.2.3.4"
  }
}

security.user.created / security.user.role_changed

json
{
  "type": "security.user.role_changed",
  "data": {
    "userId": 5,
    "fromRole": "subscriber",
    "toRole": "administrator",
    "changedBy": 1
  }
}

security.file.modified

Émis quand un fichier core change de hash (différent du baseline).

json
{
  "type": "security.file.modified",
  "data": {
    "path": "wp-includes/class-wp.php",
    "previousHash": "sha256:abc...",
    "currentHash": "sha256:def...",
    "lastSeenAt": "2026-04-27T09:00:00.000Z"
  }
}

security.brute_force.detected

Émis si > 5 login_failed sur une IP en < 1 min (logique côté plugin).

json
{
  "type": "security.brute_force.detected",
  "data": {
    "ipAddress": "1.2.3.4",
    "attemptCount": 7,
    "windowSec": 60
  }
}

Events métriques (push périodique cron)

metrics.disk_usage (/api/plugin/v2/disk-usage)

json
{
  "type": "metrics.disk_usage",
  "data": {
    "uploadsBytes": 524288000,
    "dbDumpBytes": 104857600,
    "totalBytes": 1073741824,
    "freeBytes": 5368709120
  }
}

metrics.file_integrity (/api/plugin/v2/file-integrity)

json
{
  "type": "metrics.file_integrity",
  "data": {
    "scannedFiles": 1842,
    "modifiedFiles": 3,
    "modifiedList": [
      { "path": "wp-config.php", "hash": "sha256:..." }
    ]
  }
}

metrics.time_credit (/api/plugin/v2/time-credit)

Tracking des temps consommés par les commandes asynchrones (utile pour facturation).

json
{
  "type": "metrics.time_credit",
  "data": {
    "commandId": 123,
    "type": "wp.update_plugin",
    "durationMs": 4200
  }
}

Events GDPR

gdpr.user.deletion_requested

Émis quand le mécanisme RGPD natif du CMS est déclenché.

json
{
  "type": "gdpr.user.deletion_requested",
  "data": {
    "userId": 42,
    "emailHash": "sha256:...",
    "anonymizedFields": ["firstname", "lastname", "email", "phone"]
  }
}

Comportement côté StormeoOS

À réception, les events sont :

  1. Loggés dans stormeo_sync_logs (audit)
  2. Re-broadcast aux souscripteurs webhook public-api de l'agence si l'event mappe à un event public-api (rare, via mapping interne)
  3. Affichés dans l'UI agence (SitePilot → Site → Live Feed)
  4. Agrégés pour les dashboards (charts contenu, sécurité, etc.)

Idempotence et dédup

Le plugin doit envoyer un eventUuid (UUID v4) dans chaque event pour permettre la dédup côté serveur (en cas de retry réseau) :

json
{
  "eventUuid": "550e8400-e29b-41d4-a716-446655440000",
  "type": "content.post.saved",
  "data": { ... }
}

Le serveur stocke les eventUuid reçus et ignore les doublons sur 24h.

Retry policy côté plugin

Si l'event fail (timeout, 5xx, signature rejetée) :

  • Stocker dans une queue locale (option WP stormeo_pending_events / table PS ps_stormeo_pending_events)
  • Retry exponential backoff : 1min, 5min, 30min, 2h, 12h
  • Abandon après 5 tentatives → log local + alerte UI plugin

Pour les events critiques (security.*), recommandé de NE PAS abandonner — accumuler en queue jusqu'à reconnect.

StormeoOS API