Zuletzt aktualisiert:

RECHERCHE-CAPACITOR.md — Native iOS-Hülle via Capacitor + AltStore/SideStore

Stand 06.06.2026. Anlass: Der Barcode-Scan hängt in der iOS-Home-Screen-PWA (WebKit rendert den Kamera-Prompt im standalone-Modus nicht, getUserMedia bleibt ewig pending — entschärft durch ADR-31: Permission-Vorabcheck, Timeout, Foto-Fallback). Diese Datei dokumentiert den Plan B: eine native App-Hülle per Capacitor, kostenlos verteilt über AltStore/SideStore (MacBook Pro vorhanden, kein Apple-Developer-Account gewollt, 99 €/Jahr).

Vorher testen (Plan A, 0 Minuten Aufwand): Safari → silverscale.dennisfisch.de → aA-Menü → Website-Einstellungen → Kamera → „Erlauben" → PWA neu starten → scannen. Erbt die PWA die Erlaubnis (permissions.query = granted), lässt der ADR-31-Vorabcheck die Live-Kamera durch und dieser ganze Plan B ist unnötig.


1. Vorab geklärt: Was NICHT geht (Stand 06/2026)

2. Architektur der Lösung

┌──────────────────────────────────────┐
│ Native iOS-App (Xcode-Hülle, ~leer)  │ ← einmalig bauen, per AltStore signiert
│  ┌────────────────────────────────┐  │
│  │ Capacitor-WKWebView            │  │
│  │ lädt LIVE https://silverscale. │  │ ← server.url-Modus: App-Updates kommen
│  │ dennisfisch.de (Remote-Modus)  │  │   weiter per npm run build auf dem VPS,
│  └────────────────────────────────┘  │   IPA muss praktisch NIE neu gebaut werden
│  NSCameraUsageDescription            │ ← iOS fragt EINMAL nativ, gilt dauerhaft
└──────────────────────────────────────┘

3. Teil A — App bauen (einmalig, MacBook Pro)

  1. Xcode aus dem Mac App Store (gratis, ~12 GB), einmal starten, Command-Line-Tools installieren lassen.
  2. Frontend-Kopie (muss nicht im Repo passieren): bash npm i @capacitor/core @capacitor/cli npx cap init Silverscale de.dennisfisch.silverscale npx cap add ios
  3. capacitor.config.ts → Remote-Modus: ts server: { url: 'https://silverscale.dennisfisch.de' }
  4. npx cap open ios → in der Info.plist NSCameraUsageDescription („Barcode-Scan für Artikel") eintragen.
  5. IPA ohne Signatur bauen (AltStore signiert selbst um; Xcode-Export geht mit freier Apple-ID nicht regulär): bash xcodebuild -workspace App.xcworkspace -scheme App -configuration Release \ -sdk iphoneos CODE_SIGNING_ALLOWED=NO build # .app aus DerivedData → Ordner Payload/ → zippen → in Silverscale.ipa umbenennen

4. Teil B — Signieren & Dauerbetrieb (AltStore bzw. SideStore)

AltStore Classic (offiziell, Mac-gebunden)

Einmalig: AltServer auf dem Mac (Menüleisten-App, macOS 11+; ggf. Mail-Plug-in-Dialog folgen) → iPhone per Kabel → „Install AltStore" → Apple-ID eingeben (Empfehlung: eigene, leere Apple-ID nur fürs Sideloaden) → auf dem iPhone Zertifikat vertrauen (Einstellungen → Allgemein → VPN & Geräteverwaltung) → Silverscale.ipa per AirDrop → in AltStore „+".

Für den automatischen 7-Tage-Refresh muss GLEICHZEITIG präsent sein:

Komponente Zustand
MacBook an und wach (zugeklappt/Ruhezustand = kein Refresh)
AltServer läuft (als Login-Item eintragen)
iPhone + Mac im selben WLAN
AltStore-App (iPhone) Hintergrundaktualisierung an; gelegentlich öffnen hilft

Verpasster Refresh: App startet ab Tag 7 nicht mehr — kein Datenverlust (alles liegt auf dem VPS), einmal refreshen (WLAN oder Kabel) und gut.

Limits freie Apple-ID: max. 3 aktive Apps inkl. AltStore selbst (→ 2 frei), max. 10 App-IDs pro 7 Tage (nur beim Experimentieren relevant). Jaquelines iPhone = komplett eigenes Setup mit ihrer Apple-ID.

SideStore (Fork, refresht OHNE Mac — empfohlen für unseren Fall)

Nach einmaligem Setup (Pairing-Datei vom Mac + lokaler VPN-Trick „StosVPN" + Anisette-Server) refresht SideStore auf dem iPhone selbst — die „MacBook wach im WLAN"-Pflicht entfällt. Mehr Bastelei beim Einrichten, robusterer Dauerbetrieb, gleiche Apple-ID-Limits. Da das MacBook vermutlich nicht wöchentlich wach im WLAN steht: SideStore bevorzugen.

5. ⚠️ Blocker: Pocket-ID-Passkey-Login

WebAuthn (navigator.credentials) ist in WKWebView gesperrt (nur Apps mit Browser-Entitlement); der Aufruf hängt sogar, statt sauber zu scheitern. Der Capacitor-Passkey-Shim (Cap-go) leitet auf native Passkey-APIs um, braucht aber Associated Domains = bezahltes Developer-Programm.

→ Mit freier Apple-ID kann sich die Capacitor-App nicht per Pocket ID einloggen. Vor Teil A muss serverseitig eine Lösung her, z. B.: - Geräte-Token-Login: eingeloggte PWA/Safari-Session erzeugt in den Einstellungen einen Einmal-Link/QR-Code, der in der App eine normale 180-Tage-Session setzt (kleiner Endpoint + UI-Knopf), oder - Login per ASWebAuthenticationSession-Plugin (System-Browser-Sheet, kann WebAuthn — Session-Cookie landet dann aber nicht automatisch in der WebView, daher Token-Übergabe nötig → läuft auf dasselbe hinaus).

6. Abarbeitungs-Checkliste

Quellen