4ae845bc13
A probe every ten minutes compares the remote fingerprint to ours and lights an indicator. It does not pull: adopting on its own while someone is reading an entry would change it under their eyes. The user decides when. The body is downloaded anyway - Gitea's contents API cannot answer without it - but it is thrown away undecrypted: no derivation, no write, just a string comparison. The cost is network, not time or battery. It rides the idle timer rather than a second one. That timer already beats every 15 seconds for auto-lock; counting its beats costs an integer, where another timer costs an object, a lifecycle, and one more chance to forget it on shutdown. Two indicators, two colours, two gestures. Orange: things wait HERE and the repository does not know. Blue: the repository holds things we do not have. One dot for both would say "something is wrong" without saying what - and one is resolved by publishing, the other by fetching.
155 lines
7.3 KiB
Markdown
155 lines
7.3 KiB
Markdown
# Client Android — relecture et scénario d'essai
|
|
|
|
Relecture du 2026-08-22, avant d'ajouter la vérification de fond, les réglages
|
|
et les icônes. Le but n'était pas de tout relire mais de chercher là où cette
|
|
séance a montré que les défauts se logent : **les frontières entre fichiers,
|
|
les chemins d'erreur, et ce qui traverse les threads.**
|
|
|
|
---
|
|
|
|
## Ce que la relecture a trouvé
|
|
|
|
### 1. La fusion ne transportait pas les dossiers — CORRIGÉ
|
|
|
|
`MergeSnapshots` fondait `entries` et `tombstones`, pas `folders`. Un dossier
|
|
créé sur le téléphone — hors connexion, ou juste avant qu'un autre appareil
|
|
publie — disparaissait donc de la liste, **tandis que les entrées gardaient son
|
|
nom**. Elles se retrouvaient rangées dans un dossier que rien n'affiche :
|
|
introuvables sans qu'on le sache.
|
|
|
|
C'est exactement la panne contre laquelle `EnsureFolder` avait été écrit, et
|
|
elle est revenue par une autre porte. Le report est additif — on ne retire pas
|
|
un dossier du distant parce qu'il manque ici.
|
|
|
|
### 2. Le témoin d'attente n'existait que sur la liste — CORRIGÉ
|
|
|
|
Le point orange était posé sur le cadenas, qui n'existe que dans la liste. Or
|
|
après un verrouillage on atterrit sur l'accueil — précisément là où l'on décide
|
|
de synchroniser. Il est maintenant aussi sur *Sync*.
|
|
|
|
### 3. Trois routines ne libèrent pas l'indicateur d'occupation dans un `finally`
|
|
|
|
`SaveAttachment`, `RegisterLocal` et `LoginLocal` le font dans le chemin normal
|
|
**et** dans leur `except`, ce qui couvre tout ce qui descend d'`Exception`. Une
|
|
erreur d'un autre genre laisserait le voile en place.
|
|
|
|
**Non corrigé, et assumé** : le minuteur de 25 s le lève de toute façon, et
|
|
c'est son rôle. Le signaler ici vaut mieux que d'ajouter trois `finally` qui
|
|
donneraient l'illusion d'une garantie que seul le minuteur apporte.
|
|
|
|
### 4. `ParseJSONValue(...) as TJSONObject` fuit sur une entrée qui n'est pas un objet
|
|
|
|
Le transtypage lève avant l'affectation, donc la valeur analysée n'est jamais
|
|
libérée. Dix-sept occurrences. **Non corrigé** : n'arrive que sur un conteneur
|
|
corrompu, où l'on a de plus gros ennuis, et le processus est de toute façon en
|
|
train d'échouer bruyamment. À traiter le jour où l'on touche à ces fonctions.
|
|
|
|
### 5. Ce qui a été vérifié et va bien
|
|
|
|
- **Échappement HTML** : `esc()` couvre nom, sous-titre, initiale, URI d'icône,
|
|
libellés, valeurs, noms de dossiers, options de liste. Une entrée nommée
|
|
`<script>` ne s'exécute pas. C'était le risque réel — le coffre contient du
|
|
texte arbitraire et la page construit son HTML par `innerHTML`.
|
|
- **La file de commandes du pont** libère `sending` dans un `finally` : une
|
|
exception au retrait de l'iframe ne peut plus rendre l'interface muette.
|
|
- **Les états du `body`** (`typing`, `selecting`, `searching`, `on-list`,
|
|
`on-detail`, `is-busy`) ne portent le nom d'aucun élément — le piège qui
|
|
éteignait la page entière ne se répète nulle part.
|
|
|
|
---
|
|
|
|
## Scénario d'essai
|
|
|
|
À dérouler dans l'ordre. Chaque étape dit **ce qu'il faut voir**, pas seulement
|
|
ce qu'il faut faire : un test dont on ne sait pas ce qu'il doit produire ne
|
|
prouve rien.
|
|
|
|
### A. Enregistrement hors connexion — le plus important
|
|
|
|
1. Coffre ouvert, **couper les données** (mode avion).
|
|
2. Modifier un mot de passe → message *« saved here, not published yet »*, et
|
|
**point orange** sur le cadenas.
|
|
3. Verrouiller → le point doit être **sur le bouton Sync** de l'accueil.
|
|
4. **Fermer complètement l'application** (glisser depuis les récentes), rouvrir,
|
|
ouvrir le coffre → le point doit **être encore là**. C'est l'étape qui
|
|
éprouve la persistance du drapeau ; sans elle, le reste ne prouve rien.
|
|
5. Rétablir le réseau, *Sync* → *« Offline changes published »*, point éteint.
|
|
6. Sur le poste, synchroniser → la modification doit y être.
|
|
|
|
### B. La fusion, qui est le cœur du sujet
|
|
|
|
1. Téléphone **hors ligne**, modifier l'entrée **X**.
|
|
2. Sur le poste, modifier une **autre** entrée **Y**, synchroniser.
|
|
3. Téléphone en ligne, *Sync*.
|
|
4. **Les deux modifications doivent survivre.** Si une seule survit, c'est
|
|
l'arbitrage sur `updated_at` qu'il faut regarder.
|
|
5. Variante avec un **dossier créé hors connexion** sur le téléphone : il doit
|
|
apparaître dans la barre de dossiers après la fusion, et sur le poste après
|
|
sa synchronisation. C'est le défaut n° 1 ci-dessus.
|
|
|
|
### C. Notes multilignes
|
|
|
|
1. **+** → *Note* → zone de texte pleine largeur, *Site* et *Username* disparus.
|
|
2. Taper plusieurs lignes — la touche Entrée doit **insérer un saut**, pas
|
|
replier le clavier.
|
|
3. Enregistrer, rouvrir → les ruptures doivent être là **en lecture**.
|
|
4. Basculer *Login* → *Note* après avoir tapé : la saisie doit **survivre**.
|
|
5. Contre-épreuve : dans un champ d'une ligne (*Name*, code de déverrouillage),
|
|
Entrée doit toujours **replier le clavier**.
|
|
|
|
### D. Sélection et actions de liste
|
|
|
|
1. Appui long → barre contextuelle, compteur.
|
|
2. Deuxième ligne → compteur à 2.
|
|
3. **Dupliquer** → deux copies, suffixées *(copy)*.
|
|
4. **Supprimer** → confirmation en deux temps, puis les lignes disparaissent.
|
|
5. Touche **retour** pendant une sélection → elle s'annule **sans verrouiller**.
|
|
6. Sur le poste, synchroniser → les suppressions doivent y être répercutées.
|
|
|
|
### E. Le dépôt a bougé — témoin bleu
|
|
|
|
1. Coffre ouvert sur le téléphone, **le laisser ouvert**.
|
|
2. Sur le poste, modifier une entrée et synchroniser.
|
|
3. Attendre — la vérification bat toutes les **dix minutes**. Le journal doit
|
|
dire `remote has moved - sync to bring it in`, et un **point bleu** paraître
|
|
sur *Sync* et sur le cadenas.
|
|
4. **Rien ne doit changer à l'écran de soi-même.** Si l'entrée qu'on regarde se
|
|
met à jour toute seule, c'est que le sondage adopte au lieu de signaler.
|
|
5. *Sync* → le point bleu s'éteint.
|
|
6. Les deux ensemble : provoquer A puis E sans synchroniser → **orange et bleu
|
|
côte à côte**. Ils demandent deux gestes différents ; les confondre dirait
|
|
« quelque chose ne va pas » sans dire quoi.
|
|
|
|
### F. Pièces jointes
|
|
|
|
1. Ligne *Attachment* → flèche de téléchargement → le fichier apparaît dans
|
|
*Téléchargements* sous son nom, accents et arabe compris.
|
|
|
|
### G. Code de déverrouillage
|
|
|
|
1. Poser un code, ouvrir le coffre, fermer, rouvrir → il est demandé.
|
|
2. Code faux → *« Wrong unlock code »*, et **Open vault reste offert** (le
|
|
coffre n'est pas déclaré illisible).
|
|
3. Changer le code : ancien dans le premier champ, nouveau dans le second,
|
|
*Open vault* → *« Unlock code changed »*.
|
|
4. Contre-épreuve : taper n'importe quoi dans le champ du code puis *Sync* →
|
|
le code **ne doit pas changer**.
|
|
|
|
### H. Empaquetage
|
|
|
|
1. `build-apk.ps1 -Release -Keystore ... -Alias ...` → la sortie doit afficher
|
|
`Signer #1 certificate DN: CN=R Zakarya`. Si elle affiche `CN=Android
|
|
Debug`, la release ne vaut rien.
|
|
2. Elle ne s'installe pas d'elle-même, et c'est voulu.
|
|
|
|
---
|
|
|
|
## Ce qui n'est toujours pas éprouvé
|
|
|
|
- **Le chemin `-Release`** du script n'a jamais tourné.
|
|
- **§1 point 4** — l'invalidation de la clé par enrôlement d'une empreinte,
|
|
désamorcée par le code de déverrouillage tant qu'un code est posé.
|
|
- **`MergeSelfCheck`** tourne au démarrage en débogage et écrit
|
|
`merge selfcheck: the four rules hold` dans le journal. Personne ne l'a
|
|
encore lu.
|