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,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.
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"]
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
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. |
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é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-demogift-set-config.ts
Section intitulée « gift-set-config.ts »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é) etTITREO_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. |
printf '%s' "$CLE" | pnpm gift:set-config --merchant demo --enseigne MON_ENSEIGNEGIFT_API_KEY=… pnpm gift:set-config --merchant demo --enseigne MON_ENSEIGNE# OK titreo — marchand <nom> (demo), enseigne MON_ENSEIGNE, clé …1234, vérifiéeSur 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.
Diagnostic / build
Section intitulée « Diagnostic / build »creds-check.ts
Section intitulée « creds-check.ts »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.
titreo-smoke.ts
Section intitulée « titreo-smoke.ts »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, plusTITREO_ENSEIGNEetTITREO_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.
- 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 : mêmes variables que
titreo-smoke, lues de la même façon.
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. 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éspnpm check:creds --titreo --merchant merchant-demo
# 5. (au besoin) Régénérer la spec OpenAPI après modif de routespnpm gen:openapi