Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 116 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,117 @@
# Codex instructions
# AGENTS.md — Loi du dépôt Thrustline

Ce fichier s'applique à tout le dépôt. Toute instruction plus locale doit être
compatible avec ces règles.

## Mission

Thrustline est une application Windows distribuable de gestion de compagnie
aérienne virtuelle pour Microsoft Flight Simulator. La refonte vise en priorité :

1. stabilité et récupération après erreur ;
2. sécurité d'un client distribué et modifiable ;
3. intégrité de l'économie et des données ;
4. compatibilité MSFS/SimConnect ;
5. maintenabilité, testabilité et mises à jour sûres.

## Sources de vérité

Lire avant tout travail :

1. `docs/CURRENT_STATE.md` — ce qui existe réellement ;
2. `docs/ROADMAP.md` — ordre des phases ;
3. le ticket concerné dans `docs/tickets/` ;
4. les documents spécialisés indiqués par le ticket.

Références permanentes :

- `docs/PRODUCT.md` — périmètre et règles produit ;
- `docs/ARCHITECTURE.md` — architecture cible et frontières ;
- `docs/SECURITY.md` — règles de sécurité ;
- `docs/QUALITY.md` — stratégie de tests et critères de qualité ;
- `docs/WORKFLOW.md` — cycle complet d'un ticket.

Le code et les migrations appliquées priment sur une documentation périmée.
Signaler et corriger les divergences dans le même ticket si elles sont directement
liées au changement.

## Règles de travail

- Implémenter un seul ticket à la fois.
- Ne pas anticiper les tickets futurs.
- Ne pas refactorer un système sans rapport.
- Respecter strictement `Allowed areas` et `Do not touch`.
- Préserver les modifications utilisateur non liées.
- Ne pas changer l'architecture sans ADR accepté.
- Éviter toute dépendance nouvelle si une solution simple existe déjà.
- Arrêter et demander une décision si une ambiguïté change le produit, la
sécurité, les données ou l'architecture.
- Un problème découvert hors périmètre devient un follow-up dans
`docs/KNOWN_ISSUES.md`, pas une modification opportuniste.

## Frontières techniques

- `app/` : Tauri v2, React, TypeScript, Vite, UI et orchestration cliente.
- `sim-bridge/` : .NET 8, SimConnect, télémétrie locale, REST/SignalR.
- `supabase/` : Auth, PostgreSQL, RLS, Realtime, RPC et Edge Functions.
- `legacy/` : lecture seule jusqu'à son archivage explicite.

Le desktop, le sidecar et MSFS sont des clients non fiables. Le serveur est
autoritaire pour l'argent, la propriété, la réputation, la progression et les
transitions sensibles. Aucun secret backend ne doit être livré au client.

## Qualité d'implémentation

- TypeScript strict, C# nullable et Rust sans avertissement introduit.
- Pages React minces ; règles métier et accès données hors des composants.
- Mutations sensibles via commande serveur transactionnelle et idempotente.
- Migrations Supabase append-only.
- Contrats partagés versionnés et consommateurs mis à jour ensemble.
- Erreurs actionnables pour l'utilisateur, détails techniques dans des logs
redigés.
- Aucun secret, JWT, donnée personnelle ou header d'authentification dans Git ou
les logs.

## Validation

Exécuter les contrôles proportionnés au ticket, puis consigner les résultats :

```powershell
# Frontend
Set-Location app
npm test
npm run build

# Sidecar
Set-Location ..\sim-bridge
dotnet build --configuration Release
dotnet test --configuration Release

# Tauri
Set-Location ..\app\src-tauri
cargo check --locked

# Invariants du dépôt
Set-Location ..\..
.\scripts\security-check.ps1
```

Les changements SQL exigent des tests locaux/staging d'isolation entre deux
utilisateurs. Les changements SimConnect exigent un replay de trace ou un test
manuel MSFS documenté. Ne jamais annoncer comme réussi un contrôle non exécuté.

