Zum Inhalt springen
Prototyp pruefen

Installation

  • Die Android-App baut lokal aus superheld-android.
  • superheld-cloud startet lokal im Secure-Mux-Default mit Bootstrap-Token.
  • Die App bietet im Settings-Bereich einen Account-Sign-in/Create-Account-Pfad, der die vorhandenen POST /account/register- und POST /account/login-Endpoints nutzt, die Session speichert und danach zurueck auf die Home-Oberflaeche geht. Fuer normale Endnutzer (DAU) ist das der primaere Einrichtungspfad; manuelles Token-Minting ist nicht noetig.
  • Die App kann POST /devices, POST /events, GET /status, GET /alerts, GET /incidents, GET /jobs und fuer den letzten sichtbaren Job zusaetzlich GET /jobs/{id} sowie bei vorhandener trace_id GET /traces/{id} plus GET /traces/{id}/steps gegen das lokale Backend nutzen.
  • Der DAU-Home-Screen zeigt keine separate Settings-/Hilfe-Karte. Setup und Hilfe sind nur ueber die Primaeraaktion auf dem Home-Screen oder den Tab „Settings” in der Bottom-Navigation erreichbar. Alle vier Tabs (Home, Warnings, Issues, Settings) sind im taeglichen Betrieb stabil sichtbar (Commit 158c53c).
  • Der reale Tablet-Lauf wurde mit adb reverse tcp:8080 tcp:8080 gegen http://127.0.0.1:8080 verifiziert.
  • Ein fehlender events:write-Scope ist in der App sichtbar als klares Banner Event token is missing events:write. plus HTTP 403 insufficient_scope.
  • Ein fehlender alerts:read-Scope ist in der App sichtbar als Alert read failed. plus HTTP 403 insufficient_scope.
  • Ein fehlender incidents:read-Scope ist in der App sichtbar als HTTP 403 insufficient_scope.
  • Ein fehlender jobs:read-Scope ist in der App sichtbar als HTTP 403 insufficient_scope.
  • Ein absichtlich falscher App-Tenant bleibt ebenfalls sichtbar: mit tenant-debug in der App, aber einem weiter tenant-local-gebundenen Token zeigte dieselbe Konfigurationskarte Last backend tenant: tenant-local plus eine explizite Tenant-Mismatch-Warnung.

Was noch nicht als aktueller Runtime-Stand belegt ist

Abschnitt betitelt „Was noch nicht als aktueller Runtime-Stand belegt ist“
  • Distribution über Play Store oder App Store
  • iOS-, Windows-, macOS- oder Linux-App als verifizierter v1-Lieferpfad
  • Web-Dashboard als verifizierter Betriebs- oder Nutzerpfad
  • Emulator-Flow in diesem Workspace; die lokale SDK-Installation enthält derzeit kein emulator-Binary und keine system-images
  • Workspace unter /Users/benediktpoller/code/sh
  • Go-Toolchain für superheld-cloud
  • JDK 17 oder 21
  • Android SDK Platform 35
  • adb, curl und jq
  • Optional, aber für den verifizierten Pfad empfohlen: ein per USB angeschlossenes Android-Tablet
Terminal-Fenster
go version # erwartet: go1.22 oder neuer
java -version # erwartet: 17 oder 21
adb version # erwartet: beliebige aktuelle Version
curl --version # erwartet: beliebige aktuelle Version
jq --version # erwartet: beliebige aktuelle Version
ls "$HOME/Library/Android/sdk/platforms/android-35/" # erwartet: kein Fehler

Falls android-35 fehlt, kann die Plattform ueber den SDK Manager nachinstalliert werden:

Terminal-Fenster
"$HOME/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager" "platforms;android-35"

Der Android-Build benoetigt local.properties mit dem SDK-Pfad. Falls die Datei noch nicht existiert:

Terminal-Fenster
echo "sdk.dir=$HOME/Library/Android/sdk" > /Users/benediktpoller/code/sh/superheld-android/local.properties

Die folgenden Umgebungsvariablen halten Gradle-Caches im Workspace und vermeiden Konflikte mit globalen Einstellungen:

Terminal-Fenster
export ANDROID_USER_HOME=/Users/benediktpoller/code/sh/workspace/.android
export GRADLE_USER_HOME=/Users/benediktpoller/code/sh/workspace/.gradle-home
Terminal-Fenster
cd /Users/benediktpoller/code/sh/superheld-cloud
SUPERHELD_BOOTSTRAP_TOKEN=bootstrap-token \
SUPERHELD_BOOTSTRAP_TENANT_ID=tenant-local \
go run ./cmd/server

