Scripts
À quoi servent les scripts ?
Section intitulée « À quoi servent les 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.
Vue d’ensemble
Section intitulée « Vue d’ensemble »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
Tableau récapitulatif
Section intitulée « Tableau récapitulatif »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ération de secrets
Section intitulée « Génération de secrets »keygen-bootstrap.ts
Section intitulée « keygen-bootstrap.ts »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
.envsousBOOTSTRAP_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 dansapi/src/config/index.ts).
pnpm keygen:bootstrap# === BOOTSTRAP_SIGNING_KEY (private, .env) ===# -----BEGIN PRIVATE KEY----- ...# === PUBLIC KEY (embed in bootstrap loader) ===# -----BEGIN PUBLIC KEY----- ...keygen-kek.ts
Section intitulée « keygen-kek.ts »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 (voirsetup-test-merchantetpsp-set-config). À la lecture,loadKekFromBase64()rejette toute valeur qui ne décode pas exactement à 32 octets.
pnpm keygen:kek# === PSP_CONFIG_KEK (base64, 32 bytes) ===# K6m9...base64...==keygen-api-key.ts
Section intitulée « keygen-api-key.ts »É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. |
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: adminkeygen-admin-bootstrap.ts
Section intitulée « keygen-admin-bootstrap.ts »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. |
pnpm keygen:admin --email admin@titreo-epay.io --password 'changeme-strong-12+'# ✓ admin user created: <adminUserId> (admin@titreo-epay.io)Provisioning / seed
Section intitulée « Provisioning / seed »setup-test-merchant.ts
Section intitulée « setup-test-merchant.ts »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), viaFirebirdMerchantPspConfigRepo. - 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_. |
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_...seed-merchant-user.ts
Section intitulée « seed-merchant-user.ts »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. |
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) ===psp-set-config.ts
Section intitulée « psp-set-config.ts »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). |
pnpm psp:set-config --merchant merchant-demo --provider stripe --secret sk_test_... --whsec whsec_...# OK stripe config stored for merchant merchant-demoDiagnostic / build
Section intitulée « Diagnostic / build »titreo-smoke.ts
Section intitulée « titreo-smoke.ts »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.titreodoit être résolue, c.-à-d.TITREO_API_BASE,TITREO_ENSEIGNE,TITREO_API_KEYpré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.
- sans
pnpm tsx scripts/titreo-smoke.ts# checkBalance result (probably FAILED, expected for fake card): { ... }cancel-titreo-test-cards.ts
Section intitulée « cancel-titreo-test-cards.ts »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éellementTitreoGiftCardAdapter.cancel(...)pour chaque leg (utilisetransactionIdcommeoriginalTicketet le CVV stocké/connu), puis affiche un compte rendu OK/FAIL. - Lecture base : requête SQL directe sur
payment_legsviaFirebirdDb.withTransaction. - Pré-requis : config Titreo résolue (mêmes variables que
titreo-smoke).
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 Titreogen-openapi.ts
Section intitulée « gen-openapi.ts »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(racineapi/) ;docs/openapi.json;docs/openapi.js(assignewindow.__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.
pnpm gen:openapi# openapi written: .../api/openapi.json# & .../api/docs/openapi.json# & .../api/docs/openapi.jsChemin d’appel typique (commenté)
Section intitulée « Chemin d’appel typique (commenté) »Séquence minimale pour disposer d’un environnement de test exploitable :
# 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é Titreopnpm tsx scripts/titreo-smoke.ts
# 5. (au besoin) Régénérer la spec OpenAPI après modif de routespnpm gen:openapi