# TRAIL DPS 4.2.2 - OVH position.php, latest et trace

## Objet du lot

Ce lot adapte le backend OVH sans toucher aux applications Android/iOS.

Il fait évoluer le flux d'ingestion `/api/tracking/position.php` afin que chaque position mobile valide :

1. continue d'être insérée dans `tracking_positions`,
2. alimente `tracking_positions_latest`,
3. alimente `tracking_positions_trace` selon compactage,
4. permette à `latest_positions.php` de lire la table optimisée `tracking_positions_latest`,
5. ajoute l'endpoint `trace.php` pour récupérer les traces compactées.

## Fichiers créés

- `SRC/Tracking/TrackingPositionProjectionService.php`
- `public/api/tracking/trace.php`
- `docs/TRAIL_DPS_4_2_2_OVH_POSITION_LATEST_TRACE.md`
- `sql/lot_4_2_2_validation_after_ftp.sql`

## Fichiers modifiés

- `public/api/tracking/position.php`
- `public/api/tracking/latest_positions.php`

## Règles métier appliquées

### tracking_positions

Table brute conservée.

Elle reçoit toutes les positions non-dupliquées validées.

### tracking_positions_latest

Projection courante.

Une ligne par :

- event_remote_id,
- place_instance_id,
- binding_id.

Mise à jour si :

- première position,
- intervalle >= 60 secondes,
- retour après gap >= 10 minutes,
- précision nettement meilleure,
- changement d'actor_type.

### tracking_positions_trace

Trace compacte.

Insertion si :

- premier point,
- nouveau bucket de 5 minutes,
- déplacement supérieur ou égal à 100 mètres,
- reprise après interruption >= 10 minutes.

Fenêtre de lecture recommandée : 3 heures.

Conservation serveur prévue : 7 jours via futur lot purge/cron.

## Procédure FTP

Déposer les fichiers du ZIP en respectant l'arborescence à la racine du dossier OVH existant.

Remplacer :

- `public/api/tracking/position.php`
- `public/api/tracking/latest_positions.php`

Ajouter :

- `SRC/Tracking/TrackingPositionProjectionService.php`
- `public/api/tracking/trace.php`
- `docs/TRAIL_DPS_4_2_2_OVH_POSITION_LATEST_TRACE.md`
- `sql/lot_4_2_2_validation_after_ftp.sql`

Ne pas modifier :

- `tracking_config/env.php`
- les fichiers licence,
- les fichiers SMS,
- les applications Android/iOS.

## Requêtes SQL manuelles

Aucune migration destructive n'est nécessaire pour ce lot si le lot 4.2.1 a bien été appliqué.

Après FTP, exécuter dans phpMyAdmin :

- base : `synoluidpstrack`
- onglet : `SQL`
- fichier : `sql/lot_4_2_2_validation_after_ftp.sql`

## Procédure de test rapide

1. Laisser un téléphone Android ou iOS envoyer une position.
2. Vérifier que `tracking_positions` reçoit la position brute.
3. Vérifier que `tracking_positions_latest` contient une seule ligne par binding.
4. Vérifier que `tracking_positions_trace` reçoit un point selon les règles de compactage.
5. Tester `latest_positions.php` avec les paramètres existants PLACE.
6. Tester `trace.php` sur le même événement.

## Endpoints concernés

### latest_positions.php

Lit désormais `tracking_positions_latest` et non plus `tracking_positions`.

Paramètres identiques :

- place_instance_id
- event_remote_id
- event_local_id
- run_id optionnel
- actor_types optionnel
- limit optionnel

### trace.php

Nouveau endpoint.

Paramètres :

- place_instance_id obligatoire
- event_remote_id obligatoire
- event_local_id obligatoire
- run_id optionnel
- binding_id optionnel
- device_id optionnel
- actor_types optionnel
- hours optionnel, défaut 3, maximum 24
- limit optionnel, défaut 5000, maximum 10000

## Critères de recette

- `position.php` répond `ok: true` après une position mobile.
- La réponse contient `latest_projection`.
- La réponse contient `trace_projection`.
- `tracking_positions_latest` ne grossit pas à chaque position.
- `latest_positions.php` renvoie `source_table: tracking_positions_latest`.
- `trace.php` renvoie `source_table: tracking_positions_trace`.
- Aucun changement n'est nécessaire côté Android/iOS.

## Point de vigilance

La table `tracking_positions_trace` dispose d'une clé unique par bucket de trace. Les points de déplacement > 100 m utilisent l'horodatage serveur comme bucket pour permettre une insertion immédiate distincte du bucket 5 minutes.
