Accueil › Notes de version › Release 2026-05-26 — Requêteur IA, cession Kankele 3-parties, anonymisation marketplace + analyse IA enrichie
Menu du document← Accueil
Notes de version
  1. Release 2026-09-24 — Salle de marché institutionnelle (Lots 0-8)
  2. Release 2026-06-02 — Audit liens morts backoffice + rate limit LLM + Aïssa support persona
  3. Release 2026-05-26 — Requêteur IA, cession Kankele 3-parties, anonymisation marketplace + analyse IA enrichie
Notes de version

Release 2026-05-26 — Requêteur IA, cession Kankele 3-parties, anonymisation marketplace + analyse IA enrichie

Historique — décrit des surfaces déposées au Lot 1 (2026-09) du programme « salle de marché institutionnelle » (marketplace investisseur, /marketplace.html, endpoints /v2/marketplace/*). Conservé pour mémoire. Voir docs/legal/2026-09-14-fermeture-consultation-investisseur.md et docs/releases/2026-09-24-salle-de-marche-lots-0-8.md.

Status : en production. tauraco.io, tauraco.ai, api.tauraco.io tous synchronisés.

TL;DR (5 secondes)

NouveautéSurface utilisateurDisponibilité
Requêteur IA en langage naturel/app/assistantTenants PREMIUM, tous rôles
Cession Kankele 3-partiesSeller portal + ERP factures clientsTous tenants
Anonymisation marketplace GLOBALE/marketplace.html + toutes endpoints investisseurTous investisseurs
Analyse IA enrichie par facture (Polymarket-style)Modal "Voir l'analyse" sur chaque opportunitéTous
Mapping NAF → secteurAutomatique au publish de listingTous
Dark mode charbon premiumToggle existantTous
SPA fallback /app/*Tous deep-links Vue RouterTous

Détail des PRs livrées

PR #38 — style(theme): refonte dark mode — charbon premium neutre

Bascule du fond bleu nuit saturé #0A1A2F vers un charbon neutre #0D1014 (façon Mercury / Brex / JPM Private Bank). Accent turquoise tempéré, success sage, danger terracotta, borders 10% → 6% blanc. Aucune modif fonctionnelle.

PR #39 — feat(cession): Kankele signature 3-parties sur chaque entrée marketplace

Toute soumission au marketplace (seller portal + ERP factures clients) ouvre désormais une enveloppe Kankele à 3 signataires :

  • Fournisseur (le cédant qui soumet la facture)
  • Payeur (le débiteur cédé — l'utilisateur saisit son email + titre + commentaire)
  • Tauraco (mandataire de l'investisseur ; l'investisseur réel signera plus tard via avenant à l'allocation)

La facture reste cachée du marketplace public jusqu'à signature complète des 3 parties. Deux contrats générés : factoring_assignment_agreement + buyer_notification_cession (nouveau template).

Files :

  • backend : services/cession_service.py, domains/contracts/templates/buyer_notification_cession_fr.md
  • frontend : SellerInvoicesView.vue (dialogue cession enrichi), ErpSalesInvoiceDetailView.vue (bloc signature dans le dialogue financement)

PR #40 — feat(requeteur): read-only conversational data access (premium)

Nouvelle surface POST /v2/ai/requeteur (page UI /app/assistant) qui permet aux dirigeants non-comptables de PME d'interroger leurs propres données en langage naturel (FR + EN).

Trois catalogues d'outils strictement séparés, le LLM ne génère aucune SQL :

Access typeCouvertureOutils
ACCESS_ERP_PLUS_FINERP + financement12 (ventes, clients impayés, achats, trésorerie, financements…)
ACCESS_FIN_ONLYFinancement seul5 (statut factures, coût, décaissements)
ACCESS_INVESTORInvestisseur8 (positions, rendement, opportunités anonymisées, exposition)

Couches de défense indépendantes :

  1. Catalogue par isolation d'import (les autres catalogues pas en mémoire)
  2. Schémas Pydantic extra="forbid" + liste noire {tenant_id, user_id, …} rejetée au dispatch
  3. Rôle Postgres dédié tauraco_requeteur : SELECT-only sur allow-list, default_transaction_read_only=on, statement_timeout=5s
  4. Output filter : tout batch est droppé si une ligne sort du scope (audit REQUETEUR_ISOLATION_BREACH)
  5. Audit log par appel via AuditLogService existant (visible dans /ops/audit-logs)
  6. SUPER_ADMIN / ADMIN refusés au endpoint (403)
  7. Paywall : subscription_tier == PREMIUM requis (env-overridable)

Setup ops :

  • REQUETEUR_RO_PASSWORD + DATABASE_RO_URL dans /opt/tauraco/.env
  • Migrations Alembic 030 + 031 (rôle + GRANTs)

PR #41 — feat(requeteur): NAF division → coarse sector mapping

12 secteurs coarse, mapping NAF Rev. 2 (88 divisions INSEE), labels FR+EN. Le marketplace_service.publish_invoice() lit Tenant.naf_code et écrit naf_code + sector dans la factsheet à la création du listing.

PR #42 — chore(scripts): seed naf_code on tenants from a name heuristic

Utilitaire idempotent backend/scripts/seed_tenant_naf_codes.py avec --dry-run et --refresh-listings. À lancer manuellement après chaque cohorte d'inscriptions seller. Jamais déclenché par l'agent.

PR #43 — docs+sec(requeteur): NAF invariant + k-anonymity & amount bucketing

Renforce l'anonymisation contre la ré-identification par corrélation (défaut détecté lors des tests réalistes du Volet 2) :

  • k-anonymity floor : apply_k_anonymity_on_sector(k_min=3) — un secteur apparaissant moins de 3 fois dans le résultat est collapsé en OTHER. Empêche "il n'y a qu'un seul AGRI → c'est forcément X".
  • Amount bucketing : bucket_amount() arrondit par paliers (500 / 1k / 5k / 10k selon ordre de grandeur). "18 750 EUR" devient "19 000 EUR".
  • Duration bucketing : ceil semaine (≤90j) ou mois (>90j).

Documentation : invariante NAF dans CLAUDE.md, procédure manuelle de seed dans docs/runbook.md.

PR #45 — feat(marketplace): anonymisation globale + analyse IA enrichie par facture

Constat utilisateur sur la prod : https://tauraco.io/marketplace.html montrait toujours supplier_name (le requêteur PR #40 anonymisait sa propre surface uniquement) ; et aucune analyse marché/risque pour aider l'investisseur non-expert à décider.

Volet anonymisation globale :

  • Nouveau services/listing_anonymizer.project_for_investor(), un seul code path, appliqué à /v2/marketplace/public/listings, /listings, /listings/{id} et /v3/portal/investor/investments.
  • Champs systématiquement strippés : supplier_name, buyer_name, tenant_id, invoice_number, siren/siret, extracted_data.
  • Remplacés par supplier_label = "Entreprise vérifiée — \<Secteur\>", amount_ttc bucketé (réutilise bucket_amount de PR #43), duration_days bucketé.
  • Seller portal inchangé (c'est leur propre donnée). project_for_admin() reste disponible pour ops, jamais montée sur une route publique.

Volet analyse IA Polymarket-style :

  • services/investor_brief_service.generate_brief() : appel Claude Sonnet 4.6 par listing, 4 paragraphes structurés (opportunity / market_context / risks / why_we_finance) plus un bloc expert repliable (risk_flags, score_numeric, P(paiement), …).
  • Sécurité critique : la factsheet est *redacted* avant l'appel — Claude ne reçoit JAMAIS supplier_name. Même jailbroken, il ne peut pas echo l'identité.
  • Pydantic schema, hash-idempotent ({grade, amount, sector, flags}), failure-safe (Claude down → publish OK, brief généré au prochain backfill).

UI :

  • Static marketplace.html : modal "Voir l'analyse complète" avec KPIs + 4 sections + <details> mode expert. 100% createElement + textContent (XSS-safe).
  • Vue MarketplaceListingsView.vue : section "Analyse Tauraco" dans le detail panel, mêmes 4 sections + mode expert + disclaimer réglementaire.

Backfill exécuté : 10/10 briefs générés sur les listings les plus récentes (script backend/scripts/backfill_investor_briefs.py --limit 10, ~$0.13).

Audit déploiement

SurfaceAvantAprès
Backend api.tauraco.iocode obsolète + workers depuis 3 semainesCode main 20c9468 + workers fraîchement restartés, 451 routes, migrations 031 (head)
Frontend tauraco.io/app/bundle obsolètebundle frais index-DSHZ_20b.js
SPA fallbackabsent (404 sur /app/login etc.).htaccess shipped via Vite public/
tauraco.ai (Next.js)déjà à jour (8j)inchangé

Tests E2E exécutés en prod

DomaineVérifRésultat
tauraco.io9 deep-links (login, assistant, marketplace, seller, erp, investor, pipeline)9/9 → 200
tauraco.ai4 pages marketing (home, market, investors, insights)4/4 → 200
api.tauraco.io4 endpoints publics + 4 endpoints d'auj (cession, requeteur, kankele)tous OK (200 ou 401 = auth requise)
RequeteurInvestor PREMIUM, FR+EN, 6 prompts adversariaux0 leak, 0 REQUETEUR_ISOLATION_BREACH
Marketplace anonymisation50 listings inspectés via curl0 fuite supplier_name/buyer_name/tenant_id
Briefs IABackfill prod 10 listings10/10 générés (après cap Pydantic relevé à 1500 chars + retry)

Setup à compléter par l'opérateur (post-merge)

  1. NAF seed sur les nouveaux SELLER tenants : docker compose exec backend python -m scripts.seed_tenant_naf_codes --dry-run puis sans --dry-run si OK.
  2. Kankele production : config par défaut en DEV_MODE=True (mock). Pour brancher la prod, voir docs/kankele_setup.md.
  3. Premium tier : pour ouvrir le requêteur à un tenant, soit via le flow MoMo upgrade, soit UPDATE tenants SET subscription_tier='PREMIUM' WHERE id='…'.
  4. Briefs IA — élargir le backfill au-delà des 10 plus récentes si besoin : docker compose exec backend python -m scripts.backfill_investor_briefs --limit 50 (~$0.65).
  5. Revue humaine des 10 premiers briefs en prod — vérifier le ton (factuel, pas de promesse de rendement) et la conformité réglementaire.

Statistiques de la journée

PRInsertionsDeletions
#384943
#39452127
#403 2022
#4137834
#421490
#435146
#441330
#451 15739
Total6 034251

107 tests unitaires verts au total :

  • 93 tests requêteur (pytest tests/requeteur/) — couvre catalogues, isolation, k-anonymity, NAF, anonymisation
  • 14 nouveaux tests marketplace (pytest tests/marketplace/) — anonymizer partagé + générateur de briefs (redaction LLM input, idempotence, failure-safe)