## Fin de ticket

Un ticket n'est `Done` que si :

- ses critères d'acceptation sont satisfaits ;
- les tests automatisés pertinents passent ;
- sa vérification manuelle a été effectuée ou clairement déléguée ;
- les risques et limites sont consignés ;
- `docs/CURRENT_STATE.md` est mis à jour si l'état réel change ;
- le ticket contient son Completion Report ;
- aucun changement hors périmètre n'est inclus.

Le rapport final doit donner : résumé, fichiers modifiés, commandes exécutées,
résultats, vérification manuelle, risques, follow-ups et documentation mise à jour.

Read and follow `codex.md` at the repository root before making changes. It contains the project architecture, setup commands, conventions, safety constraints, and validation expectations for the active Thrustline implementation.
44 changes: 44 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Contribuer à Thrustline

Thrustline suit un workflow par tickets afin de protéger la stabilité, la
sécurité et l'intégrité des données.

## Avant de contribuer

1. Lire `AGENTS.md`.
2. Lire `docs/CURRENT_STATE.md`.
3. Choisir un ticket `Ready` dans `docs/tickets/`.
4. Ne pas commencer un ticket Draft ou Backlog sans l'affiner.

## Branche

Utiliser `type/TXXXX-description`, par exemple :

```text
foundation/T0001-baseline-reproductible
security/T0012-tests-rls
fix/T0042-reconnexion-simconnect
```

## Pull request

Une PR couvre un ticket. Elle contient :

- lien/ID du ticket ;
- résumé et fichiers principaux ;
- tests et commandes exécutés ;
- étapes de vérification manuelle ;
- impact sécurité/données ;
- risques, limites et rollback ;
- follow-ups hors périmètre.

## Qualité

Suivre `docs/QUALITY.md` et les validations du ticket. Ne pas masquer un test
échoué ni annoncer un contrôle non exécuté.

## Sécurité

Ne jamais ouvrir une issue publique contenant une faille exploitable, un secret ou
des données personnelles. Suivre `SECURITY.md`.

218 changes: 4 additions & 214 deletions PLAN.md
Original file line number Diff line number Diff line change
@@ -1,217 +1,7 @@
# Thrustline — Plan d'implementation
# Plan de refonte

> Plan de reference pour le rework complet. Branche `rework`.
> Voir `PROGRESS.md` pour l'etat d'avancement.
La roadmap active se trouve dans [`docs/ROADMAP.md`](docs/ROADMAP.md).

---
Ce fichier est conservé comme pointeur de compatibilité pour les anciens liens.
Ne pas maintenir une seconde roadmap ici.

## Stack cible

| Couche | Techno |
|---|---|
| Shell desktop | **Tauri v2** (Rust) — sidecar pour le sim-bridge |
| Frontend | **React 18 + TypeScript + Vite + Tailwind v4** |
| Sim Bridge | **C# .NET 8** — ASP.NET Minimal API + SignalR + SimConnect SDK |
| Auth + DB | **Supabase** (Postgres + RLS + Auth + Realtime) — single source of truth |
| IPC | **HTTP REST** (CRUD) + **SignalR** (real-time sim data) |

### Schema d'execution

```
Tauri shell (Rust)
└─ React + Vite (UI) ◄── REST + SignalR (localhost:5055) ──► sim-bridge.exe (C# .NET)
├─ SimConnect thread ──► MSFS 2024
├─ ASP.NET Minimal API
├─ SignalR Hub
└─ Supabase client ──► Supabase (cloud)
```

---

## Phase 1 — Fondations (TERMINE)

### 1.1 Nettoyage
- [x] Wipe legacy stack (Electron, Fastify, Prisma, node-simconnect)
- [x] Branche `rework` depuis main

