From f994bfac30f4446bc95fa6f95861a05e1dfdf40d Mon Sep 17 00:00:00 2001 From: Pierre Martin Date: Tue, 14 Jul 2026 18:09:47 +0200 Subject: [PATCH] docs: record the list to content script seam (T1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the single storage key (revising the sibling task's "key = uid" seam, which had no way to transport the uid), the explicit ISO serialisation, and why the café fallback is display-only. Co-Authored-By: Claude Opus 4.8 --- docs/DECISIONS.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index e7cb2ea..dfa83f3 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -70,3 +70,49 @@ ici. Gravity Forms n'accepte `?input_X=` que si chaque champ est configuré « population dynamique » côté mairie (improbable). On remplit donc le **DOM par id** (ids confirmés dans `RECHERCHE.md`). + +## 2026-07-14 — [T1] Liste : couture page → content script + +La liste dépose l'événement choisi dans `storage.local` **puis** ouvre le +formulaire mairie (`extension/transfert.js`). Ce que la tâche sœur +(« formater les données pour le formulaire mairie ») doit lire : + +**Clé unique `evenement-en-attente`, PAS `evenement:`** (révise la couture +« clé = uid » annoncée par la tâche sœur, qui avait un trou). Le content script +s'exécute sur le site de la mairie : il n'a **aucun canal** pour apprendre un +`uid`, le fragment d'URL ayant été écarté (pas de pollution d'une URL tierce). +Une clé connue d'avance le rend lisible sans transporter quoi que ce soit. +- Pas de résidus : un seul slot, écrasé au clic suivant (le dernier clic gagne — + limite assumée, le geste réel est séquentiel et le formulaire est modéré). +- **On n'efface pas à la lecture** : le formulaire survit à un rechargement. +- Le dépôt est `await` **avant** `tabs.create` : sinon le content script peut + lire avant l'écriture. + +**`debut`/`fin` sérialisés en ISO 8601** (le payload n'est pas un `Event`). On ne +parie pas sur le structured clone : le contrat reste vrai quel que soit le +moteur, le content script réhydrate avec `new Date(iso)`. + +⚠️ **Si `journeeEntiere` est vrai, l'instant ISO n'est PAS significatif.** Une +`DTSTART;VALUE=DATE` est une date *flottante* (RFC 5545) : elle n'a pas de +fuseau. ical.js la matérialise à **minuit local**, donc l'ISO produit dépend de +la machine (`2026-07-10` devient `...T15:00:00Z` depuis Tokyo). Le consommateur +doit **tester `journeeEntiere` d'abord** et n'en lire que les composantes +**locales** (`getFullYear`/`getMonth`/`getDate`) — jamais l'heure, jamais une +conversion de fuseau. C'est pour la même raison que la liste formate les +journées entières **sans** `timeZone` (`presentation.js`) : forcer `Europe/Paris` +faisait glisser la date au jour précédent depuis Tokyo ou Auckland. + +**`TZ=Europe/Paris` sur `bun test` est PORTEUR — ne pas le retirer.** Le runner +de Bun force **`TZ=UTC`** quand `TZ` est absente (vérifié : `bun -e` lit le +fuseau système, le runner non). Sans le pin, les tests ne tournent donc pas dans +le fuseau des bénévoles. Corollaire pour l'écriture des tests : un fixture de +date flottante (journée entière, `DTSTART` sans `Z` ni `TZID`) se construit en +**composantes locales** (`new Date(2026, 6, 10)`), jamais en instant absolu +(`new Date("2026-07-10T00:00:00+02:00")`) — ce dernier n'est juste que sur une +machine à +02:00 et ment partout ailleurs. + +**Défaut café = affichage seulement ; `lieu` stocké brut** (`""` si absent). Les +deux avals du parseur ont chacun le leur : la liste affiche l'adresse pour ne pas +montrer une ligne vide (cas majoritaire), le content script décide s'il pose +**aussi** les coordonnées (`input_18`). Écrire l'adresse dans le payload +détruirait le signal « pas de lieu » dont il a besoin.