Projet

Général

Profil

Fonctionnalité #1582

ouvert

Authentification et gestion de licenses

Fonctionnalité #1582: Authentification et gestion de licenses

Ajouté par Damien Cuvillier il y a 4 jours. Mis à jour il y a 2 jours.

Statut:
À Tester
Priorité:
Normal
Assigné à:
-
Début:
15/09/2026
Echéance:
% réalisé:

70%

Temps estimé:

Description

Quand je clique sur se connecter, ou créer un compte (un peu partout), tu dois brancher Opsy et ses fonctionnalités de gestion de license.

Utilise le manisfeste de l'application


Fichiers

claude-session-1582.glog (471 ko) claude-session-1582.glog Damien Cuvillier, 15/09/2026 20:00
claude-session-1582.glog (1,66 Mo) claude-session-1582.glog Damien Cuvillier, 17/09/2026 18:09

Mis à jour par Damien Cuvillier il y a 4 jours Actions #1

  • Description mis à jour (diff)

Mis à jour par Damien Cuvillier il y a 4 jours Actions #2

  • % réalisé changé de 0 à 10

Mis à jour par Damien Cuvillier il y a 4 jours Actions #3

  • Statut changé de À prioriser à En cours
  • % réalisé changé de 10 à 20

Mis à jour par Damien Cuvillier il y a 4 jours Actions #4

  • % réalisé changé de 20 à 30

Mis à jour par Damien Cuvillier il y a 4 jours Actions #5

  • % réalisé changé de 30 à 40

Mis à jour par Damien Cuvillier il y a 4 jours Actions #6

  • % réalisé changé de 40 à 50

Mis à jour par Damien Cuvillier il y a 4 jours Actions #7

  • % réalisé changé de 50 à 60

Mis à jour par Damien Cuvillier il y a 4 jours Actions #8

  • % réalisé changé de 60 à 70

Mis à jour par Damien Cuvillier il y a 4 jours Actions #9

Claude Code session summary:

#1582 — Authentification et gestion de licences

Domain Seek ne tient plus ni mot de passe ni état d'abonnement : comptes,
connexion, inscription et licences vivent chez Opsy. Tout part désormais du
manifeste de l'application.

Configuration par le manifeste

application.yml ne recopie plus rien d'Opsy. Le starter lit
src/main/resources/opsy.json — produit par la console (fiche de
l'application, onglet Sécurité) — d'où viennent issuer, client_id, audience,
royaume, portail de compte et code de licence. Ne restent dans le YAML que la
redirection de retour et, en variables d'environnement, ce qui doit changer
d'un environnement à l'autre (OPSY_CLIENT_SECRET en tête : le manifeste ne
porte pas le secret, Opsy le stocke haché).

⚠️ Le manifeste reste à déposer : l'extension Chrome n'étant pas connectée,
je n'ai pas pu le télécharger depuis la console. En attendant, la configuration
locale marche par variables — .private.env a été aligné sur les noms que
Spring lie aux propriétés opsy.* (OPSY_ISSUEROPSY_ISSUER_URI, ajout de
OPSY_LICENSE_APPLICATION_CODE).

« Se connecter » / « Créer un compte », partout

Deux entrées serveur, /auth/login et /auth/register
(AuthEntryController), portent la page d'où part le visiteur (next),
sauvegardent la requête et passent la main au SSO ; au retour, l'utilisateur
retrouve la page qu'il regardait — et non l'accueil comme avant
(opsy.default-redirect-url ramené à /, sans quoi fmk/auth ignore la requête
sauvegardée). S'y ajoutent /auth/account et /auth/licenses, qui ouvrent le
portail Opsy.

Tous les points d'appel visent ces entrées : en-tête (menu de compte, y compris
la version mobile), cartes de tarifs, bandeau de démo, modale de fonctionnalité
verrouillée, paywall. Ce sont de vrais liens <a> — ils fonctionnent sans JS —
et ils disparaissent quand aucun Opsy n'est configuré. Le menu du compte
connecté gagne « Mon abonnement » → écran mes licences du portail.

