Aller au contenu

Tests du système multicarburant

Les preuves sont séparées en trois niveaux : automatisé local, PostgreSQL réel et recette FiveM. Un test statique vert ne prouve ni le placement d’un prop, ni la physique d’une corde, ni les performances resmon.

Suite locale API

Depuis api/ :

..\.venv\Scripts\python.exe -m pytest tests/test_vehicle_energy_calculations.py tests/test_vehicle_energy_contracts.py tests/test_vehicle_energy_observations.py tests/test_vehicle_energy_multifuel.py tests/test_vehicle_energy_fuel_ports.py tests/test_vehicle_energy_migration.py tests/test_vehicle_energy_anchors.py tests/test_item_catalog.py -q
..\.venv\Scripts\ruff.exe check app tests
..\.venv\Scripts\alembic.exe heads
..\.venv\Scripts\alembic.exe history -r 0040_vehicle_lc_fuel:0043_energy_station_anchors
..\.venv\Scripts\alembic.exe upgrade 0040_vehicle_lc_fuel:0043_energy_station_anchors --sql

La suite doit vérifier :

  • matrice stricte Essence/Regular-Plus-Premium, Diesel/Diesel et EV/charges ;
  • composition ppm totalisant toujours 1 000 000 et vecteur 1 L Premium ;
  • facteurs 1,0/0,9/0,8/1,0 sans changement de handling ;
  • conversions litres/% et coûts 0/1/ceil ;
  • budget maximal et monotone pour les six produits ;
  • progression fondée sur le temps à 30/60/144 FPS ;
  • catalogue 26 chargeurs + 14 spéciaux, point ambigu désactivé, catégories 9/4/1 ;
  • identifiants seed invalides, dont 00 et index négatif, refusés ;
  • bidon 2–14 kg, produit unique et falsification fail-heavy ;
  • pack EV 8 kg/+10 points/usage unique ;
  • permissions, archives, anomalies, accès groupe et catalogue serveur ;
  • observations de pompe canonisées, fraîches, dédupliquées et limitées ;
  • rétention 90/365, hash d’export anonyme, purge et idempotence.
  • snapshot exact des 669 calibrations LC Fuel, Buffalo, hash unsigned et provenance ;
  • repères LC bone-relatif et Admin origine-relative, conversion bone→monde→local sur les 669 lignes, plusieurs headings et un véhicule incliné, validation finie/bornée, collision, RBAC, révision et audit override/reset.
  • parité stricte avec les huit ancres de vehicleCapBoneList() piné, chacune en première position disponible, Buffalo sans petrolcap|petroltank, séparation du fallback brut et anti-spam CAL-FUEL-PORT par modèle/connecteur.

Migration PostgreSQL réelle

Ancres et coordonnées natives — 0043

Depuis la racine, installer le runtime de test seulement et exécuter les vraies fonctions Lua :

.\.venv\Scripts\python.exe -m pip install -r fivem/tests/requirements-lua.txt
node --test fivem/tests/energy-native-coordinates.test.mjs
.\api\tests\postgres\run_vehicle_energy_0043.ps1 -PgBin 'C:\outils\pgsql\bin'

Adapter uniquement PgBin au répertoire des binaires PostgreSQL 16 officiels disponibles ; aucun téléchargement automatique ni service système n'est installé par le harnais. Le runner Lua utilise la .venv du projet ou MEDUSA_TEST_PYTHON, puis lupa.lua54 épinglé à 2.6. Sans VM, le test échoue explicitement et fournit la commande d'installation ; il n'est pas ignoré silencieusement.

T-FLOAT-001/002 et T-NAV-001 chargent les fichiers Lua de production, injectent les octets MessagePack Cfx cd0109/d1f553, contrôlent math.type aux natives, zéro, négatifs, fractionnaires, invalides, modes all/nearest/hidden, flags, rechargement, GPS F5/F10, TP et headings. Ils échouent sur la baseline entière. T-CATALOG-001 compare les 27 centres LC, 12 legacy, 26 chargeurs, 14 spéciaux, 16 candidats et la restauration F10 d'une station routière sans point.