### 1.2 Sim-bridge C# .NET 8
- [x] Scaffold projet ASP.NET Minimal API (`sim-bridge/`)
- [x] SimConnect abstraction : `ISimClient`, `SimData`, `FlightDetector`
- [x] `MockSimClient` — vol CDG→JFK en boucle 100s
- [x] `SimConnectWorker` — BackgroundService, SignalR broadcast
- [x] Services metier : `YieldService`, `CashflowService`, `MaintenanceService`
- [x] `LandingProcessor` — pipeline complète landing → Supabase writes
- [x] Cloud models (DTOs Supabase) : Company, Aircraft, Dispatch, Flight, Transaction, Reputation
- [x] `SupabaseClientProvider` — singleton lazy-init avec service_role key
- [x] Session store (userId reçu du front via POST /session)
- [x] Endpoints REST : GET /health, POST /session, DELETE /session
- [x] SignalR hub `/hubs/sim`

### 1.3 Schema Supabase
- [x] Migration `20260405120000_init.sql` — 10 tables, 7 enums, RLS policies, triggers

### 1.4 Frontend Tauri + React
- [x] Scaffold Tauri v2 + React 18 + TS + Vite + Tailwind v4
- [x] Auth Supabase (AuthContext, page Auth email/password)
- [x] Onboarding (creation compagnie)
- [x] CompanyContext (state partage + Supabase Realtime)
- [x] SimContext + useSimStream (client SignalR)
- [x] Layout + Sidebar + SimStatusBadge + LiveFlightBar
- [x] Sidecar spawn dans lib.rs (Tauri)

---

## Phase 2 — Pages UI (TERMINE)

- [x] **Dashboard** — KPIs (capital, sim status, last landing), flight in progress
- [x] **Flights** — historique complet avec table (route, distance, duration, fuel, revenue, net)
- [x] **Fleet** — cards avions avec health bar, cycles/hours, add form, set active
- [x] **Sortie de flotte** — vente courtier des avions possedes et restitution anticipee payante des credit-bails
- [x] **Dispatch** — liste missions avec badges status, actions (dispatch → flying → completed), new dispatch form
- [x] **Crew** — table avec rank/status, aircraft assignment, hire form avec random names
- [x] **Finances** — summary cards, cashflow chart (recharts), loans, transaction ledger
- [x] **Settings** — health check sim-bridge

---

## Phase 3 — Infra technique (TERMINE)

- [x] **NativeSimConnectClient** — `#if HAS_SIMCONNECT`, thread Win32 message pump, 10 SimVars, retry auto 5s
- [x] **Sidecar auto-spawn** — `scripts/build-sidecar.ps1`, lib.rs avec child management + kill on close
- [x] **Supabase Realtime** — CompanyContext subscribe aux UPDATE sur companies, capital live
- [x] **useRealtimeTable** — hook generique INSERT/UPDATE/DELETE
- [x] **waitForBridge()** — retry helper pour attendre le sidecar au demarrage

---

## Phase 4 — Features majeures (TERMINE)

### 4.1 Base aeroports (ICAO)
- [x] Fichier statique `airports.ts` (3232 aeroports, ICAO 4-lettres, large+medium, scheduled_service)
- Source : OurAirports CSV auto-parse
- Champs : `icao, iata, name, city, country, lat, lon, elevation_ft`
- Index `airportByIcao` pour lookup O(1)
- [x] Composant `AirportPicker.tsx` — input autocomplete (recherche ICAO, IATA, nom, ville)
- Max 8 resultats, priorite exact > startsWith > contains
- Keyboard navigation (Arrow, Enter, Escape)
- Affiche nom + ville sous le code selectionne
- [x] Branche dans Dispatch (origin/dest) et Onboarding (hub)

