3 Commits

Author SHA1 Message Date
Thomas Fransolet
4e17c572ba Nom d'app, drapeau QR et liens stores par application
ApplicationInstance porte désormais AppName (traductions, jsonb),
IsQRCodeEnabled (défaut true) et les liens App Store / Play Store.
Une ligne existe par (instance, type d'app) : chaque réglage vaut
donc séparément pour le mobile et pour le web.

Les liens stores ne sont modifiables que par un SuperAdmin — c'est
Unov qui publie les apps —, contrôlé côté API et pas seulement masqué
dans l'UI.

La liste anonyme des apps expose le slug web et le nom de l'instance :
la page /download de visitapp-web n'a que l'instanceId d'un QR imprimé.

Réserve les slugs download, demo et api : un segment statique de
visitapp-web l'emporte sur [slug], l'instance serait inaccessible.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 11:42:07 +02:00
Thomas Fransolet
2dc0cfceeb Lot F : portail de facturation Stripe et coût réel d'une question
Customer Portal : StripeService.CreateBillingPortalSessionAsync +
POST /api/onboarding/billing-portal, calqué sur checkout-session.
Une garde absente de l'énoncé : StripeCustomerId peut être nul, car
CreateCustomerAsync n'est appelée que par l'inscription self-service.
Les 4 instances venues de Mongo n'ont jamais vu Stripe — sans la garde,
elles recevaient une erreur d'API Stripe illisible côté front. 409,
distinct du 404 d'instance inconnue.

Ratio jetons -> questions : InstanceQuotaDTO.aiTokensPerQuestion, mesuré
sur les VisitorQuestion.TokensUsed de l'instance, seuil de 20 questions
avant de faire foi — une seule réponse citant un long article doublerait
la moyenne. En dessous, repli sur l'hypothèse de la grille tarifaire
(10 000, pas 1 000 : le /1000 de manager-app était faux d'un facteur 10).

Trois autres points du lot F étaient déjà faits et n'attendaient qu'une
vérification : rate limiting, endpoint ApplicationInstance, quotas seed.

6 tests. dotnet test : 197 passés, 14 sautés, 0 échec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 10:10:50 +02:00
Thomas Fransolet
af6b5b76ef Self-service onboarding (Stripe + Resend) + Postgres v3 schema (pgvector, media, visitor questions)
75 fichiers, ~1 mois de travail depuis f222861 (17/07). Contenu :

Onboarding self-service — jamais exécuté de bout en bout
  OnboardingController, StripeWebhookController, StripeService, ResendEmailService
  + IEmailService (10 templates), EmailTemplates/, TrialLifecycleService (Hangfire),
  PasswordTokenHelper, SlugHelper, 5 DTOs. Essai 14 j, Stripe customer/Checkout/Tax,
  mot de passe oublié + invitation user, plafond IA d'essai.

Schéma Postgres v3 — passe pendant que la base est vide
  ContentEmbedding + index HNSW (vector_cosine_ops), IEmbeddingService +
  GoogleEmbeddingService (gemini-embedding-001, 768 dims), Deployment/Dockerfile.postgres
  (postgis 3.4.3 + pgvector 0.8.6, épinglé par digest — un tag mobile rejouerait le
  warning de collation glibc). Colonnes Resource : StoragePath, FileName,
  IncludeInAiKnowledge, AiIndexStatus + nouveaux ResourceType ajoutés EN FIN d'enum.

Guide IA
  Champs Guide* sur Instance + InstanceDTO, AssistantService lit la configuration client
  dans les 4 blocs de prompt (ton codé en dur retiré, règle hors-sujet ajoutée aux deux
  variantes qui n'en avaient pas), IHttpClientFactory à la place des new HttpClient().
  Table VisitorQuestion + ConversationId sur AiChatRequest.

Stats
  Rétention unifiée à 13 mois (instances ET plans), VisitEventPurgeService.

Nettoyage
  IsStepLocked / IsHiddenInitially / FactContent supprimés de GuidedStep — IsStepLocked
  rendait une étape définitivement infranchissable même après réussite.
  SectionMap allégé (-57 lignes).

Tests
  SectionParcoursControllerTests, FakeConfiguration, FakeEmailService.
  ContentEmbedding a cassé 116 tests sur 124 (EF InMemory ne connaît pas Vector) :
  l'entité est exclue quand le provider n'est pas Npgsql. Conséquence assumée —
  le vector store n'est couvert par aucun test. dotnet test 124/124.

10 migrations EF. Base locale à jour, dotnet build 0 erreur.
Rien n'est en prod : la bascule Mongo → Postgres est décrite dans DOCS/STATUS.md §1quinquies.

⚠️ appsettings.json contient les clés Stripe (test) et Resend (prod) en clair — à rotationner.
2026-08-09 22:11:48 +02:00