Skip to content

fix: resolve native module hoisting failures for EAS monorepo builds#3

Merged
jpdevhub merged 1 commit into
mainfrom
fix/monorepo-build-config
May 23, 2026
Merged

fix: resolve native module hoisting failures for EAS monorepo builds#3
jpdevhub merged 1 commit into
mainfrom
fix/monorepo-build-config

Conversation

@jpdevhub
Copy link
Copy Markdown
Owner

@jpdevhub jpdevhub commented May 23, 2026

Problem

When building the Android app via EAS in our npm workspaces monorepo, the build crashed during the CMake/Gradle configuration phase.
Packages like react-native-worklets, react-native-reanimated, and react-native-gesture-handler were failing to find React Native's internal C++ and Gradle files (cmake-utils, gradle.properties, libs.versions.toml).
This happens because npm hoists both the native modules and react-native to the root node_modules, breaking the relative paths hardcoded into these native modules.

Solution

  1. Added withMonorepoFix Expo Plugin: Dynamically locates the hoisted react-native directory and creates symlinks for ReactAndroid, ReactCommon, and gradle in the root node_modules. This allows all C++ and Gradle path lookups to succeed natively.
  2. Added withReactNativePickerFix Expo Plugin: Specific fix for @react-native-picker/picker which required REACT_NATIVE_NODE_MODULES_DIR to be injected globally into build.gradle.
  3. Added Root Index Route: Created app/index.tsx to handle the root agronavis:/// deep link, preventing the app from crashing on the "Unmatched Route" screen on startup.

Verification

  • expo doctor passes (18/18 checks).
  • eas build -p android --profile preview completes successfully.
  • APK launches successfully directly into the Welcome Screen.

Closes #2


Summary by cubic

Fixes EAS Android builds in our npm workspaces monorepo by resolving hoisted react-native paths for native modules and adding a safe entry route. Builds now complete and the app opens on the welcome screen.

  • Bug Fixes

    • Added ./plugins/withMonorepoFix to find hoisted react-native and symlink ReactAndroid, ReactCommon, and gradle into root node_modules, restoring Gradle/CMake lookups for react-native-worklets, react-native-reanimated, react-native-gesture-handler, and react-native-svg.
    • Added ./plugins/withReactNativePickerFix to set REACT_NATIVE_DIR and REACT_NATIVE_NODE_MODULES_DIR for @react-native-picker/picker and RNGH across root and subprojects.
    • Added app/index.tsx redirect to handle agronavis:/// and avoid the unmatched route crash on cold start.
  • Dependencies

    • Pinned react-native-worklets to 0.5.1 and react-native-svg to 15.12.1, with workspace-level overrides and Expo install.exclude to prevent incompatible upgrades.

Written for commit 9ee837b. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Added authentication redirect on app launch.
    • Added audio recording permission support for mobile app.
    • Configured EAS build system for development, preview, and production environments.
  • Configuration

    • Updated mobile app package identifier and build dependencies.
    • Added asset bundling and monorepo compatibility fixes.
    • Pinned key native module versions for stability.

Review Change Stack

@jpdevhub jpdevhub self-assigned this May 23, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

📝 Walkthrough

Walkthrough

This PR configures an EAS monorepo build for the Agronavis mobile app by fixing native module hoisting failures, establishing Expo/EAS build settings, defining the app entry point, and pinning critical dependencies. Two custom Expo plugins resolve React Native path resolution issues that occur when native modules are hoisted during npm workspace installation.

Changes

EAS Monorepo Build Configuration and Mobile App Setup

