[stealth 2/4] neutral identity, icons & manifest minimization#8860
[stealth 2/4] neutral identity, icons & manifest minimization#8860reflog wants to merge 5 commits into
Conversation
def4ef0 to
82e0867
Compare
8e087bf to
73dd0ea
Compare
There was a problem hiding this comment.
Pull request overview
This PR is the second in the Stealth Android stack and introduces build-time–gated mechanisms to neutralize install-time identity (package/app labels/auth scheme), generate neutral icon resources, and minimize the merged Android manifest for stealth modes while keeping normal builds on the existing identity defaults.
Changes:
- Add generators (with tests) for Android identity profiles (
.properties) and deterministic neutral icon resources driven by private seeds. - Introduce a post-merge Android manifest filter (with tests) to remove unwanted permissions/components and rewrite component names for stealth
vpn/novpnmodes. - Wire Android runtime strings/icons/labels to build-provided values (via placeholders/BuildConfig), and add stealth-only Kotlin + resource overlays for a neutral bridge surface.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| android/app/src/main/AndroidManifest.novpn.xml | Adds a separate manifest variant intended for a no-VPN mode configuration. |
| android/app/src/main/AndroidManifest.xml | Switches app identity and icon fields to manifest placeholders (label/icons/auth scheme/tile icon). |
| android/app/src/main/kotlin/org/getlantern/lantern/LanternApp.kt | Makes the Application class extensible for generated/debranded variants. |
| android/app/src/main/kotlin/org/getlantern/lantern/notification/NotificationManager.kt | Uses BuildConfig-driven notification channel strings and resolves configurable small-icon resources. |
| android/app/src/main/kotlin/org/getlantern/lantern/service/LanternVpnService.kt | Makes VPN service extensible and moves session naming/exclusion behavior to BuildConfig + stealth helpers. |
| android/app/src/main/kotlin/org/getlantern/lantern/service/QuickTileService.kt | Makes tile service extensible and uses BuildConfig-driven tile labels + configurable service intent target. |
| android/app/src/main/res/drawable/neutral_app_icon.xml | Adds neutral drawable icon resource for identity/profile-based placeholder usage. |
| android/app/src/main/res/drawable/neutral_notification_icon.xml | Adds neutral notification icon drawable resource. |
| android/app/src/main/res/values/string.xml | Removes the checked-in app_name string to rely on build-injected values. |
| android/app/src/stealth/kotlin/foundation/bridge/AppHost.kt | Adds stealth Application host that initializes bridge context. |
| android/app/src/stealth/kotlin/foundation/bridge/BaseHomeActivity.kt | Adds a stealth FlutterActivity base with a bridge control MethodChannel. |
| android/app/src/stealth/kotlin/foundation/bridge/BridgeCommon.kt | Adds shared stealth bridge utilities (state/paths/foreground notification). |
| android/app/src/stealth/res/drawable/launch_background.xml | Adds stealth launch background resource. |
| android/app/src/stealth/res/drawable/neutral_app_icon.xml | Adds stealth overlay neutral app icon resource. |
| android/app/src/stealth/res/drawable/neutral_notification_icon.xml | Adds stealth overlay neutral notification icon resource. |
| android/app/src/stealth/res/values-night/styles.xml | Adds stealth night theme resources. |
| android/app/src/stealth/res/values/styles.xml | Adds stealth default theme resources. |
| docs/stealth-android-icons.md | Documents stealth icon generation and build wiring. |
| docs/stealth-android-identity.md | Documents identity profile generation/usage and schema. |
| lib/core/common/app_secrets.dart | Routes Android package name usage through build-info (stealth-aware) rather than a hard-coded constant. |
| scripts/stealth/android_manifest_filter.py | Implements post-merge manifest minimization + component rewrite for stealth vpn/novpn. |
| scripts/stealth/android_manifest_filter_test.py | Adds coverage for manifest filtering invariants and idempotency. |
| scripts/stealth/debrand_kotlin.py | Implements mechanical debranding copy/transform of Kotlin sources/resources for stealth builds. |
| scripts/stealth/generate_android_icons.py | Generates deterministic neutral icon resource set and metadata from a seed. |
| scripts/stealth/generate_android_icons_test.py | Adds deterministic and file-output tests for icon generation. |
| scripts/stealth/generate_android_identity.py | Generates Android identity profiles (properties) from seed or JSON profile input. |
| scripts/stealth/generate_android_identity_test.py | Adds tests for deterministic identity generation, profile import, and properties output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
82e0867 to
bab8b58
Compare
73dd0ea to
3a9a501
Compare
bab8b58 to
fa33939
Compare
3a9a501 to
a8a0e78
Compare
fa33939 to
fb322ce
Compare
a8a0e78 to
6b0fb5c
Compare
fb322ce to
ec5db08
Compare
6b0fb5c to
4a146d2
Compare
- Always include core-ktx / lifecycle-livedata-ktx / work-runtime-ktx: these are used by the real app code (VPN status, logs, background work) in stealth builds too, not just regular builds. - Drop the dangling proguard-stealth-novpn.pro reference; the existing proguard-rules.pro applies to all release variants (incl. stealth-novpn). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ec5db08 to
03e6ede
Compare
- generate_profile.py: enforce non-branded (no "Lantern") app/session names for stealth modes, matching the de-branding contract the error messages already promised; add regression tests for branded names. - build.gradle: emit the resolved stealth mode in the STEALTH_MODE BuildConfig field so it can't read "normal" while STEALTH_ENABLED=true (e.g. when stealth is enabled via -PSTEALTH_MODE without a profile). - Makefile: gate STEALTH_GO_LDFLAGS and lanternd log level on stealth activation (BUILD_TYPE | STEALTH_MODE | STEALTH_PROFILE), not BUILD_TYPE alone; use $(PYTHON) instead of hardcoded python3 in stealth recipes. - release.yml: read stealth_leakage_mode via env indirection with an explicit allowlist instead of inlining the template expansion in shell. - docs: make quick-start commands runnable (include required app/session names). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4a146d2 to
0e2c4d1
Compare
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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 `@android/app/src/main/AndroidManifest.xml`:
- Around line 69-81: The AndroidManifest.xml intent-filters now advertise the
dynamic ${appAuthScheme} for deep-link handling, but the deep-link routing logic
in lib/lantern_app.dart still hardcodes checks for uri.scheme == 'lantern'.
Update the scheme validation logic in lib/lantern_app.dart where the auth,
report-issue, and private-server hosts are handled to check against the actual
appAuthScheme value that matches what the manifest declares, rather than the
hardcoded 'lantern' string, so that incoming URIs like mobileapp://auth?... are
properly recognized and routed.
In
`@android/app/src/main/kotlin/org/getlantern/lantern/notification/NotificationManager.kt`:
- Around line 237-251: The resolveNotificationSmallIcon function currently falls
back to R.drawable.lantern_notification_icon unconditionally when icon
resolution fails, which leaks the branded identity in stealth builds. Instead of
always returning the branded icon, check whether the application is running in
stealth mode using a stealth-aware check through LanternApp.application, then
return an appropriate stealth-aware fallback icon resource when in stealth mode,
or the branded icon otherwise.
In `@android/app/src/stealth/kotlin/foundation/bridge/BridgeCommon.kt`:
- Line 93: The `.setContentTitle()` call in BridgeCommon.kt is referencing
R.string.app_name which does not exist in the stealth resource tree. Either add
an app_name string resource definition to the stealth flavor's string.xml file,
or replace the R.string.app_name reference with a string resource that actually
exists in the stealth resources (such as the existing disconnect string), or use
a hardcoded string literal instead of a resource reference.
In `@docs/stealth-android-identity.md`:
- Around line 82-87: The documentation in lines 82-87 and 117-119 does not
adequately clarify the difference in APP_AUTH_SCHEME handling between stealth
and non-stealth Android builds. Revise the text to explicitly state that for
stealth builds, ANDROID_IDENTITY_DART_DEFINES remains empty (because
STEALTH_ENABLED is set), which means the appAuthScheme from the .properties file
is passed only to Gradle for manifest substitution but not to Dart. Therefore,
stealth builds must explicitly pass
--dart-define=APP_AUTH_SCHEME=<appAuthScheme> (extracted from the generated
.properties file) when invoking flutter build to ensure Dart's deep-link
handling matches the manifest scheme. Additionally, clarify that lines 117-119
describe behavior specific to non-stealth Android release builds by updating the
section context or heading to distinguish between stealth and non-stealth
configurations.
In `@scripts/stealth/android_manifest_filter.py`:
- Around line 213-229: The ensure_novpn_service() function only checks for
STEALTH_NOVPN_SERVICE_NAME when determining if a no-VPN service already exists,
but it should also recognize pre-existing no-VPN service aliases like
foundation.bridge.SyncService. Modify the condition in the function to check for
all known no-VPN service aliases in addition to STEALTH_NOVPN_SERVICE_NAME, so
that if any variant already exists in the application, the function returns
early instead of appending a duplicate service entry. Additionally, add a
regression test case with a fixture containing foundation.bridge.SyncService to
verify that the function correctly skips appending a new service when this alias
is already present.
In `@scripts/stealth/debrand_kotlin.py`:
- Around line 139-140: Add validation logic before the resource processing
blocks to ensure fail-fast behavior: verify that if --res-source is provided,
--res-output must also be provided (and vice versa), and if --res-overlay is
provided as a path argument, it must be a valid directory before attempting to
process it. If these conditions are not met, the script should exit with an
appropriate error message rather than silently continuing with incomplete
resource operations. This applies to both the main resource processing block at
lines 139-140 and the related section mentioned at lines 177-178.
🪄 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: 47520e99-ed4b-49c5-80ce-5c68c4be832d
📒 Files selected for processing (27)
android/app/src/main/AndroidManifest.novpn.xmlandroid/app/src/main/AndroidManifest.xmlandroid/app/src/main/kotlin/org/getlantern/lantern/LanternApp.ktandroid/app/src/main/kotlin/org/getlantern/lantern/notification/NotificationManager.ktandroid/app/src/main/kotlin/org/getlantern/lantern/service/LanternVpnService.ktandroid/app/src/main/kotlin/org/getlantern/lantern/service/QuickTileService.ktandroid/app/src/main/res/drawable/neutral_app_icon.xmlandroid/app/src/main/res/drawable/neutral_notification_icon.xmlandroid/app/src/main/res/values/string.xmlandroid/app/src/stealth/kotlin/foundation/bridge/AppHost.ktandroid/app/src/stealth/kotlin/foundation/bridge/BaseHomeActivity.ktandroid/app/src/stealth/kotlin/foundation/bridge/BridgeCommon.ktandroid/app/src/stealth/res/drawable/launch_background.xmlandroid/app/src/stealth/res/drawable/neutral_app_icon.xmlandroid/app/src/stealth/res/drawable/neutral_notification_icon.xmlandroid/app/src/stealth/res/values-night/styles.xmlandroid/app/src/stealth/res/values/styles.xmldocs/stealth-android-icons.mddocs/stealth-android-identity.mdlib/core/common/app_secrets.dartscripts/stealth/android_manifest_filter.pyscripts/stealth/android_manifest_filter_test.pyscripts/stealth/debrand_kotlin.pyscripts/stealth/generate_android_icons.pyscripts/stealth/generate_android_icons_test.pyscripts/stealth/generate_android_identity.pyscripts/stealth/generate_android_identity_test.py
💤 Files with no reviewable changes (1)
- android/app/src/main/res/values/string.xml
- lantern_app.dart: route host-based deep links via AppBuildInfo.isAppAuthUri()
instead of a hardcoded 'lantern' scheme, matching the ${appAuthScheme} manifest
intent-filters (default scheme is still 'lantern', so normal builds are
unchanged).
- NotificationManager: stealth-aware fallback for the small notification icon so
a failed resource lookup never reintroduces the branded icon.
- BridgeCommon: drop the non-existent R.string.app_name (would fail resource
linking); use the app's own (neutral) label via PackageManager.
- android_manifest_filter: normalize pre-existing/legacy no-VPN services
(e.g. foundation.bridge.SyncService) into a single canonical special-use FGS
instead of appending a duplicate; add regression tests.
- debrand_kotlin: fail fast on partial --res-source/--res-output or an invalid
--res-overlay before writing any output.
- docs: clarify that APP_AUTH_SCHEME is injected only for non-stealth identity
release builds; stealth builds must pass --dart-define explicitly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Part of epic getlantern/engineering#3569 — stacked PR 2/4, targets
stealth/pr1-foundation.Per-build neutral Android identity (randomized package name, labels, VPN session name), generated neutral app/notification icons, and Android manifest + permission minimization (incl. the no-VPN manifest). Normal builds unchanged.
Implements getlantern/engineering#3624.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation