Aller au contenu

Scripts

Le dossier api/scripts/ regroupe des outils en ligne de commande qui n’appartiennent pas au flux de requêtes HTTP : ils servent à préparer l’environnement, pas à le faire tourner. On les lance à la main (ou dans un script d’init Docker), une fois, en dehors du serveur Fastify.

Trois grandes familles :

  • Génération de secrets (keygen-*) : produire les clés cryptographiques que le serveur attend dans son .env (clé de signature du bootstrap, clé de chiffrement des configs PSP), et émettre une clé d’API marchand stockée en base.
  • Provisioning / seed (setup-test-merchant, seed-merchant-user, psp-set-config, gift-set-config, keygen-admin-bootstrap) : créer en base les enregistrements de départ (un marchand, sa config PSP chiffrée, ses accès cartes cadeaux, une clé d’API, un compte console, le premier super-admin) pour pouvoir tester de bout en bout.
  • Diagnostic / build (creds-check, titreo-smoke, cancel-titreo-test-cards, gen-openapi) : vérifier que des identifiants sont acceptés, vérifier la connectivité Titreo, nettoyer des cartes de test, régénérer la spec OpenAPI.
flowchart TD
  subgraph keygen["Génération de secrets (.env)"]
    KB["keygen-bootstrap → BOOTSTRAP_SIGNING_KEY"]
    KK["keygen-kek → PSP_CONFIG_KEK"]
  end
  subgraph seed["Provisioning en base (Firebird)"]
    KA["keygen-admin-bootstrap → admin_users"]
    STM["setup-test-merchant → merchants + api_keys + merchant_psp_configs"]
    SMU["seed-merchant-user → merchant_users"]
    PSC["psp-set-config → merchant_psp_configs"]
    GSC["gift-set-config → merchant_gift_configs"]
    KAK["keygen-api-key → api_keys"]
  end
  subgraph diag["Diagnostic / build"]
    CC["creds-check (Titréo, SMTP, PSP)"]
    TS["titreo-smoke (lecture solde)"]
    CTC["cancel-titreo-test-cards (rollback gift)"]
    GO["gen-openapi → openapi.json"]
  end
  KK -. chiffre les secrets PSP .-> STM
  KK -. chiffre les secrets PSP .-> PSC
  KK -. chiffre la clé Titréo .-> GSC
  STM -. crée le merchant requis .-> GSC
  STM -. crée le merchant requis .-> SMU
Script (api/scripts/) Commande Rôle
keygen-bootstrap.ts pnpm keygen:bootstrap Génère une paire de clés Ed25519 (signature du bootstrap loader).
keygen-kek.ts pnpm keygen:kek Génère la KEK (clé de chiffrement des configs PSP), 32 octets base64.
keygen-api-key.ts pnpm keygen:api-key Émet une clé d’API marchand et l’enregistre (hash) en base.
keygen-admin-bootstrap.ts pnpm keygen:admin Crée le premier super-admin Titreo dans admin_users.
setup-test-merchant.ts pnpm setup:test-merchant Crée en une fois : marchand + clé d’API + config PSP chiffrée active.
seed-merchant-user.ts pnpm seed:merchant-user Crée/maj un compte de connexion console marchand, déjà vérifié.
psp-set-config.ts pnpm psp:set-config Insère/met à jour la config PSP chiffrée d’un marchand existant.
gift-set-config.ts pnpm gift:set-config Vérifie auprès de Titréo puis enregistre, chiffrés, les accès cartes cadeaux d’un marchand existant.
creds-check.ts pnpm check:creds Vérifie que des identifiants fonctionnent vraiment : accès Titréo d’un marchand, relais SMTP, clé PSP.
titreo-smoke.ts pnpm tsx scripts/titreo-smoke.ts Smoke test : vérifie l’auth Titreo via une lecture de solde.
cancel-titreo-test-cards.ts pnpm tsx scripts/cancel-titreo-test-cards.ts Annule les débits gift capturés sur des cartes de test Titreo.
gen-openapi.ts pnpm gen:openapi Écrit openapi.json (+ variantes docs) depuis l’app HTTP.

Génère une paire de clés Ed25519 pour signer/vérifier le bootstrap loader (le snippet JS injecté chez le marchand). S’appuie sur generateEd25519KeyPairPem() (api/src/infrastructure/crypto/ed25519-signer.ts).

  • Sortie stdout : la clé privée PEM (à coller dans .env sous BOOTSTRAP_SIGNING_KEY) puis la clé publique PEM (à embarquer côté loader pour vérifier la signature).
  • Variable d’env associée : BOOTSTRAP_SIGNING_KEY (lue dans api/src/config/index.ts).
Fenêtre de terminal
pnpm keygen:bootstrap
# === BOOTSTRAP_SIGNING_KEY (private, .env) ===
# -----BEGIN PRIVATE KEY----- ...
# === PUBLIC KEY (embed in bootstrap loader) ===
# -----BEGIN PUBLIC KEY----- ...