T-ANCHORS-PG-001/002 utilise une base réellement migrée jusqu'à 0042. Les cas isolés vérifient : ajout des 16 ancres si absentes ; Paleto seule ancienne station déplacée ; témoins avant/après de toutes les tables ; protection des modifications, archives, identités, couverture et buckets ; sessions actives via les deux relations réelles ; atomicité en cas d'échec d'audit ; LSIA conservée ; idempotence et édition F10 postérieure. Dump et logs restent dans le dossier temporaire annoncé. Le harnais arrête seulement son cluster. Les anciens écarts alembic check doivent être présents avant 0043 aussi, avec schéma pg_dump --schema-only strictement inchangé (hors jeton aléatoire restrict de pg_dump). Un écart introduit par 0043 bloque le test ; le contrôle global n'est pas annoncé vert lorsque la dette historique existe.

Recette FiveM T-STATIONS-RUNTIME-001, distincte des tests locaux :

  1. Vérifier le head 0043 déployé et laisser le catalogue se synchroniser ; aucun plein actif lors d'un restart explicitement autorisé.
  2. Vérifier Pillbox sur la grande carte et GPS F5, au centre de la station attendue, sans déplacer la borne LC 05 ; faire de même à Paleto Bay et sur un échantillon des nouvelles zones.
  3. Tester Tous/Plus proche/Masqués, approche/éloignement minimap, reconnexion et reconstruction.
  4. Contrôler GPS/TP F10 station, véhicule et garage, y compris une coordonnée entière/zero ; refuser ces actions sans leurs permissions. Tester une borne tournée dans F10, puis restart/restauration.
  5. Vérifier pompes GTA, plein thermique, recharge et bidon/pack, sans nouveau prop routier ni doublon.

Sans session FiveM pilotable, cette recette reste ouverte : un test Lua sous espions ne prouve pas le rendu natif sur la carte du joueur.

Docker Desktop est requis. Depuis la racine :

.\api\tests\postgres\run_vehicle_energy_0040.ps1

Si le projet Compose isolé existe déjà et peut être supprimé avec son volume de test uniquement :

.\api\tests\postgres\run_vehicle_energy_0040.ps1 -Cleanup

Le script utilise exclusivement le projet medusa-energy-0040-test et la base medusa_energy_0040_test. Il :

  1. migre une base propre jusqu’à 0038 ;
  2. injecte la fixture historique 0039 ;
  3. applique 0039, exige la présence de son unique tarif historique gasoline/liter, puis ajoute les véhicules Essence, EV, Diesel, bateau et avion ;
  4. conserve un dump avant 0040 ;
  5. applique 0040 puis head une seconde fois ;
  6. exécute alembic check ;
  7. démarre l’API et laisse le recovery finaliser les anciennes sessions ;
  8. contrôle pourcentages, états de réservoir, six prix, 22 archives, 26 chargeurs, 14 spéciaux, matrice 108 point-produits, deux objets actifs et audit unique ;
  9. confirme le refus forward-only du downgrade 0040→0039 ;
  10. conserve dump et log API dans un dossier temporaire annoncé en sortie.

Une absence de Docker doit être enregistrée comme test non exécuté, jamais comme succès. Le test Alembic offline contrôle en plus l’ordre exact : retrait des anciennes contraintes, suppression du tarif historique, insertion des six nouveaux tarifs, puis recréation de toutes les contraintes remplacées. Ce contrôle statique prévient la régression d’ordre ; seul le harnais PostgreSQL ci-dessus prouve l’exécution réelle.

La migration corrective possède son propre harnais isolé :

.\api\tests\postgres\run_vehicle_energy_0041.ps1 -Cleanup

Il crée uniquement le projet medusa-energy-0041-test, rejoue 0038→fixtures 0039→fixtures 0040→0040, capture les empreintes JSON des données énergie représentatives, applique 0041 deux fois, exige 669 baselines LC protégées et la Buffalo exacte, rejoue aussi les assertions historiques 0040, puis teste les contraintes/triggers, alembic check, /ready et le refus forward-only du downgrade. Aucune base ou volume de production n’est ciblé.

La rotation conditionnelle possède également un harnais dédié :

.\api\tests\postgres\run_vehicle_energy_0042.ps1 -Cleanup

Il crée uniquement medusa-energy-0042-test, migre une base propre jusqu’à 0041, conserve un dump, tourne manuellement lc-charger-02, ajoute une installation custom et capture les empreintes des champs hors heading. Après 0042 et un second upgrade head, il exige 25 rotations station + point, la conservation de l’angle manuel, des autres données, des produits, des points spéciaux et archives, l’audit agrégé unique, alembic check, /ready et le refus forward-only du downgrade.