Wichtige Runtime-Fakten:

  • Default-Bind: 127.0.0.1:8080
  • Secure-Mux ist Default; ohne SUPERHELD_BOOTSTRAP_TOKEN startet cmd/server nicht im sicheren Modus
  • Persistenz liegt standardmäßig unter ./data; mit SUPERHELD_DATA_DIR (JSON-Dateien) oder SUPERHELD_SQLITE_PATH (SQLite-Datenbank) kann der Lauf expliziter gemacht werden
  • Mit SUPERHELD_SQLITE_PATH ueberleben Incidents und andere Daten einen Server-Restart zuverlaessig

Schnelltest nach dem Start (in einem zweiten Terminal):

Terminal-Fenster
curl -s http://127.0.0.1:8080/status \
-H 'Authorization: Bearer bootstrap-token' | jq .

Erwartet wird eine JSON-Antwort mit dem aktuellen Schutzstatus. Falls der Aufruf fehlschlaegt, ist der Server nicht korrekt gestartet.

Seit Commit 0371231 bietet die Android-App im Settings-Bereich zwei Wege zur Einrichtung:

DAU-Pfad: Account-Sign-in (empfohlen fuer Endnutzer)

Abschnitt betitelt „DAU-Pfad: Account-Sign-in (empfohlen fuer Endnutzer)“

Normale Endnutzer muessen kein Token manuell minten. Stattdessen wird im Settings-Bereich der App ein Account erstellt oder ein bestehender Account verwendet. Die App nutzt dafuer die vorhandenen Endpoints POST /account/register (mit E-Mail, Passwort und Tenant-ID) bzw. POST /account/login (mit E-Mail und Passwort). Nach erfolgreichem Sign-in speichert die App die Session und kehrt zur Home-Oberflaeche zurueck. Die Session traegt automatisch die benoetigten Scopes (status:read, devices:read, alerts:read, incidents:read, tokens:read, tokens:write).

Fuer diesen Pfad reicht es, nach dem Start der lokalen Cloud (Schritt 1) direkt mit dem App-Build (Schritt 3) fortzufahren. Die Account-Einrichtung erfolgt dann in der App selbst.

Fuer Operatoren, Entwickler und automatisierte Setups bleibt der manuelle Token-Pfad verfuegbar. Das App-Token fuer den verifizierten Android-MVP benoetigt mindestens diese Scopes:

  • devices:write
  • events:write
  • status:read
  • alerts:read
  • incidents:read
  • jobs:read

Für den heute verifizierten host-seitigen Demo-Job-Lauf kam zusätzlich jobs:write hinzu.

Terminal-Fenster
curl -s \
-X POST http://127.0.0.1:8080/tokens \
-H 'Authorization: Bearer bootstrap-token' \
-H 'Content-Type: application/json' \
-d '{"scopes":["devices:write","events:write","status:read","alerts:read","incidents:read","jobs:read","jobs:write"]}' \
| jq .

Erwartet wird eine Antwort mit einem Roh-Token, das genau einmal zurückgegeben wird, plus tenant_id=tenant-local. Diese Token-Bindung ist die Runtime-Wahrheit. Wenn die App spaeter mit einer anderen tenant_id startet, signalisiert sie den Drift jetzt explizit, statt einen normalen Success ohne Hinweis zu zeigen.

Um die Job-Karte in der App mit echtem Backend-Inhalt zu fuellen, wurde im verifizierten Lauf host-seitig ein kleiner Demo-Job angelegt:

Terminal-Fenster
curl -s \
-X POST http://127.0.0.1:8080/jobs \
-H 'Authorization: Bearer <tenant-app-token>' \
-H 'Content-Type: application/json' \
-d '{"job_class":"incident_triage","workflow_id":"incident_triage_v1","input_refs":{"event_ids":["evt-job-read-demo-missing"]}}' \
| jq .

Dieser Demo-Job landet ohne vorhandenes Quellereignis erwartbar in failed_terminal, bleibt tenant-scoped ueber GET /jobs sichtbar und wird in der App fuer den letzten sichtbaren Job zusaetzlich ueber GET /jobs/{id} nachgeladen. Der Pfad traegt dabei eine trace_id, die in der App unmittelbar fuer GET /traces/{id} und GET /traces/{id}/steps weiterverwendet wird.

