import { ExpoConfig, ConfigContext } from "expo/config"; export default ({ config }: ConfigContext): ExpoConfig => ({ ...config, name: "ReBreak", slug: "rebreak", version: "0.3.4", orientation: "portrait", icon: "./assets/icon.png", scheme: "rebreak", userInterfaceStyle: "automatic", newArchEnabled: true, splash: { image: "./assets/icon.png", resizeMode: "contain", backgroundColor: "#0f172a", }, ios: { supportsTablet: true, bundleIdentifier: "org.rebreak.app", buildNumber: "13", // Apple Sign-In Entitlement — Pflicht für expo-apple-authentication nativen // signInAsync()-Flow. Ohne flag generiert Expo's prebuild den // com.apple.developer.applesignin-Entitlement nicht in die .entitlements. usesAppleSignIn: true, config: { usesNonExemptEncryption: false, }, infoPlist: { ITSAppUsesNonExemptEncryption: false, NSMicrophoneUsageDescription: "Rebreak nutzt das Mikrofon für Sprachnachrichten an Lyra.", NSPhotoLibraryUsageDescription: "Rebreak greift auf Fotos zu, damit du sie in deinen Posts teilen kannst.", NSPhotoLibraryAddUsageDescription: "Rebreak speichert Bilder in deine Foto-Mediathek.", NSFaceIDUsageDescription: "Rebreak nutzt Face ID, um die App zu entsperren — damit niemand außer dir sie öffnen kann.", }, }, android: { package: "org.rebreak.app", versionCode: 10, adaptiveIcon: { // Foreground muss in der ~66%-Safe-Zone bleiben (Launcher-Mask clippt den // Außenring) → adaptive-foreground.png ist das Logo auf transparentem // 1024er-Canvas mit ~19% Padding. Hintergrund weiss → matcht den // Play-Console-Look (dunkles Logo auf Weiss), statt dunkel-auf-dunkel. foregroundImage: "./assets/adaptive-foreground.png", backgroundColor: "#ffffff", }, permissions: [ "INTERNET", "ACCESS_NETWORK_STATE", "BIND_VPN_SERVICE", "FOREGROUND_SERVICE", "POST_NOTIFICATIONS", "BIND_ACCESSIBILITY_SERVICE", "RECORD_AUDIO", ], }, plugins: [ "expo-router", "expo-localization", "expo-font", "expo-web-browser", [ "expo-build-properties", { ios: { deploymentTarget: "15.1", useFrameworks: "static", }, android: { minSdkVersion: 26, compileSdkVersion: 36, targetSdkVersion: 36, }, }, ], // Xcode 16 + RN 0.79 fmt consteval workaround "./plugins/with-fmt-consteval-fix", // Xcode 14+ resource-bundle-signing fix (needed because useFrameworks: static) "./plugins/with-resource-bundle-signing-fix", // Phase 5: NEFilter Extension + Family Controls Entitlements (iOS) "./plugins/with-rebreak-protection-ios", // Phase 5: VpnService + AccessibilityService (Android) "./plugins/with-rebreak-protection-android", // Rive-Asset (lyra-avatar.riv) als Android raw-resource bundlen "./plugins/with-rive-asset-android", // MaterialComponents-Theme-Fix für BadgeDrawable in react-native-bottom-tabs "./plugins/with-material-theme-android", // Release-Signing-Block in build.gradle (liest android/key.properties — nicht committen) "./plugins/with-release-signing-android", ], experiments: { typedRoutes: true, }, extra: { eas: { projectId: "a4f2186e-8ca5-4d38-921d-82ae96c9c086", // EAS muss VOR dem Build wissen, dass es eine App-Extension gibt — sonst // generiert es nur Credentials für die Haupt-App und der Xcode-Build kippt // mit "No profiles for 'org.rebreak.app.URLFilterExtension' were found". // Bundle-ID + Entitlements müssen exakt zu plugins/with-rebreak-protection-ios.js // und modules/rebreak-protection/ios/RebreakURLFilterExtension/ passen. build: { experimental: { ios: { appExtensions: [ { targetName: "RebreakURLFilterExtension", bundleIdentifier: "org.rebreak.app.URLFilterExtension", entitlements: { "com.apple.developer.networking.networkextension": [ "url-filter-provider", ], "com.apple.security.application-groups": [ "group.org.rebreak.app", ], }, }, ], }, }, }, }, // Family Controls (denyAppRemoval via ManagedSettings) braucht ein // DISTRIBUTION-Entitlement das noch bei Apple zur Freigabe liegt. Ohne das // Entitlement blockt iOS den ManagedSettingsAgent-XPC auf Sandbox-Ebene // (NSCocoaErrorDomain:4099 "Sandbox restriction" — verifiziert in Build 11). // // Der Wert MUSS mit dem Entitlement-Gating im Plugin übereinstimmen: // plugins/with-rebreak-protection-ios.js setzt das family-controls-Entitlement // mit derselben Bedingung. Family Controls ist Kern-Funktion und Apples // Distribution-Entitlement ist freigegeben (v0.3.4) → DEFAULT AN. Nur ein // explizites `REBREAK_ENABLE_FAMILY_CONTROLS=0` schaltet es ab (Escape-Hatch // für FC-lose Test-Builds). Konsequenz: jeder Build braucht ein // Provisioning-Profil mit FC-Capability — für den ReBreak-Apple-Account gegeben. familyControlsEnabled: process.env.REBREAK_ENABLE_FAMILY_CONTROLS !== "0", // iOS-NEURLFilter / PIR-Server. Der Auth-Token kommt aus der Build-Umgebung // (Infisical staging/PIR_AUTH_TOKEN) — NIEMALS committen. Lokaler Dev-Build: // `PIR_AUTH_TOKEN=… npx expo run:ios --device`. pirServerURL: process.env.PIR_SERVER_URL || "https://pir.staging.rebreak.org", pirAuthToken: process.env.PIR_AUTH_TOKEN || "", apiUrl: process.env.EXPO_PUBLIC_API_URL || process.env.API_URL || "https://staging.rebreak.org", // TEMP: Staging Anon-Key + URL hardcoded für lokales Dev-Testing. // Anon-Key ist designed für Client-Ship (RLS protectiert DB). Trotzdem: // BFF-Migration kommt in Phase 5 — dann fliegen diese 2 Zeilen wieder raus. supabaseUrl: process.env.EXPO_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL || "https://db-staging.rebreak.org", supabaseAnonKey: process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY || process.env.SUPABASE_KEY || process.env.SUPABASE_ANON_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsImF1ZCI6ImF1dGhlbnRpY2F0ZWQiLCJyb2xlIjoiYW5vbiIsImV4cCI6MjA5MTAxODk1NSwiaWF0IjoxNzc1NjU4OTU1fQ.93d2r3pft2E-alf1JezqueD0l0n1dim7dGvhBN0l1Cs", }, });