chore(android): section 5 - ten permissions down to three, no secrets in release

The manifest asked for fine and coarse location, camera, phone, phone state
and external storage - Delphi's defaults, none of them used. On a password
vault those are exactly the wrong signals: whoever reads the app's listing saw
a request for position and camera with no possible explanation. The list is
written by hand now.

A trap on the way: naming the substitution marker inside the comment that
explains its removal is enough to bring it back. The substitution is textual
and does not care that it lands in a comment.

The bench credentials are no longer compiled into a release - the local
include is debug-only. Verified in the binary in UTF-8 AND UTF-16: Delphi
stores strings as UTF-16, so an ASCII grep returned zero on both sides and
proved nothing.

The log leaves the home screen in release without leaving the application: a
1.5 s press on the status line brings it back. Nothing secret is in it, but a
permanent Log button is development noise, and diagnostics must stay reachable
for the day something goes wrong remotely.

And the Release configuration did not compile at all, which nobody knew: the
two self-checks had their declarations under IFDEF DEBUG and their bodies
outside. Invisible as long as one only ever builds Debug.

Signing is what remains, and the keystore password is the user's to hold.
This commit is contained in:
r-zakarya
2026-08-21 17:38:46 +01:00
parent eb9999c4b2
commit 0b0f1e3fcd
4 changed files with 119 additions and 7 deletions
+53 -6
View File
@@ -460,12 +460,59 @@ tombstones ni génération d'uuid.
## 5. Empaquetage
- Icône, nom d'application, numéro de version.
- Signature avec un magasin de clés dédié, pas la clé de débogage.
- Revue des permissions : `INTERNET` suffit.
- Retirer le journal de diagnostic de l'écran de déverrouillage, ou le mettre
derrière un appui long.
- Le mot de passe préchargé depuis `PMA.LocalConfig.inc` doit disparaître.
### Fait — 2026-08-21
- **Icône, nom, version** : « Coffre », `versionCode=1`, `versionName=1.0.0`.
- **Permissions : dix devenues trois.** Le manifeste demandait localisation
fine et grossière, caméra, téléphone, état du téléphone et stockage externe —
les défauts de Delphi, aucun utilisé. Sur un coffre à mots de passe ce sont
exactement les mauvais signaux : celui qui lit la fiche y voyait une demande
de position et d'appareil photo sans explication possible. La liste est
désormais **écrite à la main** dans le modèle : `INTERNET`, `USE_BIOMETRIC`,
`USE_FINGERPRINT`.
*Piège rencontré* : nommer le marqueur de substitution dans le commentaire qui
explique son retrait suffit à le faire revenir — la substitution est
textuelle et ne regarde pas si elle tombe dans un commentaire.
- **Les secrets de banc d'essai ne sont plus compilés en release.**
`PMA.LocalConfig.inc` n'est inclus qu'en débogage ; en release les deux
constantes valent la chaîne vide. Vérifié dans le binaire, en UTF-8 **et en
UTF-16** — Delphi range ses chaînes en UTF-16, et un grep ASCII rendait zéro
des deux côtés, donc ne prouvait rien :
```
debug jeton=1 motdepasse=1
release jeton=0 motdepasse=0
```
- **Le journal quitte l'écran d'accueil en release**, sans quitter
l'application : un appui long de 1,5 s sur la ligne d'état le ramène. Il ne
contient rien de secret — le jeton n'y figure que par empreinte — mais un
bouton « Log » permanent est du bruit de développement, et les diagnostics
doivent rester atteignables le jour où quelque chose cloche à distance.
- **La configuration Release compilait pas du tout**, et personne ne le savait :
les déclarations des deux auto-contrôles étaient sous `{$IFDEF DEBUG}`, leurs
**implémentations** non. La classe ne les déclarant plus, leurs corps
devenaient des membres inconnus. Invisible tant qu'on ne construit qu'en
débogage — ce qui a été le cas jusqu'ici.
### Reste : la signature
Un magasin de clés dédié, jamais la clé de débogage — celle-ci est partagée par
toutes les installations de Delphi, donc n'authentifie rien. Le mot de passe du
magasin appartient à l'utilisateur ; il n'a sa place ni ici ni dans le dépôt.
```
keytool -genkeypair -v -keystore pmserver-release.jks -alias pmserver -keyalg RSA -keysize 4096 -validity 10000
```
Puis, dans Delphi : *Project > Options > Provisioning*, configuration **Release**,
pointer le fichier `.jks` et l'alias. Le magasin se range **hors du dépôt** et
se sauvegarde ailleurs : le perdre interdit toute mise à jour de l'application
déjà installée, Android refusant une signature différente.
Une release se construit ensuite comme le débogage, en changeant la
configuration ; `android-client/build-apk.ps1` ne connaît que Debug pour
l'instant, et ne saura signer que le jour où le magasin existe.
---
+22
View File
@@ -955,6 +955,28 @@ var PM = {
if (show !== !document.getElementById('cfg').hidden) togglePanel('cfg');
},
/// LE JOURNAL SORT DE LA VUE EN RELEASE, sans disparaitre.
///
/// Il ne contient rien de secret - le jeton n'y figure que par empreinte -
/// mais un bouton "Log" en permanence sur l'ecran d'accueil d'un coffre a
/// mots de passe est du bruit de developpement, et il invite a lire ce qu'on
/// n'a pas a lire. Un appui long sur la ligne d'etat le ramene : les
/// diagnostics restent atteignables le jour ou quelque chose cloche a
/// distance, ce qui arrivera.
hideLog: function () {
document.getElementById('btnLog').hidden = true;
var st = document.getElementById('status'), timer = null;
st.addEventListener('touchstart', function () {
timer = setTimeout(function () {
document.getElementById('btnLog').hidden = false;
toast('Log available');
}, 1500);
});
['touchend', 'touchmove', 'touchcancel'].forEach(function (e) {
st.addEventListener(e, function () { clearTimeout(timer); });
});
},
/// Le coffre local est scelle sous un code : il faut le retaper pour
/// l'ouvrir. Delphi le sait en lisant le premier octet du cache.
/// TOUJOURS VISIBLE, seule l'indication change. Le cacher quand aucun code