Génère la KEK (Key Encryption Key) servant à chiffrer en base les secrets PSP (clés API et secrets webhook des marchands). Délègue à generateKekBase64() (api/src/infrastructure/crypto/aead.ts) : 32 octets aléatoires encodés en base64.

  • Sortie stdout : la KEK base64 (32 octets).
  • Variable d’env associée : PSP_CONFIG_KEK. Requise dès qu’on manipule une config PSP (voir setup-test-merchant et psp-set-config). À la lecture, loadKekFromBase64() rejette toute valeur qui ne décode pas exactement à 32 octets.
Fenêtre de terminal
pnpm keygen:kek
# === PSP_CONFIG_KEK (base64, 32 bytes) ===
# K6m9...base64...==

Émet une clé d’API marchand et l’enregistre en base (table api_keys). La clé en clair n’est affichée qu’une seule fois ; la base ne stocke que son hash SHA-256 (hashApiKey), le préfixe et les 4 derniers caractères.

  • Génération : generateApiKey(prefix) (api/src/infrastructure/crypto/api-key.ts) — prefix + 32 octets aléatoires en base64url.
  • Persistance : FirebirdApiKeyRepo.insert(...).
  • Pas de variable d’env dédiée : la clé vit en base (api_keys), pas dans .env.
Option Défaut Rôle
--merchant <id> (requis) Identifiant marchand propriétaire de la clé.
--name <name> (requis) Libellé de la clé.
--scopes <csv> admin Scopes autorisés (séparés par virgule), validés par parseScopes.
--prefix <p> tep_live_ Préfixe : tep_live_ ou tep_test_.
--expires <ISO> (aucune) Date d’expiration optionnelle.
Fenêtre de terminal
pnpm keygen:api-key --merchant merchant-demo --name "server key" --scopes admin --prefix tep_test_
# === API KEY (à montrer une seule fois au marchand) ===
# tep_test_xxxxxxxxxxxx
# scopes: admin

Crée le premier super-admin Titreo dans admin_users (back-office admin). Malgré le préfixe keygen-, ce script ne génère pas de clé : il crée un compte (email + mot de passe hashé). Il s’appuie sur le use case CreateAdminUser (api/src/application/auth/create-admin-user.ts), qui refuse la création si l’email existe déjà (findByEmail → erreur de validation).

  • Hash : ScryptPasswordHasher.
  • Persistance : FirebirdAdminUserRepo.
Option Défaut Rôle
--email <email> (requis) Email du super-admin.
--password <pwd> (requis) Mot de passe (fort recommandé).
--role <role> super_admin Rôle admin.
Fenêtre de terminal
pnpm keygen:admin --email admin@titreo-epay.io --password 'changeme-strong-12+'
# ✓ admin user created: <adminUserId> (admin@titreo-epay.io)

Le script « tout-en-un » pour démarrer : crée (ou met à jour) un marchand, émet une clé d’API privée (scope admin par défaut), et upserte une config PSP active (stripe ou adyen) chiffrée avec la KEK. Lit les credentials PSP depuis l’environnement, puis affiche les artefacts à coller dans le .env.local de la boutique de démo.

  • Pré-requis env : PSP_CONFIG_KEK (sinon arrêt), plus les variables du PSP choisi :
    • stripe → STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (requis), STRIPE_PUBLIC_KEY (optionnel) ;
    • adyen → ADYEN_API_KEY, ADYEN_HMAC_KEY, ADYEN_MERCHANT_ACCOUNT (requis), ADYEN_CLIENT_KEY (optionnel).
  • Chiffrement : AesGcmAead + loadKekFromBase64(config.pspConfigKek), via FirebirdMerchantPspConfigRepo.
  • Idempotence partielle : si le marchand existe déjà, il est mis à jour (diff pspProviderType / giftProviderType / webhookUrl) ; une nouvelle clé d’API est créée à chaque exécution.
Option Défaut Rôle
--provider adyen PSP à configurer : adyen ou stripe.
--merchant-id merchant-demo Identifiant du marchand.
--merchant-name Maison Générique Nom affiché.
--webhook-url webhook plugin PrestaShop de démo URL de webhook côté marchand.
--gift-provider titreo Fournisseur de carte cadeau.
--scopes admin Scopes de la clé d’API émise.
--prefix tep_test_ Préfixe de la clé : tep_test_ ou tep_live_.
Fenêtre de terminal
pnpm setup:test-merchant \
--provider stripe \
--merchant-id merchant-demo \
--merchant-name "Maison Générique" \
--webhook-url http://localhost:3200/api/webhooks/titreo
# ✓ merchant created / ✓ apiKey created / ✓ stripe pspConfig upserted
# === Copier dans demo-shop/.env.local ===
# TITREO_API_KEY=tep_test_...
# TITREO_WEBHOOK_SECRET=whtep_...