Terminal-Fenster
cd /Users/benediktpoller/code/sh/superheld-android
ANDROID_USER_HOME=/Users/benediktpoller/code/sh/workspace/.android \
GRADLE_USER_HOME=/Users/benediktpoller/code/sh/workspace/.gradle-home \
./gradlew testDebugUnitTest assembleDebug

Wenn local.properties noch fehlt, muss sdk.dir=/Users/benediktpoller/Library/Android/sdk gesetzt sein.

Terminal-Fenster
adb devices
adb reverse tcp:8080 tcp:8080

Für den verifizierten Tablet-Pfad gilt:

  • bevorzugte Backend-URL in der App: http://127.0.0.1:8080
  • 10.0.2.2:8080 bleibt der Emulatorpfad und ist in diesem Workspace aktuell nicht als realer Lauf belegt

Wenn der Account-Sign-in-Pfad genutzt wird, genuegt die Installation ohne Build-Parameter fuer Token und Tenant. Die Backend-URL kann optional vorbelegt werden:

Terminal-Fenster
cd /Users/benediktpoller/code/sh/superheld-android
ANDROID_USER_HOME=/Users/benediktpoller/code/sh/workspace/.android \
GRADLE_USER_HOME=/Users/benediktpoller/code/sh/workspace/.gradle-home \
./gradlew installDebug \
-Psuperheld.baseUrl=http://127.0.0.1:8080
adb shell am start -W -n com.superheld.android/.MainActivity

Die App oeffnet den Settings-Bereich und bietet dort Account erstellen oder anmelden an. Nach erfolgreichem Sign-in kehrt die App zur Home-Oberflaeche zurueck.

Terminal-Fenster
cd /Users/benediktpoller/code/sh/superheld-android
ANDROID_USER_HOME=/Users/benediktpoller/code/sh/workspace/.android \
GRADLE_USER_HOME=/Users/benediktpoller/code/sh/workspace/.gradle-home \
./gradlew connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.class=com.superheld.android.DeviceIdentityManagerInstrumentedTest
ANDROID_USER_HOME=/Users/benediktpoller/code/sh/workspace/.android \
GRADLE_USER_HOME=/Users/benediktpoller/code/sh/workspace/.gradle-home \
./gradlew installDebug \
-Psuperheld.baseUrl=http://127.0.0.1:8080 \
-Psuperheld.apiToken=<tenant-app-token> \
-Psuperheld.tenantId=tenant-local
adb shell am start -W -n com.superheld.android/.MainActivity

Nach dem Start zeigt die App den DAU-Hauptscreen. Im aktuell verifizierten Lauf wurde diese Reihenfolge erfolgreich geprüft:

  1. App zeigt „Start here” mit Setup-Wording-CTA zur Einrichtung
  2. Der CTA fuehrt zum Settings-Tab und landet zuerst auf der ruhigen Support-Uebersicht (nicht direkt in Eingabefeldern)
  3. DAU-Pfad: Im Bereich Account erstellen oder anmelden — die App nutzt POST /account/register oder POST /account/login, speichert die Session und kehrt zur Home-Oberflaeche zurueck
  4. Operator-Pfad: Von der Support-Uebersicht explizit in den Bereich Verbindung/Registrierung navigieren und Verbindungsdaten manuell eingeben (Service-Adresse, Zugangscode, Familien-Code)
  5. Geraet registrieren ueber die Support-Aktionen auf dem Settings-und-Hilfe-Screen
  6. Ueber den Tab „Home” in der unteren Navigation zurueck zum Hauptscreen: Status wechselt zu „Everything looks calm”; der Home-Screen zeigt keine separate Settings-/Hilfe-Karte
  7. Schnell-Check-Metriken zeigen Geraetestatus, Warnungen und ernste Probleme

Sichtbare Erfolgsindikatoren:

  • Der Hauptscreen zeigt „Everything looks calm” mit ruhigem Hintergrundton nach erfolgreicher Einrichtung. Der Home-Screen zeigt keine separate Settings-/Hilfe-Karte; Setup und Hilfe sind ueber die Primaeraaktion oder den Tab „Settings” in der Bottom-Navigation erreichbar.
  • Schnell-Check-Metriken erscheinen: Geraet geschuetzt, keine Warnungen, keine ernsten Probleme.
  • Nach einem Demo-Event (ueber Support-Aktionen auf dem Settings-und-Hilfe-Screen → „Send guided test event”) wechselt der Status auf „Needs attention now” mit einer Problem-Karte in Klarsprache.
  • Einrichtung und technische Details befinden sich auf dem separaten Settings-und-Hilfe-Screen. Der Hauptscreen zeigt keine separate Settings-/Hilfe-Karte; Setup und Hilfe sind nur ueber die Primaeraaktion oder den Tab „Settings” erreichbar.

