Distribuer l'outil comme un binaire Go autonome

serve.py supposait Python installé et une commande tapée dans un terminal
depuis le dossier du dépôt. L'objectif ici : poser l'exécutable et son
planning dans un dossier synchronisé, et les retrouver sur n'importe quelle
machine sans rien installer.

Le binaire embarque l'interface, expose les mêmes routes sur le même format,
et cherche son projets.json à côté de lui. Compilé avec CGO_ENABLED=0, il ne
dépend d'aucune bibliothèque système, pas même de la glibc ; build.sh produit
les cinq plateformes depuis une seule machine.

Le front est inchangé : les modules ES sont embarqués et servis tels quels,
et --dev les sert depuis le disque pour développer sans recompiler.

Deux ajustements dictés par le double-clic, où aucun drapeau ne peut être
passé : le port se cherche à partir de 8000 s'il est occupé, et le fichier de
données est résolu depuis l'exécutable et non depuis le répertoire courant.

La décision 3 est rectifiée au passage : elle affirmait à tort que la File
System Access API ne fonctionne pas depuis file://. Vérification faite, c'est
CORS sur les modules ES qui ferme cette voie, pas la sécurité de l'API.

serve.py est supprimé, le binaire l'ayant remplacé en usage réel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 16:48:59 +02:00
parent 6b15972e3b
commit 558d42f4cb
9 changed files with 940 additions and 259 deletions

View File

@@ -9,26 +9,63 @@ checklists. Une phase représente plusieurs semaines ou plusieurs mois de travai
## Démarrer
Récupérer le binaire de sa plateforme, le poser dans un dossier avec son planning, et le
lancer — par un double-clic ou en ligne de commande :
```sh
python3 serve.py
./frise
```
Puis ouvrir <http://localhost:8000>. Aucune installation, aucune dépendance, aucune étape de
compilation — ni côté Python (bibliothèque standard uniquement) ni côté navigateur (JavaScript
vanilla en modules ES natifs).
Le navigateur s'ouvre tout seul. **Rien à installer** : l'interface est embarquée dans
l'exécutable, qui ne dépend d'aucune bibliothèque système — pas même de la glibc. Il tourne tel
quel sur n'importe quelle distribution, et sur une machine sans Python ni Node.
Par défaut, le planning est le fichier `projets.json` **posé à côté de l'exécutable**. C'est ce
qui permet de déposer les deux dans un dossier synchronisé (Dropbox, Nextcloud, Syncthing) et de
retrouver son outil et ses données sur n'importe quelle machine.
```
📁 Mon dossier synchronisé
├── frise ← l'exécutable
└── projets.json ← le planning
```
Options :
```sh
python3 serve.py --port 9000 # changer le port
python3 serve.py --data data/exemple.json # ouvrir un autre fichier de données
./frise --port 9000 # imposer un port (sinon : le premier libre à partir de 8000)
./frise --data ~/plannings/2027.json # ouvrir un autre fichier
./frise --no-browser # ne pas ouvrir le navigateur
```
Au premier lancement, le planning est vide. Pour découvrir l'outil sur des données
réalistes :
Au premier lancement, le planning est vide et aucun fichier n'est créé tant qu'on n'a rien
saisi. Pour découvrir l'outil sur des données réalistes, copier `data/exemple.json` en
`projets.json` à côté de l'exécutable.
### Compiler soi-même
```sh
cp data/exemple.json data/projets.json
./build.sh # les cinq plateformes, dans dist/
./build.sh local # seulement la machine courante
```
Il faut [Go](https://go.dev) 1.22 ou plus récent, et rien d'autre : aucune dépendance externe,
aucun `vendor/`. Les binaires des trois systèmes se produisent depuis une seule machine, sans
intégration continue ni SDK tiers.
### Développer
```sh
go run . --dev
```
Le mode `--dev` sert `index.html`, `css/` et `js/` **depuis le disque** plutôt que depuis le
binaire : un simple rafraîchissement suffit à voir ses modifications, sans recompiler. Il lit
alors `data/projets.json`, comme avant.
```sh
go test ./... # le serveur
node --test tests/ # le modèle métier
```
## Prise en main
@@ -131,14 +168,20 @@ Tout tient dans un fichier JSON, `data/projets.json`, décrit dans
parlants (`site-web`, `cadrage`) plutôt que des UUID : il reste éditable à la main et lisible dans un
diff git.
À chaque sauvegarde, le serveur copie la version précédente dans `data/backups/`, horodatée.
À chaque sauvegarde, le serveur copie la version précédente dans un dossier `backups/` voisin du
planning, horodatée.
Le planning n'est **pas versionné** : `.gitignore` exclut `data/projets.json`, ce dépôt ne contenant
Le planning n'est **pas versionné** : `.gitignore` exclut `projets.json`, ce dépôt ne contenant
que le code. Seul `data/exemple.json` y figure, comme jeu de démonstration.
**Pour synchroniser plusieurs machines**, placer le dossier du projet dans un espace synchronisé
(Syncthing, Drive). L'option `--data` ne permet pas de pointer ailleurs : le serveur refuse un
fichier situé hors de son propre dossier.
**Pour synchroniser plusieurs machines**, déposer l'exécutable et son `projets.json` dans un
espace synchronisé. L'option `--data` accepte n'importe quel chemin, le planning peut donc aussi
vivre ailleurs que le binaire.
Deux frictions propres à ce mode de distribution, qui touchent tout exécutable et pas seulement
celui-ci : le bit d'exécution n'est pas toujours préservé par la synchronisation (`chmod +x frise`
une fois par machine), et un binaire non signé déclenche un avertissement au premier lancement —
SmartScreen sous Windows, Gatekeeper sous macOS.
L'outil ne gère pas les conflits — si deux machines modifient le planning en même temps, la dernière
écriture l'emporte. Les sauvegardes horodatées de `data/backups/` sont le filet de sécurité.
@@ -146,18 +189,21 @@ L'outil ne gère pas les conflits — si deux machines modifient le planning en
## Tests
```sh
node --test
node --test # la logique métier
go test ./... # le serveur
```
Couvre la logique métier : validation des dates, bornes d'un projet, calcul de dérive, génération des
identifiants, normalisation et filtrage des tags. Aucune dépendance, le lanceur de tests intégré à
Node suffit.
Côté navigateur : validation des dates, bornes d'un projet, calcul de dérive, génération des
identifiants, normalisation et filtrage des tags. Côté serveur : lecture et écriture du planning,
refus des corps invalides, rotation des sauvegardes, écriture atomique, résolution du chemin de
données. Aucune dépendance de part ni d'autre, les lanceurs intégrés à Node et à Go suffisent.
## Organisation du code
| Fichier | Rôle |
|---|---|
| `serve.py` | Sert les fichiers statiques, expose `GET`/`PUT` sur `/api/data`, écrit les sauvegardes |
| `main.go` | Sert l'interface embarquée, expose `GET`/`PUT` sur `/api/data`, écrit les sauvegardes |
| `build.sh` | Compile les binaires des cinq plateformes dans `dist/` |
| `js/model.js` | Données et règles métier : CRUD, validation, bornes, référence, dérive, tags |
| `js/storage.js` | Dialogue avec le serveur, sauvegarde debouncée, indicateur d'état |
| `js/timeline.js` | Rendu de la frise : échelle, couloirs, barres, jalons, pli/dépli |