Suites FiveM et assets

Depuis la racine :

node fivem/tests/vehicle-energy.test.mjs
node fivem/tests/vehicle-energy-asset.test.mjs
node fivem/tests/vehicle-energy-fuel-ports.test.mjs
node fivem/tests/vehicle-energy-fuel-port-sync.test.mjs
node fivem/tests/vehicle-energy-physical-flow.test.mjs
node fivem/tests/lua-syntax.mjs
node --check "fivem/resources/[local]/medusa-energy/server.js"
node --check "fivem/resources/[mods]/lc_fuel/nui/panel.js"
& 'C:\Program Files\Git\bin\bash.exe' fivem/tests/managed-resource-sync.test.sh

Sur un environnement Windows qui interdit la création de sous-processus (spawn EPERM), exécuter les modules .mjs directement comme ci-dessus. Les contrôles couvrent manifests, ordre de démarrage, contrat façade sans writer, absence de mysql-async/commandes amont, denylist de writers, sept pompes GTA, seeds 26/14, hashes/provenance/licences, icônes, transparence NUI, F5/F7, blips, locales, native allowlist et absence de réseau/log dans une boucle frame. Le harnais managed-resource-sync crée un faux volume contenant des façades LC v1 et vérifie que la routine réelle de l’entrypoint les remplace par les copies embarquées, en supprimant aussi les fichiers runtime périmés. Sur Linux, l’exécuter directement avec sh fivem/tests/managed-resource-sync.test.sh.

Le hash attendu du pack EV approuvé est :

A4033486000BA853391CEC9A211407D7F7AE0AF339B31E3636388E316CCF1B5A

Administration web

Depuis admin/ :

npx playwright test tests/vehicle-energy.spec.js --reporter=line

Les tests vérifient 360/768/1280/1920 px, six tarifs, recherche et filtres par catégorie/produit, seed protégé, custom modifiable/supprimable, archives en lecture seule, masquage audit sans permission et affichage du message + code corrélé pour une erreur 409. Ajouter la suite complète avant livraison :

npx playwright test --reporter=line

Matrice de recette FiveM

Préflight

  1. Faire un backup nommé et tester la migration sur une copie PostgreSQL.
  2. Démarrer avec les flags maîtrisés et vérifier le head 0043_energy_station_anchors.
  3. Confirmer l’ordre medusa-vehicles, lc_utils, medusa-energy, lc_fuel, medusa-admin.
  4. Depuis un volume persistant contenant une ancienne façade, reconstruire/redémarrer puis vérifier dans les logs Mirroring bundled lc_utils resource, Mirroring bundled lc_fuel resource et le diagnostic LC version=2, physical=true, physicalProfileVersion=1. Les stations et blips doivent revenir sans suppression manuelle du volume.
  5. Vérifier le diagnostic writer=false/database=false/commands=false.
  6. Démarrer un writer factice ou LegacyFuel : l’énergie Medusa doit rester bloquée et nommer le conflit, sans arrêter arbitrairement la ressource tierce.
  7. Tester chaque flag séparément, à chaud puis après restart : global = aucune nouvelle opération ; consommation = aucun nouveau snapshot ; stations = aucun prop/blip/Alt/E ni session physique ; électrique = aucun chargeur, session EV ou achat de pack ; portable = aucun achat/remplissage/usage ; interfaces = aucun F5/F7/NUI/Alt/E. Une session durable antérieure doit encore se fermer ou être récupérée sans double débit.
  8. Pendant une session physique, arrêter puis redémarrer lc_fuel : la session doit se fermer au dernier volume confirmé, le focus/pistolet/câble/verrou doivent disparaître et aucune session ne doit pouvoir repartir avant la réinscription de la façade. Vérifier aussi qu’un motif de fermeture forgé côté client est journalisé comme player_cancelled, jamais comme motif système.

Produits et modes

Avec Essence, Diesel et EV, tester plein, quantité, pourcentage, budget, liquide et compte :

  • chaque combinaison autorisée livre sans dépasser la cible ;
  • chaque combinaison interdite échoue avant débit ;
  • l’aperçu affiche durée, brut, arrondi et source ;
  • cas bruts 0, 0,01, 0,99, 1,00 et 1,01 $ ;
  • changement de prix pendant une session : le snapshot de prix initial reste appliqué ;
  • double clic et retry : une session, un paiement et une livraison seulement.

