# field-sync-gui GUI desktop sur-mesure Cosma terrain : ingest cartes SD GoPro → disque local + AWS S3. Stack : **Wails v2** (Go backend) + **Svelte+TS+Tailwind** (frontend) + **s5cmd** (uploads S3 parallèles). ## Pourquoi ? Workflow terrain actuel : SD → disque dur (1 par 1) → script rclone Windows → S3. Lent, série, peu de visibilité. `field-sync-gui` ingère **4 cartes SD en parallèle**, copie locale + sync S3 simultanés, progress live par slot, manifeste JSON par session, retry auto, dry-run dispo. Single binary par OS, 0 install. ## Binaries pré-buildés (Linux + Windows) Build host : `192.168.0.91` (Proxmox VM `openclaw`). ``` build/bin/field-sync-gui # Linux x86_64 (~7.7 MB) build/bin/field-sync-gui.exe # Windows x86_64 (~11 MB) ``` macOS : non cross-compilable depuis Linux sans osxcross. À builder sur un Mac (cf. section Build). ## Install runtime ### Pré-requis user (toutes OS) - **s5cmd** dans le PATH — uploads S3 (10× plus rapide que aws-cli) — https://github.com/peak/s5cmd/releases - **AWS credentials** : profile `cosma` (ou autre) configuré dans `~/.aws/credentials` ou `aws configure --profile cosma` ### Linux ```bash chmod +x field-sync-gui ./field-sync-gui ``` Pré-requis système : `libwebkit2gtk-4.1-0` (Ubuntu 24.04) ou `libwebkit2gtk-4.0-37` (Ubuntu ≤22). ### Windows Double-clic `field-sync-gui.exe`. WebView2 Runtime requis (préinstallé Win11, Edge récent). ### macOS Build local nécessaire — voir section Build. ## Configuration Au premier lancement, l'app charge `.env` depuis le répertoire courant ou variables d'env : ```env FIELD_SYNC_S3_BUCKET=cosma-field-data FIELD_SYNC_LOCAL_DEST=/data/cosma/sessions AWS_PROFILE=cosma FIELD_SYNC_CONCURRENCY=4 ``` `FIELD_SYNC_CONCURRENCY` = nombre de workers parallèles (défaut 4 = 1 par slot). ## Usage 1. Insère jusqu'à 4 cartes SD GoPro (USB readers ou slot natif) 2. Lance l'app → **↻ Rescan** détecte les cartes (auto-rescan toutes les 3s) 3. Vérifie les slots A/B/C/D affichés 4. (Optionnel) Coche **Dry-run** pour simuler sans toucher S3 5. Clique **▶ START INGEST** → 4 workers parallèles, progress live 6. À la fin → manifeste `//manifest.json` (sha256, S3 URI, status par fichier) 7. **✕ Cancel** pour interrompre proprement ## Format manifeste ```json { "sessionID": "cosma-20260427-2200", "entries": [ { "source": "/media/sd-A/DCIM/100GOPRO/GX010001.MP4", "localDest": "/data/cosma/sessions/cosma-20260427-2200/A/DCIM/100GOPRO/GX010001.MP4", "s3Path": "s3://cosma-field-data/cosma-20260427-2200/A/DCIM/100GOPRO/GX010001.MP4", "sha256": "abc123...", "bytes": 524288000, "status": "done" } ] } ``` Statuts : `local` | `s3` | `done` | `error` | `dry-run`. ## Build (depuis sources) ### Pré-requis - Go 1.22+ - Node 18+ - Wails CLI : `go install github.com/wailsapp/wails/v2/cmd/wails@latest` - Linux : `apt install libgtk-3-dev libwebkit2gtk-4.1-dev` - Windows cross-compile depuis Linux : `apt install gcc-mingw-w64-x86-64` - macOS : build sur un Mac (Xcode CLI tools) ### Commandes ```bash # Linux natif wails build -tags webkit2_41 -platform linux/amd64 # Windows depuis Linux CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ wails build -platform windows/amd64 # macOS (sur Mac) wails build -platform darwin/amd64 # Intel wails build -platform darwin/arm64 # Apple Silicon wails build -platform darwin/universal # Universal binary ``` Sortie dans `build/bin/`. ### Dev mode (hot reload) ```bash wails dev -tags webkit2_41 ``` ## Architecture ``` field-sync-gui/ ├── app.go # orchestrateur Wails (méthodes exposées au frontend) ├── main.go # entrypoint Wails ├── internal/ │ ├── config/ # .env loader │ ├── detect/ # gopsutil → SD cards detection │ ├── copier/ # CopyLocal (sha256 streaming) + CopyS3 (s5cmd) + Pool workers │ └── manifest/ # JSON atomic writer (lock + tmp+rename) ├── frontend/ │ ├── src/ │ │ ├── App.svelte # UI 4 slots + boutons + progress bars │ │ ├── style.css # Tailwind directives │ │ └── main.ts │ ├── tailwind.config.js │ └── postcss.config.js └── build/bin/ # binaires output ``` ## Méthodes Wails exposées | Méthode | Signature | Rôle | |---|---|---| | `ScanCards()` | `[]SDCard` | Détecte cartes SD (4 max) | | `StartIngest(slots)` | `[]SlotPayload → error` | Lance ingest 4 workers | | `CancelIngest()` | `error` | Cancel ctx en cours | | `GetSnapshot()` | `Snapshot` | État courant (slots + config) | | `SetDryRun(b)` | `bool` | Toggle dry-run | | `LoadConfig()` | `config.Config` | Recharge `.env` | Events Wails : `slot-update` (par worker), `session-done` (fin de session). ## Limitations connues / TODO - macOS : pas de build cross-OS depuis Linux (osxcross trop lourd, build sur Mac requis) - Windows : code-signing absent (warning SmartScreen au premier run) - Pas de mode resume après crash (TODO : reprendre manifeste partiel) - Pas de vérif ETag S3 post-upload (TODO : compare sha256 ↔ ETag pour fichiers <5GB) - Pas de hook Discord/Webhook fin de session (TODO) - Détection SD : heuristique (paths `/media/`, `/Volumes/`, opt `removable`) — peut nécessiter ajustement par OS ## Licence Internal Cosma — non distribué publiquement.