### 4.2 Base avions (types + contraintes)
- [x] Fichier statique `aircraftTypes.ts` (36 types MSFS courants)
- Airbus (A319→A388), Boeing (B737→B78X), Regional (CRJ, Embraer), Turboprops (ATR, Dash8), GA (C172, TBM9, PC12)
- Champs : `icaoType, name, manufacturer, rangeNm, maxPaxEco, maxPaxBiz, fuelCapacityGal, ceilingFt, cruiseSpeedKts`
- [x] Composant `AircraftTypePicker.tsx` — dropdown searchable avec specs
- [x] Validation Dispatch : warning si distance route > range avion (haversine)
- [x] Auto-fill pax eco/biz depuis le type selectionne
- [x] Integration Fleet : remplacement input icao_type

### 4.3 Carte live (Flight Map)
- [x] Package `react-leaflet@4` + `leaflet@1` (compatible React 18)
- [x] Composant `FlightMap.tsx` reutilisable (props: origin, dest, waypoints, aircraft)
- Marqueur avion anime avec rotation heading (SVG)
- Polyline route (dashed, couleur brand cyan)
- Marqueurs aeroports avec labels ICAO permanents
- Auto-fit bounds sur origin+dest
- [x] Integration Dashboard (carte 260px, non-interactive, hub + avion live)
- [x] Integration Dispatch (carte 180px dans le formulaire, route quand origin+dest)
- [x] Dark map tiles CartoDB dark_matter + Leaflet CSS overrides

### 4.4 Integration SimBrief
- [x] Champ `simbrief_username` dans Settings (sauvegarde Supabase)
- [x] Bouton "Generate on SimBrief" dans Dispatch (ouvre URL pre-remplie)
- [x] Bouton "Import OFP" — poll API toutes les 5s (max 60s)
- [x] Lib `simbrief.ts` — fetch + parse OFP (route, fuel, weights, times, navlog)
- [x] Modal OFP glassmorphism avec sections (Route, Fuel, Weights, Times, Aircraft)
- [x] Bouton "Apply to dispatch" dans OFP Modal → pre-remplit le formulaire
- [x] Trace route waypoints navlog sur la carte
- [x] Helper `geo.ts` — haversine distance en nautical miles

---

## Phase 5 — Game Mechanics (EN COURS)