Installations physiques

  • parcourir les sept modèles de pompe GTA : aucune ligne/cercle et aucune interaction fantôme ;
  • vérifier les 26 chargeurs un par un, leur heading/sol/collision et les deux rythmes ;
  • vérifier les 14 points spéciaux, le prop, les produits, le câble 14 m et les catégories ;
  • confirmer que le point porte-avions reste désactivé et que les quatre points exclus sont absents ;
  • tester Alt+clic et touche remappable, contour, focus et même action idempotente ;
  • tester moteur allumé, véhicule mobile, joueur assis, hors portée, mauvaise classe, sans clé, trappe absente et calibration : refus visible avant réservation ;
  • tester les huit ancres LC dans leur ordre piné, les quatre fallbacks carburant bruts, un override F10 et l’absence de fallback générique au centre/roue/moteur/châssis ;
  • ouvrir le panneau puis annuler : aucun pistolet, flexible, gel ou state bag ne doit apparaître ;
  • confirmer une réservation : le panneau doit se fermer, le focus revenir au jeu, l’animation LC se jouer une fois et le pistolet réseau apparaître dans la main avec son flexible ;
  • confirmer avec une réplication OneSync retardée de 200 ms à 5 s : le serveur doit créer le pistolet, publier son NetID après réservation et le client doit l’attendre sans en créer un second ; dès qu’OneSync lui en attribue le contrôle, il apparaît dans la main. Une substitution de NetID, une entité de mauvais type, un mauvais propriétaire ou un mauvais bucket doit toujours être refusé après le délai borné ;
  • marcher jusqu’à la trappe puis tester E et Alt : le tick est refusé avant attache, le pistolet se branche exactement sur la trappe sûre et la livraison commence seulement après l’état serveur attached, avec une petite progression transparente et sans focus ;
  • vérifier en 1280×720, 1920×1080, 2560×1440 et ultrawide que la progression thermique puis la progression électrique sont entièrement au-dessus du panneau « Trappe à carburant », tandis que ce panneau et le panneau LC complet conservent leur position ;
  • arrêter avec E ou Alt : la session est réglée au volume confirmé, le pistolet revient en main et le joueur doit le rendre à la pompe d’origine ; vérifier aussi le cleanup forcé après 60 secondes ;
  • répéter 20 prises/retours du pistolet avec sv_filterRequestControl=4, puis vérifier qu’aucun cycle ne produit vehicle_energy_equipment_entity_invalid et qu’aucun prop orphelin ne reste au sol ;
  • avec une Buffalo originale devant une pompe GTA native, vérifier que le pistolet est à l’extérieur de la carrosserie au point ancre LC + (-0,45 forward, -0,24 right, +0,35 up), relever l’ancre réellement sélectionnée, puis vérifier l’ouverture et la fin du ravitaillement sans CAL-FUEL-PORT ;
  • sur un modèle réellement sans point résoluble, déclencher rapidement E et Alt cinq fois : une seule notification CAL-FUEL-PORT doit apparaître pendant 2,5 secondes ; une autre pompe ou un autre modèle doit notifier immédiatement, et la même cible doit pouvoir notifier après expiration ;
  • répéter l’alignement sur un véhicule à trappe avant/arrière, gauche/droite, un véhicule incliné, un modèle avec rotation LC, un override Admin, un point seed/custom/spécial et un objet portable ;
  • dans F10, confirmer une calibration avec E, annuler avec Retour arrière/Échap, perdre/déplacer la cible puis reset LC ; comparer la source, les valeurs et la révision avec Medusa Admin web ;
  • après mutation, restart et reconnexion, vérifier le nouveau point sans appel réseau/log par frame.

