Skip to content

feat: Location enrichment#666

Merged
Shahroz16 merged 12 commits intomainfrom
feat/real-time-location
Mar 9, 2026
Merged

feat: Location enrichment#666
Shahroz16 merged 12 commits intomainfrom
feat/real-time-location

Conversation

@Shahroz16
Copy link
Contributor

@Shahroz16 Shahroz16 commented Mar 6, 2026

Note

Medium Risk
Adds a new module that handles location (PII), persistence/encryption, and hooks into identify/reset flows; mistakes could leak data, mis-enrich profiles, or increase event volume despite the gating/filter safeguards.

Overview
Adds a new location module that can cache device coordinates, enrich identify() event context with lat/lng, and optionally emit a gated CIO Location Update track event (24h/1km filter) via a new internal DataPipeline interface.

Introduces internal plumbing to support module-driven enrichment: IdentifyHook + IdentifyHookRegistry in core, a Segment IdentifyContextPlugin in datapipelines (also propagating synchronous resets), and updates CustomerIO to implement/register DataPipeline and to publish UserChangedEvent after analytics.identify().

Adds encrypted-at-rest preference storage via PreferenceCrypto (Android Keystore w/ plaintext fallback), a new locationScope coroutine scope, a shared MainThreadPoster abstraction (moved from in-app), plus build/dep updates (Play Services Location) and sample app wiring/UI to exercise location APIs.

Written by Cursor Bugbot for commit 0616b22. This will update automatically on new commits. Configure here.

@Shahroz16 Shahroz16 requested a review from a team as a code owner March 6, 2026 11:05
@Shahroz16 Shahroz16 self-assigned this Mar 6, 2026
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

Sample app builds 📱

Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.


@codecov
Copy link

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 11.25000% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.07%. Comparing base (b5cf24d) to head (0616b22).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
...lin/io/customer/sdk/data/store/PreferenceCrypto.kt 0.00% 43 Missing ⚠️
...mer/datapipelines/plugins/IdentifyContextPlugin.kt 25.00% 14 Missing and 1 partial ⚠️
...customer/sdk/core/pipeline/IdentifyHookRegistry.kt 0.00% 7 Missing ⚠️
...tlin/io/customer/sdk/core/util/MainThreadPoster.kt 0.00% 3 Missing ⚠️
...tlin/io/customer/sdk/core/pipeline/IdentifyHook.kt 0.00% 1 Missing ⚠️
.../kotlin/io/customer/sdk/core/util/ScopeProvider.kt 0.00% 1 Missing ⚠️
...ines/src/main/kotlin/io/customer/sdk/CustomerIO.kt 80.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #666      +/-   ##
============================================
- Coverage     69.07%   68.07%   -1.01%     
- Complexity      838      842       +4     
============================================
  Files           149      153       +4     
  Lines          4601     4679      +78     
  Branches        628      637       +9     
============================================
+ Hits           3178     3185       +7     
- Misses         1189     1259      +70     
- Partials        234      235       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

currentLocationJob = null
}
}
}
Copy link

Choose a reason for hiding this comment

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

Non-atomic check-then-act on volatile job field

Low Severity

requestLocationUpdate() performs a non-atomic check-then-act on currentLocationJob — reading isActive and then assigning a new job. Similarly, cancelInFlightRequest() reads and nulls the field without synchronization. Since @Volatile only ensures visibility (not atomicity of compound operations), two concurrent calls to requestLocationUpdate() can both pass the active check and launch duplicate coroutines, with the second overwriting the first's reference. The orphaned job still runs to completion but is untracked.

Additional Locations (1)

Fix in Cursor Fix in Web


if (!isLocationServicesEnabled()) {
throw LocationRequestException(error = LocationProviderError.SERVICES_DISABLED)
}
Copy link

Choose a reason for hiding this comment

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

Redundant authorization check in provider and orchestrator

Low Severity

LocationOrchestrator.requestLocationUpdate() checks currentAuthorizationStatus().isAuthorized and returns early if denied. Then FusedLocationProvider.requestLocation() performs the exact same authorization check and throws LocationRequestException if denied. The orchestrator's check makes the provider's check unreachable via the normal call path, adding unnecessary duplication.

Additional Locations (1)

Fix in Cursor Fix in Web

@github-actions
Copy link

github-actions bot commented Mar 6, 2026

  • java_layout: feat/real-time-location (1772795200)

@github-actions
Copy link

github-actions bot commented Mar 6, 2026

Build available to test
Version: feat-real-time-location-SNAPSHOT
Repository: https://central.sonatype.com/repository/maven-snapshots/

@github-actions
Copy link

github-actions bot commented Mar 6, 2026

📏 SDK Binary Size Comparison Report

Module Last Recorded Size Current Size Change in Size
core 29.88 KB 31.27 KB ⬆️ +1.39KB
datapipelines 39.12 KB 40.57 KB ⬆️ +1.45KB
messagingpush 30.25 KB 30.25 KB ✅ No Change
messaginginapp 122.30 KB 121.84 KB ⬇️ -0.46KB
tracking-migration 22.89 KB 22.89 KB ✅ No Change

@github-actions
Copy link

github-actions bot commented Mar 6, 2026

  • kotlin_compose: feat/real-time-location (1772795205)

@github-actions
Copy link

github-actions bot commented Mar 9, 2026

  • java_layout: feat/real-time-location (1773036588)

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.


logger.debug("Re-evaluating cached location: lat=$lat, lng=$lng")
trySendLocationTrack(lat, lng)
}
Copy link

Choose a reason for hiding this comment

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

Cold start location sync relies on unreceived event

Medium Severity

The comment on syncCachedLocationIfNeeded says it's called "on cold start (via replayed UserChangedEvent)," but postUserIdentificationEvents() publishes UserChangedEvent in the CustomerIO init block — before ModuleLocation.initialize() subscribes to the event bus. If EventBus doesn't replay cached events to new subscribers, the location module never receives the initial UserChangedEvent, so syncCachedLocationIfNeeded() is never called on cold start for an already-identified user, silently skipping the supplementary "CIO Location Update" track event.

Additional Locations (2)

Fix in Cursor Fix in Web

@github-actions
Copy link

github-actions bot commented Mar 9, 2026

  • kotlin_compose: feat/real-time-location (1773036588)

Copy link
Contributor

@mahmoud-elmorabea mahmoud-elmorabea left a comment

Choose a reason for hiding this comment

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

✅ Collection of approved PRs

@mahmoud-elmorabea mahmoud-elmorabea requested a review from a team March 9, 2026 11:15
@Shahroz16 Shahroz16 merged commit 8d856bc into main Mar 9, 2026
41 of 45 checks passed
@Shahroz16 Shahroz16 deleted the feat/real-time-location branch March 9, 2026 14:07
github-actions bot pushed a commit that referenced this pull request Mar 9, 2026
## [4.17.0](4.16.1...4.17.0) (2026-03-09)

### Features

* Location enrichment ([#666](#666)) ([8d856bc](8d856bc))
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.

3 participants