ArchitecturePanel Ingest Contract : BoostEcom Spy ↔ BoostEcom Intelligence

Panel Ingest Contract : BoostEcom Spy ↔ BoostEcom Intelligence

Spec d'intégration entre l'extension Chrome BoostEcom Spy (worktree Extensions/@BoostEcom) et le pipeline d'intelligence BoostEcom. Phase 1 livrée 2026-05-22 sur branche claude/elegant-sagan-TRd77. Contrat voisin, autre…

Spec d'intégration entre l'extension Chrome BoostEcom Spy (worktree Extensions/@BoostEcom) et le pipeline d'intelligence BoostEcom. Phase 1 livrée 2026-05-22 sur branche claude/elegant-sagan-TRd77. Contrat voisin, autre sujet : extension-presence-contract.md — comment l'extension s'annonce à la page (badge de la home). Ce qui est caché au navigateur, ce qui ne peut pas l'être et ce que les tests garantissent : code-protection.md.

Pourquoi

Pour rivaliser avec SimilarWeb / Datos sur le long terme, BoostEcom construit son propre panel de trafic. BoostEcom Spy collecte les événements de navigation côté utilisateur (avec consent) et les pousse en batch HMAC-signé vers BoostEcom. Le pipeline d'intelligence les agrège dans IntelligencePanelEvent puis rolle dans les signaux TrafficSection du record canonique.

Endpoint

POST https://www.boostecom.app/api/intelligence/panel/ingest
Content-Type: application/json
X-BoostEcom-Signature: <hex HMAC-SHA256 of body, key = INGEST_SECRET>

Body (JSON)

{
  events: [
    {
      user_id_hash: string,   // 32-128 chars — SHA-256 du device id
      primary_domain: string, // 3-255 chars — lowercased
      visited_at: string,     // ISO 8601 datetime
      referer?: string,       // optional, max 2048 chars
      country?: string        // optional, ISO-2
    },
    ...
  ]  // 1..500 events per batch
}

Réponse

{
  stored: number,  // events accepted
  dropped: number, // malformed / persistence failed
  total: number
}

Sécurité

  • Session BoostEcom obligatoire (withSessionAuth). Plus de secret partagé : l'extension est du code public, tout secret qu'elle embarque est lisible par n'importe qui (le .crx du Chrome Web Store est un ZIP).
  • Pseudonyme dérivé côté serveur : HMAC(INTELLIGENCE_ANON_SECRET, "panel:" + userId). Le client n'envoie plus user_id_hash (champ refusé).
  • Origin : l'app ou chrome-extension://<EXTENSION_ID> publié. C'est la protection CSRF, pas l'authentification.
  • Bornes : 30 batchs/min par utilisateur, 100 événements par batch, 64 Ko, visited_at dans les 7 derniers jours, une visite par (panéliste, domaine, heure UTC), 1 000 événements par panéliste sur 24 h, referer réduit à son origine.
  • Contrat du body : { events: [{ primary_domain, visited_at, referer?, country? }] }.
  • Tests : src/app/api/intelligence/panel/ingest/route.test.ts.
  • INTELLIGENCE_PANEL_INGEST_SECRET est supprimé du schéma env : le retirer de Vercel.

Côté BoostEcom Spy

Le code d'envoi vit dans le worktree Extensions/@BoostEcom. Pattern recommandé :

  1. Buffer local des événements de navigation (30s ou 100 events, whichever first).
  2. Calcul HMAC sur le body sérialisé.
  3. POST avec header signature.
  4. Drop le buffer si réponse OK ; retry x3 avec backoff exponentiel si réseau.
  5. Skip silencieux si l'utilisateur a opt-out (drapeau local).

Storage

Persisté dans IntelligencePanelEvent (Prisma model) avec partitionKey = "YYYY-MM" pour qu'on puisse déclarer des partitions natives Postgres plus tard sans reshape des données.

Agrégation (cron à venir)

Phase 2 : un cron quotidien panel-rollup agrégera les events des 24 dernières heures par primary_domain et alimentera traffic.monthly_visits (proportion du panel × population estimée), traffic.top_country (mode des country), traffic.top_source (catégorisation des referer).

Phase 1 livre uniquement l'ingestion + le storage, la rollup arrive quand le panel a assez de volume pour produire des signaux non bruités (~10K MAU d'extension installée).