4 Commits

Author SHA1 Message Date
ordinarthur
e38aa224e8 feat(api): commande ocr:validate pour bencher l'OCR sur factures réelles
All checks were successful
Build & Deploy Web / build-and-deploy (push) Successful in 1m35s
Build & Deploy API / build-and-deploy (push) Successful in 2m24s
Outil standalone qui mesure la qualité d'extraction du provider OCR
courant (Mock, Mistral, ou autre futur) sur un set de factures avec
ground truth, séparé de la suite Playwright (qui reste sur OCR mock
pour la rapidité CI).

Pourquoi : permet de valider qu'un changement de provider (Mistral
upgrade, ajout Document AI, custom prompt) maintient la précision sur
les factures réelles avant de l'activer en prod.

Architecture :
  - Lit `e2e/fixtures/invoices/<name>.pdf` (ou .png/.jpg)
  - À côté, `<name>.expected.json` avec la ground truth
  - Pour chaque facture : upload temporaire vers le storage courant
    (MinIO en dev), appelle provider.extract(), compare field-by-field
  - Cleanup du fichier temp après extraction
  - Sommaire : accuracy globale, par champ, latence moyenne, exit 1
    si une fixture a échoué (utile CI)

Tolérances par champ :
  - amountTtcCents : exact (la précision financière compte)
  - issueDate / dueDate : jour exact
  - numero : exact (trim, case-insensitive)
  - clientName : Jaccard similarity ≥ 85 % sur les tokens
    (tolère "SARL" final manquant, espaces, etc.)
  - clientEmail : exact (lowercased) ou null

Usage :
  pnpm ocr:validate                                  # provider courant (.env)
  OCR_PROVIDER=mistral MISTRAL_API_KEY=... pnpm ocr:validate
  node ace ocr:validate --fixtures-dir=./other --out=report.json

Sécurité :
  - `.gitignore` exclut tous les fichiers de e2e/fixtures/invoices/
    sauf README + .gitignore eux-mêmes — les vraies factures ne fuitent
    pas dans le repo public

À faire par Arthur :
  1. Dépose 10-20 vraies factures (anonymisées si possible) dans
     e2e/fixtures/invoices/
  2. Pour chaque, écrit le .expected.json (5 min par facture)
  3. Lance `OCR_PROVIDER=mistral pnpm ocr:validate` → ajuste prompt ou
     post-process si l'accuracy descend sous le seuil

Format ground truth + seuils cibles documentés dans le README du dossier.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 15:23:19 +02:00
ordinarthur
59f81879d8 test(e2e): tests Playwright multi-stack — vrai navigateur, DB isolée, Stripe mocké
All checks were successful
Build & Deploy Landing / build-and-deploy (push) Successful in 1m39s
Build & Deploy API / build-and-deploy (push) Successful in 2m30s
Build & Deploy Web / build-and-deploy (push) Successful in 1m21s
Ajoute une couche end-to-end où un Chromium drive la SPA + API ensemble
contre une DB Postgres séparée, avec Stripe entièrement mocké au niveau
API. 6 scénarios couverts (signup + onboarding + 4 sur le billing trial).

Architecture :
  - DB `rubis_test_e2e` séparée, TRUNCATE entre tests (~50 ms reset)
  - Routes test-only `/__test__/*` gated par NODE_ENV=test_e2e
    (reset, install Stripe mock, fire webhook, lire org state, last-org)
  - Stripe mocké via __setStripeForTests — pas d'appel réseau
  - Playwright spawn API + SPA automatiquement (webServer config)
  - CORS étendu à test_e2e pour le cross-origin localhost:5173 → :3333

Scénarios :
  - signup.spec.ts : signup → onboarding 3 étapes → dashboard (assert rubis hero)
  - billing-trial.spec.ts :
      • démarrer essai 14j → redirect Stripe Checkout (mock)
      • fallback Free 2 factures continue l'onboarding
      • webhook checkout.completed → org en trialing + trial_ends_at
      • retour ?trial=cancel après abandon
      • inspection DB : stripeCustomerId posé après start-trial

Scripts :
  - pnpm e2e          (headless)
  - pnpm e2e:headed   (Chromium visible)
  - pnpm e2e:ui       (mode interactif Playwright)
  - pnpm e2e:setup    (crée + migre rubis_test_e2e via docker exec)

Documentation : docs/tech/e2e-tests.md — architecture, scénarios,
extensions, CI, troubleshooting.

Limites assumées :
  - L'UI Stripe Checkout (3DS, formulaire CB) n'est pas testée — externe.
    Pour ça : playbook manuel docs/tech/stripe-trial-e2e-playbook.md.
  - Le rendu du banner "Essai Pro" n'est pas asserté en E2E à cause de
    TanStack Query staleTime — couvert par les tests vitest à la place.

État global du chantier billing : 127 tests japa + 6 Playwright + 11
vitest = couverture multi-niveaux.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 14:58:51 +02:00
ordinarthur
4a6c778e7c chore(api): docker-compose dev (PG/Redis/MinIO/Mailhog) + bascule sur Postgres
- docker-compose.dev.yml à la racine : PG 16, Redis 7, MinIO + bucket auto, Mailhog. Ports décalés (5433, 6380, 9100…) pour éviter les collisions locales.
- apps/api/config/database.ts : Postgres en default, SQLite reste accessible via DB_CONNECTION=sqlite.
- start/env.ts : validation des nouvelles vars (PG, Redis, S3, Mail, OCR, refresh tokens).
- .env.example complété, scripts pnpm dev:up/down/logs/reset à la racine.
- docs/tech/dev-setup.md pour expliquer la stack locale.
2026-05-06 12:57:42 +02:00
ordinarthur
8d3bab6a89 feat: scaffold frontend monorepo + first /login screen
Monorepo Turborepo (pnpm workspaces) avec 3 packages :

- apps/web : SPA React 19 + Vite 8 + Tailwind v4 (CSS-first)
  • TanStack Router (file-based, auto code-splitting), Query, Form
  • Radix primitives bruts + CVA + clsx + tailwind-merge
  • MSW pour mocker l'API tant qu'Adonis n'est pas branché
  • Polices Bricolage Grotesque + Inter self-hostées via fontsource
  • Tokens marque (rubis, cream, ink) exposés via @theme
  • Primitives maison : Gem, Brand, Eyebrow, Button, Input, Field
  • Route /login full flow : TanStack Form + Zod + mutation Query

- apps/api : Adonis 7 (kit api, scaffold via create-adonisjs)
  • Auth access tokens (Bearer) — cf. ADR-017
  • Tuyau core déjà câblé pour la génération de types
  • Routes /api/v1/auth/{signup,login} + /api/v1/account/{profile,logout}
  • Minimal — uniquement le pont front ↔ back

- packages/shared : types TS + schemas Zod + constantes
  • Source unique de vérité partagée api ↔ web
  • Domaines : User, Org, Auth, Client, Invoice, Plan

Tooling racine : Turbo, ESLint v9 flat, Prettier, husky, lint-staged.

CLAUDE.md et docs/decisions.md mis à jour avec ADR-014 à ADR-018
(stack, monorepo, PG existant, Bearer tokens, MinIO existant)
et le pointeur vers docs/tech/architecture.md.

Logo Rubis déplacé de landing/assets/ vers /assets/ (source unique
réutilisée par la landing et l'app).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-06 10:10:48 +02:00