Crée (ou met à jour) un compte de connexion à la console marchand (merchant_users), déjà vérifié et actif — pratique pour qu’un dev se connecte sans passer par le flux signup + vérification email. Idempotent par email. Le marchand ciblé doit déjà exister (lancer setup-test-merchant.ts avant).

  • Hash : ScryptPasswordHasher.
  • Persistance : FirebirdMerchantUserRepo (insert ou updatePassword + markEmailVerified + éventuels updateRole / réactivation).
  • Garde-fous : --role ∈ owner | developer | ops ; --password ≥ 12 caractères.
Option Défaut Rôle
--merchant-id merchant-demo Marchand auquel rattacher le compte (doit exister).
--email dev@titreo-epay.local Email de connexion (mis en minuscules).
--password MerchantDev2026! Mot de passe (≥ 12 caractères).
--role owner Rôle console : owner, developer ou ops.
Fenêtre de terminal
pnpm seed:merchant-user --merchant-id merchant-demo --email dev@titreo-epay.local --password 'MerchantDev2026!' --role owner
# ✓ merchant user created + verified: dev@titreo-epay.local (owner)
# === Connexion console marchand (http://localhost:3500) ===

Insère ou met à jour la config PSP chiffrée d’un marchand déjà existant (version « bas niveau » de la partie PSP de setup-test-merchant). Les secrets passent en arguments CLI ; ils sont chiffrés avec la KEK avant stockage (FirebirdMerchantPspConfigRepo + AesGcmAead).

  • Pré-requis env : PSP_CONFIG_KEK.
Option Défaut Rôle
--merchant (requis) Identifiant marchand.
--provider (requis) Type de PSP (ex. stripe, adyen).
--secret (requis) Clé secrète PSP (stockée chiffrée ; last4 conservé en clair).
--whsec (requis) Secret de signature webhook (stocké chiffré ; last4 en clair).
--publicKey (aucun) Clé publique / publishable PSP.
--account (aucun) Référence de compte (ex. merchantAccount Adyen).
--inactive false Si présent, marque la config inactive (active = false).
Fenêtre de terminal
pnpm psp:set-config --merchant merchant-demo --provider stripe --secret sk_test_... --whsec whsec_...
# OK stripe config stored for merchant merchant-demo

Pose les accès cartes cadeaux d’un marchand déjà existant : pour Titréo, le nom d’enseigne et la clé de l’API Titréo REST. C’est le même use case que la console marchand (UpsertGiftConfig) : vérification en direct auprès de Titréo, puis enregistrement chiffré. Il sert au semis des marchands existants et au support ; un marchand saisit normalement ses accès lui-même.

  • Pré-requis env : PSP_CONFIG_KEK (chiffrement de la clé) et TITREO_API_BASE (adresse de l’API Titréo REST).
  • La clé ne passe jamais par la ligne de commande : elle resterait dans l’historique du shell et la liste des processus. Elle vient de la variable GIFT_API_KEY, à défaut de l’entrée standard.
  • Rien n’est écrit si Titréo refuse les accès (GIFT_CREDENTIALS_REJECTED) ou ne répond pas (GIFT_PROVIDER_UNREACHABLE). Le script sort alors en code 1.
Option Défaut Rôle
--merchant (requis) Identifiant marchand (doit exister).
--enseigne (requis) Nom d’enseigne chez Titréo.
--provider titreo Fournisseur de cartes cadeaux.
Fenêtre de terminal
printf '%s' "$CLE" | pnpm gift:set-config --merchant demo --enseigne MON_ENSEIGNE
GIFT_API_KEY=… pnpm gift:set-config --merchant demo --enseigne MON_ENSEIGNE
# OK titreo — marchand <nom> (demo), enseigne MON_ENSEIGNE, clé …1234, vérifiée

Sur un serveur, passer par la CLI de déploiement : tep gift set --merchant <id> --enseigne <nom> demande la clé en saisie masquée, ou la lit sur l’entrée standard.

Vérifie que des identifiants fournis par un tiers fonctionnent vraiment, en faisant l’appel réel. Un contrôle à la fois ; le script sort en 0 s’il passe, 1 sinon. Aucun secret n’est affiché : au plus les quatre derniers caractères et la longueur.

Commande Ce qui est vérifié
pnpm check:creds --titreo TITREO_API_BASE est renseignée ; état du catalogue TITREO_PRODUCT_LABELS.
pnpm check:creds --titreo --merchant <id> Les accès Titréo de ce marchand, lus en base et déchiffrés, obtiennent un jeton. Aucune carte n’est engagée.
pnpm check:creds --titreo --merchant <id> --card <barcode> En plus : lit le solde de la carte et affiche codeProduit et l’émetteur. Aucun mouvement.
pnpm check:creds --smtp [--to adresse] Ouvre la session SMTP ; avec --to, envoie un message.
pnpm check:creds --psp --merchant <id> Interroge Stripe avec la clé stockée pour ce marchand. Pour un autre PSP, seuls le format et le déchiffrement sont contrôlés.

