Commit graph

2 commits

Author SHA1 Message Date
Stephan Morand
4766c57dda Déclarer PHP 8.4 et alléger l'interpolation du compose
Le premier déploiement Coolify a échoué sur « Lazy loading proxies require
PHP 8.4 or higher ». La cause n'était pas dans le dépôt — Coolify avait
construit avec Nixpacks au lieu du compose — mais l'échec a mis au jour une
inexactitude réelle.

composer.json annonçait « php >=8.3 » alors que l'application exige 8.4 :
config.platform le pinçait déjà à 8.4.0, et les proxies de chargement paresseux
de Symfony ne fonctionnent pas en dessous. Toute chaîne de packaging qui lit la
contrainte pouvait donc choisir 8.3 en toute bonne foi, et échouer bien plus
loin sur un message sans rapport apparent. Contrainte remise à >=8.4.

compose.prod.yaml n'utilise plus `${VAR:?message}` : la forme arrête
correctement `docker compose`, mais le parseur de Coolify ne la comprend pas
partout. Le refus reste porté par docker/entrypoint.prod.sh, où il est testé et
où le message dit quoi faire plutôt que de citer un nom de variable.

Ajout au passage du garde-fou manquant : MARIADB_PASSWORD oubliée produisait
« mysql://tqslator:@database:… », un DSN valide au mot de passe vide, dont
l'échec remonte en erreur de droits d'accès sans jamais nommer la variable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 11:12:25 +02:00
Stephan Morand
9025c64c0b Socle complet de TQ-Slator : éditeur, API, CLI, administration
Système de gestion de traductions pensé en CMS headless : un back-office
pour ceux qui traduisent, une API pour ce qui consomme.

Architecture
- Symfony 7.4 / API Platform 4.3 / MariaDB 11.4, SPA React 19 servie en
  même origine — ce qui rend viable le cookie de session plutôt qu'un
  jeton en localStorage.
- Deux APIs séparées : Management (session ou clé) et Delivery
  (stateless, clé seule). Les fusionner ferait porter à chaque lecture de
  bundle le coût de la session.
- Stockage canonique en ICU MessageFormat, sérialisation par plateforme.
  Le format d'une plateforme ne contamine pas la base.
- Publication par releases immuables ; le déploiement est un déplacement
  de pointeur, donc le rollback aussi.
- Isolation multi-organisation par filtre Doctrine, avec un test
  d'architecture qui casse la CI si une entité échappe à l'invariant.

Éditeur, deux vues
- Par langue : source et cible, jamais douze colonnes. Grille virtualisée,
  saisie sans bouton « Enregistrer », panneau de contexte permanent.
- Par clé : une clé, toutes ses langues empilées et repliées. Répond à
  « ce libellé est-il prêt partout ? ».
- Mode Focus dans les deux : une file à vider, ⌘↵ pour enchaîner.
- Le traducteur ne voit jamais d'ICU : pastilles de variables, un champ
  par catégorie CLDR de la langue cible.

Administration
- Deux niveaux : projet (membres, clés API, plateformes) et organisation
  (annuaire des comptes, création de projets).
- Invitations par e-mail, jeton 256 bits stocké haché.
- Désactiver un compte coupe les sessions en cours, pas seulement les
  connexions suivantes.
- Les plateformes s'archivent ; ni elles ni les environnements ne se
  suppriment — la trace explique pourquoi telle clé existe.

CLI tqs
- PHAR autonome de 3 Mo, autoloader généré : le dépôt client ne dépend
  ni de Composer ni de la disponibilité de TQ-Slator.
- init / push / pull / status ; le sync est non destructif par défaut et
  son prune est scopé plateforme.

126 tests, PHPStan niveau 8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 08:16:05 +02:00