Studio interne2026·v1.1.1 prod·Architecture full-stack

Un génie d’Aladdin pour restaurateur BD non-tech.

Application desktop Electron + FastAPI pour scoring d’éditions rares de bande dessinée. Deux moteurs : RADAR scrape les marketplaces et alerte sous-cote BDM, CANON identifie les éditions par photo via Claude Haiku Vision et génère description et suggestion prix.

  • 228tests pytest verts /228
  • 64éditions whitelist stricte
  • 0,44 €vision IA · 233 photos
  • 110 MBinstalleur win+mac
Contexte

Le problème : un marché opaque, un client non-tech, un cap de coût IA.

Restaurateur BD Tintin basé en France, 134 éditions client BDM 2023-2024 dans son inventaire (valeur estimée ~71 950 €), zero compétence terminal. Le brief : un outil unique qui détecte les sous-cotes BDM sur Leboncoin, eBay, Facebook, Catawiki et Delcampe, et qui sait reconnaître une édition à partir d’une photo abîmée.

Deux contraintes dures. Un : aucun POST automatisé sur les marketplaces (TOS-safe, drafts + ouverture navigateur). Deux : un cap absolu sur la facture Claude — 3 € par campagne CANON, pas un centime de plus. Le reste — architecture, scoring, packaging — devait tenir dans une app desktop qui se lance par double-clic.

Architecture

Trois couches, une décision par couche.

Le pipeline RADAR + CANON tient sur trois layers, chacun avec son trade-off coût/précision.

  1. L1

    Extracteurs regex par éditeur

    tintin.py, asterix_dargaud.py, quick_flupke.py, jo_zette.py — un module dédié par série. Regex strictes par éditeur, lecture des mentions Casterman/Dargaud/Hachette en clair sur la description. Coût ≈ 0 €, faux positifs ≈ 0 sur les éditions standards.

  2. L2

    Claude AI override sur éditions masquées

    Quand le scraper layer 1 ne tranche pas (annonce floue, photo seulement, vendeur qui ment), bascule vers Claude Haiku avec prompt caching. Coût ramené à ~1/10 vs cold call. Cap dur 0,05 € par deal — au-delà, le deal est marqué incertain.

  3. L3

    Confidence gating UI

    Chaque deal sort avec un score 0-1. ≥0.6 → carte verte, achat suggéré. 0.3-0.6 → carte orange, scoring multiplié par 0,5 (prudence). <0.3 → cap 50 € + badge « ? » rouge dashed, aucune valeur affichée. L’utilisateur final voit la couleur, pas le chiffre.

Stack

Choisi pour un livrable double-clic, pas pour un README.

01

Runtime

  • Electron 32
  • electron-vite
  • Node 20
02

Frontend

  • React 18
  • TypeScript 5
  • Tailwind 3.4
  • Zustand 4
03

Backend

  • Python 3.11
  • FastAPI
  • SQLAlchemy
  • SQLite
  • Playwright
04

IA

  • Anthropic SDK
  • Claude Haiku 4.5
  • Vision
  • prompt caching
Décisions clés

Quatre règles d’or, gravées dans le repo.

  1. 01

    Mode hybride sûr TOS

    Aucun POST automatisé sur les marketplaces. Le scraper lit, génère un draft, ouvre le navigateur sur la page produit. L’humain valide et publie. Zero risque de ban Leboncoin/eBay/Facebook.

  2. 02

    AI Edition Override avec prompt caching

    Le prompt système (whitelist 64 éditions, format de sortie, garde-fous) est cached côté Anthropic. Coût ramené à ~1/10 d’un cold call. Cap dur 0,05 € par deal vérifié côté serveur, jamais côté UI.

  3. 03

    Sanitize centralisé

    BaseScraper._process_listing est l’unique point qui sanitize une annonce avant scoring. Modif sécurité = 1 patch, jamais 5. Audit avril 2026 a validé l’approche : zero injection prompt en EN+FR.

  4. 04

    Un seul point de vérité CSP Electron

    CSP injecté via session.webRequest.onHeadersReceived. Jamais en <meta>. Jamais double. Mode dev et mode prod partagent le même header — un seul fichier à patcher quand une nouvelle origine doit passer.

Métriques

Ce qui s’est mesuré, pas ce qui se raconte.

0 / 228
Tests pytest verts
174 scoring + 41 sécu + 13 wiring
0
Photos analysées · campagne J2
vision IA Claude Haiku 4.5
0,44 €
Coût total campagne
cap 3 € · 14,8 % utilisé
0,0019 €
Coût moyen par image
prompt caching ~1/10
0
Éditions inventaire client
~71 950 € valeur BDM 2023-2024
0 MB
Installeur v1.1.1
win + mac validés
0 / 21
Playwright baseline green
5 scrapers couverts
Code

AI Edition Override · prompt caching

src/backend/services/edition_override.py — coût ramené à ~1/10 d’un cold call.

python
from anthropic import Anthropic
from .cap import deal_cap  # 0.05  par deal

client = Anthropic()

SYSTEM_PROMPT = load_whitelist_prompt()  # 64 éditions strictes

def override_edition(listing: Listing) -> Verdict:
    if deal_cap.exceeded(listing.id):
        return Verdict.unknown(reason="cap_reached")

    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=256,
        system=[{
            "type": "text",
            "text": SYSTEM_PROMPT,
            "cache_control": {"type": "ephemeral"},
        }],
        messages=[{"role": "user", "content": listing.to_prompt()}],
    )
    deal_cap.charge(listing.id, response.usage)
    return parse_verdict(response.content[0].text)
Lessons / Next

Ce que ce projet a gravé.

  1. Un seul point de vérité CSP Electron — meta + header = double règle = bug fantôme garanti.
  2. Mode dev ≠ mode prod CSP. Tester les deux dès le premier sprint sécurité, pas après packaging.
  3. Sanitize centralisé > sanitize par scraper. Cinq scrapers = cinq oublis possibles, un BaseScraper = un seul patch.
  4. PyInstaller works on my machine = keyring absent CI. Toujours tester le binaire emballé sur une VM vierge, pas le venv local.
  5. Prompt caching Anthropic n’est pas magique : sans cap dur côté serveur, une boucle bouffe 3 € en 4 minutes.