Layer / File(s) Summary
Native Module Path Resolution—Monorepo Symlink Fix
apps/mobile/plugins/withMonorepoFix.js
withMonorepoFix Expo config plugin locates hoisted react-native and creates symlinks for ReactAndroid, ReactCommon, and gradle in the root node_modules, falling back to directory copy if symlink creation fails.
Native Module Path Resolution—React Native Picker Fix
apps/mobile/plugins/withReactNativePickerFix.js
withReactNativePickerFix Expo config plugin conditionally injects Groovy Gradle logic to resolve react-native and propagate REACT_NATIVE_DIR ext properties for native modules that require them.
Expo App Configuration and Plugin Wiring
app.json, apps/mobile/app.json
Expo app configuration adds asset bundle patterns, changes Android package to com.karolix.agronavis, adds RECORD_AUDIO permission, wires withMonorepoFix plugin, sets EAS project UUID, and includes router configuration.
EAS Build Configuration
eas.json, apps/mobile/eas.json
Root and mobile EAS configurations set CLI version constraints, remote app version sourcing, build profiles for development/preview/production with internal distributions, Android APK output, and npm legacy peer deps environment variable.
Mobile App Entry Point
apps/mobile/app/index.tsx
Root Index route component redirects users to the auth welcome screen using Expo Router Redirect, with comments marking where future auth gating logic should be added.
Dependency Versioning and Script Updates
apps/mobile/package.json, package.json
Mobile app scripts updated to use expo run:android/expo run:ios, dependencies pin react-native-worklets@0.5.1 and react-native-svg@15.12.1 across the monorepo, @types/react-native removed, and package overrides and Expo install exclusions enforce consistent native module versions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Symlinks dance in monorepo's weave,
Native paths found, builds now breathe,
Hoisting solved with plugins true,
Welcome routes and configs new.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: resolving native module hoisting failures for EAS monorepo builds, which is the core problem and solution implemented throughout the changeset.
Linked Issues check ✅ Passed All coding requirements from issue #2 are met: withMonorepoFix plugin locates hoisted react-native and creates symlinks [#2], withReactNativePickerFix plugin injects REACT_NATIVE_NODE_MODULES_DIR [#2], app/index.tsx handles root deep-link routing [#2], and configuration updates support the build pipeline [#2].
Out of Scope Changes check ✅ Passed All changes are directly related to resolving monorepo hoisting failures: plugin implementations, configuration updates for EAS/Expo, package.json overrides to pin problematic versions, and root routing setup align with issue #2 requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/monorepo-build-config

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/mobile/plugins/withReactNativePickerFix.js (1)

31-34: ⚡ Quick win

Use a plugin-specific marker instead of a broad REACT_NATIVE_DIR string check.

Current guard can skip injection on unrelated content matches; use a unique sentinel for deterministic idempotency.

