# RELEASE_READINESS — TestFlight Internal + Play Internal Testing **Owner:** zied (Release-/Rollout-Engineer) **Stand:** 2026-05-07 (Donnerstag) **Deadline:** Wochenende 2026-05-09/10 — iOS auf TestFlight Internal, Android auf Play Console Internal Testing **Stack:** Expo SDK 53 + React Native 0.79.6 (NICHT Capacitor — alte zied.md ist veraltet) **Repo-Pfad:** `/Users/chahinebrini/mono/rebreak-monorepo/apps/rebreak-native/` > Ziel "Internal Only": kein Apple-Review, kein Google-Review nötig. Apple TestFlight Internal Tester (≤100, App-Store-Connect-User) sind direkt installierbar. Play Console Internal Testing Track lässt bis zu 100 Tester per Email-Liste sofort builden. --- ## Status-Quo-Tabelle Legende: ✅ ready / 🟡 vorhanden aber Anpassung nötig / 🔴 fehlt blockierend / ⚪ User-Bestätigung nötig ### iOS | Item | Status | Detail | |---|---|---| | Bundle-ID | ✅ | `org.rebreak.app` (app.config.ts:22 + Info.plist) | | App Store Connect entry | ⚪ | Existiert? Apple-Login nötig — User-Bestätigung | | Apple Developer Account aktiv | ⚪ | TestFlight setzt aktiven $99/Jahr-Account voraus | | Provisioning Profile + Cert | ⚪ | EAS managed credentials kann das, aber Account muss connected sein | | `eas.json` | 🔴 | **fehlt komplett** — muss generiert werden für `eas build` | | iOS Native-Folder (`ios/`) | ✅ | Existiert via expo prebuild, Workspace + Pods sind drin | | `Info.plist` Versions | 🟡 | `CFBundleShortVersionString=0.1.0`, `CFBundleVersion=1` — für TF muss CFBundleVersion bei jedem Re-Upload steigen | | `PrivacyInfo.xcprivacy` | ✅ | vorhanden (Pflicht seit April 2024); declared APIs FileTimestamp/UserDefaults/DiskSpace/SystemBootTime + `NSPrivacyTracking=false` | | Entitlements | 🟡 | `aps-environment=development` — für TestFlight production-Build muss auf `production` (oder via EAS-Profile gesetzt). Family-Controls + Network-Extension + App-Group sind drin | | Apple Sign-In | 🟡 | Code-Stub in `stores/auth.ts:82-87` mit TODO. UI zeigt "via Apple Sign-In"-Pill (`components/profile/ProfileHeader.tsx:55`). Capability fehlt im entitlements file. **Apple-Review-Risk:** Apple verlangt Sign-In-with-Apple wenn andere 3rd-Party-Logins (Google) vorhanden. Für TestFlight Internal nicht zwingend, aber für External + Production blocker | | App-Icon (1024×1024) | ✅ | `ios/Rebreak/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png` + Contents.json | | Splash | ✅ | `SplashScreen.storyboard` + Image-Assets im Xcasset | | Stripe-IAP-Konflikt | 🟡 | Code prüft Pro/Legend (`stores/auth.ts`, `app/(app)/blocker.tsx:268`). UI hat KEINEN Upgrade-Button in App — alle Upgrade-Pfade sind `Alert.alert(...)` ohne Stripe-Link → für TestFlight Internal OK, aber bei External/Prod muss klar dokumentiert werden: Subscription nur via rebreak.org/web (nicht in App). Apple-Reviewer-Notes nötig | ### Android | Item | Status | Detail | |---|---|---| | Package-ID | ✅ | `org.rebreak.app` (app.config.ts:38 + AndroidManifest.xml + build.gradle:90/92) | | Google Play Developer Account | ✅ | Validiert 2026-05-05 (siehe trucko-memory `project_google_dev_account.md`) | | Play Console App-Entry | ⚪ | User-Bestätigung: existiert "ReBreak"-App im Play Console schon mit Internal-Track? | | Android Native-Folder (`android/`) | ✅ | Existiert, gradle-Setup ok | | Keystore (Production) | 🔴 | `android/app/build.gradle:113` signed Release-Build mit **debug.keystore** — Play Store akzeptiert das nicht. Production-Keystore muss erzeugt werden. **Alternativ (empfohlen):** EAS managed Android Credentials → EAS hält Keystore, kein User-Custody-Risk | | versionCode/versionName | 🟡 | `versionCode=1, versionName="0.1.0"` — versionCode muss bei jedem Play-Upload steigen | | AAB-Build-Konfig | 🟡 | Keine custom AAB-Targets, default `bundleRelease` würde laufen — aber mit debug-keystore. EAS erzeugt automatisch AAB bei production-Profile | | `eas.json` | 🔴 | fehlt — siehe iOS | | Adaptive Icon (foreground/background) | ✅ | `adaptive-icon-android.png` (foreground only, ohne Schrift wegen Mask) + `adaptiveIcon.backgroundColor=#0a0a0a`. mipmap-xxxhdpi etc. via prebuild generiert | | Notification-Icon (24×24 monochrome) | 🟡 | nicht explizit gesetzt — Expo nutzt fallback. Für expo-notifications im Push-Use-Case sollte ein dedicated white-icon hinterlegt werden | | Manifest Permissions | ✅ | INTERNET, BIND_VPN_SERVICE, BIND_ACCESSIBILITY_SERVICE, FOREGROUND_SERVICE, POST_NOTIFICATIONS, RECORD_AUDIO etc. drin | | VpnService + AccessibilityService | ✅ | im Manifest deklariert (Zeile 38-48). **Risk:** Google Play prüft AccessibilityService-Apps streng (Use-Disclosure-Form pflicht). Empfehlung unten | | Data-Safety-Form | 🔴 | Pflicht-Form in Play Console — User muss DSGVO-Selbstauskunft ausfüllen | | Content-Rating | 🔴 | Erwartet PEGI 12+ wegen Glücksspiel-Thematik; Form muss vor Internal-Submit ausgefüllt werden | ### Cross-Platform | Item | Status | Detail | |---|---|---| | Versionierung sync (app.config.ts ↔ ios ↔ android) | 🟡 | `app.config.ts:7 version="0.1.0"` ↔ Info.plist `CFBundleShortVersionString=0.1.0` ↔ android `versionName="0.1.0"`. Synchron, aber mehrfache Locations → Sync-Skript fehlt | | Privacy-Policy URL (öffentlich erreichbar) | 🔴 | NICHT gefunden im App-Code. **Pflicht** für App Store + Play Store. URL z.B. `https://rebreak.org/privacy` muss live sein | | Imprint/Impressum URL | 🔴 | dito | | Test-Account-Credentials für Reviewer | 🔴 | Erst External-Review-relevant, für Internal not blocking | | `apiUrl`-Default im Build | 🟡 | `https://staging.rebreak.org` als fallback in app.config.ts:91 — für TF/Play-Internal sollte ein Production-API gewählt werden ODER explizit dokumentiert werden, dass Tester Staging-Backend nutzen | | Supabase-Anon-Key hardcoded | 🟡 | app.config.ts:103 hat hardcoded staging anon-key (Comment sagt: temp bis BFF-Migration in Phase 5). Anon-Key ist designed für Client-Ship, RLS protected — aber für Production-Build sollte besser via env-Var injected werden | --- ## Internal-Only-Pfad (3 Tage — realistisch für Wochenende) **Nötiger Minimalumfang für TestFlight Internal + Play Console Internal Testing:** 1. **`eas.json` schreiben** mit 2-3 Profilen (development, preview, production-internal) 2. **Apple Developer Account** aktiv + ASC-App "ReBreak" erstellen (User-Action) 3. **Play Console** App-Entry für `org.rebreak.app` erstellen, Internal Testing Track aktiv (User-Action) 4. **EAS Login** + projekt initialisieren (`eas init` → projectId in app.config.ts speichern) 5. **EAS managed credentials**: `eas credentials` für iOS (cert + provisioning) und Android (Keystore generieren lassen ODER existing hochladen) 6. **iOS APS-Environment** → für production-Build via EAS-Profile auf `production` setzen 7. **Build triggern:** `eas build --platform ios --profile production` + `eas build --platform android --profile production` (kostet je 1 Build-Quota — User-Approval) 8. **Submit:** `eas submit --platform ios` (lädt automatisch zu TestFlight) + `eas submit --platform android --track internal` 9. **TestFlight Internal Tester** in ASC einladen (User per Email-Liste) 10. **Play Console Internal Tester** in Play Console einladen (Email-Liste oder Google-Group) **Was Internal NICHT braucht (im Gegensatz zu External/Production):** - Apple-Review (nur External Beta + Public) - Google-Review (nur Closed/Open Testing + Production) - Privacy-Policy-URL hardcoded sichtbar (nur für Listing) - Screenshots, Feature-Graphic, Beschreibung - Data-Safety-Form (technisch ja, aber für Internal nicht streng durchgesetzt — sollte trotzdem ausgefüllt werden) - Content-Rating --- ## External-Beta-Pfad (zusätzlich, ~1 Woche) Wenn ihr nach Internal-Test auf External (TestFlight Public Link / Play Closed-Test) gehen wollt: - ✅ Privacy-Policy-URL live unter `https://rebreak.org/privacy` (DSGVO-konform, mit Lyra-Memory + Auto-Extract-Klauseln, Hans-Müller-DSB review) - ✅ Imprint live unter `https://rebreak.org/imprint` - ✅ App Store Listing: 8+ Screenshots (iPhone 6.5", 5.5"), App-Beschreibung DE/EN - ✅ Play Store Listing: 8+ Screenshots Phone, Feature-Graphic 1024×500, Beschreibung DE/EN - ✅ Data-Safety-Form Play Console - ✅ App-Content-Rating Play Console (~PEGI 12+) - ✅ Apple-Review Notes: Demo-Account-Credentials, Hinweis dass Subscription über Web läuft (nicht IAP) - ✅ Apple Sign-In wirklich implementiert (nicht TODO) — wenn Google-OAuth bleibt, Apple-Sign-In-Pflicht - ✅ AccessibilityService Disclosure-Form Play Console (warum BIND_ACCESSIBILITY_SERVICE nötig — App-Schutz vor Glücksspiel-Apps) --- ## Risk-Assessment ### R1 — Stripe-IAP-Konflikt (HOCH für External, MITTEL für Internal) Apple lehnt Apps für "digital goods" ab wenn nicht via IAP gekauft. Rebreak hat Pro/Legend-Subscription via Stripe. **Aktueller App-Code zeigt KEINEN Upgrade-Button** — nur `Alert.alert("Upgrade nötig")` ohne Stripe-Link. Das ist Apple-konformer Workaround: - App informiert User dass Pro nötig ist - Kein Link zur Web-Bezahlseite (Apple verbietet das im App-Body) - User abonniert auf rebreak.org/web (extern) - App nutzt aktiviertes Abo **Empfehlung:** für Internal-Build OK lassen. Vor External-Submit Apple-Reviewer-Note schreiben: *"Subscriptions are sold exclusively on rebreak.org. The app does not contain purchase flows. Pro features unlock automatically when the user's web account holds an active subscription."* ### R2 — VPN-Filter-Inclusion im Build (MITTEL) Native Module `rebreak-protection` ist via `app.config.ts plugins`-Block aktiv. iOS NEFilter Extension + Android VpnService + AccessibilityService sind im Build mit drin. Für **erstes Internal-TestFlight** ist das Risiko: - iOS: NEFilterDataProvider braucht spezielle Entitlement-Approval von Apple (Network Extensions). Falls Apple Account das nicht hat → Build schlägt beim Codesign fehl. - Android: AccessibilityService braucht in Play Console eine Use-Disclosure beim Submit; ohne Form lehnt Google ab. **User-Decision nötig:** Soll VPN-Filter im ersten TestFlight/Play-Internal-Build sein, oder erst V2? **Empfehlung:** für Internal Test OK behalten (kein Review), für External/Prod muss Disclosure-Form + Apple-Entitlement-Antrag laufen. ### R3 — Apple Sign-In TODO (MITTEL für External) `stores/auth.ts:82-87` ist TODO. UI zeigt aber Apple-Pill. Bei External-Beta verlangt Apple Sign-In-with-Apple wenn andere 3rd-Party-Logins (Google) da sind — Pflicht-Guideline 4.8. Für Internal ist das egal (kein Review). ### R4 — Production-Keystore-Custody (HOCH) Aktuell ist nur Debug-Keystore eingerichtet. Bei eigenem Keystore: User hält Passwort, Backup-Pflicht (verloren = Update-Path tot). **Empfehlung:** EAS managed Credentials (EAS hält Keystore, ist Industry-Standard, kein User-Custody-Stress). ### R5 — Hardcoded Supabase Anon-Key in app.config.ts (NIEDRIG) `app.config.ts:103` hat hardcoded staging anon key. Anon-keys sind designed for client-ship (RLS protected DB). Aber für Production sollte env-injection. Internal-Build OK. ### R6 — Backend-API-Pointer für Tester (MITTEL) `apiUrl` default ist `https://staging.rebreak.org`. Tester nutzen also Staging-DB. Wenn Prod-DB getrennt: Datenstand divergent. **User-Decision:** Internal-Tester gegen Staging oder schon Prod-Backend? --- ## TODO-Liste sortiert nach Tag ### Donnerstag 2026-05-07 (HEUTE — Recon + Doc) - [x] `RELEASE_READINESS.md` schreiben - [ ] **User:** Antworten auf Open Questions (siehe unten) - [ ] **User-Bestätigung:** TestFlight & Play-Internal-Targeting (Internal-only oder gleich External?) ### Freitag 2026-05-08 (Setup + Configs, alles ohne Build-Trigger) - [ ] zied: `eas.json` mit production-Profile schreiben (User reviewt vor Commit) - [ ] zied: `app.config.ts` cleanup wenn nötig (env-vars für apiUrl) - [ ] zied: Privacy-Policy + Imprint Stub-Pages (oder im rebreak-backend webroot deployen — Koordination mit rebreak-ops) - [ ] **User:** Apple Developer Account-Status verifizieren ($99/Jahr aktiv?) - [ ] **User:** ASC-App "ReBreak" erstellen (Bundle org.rebreak.app) - [ ] **User:** Play Console App-Entry erstellen + Internal-Test-Track + Tester-Liste - [ ] **User:** `eas login` + `eas init` (nur User kann sich einloggen) - [ ] **User:** Decision EAS-managed Credentials vs eigener Keystore - [ ] zied: VersionCode-Bump-Pattern dokumentieren ### Samstag 2026-05-09 (Build + Submit, alles mit User-Approval) - [ ] **User-Approval + Trigger:** `eas build --platform ios --profile production-internal` - [ ] **User-Approval + Trigger:** `eas build --platform android --profile production-internal` - [ ] zied: Build-Output validieren (size, sha) - [ ] **User-Approval + Trigger:** `eas submit --platform ios` (TestFlight) + `eas submit --platform android --track internal` - [ ] **User:** TestFlight Tester-Emails einladen via ASC - [ ] **User:** Play Console Internal-Tester-Emails einladen - [ ] zied: Smoke-Test-Plan auf User-Device (Install, Login, Streak, Lyra-Chat 1 Roundtrip) ### Sonntag 2026-05-10 (Buffer + Iteration) - [ ] Bugfix-Round 1 falls Tester-Feedback (rebreak-native-ui handled UI-Bugs) - [ ] Falls neue Build nötig: versionCode++ → re-upload --- ## Top-5 User-Actions die nicht verschoben werden können 1. **Apple Developer Account login + ASC-App-Entry erstellen** (org.rebreak.app, Bundle-ID, App-Name "ReBreak"). Ohne ASC-Entry kein TestFlight. 2. **Play Console App-Entry + Internal-Track aktivieren** für `org.rebreak.app`. Ohne Track kein Internal-Upload. 3. **`eas login` + `eas init`** im `apps/rebreak-native/` ausführen — registriert Projekt + speichert projectId. 4. **Decision EAS-managed-Credentials vs eigener Keystore** + ggf. Keystore-Passwort generieren/sichern (User-Custody, NIEMALS commit). 5. **Privacy-Policy + Imprint live unter rebreak.org-URLs** — auch für Internal empfohlen (Vermeidet Hick-Up beim späteren External-Switch). Für External strikt Pflicht. --- ## Realistischer Wochenend-Plan — Machbarkeit **Ja, Internal-TestFlight + Play-Internal sind machbar bis Sonntag 2026-05-10**, sofern: - Apple Dev Account heute/morgen früh reaktiviert/bestätigt - User Freitag Mittag verfügbar für `eas login` + ASC/Play-Console-Setup - Keine Apple-Entitlement-Hick-Ups beim ersten iOS-Codesign (NEFilter braucht Entitlement-Approval — falls Apple Account das nicht hat, müssen wir die Plugin-Aktivierung temporär entfernen für Internal Build → V2 mit VPN-Filter) - EAS-Build-Quota verfügbar (Free-Tier hat ~30 Builds/Monat — sollte reichen) **Realistischer Risk-Pfad:** Falls iOS-NEFilter-Entitlement nicht da ist, Plan B = Internal-TestFlight ohne VPN-Filter-Plugin (1-Line plugin-comment-out) → User-Test der Core-Loop (Streak/Lyra/Posts/Games) ohne Blocker-Feature. VPN-Filter dann V2. **External-Beta (TestFlight Public Link / Play Closed-Test) Wochenend-Ziel = NICHT realistisch.** Privacy-Policy-Live + Apple-Review-Process + Sign-In-with-Apple-Implementierung würden mind. 1 weitere Woche brauchen. --- ## 3 wichtigste Open Questions an User ### Q1 — VPN-Filter im ersten Build dabei oder rauslassen? Plugins `with-rebreak-protection-ios` (NEFilter Extension) + `with-rebreak-protection-android` (VpnService + AccessibilityService) sind aktiv. Risk bei NEFilter: braucht spezielle Apple-Entitlement (Network Extensions Capability), die nicht im Standard-Dev-Account drin ist — muss von Apple separat genehmigt werden (1-2 Wochen Wartezeit historisch). **Optionen:** - (A) NEFilter+VpnService dabei → erstmaliger Build kann an Codesign scheitern, falls Entitlement fehlt - (B) Plugins temporär raus (1-Line Comment in app.config.ts), Core-App testflighten, VPN-Filter V2 mit eigenem Build-Cycle - (C) Erst Apple-Entitlement-Status prüfen (User-Login ASC), dann entscheiden ### Q2 — Backend-API-Pointer für Internal-Tester: Staging oder Prod? Default `apiUrl=https://staging.rebreak.org`. Tester schreiben dann in Staging-DB. Wenn Prod-DB schon läuft: Daten-Inkonsistenz. Wenn Test-DB OK: weiter mit Staging. **Meine Empfehlung:** Internal-Tester auf Staging (klarer Test-Modus, keine Vermischung mit Production-User). Externe Beta dann auf Prod. ### Q3 — Keystore-Strategie Android: EAS managed oder eigener Custody? EAS managed = EAS speichert keystore verschlüsselt, kein User-Custody, automatisch im Build verwendet. Industry-Standard. Recovery via Expo-Account. Eigener = User generiert keystore lokal, hält Passwort, lädt zu EAS hoch via `eas credentials`. Mehr Kontrolle, mehr Custody-Risk. **Meine Empfehlung:** EAS managed für Wochenend-Speed, später kann User keystore mit `eas credentials --platform android` exportieren wenn Custody gewünscht.