Opsy héberge l'inscription sur son propre écran de connexion (lien « créer un
compte ») : faute d'un paramètre d'autorisation qui ouvrirait ce formulaire
d'emblée, /auth/register entre par le même flux — ce qui préserve le retour
vers l'application, qu'une visite directe de {issuer}/register perdrait.

Les licences pilotent les fonctionnalités

LicenseService est la source unique des droits : recherches quotidiennes,
combinaisons, générateur de mots-clés et paniers se lisent sur les
entitlements de la licence active. Deux garde-fous : un plafond chiffré par
l'offre gagne toujours, et une fonctionnalité ne se ferme que du jour où une
offre la vend
— tant que le catalogue n'en parle pas, les règles d'avant Opsy
s'appliquent (plafonds quota.*, générateur ouvert à tout compte, paniers aux
licenciés). Aucune régression pour les utilisateurs actuels.

Côté serveur, les endpoints suivent : /api/wordlist refuse enfin les
anonymes (401) et les comptes sans droit (402) — le TODO « Phase 2.3 » est
levé —, /api/cart répond license_required, /api/check et
/api/search-log comparent au plafond de la licence plutôt qu'à celui de
l'anonyme. UserService.isSubscribed() délègue à la licence, QuotaService
ne fait plus que compter.

GET /api/license sert au front l'état complet (droits, plafonds, URL du
portail, offres). Les offres et les prix viennent du catalogue public
d'Opsy
(/api/public/catalog/{code}, en cache 10 min) : la grille de tarifs
et le paywall sont chiffrés par la console, pas par le code. Le paywall propose
les offres du royaume et renvoie l'achat au portail ; tant qu'aucune offre n'y
est publiée, le paiement Stripe existant reste en place — le tunnel d'achat
n'existe pas encore côté Opsy, aucune vente n'est donc cassée.

Divers

  • Duplication supprimée entre PublicController et AppController : le bloc
    identité / droits / tarifs vit dans AccountModel.
  • Nouveaux textes traduits dans les cinq langues ; styles en SCSS (@apply),
    avec un mixin partagé pour les actions de modale, désormais liens ou boutons.
  • README : section « Accounts and licences (Opsy) » et variables d'environnement.

Vérifié