Synchronisation des trappes

  1. Démarrer API et medusa-energy, attendre la diffusion initiale, puis connecter un joueur : le diagnostic trappes doit atteindre ready=669. Pendant la sélection, aucune notification vehicle_energy_player_unavailable ne doit apparaître. Après spawn, le diagnostic personalBootstrap.state doit atteindre ready, y compris après un restart client de la ressource.
  2. Pendant requesting ou degraded, utiliser une pompe ou un bidon : aucun panneau, aucune réservation et aucun CAL-FUEL-PORT ne doivent apparaître ; un seul message SYNC-FUEL-PORT localisé est visible pendant le cooldown.
  3. Reconnecter le joueur, puis redémarrer successivement le client de la ressource et medusa-energy. Dans chaque cas, attendre le nouvel état ready=669 sans F10 ni reconnexion supplémentaire.
  4. Avec le cache prêt, ravitailler une Buffalo devant une pompe GTA native. Vérifier que l’offset LC exact est appliqué depuis le bone et que proximité, marqueur, attache et F10 désignent le même point, puis l’ouverture et la clôture normales sans erreur de calibration.
  5. Modifier puis réinitialiser une calibration via F10 : la génération et l’empreinte changent, les clients reçoivent la diffusion, puis une demande à empreinte égale obtient unchanged sans les 669 lignes.
  6. Couper temporairement l’API catalogue, laisser les retries 250/500/1 000/2 000/4 000 ms atteindre degraded, puis restaurer l’API et relancer un événement de cycle de vie. Le cache valide ne doit jamais être vidé. Contrôler F8, console, réseau et resmon au repos et près d’une pompe : aucune requête, notification ou ligne de log par frame.
  7. Bloquer le bootstrap tarifaire puis ouvrir une pompe : aucun panneau à prix nul ne doit apparaître et SYNC-ENERGY-PRICES doit être visible. Restaurer l’API, attendre l’état ready, puis demander un plein : vérifier le prix unitaire, le coût brut et le débit au dollar supérieur. Cas de référence automatisé : 43,08 L à 1,55 $/L = 66,774 $ bruts et 67 $ débités.

Interruptions et concurrence

Déclencher pendant une session : annulation, éloignement, mort, entrée, disparition, explosion, déconnexion, restart client, restart medusa-energy, restart LC, panne API et panne banque. Attendu : dernier confirmé conservé, reliquat rendu, recovery unique, aucun prop/corde/freeze/focus/lock/dette.

Avec deux clients : même point simultané = un gagnant ; points distincts = deux sessions ; timeout sans progression = libération à 120 s. Rejouer des ticks dupliqués et hors ordre. Sous charge, simuler 100 véhicules et vérifier absence de ligne PNJ, seed dupliqué, double débit ou divergence state bag.

Pendant le cycle physique, le second client doit voir le même pistolet et un seul flexible dans le même routing bucket. Il ne doit rien voir après changement de bucket. Rejouer taken, attached, detached et returned en double ou hors ordre ; vérifier qu’aucune quantité, réservation, facturation, clôture ou suppression n’est exécutée deux fois.

Véhicules, objets et garages

  • voiture, moto, poids lourd, bateau, hélicoptère et avion consomment ; vélo/train non ;
  • répéter le même parcours à 30/60/144 FPS et comparer consommation, livraison et montant ;
  • moteur coupé = zéro, ralenti faible, seuils 20/10/5/0 sans spam, démarrage 0,9/1 % ;
  • bidon vide/partiel/plein, quatre produits thermiques, changement seulement vide, poids 2/8/14 kg ;
  • pack EV à 0/20/21 %, thermique, double clic et API coupée ; l’objet disparaît seulement au succès ;
  • pour le bidon puis le pack, répéter avec Utiliser dans l’inventaire et avec chacun des raccourcis rapides 1–5 : même UUID côté serveur, inventaire fermé, moteur coupé avant l’intention, aucun menu de station, niveau augmenté et objet diminué/supprimé une seule fois ;
  • placer côte à côte un véhicule compatible et un véhicule incompatible plus proche : le portable doit choisir le compatible ; répéter moteur allumé, véhicule plein, EV à 21 %, perte de contrôle et disparition pendant les 300 ms de synchronisation, sans item consommé ni prop/gel résiduel ;
  • ranger/sortir/restaurer à 0/5/50/100 %, mélange essence inclus, puis restart serveur ;
  • vérifier clés/doubles, U, moteur G, délai 60 s, handling, TAB coffre/boîte à gants, sièges, Alt extérieur, F5 et les trois compteurs.