Proposed patch
-    if (contents.includes("REACT_NATIVE_DIR")) {
+    if (contents.includes("_MONOREPO_PICKER_FIX_")) {
       // Already patched, skip
       return config;
     }

     const injection = `
-// ─── Monorepo Fix ────────────────────────────────────────────────────────────
+// _MONOREPO_PICKER_FIX_ ───────────────────────────────────────────────────────
+// ─── Monorepo Fix ────────────────────────────────────────────────────────────
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/mobile/plugins/withReactNativePickerFix.js` around lines 31 - 34, The
current idempotency check uses a broad string match on
contents.includes("REACT_NATIVE_DIR") which may collide with unrelated files;
change it to look for and insert a plugin-specific sentinel (e.g., a unique
comment like "// withReactNativePickerFix applied" or "/*
WITH_RN_PICKER_FIX_MARKER */") so the guard becomes
contents.includes("<UNIQUE_SENTINEL>") and the injection code adds that sentinel
along with the patch. Update the code in withReactNativePickerFix.js where the
variable contents is inspected and where the patch is written (the
injection/return path) to use the new unique marker so the plugin is
deterministically idempotent.
apps/mobile/plugins/withMonorepoFix.js (1)

84-101: ⚡ Quick win

Refresh fallback-copied directories instead of permanently skipping existing paths.

When symlink creation fails once, later runs hit the “already exists” branch and never refresh copied files, which can drift after React Native upgrades.

Proposed patch
-            } else {
-                logger.lifecycle("[MonorepoFix] Already exists: node_modules/" + _dirname)
+            } else {
+                if (!java.nio.file.Files.isSymbolicLink(_link.toPath())) {
+                    ant.copy(todir: _link.absolutePath, overwrite: true) {
+                        fileset(dir: _source.absolutePath)
+                    }
+                    logger.lifecycle("[MonorepoFix] Refreshed copied dir: node_modules/" + _dirname)
+                } else {
+                    logger.lifecycle("[MonorepoFix] Already symlinked: node_modules/" + _dirname)
+                }
             }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/mobile/plugins/withMonorepoFix.js` around lines 84 - 101, Currently when
_link.exists() we skip updating fallback-copied directories, so once a symlink
attempt fails the copied files are never refreshed; change the else branch that
logs "[MonorepoFix] Already exists: node_modules/" + _dirname to detect that the
path exists as a fallback directory and refresh its contents from _source by
running the same copy logic (ensure _link.mkdirs() then call ant.copy with
todir: _link.absolutePath and overwrite: true using fileset(dir:
_source.absolutePath)), and emit a lifecycle/log message (e.g. "[MonorepoFix]
Refreshed: node_modules/..." ) so copied files are updated when React Native or
source files change.
apps/mobile/package.json (1)

85-88: ⚡ Quick win

Remove workspace-local overrides from apps/mobile/package.json

In npm workspaces, overrides are only applied when defined in the project root package.json; a workspace-level overrides block won’t affect dependency resolution and can mislead readers.

Proposed cleanup diff
-  "overrides": {
-    "react-native-svg": "15.12.1",
-    "react-native-worklets": "0.5.1"
-  },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/mobile/package.json` around lines 85 - 88, The package.json in this
workspace contains a local "overrides" block for "react-native-svg" and
"react-native-worklets" which has no effect in npm workspaces; remove the entire
"overrides" object from the apps/mobile package.json and, if those version pins
are required, add them to the repository root package.json "overrides" instead
so dependency resolution is applied workspace-wide. Ensure you delete the
"overrides" key and its entries ("react-native-svg", "react-native-worklets")
from the mobile manifest and run a fresh install to validate the lockfile
updates.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/mobile/eas.json`:
- Around line 11-16: The build profiles in apps/mobile/eas.json (the "preview"
and "production" objects under "build") are missing android.buildType: "apk" and
env.npm_config_legacy_peer_deps: "true" that are present in the root eas.json;
update the "preview" and "production" profiles in apps/mobile/eas.json to
include android.buildType set to "apk" and add an env object with
npm_config_legacy_peer_deps set to "true" so EAS behavior is consistent
regardless of working directory.

In `@eas.json`:
- Around line 20-31: The production profile in eas.json currently forces an
Android APK via the "production" -> "android" -> "buildType": "apk" setting
which prevents eas submit from producing an AAB; remove that override (or change
it to "aab") so the production profile outputs an Android App Bundle for Google
Play submissions and reserve "apk" only for testing/preview profiles (e.g.,
"preview" profile), updating the "production" profile's android.buildType
accordingly.

---

Nitpick comments:
In `@apps/mobile/package.json`:
- Around line 85-88: The package.json in this workspace contains a local
"overrides" block for "react-native-svg" and "react-native-worklets" which has
no effect in npm workspaces; remove the entire "overrides" object from the
apps/mobile package.json and, if those version pins are required, add them to
the repository root package.json "overrides" instead so dependency resolution is
applied workspace-wide. Ensure you delete the "overrides" key and its entries
("react-native-svg", "react-native-worklets") from the mobile manifest and run a
fresh install to validate the lockfile updates.

In `@apps/mobile/plugins/withMonorepoFix.js`:
- Around line 84-101: Currently when _link.exists() we skip updating
fallback-copied directories, so once a symlink attempt fails the copied files
are never refreshed; change the else branch that logs "[MonorepoFix] Already
exists: node_modules/" + _dirname to detect that the path exists as a fallback
directory and refresh its contents from _source by running the same copy logic
(ensure _link.mkdirs() then call ant.copy with todir: _link.absolutePath and
overwrite: true using fileset(dir: _source.absolutePath)), and emit a
lifecycle/log message (e.g. "[MonorepoFix] Refreshed: node_modules/..." ) so
copied files are updated when React Native or source files change.

In `@apps/mobile/plugins/withReactNativePickerFix.js`:
- Around line 31-34: The current idempotency check uses a broad string match on
contents.includes("REACT_NATIVE_DIR") which may collide with unrelated files;
change it to look for and insert a plugin-specific sentinel (e.g., a unique
comment like "// withReactNativePickerFix applied" or "/*
WITH_RN_PICKER_FIX_MARKER */") so the guard becomes
contents.includes("<UNIQUE_SENTINEL>") and the injection code adds that sentinel
along with the patch. Update the code in withReactNativePickerFix.js where the
variable contents is inspected and where the patch is written (the
injection/return path) to use the new unique marker so the plugin is
deterministically idempotent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2049c0f9-359b-4821-9c95-3b2cc8ecc3e8

📥 Commits

Reviewing files that changed from the base of the PR and between b80da47 and 9ee837b.

⛔ Files ignored due to path filters (6)
  • apps/mobile/assets/images/adaptive-icon.png is excluded by !**/*.png
  • apps/mobile/assets/images/favicon.png is excluded by !**/*.png
  • apps/mobile/assets/images/icon.png is excluded by !**/*.png
  • apps/mobile/assets/images/notification-icon.png is excluded by !**/*.png
  • apps/mobile/assets/images/splash-icon.png is excluded by !**/*.png
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • app.json
  • apps/mobile/app.json
  • apps/mobile/app/index.tsx
  • apps/mobile/eas.json
  • apps/mobile/package.json
  • apps/mobile/plugins/withMonorepoFix.js
  • apps/mobile/plugins/withReactNativePickerFix.js
  • eas.json
  • package.json

Comment thread apps/mobile/eas.json
Comment on lines +11 to +16
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read-only check: show effective profile drift between root and app-level EAS configs.
python - <<'PY'
import json, pathlib
root = json.loads(pathlib.Path("eas.json").read_text())
app  = json.loads(pathlib.Path("apps/mobile/eas.json").read_text())

for profile in ["preview", "production"]:
    r = root.get("build", {}).get(profile, {})
    a = app.get("build", {}).get(profile, {})
    print(f"\n[{profile}]")
    for key in ["distribution", "android", "env", "autoIncrement"]:
        print(f"{key}: root={r.get(key)!r} | app={a.get(key)!r}")
PY

Repository: jpdevhub/Agronavis-App

Length of output: 459


Align apps/mobile/eas.json build profiles with root eas.json to prevent build/install drift.

build.preview and build.production in apps/mobile/eas.json omit android.buildType: "apk" and env.npm_config_legacy_peer_deps: "true" that exist in the root config, so running EAS from different locations can yield different behavior.

Proposed alignment diff
   "build": {
     "development": {
       "developmentClient": true,
       "distribution": "internal"
     },
     "preview": {
-      "distribution": "internal"
+      "distribution": "internal",
+      "android": {
+        "buildType": "apk"
+      },
+      "env": {
+        "npm_config_legacy_peer_deps": "true"
+      }
     },
     "production": {
-      "autoIncrement": true
+      "autoIncrement": true,
+      "android": {
+        "buildType": "apk"
+      },
+      "env": {
+        "npm_config_legacy_peer_deps": "true"
+      }
     }
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true
}
"preview": {
"distribution": "internal",
"android": {
"buildType": "apk"
},
"env": {
"npm_config_legacy_peer_deps": "true"
}
},
"production": {
"autoIncrement": true,
"android": {
"buildType": "apk"
},
"env": {
"npm_config_legacy_peer_deps": "true"
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/mobile/eas.json` around lines 11 - 16, The build profiles in
apps/mobile/eas.json (the "preview" and "production" objects under "build") are
missing android.buildType: "apk" and env.npm_config_legacy_peer_deps: "true"
that are present in the root eas.json; update the "preview" and "production"
profiles in apps/mobile/eas.json to include android.buildType set to "apk" and
add an env object with npm_config_legacy_peer_deps set to "true" so EAS behavior
is consistent regardless of working directory.

Comment thread eas.json
Comment on lines +20 to +31
"production": {
"autoIncrement": true,
"android": {
"buildType": "apk"
},
"env": {
"npm_config_legacy_peer_deps": "true"
}
}
},
"submit": {
"production": {}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For Expo EAS as of 2026, does build.production.android.buildType: "apk"produce an artifact compatible with Google Play submission viaeas submit, or is AAB required?

💡 Result:

Yes—however, for Google Play submissions via Expo EAS Submit, AAB is the expected/accepted format, and Expo explicitly recommends AAB for store submission. 1) What build.production.android.buildType: "apk" produces Expo’s EAS Build configuration supports generating an Android.apk by setting android.buildType to apk in your build profile. Expo notes that the default Android build output is an Android App Bundle (AAB), and that.apk is mainly for install/testing on emulators or devices rather than store distribution. [1][2] 2) What eas submit accepts for Google Play Expo’s EAS Submit documentation states that EAS Submit accepts any valid Android App Bundle (.aab) file for Android submissions to Google Play. [3] 3) Is an APK sufficient for Google Play via EAS Submit? Expo’s store-submission guidance is that production builds are ready to be submitted to app stores, and Expo recommends using AAB when submitting to stores; AAB is the default configuration. [4][2] Given (a) Expo’s explicit “AAB recommended/default for Google Play store submission” guidance [4][2] and (b) EAS Submit’s stated acceptance of valid .aab Android binaries for Google Play submissions [3], the safe conclusion as of 2026-05-23 is: AAB is required/expected for Play submission via eas submit, and using buildType: "apk" may not be compatible with Play submission through EAS Submit. Practical recommendation If your goal is Google Play via eas submit, keep your production Android build as the default AAB output (omit android.buildType: "apk" for the production profile), and use eas submit --platform android after building the production profile. [4][5][3]