Sans accès actif pour le marchand, --titreo --merchant échoue et le dit : la page de paiement de ce marchand ne propose pas les cartes cadeaux. Un 401 signifie enseigne ou clé fausse ; un 404, une TITREO_API_BASE qui n’est pas la bonne.

Équivalents sur un serveur : tep check titreo --merchant <id> [--card <barcode>], tep gift check --merchant <id>, tep check smtp, tep check psp.

Smoke test de connectivité Titreo : instancie TitreoGiftCardAdapter et appelle checkBalance(...). Charge d’abord le .env du dossier api/ (helper loadDotEnv interne, ne réécrit pas les variables déjà définies).

  • Pré-requis : TITREO_API_BASE, plus TITREO_ENSEIGNE et TITREO_API_KEY ; sinon le script s’arrête. Ces deux dernières ne font plus partie de la configuration de l’API : c’est un outil de développement, qui les lit directement dans l’environnement pour une enseigne de test. En service, les accès viennent du marchand, en base.
  • Comportement :
    • sans TITREO_TEST_CARD → appel sur une carte bidon (0000000000000000) pour forcer l’auth : un 401 signale de mauvais credentials ;
    • avec TITREO_TEST_CARD → lit et affiche le solde réel de la carte.
Fenêtre de terminal
pnpm tsx scripts/titreo-smoke.ts
# checkBalance result (probably FAILED, expected for fake card): { ... }

Script « one-shot » de nettoyage : annule les débits gift capturés (legs gift_card au statut CAPTURED) posés sur une liste figée de 10 cartes de test Titreo (tokens + CVV codés en dur dans le fichier). Utile pour reremettre à zéro l’environnement de test après une série de scénarios split-tender.

  • Mode par défaut = dry-run : lit les legs concernés en base et les liste, sans appel API.
  • Mode --live : appelle réellement TitreoGiftCardAdapter.cancel(...) pour chaque leg (utilise transactionId comme originalTicket et le CVV stocké/connu), puis affiche un compte rendu OK/FAIL.
  • Lecture base : requête SQL directe sur payment_legs via FirebirdDb.withTransaction.
  • Pré-requis : mêmes variables que titreo-smoke, lues de la même façon.
Fenêtre de terminal
pnpm tsx scripts/cancel-titreo-test-cards.ts # dry-run : montre ce qui serait annulé
pnpm tsx scripts/cancel-titreo-test-cards.ts --live # exécute réellement les annulations Titreo

Régénère la spec OpenAPI du backend. Construit une instance HTTP de test via buildHttpFixture(...) (api/tests/fixtures/build-http-app.ts), récupère app.swagger(), puis écrit le résultat dans trois cibles, relativement au dossier api/ :

  • openapi.json (racine api/) ;
  • docs/openapi.json ;
  • docs/openapi.js (assigne window.__OPENAPI_SPEC__ pour l’affichage statique des docs).

À relancer après toute modification de schéma de route (Zod). Voir Contrats pour la chaîne Zod → OpenAPI.

Fenêtre de terminal
pnpm gen:openapi
# openapi written: .../api/openapi.json
# & .../api/docs/openapi.json
# & .../api/docs/openapi.js

Séquence minimale pour disposer d’un environnement de test exploitable :

Fenêtre de terminal
# 1. Secrets dans api/.env (une fois)
pnpm keygen:bootstrap # → BOOTSTRAP_SIGNING_KEY (clé privée Ed25519)
pnpm keygen:kek # → PSP_CONFIG_KEK (KEK base64, 32 octets)
# 2. Marchand + clé d'API + config PSP chiffrée (utilise PSP_CONFIG_KEK + creds Stripe/Adyen de l'env)
pnpm setup:test-merchant --provider stripe --merchant-id merchant-demo
# 3. Compte console pour se connecter (le marchand de l'étape 2 doit exister)
pnpm seed:merchant-user --merchant-id merchant-demo --email dev@titreo-epay.local --password 'MerchantDev2026!'
# 4. Accès cartes cadeaux du marchand (vérifiés auprès de Titréo, puis chiffrés)
printf '%s' "$CLE" | pnpm gift:set-config --merchant merchant-demo --enseigne MON_ENSEIGNE
# 4 bis. (optionnel) Vérifier que ces accès sont toujours acceptés
pnpm check:creds --titreo --merchant merchant-demo
# 5. (au besoin) Régénérer la spec OpenAPI après modif de routes
pnpm gen:openapi