Configuration¶
Ce document détaille les variables d'environnement lues par BCard, section par section. Les valeurs de la colonne Exemple sont neutres — aucune n'est une valeur réellement utilisée par le dépôt.
Où sont définies les variables¶
Symfony charge ces fichiers dans l'ordre, chaque niveau surchargeant le précédent :
| Fichier | Rôle | Versionné |
|---|---|---|
.env |
Valeurs par défaut de développement | Oui |
.env.local |
Surcharges locales, propres au poste | Non |
.env.$APP_ENV (ex. .env.test) |
Valeurs par défaut spécifiques à un environnement | Oui |
.env.$APP_ENV.local |
Surcharges spécifiques à un environnement | Non |
Le dépôt versionne un .env et un .env.test pré-remplis, ainsi qu'un .env.local local au
poste de développement — les trois ne devraient jamais contenir de secrets réels, mais
c'est le mécanisme que Symfony utilise pour les lire, indépendamment de leur contenu à un
instant donné. En production, le conteneur applicatif reçoit les valeurs par de vraies
variables d'environnement (voir docker-compose.prod.yml), qui priment sur les fichiers
.env*.
Application¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
APP_ENV |
Environnement Symfony (dev, test ou prod) ; conditionne le chargement des fichiers .env.$APP_ENV et le comportement du kernel |
Oui | dev |
APP_SECRET |
Secret applicatif Symfony (framework.secret dans config/packages/framework.yaml), utilisé entre autres pour le CSRF. Il est aussi lu directement ($_ENV['APP_SECRET'] / getenv('APP_SECRET')) par plusieurs contrôleurs et par App\Service\BusinessCardGenerationService pour dériver un hachage stable |
Oui | a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 |
APP_BASE_URL |
Destinée à porter l'URL publique de l'application (déclarée requise dans docker-compose.prod.yml) |
Oui en production | https://card.example.com |
DOCS_HOST |
Hôte Traefik du portail documentaire servi par bcard-docs dans docker-compose.prod.yml |
Non | docs.example.com |
OBFUSCATE_ID_SECRET |
Destinée à un secret d'obfuscation des identifiants exposés (déclarée requise dans docker-compose.prod.yml) |
Oui en production | un-secret-different-de-app-secret |
MESSENGER_TRANSPORT_DSN |
Destinée au transport Symfony Messenger | Non | doctrine://default |
Variables déclarées mais non lues par le code applicatif
APP_BASE_URL, OBFUSCATE_ID_SECRET et MESSENGER_TRANSPORT_DSN figurent toutes trois dans
docker-compose.prod.yml, mais aucune occurrence de leur nom n'apparaît dans src/ ni
config/ au moment de la rédaction de cette page (vérifié par recherche textuelle).
APP_BASE_URL et OBFUSCATE_ID_SECRET y sont déclarées avec la syntaxe obligatoire
(${VAR:?...}) : leur absence fait échouer le démarrage du conteneur. MESSENGER_TRANSPORT_DSN
y est déclarée avec une valeur par défaut (${MESSENGER_TRANSPORT_DSN:-doctrine://default}) :
son absence ne bloque pas le démarrage. Aucun fichier config/packages/messenger.yaml
n'existe malgré la dépendance symfony/doctrine-messenger déclarée dans composer.json : le
bus Messenger n'est donc pas configuré. La génération des identifiants publics de carte
(App\Command\GeneratePublicHashCommand, App\Service\BusinessCardGenerationService)
utilise en pratique APP_SECRET, pas OBFUSCATE_ID_SECRET.
Base de données¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
DATABASE_URL |
DSN de connexion Doctrine DBAL (config/packages/doctrine.yaml) |
Oui | mysql://user:password@127.0.0.1:3306/bcard?serverVersion=8.0.32&charset=utf8mb4 |
Messagerie¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
MAILER_DSN |
DSN Symfony Mailer d'envoi des e-mails (vérification de compte, notifications de commande, etc.). En production Docker, la valeur par défaut est smtp://mailer:1025 via le réseau infra-messaging. |
Non en production Docker, oui hors compose prod | smtp://utilisateur:motdepasse@smtp.example.com:587?encryption=tls&auth_mode=login |
MAILER_FROM_EMAIL |
Adresse d'expédition, injectée dans le service de mail (config/services.yaml) |
Oui | contact@example.com |
MAILER_FROM_NAME |
Nom d'expédition affiché | Oui | BCard |
En développement, l'image axllent/mailpit (voir compose.override.yaml) peut intercepter les
e-mails localement — sous réserve que ce fichier soit effectivement chargé, ce qui n'est
actuellement pas le cas avec docker compose up seul (voir Installation).
Authentification JWT¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
JWT_SECRET_KEY |
Chemin de la clé privée JWT (config/packages/lexik_jwt_authentication.yaml) |
Oui | %kernel.project_dir%/config/jwt/private.pem |
JWT_PUBLIC_KEY |
Chemin de la clé publique JWT | Oui | %kernel.project_dir%/config/jwt/public.pem |
JWT_PASSPHRASE |
Passphrase protégeant la clé privée, utilisée à sa génération et à chaque signature de jeton | Oui | une-passphrase-longue-et-aleatoire |
Voir Installation → Clés JWT pour la commande de génération.
Connexion sociale¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
OAUTH_GOOGLE_CLIENT_ID |
Identifiant client OAuth Google (config/packages/knpu_oauth2_client.yaml) |
Non (fonctionnalité optionnelle) | xxxxxxxxxx.apps.googleusercontent.com |
OAUTH_GOOGLE_CLIENT_SECRET |
Secret client OAuth Google | Non | GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxxxxxx |
OAUTH_FACEBOOK_CLIENT_ID |
Identifiant client OAuth Facebook | Non | 1234567890123456 |
OAUTH_FACEBOOK_CLIENT_SECRET |
Secret client OAuth Facebook | Non | abcdef1234567890abcdef1234567890 |
Protection anti-robot¶
Trois jeux de variables reCAPTCHA coexistent dans .env / .env.local. Une recherche dans
config/ et src/ (hors vendor/) montre que seuls deux sont réellement câblés à un
traitement, et un seul est réellement actif de bout en bout :
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
RECAPTCHA3_KEY |
Clé publique reCAPTCHA v3, lue par config/packages/karser_recaptcha3.yaml (bundle karser/karser-recaptcha3-bundle) |
Oui pour l'inscription | 6Lxxx-exemple |
RECAPTCHA3_SECRET |
Clé secrète reCAPTCHA v3, utilisée par le même bundle | Oui pour l'inscription | 6Lxxx-exemple |
RECAPTCHA_SITE_KEY |
Clé publique injectée dans App\Service\RecaptchaService (config/services.yaml) et transmise par UserController::register() à la vue sous la variable site_key |
Non | 6Lxxx-exemple |
RECAPTCHA_SECRET_KEY |
Clé secrète injectée au même service | Non | 6Lxxx-exemple |
GOOGLE_RECAPTCHA_SITE_KEY |
Présente dans .env.local |
Non | 6Lxxx-exemple |
Ce que fait réellement chaque jeu :
RECAPTCHA3_*est le mécanisme actif. Le formulaire d'inscription (src/Form/RegistrationFormType.php) embarque un champRecaptcha3Type, etUserController::register()rejette la soumission (message flash, retour au formulaire) siRecaptcha3Validatorrenvoie un score inférieur au seuil défini parUserController::RECAPTCHA_THRESHOLD(0.5).RECAPTCHA_SITE_KEY/RECAPTCHA_SECRET_KEYsont câblés mais inertes.RecaptchaService::getSiteKey()est bien appelé et sa valeur passée au templatehome/register.html.twig, mais le script qui l'utiliserait y est commenté ; côté serveur,RecaptchaService::getSecretKey()n'est appelé nulle part danssrc/. Ces deux variables ne produisent donc aucune vérification effective aujourd'hui.GOOGLE_RECAPTCHA_SITE_KEYest redondante et sans usage. Elle n'apparaît dans aucun fichier deconfig/nisrc/: ni lue par un service, ni référencée dans un gabarit.
Paiements¶
L'entité Payment reconnaît trois moyens de paiement, proposés comme choix équivalents dans
les formulaires de commande (src/Form/CheckoutType.php, src/Form/CompanyOrderType.php) :
credit_card, orange_money et cash_on_delivery. Seul credit_card aboutit à un
règlement réel, via Stripe. Les variables ci-dessous documentent donc deux mécanismes
distincts — Stripe (actif) et Orange Money (câblé au formulaire mais pas au règlement) — et non
deux options de paiement strictement équivalentes.
Stripe (credit_card)¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
STRIPE_SECRET_KEY |
Clé secrète de l'API Stripe, injectée dans App\Service\StripeService et App\Controller\StripeWebhookController (config/services.yaml) |
Oui pour le paiement par carte | sk_test_xxx |
STRIPE_PUBLIC_KEY |
Clé publique Stripe, exposée côté client | Oui pour le paiement par carte | pk_test_xxxxxxxxxxxxxxxxxxxxxxxx |
STRIPE_WEBHOOK_SECRET |
Secret de signature des webhooks Stripe, vérifié par StripeWebhookController |
Oui pour le paiement par carte | whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxx |
Orange Money (orange_money)¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
OM_CLIENT_ID |
Identifiant client de l'API Orange Money | — | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
OM_CLIENT_SECRET |
Secret client de l'API Orange Money | — | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
OM_MERCHANT_KEY |
Clé marchand Orange Money | — | 01a2b3c4 |
OM_API_BASE_URL |
URL de base de l'API Orange Money | — | https://exemple.orange-money.test |
OM_TOKEN_ENDPOINT |
Chemin de l'endpoint d'obtention de jeton | — | /exemple/oauth/token |
OM_PAYMENT_ENDPOINT |
Chemin de l'endpoint de paiement web | — | /exemple/webpayment |
OM_TRANSACTIONSTATUS_ENDPOINT |
Chemin de l'endpoint de statut de transaction | — | /exemple/transactionstatus |
OM_RETURN_URL |
URL de retour après paiement accepté | — | https://card.example.com/payment/orange/return |
OM_CANCEL_URL |
URL de retour après annulation | — | https://card.example.com/payment/orange/cancel |
OM_NOTIF_URL |
URL de notification (webhook) Orange Money | — | https://card.example.com/payment/orange/webhook |
Orange Money : proposé au formulaire, non implémenté au règlement
Aucune de ces variables OM_* n'apparaît dans src/ ni config/ : rien ne les lit. Dans
tous les points d'entrée où orange_money est traité comme méthode de paiement
(src/Controller/PaymentController.php, src/Controller/admin/CompanyPaymentController.php,
src/Controller/api/SubscriptionApiController.php), le code lève une exception ou renvoie
une réponse d'indisponibilité (« Paiement par Orange Money non disponible » /
« temporairement indisponible ») au lieu d'appeler une API Orange Money. Le moyen de
paiement est donc présent dans l'interface mais non fonctionnel à ce jour.
PHP et téléversements¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
PHP_MEMORY_LIMIT |
Destinée à la limite mémoire PHP | Non | 512M |
PHP_POST_MAX_SIZE |
Destinée à la taille maximale d'un corps de requête POST | Non | 75M |
PHP_UPLOAD_MAX_FILESIZE |
Destinée à la taille maximale d'un fichier téléversé | Non | 70M |
Variables non consommées par l'image Docker
Ces trois variables figurent dans .env.local avec un commentaire indiquant qu'elles
permettent des téléversements jusqu'à 70 Mo, mais aucun fichier .ini ni script de
l'image Docker ne les lit. La limite mémoire réellement appliquée en production provient
d'un fichier statique, docker/php/php-memory-limit.ini (valeur fixe, indépendante de
PHP_MEMORY_LIMIT) ; aucun réglage équivalent n'existe pour post_max_size ou
upload_max_filesize.
Variables sans usage¶
| Variable | Rôle | Obligatoire | Exemple |
|---|---|---|---|
KEYCLOAK_BASE_URL |
Destinée à l'URL de base d'un serveur Keycloak | Non | https://auth.example.com/ |
KEYCLOAK_REALM |
Destinée au royaume (realm) Keycloak | Non | bcard |
KEYCLOAK_CLIENT_ID |
Destinée à l'identifiant client OIDC | Non | bcard-app |
KEYCLOAK_CLIENT_SECRET |
Destinée au secret client OIDC | Non | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
KEYCLOAK_ADMIN_CLIENT_ID |
Destinée à l'identifiant client d'administration | Non | identifiant-fictif |
KEYCLOAK_ADMIN_CLIENT_SECRET |
Destinée au secret du client d'administration | Non | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
KEYCLOAK_PUBLIC_KEY |
Destinée à la clé publique de validation des jetons Keycloak | Non | EXEMPLE-CLE-PUBLIQUE-BASE64-NE-PAS-UTILISER |
SONAR_TOKEN |
Jeton d'authentification à une instance SonarQube, pour l'analyse de qualité de code | Non, hors application | sqa_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
Variables héritées
Les variables KEYCLOAK_* ne sont lues par aucun code de l'application.
Elles proviennent d'une piste d'authentification abandonnée et peuvent
être retirées de .env.local.
SONAR_TOKEN est d'une autre nature : il ne configure pas l'application mais l'outillage de
qualité de code (SonarQube, docker/sonarqube/), hors du périmètre de ce document. Il ne
relève pas de l'application Symfony elle-même et n'est lu par aucun code de src/ ni de
config/.