Watch-Sync zu minerva durch Android-Cleartext-Policy blockiert (gelöst via HTTPS app.doctate.de) #7

Closed
opened 2026-05-30 14:10:50 +02:00 by Brummel · 0 comments
Owner

Beobachtung

Die Watch-App (brummel-minerva) schien lokal mit dem Dev-Server verbunden. Tatsächlich waren das nur lokale Altdaten (ein installDebug-Update behält das App-Datenverzeichnis). Der echte Defekt: Der SyncWorkerLoop erreichte minerva überhaupt nicht. Logcat:

W SyncWorkerLoop: transient: network: CLEARTEXT communication to minerva.lan
  not permitted by network security policy → backoff 60000ms

Der Sync war damit komplett blockiert — Kernfunktionalität für die Alpha-Tester (BLOCKER-Schwere).

Ursache

Seit Android 9 (API 28) ist unverschlüsseltes HTTP standardmäßig blockiert. app/src/main/res/xml/network_security_config.xml erlaubt Cleartext nur für 10.0.2.2 (Emulator) und 192.168.178.27 (Dev-Laptop) — nicht für minerva.lan. Das brummel-minerva-Profil zeigte aber auf http://minerva.lan:3000 → jeder Request wurde von der Policy verworfen.

Strukturell dieselbe Drift-Klasse wie #6: statisch hartkodierte Hosts vs. profilgetriebener Server.

Lösung

Statt die Security-Policy aufzuweichen: app-Clients erreichen minerva nur noch über den bereits existierenden HTTPS-Endpunkt https://app.doctate.de (OpenResty-TLS-Terminierung mit Let's-Encrypt-Cert → intern minerva:3000; DNS via variomedia-CNAME → myfritz-DDNS). Ein öffentlich vertrauenswürdiges Cert greift über den system-Trust-Store der Watch — keine network_security_config.xml-Änderung nötig.

Geänderte Profile (gitignored): brummel-minerva.sh, krey-minerva.shSERVER_URL=https://app.doctate.de. Template example-profile.sh.example (im Repo) auf die HTTPS-Konvention nachgezogen.

Verifikation (live an echter Watch, 2026-05-30)

  • Redeploy über WLAN, BuildConfig.SERVER_URL = https://app.doctate.de.
  • Logcat nach dem Fix: kein Cleartext-Block mehr, SyncWorkerLoop: burst-poll hit caseId=… → returning to default interval (erfolgreicher Server-Kontakt).
  • X-API-Key-Auth über HTTPS gegen https://app.doctate.de/api/oneliners → 200.
  • NAT-Hairpin bestätigt: Watch erreicht die Domain im Heim-WLAN wie remote.

Kein Code-Unit-Test (reiner Deployment-/Config-Defekt); Nachweis über Live-Logcat.

## Beobachtung Die Watch-App (`brummel-minerva`) schien lokal mit dem Dev-Server verbunden. Tatsächlich waren das nur lokale Altdaten (ein `installDebug`-Update behält das App-Datenverzeichnis). Der echte Defekt: Der `SyncWorkerLoop` erreichte minerva überhaupt nicht. Logcat: ``` W SyncWorkerLoop: transient: network: CLEARTEXT communication to minerva.lan not permitted by network security policy → backoff 60000ms ``` Der Sync war damit komplett blockiert — Kernfunktionalität für die Alpha-Tester (BLOCKER-Schwere). ## Ursache Seit Android 9 (API 28) ist unverschlüsseltes HTTP standardmäßig blockiert. `app/src/main/res/xml/network_security_config.xml` erlaubt Cleartext nur für `10.0.2.2` (Emulator) und `192.168.178.27` (Dev-Laptop) — **nicht** für `minerva.lan`. Das `brummel-minerva`-Profil zeigte aber auf `http://minerva.lan:3000` → jeder Request wurde von der Policy verworfen. Strukturell dieselbe Drift-Klasse wie #6: statisch hartkodierte Hosts vs. profilgetriebener Server. ## Lösung Statt die Security-Policy aufzuweichen: app-Clients erreichen minerva nur noch über den bereits existierenden HTTPS-Endpunkt **`https://app.doctate.de`** (OpenResty-TLS-Terminierung mit Let's-Encrypt-Cert → intern `minerva:3000`; DNS via variomedia-CNAME → myfritz-DDNS). Ein öffentlich vertrauenswürdiges Cert greift über den `system`-Trust-Store der Watch — **keine** `network_security_config.xml`-Änderung nötig. Geänderte Profile (gitignored): `brummel-minerva.sh`, `krey-minerva.sh` → `SERVER_URL=https://app.doctate.de`. Template `example-profile.sh.example` (im Repo) auf die HTTPS-Konvention nachgezogen. ## Verifikation (live an echter Watch, 2026-05-30) - Redeploy über WLAN, `BuildConfig.SERVER_URL = https://app.doctate.de`. - Logcat nach dem Fix: kein Cleartext-Block mehr, `SyncWorkerLoop: burst-poll hit caseId=… → returning to default interval` (erfolgreicher Server-Kontakt). - `X-API-Key`-Auth über HTTPS gegen `https://app.doctate.de/api/oneliners` → 200. - NAT-Hairpin bestätigt: Watch erreicht die Domain im Heim-WLAN wie remote. Kein Code-Unit-Test (reiner Deployment-/Config-Defekt); Nachweis über Live-Logcat.
Brummel added the BLOCKERbug labels 2026-05-30 14:10:50 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/doctate#7