Compilation Maven, build Vite, démarrage de l'application contre l'Opsy local :
liens /auth/* rendus avec le bon next, redirections vers l'autorisation et
vers le portail, refus 401/402 des endpoints sous licence, /api/license
servi, catalogue interrogé sans erreur (royaume sans offre → repli). Le
parcours de connexion bout en bout demande des identifiants Opsy et reste à
jouer manuellement.

À faire côté Opsy

  1. Déposer src/main/resources/opsy.json (console → fiche domain-seek →
    Sécurité → télécharger le manifeste).
  2. Déclarer les features daily-searches, combinations,
    keyword-generator, carts et publier l'offre correspondante : c'est ce
    qui fait passer l'application au régime « licence ».

Mis à jour par Damien Cuvillier il y a 2 jours Actions #10

l'authentification fonctionne mais me redirige directement vers opsy après le succes

Mis à jour par Damien Cuvillier il y a 2 jours Actions #11

  • % réalisé changé de 70 à 10

Mis à jour par Damien Cuvillier il y a 2 jours Actions #12

  • Statut changé de À Tester à En cours
  • % réalisé changé de 10 à 20

Mis à jour par Damien Cuvillier il y a 2 jours Actions #13

  • % réalisé changé de 20 à 30

Mis à jour par Damien Cuvillier il y a 2 jours Actions #14

  • % réalisé changé de 30 à 40

Mis à jour par Damien Cuvillier il y a 2 jours Actions #15

  • % réalisé changé de 40 à 50

Mis à jour par Damien Cuvillier il y a 2 jours Actions #16

  • % réalisé changé de 50 à 60

Mis à jour par Damien Cuvillier il y a 2 jours Actions #17

  • % réalisé changé de 60 à 70

Mis à jour par Damien Cuvillier il y a 2 jours Actions #18

Claude Code session summary:

#1582 — Authentification et gestion de licences

Les entrées « se connecter » et « créer un compte » mènent au SSO Opsy et en
reviennent sur la page d'origine ; la configuration ne se recopie plus, elle
vient du manifeste ; les offres et les tarifs sont lus par le SDK Opsy.

Le manifeste est devenu la source de configuration

./opsy.json est déposé à la racine du projet. Issuer, client_id, secret,
audience, royaume, portail de compte et code d'application en viennent : plus
aucune variable OPSY_* dans .private.env. Vérifié en conditions réelles —
l'application démarre sur le seul manifeste, le flux OIDC part vers
domain-seek.auth.7app.localhost:11501 avec le bon client_id, et le secret
est accepté par le point d'échange de jetons du royaume.

Le fichier porte un secret : il est git-ignoré (OPSY-API-084) et se monte au
déploiement dans /app/opsy.json (documenté dans HOSTING.md §1.2, le
Dockerfile et README.md). domain-seek étant un client confidentiel, le
retélécharger depuis la console fait tourner le secret (OPSY-API-076b) : les
autres environnements branchés sur cette application veulent le nouveau
manifeste.

Les offres et les tarifs passent par le SDK

OpsyCatalogService, écrit à la main dans l'application, est remplacé par
OpsyCatalog, ajouté au starter io.gotan.opsy:opsy-spring-boot-starter
(dépôt apps/opsy, spec OPSY-API-026b/c/d) : lecture de
GET {issuer}/api/public/catalog/{code}, gardée dix minutes, muette en cas de
panne du royaume — une page de tarifs s'affiche même quand Opsy ne répond pas.
LicenseService, PricingModel et LicenseController s'y branchent.

Deux corrections au SDK que ce branchement a révélées :

  • le manifeste ne posait opsy.license.application-code que si
    license.enabled était vrai. Or domain-seek n'a pas encore d'offre active
    (enabled: false) tout en ayant un catalogue à afficher : sans ce code, la
    page de tarifs n'avait rien à demander. Il est désormais posé dans les deux
    cas ;
  • la lecture du catalogue pose son propre mapper JSON, tolérant aux champs
    absents : le contrat omet trialDays quand une offre n'a pas d'essai, ce
    qu'un mapper strict (Jackson 3 sous Boot 4) refusait d'asseoir sur un int
    une seule offre sans essai vidait la grille entière.

Un bug qui coupait tout accès au compte

Une fois connecté, le menu de compte ne s'affichait pas : NG0203 au
constructeur de GotanUserMenuComponent. @gotan/auth-ng est un lien vers
fmk/auth, qui porte ses propres node_modules — le bundle embarquait deux
Angular, et le second n'avait pas le contexte d'injection du premier. Profil,
mot de passe, licence et déconnexion étaient donc inatteignables.
resolve.dedupe dans vite.config.js corrige la résolution ; le menu et ses
entrées vers le portail Opsy sont de retour.

Accès aux licences, même sans catalogue

Le paywall retombe sur le paiement Stripe tant que le royaume ne publie pas
d'offre, et ne menait alors nulle part chez Opsy. Il porte maintenant dans tous
les cas un lien « Ma licence » vers l'écran des licences du portail — seul
endroit où un compte voit ce qu'il détient. Le style est factorisé en mixin SCSS
avec le lien de devise (une seule clause @apply, marge en paramètre).

Vérifié

  • mvn test au vert des deux côtés (domain-seek 19 tests, starter Opsy 38 +
    8 nouveaux sur OpsyCatalog et le code d'application du manifeste) ;
  • parcours réel dans le navigateur : « se connecter » → écran Opsy → retour sur
    la page d'origine, en-tête avec le menu de compte ;
  • chaîne complète des offres éprouvée en pointant temporairement le SDK sur une
    application du même royaume qui publie une offre : nom, prix multi-devises,
    durée d'essai et comparatif remontent jusqu'à la grille de tarifs et au
    paywall.

Reste à faire — hors code

Le catalogue de domain-seek ne publie aucune offre (offers: []) : les
écrans tournent donc sur leur repli d'avant Opsy et la gestion de licence ne se
voit pas encore à l'usage. Les deux offres à créer sont décrites dans
docs/OPSY_CATALOG.md et scripts/opsy-catalog.py
les pose d'un coup — il lui faut un jeton REALM_ADMIN, que je n'ai pas.

Formats disponibles : PDF Atom