Neuer iOS-Layer-1-Filter: ein NEPacketTunnelProvider-DNS-Sinkhole — MDM-frei, ab iOS 16, Parität zum Android-VPN-DNS-Filter. Ersetzt den Apple-seitig blockierten NEURLFilter als Default. NEURLFilter-/PIR-Code bleibt inaktiv als iOS-26-Upgrade-Pfad erhalten (User-Entscheidung). Neues Extension-Target RebreakPacketTunnelExtension/: - PacketTunnelProvider.swift — TUN-Setup (virtuelle DNS-IP 10.0.0.1, nur diese Route ins TUN), Read-Loop, NXDOMAIN-Sinkhole, Upstream-Forward via NWConnection zu 1.1.1.1, Blocklist-Reload via Darwin-Notification. - DnsFilter.swift / HashList.swift / DomainHasher.swift — Swift-Ports der Android-DNS-Filter-Logik. blocklist.bin-Format (sortierte big-endian UInt64, SHA-256-Prefix) 1:1 beibehalten, mmap statt Heap-Load. RebreakProtectionModule.swift: - activateUrlFilter startet jetzt den Packet-Tunnel via NETunnelProviderManager (Default-Layer-1, On-Demand-Auto-Reconnect aktiv). - NEURLFilter-Code in activateNeUrlFilter ausgelagert (inaktiv, behalten). - getDeviceState/disable lesen bzw. stoppen den Tunnel-Status. with-rebreak-protection-ios.js: zweites app_extension-Target, klassischer Embed-Pfad (dstSubfolderSpec 13), packet-tunnel-provider-Entitlement + App-Group. app.config.ts: zweites appExtensions-Target. NICHT auf echtem Gerät verifiziert — NE-Packet-Tunnel laufen nicht im Simulator. Ungetestete Annahmen im Code mit "UNGETESTETE ANNAHME" markiert. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
190 lines
7.5 KiB
TypeScript
190 lines
7.5 KiB
TypeScript
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: [
|
|
{
|
|
// Layer 1 (NEU, Default) — Packet-Tunnel-DNS-Filter.
|
|
// Bundle-ID + Entitlements müssen exakt zu
|
|
// plugins/with-rebreak-protection-ios.js (PT_BUNDLE_SUFFIX)
|
|
// und modules/rebreak-protection/ios/RebreakPacketTunnelExtension/
|
|
// passen, sonst kippt der EAS-Build mit
|
|
// "No profiles for 'org.rebreak.app.PacketTunnelExtension'".
|
|
targetName: "RebreakPacketTunnelExtension",
|
|
bundleIdentifier: "org.rebreak.app.PacketTunnelExtension",
|
|
entitlements: {
|
|
"com.apple.developer.networking.networkextension": [
|
|
"packet-tunnel-provider",
|
|
],
|
|
"com.apple.security.application-groups": [
|
|
"group.org.rebreak.app",
|
|
],
|
|
},
|
|
},
|
|
{
|
|
// Layer 1-alt — NEURLFilter (iOS 26). INAKTIV, behalten als
|
|
// optionaler Upgrade-Pfad. EAS muss das Target trotzdem kennen.
|
|
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",
|
|
},
|
|
});
|