Finitions R6 et boutique sans véhicule

  • à une pompe thermique sans véhicule, ouvrir par E puis acheter un bidon en liquide et depuis un compte ; recommencer avec un EV voisin incompatible : seul fuel_can_gasoline doit être proposé ;
  • à une borne électrique sans véhicule puis avec un thermique voisin, répéter pour ev_charge_pack ; aucun contrôle de réservoir, pistolet, corde, session, tick ou state bag ne doit apparaître ;
  • fermer avec la croix, Échap et un clic hors modal, puis réussir un achat : focus et interaction doivent être libérés ; après un refus fonds/inventaire/API, la modal reste réessayable ;
  • forger successivement point, station, coordonnées, modèle de pompe, bucket et item, s’éloigner, désactiver/archiver le point puis perdre le personnage : chaque cas doit refuser avant débit/item ;
  • double-cliquer la confirmation et vérifier une seule transaction, un seul item et 300 $ ou 500 $ débités exactement ; tester inventaire plein et fonds insuffisants sur cash puis compte ;
  • avec l’inventaire personnel de 15 kg, tenter un bidon plein avec moins de 14 kg libres et un pack avec moins de 8 kg libres : afficher le refus de poids, ne rien débiter et garder la modal réessayable. Répéter après avoir libéré assez de poids : achat, débit et instance unique ;
  • simuler successivement inventory_too_heavy, inventory_full, fonds insuffisants, timeout et panne réseau à travers l’export Cfx : le toast doit conserver le motif/code exact et le log serveur sa corrélation, sans corps de requête ni donnée bancaire ;
  • avec un véhicule réellement compatible, provoquer moteur allumé, mouvement, clé absente et trappe invalide : l’erreur normale doit rester visible et la boutique ne doit pas la remplacer ;
  • cliquer Alt dans le vide, sur un prop/Ped sans véhicule et sans candidat : aucun toast ni son. Refaire avec cible périmée, fournisseur/action en erreur et panne CEF : message et code restent visibles ;
  • contrôler les deux progressions aux quatre résolutions, la transparence NUI fermée et resmon : aucune boucle réseau/log par frame et budgets historiques inchangés.

Libération et progression portables R7

  • avec un bidon puis un pack, démarrer depuis Utiliser et chacun des raccourcis 1–5 ; contrôler le même UUID, 0 % au snapshot initial, une progression monotone fondée sur le confirmé serveur et 100 % uniquement lorsque la cible est réellement atteinte ;
  • pendant l’opération, essayer direction, accélération et entrée dans le véhicule : aucun contrôle n’est neutralisé et aucun FreezeEntityPosition(true) portable n’existe ; le moteur qui redémarre ou une vitesse supérieure à 0,55 m/s provoque une seule annulation avant le tick suivant ;
  • rejouer succès, refus initial, annulation, hors portée, mort, entrée véhicule, despawn/destruction, déconnexion et restarts medusa-energy/lc_fuel ; après chaque cas, tester immédiatement direction et accélération, puis vérifier zéro prop, barre, timer, focus, lock ou session orphelin ;
  • pour le bidon plein puis partiel, comparer exactement litres confirmés/restants à la session API ; injecter une révision dupliquée, ancienne ou avec confirmé en recul : l’affichage ne doit jamais régresser ni avancer de lui-même ;
  • pour un EV à 0 %, 20 % et 21 %, vérifier +10 points atomiques, un seul item consommé uniquement au succès et un final 100 % visible 650 ms au maximum 800 ms ; à 21 % ou avec un UUID falsifié, aucune consommation et aucune barre résiduelle ;
  • vérifier thermique et électrique en 1280×720, 1920×1080, 2560×1440 et ultrawide : rail dans la zone R6, textes français/anglais, racine transparente, aucune capture souris/clavier/manette, caméra ou radio ;
  • terminer par les achats R6, le cycle pistolet/corde, garages, F5, Alt, TAB, clés et les suites véhicules. Le gel positif reste attendu uniquement dans le cycle physique stationnaire.

