community/posts.get.ts + social/profile/[userId].get.ts lieferten neben nickname auch username an fremde Clients — username ist der Login- Identifikator ({username}@rebreak.internal) und verletzt die Nickname- Anonymitäts-Invariante (REQ-COMM-005 / R-DATA-07) + exponiert das halbe Login-Credential-Paar. Frontend rendert das Feld nirgends (verifiziert); totes Typ-Feld in stores/community.ts entfernt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rebreak Native (React Native + Expo)
Mobile App für iOS + Android. Migration von Nuxt+Capacitor → React Native+Expo. Migration-Plan:
apps/rebreak/docs/react-native-migration.md
Status
Phase 1 — Foundation Skeleton (2026-05-02)
- Verzeichnisstruktur
package.jsonmit Expo SDK 53 + RN 0.76 (New Architecture)app.config.ts(Expo, Bundle-IDorg.rebreak.app)- Expo Router Skeleton
- NativeWind Setup (Tailwind für RN)
- Metro Config (pnpm Monorepo aware)
- Supabase Client + API Wrapper
pnpm install— vom User auszuführenexpo prebuild— generiertios/+android/Bare-Projekte- Native Module Imports (NEFilter, VpnService, A11y) — Phase 5+
Setup
# vom Monorepo-Root:
pnpm install
# Native-Projekte generieren (lokal, nicht committed)
cd apps/rebreak-native
pnpm prebuild
# Run
pnpm ios # iOS Simulator
pnpm android # Android Emulator
Stack
| Bereich | Lib |
|---|---|
| Framework | React Native 0.76 (New Architecture) + Expo SDK 53 |
| Routing | Expo Router (file-based) |
| State | Zustand |
| Server State | TanStack Query (React Query) |
| Styling | NativeWind 4 (Tailwind) |
| Forms | React Hook Form + Valibot |
| i18n | react-i18next |
| Auth | @supabase/supabase-js + AsyncStorage |
| Animation | react-native-reanimated, lottie-react-native |
| Storage | react-native-mmkv (fast key-value) |
Verzeichnisstruktur
apps/rebreak-native/
├── app/ # Expo Router (file-based routes)
│ ├── _layout.tsx # Root Stack
│ ├── index.tsx # Landing (auth oder app entscheiden)
│ ├── (auth)/ # Auth-Flow (signin, signup, forgot-password)
│ └── (app)/ # Authenticated App (tabs)
├── components/ # Reusable UI Components
├── hooks/ # Custom React Hooks
├── stores/ # Zustand Stores
├── lib/ # Supabase Client, API Wrapper, Utils
│ ├── supabase.ts
│ └── api.ts
├── locales/ # de.json, en.json
├── modules/ # Custom Expo Native Modules
│ ├── rebreak-ios-filter/ # NEFilter + Tunnel (Phase 5)
│ ├── rebreak-android-blocker/ # VpnService + DnsFilter (Phase 6)
│ └── rebreak-android-a11y/ # AccessibilityService (Phase 6)
├── plugins/ # Expo Config Plugins
└── assets/ # Icons, Splashscreens, Fonts
Dev-Variant (Hot-Reload parallel zur MDM-App)
Die MDM-managed Dist-App (org.rebreak.app) ist non-removable auf dem iPhone Air.
Der Dev-Build nutzt eine separate Bundle-ID (org.rebreak.app.dev) und kann parallel installiert werden.
Erstmaliges Setup (nur einmal nötig)
# 1. Dev-Build starten — schlägt beim ersten Mal wegen Signing-Bundle fehl
REBREAK_DEV=1 ./dev-build.sh --clean
# Wenn Xcode "No profiles for 'org.rebreak.app.dev'" meldet:
# a) open ios/ReBreak.xcworkspace
# b) Targets → ReBreak → Signing & Capabilities
# c) Team auf "84BQ7MTFYK" setzen — Xcode registriert Bundle-ID automatisch
# d) Xcode schliessen, nochmal ausführen:
REBREAK_DEV=1 ./dev-build.sh --clean
Täglicher Workflow
# Vollbuild (nach native-code Änderungen oder erstem Mal):
./dev-build.sh
# Nur Metro (wenn Dev-App schon auf iPhone, reine JS-Änderungen):
./dev-build.sh --metro-only
# Nuclear clean + rebuild (nach Plugin/Pod-Änderungen):
./dev-build.sh --clean
Wichtige Unterschiede Dev vs. Dist
Dev (org.rebreak.app.dev) |
Dist (org.rebreak.app) |
|
|---|---|---|
| App-Name | ReBreak Dev | ReBreak |
| Splash-Color | #1e3a5f (dunkles Blau) | #0f172a (schwarz) |
| URL-Scheme | rebreak-dev:// |
rebreak:// |
| App-Group | group.org.rebreak.app (geteilt) |
group.org.rebreak.app |
| Hot-Reload | via Metro | nein |
| MDM-managed | nein | ja (non-removable) |
App-Group ist bewusst geteilt — Dev-Build kann blocklist.bin lesen und Sideload-Profile-Verhalten testen ohne MDM-Push.
Prod-Build bleibt unverändert
deploy-adhoc.sh und deploy-tf.sh setzen REBREAK_DEV nicht
→ landen automatisch auf org.rebreak.app.
Wichtige Konfiguration
| Datei | Zweck |
|---|---|
app.config.ts |
Expo App-Config (Bundle-ID, Permissions, Plugins) |
metro.config.js |
Monorepo-aware Metro (Symlinks, Workspace-Folders) |
babel.config.js |
NativeWind Preset + Reanimated Plugin |
tailwind.config.js |
Tailwind Config — Brand-Colors aus apps/rebreak/ syncen |
global.css |
NativeWind Tailwind-Imports |
Native Module Strategie
Bestehender Native-Code aus apps/rebreak/ios/ + apps/rebreak/android/ wird in Expo Native Modules gewrappt — ohne neu zu schreiben.
iOS — modules/rebreak-ios-filter/
Wrapped:
RebreakURLFilter(NEFilterDataProvider) → blockt bet365 etc.RebreakTunnel(NEPacketTunnelProvider) → DNS-Filter
Android — modules/rebreak-android-blocker/
Wrapped:
RebreakVpnService(Kotlin) → VpnService DNS-FilterDnsFilter+HashList+DomainHasher
Android — modules/rebreak-android-a11y/
Wrapped:
RebreakAccessibilityService→ Detection von Gambling-Apps
⚠️ Wichtige Hinweise
- Schutz-Stack bleibt 1:1 erhalten — Swift- und Kotlin-Code wandert unverändert in
modules/. - Backend bleibt in
apps/rebreak/server/— RN ruft die gleichen Endpoints. - Alte Capacitor-App bleibt deployed bis RN-App im Store ist.
- Kein Auto-Commit — User entscheidet wann committet wird.
Release-Pipeline
Multi-Target Deploy (deploy-app.sh)
Ein einziges Script baut und deployed alle drei Release-Targets:
# Default: Alle drei Targets (MDM + TestFlight + Android)
./deploy-app.sh --bump
# Nur spezifische Targets
./deploy-app.sh --mdm-only # Nur MDM (Ad-Hoc iOS)
./deploy-app.sh --tf-only # Nur TestFlight
./deploy-app.sh --android-only # Nur Android (EAS → Play-Console)
# Targets selektiv überspringen
./deploy-app.sh --skip-mdm --bump # TestFlight + Android
./deploy-app.sh --skip-android # Nur iOS (MDM + TF)
# Version-Bumping
./deploy-app.sh --bump # iOS buildNumber++, Android versionCode++
./deploy-app.sh --version 0.4.0 # Explizite SemVer
./deploy-app.sh --android-version-code 15 # Override Android versionCode
# Dry-Run (alles simulieren)
./deploy-app.sh --dry-run --bump
Was passiert pro Target
| Target | Pipeline | Output |
|---|---|---|
| MDM | deploy-adhoc.sh → xcodebuild → scp upload |
MDM-Push via NanoMDM (systemd-watcher) |
| TestFlight | deploy-tf.sh → altool upload |
ASC → Internal Testing (~5-15min) |
| Android | EAS Cloud-Build → Play-Console | Internal-Track (~10-30min Processing) |
Android-Vorbereitung (einmalig)
Android-Submit benötigt serviceAccountKeyPath in eas.json:
- Google-Cloud-Service-Account erstellen (Play-Console-Zugriff)
- JSON-Key downloaden (z.B.
~/secrets/rebreak-play-service-account.json) - In
eas.jsoneintragen:"submit": { "production": { "android": { "serviceAccountKeyPath": "~/secrets/rebreak-play-service-account.json", "track": "internal" } } } - NIEMALS committen (liegt in
.gitignore)
Falls noch nicht konfiguriert → Script bricht mit klarer Fehlermeldung ab.
Changelog
Changelog-Updates erfolgen bei --bump automatisch für iOS (via deploy-adhoc.sh intern) und Android (via deploy-app.sh).
Alte Scripts (weiterhin nutzbar)
deploy-adhoc.sh— MDM (Ad-Hoc iOS) standalonedeploy-tf.sh— TestFlight standalone (wiederverwendet xcarchive)eas-release.sh— EAS Cloud-Build (manueller Wrapper, KEIN Version-Bumping)
deploy-app.sh ist die empfohlene All-in-One-Lösung.
Phasen-Tracker
Siehe Migration-Plan für Details: apps/rebreak/docs/react-native-migration.md