feat(monetization-261): prepare entitlement infrastructure and quota enforcement for release
- Add EntitlementSnapshot, EntitlementRevalidationUseCase, and BillingUseCases - Add DriftEntitlementSnapshotRepository for offline entitlement caching - Add HealthConnect gateway and integration - Add quota enforcement in share acceptance (server and UI) - Add entitlement API endpoints in server - Add privacy policy v1 and release compliance checklist - Add QA gates and device runbooks for release validation - Add demo content screen and settings screen Ticket #261
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
import '../infrastructure/health_connect/health_connect.dart';
|
||||
import '../infrastructure/local/local.dart';
|
||||
import '../infrastructure/remote/remote.dart';
|
||||
import '../infrastructure/security/security.dart';
|
||||
@ -14,7 +15,10 @@ abstract interface class AppDependencies {
|
||||
ActiveWorkoutSessionUseCases get activeWorkoutSessionUseCases;
|
||||
ActiveExerciseStepUseCases get activeExerciseStepUseCases;
|
||||
ActiveWorkoutSensorUseCases get activeWorkoutSensorUseCases;
|
||||
ExecutionDebugUseCase get executionDebugUseCase;
|
||||
SeedQaFunctionalContentUseCase get seedQaFunctionalContentUseCase;
|
||||
WorkoutTelemetryUseCases get workoutTelemetryUseCases;
|
||||
WatchCompanionProjectionUseCases get watchCompanionProjectionUseCases;
|
||||
CloseWorkoutSessionUseCase get closeWorkoutSessionUseCase;
|
||||
WorkoutHistoryUseCases get workoutHistoryUseCases;
|
||||
ProgressionStatsUseCase get progressionStatsUseCase;
|
||||
@ -22,6 +26,8 @@ abstract interface class AppDependencies {
|
||||
WatchAlertPublisher get watchAlertPublisher;
|
||||
DataExportUseCase get dataExportUseCase;
|
||||
DataImportUseCase get dataImportUseCase;
|
||||
HealthConnectUseCases get healthConnectUseCases;
|
||||
EntitlementRevalidationUseCase get entitlementRevalidationUseCase;
|
||||
SyncUseCases get syncUseCases;
|
||||
ShareUseCases get shareUseCases;
|
||||
}
|
||||
@ -37,6 +43,8 @@ final class AppBootstrap implements AppDependencies {
|
||||
required this.activeWorkoutSessionUseCases,
|
||||
required this.activeExerciseStepUseCases,
|
||||
required this.activeWorkoutSensorUseCases,
|
||||
required this.executionDebugUseCase,
|
||||
required this.seedQaFunctionalContentUseCase,
|
||||
required this.workoutTelemetryUseCases,
|
||||
required this.watchCompanionProjectionUseCases,
|
||||
required this.watchCompanionCommandHandler,
|
||||
@ -48,6 +56,8 @@ final class AppBootstrap implements AppDependencies {
|
||||
required this.exercisePerformanceReferenceUseCase,
|
||||
required this.dataExportUseCase,
|
||||
required this.dataImportUseCase,
|
||||
required this.healthConnectUseCases,
|
||||
required this.entitlementRevalidationUseCase,
|
||||
required this.syncUseCases,
|
||||
required this.shareUseCases,
|
||||
required this.syncGateway,
|
||||
@ -71,7 +81,12 @@ final class AppBootstrap implements AppDependencies {
|
||||
@override
|
||||
final ActiveWorkoutSensorUseCases activeWorkoutSensorUseCases;
|
||||
@override
|
||||
final ExecutionDebugUseCase executionDebugUseCase;
|
||||
@override
|
||||
final SeedQaFunctionalContentUseCase seedQaFunctionalContentUseCase;
|
||||
@override
|
||||
final WorkoutTelemetryUseCases workoutTelemetryUseCases;
|
||||
@override
|
||||
final WatchCompanionProjectionUseCases watchCompanionProjectionUseCases;
|
||||
final WatchCompanionCommandHandler watchCompanionCommandHandler;
|
||||
final WatchWearDataLayerAdapter watchWearDataLayerAdapter;
|
||||
@ -91,6 +106,10 @@ final class AppBootstrap implements AppDependencies {
|
||||
@override
|
||||
final DataImportUseCase dataImportUseCase;
|
||||
@override
|
||||
final HealthConnectUseCases healthConnectUseCases;
|
||||
@override
|
||||
final EntitlementRevalidationUseCase entitlementRevalidationUseCase;
|
||||
@override
|
||||
final SyncUseCases syncUseCases;
|
||||
@override
|
||||
final ShareUseCases shareUseCases;
|
||||
@ -110,6 +129,9 @@ final class AppBootstrap implements AppDependencies {
|
||||
final pendingShareActionRepository = DriftPendingShareActionRepository(
|
||||
database,
|
||||
);
|
||||
final entitlementSnapshotRepository = DriftEntitlementSnapshotRepository(
|
||||
database,
|
||||
);
|
||||
final programRepository = DriftProgramRepository(database);
|
||||
final templateRepository = DriftWorkoutTemplateRepository(database);
|
||||
final activeSessionRepository = DriftActiveSessionRepository(database);
|
||||
@ -124,6 +146,7 @@ final class AppBootstrap implements AppDependencies {
|
||||
const localBackupMediaStore = PathProviderLocalMediaStorage();
|
||||
final ids = LocalIdGenerator();
|
||||
const clock = SystemClock();
|
||||
const authTokenStore = SecureStorageAuthTokenStore();
|
||||
const originDeviceId = 'local-device';
|
||||
final activeWorkoutSessionUseCases = ActiveWorkoutSessionUseCases(
|
||||
sessionRepository: activeSessionRepository,
|
||||
@ -142,6 +165,16 @@ final class AppBootstrap implements AppDependencies {
|
||||
final activeWorkoutSensorUseCases = ActiveWorkoutSensorUseCases(
|
||||
clock: clock,
|
||||
);
|
||||
final executionDebugUseCase = ExecutionDebugUseCase(
|
||||
sessionRepository: activeSessionRepository,
|
||||
clock: clock,
|
||||
);
|
||||
final seedQaFunctionalContentUseCase = SeedQaFunctionalContentUseCase(
|
||||
seedStateRepository: starterSeedRepository,
|
||||
contentRepository: starterSeedRepository,
|
||||
clock: clock,
|
||||
originDeviceId: originDeviceId,
|
||||
);
|
||||
final workoutTelemetryUseCases = WorkoutTelemetryUseCases(
|
||||
repository: telemetryRepository,
|
||||
sessionRepository: activeSessionRepository,
|
||||
@ -153,6 +186,7 @@ final class AppBootstrap implements AppDependencies {
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
originDeviceId: originDeviceId,
|
||||
activeWorkoutSensorUseCases: activeWorkoutSensorUseCases,
|
||||
);
|
||||
final watchCompanionCommandHandler = WatchCompanionCommandHandler(
|
||||
sessionRepository: activeSessionRepository,
|
||||
@ -164,6 +198,11 @@ final class AppBootstrap implements AppDependencies {
|
||||
repository: historyRepository,
|
||||
clock: clock,
|
||||
);
|
||||
final healthConnectUseCases = HealthConnectUseCases(
|
||||
gateway: const MethodChannelHealthConnectGateway(),
|
||||
historyRepository: historyRepository,
|
||||
telemetryUseCases: workoutTelemetryUseCases,
|
||||
);
|
||||
final watchWearDataLayerAdapter = WatchWearDataLayerAdapter(
|
||||
nativeChannel: const MethodChannelWatchBridgeNativeChannel(),
|
||||
commandIngress: watchCompanionCommandHandler,
|
||||
@ -193,11 +232,15 @@ final class AppBootstrap implements AppDependencies {
|
||||
final remoteShareApi = HttpRemoteShareApi(
|
||||
HttpApiClient(baseUrl: Uri.parse(HttpApiClient.defaultBaseUrl)),
|
||||
);
|
||||
final remoteEntitlementSnapshotSource = HttpRemoteEntitlementSnapshotSource(
|
||||
client: HttpApiClient(baseUrl: Uri.parse(HttpApiClient.defaultBaseUrl)),
|
||||
tokenStore: authTokenStore,
|
||||
);
|
||||
|
||||
return AppBootstrap._(
|
||||
database: database,
|
||||
authUseCases: AuthUseCases(
|
||||
tokenStore: const SecureStorageAuthTokenStore(),
|
||||
tokenStore: authTokenStore,
|
||||
accountRepository: onlineAccountRepository,
|
||||
remoteAuthApi: remoteAuthApi,
|
||||
clock: clock,
|
||||
@ -236,6 +279,8 @@ final class AppBootstrap implements AppDependencies {
|
||||
activeWorkoutSessionUseCases: activeWorkoutSessionUseCases,
|
||||
activeExerciseStepUseCases: activeExerciseStepUseCases,
|
||||
activeWorkoutSensorUseCases: activeWorkoutSensorUseCases,
|
||||
executionDebugUseCase: executionDebugUseCase,
|
||||
seedQaFunctionalContentUseCase: seedQaFunctionalContentUseCase,
|
||||
workoutTelemetryUseCases: workoutTelemetryUseCases,
|
||||
watchCompanionProjectionUseCases: watchCompanionProjectionUseCases,
|
||||
watchCompanionCommandHandler: watchCompanionCommandHandler,
|
||||
@ -245,6 +290,8 @@ final class AppBootstrap implements AppDependencies {
|
||||
sessionRepository: activeSessionRepository,
|
||||
historyRepository: historyRepository,
|
||||
telemetryRepository: telemetryRepository,
|
||||
healthConnectUseCases: healthConnectUseCases,
|
||||
activeWorkoutSensorUseCases: activeWorkoutSensorUseCases,
|
||||
clock: clock,
|
||||
ids: ids,
|
||||
originDeviceId: originDeviceId,
|
||||
@ -267,8 +314,13 @@ final class AppBootstrap implements AppDependencies {
|
||||
mediaStore: localBackupMediaStore,
|
||||
clock: clock,
|
||||
),
|
||||
healthConnectUseCases: healthConnectUseCases,
|
||||
entitlementRevalidationUseCase: EntitlementRevalidationUseCase(
|
||||
repository: entitlementSnapshotRepository,
|
||||
remote: remoteEntitlementSnapshotSource,
|
||||
),
|
||||
syncUseCases: SyncUseCases(
|
||||
tokenStore: const SecureStorageAuthTokenStore(),
|
||||
tokenStore: authTokenStore,
|
||||
remoteSyncApi: remoteSyncApi,
|
||||
metadataRepository: syncMetadataRepository,
|
||||
mappingRepository: mappingRepository,
|
||||
@ -277,7 +329,7 @@ final class AppBootstrap implements AppDependencies {
|
||||
deviceId: originDeviceId,
|
||||
),
|
||||
shareUseCases: ShareUseCases(
|
||||
tokenStore: const SecureStorageAuthTokenStore(),
|
||||
tokenStore: authTokenStore,
|
||||
remoteShareApi: remoteShareApi,
|
||||
inboxRepository: shareInboxRepository,
|
||||
pendingActionRepository: pendingShareActionRepository,
|
||||
|
||||
Reference in New Issue
Block a user