14 KiB
MotorSignal Cloud Architecture
Status: Planning baseline
Date: 2026-09-01
Backend direction: Firebase Authentication + Firebase cloud services, integrated with the existing local-first Flutter application
Purpose
Define the cloud architecture required for MotorSignal accounts, ride backup, synchronization, profiles, friends, planned rides, trips, and group rides.
This document intentionally favors an offline-first architecture. Local data remains the immediate source for recording and ride operation; cloud services provide identity, backup, synchronization, collaboration, and cross-device continuity.
Architectural Goals
- Recording must work without internet access.
- Cloud synchronization must be resilient to intermittent connectivity.
- A user's data must be isolated from other users by security rules.
- Synchronization must be idempotent and safe to retry.
- Reinstalling the app must not require recreating a user's ride history.
- Cloud functionality must support both Free and Pro entitlements.
- The data model must support future social/group-riding features without a major rewrite.
- Sensitive location information must receive stronger privacy treatment than ordinary profile information.
- Account deletion must have a defined, testable data-deletion path.
- Raw high-volume telemetry should not automatically be treated like ordinary profile documents.
High-Level Architecture
MotorSignal Flutter App
│
┌────────────────────┴────────────────────┐
│ │
Local Database Cloud Services
/ Local Files / Firebase
│ │
│ ┌──────────┼──────────┐
│ │ │ │
│ Auth Firestore Storage
│ │ │ │
└──────────────┬───────────────┴──────────┴──────────┘
│
Sync Engine
│
Entitlement
│
Pro / Free
Identity
Firebase Authentication provides the account identity.
The internal account identifier should remain stable even if a user changes:
- Display name.
- Username.
- Profile photo.
- Optional public location.
Google sign-in should remain compatible with the existing application authentication flow.
The Firebase user ID should be treated as an internal identifier, not a public username.
Proposed Data Model
The exact collection structure can be refined during implementation, but the logical model should include:
users/{userId}
users/{userId}/motorcycles/{motorcycleId}
users/{userId}/rides/{rideId}
users/{userId}/trips/{tripId}
users/{userId}/events/{eventId}
users/{userId}/friends/{friendId}
Potential future top-level collaborative resources:
groupRides/{groupRideId}
publicRoutes/{routeId}
These should only be introduced when query patterns and security requirements justify them.
User Document
Conceptual fields:
id
username
displayName
profilePhotoUrl
bio
location
createdAt
updatedAt
privacySettings
preferences
Do not store sensitive secrets in the user document.
Avoid storing a complete ride history or large telemetry payload directly inside the user document.
Motorcycle Document
Conceptual fields:
id
ownerId
year
make
model
nickname
photoUrl
photoSource
photoAttribution
createdAt
updatedAt
privacy
The motorcycle should have a stable ID independent of its displayed name.
Ride Document
Conceptual metadata:
id
ownerId
motorcycleId
tripId?
groupRideId?
startedAt
endedAt
duration
distance
summaryStatistics
routeReference?
telemetryReference?
createdAt
updatedAt
syncState
visibility
High-volume telemetry should not be duplicated unnecessarily across multiple Firestore documents.
Where appropriate, use compressed/structured files in Firebase Storage and keep searchable summary metadata in Firestore.
Trip Document
Conceptual fields:
id
ownerId
name
startDate
endDate
description
routeReferences
waypoints
participants
createdAt
updatedAt
visibility
Trips may contain multiple daily routes and completed rides.
Event Document
For meetups and planned events:
id
ownerId
name
description
startAt
location
attendees
linkedGroupRideId?
createdAt
updatedAt
visibility
An event does not automatically imply live location sharing.
Friend Relationship
Friend relationships should have explicit state.
PENDING
ACCEPTED
DECLINED
BLOCKED
Friendship should not automatically grant access to private ride data.
Visibility remains controlled by the owner's privacy settings.
Group Ride
A group ride should be a shared activity context while each rider retains ownership of their own ride record.
Conceptually:
Group Ride
├── Organizer
├── Participants
├── Route
├── Meeting Point
├── Schedule
├── Live Ride State
└── Completed Ride References
A rider's individual telemetry remains associated with that rider and motorcycle.
Local-First Sync
The app should never require a successful cloud write before considering a ride locally saved.
Write flow
User records ride
↓
Save locally
↓
Mark PENDING_UPLOAD
↓
Continue normal app operation
↓
Connectivity available
↓
Sync engine uploads
↓
Server acknowledgement
↓
Mark SYNCED
Offline flow
No internet
↓
Record normally
↓
Queue cloud operation
↓
Internet returns
↓
Retry automatically
Sync States
Recommended common state model:
LOCAL_ONLY
PENDING_UPLOAD
SYNCED
PENDING_DELETE
CONFLICT
SYNC_FAILED
The implementation may combine or rename states, but synchronization must be observable and debuggable.
Idempotency
Cloud writes must be safe to retry.
Do not create a new ride document every time an upload request is retried.
Use stable application-generated IDs so:
same ride ID + repeated upload = same logical ride
not:
same ride + repeated upload = duplicate rides
Conflict Handling
Conflicts should be rare but must be explicitly designed.
Potential strategy:
- Server metadata determines whether an object changed.
- Immutable ride telemetry should generally not be merged field-by-field.
- User-editable metadata can use last-write-wins or explicit conflict resolution where appropriate.
- Never silently overwrite a user's ride data without a defined policy.
For example, if two devices edit a motorcycle nickname, last-write-wins may be acceptable.
If two devices produce different telemetry for the same ride ID, preserve enough information to diagnose the conflict rather than silently destroying one copy.
Cloud Storage
Use Firebase Storage for large binary objects where appropriate:
- Ride telemetry files.
- Exported reports if cloud retention is required.
- Profile photos.
- Motorcycle photos where user-uploaded.
- Future ride media.
Keep Firestore documents focused on metadata, indexes, relationships, and summaries.
Security Model
Every user-owned resource must enforce ownership server-side.
Conceptually:
request.auth.uid == resource.ownerId
or an equivalent rule based on the final data model.
Never rely solely on Flutter UI restrictions to protect data.
A hidden button is not a security boundary.
Social Security
Friendship and group participation must not automatically permit access to all account data.
Examples:
- Being a friend does not expose private ride history.
- Joining a group ride does not expose a user's historical rides.
- Live location is only available during explicitly authorized group activity.
- Public profile data is distinct from private account data.
Location Privacy
Ride telemetry and GPS tracks can reveal a user's home, workplace, and routine.
The platform should support:
- Private rides.
- Friends-only rides.
- Public rides.
- Optional location sharing.
- Home/start/end location obfuscation for shared rides.
- No continuous background social tracking merely because a user has an account.
Live group location must require explicit participation/consent and should automatically stop at the end of the group ride.
Cloud Entitlements
Cloud usage must be controlled through the centralized entitlement system.
Example capabilities:
canCloudBackup
canUnlimitedCloudHistory
canMultiDeviceRestore
The client may use these capabilities for UX, but backend rules must also enforce limits and ownership where practical.
Do not trust a client-provided isPro=true field as proof of payment.
Subscription / Account Separation
A user account should continue to exist even if a Pro subscription expires.
Conceptually:
Firebase Account
│
├── Profile
├── Garage
├── Rides
└── Entitlement
│
┌──────┴──────┐
│ │
Free Pro Monthly/Lifetime
Billing provider state determines the paid entitlement. The account owns the data.
Expired Pro Data Policy
The final product policy must be defined before launch.
Recommended direction:
- Do not silently delete historical rides when Pro expires.
- Preserve account and existing data.
- Restrict creation/synchronization of additional premium-only data if the user exceeds Free limits.
- Allow upgrade to restore full Pro functionality.
The exact storage allowance and retention policy must be finalized after Firebase cost modeling and legal review.
Backup / Restore
Backup should be automatic where the user's entitlement allows it.
Restore should be explicit and understandable.
New device flow:
Install MotorSignal
↓
Sign in
↓
Authenticate
↓
Discover cloud account
↓
Download motorcycle/profile metadata
↓
Download ride metadata
↓
Download required ride data
↓
Rebuild local database
↓
Ready
The restore process should be resumable if interrupted.
Account Deletion
Account deletion must be a real backend workflow.
It should address:
- Firebase Authentication identity.
- User profile.
- Motorcycles.
- Rides.
- Telemetry files.
- Profile photos.
- Social relationships.
- Trips/events owned by the user.
- Group ride participation data where legally/technically appropriate.
Do not simply delete the authentication record while leaving user data orphaned indefinitely.
Data Export
Provide an account-level export capability where required/appropriate.
Potential export contents:
- Profile information.
- Motorcycle data.
- Ride metadata.
- Ride telemetry.
- Routes.
- Trip data.
The existing CSV/PDF ride exports are not necessarily sufficient to satisfy an account-level data export requirement.
Observability
Cloud synchronization should provide enough logging to diagnose:
- Authentication failures.
- Upload failures.
- Download failures.
- Permission-denied errors.
- Duplicate prevention failures.
- Conflict events.
- Storage failures.
- Billing/entitlement synchronization problems.
Do not log raw sensitive telemetry or credentials unnecessarily.
Testing Matrix
Authentication
- Fresh account.
- Existing account.
- Sign out.
- Sign in again.
- Multiple devices.
- Account deletion.
Offline
- Record without internet.
- Save ride locally.
- Restore connectivity.
- Automatic upload.
- Retry after failure.
Sync
- New motorcycle sync.
- Ride sync.
- Ride update.
- Ride deletion.
- Duplicate upload prevention.
- Conflict behavior.
Restore
- Reinstall.
- New device.
- Large ride history.
- Interrupted restore.
- Partial network failure.
Security
- User A cannot read User B's private rides.
- User A cannot write User B's data.
- Friend access respects privacy.
- Group membership does not grant historical access.
- Client cannot self-grant Pro entitlement.
Implementation Order
- Audit existing Firebase/auth implementation.
- Document current local Room/database models.
- Define cloud DTOs and stable IDs.
- Define Firestore/Storage collections.
- Write security rules before exposing new data.
- Implement profile document.
- Implement motorcycle synchronization.
- Implement ride metadata synchronization.
- Implement telemetry/blob synchronization.
- Implement retry queue.
- Implement conflict/error handling.
- Implement backup status UI.
- Implement restore.
- Add account deletion/data export.
- Connect cloud capability checks to entitlement manager.
- Test Free/Pro storage behavior.
- Add friends/social resources.
- Add planned rides/trips.
- Add group rides and explicit live-location sessions.
Design Rule
The cloud system must make MotorSignal more reliable, not more fragile.
The critical riding path should remain:
Sensors → Local Recording → Local Database → Ride Processing
Cloud synchronization should be downstream:
Local Ride → Sync Queue → Cloud Backup
A cloud outage must not prevent a rider from recording a ride.