Animations contextuelles MED-20260904-001

  • exécuter node --test tests/vehicle-energy-portable-ux.test.mjs depuis fivem/ : les profils essence/électrique, l’autorité de medusa:energy:session, l’idempotence, le timeout de 3 s, le cleanup exact et les invariants anti-gel R7 doivent être verts ; ce fichier fait aussi partie de npm test ;
  • avec fuel_can_gasoline, recommencer par Utiliser puis par chaque raccourci : avant la réponse serveur aucun geste ne doit partir ; après acceptation, vérifier orientation unique puis weapons@misc@jerrycan@ / fire pendant que le bidon reste attaché à la main. Répéter sur les personnages freemode homme et femme, avec une berline, un SUV et un véhicule bas : le bidon ne doit plus pendre à la hanche ni traverser visiblement le personnage ou la carrosserie ;
  • avec ev_charge_pack, répéter à 0 % puis 20 % et vérifier mini@repair / fixing_a_ped, le prop existant, la progression exacte et la consommation unique au succès ; à 21 %, sur thermique, avec UUID falsifié ou serveur refusant, aucun geste de recharge ne doit apparaître ;
  • pendant chaque geste, provoquer succès, annulation, mouvement, redémarrage moteur, éloignement, entrée dans le véhicule, mort, despawn, remplacement et restart. La tâche, le dictionnaire, le prop et la barre doivent disparaître une fois, sans gel ni commande neutralisée ;
  • en recette contrôlée seulement, remplacer chaque dictionnaire par une valeur invalide : après trois secondes au plus, seule l’animation manque ; progression, mutation serveur, erreur et cleanup restent fonctionnels, sans boucle F8 ni nouvelle requête réseau par frame.
  • après migration 0042, inspecter les 26 lc-charger-*, redémarrer client et serveur, tourner une borne témoin dans F10 puis redémarrer : l’angle manuel doit rester. Utiliser ensuite Restaurer : elle doit reprendre l’orientation canonique 0042, sans déplacement ni double rotation au spawn.

UI, carte et administration

  • modes de blips Tous/Plus proche/Masqués sur deux comptes et quatre catégories ;
  • T-RADAR-001 / AC-001, AC-005 (MED-20260905-001) : en mode Tous avec des stations actives, s'éloigner puis revenir à pied et en véhicule auprès de stations Route, Électrique, Aviation et Maritime. Les stations lointaines ne restent pas au bord du radar ; les proches réapparaissent avec leurs sprites/couleurs habituels. Les stations désactivées, archivées ou exclues par les feature flags restent absentes ;
  • T-MAP-001 / AC-002, AC-004 : loin des stations, ouvrir la carte pause, sélectionner une station distante et poser un waypoint. Les stations autorisées restent visibles sur la grande carte ; le waypoint et son itinéraire restent utilisables au retour en jeu ;
  • T-PREF-001 / AC-003 : passer de Tous à Plus proche (sélection existante par catégorie), puis Masqués et revenir à Tous. Reconnecter le compte puis effectuer un restart contrôlé de la ressource, hors session de ravitaillement et avec autorisation : la préférence persiste sans rétablir les blips lointains. Confirmer l'indépendance des préférences avec un second compte ;
  • T-HUD-001 / AC-004 : reprendre la recette HUD-007 en 16:9 et ultrawide, avec les zones sûres habituelles. Vérifier la flèche joueur, le nord, garages/banques/vêtements, le cadre de la minimap et le GPS F5 vers une station distante. Aucun de ces éléments ne doit être masqué par le correctif des stations ;
  • T-LOCAL-001 / AC-006 : exécuter npm --prefix fivem test, les contrôles contexte et MkDocs strict. Ces contrôles ne prouvent pas le rendu natif : consigner séparément les résultats FiveM de T-RADAR-001, T-MAP-001, T-PREF-001 et T-HUD-001 ;
  • GPS F5 vers le point compatible ; graphique conducteur via touche remappable sans slash ;
  • 100 cycles ouvrir/fermer/annuler/erreur/restart en 16:9 et ultrawide : aucun backdrop noir, caméra, radio, attaque ou conduite bloqués après fermeture ;
  • F10 : déplacer/rotate/disable/restore seed, créer/dupliquer/delete custom, GPS/TP/calibration/test ;
  • web : vérifier la mutation immédiatement, conflit de révision 409, RBAC des six permissions et audit avant/après/justification ;
  • déclencher les erreurs importantes en français puis anglais ; le message et son code sont visibles, jamais seulement dans F8.

Performance et gate finale

Mesurer resmon : éloigné ≤0,10 ms, proche ≤0,25 ms, session active ≤0,50 ms. Mesurer l’API p95 <500 ms. Confirmer par inspection qu’aucun appel réseau ou log n’est exécuté par frame.

L’activation globale nécessite un rapport signé couvrant AC-001 à AC-034, captures des placements, logs client/serveur, mesures 30/60/144 FPS, deux joueurs et non-régressions. Un commit, un push, le hook Portainer ou un serveur « démarré » ne remplace jamais cette recette.