Citations:


Switch production Android build from apk to AAB for eas submit
eas.json sets build.production.android.buildType: "apk" (lines 20-31), which makes EAS Build output an APK. For Google Play submissions via Expo EAS Submit, store submission expects an Android App Bundle (.aab), so keep production aligned to the AAB/default output (e.g., remove the android.buildType: "apk" override) and restrict APK to preview/testing if needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@eas.json` around lines 20 - 31, The production profile in eas.json currently
forces an Android APK via the "production" -> "android" -> "buildType": "apk"
setting which prevents eas submit from producing an AAB; remove that override
(or change it to "aab") so the production profile outputs an Android App Bundle
for Google Play submissions and reserve "apk" only for testing/preview profiles
(e.g., "preview" profile), updating the "production" profile's android.buildType
accordingly.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 15 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="eas.json">

<violation number="1" location="eas.json:13">
P1: Production builds should use AAB format (the default), not APK. APK is appropriate for `preview`/internal distribution, but Google Play Store requires AAB for submission. Since you have a `submit.production` block, this will prevent successful store submission.</violation>
</file>

<file name="apps/mobile/app.json">

<violation number="1" location="apps/mobile/app.json:39">
P2: `RECORD_AUDIO` permission is added but no code in the app uses audio recording. Unnecessary permissions increase the app's attack surface and may cause user trust issues or app store review friction. Remove it unless an upcoming feature requires it.</violation>
</file>

<file name="apps/mobile/plugins/withReactNativePickerFix.js">

<violation number="1" location="apps/mobile/plugins/withReactNativePickerFix.js:73">
P2: This plugin file is dead code — it's never registered in `app.json` or imported anywhere. The active plugin `./plugins/withMonorepoFix` already sets `ext.REACT_NATIVE_DIR` and `ext.REACT_NATIVE_NODE_MODULES_DIR` using the same logic. Consider removing this file to avoid confusion.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread eas.json
},
"preview": {
"distribution": "internal",
"android": {
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Production builds should use AAB format (the default), not APK. APK is appropriate for preview/internal distribution, but Google Play Store requires AAB for submission. Since you have a submit.production block, this will prevent successful store submission.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At eas.json, line 13:

<comment>Production builds should use AAB format (the default), not APK. APK is appropriate for `preview`/internal distribution, but Google Play Store requires AAB for submission. Since you have a `submit.production` block, this will prevent successful store submission.</comment>

<file context>
@@ -0,0 +1,33 @@
+    },
+    "preview": {
+      "distribution": "internal",
+      "android": {
+        "buildType": "apk"
+      },
</file context>
Fix with Cubic

Comment thread apps/mobile/app.json
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.READ_EXTERNAL_STORAGE"
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.RECORD_AUDIO"
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: RECORD_AUDIO permission is added but no code in the app uses audio recording. Unnecessary permissions increase the app's attack surface and may cause user trust issues or app store review friction. Remove it unless an upcoming feature requires it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mobile/app.json, line 39:

<comment>`RECORD_AUDIO` permission is added but no code in the app uses audio recording. Unnecessary permissions increase the app's attack surface and may cause user trust issues or app store review friction. Remove it unless an upcoming feature requires it.</comment>

<file context>
@@ -27,12 +30,13 @@
         "android.permission.ACCESS_COARSE_LOCATION",
-        "android.permission.READ_EXTERNAL_STORAGE"
+        "android.permission.READ_EXTERNAL_STORAGE",
+        "android.permission.RECORD_AUDIO"
       ]
     },
</file context>
Fix with Cubic

@@ -0,0 +1,73 @@
/**
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This plugin file is dead code — it's never registered in app.json or imported anywhere. The active plugin ./plugins/withMonorepoFix already sets ext.REACT_NATIVE_DIR and ext.REACT_NATIVE_NODE_MODULES_DIR using the same logic. Consider removing this file to avoid confusion.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mobile/plugins/withReactNativePickerFix.js, line 73:

<comment>This plugin file is dead code — it's never registered in `app.json` or imported anywhere. The active plugin `./plugins/withMonorepoFix` already sets `ext.REACT_NATIVE_DIR` and `ext.REACT_NATIVE_NODE_MODULES_DIR` using the same logic. Consider removing this file to avoid confusion.</comment>

<file context>
@@ -0,0 +1,73 @@
+  });
+};
+
+module.exports = withReactNativePickerFix;
</file context>
Fix with Cubic

@jpdevhub jpdevhub merged commit fb88049 into main May 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: resolve native module hoisting failures for EAS monorepo builds

1 participant