Ordre d'implementation : 5.3 → 5.2 → 5.4 → 5.1
(base economique d'abord, puis emprunts, puis reputation, puis evenements)

### 5.3 Salaires & charges mensuelles (PREMIER)
- [ ] **Timer de session** : a chaque lancement de l'app, calculer le nombre de "mois de jeu" ecoules depuis le dernier calcul
- Stocker `last_billing_at` dans `companies` (nouvelle colonne)
- Au login, si > 30 jours ecoules → declencher un cycle de facturation
- Endpoint sim-bridge `POST /billing/cycle` ou logique frontend-only via Supabase
- [ ] **Deduction salaires crew** : pour chaque crew_member, deduire `salary_mo` du capital
- INSERT transaction (type=salary, amount=-salary_mo, description="Salary — {name}")
- UPDATE companies.capital -= total_salaries
- [ ] **Deduction lease avions** : pour chaque aircraft ownership=leased, deduire `lease_cost_mo`
- INSERT transaction (type=lease, amount=-lease_cost_mo, description="Lease — {name}")
- UPDATE companies.capital -= total_leases
- [ ] **UI Finances** : section "Monthly charges" avec breakdown salaires + leases
- [ ] **Notification** : toast/banner au login montrant le recap des charges deduites

### 5.2 Systeme de loans
- [ ] **Formulaire emprunt** dans Finances : montant, duree (mois), taux d'interet fixe
- Table `loans` existe deja : amount, interest_rate, monthly_payment, remaining, active
- INSERT loan + UPDATE capital += montant emprunte
- [ ] **Remboursement mensuel** : dans le cycle de facturation (5.3), deduire `monthly_payment` de chaque loan actif
- INSERT transaction (type=loan_payment, amount=-monthly_payment)
- UPDATE loans.remaining -= (monthly_payment - interet)
- Si remaining <= 0 → UPDATE loans.active = false
- [ ] **UI Finances** : liste des emprunts actifs, progress bar remboursement, historique
- [ ] **Validation** : plafond d'emprunt (ex: max 3x le capital actuel), refus si capital < 0

### 5.4 Reputation avancee
- [ ] **Score par route** (table `reputations` existe deja) :
- Deja ajuste par qualite d'atterrissage dans LandingProcessor
- Ajouter : bonus si vol regulier (>3 vols sur la meme route), malus si route abandonnee (>30 jours sans vol)
- [ ] **Impact sur la demande pax** : dans YieldService, le `repMult` est deja calcule (0.5 + score/100)
- Ajouter : affichage du multiplicateur dans Dispatch (ex: "Demand: 1.2x" a cote de la route)
- Couleur verte si >1x, rouge si <1x
- [ ] **UI reputation** : nouvelle section dans Dashboard ou page dediee
- Liste des routes avec score, nombre de vols, tendance (↑↓)
- Badge "Premium route" si score > 80
- [ ] **Routes premium** : routes a haute reputation (>80) generent un bonus +20% de revenue
- Modifier YieldService pour ajouter le premium bonus

### 5.1 Evenements aleatoires (DERNIER)
- [ ] **GameEvent system** : table `game_events` existe deja (type, scope, multiplier, active, expires_at)
- Types : fuel_spike (+30% fuel cost), fuel_drop (-20%), weather (annule des vols), tourism_boom (+50% pax revenue sur une route), strike (-100% revenue temporaire), mechanical (-health sur un avion)
- [ ] **Generateur d'evenements** : a chaque cycle mensuel, 30% de chance de generer 1-2 evenements
- Duree : 1-7 jours (expires_at)
- Scope : global (toutes routes), route (une route specifique), aircraft (un avion specifique)
- [ ] **Modificateurs dans les services** :
- CashflowService : deja supporte `fuelPriceMultiplier` et `landingFeeMultiplier`
- YieldService : ajouter `demandMultiplier` depuis game_events
- [ ] **UI notifications** : banner en haut du Dashboard avec les evenements actifs
- Icone + couleur selon type (rouge=strike, vert=tourism_boom, orange=fuel_spike)
- Compte a rebours avant expiration
- [ ] **UI evenements** : liste dans Settings ou page dediee avec historique

---

## Phase 6 — Flight Scheduling (MVP TERMINE)

- [x] Generateur de rotations continues par avion, sans teleport
- [x] Contraintes : nombre de vols, nombre de rotations, heures totales, duree max par vol, range avion
- [x] Retour optionnel au hub et avertissements quand les contraintes sont impossibles
- [x] Position persistante de chaque avion (`current_airport_icao`)
- [x] Tables `schedules`, `schedule_rotations`, `schedule_legs` avec RLS
- [x] Page Schedule : configuration, preview carte/liste, sauvegarde et progression
- [x] Un seul leg disponible a la fois, transforme en dispatch a la demande
- [x] LandingProcessor : complete le leg, deplace l'avion et debloque le suivant
- [x] Garde-fous DB : un planning actif et un vol flying par avion, validation de position
- [x] Horaires reels par leg et temps au sol configurable
- [x] Equipage fixe captain + first officer + PNC selon le type d'avion par schedule passif, avec garde-fous de rang et de conflit
- [x] Vols passifs avec progression, economie/usure, position carte et rattrapage au prochain lancement
- [x] Vitesse des operations passives configurable (1x, 6x, 12x ou 24x)
- [x] Economie passive basee sur la demande passagers, la capacite et les couts propres au type d'avion
- [ ] Vue calendrier/timeline multi-avions, overnight et maintenance planifiee

---

## Phase 7 — Polish & Deploy (A VENIR)

- [ ] CI/CD (GitHub Actions : build + test)
- [ ] `supabase gen types typescript` — types auto-generes
- [ ] Installeur Windows (NSIS/MSI via Tauri)
- [ ] Virtual Airlines (compagnie partagee, invitations, roles)
- [ ] Stripe freemium → Pro
Loading
Loading