SDK-4960: Encryption at Rest.
Details: https://wizrocket.atlassian.net/browse/SDK-4960
Summary by CodeRabbit
-
New Features
- Full-data encryption option; account-scoped preferences; clock-driven push TTL; sample app multi-instance support and richer demo actions.
-
Bug Fixes
- Safer default-instance guard for missing credentials; more reliable session timestamp and token caching/storage.
-
Refactor
- Database reorganized into modular DAOs and updated DB manager/adapter; variables caching moved to a new repository; centralized, account-aware storage helper and DB encryption handler.
-
Tests
- Large expansion across unit, integration, Robolectric and Android instrumented database benchmarks.
[!CAUTION]
Review failed
The pull request is closed.
[!NOTE]
Other AI code review bot(s) detected
CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.
Walkthrough
Replaces the Java StorageHelper with a Kotlin, account-scoped StorageHelper; introduces ICryptHandler and EncryptionLevel.FULL_DATA with DBEncryptionHandler/VariablesRepo; refactors DB layer into DAOs/DBAdapter/DBManager with Clock injection; updates many callers, migration logic, samples, and tests.
Changes
| Cohort / File(s) | Summary |
|---|---|
Storage helper & prefs APIclevertap-core/src/main/java/com/clevertap/android/sdk/StorageHelper.java, clevertap-core/src/main/java/com/clevertap/android/sdk/StorageHelper.kt, .../test/** |
Remove Java StorageHelper; add Kotlin account-scoped StorageHelper (context, accountId, key, ...) and update callers/tests to use accountId-based get/put/remove and immediate/persist variants. |
Call-site updates to account-scoped prefs.../ActivityLifeCycleManager.java, .../DeviceInfo.java, .../SessionManager.java, .../cryption/*, .../login/*, .../network/*, .../inapp/* |
Replace composite storage-key usage with accountId+key overloads or getXFromPrefs variants across many classes; minor formatting changes. |
Cryptography & encryption flowclevertap-core/src/main/java/com/clevertap/android/sdk/cryption/ICryptHandler.kt, .../CryptHandler.kt, .../EncryptionLevel.kt, .../CryptMigrator.kt, .../DBEncryptionHandler.kt, consumers (LocalDataStore.java, StoreProvider.kt, InAppStore.kt, LoginInfoProvider.java), tests |
Add ICryptHandler interface; make CryptHandler implement it; add encryptSafe/decryptSafe/decryptWithAlgorithm and update callers; add EncryptionLevel.FULL_DATA and shouldEncrypt(); introduce DBEncryptionHandler and level-driven migration flows. |
DB redesign β DAO layerclevertap-core/src/main/java/com/clevertap/android/sdk/db/DBAdapter.kt, .../DBManager.kt, .../CtDatabase.kt, .../DatabaseHelper usages, clevertap-core/src/main/java/com/clevertap/android/sdk/db/dao/*, .../usereventlogs/UserEventLogDAOImpl.kt |
Rework DB to per-DAO architecture (Event, InboxMessage, UserProfile, PushNotification, UninstallTimestamp); change constructors to accept accountId/databaseName/ILogger/DBEncryptionHandler/Clock; add DAO interfaces and implementations; update wiring and tests. |
VariablesRepo & VarCache / Factory wiringclevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapFactory.kt, .../variables/VarCache.java, .../variables/repo/VariablesRepo.kt, tests |
Add VariablesRepo for encrypted variable cache; inject into VarCache and CleverTapFactory; VarCache delegates load/store to repo; update tests to mock/inject repo. |
Push, Clock, and constantsclevertap-core/src/main/java/com/clevertap/android/sdk/pushnotification/PushProviders.java, .../Constants.java, .../response/PushAmpResponse.java |
Inject Clock into PushProviders and use clock calls; rename DEFAULT_PUSH_TTL β DEFAULT_PUSH_TTL_SECONDS (seconds); adjust TTL usage and PushAmpResponse ACK handling. |
CoreState, CleverTapAPI & configclevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java, .../CoreState.kt, .../CleverTapInstanceConfig.java, .../ManifestInfo.java, sample/.../MyApplication.kt, tests |
Switch crypt handler types to ICryptHandler; update StorageHelper.putString to accountId form; add getDefaultInstance guard; add ManifestInfo.clearPreloadedManifestInfo() for tests; sample multi-instance support and test adjustments. |
Network repos & IJRepoclevertap-core/src/main/java/com/clevertap/android/sdk/network/IJRepo.kt, .../network/NetworkRepo.kt |
Convert shared-preference key handling to accountId-scoped APIs or inline "$KEY:$accountId" formatting and update get/put calls accordingly. |
DAO-related tests and DB testsclevertap-core/src/test/java/com/clevertap/android/sdk/db/*, clevertap-core/src/androidTest/kotlin/* |
Add extensive unit and instrumented tests for new DAOs and DB behavior, DB benchmarks, and update existing DB/DAO tests to new constructors and encryption handler mocks. |
Build & test toolingclevertap-core/build.gradle, gradle/libs.versions.toml |
Add instrumentation test runner and androidTest dependencies (runner, rules, espresso, work-testing); update test library versions and mappings. |
Samples / UI helperssample/src/main/java/com/clevertap/demo/MyApplication.kt, .../HomeScreenModel.kt, .../HomeScreenViewModel.kt, sample/build.gradle |
Add optional multi-instance sample (ctMultiInstance), make buildCtInstance nullable, add richer profile/variables helpers, and add BuildConfig helper in sample Gradle. |
Sequence Diagram(s)
sequenceDiagram
autonumber
actor App
participant Factory as CleverTapFactory
participant DBM as DBManager
participant DBA as DBAdapter
participant DAO as DAO Layer
Note over App,Factory: SDK init wires accountId, DBEncryptionHandler, Clock, VariablesRepo
App->>Factory: initialize(config)
Factory->>DBM: new DBManager(accountId, logger, databaseName, ..., dbEncryptionHandler)
DBM->>DBA: new DBAdapter(context, databaseName, accountId, logger, dbEncryptionHandler, clock)
DBA->>DAO: delegate DB operations (events, inbox, profiles, push, uninstall)
sequenceDiagram
autonumber
actor Operator
participant CM as CryptMigrator
participant Crypt as ICryptHandler
participant Repo as VariablesRepo
participant DBA as DBAdapter
Note over Operator,CM: Encryption-level migration flow (supports FULL_DATA)
Operator->>CM: migrateEncryption(config)
CM->>Crypt: read stored encryption level
alt target includes FULL_DATA
CM->>Repo: loadDataFromCache()
CM->>Repo: storeDataInCache(encryptedData)
CM->>DBA: fetchUserProfilesByAccountId(...) / upsert messages (migrate PII)
end
CM->>Crypt: updateMigrationFailureCount(success)
sequenceDiagram
autonumber
actor App
participant PP as PushProviders
participant Clock as Clock
participant DAO as PushNotificationDAO
Note over App,PP: Push TTL management with injected Clock
App->>PP: load(..., clock)
PP->>Clock: currentTimeSeconds()
PP->>DAO: storePushNotificationId(id, ttlSeconds)
PP->>DAO: fetchPushNotificationIds()
PP->>DAO: cleanUpPushNotifications()
Estimated code review effort
π― 5 (Critical) | β±οΈ ~120+ minutes
Files/areas needing extra attention:
- Cryptography & migration: CryptMigrator, ICryptHandler/CryptHandler, DBEncryptionHandler and FULL_DATA migration tests.
- DB redesign: DBAdapter, DBManager, DatabaseHelper signature changes and all new DAO implementations + tests.
- Storage API migration: removal/addition of StorageHelper and widespread call-site updates across Java/Kotlin files and tests.
- Cross-cutting wiring: CleverTapFactory, CleverTapAPI, VariablesRepo, Clock injection, and sample multi-instance logic.
Possibly related PRs
#884β Overlaps full encryption refactor (ICryptHandler, FULL_DATA, DBEncryptionHandler, VariablesRepo).#867β Related DB redesign introducing DAO interfaces/implementations and DBManager/DBAdapter constructor changes.#779β Related encryption/migration and StorageHelper account-scoped changes.
Suggested reviewers
- darshanclevertap
- piyush-kukadiya
- Anush-Shand
Pre-merge checks and finishing touches
β Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | β οΈ Warning | Docstring coverage is 30.99% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
β Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. |
| Title check | β Passed | The title 'SDK-4960: Full data Encryption at Rest' accurately describes the main objective of this pull request, which introduces full-data encryption capabilities to the SDK. |
π Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π₯ Commits
Reviewing files that changed from the base of the PR and between 029a2e1bab755cbac6b8c87b8926ef1430c47b7a and b8b34d97cba8a8981d0de7220439d8fd43a8c26c.
π Files selected for processing (1)
clevertap-core/src/main/java/com/clevertap/android/sdk/Constants.java(1 hunks)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
:white_check_mark: Snyk checks have passed. No issues have been found so far.
| Status | Scanner | Total (0) | ||||
|---|---|---|---|---|---|---|
| :white_check_mark: | Open Source Security | 0 | 0 | 0 | 0 | 0 issues |
| :white_check_mark: | Licenses | 0 | 0 | 0 | 0 | 0 issues |
| :white_check_mark: | Code Security | 0 | 0 | 0 | 0 | 0 issues |
:computer: Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.
Code Coverage Debug
| Metric (instruction) | Coverage | Threshold | Ξ Coverage | Status |
|---|---|---|---|---|
| Overall | 66.83% | 75.0% | +0.04% | β |
| Changed Files | 65.68% | 75.0% | -0.16% | β |
| Report | Coverage (O/Ch) | Threshold (O/Ch) | Ξ Coverage (O/Ch) | Status (O/Ch) |
|---|---|---|---|---|
clevertap-core |
66.93% / 2947.35% | 75.0% / 75.0% | +0.04% / -1.79% | β/β |
clevertap-pushtemplates |
59.42% / 0.0% | 75.0% / 75.0% | 0.0% / 0.0% | β/β |
Merged due to tests rerun on branch update.