Fuer den technischen Verifikationspfad mit Backend-API-Aufrufen und Telemetrie-Details siehe das Operator-Runbook.

Die App klassifiziert Fehler in vier Kategorien mit dedizierter Guidance pro Read-/Write-Karte:

FehlerklasseTypische UrsacheBeispiel-Anzeige
Auth (unauthorized)Ungueltiges oder abgelaufenes TokenRefresh rejected by backend authentication.
Scope (insufficient_scope)Token hat den benoetigten Scope nichtAlert read was rejected due to missing scope.
Tenant (tenant_mismatch)App-Tenant stimmt nicht mit Token-Bindung uebereinTrace read is using the wrong tenant context.
Netzwerk (network_error)Backend nicht erreichbarRefresh could not reach the backend.

Jede Fehlerkarte zeigt zusaetzlich run_id, Result, Backend version (wenn vorhanden) und Error code.

Verifizierte Negativlaeufe auf dem USB-Tablet:

  • Scope-Fehler: Tokens ohne events:write, alerts:read, incidents:read oder jobs:read zeigen dedizierte Scope-Guidance pro Karte plus HTTP 403 insufficient_scope
  • Auth-Fehler: Ein komplett ungueltiges Token zeigt unauthorized-Guidance in allen Read-Karten (Status, Alerts, Incidents, Jobs)
  • Tenant-Mismatch: App-Tenant tenant-debug mit tenant-local-gebundenem Token zeigt Mismatch-Warnung und Korrekturhinweis
  • Netzwerk-Fehler: Nach einem erfolgreichen Refresh verschwindet das Backend; der naechste Refresh zeigt Netzwerk-Guidance in allen Karten plus Last successful sync-Zeitstempel
  • Downstream-Detailfehler: Ein einzelner GET /incidents/{id} 404 nach erfolgreichem Listenread zeigt Incident list loaded, but the latest incident detail read failed.; ein GET /traces/{id} 403 tenant_mismatch nach erfolgreichem Job-Read zeigt Tenant-Guidance in der Trace-Karte

Alle diese Pfade sind als wiederholbare Instrumentation-Tests auf dem angeschlossenen Tablet verifiziert.

ProblemWahrscheinliche UrsacheAktueller Umgang
cmd/server startet nicht im sicheren ModusSUPERHELD_BOOTSTRAP_TOKEN oder SUPERHELD_BOOTSTRAP_TENANT_ID fehltSecure-Mux mit Bootstrap-Token starten
Tablet erreicht das lokale Backend nichtadb reverse tcp:8080 tcp:8080 fehltReverse erneut setzen und App mit http://127.0.0.1:8080 konfigurieren
Refresh wirkt erfolgreich, aber die App zeigt einen Tenant-MismatchToken ist an einen anderen Tenant gebunden als die in der App gesetzte tenant_idApp-Tenant auf die Token-Bindung ziehen oder ein Token fuer den beabsichtigten Tenant minten
Incident-Sektion bleibt leerEs gibt aktuell noch keinen tenant-sichtbaren IncidentNach Send Demo Event erneut Refresh Status ausfuehren; das Demo-Event erzeugt unmittelbar einen malicious_app-Incident. Bei SQLite-Persistenz bleiben Incidents auch ueber Server-Restarts erhalten
App zeigt beim Start alten Zustand statt „Start here”Die App persistiert den letzten erfolgreichen Home-Snapshot lokal und stellt ihn beim naechsten Start sofort wieder herDas ist Normalverhalten seit Commit 6a67f8d. Einen frischen Startzustand erhaelt man durch Aendern der Service-Adresse, des Zugangscodes oder des Familien-Codes auf dem Settings-Screen
Job-Sektion bleibt leerEs existiert aktuell kein tenant-sichtbarer JobHost-seitig einen kleinen Demo-Job über POST /jobs anlegen und danach erneut refreshen
Emulator-Befehle fehlenSDK enthält lokal kein emulator-BinaryUSB-Tablet als bevorzugten Testpfad verwenden