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, keygen-admin-bootstrap) : créer en base les enregistrements de départ (un marchand, sa config PSP chiffrée, une clé d’API, un compte console, le premier super-admin) pour pouvoir tester de bout en bout.
  • Diagnostic / build (titreo-smoke, cancel-titreo-test-cards, gen-openapi) : 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"]
    KAK["keygen-api-key → api_keys"]
  end
  subgraph diag["Diagnostic / build"]
    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
  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.
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 :
    • stripeSTRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET (requis), STRIPE_PUBLIC_KEY (optionnel) ;
    • adyenADYEN_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 : --roleowner | 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

Smoke test de connectivité Titreo : instancie TitreoGiftCardAdapter avec la config Titreo 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 : config.titreo doit être résolue, c.-à-d. TITREO_API_BASE, TITREO_ENSEIGNE, TITREO_API_KEY présentes ; sinon le script s’arrête.
  • 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 : config Titreo résolue (mêmes variables que titreo-smoke).
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. (optionnel) Vérifier la connectivité Titreo
pnpm tsx scripts/titreo-smoke.ts
# 5. (au besoin) Régénérer la spec OpenAPI après modif de routes
pnpm gen:openapi