From 6cab9b7c0a527440a71c9faf6374338a967753ab Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Mon, 17 Aug 2026 14:09:36 +0100 Subject: [PATCH] feat(android): Gitea read path verified on device Against Zaki/pm_sync on Gitea 1.26.1, container uploaded through the web UI: HTTP 200 in 1079 ms, decrypted, cache written with the sha; the next Sync finds the same sha and skips the derivation entirely. That was the point of the ETag on the PHP endpoint and it survives the change of transport. One log line was lying: it announced If-None-Match, which is never sent to Gitea - the API does not know that header, and the comparison happens on the sha after reception. Announcing it sent you looking for a 304 from the server that will never come. It now says "known sha" on that transport. The plan records the two frictions met on the way, both already fixed: settings kept only after a successful decryption (so a wrong password lost the URL and the token every time), and the launch refresh being silent and using the password stored with the vault rather than the field. Co-Authored-By: Claude Opus 5 --- android-client/PLAN.md | 29 ++++++++++++++++++++++++----- mainApk.pas | 8 +++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/android-client/PLAN.md b/android-client/PLAN.md index fef0ed5..afbb162 100644 --- a/android-client/PLAN.md +++ b/android-client/PLAN.md @@ -431,7 +431,7 @@ purge. Ça ne l'est pas sur GitHub, où le chiffré part chez un tiers, répliqu et sauvegardé, avec un dépôt rendu public par erreur pour scénario du pire : attaquable hors ligne, par n'importe qui, pour toujours. -### État : la lecture est écrite, elle n'a jamais parlé à un vrai dépôt +### État : la lecture fonctionne contre un vrai dépôt — 2026-08-17 [PMA.SyncClient.pas](PMA.SyncClient.pas) parle les deux transports, **reconnus à l'URL** : `/api/v1/repos/` → Gitea, sinon l'endpoint PHP. Le PHP est gardé le @@ -446,10 +446,29 @@ retéléchargé, mais la dérivation de clé, elle, est bien épargnée. Le cham `ETag` du résultat porte le `sha` : l'appelant n'a pas à savoir lequel des deux transports lui répond. -**Rien de tout cela n'a encore atteint un vrai dépôt.** Il faut, dans cet ordre : -un dépôt privé, un fichier `vault-sync.json` publié par le poste Windows, un -jeton limité à ce dépôt, puis l'URL de contenu complète dans *Server settings*. -Tant que le poste publie sur `sync.php`, le téléphone continue de lire là. +**Vérifié sur téléphone** contre `Zaki/pm_sync` (Gitea 1.26.1), conteneur déposé +par l''interface web : + +``` +GET .../api/v1/repos/Zaki/pm_sync/contents/vault-sync.json + HTTP 200 in 1079 ms + 304: unchanged, vault served from cache + 4 entries, 2 in trash +``` + +Le premier appel télécharge, déchiffre et écrit le cache avec le `sha` ; le +second retrouve le même `sha` et épargne la dérivation. Le conteneur d''export +porte la corbeille, d''où les 2 en corbeille — un instantané de sync n''en aurait +aucune. + +Deux frottements rencontrés en chemin, tous deux corrigés : + +- les coordonnées n''étaient enregistrées qu''après un **déchiffrement** réussi, + donc un mot de passe faux faisait perdre l''URL et le jeton à chaque essai. Un + `200` prouve l''adresse et le jeton ; c''est là qu''elles sont retenues. +- le rafraîchissement au lancement est **silencieux** et utilise le mot de passe + rangé avec le coffre, pas le champ. Changer de conteneur demande donc un + *Sync* explicite au moins une fois. **Reste à faire** : le PUT (§4 seulement — la lecture n'écrit rien), la même bascule côté poste Windows en remplacement de WebDAV, et une purge périodique de diff --git a/mainApk.pas b/mainApk.pas index 34bae7f..058d08f 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -784,7 +784,13 @@ begin try try Log('GET ' + AUrl); - if FETag <> '' then Log(' If-None-Match: ' + FETag); + // NOMMER CE QUI EST REELLEMENT ENVOYE. Sur Gitea aucun If-None-Match ne + // part - l'API ne le connait pas, et la comparaison se fait sur le sha + // apres reception. Annoncer l'en-tete faisait chercher un 304 du serveur + // qui ne viendra jamais. + if FETag <> '' then + if LClient.IsGitea then Log(' known sha: ' + FETag) + else Log(' If-None-Match: ' + FETag); LSw := TStopwatch.StartNew; LRes := LClient.Fetch(FETag); LSw.Stop;