Skip to content

Commit 4408140

Browse files
committed
fix: prevent dev/debug data stores from restoring on fresh install
Exclude beta-flags, user-flag-overrides, and release-stage DataStore files from Android Auto Backup. Reset each on fresh install using noBackupFilesDir marker files to prevent stale overrides, sandbox routing, or incorrect release stage classification after restore. Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 81cbd0c commit 4408140

6 files changed

Lines changed: 68 additions & 0 deletions

File tree

apps/flipcash/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
<application
4444
android:name="com.flipcash.app.FlipcashApp"
4545
android:allowBackup="true"
46+
android:fullBackupContent="@xml/backup_rules"
47+
android:dataExtractionRules="@xml/data_extraction_rules"
4648
android:icon="@mipmap/ic_launcher"
4749
android:label="@string/app_name"
4850
android:largeHeap="true"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<full-backup-content>
3+
<exclude
4+
domain="file"
5+
path="datastore/beta-flags.preferences_pb" />
6+
<exclude
7+
domain="file"
8+
path="datastore/user-flag-overrides.preferences_pb" />
9+
<exclude
10+
domain="file"
11+
path="datastore/release-stage.preferences_pb" />
12+
</full-backup-content>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<data-extraction-rules>
3+
<cloud-backup>
4+
<exclude
5+
domain="file"
6+
path="datastore/beta-flags.preferences_pb" />
7+
<exclude
8+
domain="file"
9+
path="datastore/user-flag-overrides.preferences_pb" />
10+
<exclude
11+
domain="file"
12+
path="datastore/release-stage.preferences_pb" />
13+
</cloud-backup>
14+
<device-transfer>
15+
<exclude
16+
domain="file"
17+
path="datastore/beta-flags.preferences_pb" />
18+
<exclude
19+
domain="file"
20+
path="datastore/user-flag-overrides.preferences_pb" />
21+
<exclude
22+
domain="file"
23+
path="datastore/release-stage.preferences_pb" />
24+
</device-transfer>
25+
</data-extraction-rules>

apps/flipcash/shared/appupdates/src/main/kotlin/com/flipcash/app/updates/internal/GooglePlayReleaseStageProvider.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.flipcash.app.updates.resolveStage
1111
import kotlinx.coroutines.flow.firstOrNull
1212
import kotlinx.coroutines.flow.map
1313
import kotlinx.serialization.json.Json
14+
import java.io.File
1415
import okhttp3.OkHttpClient
1516
import okhttp3.Request
1617
import timber.log.Timber
@@ -31,6 +32,14 @@ internal class GooglePlayReleaseStageProvider(private val context: Context) : Re
3132
private set
3233

3334
override suspend fun loadCachedStage(versionCode: Int): ReleaseStage? {
35+
// Clear cached manifest restored from backup on fresh install.
36+
val marker = File(context.noBackupFilesDir, "release-stage-initialized")
37+
if (!marker.exists()) {
38+
context.releaseStageDataStore.edit { it.clear() }
39+
marker.createNewFile()
40+
return null
41+
}
42+
3443
val cached = context.releaseStageDataStore.data
3544
.map { prefs -> prefs[MANIFEST_KEY] }
3645
.firstOrNull()

apps/flipcash/shared/featureflags/src/main/kotlin/com/flipcash/app/featureflags/internal/InternalFeatureFlagController.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.map
2121
import kotlinx.coroutines.flow.onEach
2222
import kotlinx.coroutines.flow.stateIn
2323
import kotlinx.coroutines.launch
24+
import java.io.File
2425
import javax.inject.Inject
2526

2627
internal class InternalFeatureFlagController @Inject constructor(
@@ -49,6 +50,15 @@ internal class InternalFeatureFlagController @Inject constructor(
4950
FeatureFlag.entries
5051
.filter { it.launched }
5152
.onEach { reset(it) }
53+
54+
// Clear beta flags restored from backup on fresh install.
55+
// noBackupFilesDir is never included in Auto Backup, so the marker
56+
// file won't exist after a restore — triggering a full reset.
57+
val marker = File(context.noBackupFilesDir, "beta-flags-initialized")
58+
if (!marker.exists()) {
59+
reset()
60+
marker.createNewFile()
61+
}
5262
}
5363

5464
override fun enableBetaFeatures() {

apps/flipcash/shared/userflags/src/main/kotlin/com/flipcash/app/userflags/UserFlagsCoordinator.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.flipcash.services.models.UserFlags
1313
import com.flipcash.services.user.UserManager
1414
import com.getcode.opencode.model.financial.Fiat
1515
import dagger.hilt.android.qualifiers.ApplicationContext
16+
import java.io.File
1617
import kotlinx.coroutines.CoroutineScope
1718
import kotlinx.coroutines.SupervisorJob
1819
import kotlinx.coroutines.flow.SharingStarted
@@ -64,6 +65,15 @@ class UserFlagsCoordinator @Inject constructor(
6465
produceFile = { context.preferencesDataStoreFile("user-flag-overrides") }
6566
)
6667

68+
init {
69+
// Clear overrides restored from backup on fresh install.
70+
val marker = File(context.noBackupFilesDir, "user-flag-overrides-initialized")
71+
if (!marker.exists()) {
72+
clearAll()
73+
marker.createNewFile()
74+
}
75+
}
76+
6777
// Parse DataStore prefs → Overrides
6878
private val overrides: StateFlow<Overrides> = dataStore.data.map { prefs ->
6979
Overrides(

0 commit comments

Comments
 (0)