docs(android): Gitea as the transport, instead of hosting the endpoint
The Contents API maps term for term onto what is already written: it returns the file with its sha and demands that sha to write, answering 409 on a stale one - exactly the roles of the ETag and the 412. The desktop's bounded reread-remerge-repush loop would work unchanged. It also settles the one remaining obstacle: nothing to host, no certificate, outside access for free. Records the calls, and why the answer is a private Gitea rather than GitHub - git history never forgets, so every past snapshot stays readable under whatever sync password was current then. Survivable on your own disk, not on a third party's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -173,6 +173,7 @@ Par ordre de gravité, pas de taille.
|
|||||||
l'endpoint en HTTPS avec un vrai certificat. L'attribut est marqué
|
l'endpoint en HTTPS avec un vrai certificat. L'attribut est marqué
|
||||||
TEST-ONLY ; le jeton Bearer circule à chaque appel. **Gardé pour l'instant** :
|
TEST-ONLY ; le jeton Bearer circule à chaque appel. **Gardé pour l'instant** :
|
||||||
le retirer casserait l'essai local par `adb reverse`, qui passe en clair.
|
le retirer casserait l'essai local par `adb reverse`, qui passe en clair.
|
||||||
|
Voir §6 : passer par Gitea réglerait ce point sans rien héberger de plus.
|
||||||
3. ~~**`FLAG_SECURE`**~~ — **fait**, [PMA.ScreenGuard.pas](PMA.ScreenGuard.pas),
|
3. ~~**`FLAG_SECURE`**~~ — **fait**, [PMA.ScreenGuard.pas](PMA.ScreenGuard.pas),
|
||||||
**en Release seulement** : en debug le drapeau interdit aussi les captures
|
**en Release seulement** : en debug le drapeau interdit aussi les captures
|
||||||
d'écran de développement. Le vérifier demande donc une compilation Release.
|
d'écran de développement. Le vérifier demande donc une compilation Release.
|
||||||
@@ -328,6 +329,71 @@ tombstones ni génération d'uuid.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 6. Remplacer l'endpoint par un dépôt Gitea
|
||||||
|
|
||||||
|
Piste sérieuse pour le §2 item 2 : au lieu d'héberger `sync.php` en HTTPS avec
|
||||||
|
un certificat, déposer l'instantané chiffré dans un dépôt **privé** du Gitea
|
||||||
|
déjà en service. Plus rien à héberger, plus de certificat à renouveler, et
|
||||||
|
l'accès depuis l'extérieur vient gratuitement.
|
||||||
|
|
||||||
|
**La mécanique tombe terme à terme sur ce qui est déjà écrit.** L'API rend le
|
||||||
|
fichier avec son `sha` et exige ce même `sha` pour écrire ; un `sha` périmé
|
||||||
|
donne un **409**. C'est exactement le rôle de l'`ETag` et du **412** : la
|
||||||
|
boucle relire-refusionner-renvoyer du poste Windows, bornée à trois essais,
|
||||||
|
fonctionne sans changer de forme.
|
||||||
|
|
||||||
|
### Lire
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/v1/repos/{owner}/{repo}/contents/vault-sync.json?ref=main
|
||||||
|
Authorization: token <PAT>
|
||||||
|
```
|
||||||
|
|
||||||
|
Réponse : `{ "content": "<base64>", "encoding": "base64", "sha": "<blob sha>" }`.
|
||||||
|
Le `content` est le conteneur `pm-encrypted-export-v1`, déjà chiffré — Gitea ne
|
||||||
|
voit que des octets. Le `sha` prend la place de l'ETag, et se range avec le
|
||||||
|
coffre comme lui, puisqu'il décrit le clair détenu.
|
||||||
|
|
||||||
|
**404** = pas encore d'instantané, à traiter comme le 404 actuel : premier
|
||||||
|
envoi, pas une erreur.
|
||||||
|
|
||||||
|
### Écrire
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /api/v1/repos/{owner}/{repo}/contents/vault-sync.json
|
||||||
|
Authorization: token <PAT>
|
||||||
|
{ "message": "sync", "content": "<base64>", "sha": "<sha lu>",
|
||||||
|
"branch": "main" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Sans `sha`, Gitea refuse d'écraser un fichier existant ; avec un `sha` périmé
|
||||||
|
il répond **409**. C'est le `If-Match` qu'on avait dû implémenter à la main.
|
||||||
|
|
||||||
|
### Le jeton
|
||||||
|
|
||||||
|
Un jeton d'accès personnel **limité à ce dépôt**, droits `repo` en écriture. Il
|
||||||
|
remplace le jeton Bearer actuel et se range au même endroit — `settings.bin`,
|
||||||
|
scellé par la clé AES du Keystore, lisible sans authentification. Le
|
||||||
|
raisonnement ne change pas : il n'ouvre que du chiffré.
|
||||||
|
|
||||||
|
### Ce que ça coûte, et pourquoi pas GitHub
|
||||||
|
|
||||||
|
**L'historique de Git ne s'efface pas.** Chaque synchronisation est un commit,
|
||||||
|
et changer de mot de passe de sync n'enlève rien : toutes les versions
|
||||||
|
antérieures restent, chacune chiffrée sous le mot de passe de son époque. Un
|
||||||
|
ancien mot de passe faible resterait attaquable indéfiniment. Sur un serveur
|
||||||
|
qui écrase un fichier, ce problème n'existe pas.
|
||||||
|
|
||||||
|
C'est vivable sur **son propre** Gitea — le disque est à soi, l'historique se
|
||||||
|
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.
|
||||||
|
|
||||||
|
**À faire si on s'y engage** : un `PMA.SyncClient` qui parle cette API (le GET
|
||||||
|
authentifié existe déjà), la même chose côté poste Windows en remplacement de
|
||||||
|
WebDAV, et une purge périodique de l'historique — sans quoi le dépôt grossit
|
||||||
|
d'un instantané complet à chaque synchronisation, pièces jointes comprises.
|
||||||
|
|
||||||
## Ordre proposé
|
## Ordre proposé
|
||||||
|
|
||||||
1. **Vérifier §1 sur téléphone** — c'est ce qui valide le travail déjà fait, et
|
1. **Vérifier §1 sur téléphone** — c'est ce qui valide le travail déjà fait, et
|
||||||
|
|||||||
Reference in New Issue
Block a user