Ops Manual
Dieses Dokument ist das konsolidierte Betriebshandbuch fuer den ersten auslieferbaren Superheld-Stand: Android-App plus lokales superheld-cloud-Backend.
1. Architekturueberblick
Abschnitt betitelt „1. Architekturueberblick“Der erste Lieferstand besteht aus zwei Komponenten:
| Komponente | Beschreibung | Laufzeitort |
|---|---|---|
superheld-cloud | Backend-API mit Secure-Mux, Event-Ingestion, Alert-/Incident-Ableitung, Job-Runtime, Token-Lifecycle, Webhook-Delivery | Lokaler Prozess auf 127.0.0.1:8080 |
superheld-android | Android-App mit Device-Identitaet, signierter Event-Submission, Status-/Alert-/Incident-/Job-Refresh, Telemetrie | Android-Geraet (USB-Tablet verifiziert) |
Datenfluss
Abschnitt betitelt „Datenfluss“- Die Android-App registriert sich per
POST /devicesmit RSA-Signatur. - Die App sendet signierte Events per
POST /events. - Das Backend leitet aus akzeptierten Events Alerts ab; aus High-Severity-Events auch Incidents.
- Die App liest
GET /status,GET /alerts,GET /incidents,GET /jobsund nachgelagerte Detail-Reads. - Webhooks liefern Events an externe Systeme.
Tenant-Modell
Abschnitt betitelt „Tenant-Modell“Alle Daten sind tenant-scoped. Tokens sind an genau einen Tenant gebunden. Cross-Tenant-Zugriffe werden vom Secure-Mux abgelehnt.
Sicherheitsgrenzen
Abschnitt betitelt „Sicherheitsgrenzen“- Device-Identitaet: RSA-Keypair pro Geraet, Proof-of-Possession bei Registrierung
- API-Zugang: Bearer-Token mit Scope-Pruefung im Secure-Mux
- Event-Integritaet: RSA-PSS-Signatur auf
POST /events - Token-Speicherung: SHA-256(token) im Backend, Klartext nur einmal bei Create
2. Start, Stop, Restart, Upgrade
Abschnitt betitelt „2. Start, Stop, Restart, Upgrade“Backend starten
Abschnitt betitelt „Backend starten“Mit JSON-Persistenz:
cd /Users/benediktpoller/code/sh/superheld-cloudSUPERHELD_DATA_DIR=/pfad/zum/data-dir \SUPERHELD_BOOTSTRAP_TOKEN=<sicheres-token> \SUPERHELD_BOOTSTRAP_TENANT_ID=<tenant-id> \go run ./cmd/serverMit SQLite-Persistenz (empfohlen fuer Restart-Sicherheit):
cd /Users/benediktpoller/code/sh/superheld-cloudSUPERHELD_SQLITE_PATH=/pfad/zur/superheld.db \SUPERHELD_BOOTSTRAP_TOKEN=<sicheres-token> \SUPERHELD_BOOTSTRAP_TENANT_ID=<tenant-id> \go run ./cmd/serverStoppen
Abschnitt betitelt „Stoppen“Im lokalen Dev-Pfad: Prozess mit Ctrl-C oder kill beenden. Der Server hat keine spezielle Graceful-Shutdown-Logik dokumentiert; offene Requests werden beim Stoppen abgebrochen.
Restart
Abschnitt betitelt „Restart“- Server stoppen.
- Server mit demselben Kommando und denselben Umgebungsvariablen neu starten.
- Mit SQLite bleiben alle Daten erhalten. Mit JSON werden die Dateien beim Start neu geladen.
- Nach dem Start:
curl -s http://127.0.0.1:8080/status -H 'Authorization: Bearer <token>' | jq .zur Verifikation.
Upgrade
Abschnitt betitelt „Upgrade“Kein formaler Upgrade-Pfad dokumentiert. Aktueller Ablauf:
- Server stoppen.
- Neuen Code aus dem Repository ziehen (
git pullinsuperheld-cloud). - Server neu starten.
- Persistierte Daten bleiben kompatibel; aeltere Formate werden beim Lesen transparent migriert.
3. TLS, Bind-Adresse und sichere Defaults
Abschnitt betitelt „3. TLS, Bind-Adresse und sichere Defaults“Bind-Adresse
Abschnitt betitelt „Bind-Adresse“| Umgebungsvariable | Default | Beschreibung |
|---|---|---|
SUPERHELD_BIND_ADDR | 127.0.0.1:8080 | Adresse und Port fuer den Server |
Default ist Loopback. Nicht-Loopback-Binds erwarten ein TLS-Zertifikat.
| Umgebungsvariable | Beschreibung |
|---|---|
SUPERHELD_TLS_CERT_FILE | Pfad zum TLS-Zertifikat |
SUPERHELD_TLS_KEY_FILE | Pfad zum TLS-Schluessel |
Wenn beide gesetzt sind, startet der Server mit TLS und emittiert Strict-Transport-Security auf allen Antworten.
Plaintext-Override
Abschnitt betitelt „Plaintext-Override“| Umgebungsvariable | Beschreibung |
|---|---|
SUPERHELD_ALLOW_PLAINTEXT_BIND | true erlaubt nicht-Loopback-Bind ohne TLS (nur fuer kontrollierte Dev-/Proxy-Setups) |
Sichere Defaults
Abschnitt betitelt „Sichere Defaults“- Secure-Mux ist Default; ohne
SUPERHELD_BOOTSTRAP_TOKENstartet der sichere Modus nicht. - Rate Limiting: 120 Anfragen/Minute, tenant-gebunden wenn authentifiziert.
- Security-Header auf allen Antworten:
X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Referrer-Policy: no-referrer,Cache-Control: no-store. - Request-Body-Limit: Requests ueber dem konfigurierten Groessenlimit werden mit
413abgelehnt.
4. Token-, Secret- und Bootstrap-Handling
Abschnitt betitelt „4. Token-, Secret- und Bootstrap-Handling“Bootstrap-Token
Abschnitt betitelt „Bootstrap-Token“Das Bootstrap-Token ist der initiale Zugang zum System. Es wird per Umgebungsvariable gesetzt und sollte nicht in Klartextlogs oder Quellcode erscheinen.
| Umgebungsvariable | Beschreibung |
|---|---|
SUPERHELD_BOOTSTRAP_TOKEN | Initiales Zugriffstoken fuer den Secure-Mux |
SUPERHELD_BOOTSTRAP_TENANT_ID | Tenant-Bindung des Bootstrap-Tokens |
SUPERHELD_BOOTSTRAP_SCOPES | Komma-getrennte Scopes (Default: alle) |
SUPERHELD_BOOTSTRAP_TOKEN_TTL | Optionale Lebensdauer (z. B. 24h) |
App-Token minten
Abschnitt betitelt „App-Token minten“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","incidents:write","jobs:read"]}' \ | jq .Wichtig:
- Das rohe Token wird nur einmal in der Create-Antwort zurueckgegeben.
- Nur SHA-256(token) wird persistiert.
- Neue Tokens koennen nur Scopes anfordern, die der aufrufende Token bereits besitzt.
Token widerrufen
Abschnitt betitelt „Token widerrufen“curl -s -X DELETE http://127.0.0.1:8080/tokens/<token-id> \ -H "Authorization: Bearer <bootstrap-token>"Token-Audit pruefen
Abschnitt betitelt „Token-Audit pruefen“# Alle Token-Audit-Eintraege des Tenantscurl -s http://127.0.0.1:8080/tokens/audit \ -H "Authorization: Bearer <bootstrap-token>" | jq .
# Audit fuer ein bestimmtes Tokencurl -s http://127.0.0.1:8080/tokens/<token-id>/audit \ -H "Authorization: Bearer <bootstrap-token>" | jq .Filter: ?action=revoke oder ?token_id=<id> sind auf /tokens/audit verfuegbar.
Notfall-Rotation
Abschnitt betitelt „Notfall-Rotation“- Kompromittiertes Token ueber
DELETE /tokens/<id>widerrufen. - Audit pruefen:
GET /tokens/audit?token_id=<id>fuer Aktivitaeten des kompromittierten Tokens. - Neues Token minten.
- App-Konfiguration mit neuem Token aktualisieren.
5. Persistenz, Backup, Restore
Abschnitt betitelt „5. Persistenz, Backup, Restore“Persistenz-Modi
Abschnitt betitelt „Persistenz-Modi“| Modus | Umgebungsvariable | Restart-sicher | Empfohlen |
|---|---|---|---|
| JSON-Dateien | SUPERHELD_DATA_DIR | Ja (Dateien werden neu geladen) | Fuer schnelle Dev-Laeufe |
| SQLite | SUPERHELD_SQLITE_PATH | Ja (zuverlaessig) | Fuer Produktbetrieb |
JSON-Dateien
Abschnitt betitelt „JSON-Dateien“Unter SUPERHELD_DATA_DIR entstehen:
tokens.json, devices.json, events.json, alerts.json, incidents.json, jobs.json, traces.json, artifacts.json, webhooks.json, token_audit.json, job_audit.json
Aeltere Formate (z. B. incident_id statt id) werden beim Lesen transparent migriert.
Eine einzelne Datei unter SUPERHELD_SQLITE_PATH. Fehlende Spalten in aelteren Datensaetzen werden beim Lesen aus vorhandenen Spalten rekonstruiert.
- Server stoppen (oder sicherstellen, dass kein Schreibvorgang laeuft).
- JSON: Das gesamte
SUPERHELD_DATA_DIRkopieren. - SQLite: Die
.db-Datei kopieren.
Restore
Abschnitt betitelt „Restore“- Server stoppen.
- Backup an die konfigurierte Stelle kopieren.
- Server neu starten.
- Verifikation:
GET /status,GET /tokens,GET /incidentspruefen.
6. Audit-Logs, Token-Audit, Job-Audit
Abschnitt betitelt „6. Audit-Logs, Token-Audit, Job-Audit“Audit-Endpunkte
Abschnitt betitelt „Audit-Endpunkte“| Endpunkt | Zweck | Filter |
|---|---|---|
GET /tokens/audit | Alle Token-Lifecycle-Eintraege des Tenants | action, token_id |
GET /tokens/{id}/audit | Audit eines bestimmten Tokens | — |
GET /jobs/audit | Alle Job-Review-Audit-Eintraege des Tenants | action, reviewed_by |
GET /jobs/{id}/audit | Audit eines bestimmten Jobs | — |
Alle Audit-Antworten folgen dem Cursor-/Limit-Paginierungsschema und liefern strukturierte fields neben dem rohen detail.
Audit-Integritaet
Abschnitt betitelt „Audit-Integritaet“Die Runtime fuehrt eine interne Hash-Kette ueber Audit-Eintraege. Jeder Eintrag referenziert den Hash des vorigen Eintrags.
Operator-Beispiele
Abschnitt betitelt „Operator-Beispiele“Token-Widerruf nachvollziehen:
curl -s 'http://127.0.0.1:8080/tokens/audit?action=revoke' \ -H "Authorization: Bearer <bootstrap-token>" | jq '.data[] | {timestamp, action, token_id: .fields.token_id}'Job-Review-Entscheidungen pruefen:
curl -s 'http://127.0.0.1:8080/jobs/audit?action=approve' \ -H "Authorization: Bearer <bootstrap-token>" | jq '.data[] | {timestamp, action, reviewed_by: .fields.reviewed_by, job_id: .fields.job_id}'7. Webhooks, DLQ, Replay
Abschnitt betitelt „7. Webhooks, DLQ, Replay“Webhook einrichten
Abschnitt betitelt „Webhook einrichten“curl -s -X POST http://127.0.0.1:8080/webhooks \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"url":"https://siem.example.com/ingest","secret":"<signing-secret>"}'Anforderungen:
- URL muss
https://verwenden. - Loopback-, Link-Local- und private Adressen werden abgelehnt.
- Redirects auf solche Adressen ebenfalls.
Signaturverifikation
Abschnitt betitelt „Signaturverifikation“Jede Zustellung traegt X-Superheld-Signature (HMAC-SHA256) und X-Superheld-Timestamp (Unix Seconds). Signing-Input: <timestamp>.<raw-body>.
Retry-Verhalten
Abschnitt betitelt „Retry-Verhalten“| Versuch | Verzoegerung |
|---|---|
| 1 | sofort |
| 2 | 1 Sekunde |
| 3 | 2 Sekunden |
| 4 | 4 Sekunden |
Nach 3 fehlgeschlagenen Wiederholungen landet die Zustellung in der Dead-Letter-Queue.
DLQ verwalten
Abschnitt betitelt „DLQ verwalten“# Fehlgeschlagene Zustellungen auflistencurl -s http://127.0.0.1:8080/webhooks/dlq \ -H "Authorization: Bearer <token>" | jq .
# Einzelnen Eintrag erneut zustellencurl -s -X POST http://127.0.0.1:8080/webhooks/dlq \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"entry_id":"<dlq-entry-id>"}'
# Eintrag quittieren/loeschencurl -s -X DELETE http://127.0.0.1:8080/webhooks/dlq \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"entry_id":"<dlq-entry-id>"}'DLQ-Retention: 7 Tage im aktuellen Runtime-Vertrag.
Webhook-Status pruefen
Abschnitt betitelt „Webhook-Status pruefen“curl -s http://127.0.0.1:8080/webhooks \ -H "Authorization: Bearer <token>" \ | jq '.data[] | {webhook_id, url, last_delivery_status, last_delivery_error, last_delivery_at, last_delivery_attempts}'8. Monitoring, Logs, Health-Checks, Debugging
Abschnitt betitelt „8. Monitoring, Logs, Health-Checks, Debugging“Monitoring
Abschnitt betitelt „Monitoring“| Pruefpunkt | Methode | Status |
|---|---|---|
| Runtime-Check | GET /status mit gueltigem Token | Verifiziert |
| Dedizierter Health-Endpoint | /healthz oder /metrics | Nicht implementiert |
| Prometheus/OpenTelemetry | Metrics-Export | Nicht implementiert |
GET /status ist der leichtgewichtige Runtime-Check. Ein separater Health-Endpoint ohne Auth ist heute nicht belegt.
Fuer eine vollstaendige Uebersicht, welche Observability-Pfade (Audit, Logging, Monitoring, SIEM, Telemetrie) heute verifiziert sind und was noch Zielarchitektur ist, siehe die Operatoren-Schnellreferenz in der Telemetrie-Seite.
Backend-Logs
Abschnitt betitelt „Backend-Logs“Der Server schreibt nach stdout/stderr. Fuer persistentes Logging:
SUPERHELD_BOOTSTRAP_TOKEN=... \SUPERHELD_BOOTSTRAP_TENANT_ID=... \go run ./cmd/server 2>&1 | tee server.logTelemetrie-Logzeilen
Abschnitt betitelt „Telemetrie-Logzeilen“Wenn die App X-Superheld-Run-Id mitsendet, schreibt der Server pro Request eine strukturierte Zeile:
telemetry flow=status_refresh run_id=status-refresh-<uuid> tenant_id=tenant-local device_id=android-<uuid> app_version=0.1.0 backend_version=(devel) method=GET path=/status status=200 result=success latency=183µsBei Fehlern zusaetzlich: error_code=insufficient_scope
Tenant-Mismatch-Erkennung
Abschnitt betitelt „Tenant-Mismatch-Erkennung“Wenn X-Superheld-Tenant-Id nicht zum Token-Tenant passt:
tenant_hint_mismatch token_tenant_id=tenant-local requested_tenant_id=tenant-debug token_id=... flow=... run_id=...App-Logs
Abschnitt betitelt „App-Logs“adb logcat -d -s SuperheldTelemetry:IZeigt telemetry flow=app_launch ... method=APP path=/main_activity ... backend_version=app_local und aehnliche Zeilen.
Debugging-Checkliste
Abschnitt betitelt „Debugging-Checkliste“| Symptom | Diagnose | Loesung |
|---|---|---|
| Server startet nicht | SUPERHELD_BOOTSTRAP_TOKEN oder SUPERHELD_BOOTSTRAP_TENANT_ID fehlt | Umgebungsvariablen setzen |
| App erreicht Backend nicht | adb reverse fehlt oder Server nicht gestartet | adb reverse tcp:8080 tcp:8080 und Server pruefen |
| 401 auf allen Requests | Token ungueltig oder widerrufen | Neues Token minten |
| 403 insufficient_scope | Token hat benoetigten Scope nicht | Token mit korrekten Scopes minten |
| 403 tenant_mismatch | App-Tenant stimmt nicht mit Token-Tenant ueberein | App-Tenant oder Token anpassen |
| Incidents leer nach Restart | JSON-Persistenz: Datei beschaedigt oder fehlt | SQLite verwenden oder JSON-Datei pruefen |
| Webhook-Zustellung schlaegt fehl | Ziel nicht erreichbar oder kein HTTPS | Ziel-URL und TLS pruefen, DLQ pruefen |
Run-Compare
Abschnitt betitelt „Run-Compare“Zwei Laeufe desselben Flows vergleichen:
go run ./cmd/telemetrycompare \ -log server.log \ -flow status_refresh \ -tenant-id tenant-local \ -app-version 0.1.0Optionale Filter: -device-id, -backend-version, -result, -error-code, -run-a, -run-b.
9. Incident- und Recovery-Ablauf
Abschnitt betitelt „9. Incident- und Recovery-Ablauf“Incident-Kategorien
Abschnitt betitelt „Incident-Kategorien“| Kategorie | Beispiel | Primaere Massnahme |
|---|---|---|
| Token-Kompromittierung | Bootstrap- oder App-Token geleakt | Token widerrufen, Audit pruefen, neues Token minten |
| Backend-Kompromittierung | Unautorisierter Zugang zum Server-Prozess | Server stoppen, Persistenz sichern, Audit pruefen |
| Geraete-Kompromittierung | Android-Geraet gerootet oder gestohlen | Geraete-Token widerrufen, Events des Geraets pruefen |
| Datenexposition | Persistierte Daten an Unbefugte gelangt | Tokens widerrufen, Passwoerter rotieren, Umfang bestimmen |
Ablauf bei Token-Kompromittierung
Abschnitt betitelt „Ablauf bei Token-Kompromittierung“- Erkennen: Verdaechtiger Zugriff in Audit-Logs oder anomale API-Nutzung.
- Eindaemmen:
DELETE /tokens/<id>fuer das kompromittierte Token. - Untersuchen:
GET /tokens/<id>/auditundGET /tokens/audit?token_id=<id>fuer alle Aktionen des Tokens. - Bereinigen: Neues Token mit gleichen Scopes minten, App-Konfiguration aktualisieren.
- Dokumentieren: Zeitpunkt, betroffenes Token, durchgefuehrte Massnahmen, Ursache.
Ablauf bei Backend-Stoerung
Abschnitt betitelt „Ablauf bei Backend-Stoerung“- Erkennen:
GET /statusschlaegt fehl oder App zeigtnetwork_error. - Eindaemmen: Server-Logs pruefen (
tail server.log). - Wiederherstellen: Server mit denselben Umgebungsvariablen neu starten.
- Verifizieren:
GET /status,GET /incidents,GET /tokenspruefen. - Dokumentieren: Ausfalldauer, Ursache, Datenverlust (falls vorhanden).
Ablauf bei Geraeteverlust
Abschnitt betitelt „Ablauf bei Geraeteverlust“- Token widerrufen:
DELETE /tokens/<app-token-id>. - Events pruefen:
GET /eventsfuer verdaechtige Eintraege des Geraets. - Neues Token: Fuer Ersatzgeraet minten.
Recovery-Checkliste
Abschnitt betitelt „Recovery-Checkliste“- Alle kompromittierten Tokens widerrufen
- Audit-Logs fuer den Zeitraum gesichert
- Neue Tokens gemintet und verteilt
- App-Konfiguration auf den neuen Zustand gezogen
- Server-Persistenz intakt (Backup vorhanden)
-
GET /statusliefert erwarteten Zustand
Verwandte Dokumente
Abschnitt betitelt „Verwandte Dokumente“- Lokales Android-Cloud-Ops-Runbook — Detaillierter Schritt-fuer-Schritt-Leitfaden fuer den verifizierten USB-Tablet-Pfad
- Installation — Ersteinrichtung
- API-Uebersicht — Endpunkt-Referenz
- Authentifizierung — Token- und Auth-Details
- Telemetrie und Logging — Observability-Sicht
- SIEM-Integration — Event-Export