diff --git a/mobile_app/app.json b/mobile_app/app.json index b2e8222..5c30c63 100644 --- a/mobile_app/app.json +++ b/mobile_app/app.json @@ -108,14 +108,6 @@ "@magicred-1/react-native-lxmf", "./plugins/withAndroidForegroundService", "expo-web-browser", - [ - "@sentry/react-native", - { - "organization": "anonmesh", - "project": "react-native", - "url": "https://sentry.io/" - } - ], "expo-audio" ], "experiments": { diff --git a/mobile_app/context/NetworkModeContext.tsx b/mobile_app/context/NetworkModeContext.tsx index 08fc2e7..bc844b4 100644 --- a/mobile_app/context/NetworkModeContext.tsx +++ b/mobile_app/context/NetworkModeContext.tsx @@ -107,9 +107,9 @@ export function NetworkModeProvider({ children }: { readonly children: ReactNode const adapter = useMemo(() => { if (mode === "online") return new DirectRpcAdapter(solanaConnection); - if (mode === "mesh") return new MeshRpcAdapter(meshHash, beaconRpcWait); + if (mode === "mesh") return new MeshRpcAdapter(meshHash, beaconBroadcastRpc); return new IsolatedRpcAdapter(); - }, [mode, meshHash, beaconRpcWait]); + }, [mode, meshHash, beaconBroadcastRpc]); const value = useMemo( () => ({ mode, adapter, relayHash: adapter.relayHash }), diff --git a/mobile_app/metro.config.js b/mobile_app/metro.config.js index a016d7c..327c836 100644 --- a/mobile_app/metro.config.js +++ b/mobile_app/metro.config.js @@ -1,10 +1,9 @@ -// getSentryExpoConfig wraps Expo's default Metro config to enable source-map -// upload for crash symbolication. It is a drop-in for getDefaultConfig; if the -// Sentry integration is ever removed, swap this line back to getDefaultConfig. -const { getSentryExpoConfig } = require('@sentry/react-native/metro'); +// Plain Expo Metro config. (Sentry's getSentryExpoConfig wrapper was removed +// along with @sentry/react-native.) +const { getDefaultConfig } = require('expo/metro-config'); const path = require('node:path'); -const config = getSentryExpoConfig(__dirname); +const config = getDefaultConfig(__dirname); config.resolver.unstable_enablePackageExports = true; config.resolver.unstable_conditionNames = [ diff --git a/mobile_app/src/observability/sentry.ts b/mobile_app/src/observability/sentry.ts index aecb2be..3c0346c 100644 --- a/mobile_app/src/observability/sentry.ts +++ b/mobile_app/src/observability/sentry.ts @@ -1,60 +1,44 @@ /** - * Crash/error observability — Sentry, crash-only, privacy-scrubbed. + * Crash/error observability — Sentry removed. * - * Scope is deliberately narrow: unhandled JS/native crashes + handled React - * errors. NO product analytics, NO user identity, NO performance tracing. - * See AI Briefs/Anonmesh/telemetry.md for the rationale. + * `@sentry/react-native` was removed: its native Gradle step (`sentry.gradle` + * source-map/symbol upload via `sentry-cli`) broke CI, and the app opted out of + * third-party crash reporting. This is a no-op shim that preserves the former + * import surface (`Sentry`, `initObservability`, `observabilityEnabled`) so + * `app/_layout.tsx` and `ErrorBoundary.tsx` compile and run unchanged. The + * ErrorBoundary still renders its fallback UI — it just no longer reports. * - * KILL SWITCH: this is a no-op unless EXPO_PUBLIC_SENTRY_DSN is set AND the - * build is not __DEV__. Unset the env var (or delete this module's call site in - * app/_layout.tsx) and the app sends nothing. Nothing here runs in development. + * The `errorHandler` global handler (console.error + native crash path) is + * unaffected and remains the crash signal. */ -import * as Sentry from '@sentry/react-native'; -import type { ErrorEvent, Breadcrumb } from '@sentry/react-native'; -import { scrubDeep } from './scrub'; +/** Always false — Sentry is gone. Kept for callers that gate on it. */ +export const observabilityEnabled = false; -const DSN = process.env.EXPO_PUBLIC_SENTRY_DSN; - -/** - * Telemetry is OFF in development and OFF whenever no DSN is configured. A - * release build with no DSN ships completely inert — this is the removal path. - */ -export const observabilityEnabled = Boolean(DSN) && !__DEV__; - -function beforeSend(event: ErrorEvent): ErrorEvent { - // Belt-and-suspenders: never attach a user even if something tries to. - delete event.user; - return scrubDeep(event); -} - -function beforeBreadcrumb(crumb: Breadcrumb): Breadcrumb | null { - // Navigation breadcrumbs can carry route params (e.g. ?to=
) — drop - // their data and keep only the scrubbed message text. - if (crumb.data) crumb.data = {}; - return scrubDeep(crumb); -} - -/** - * Initialise crash observability. Safe to call unconditionally — it no-ops - * unless {@link observabilityEnabled}. Call once at app entry, before render. - */ +/** No-op: Sentry removed. Safe to call once at app entry. */ export function initObservability(): void { - if (!observabilityEnabled) return; + /* no-op */ +} - Sentry.init({ - dsn: DSN, - enabled: true, - // Crash-only: no performance/tracing spans, no profiling. - tracesSampleRate: 0, - // Never collect IP, cookies, or default request PII. - sendDefaultPii: false, - // Keep breadcrumb history short; they are scrubbed but fewer is safer. - maxBreadcrumbs: 30, - attachStacktrace: true, - beforeSend, - beforeBreadcrumb, - }); +interface NoopScope { + setTag(key: string, value: string): void; + setContext(key: string, value: Record | null): void; } -export { Sentry }; +const noopScope: NoopScope = { + setTag: () => {}, + setContext: () => {}, +}; + +/** No-op stand-in for the `@sentry/react-native` API the app referenced. */ +export const Sentry = { + wrap(component: T): T { + return component; + }, + withScope(callback: (scope: NoopScope) => void): void { + callback(noopScope); + }, + captureException(_error: unknown): void { + /* no-op */ + }, +};