๐1. Introduction
Sudoku Puzzle ("the Application") is developed by TheCatsizerLab and available on Google Play Store. We respect your privacy and are committed to processing your personal data transparently and securely in accordance with GDPR and applicable data protection laws worldwide.
This privacy policy explains how we collect, use, share, and protect your personal data when you use our Application.
๐ค2. Data Controller
TheCatsizerLab
๐ Zigliara, South Corsica, France
๐ง Email: contact.thecatsizerlab@gmail.com
For any data-related inquiries, please contact us at the address above.
2.2 App Package Information
- App Package Name: com.catsizerlab.sudoku
- Google Play Store Link: View on Google Play
- Minimum Android Version: Android 7.0 (API 24)
- Target Android Version: Android 14/15 (API 34/35)
๐3. Data We Collect
3.1 Data Collected Directly from You
๐ฎGoogle Play Games Services (GPGS)
- Unique player identifier (Player ID)
- Display name
- Profile picture (optional)
- Game progression data synchronized via Google Cloud
Legal Basis: Consent (explicit upon connection) | Purpose: Authentication, cloud sync, leaderboards, achievements
๐ฏGame Data
- Game scores (solo and multiplayer)
- Match history (duration, error count, game mode)
- Progression through levels
- Selected difficulty
- Elapsed time in games
- Number of correct placements
- Combo statistics
Legal Basis: Service contract | Purpose: Save progression, populate leaderboards, improve gameplay
๐ฅMultiplayer Data
- Opponent's display name
- Real-time game progression
- Match statistics (correct moves, errors, combo)
- Match results
- Energy and power-ups used
- Friends list and friend codes
- Pending friend invitations
Legal Basis: Service contract | Purpose: Real-time multiplayer sync, leaderboards, game balancing
๐พMatch Details Backup (Local)
- Last 5 matches stored in device SharedPreferences
- Includes: opponent name, scores, victory/defeat, reason, timestamp
Purpose: Display recent match history offline
Retention: Until manual app data clear
Storage: SharedPreferences (JSON format)
โฑ๏ธDeferred Game Results (Backup System)
Purpose: Prevent lost match results due to disconnects during game_over event
Storage:
- PostgreSQL database (Neon) - table: finished_games
- Columns stored:
- room_id (UNIQUE) - Match identifier
- winner_id, winner_name, winner_score
- loser_id, loser_name, loser_score
- reason (completed, abandoned, timeout, too_many_errors)
- winner_delivered (BOOLEAN) - Has winner retrieved result?
- loser_delivered (BOOLEAN) - Has loser retrieved result?
- created_at (TIMESTAMP)
Dual-Flag Delivery System:
- When a player is offline at match end, result is stored with their delivery flag = FALSE
- When player reconnects and retrieves result via GET /api/game_over/check/{playerId}, their flag becomes TRUE
- Row is ONLY deleted when BOTH winner_delivered AND loser_delivered are TRUE
- This ensures both players receive their match result exactly once
API Endpoints:
- POST /api/game_over/batch - Store results for multiple disconnected players (atomic batch insert)
- GET /api/game_over/check/{playerId} - Atomic retrieval sequence:
- SELECT FOR UPDATE SKIP LOCKED (prevents race conditions)
- UPDATE delivery flag for requesting player (winner_delivered or loser_delivered)
- DELETE row if both flags are TRUE
- Returns match result in single transaction
Retention:
- Until both players retrieve result (automatic deletion after dual-confirmation)
- Auto-cleanup: Results older than 1 hour are deleted (even if not retrieved)
- Cleanup runs every hour via scheduled job
Privacy:
- Stored in encrypted PostgreSQL (Neon) with SSL/TLS connections
- No persistent retention after both players confirm delivery
- Maximum retention: 1 hour (hard limit via cleanup job)
Security:
- Atomic database operations prevent duplicate delivery
- SKIP LOCKED prevents concurrent retrieval conflicts
- Transaction rollback on any error ensures data consistency
โ๏ธPreference Data
- Selected visual theme
- Language preference
- Audio settings (sound enabled/disabled)
- Vibration preferences
- Premium theme purchase history
Storage: Device local storage (SharedPreferences)
Legal Basis: Service contract | Purpose: Personalize user experience
๐Audio Preferences
- Sound enabled/disabled state
- Music volume level (0.0-1.0)
- Sound effects volume level (0.0-1.0)
- Last played music track
Storage: Device local storage (SharedPreferences)
Legal Basis: Service contract
Purpose: Remember your audio settings across sessions
โ๏ธCloud Game Save (GPGS)
- Current grid state (9x9 array of numbers)
- Initial puzzle grid (unmodified)
- Solution grid (complete puzzle)
- Difficulty level (easy/medium/hard/expert)
- Elapsed time (in seconds)
- Error count
- Continues used (if game restarted after loss)
- Current score
- Cell notes (9x9 array of note arrays)
- Hints remaining
Storage: Google Play Games Saved Games
Legal Basis: Service contract (cloud sync)
Purpose: Resume game across devices
Retention: As long as GPGS account exists
Sync: Automatic when GPGS is connected
๐ Achievement Progress Tracking (Local)
- Win counters (per difficulty + total)
- Flawless games count (0 errors)
- Hints usage statistics
- Notes usage frequency
- Correct placement accuracy
- Win streak counters (current + best)
- Error-free grids completed
- Daily challenge participation streak
- Multiplayer victories
Storage: Device local storage (SharedPreferences)
Legal Basis: Service contract
Purpose: Track achievement unlock progress
Sync: Synced with Google Play Games when achievements are unlocked
Retention: As long as app is installed
๐Player Profile Statistics
- Total games played (solo + multiplayer)
- Games won/lost (per game mode)
- Win rate percentage (automatically calculated)
- Last game timestamp
- Profile creation date
Legal Basis: Service contract
Purpose: Display player performance statistics
Visibility: Private (only visible to you)
Retention: As long as GPGS account exists + 90 days after deletion
๐พProfile Statistics Storage (PostgreSQL)
Storage Structure:
- Solo Statistics Table (player_profile_solo):
- games_played (INTEGER)
- games_won (INTEGER)
- games_lost (INTEGER)
- last_game_at (TIMESTAMP - last solo match completed)
- created_at / updated_at (TIMESTAMP)
- Multiplayer Statistics Table (player_profile_multi):
- games_played (INTEGER)
- games_won (INTEGER)
- games_lost (INTEGER)
- last_game_at (TIMESTAMP - last multiplayer match completed)
- created_at / updated_at (TIMESTAMP)
Calculation:
- Win rate: (games_won / games_played) ร 100
- Calculated server-side on each API request
API Endpoints:
- GET /api/profile/stats?gameMode=solo - Retrieve solo statistics
- GET /api/profile/stats?gameMode=multi - Retrieve multiplayer statistics
- POST /api/profile/update - Updates statistics after each match completion
Storage Location: PostgreSQL (Neon) - encrypted at rest (AES-256)
Retention: As long as GPGS account exists + 90 days after deletion
Privacy: Statistics are private and only visible to the account owner
๐Profile Statistics Cache (In-Memory)
- Solo/Multi stats cached in RAM (not persistent storage)
- Auto-refresh from server on app resume
- Cached data: gamesPlayed, gamesWon, gamesLost, winrate, lastGameAt, updatedAt
Purpose: Reduce API calls, improve performance
Storage: Volatile memory (lost on app close)
Retention: Session only (cleared when app is closed)
3.2 Data Collected Automatically
๐ฅ๏ธTechnical Data
- Device type and model
- Android OS version
- Unique identifiers (Android Advertising ID)
- IP address
- Region and timezone
- Storage capacity and remaining storage
- Device memory information
Legal Basis: Legitimate interest (technical maintenance, security, analytics) | Purpose: Performance optimization, fraud prevention, debugging
๐ฑConnection Data
- Session timestamps
- Session duration
- Game events (matches started, completed, abandoned)
- Ad interaction data (impressions, clicks, rewarded ad views)
- Connection type (WiFi vs cellular)
- App launch frequency
Legal Basis: Legitimate interest (analytics - collecte obligatoire) | Purpose: Service improvement, usage analysis, performance monitoring
โ ๏ธCrash and Error Data (Firebase Crashlytics)
Automatic Collection: Firebase Crashlytics automatically captures and sends crash reports when the app crashes.
- Crash reports: Automatic fatal error reports with stack traces
- Non-fatal errors: Logged exceptions (manually recorded by developers)
- Stack traces: Full error trace for debugging
- Application state: Memory usage, device orientation, free disk space at crash time
- Device information: Model, OS version, manufacturer
- Session data: App version, crash timestamp, time since app launch
- Custom logs: Developer-added breadcrumbs for debugging context
Data NOT collected by Crashlytics:
- โ User identifiers (Player ID, GPGS name) - NOT automatically linked
- โ IP addresses
- โ Personal data from game state (grid content, scores)
Storage & Retention:
- Storage: Firebase servers (Google Cloud, USA)
- Retention: 90 days (automatic deletion after)
- Encryption: Data encrypted in transit (HTTPS/TLS 1.3) and at rest (AES-256)
Legal Basis: Legitimate interest (GDPR Article 6.1.f - technical maintenance, security, app stability)
Purpose: Detect and fix crashes, improve app stability, prevent future errors
- Uninstall the app to stop all data collection
- Request crash data deletion via email (see Section 7.3)
๐Android Permissions
The Application requests the following Android permissions:
| Permission | Purpose | Required |
|---|---|---|
INTERNET |
Connect to leaderboard servers, daily challenges, multiplayer | โ Yes |
ACCESS_NETWORK_STATE |
Check network availability before server requests | โ Yes |
VIBRATE |
Haptic feedback on correct/incorrect moves (can be disabled in Settings) | โ Yes (declared in manifest) |
BILLING |
In-App Purchases (Google Play Billing) | โ Yes |
Note: All permissions are requested at runtime and can be revoked in Android Settings > Apps > Sudoku Puzzle > Permissions.
3.3 Payment Data
๐ณIn-App Purchase Transactions
- Products purchased (premium lifetime, theme bundle, individual themes)
- Purchase tokens (Google Play verification data)
- Purchase amount and currency
- Transaction date and time
- Transaction status (completed, pending, failed, restored)
- Product IDs (premium_lifetime, theme_spring_premium, theme_tropical_premium, theme_midnight_premium, theme_rainy_premium, theme_desert_premium, theme_golden_premium, theme_cherry_premium, theme_sky_premium, theme_rice_premium, theme_bundle_premium)
Legal Basis: Service contract | Purpose: Purchase management, product attribution, fraud prevention
๐Purchase Restoration
- Purchase restoration requests (timestamp)
- Server-side purchase validation (Google Play receipt verification)
- Backup purchase records (in case of Google Play sync failure)
- Restoration attempts (frequency, device changes)
Purpose: Ensure purchases are not lost on device change/reinstall
Security: Dual validation (Google Play + server-side)
3.4 Third-Party Data
๐ขGoogle AdMob (Advertising)
Advertisements displayed in the Application are managed by Google through AdMob.
Data collected by Google:
- Android Advertising ID
- Inferred interest categories
- Ad view history
- Ad clicks
- App usage patterns
Legal Basis: Consent (compliant with Google policy) | Purpose: Personalized ad delivery, app monetization
Manage Ad Preferences: Go to Settings > Google > Manage your Google Account > Data & Privacy > Ad Settings
๐ฅFirebase Services (Google)
Firebase Analytics
- Automatic screen view tracking
- Session duration and frequency
- Device type, OS version, app version
- Custom events logged by developers (game_start, game_end, purchase, etc.)
Provider: Google LLC
Privacy Policy: firebase.google.com/support/privacy
Firebase Crashlytics
- Crash reports (fatal errors only)
- Stack traces for debugging
- Device state at crash time (memory, storage, battery)
- NO personal data (Player ID, game scores) unless manually logged
Provider: Google LLC
Privacy Policy: firebase.google.com/support/privacy/crashlytics
Legal Basis: Legitimate interest (GDPR Article 6.1.f)
Retention: 90 days (Crashlytics), 14 months (Analytics)
โกPower-Up Cooldown & Energy Management
Cooldown System:
- 5 seconds minimum between power-up activations
- Last activation timestamp stored in RAM (player.lastPowerUpTime)
- Throttle protection: 100ms minimum between trigger_power events (spam prevention)
Energy Deduction:
- Energy cost: 1 point per power-up activation
- Deducted BEFORE power-up validation (prevents race conditions)
- Automatic refund if power-up fails execution
Refund Scenarios (Energy returned to player):
- Opponent disconnected at activation time
- No valid cells to erase (cell_eraser power-up on empty grid)
- Self-target on invalid grid state
- Invalid game state (match already finished)
- Power-up activation during cooldown period
Power-Up Targeting:
- 80% chance: Targets opponent
- 20% chance: Targets yourself (random server-side selection)
- Randomization performed server-side for fairness
Storage: RAM only (session-based, not persistent)
Purpose: Prevent power-up spam, ensure fair energy consumption, maintain game balance
Retention: Until match ends or player disconnects (volatile memory)
๐ฌRewarded Video Ads
- Ad impression timestamps
- Ad completion status (watched fully vs skipped)
- Rewards earned (continue game, bonus hints)
- Ad unit IDs shown
- Frequency capping data
Legal Basis: Consent (Google ToS)
Purpose: Provide optional rewards in exchange for ad views
Provider: Google AdMob
Control: You can refuse to watch ads (feature unavailable without viewing)
โฑ๏ธRewarded Ad Cooldown
- Last ad view timestamp stored locally
- Minimum 3 minutes cooldown between rewarded ads
Purpose: Prevent ad spam exploitation
Control: Premium subscription removes ads entirely
โฑ๏ธInterstitial Ad Frequency Control
- Last ad display timestamp (stored locally)
- Games played since last ad (counter)
- Cooldown timer (3 minutes minimum between ads)
- Ad display frequency (1 ad per 3 games completed)
Storage: Device local storage (SharedPreferences)
Purpose: Limit ad annoyance, respect user experience
Control: Premium subscription removes all interstitial ads
๐Google Play Games Services (Leaderboards & Achievements)
- Public scores on leaderboards
- Unlocked achievement badges
- Public profile information
Legal Basis: Service contract | Purpose: Leaderboards, social features
๐Private Statistics Leaderboards (GPGS)
In addition to public leaderboards, we maintain private leaderboards for internal tracking:
- Total playtime (cumulative seconds)
- Games played (all modes combined)
- Total wins (all difficulties)
Visibility: Private (only visible to you via GPGS)
Status: These leaderboards are coded in the app but currently disabled in the Google Play Console (for internal use only)
Google Play IDs:
- CgkIzuudz8UbEAIQAg (playtime)
- CgkIzuudz8UbEAIQAw (games played)
- CgkIzuudz8UbEAIQBA (total wins)
3.5 Daily Challenge Data
๐ Daily Puzzle Progress
- Daily puzzle completion status (completed date stored locally)
- Best daily scores per challenge date
- Completion times (in seconds)
- Number of hints used per challenge (0-2)
- Submission timestamps
Legal Basis: Service contract | Purpose: Daily challenge leaderboards, player engagement tracking
Storage: PostgreSQL database (Neon) via Fly.io servers (USA)
Retention: Indefinite (for leaderboard integrity and historical rankings)
๐Daily Leaderboards
- Public rankings (today + all-time)
- Player names associated with scores
- Total days participated
- Average completion times
Visibility: All daily challenge scores are publicly visible in leaderboards
๐Duplicate Submission Prevention
Server-Side Validation:
- Before accepting a score, server checks if player already completed today's challenge
- SQL query:
SELECT COUNT(*) WHERE player_id = $1 AND challenge_date = $2 - HTTP 409 Conflict error returned if already completed
- Prevents score manipulation and duplicate submissions
Client-Side Check:
- GET /api/daily/check-completed - Returns boolean completion status
- Called on app launch to disable "Play" button if already completed
- Local cache updated after successful submission
Purpose: Ensure fair leaderboards, prevent score manipulation, maintain competitive integrity
Legal Basis: Legitimate interest (fraud prevention - GDPR Article 6.1.f)
๐Anti-Cheat Validation
- Maximum score limit: 9500 points (server-side enforcement)
- Time validation: Must be positive integer (in seconds)
- Hints validation: 0-2 hints only (expert difficulty allows max 2 hints)
- Scores exceeding limits are rejected with HTTP 400 Bad Request
- Suspicious submissions flagged for review (see Section 6.1)
3.6 Friends System Data
๐ฅFriend Connections
- Unique friend code (8-digit numeric format: XXXX-XXXX, e.g., 1234-5678)
- Friend code validation (must match format
^\d{4}-\d{4}$) - Friend list (player IDs + display names)
- Friend invitations sent/received (status: pending, accepted, declined)
- Friendship timestamps (creation date)
- Last synchronization time
Legal Basis: Consent + Service contract | Purpose: Social features, friend-to-friend matching
๐Friend Code Generation
Your friend code is generated using a deterministic, non-reversible hash algorithm based on your Player ID. This means:
- The code cannot be traced back to your Player ID
- It remains the same across all your sessions
- No personally identifiable information is embedded in the code
โกFriend Invitations
- Sender information (Player ID, name, friend code)
- Recipient friend code (8-digit code)
- Invitation status (pending, accepted, declined)
- Game mode and difficulty requested (if challenge)
Retention: 60 seconds (auto-expire if not responded), then permanently deleted
Storage: PostgreSQL database (Neon) via Fly.io servers (USA)
3.7 Challenge System Data
โ๏ธPlayer-to-Player Challenges
- Challenge sender/receiver information (Player ID, name)
- Game mode requested (classic, powerup, timeAttack)
- Difficulty level requested (easy, medium, hard, expert)
- Challenge acceptance/decline status
- Challenge timestamps (sent, responded)
Legal Basis: Service contract | Purpose: Facilitate direct player-to-player matches
Retention: 60 seconds maximum (auto-expire), then permanently deleted
Storage: Temporary in-memory storage (server RAM), no persistent database storage
3.8 Authentication Tokens
๐JWT Authentication
- JWT tokens (JSON Web Tokens) containing:
- Player ID (encrypted)
- Player Name (encrypted)
- Expiration timestamp (30 days)
- Token generation timestamp
- Token stored locally (SharedPreferences - encrypted)
Legal Basis: Service contract + Security (legitimate interest)
Purpose: Secure API authentication for leaderboards, daily challenges, friends system
Expiration: 30 days (automatic renewal on reconnection)
Storage Location: Device local storage (encrypted) + server-side validation
Security: Tokens are signed using industry-standard HS256 algorithm with a 32+ character secret key
3.9 Real-Time Multiplayer Data (WebSocket/Socket.IO)
๐WebSocket Connection
During multiplayer matches, your device establishes a real-time WebSocket connection to our game server.
| Data Type | Details | Retention |
|---|---|---|
| IP Address | Used for WebSocket routing and connection management | Session only |
| Socket ID | Temporary unique identifier for your WebSocket connection | Until disconnect |
| Room ID | Temporary match identifier (shared with opponent) | Until match ends |
| Game Moves | Row, column, value placed in real-time | Match duration |
| Player Stats | Progress, combo, errors, energy (synced live) | Match duration |
| Heartbeat Signals | Connection alive pings (throttled to max 1 per 3 seconds) | Not stored |
| Power-Up Events | Type, duration, target player | Match duration |
| Match Start Timestamp | Unix timestamp (ms) when room was created (startTime) | Session only |
| Server Timestamp | Current server time (ms) for client synchronization (serverTime) | Not stored |
| Time Consumed (Time Attack) | Elapsed time in seconds (calculated from personalEndTime - currentTime) | Session only |
Timestamp Synchronization:
- startTime: Match creation timestamp (UTC) - used to calculate elapsed time
- serverTime: Current server timestamp (UTC) - sent on matchFound to sync client clock
- Usage: Calculate elapsedSeconds = (currentTime - startTime) / 1000
- Time Attack: Sync personalEndTime countdown timers across devices
- Privacy Note: Timestamps are in UTC (no timezone data sent), but difference between server and client time may indirectly reveal timezone
Time Attack - Time Consumed:
- Calculated when match ends or timer expires:
timeConsumed = (timeLimit - timeRemaining) / 1000 - Stored temporarily in player object (RAM) during match
- Sent in game_over event to both players
- Purpose: Display actual time taken to complete puzzle (performance tracking)
- Storage: Not persisted to database (session-only data)
Server: sudokupuzzle-server.fly.dev (Fly.io infrastructure, USA)
Transport Security: WebSocket Secure (WSS) over TLS 1.3
Legal Basis: Service contract (multiplayer functionality)
Purpose: Enable real-time 1v1 synchronization
๐Reconnection Dialog
When you reconnect after temporary disconnect (within 60 seconds), server sends:
- Current grid state (your puzzle with filled cells)
- Initial puzzle (frozen state at match start)
- Solution grid (complete puzzle reference)
- Opponent progress (percentage completion 0-81)
- Your stats:
- correctMoves (validated placements)
- errors (incorrect placements)
- combo (current streak)
- energy (power-up charges available)
- energyCombo (progress toward next energy point)
- currentScore (recalculated at reconnection)
- drainRate (Classic/PowerUp only)
- Elapsed time since match start (in seconds):
elapsedSeconds = Math.floor((Date.now() - room.startTime) / 1000) - personalEndTime (Time Attack only - your timer deadline in Unix timestamp ms)
- startTime (match creation timestamp - used to recalculate elapsed time client-side)
Score Recalculation on Reconnection:
- Classic/PowerUp:
score = initialPool - (elapsedSeconds ร drainRate) + (correctMoves ร basePoints) - (errors ร errorPenalty) - Time Attack:
score = currentScore(accumulated points, no recalculation needed) - Ensures fair scoring even after disconnect/reconnect
Data Source: All data retrieved from server RAM (rooms object), no database queries
Retention: Sent once on reconnection, not stored client-side beyond session
3.10 Backend Server Infrastructure
๐Leaderboard Backend Server
- Server URL: sudokupuzzle-leaderboards.fly.dev
- Location: Fly.io infrastructure (USA)
- Purpose: Store and rank player scores globally
- Data stored:
- Player ID (GPGS)
- Player Name (GPGS)
- Total scores per category (solo/multi/daily)
- Games played count
- Last submission timestamp
- Security: JWT authentication (Bearer tokens)
- Retention: 90 days inactivity-based cleanup
๐พPostgreSQL Database (Neon)
- Purpose: Persistent storage for daily challenges, friends, leaderboards
- Location: Neon infrastructure (USA)
- Data stored:
- Daily challenge scores and completion times
- Friend codes and friendships
- Friend invitations (60s expiry)
- Player statistics
- Security: Encrypted at rest (AES-256)
- Access: API requests only (no direct database access)
๐ฏ4. How We Use Your Data
4.1 Primary Purposes
| Purpose | Data Used | Legal Basis |
|---|---|---|
| Provide game service | Game data, player profile | Contract |
| Cloud synchronization | Progression data | Contract |
| Leaderboards & Achievements | Scores, name, stats | Contract |
| Performance optimization | Technical data, crash logs | Legitimate Interest |
| Security & fraud prevention | IP, device ID, transactions | Legitimate Interest |
| Personalized ads | Advertising ID, interests | Consent (Google) |
| Technical maintenance | All relevant logs | Legitimate Interest |
| Legal compliance | Relevant data | Legal Obligation |
๐Cloud Sync Conflict Resolution
When syncing data between device and cloud (GPGS), we use a MAX merge strategy:
- For win counters: Highest value kept (prevents data loss)
- For playtime: Longest time kept
- For settings: Most recent timestamp wins
Example: If you have 10 wins locally and 15 wins in cloud, we keep 15.
Rationale: This prevents accidental data loss from reinstalls or device changes.
4.2 Data Sharing
Your data is NEVER sold to third parties.
| Third Party | Data Shared | Reason | Data Processing Agreement |
|---|---|---|---|
| Google Play Games | Player ID, name, scores | Authentication & leaderboards | โ Yes (Google ToS) |
| Google AdMob | Advertising ID | Ad personalization | โ Yes (Google ToS) |
| Game Server (Fly.io) | Multiplayer stats | Real-time sync | โ Yes (encrypted) |
| Google Play Billing | Transaction data | Payment processing | โ Yes (PCI DSS) |
| PostgreSQL (Neon) | Scores, daily data, friends, challenges | Persistent database storage | โ Yes (encrypted at rest) |
| JWT Tokens (Local) | Authentication tokens (Player ID + Name) | API authentication | โ Yes (30-day expiry, HS256 signed) |
| Legal Authorities | Relevant data | Legal obligation upon request | N/A |
โณ5. Data Retention
5.1 Game Data Retention
- Solo Progression History: Retained as long as GPGS account exists + 12 months after deletion
- Multiplayer Scores: 90 days after last activity (inactivity-based cleanup)
- Daily Challenge Scores: Indefinite (for leaderboard integrity)
- Match Statistics: 2 years (classic/powerup/timeAttack match history)
- Technical Logs: 30 days (crash reports, error logs)
5.2 Payment Data Retention
- Completed Transactions: 7 years (tax compliance requirement - France & EU)
- Failed Transactions: 30 days (then permanently deleted)
- Purchase History: Indefinite via Google Play Store (managed by Google)
- Purchase Tokens: 90 days after last validation (server-side)
5.3 Profile & Preference Data
- GPGS Data: As long as your Google account exists (managed by Google)
- Preference Settings: As long as GPGS account exists + 90 days after deletion
- Cookies/Analytics: 2 years (automatic reset)
- JWT Tokens: 30 days (automatic expiration)
5.4 Friends & Social Data
- Friend Codes: As long as GPGS account exists
- Friendships: Until manually deleted by user OR 12 months after GPGS account deletion
- Friend Invitations (Pending): 60 seconds maximum (auto-expire)
- Friend Invitations (Declined): Immediately deleted upon decline
- Challenge Invitations: 60 seconds maximum (auto-expire), no persistent storage
๐6. Data Security
6.1 Technical Measures
- Encryption in Transit: HTTPS/TLS 1.3 for all transfers
- Encryption at Rest: Cloud data encrypted via GPGS, server data encrypted via PostgreSQL (AES-256)
- Server Isolation: Fly.io infrastructure with network isolation
- No Payment Storage: Payment data remains with Google (never stored locally)
- Input Validation: Protection against SQL injection, XSS attacks
- JWT Authentication: Secure tokens with 30-day expiration, HS256 signature algorithm
- PostgreSQL Encryption: Data encrypted at rest via Neon infrastructure (AES-256)
- Friend Code Hashing: Non-reversible deterministic hashing (cannot be traced back to Player ID)
- Challenge Data Volatility: Challenges stored in RAM only (60s max), never written to disk
- Purchase Token Validation: Tokens sent to server over HTTPS/TLS 1.3, validated once, then discarded
- Request Timeouts: 15 seconds maximum per API request (prevents hanging)
- Cold Start Handling: Extended timeout (12s) on server wake-up (Fly.io sleep mode)
๐WebSocket Connection Retry Logic
- Connection Timeout: 30 seconds maximum (60 attempts ร 500ms intervals)
- Retry Mechanism: Automatic retry every 500ms until connected or timeout
- Reconnection Window: 60 seconds grace period after disconnect before match abandonment
Purpose: Handle temporary network interruptions, prevent match loss due to brief disconnects
๐ก๏ธRate Limiting
Protection Levels:
- General API: 100 requests/minute per IP address
- Score Submission: 50 requests/minute per IP address
- Friend System: 30 requests/minute per IP address
- Auth Endpoints: 5 requests/minute per IP address (failed attempts counted)
Data Collected for Rate Limiting:
- IP address (temporary tracking for rate limit enforcement only)
- Request counters per IP (rolling window)
- Timestamp of first request in current window
Implementation:
- Express-rate-limit middleware (server-side)
- Rolling window algorithm (resets every 60 seconds)
- HTTP 429 "Too Many Requests" response when limit exceeded
Retention: 60 seconds (rolling window), then automatically cleared
Purpose: Prevent API abuse, DDoS attacks, score manipulation via spam
Legal Basis: Legitimate interest (security - GDPR Article 6.1.f)
๐จAnti-Cheat - Suspicious Score Flagging
Detection Criteria:
- Scores exceeding maximum thresholds:
- Solo Easy: > 5000 points
- Solo Medium: > 8000 points
- Solo Hard: > 10000 points
- Solo Expert: > 15000 points
- Multi Classic: > 7000 points
- Multi PowerUp: > 12000 points
- Time Attack Classic: > 6000 points
- Time Attack PowerUp: > 10000 points
- Negative scores (impossible under normal gameplay)
- Invalid difficulty/mode combinations
- Submission rate anomalies (via rate limiting)
Flagging Process:
- Suspicious scores are logged to PostgreSQL table:
suspicious_scores - Data stored: player_id, score, game_type, difficulty, reason (validation failure message), flagged_at (timestamp)
- Flagged scores are rejected (HTTP 400 Bad Request) - NOT saved to leaderboards
- Console log generated:
๐จ Score suspect: {playerId} - {score} pts ({reason})
Storage & Retention:
- Database: PostgreSQL (Neon) - table: suspicious_scores
- Retention: Indefinite (for fraud investigation and pattern analysis)
- Access: Internal review only (not shared with third parties)
Your Rights:
- Request deletion of flagged records via email: contact.thecatsizerlab@gmail.com
- Appeal false positives with evidence (screenshots, gameplay videos)
- GDPR Right to Erasure applies (Article 17) - unless fraud investigation ongoing
Purpose: Detect and prevent score manipulation, maintain leaderboard integrity, protect fair play
Legal Basis: Legitimate interest (fraud prevention - GDPR Article 6.1.f)
6.2 Organizational Measures
- Access to data limited to authorized personnel only
- Confidentiality agreements with all service providers
- Regular security audits
- Automated dependency updates and security patches
โ7. Your Privacy Rights
7.1 Right of Access (GDPR Article 15)
You can request access to your personal data.
How to Request:
- Email: contact.thecatsizerlab@gmail.com
- Response Time: 30 days
Data Accessible Directly:
- GPGS Profile: Google Play Games > Settings
- Purchase History: Google Play Store > Account > Payments and Subscriptions
- Google Privacy Settings: myaccount.google.com
7.2 Right of Correction (GDPR Article 16)
You can correct inaccurate data about yourself.
- Edit your GPGS profile directly in Google Play Games
- Update preferences within the Application settings
7.3 Right to Erasure (GDPR Article 17)
You can request deletion of your personal data. However, certain data must be retained for the app to function properly.
๐๏ธWhat Can Be Deleted
| Data Type | Deletion Method | Effect |
|---|---|---|
| Google Play Games Profile | Delete GPGS account via Google Settings | Complete account removal from GPGS (managed by Google) |
| Local Device Data | Uninstall app or Clear Data in Android Settings | All local progress deleted |
| Specific Friendships | Settings > Friends > Remove Friend | Individual friend removed from your list |
| JWT Tokens | Automatic after 30 days OR manual logout | Re-authentication required |
| Temporary Game Backups | Automatic after 1 hour | No manual action needed |
๐What CANNOT Be Deleted (Service Integrity)
The following data is essential for the app to function and cannot be deleted while you maintain an active account:
| Data Type | Reason for Retention | Legal Basis (GDPR) |
|---|---|---|
| Leaderboard Scores | Required for competitive ranking integrity. Deleting scores would artificially boost other players' ranks. | Article 17.3.b (Public Interest) + Article 6.1.b (Contract) |
| Player Profile Statistics (games played, win rate, etc.) |
Core functionality of your account. Without stats, profile features are non-functional. | Article 6.1.b (Contract - necessary for service provision) |
| Friend Connections | Social feature foundation. Your friends list is part of your account data. | Article 6.1.b (Contract) + Article 6.1.a (Consent - given when adding friends) |
| Friend Code | Unique identifier for friend system. Required for other players to find you. | Article 6.1.b (Contract) |
| Daily Challenge History | Historical leaderboard integrity. Past rankings cannot be retroactively altered. | Article 17.3.b (Public Interest) |
| Match History | Used for matchmaking balancing and anti-cheat systems. | Article 6.1.f (Legitimate Interest - fraud prevention) |
| Premium Purchases | Legal requirement for tax records and fraud prevention. | Article 17.3.b (Legal Obligation - 7 years retention, France/EU law) |
| Player Name (GPGS) | Managed by Google Play Games Services. We cannot delete GPGS data. | Third-party service (see Google's Privacy Policy) |
- Data is necessary for contract performance (Article 6.1.b) โ
- Data serves a public interest (leaderboard integrity - Article 17.3.b) โ
- Data is required by law (tax records - Article 17.3.b) โ
Your choice: Keep your account with all features OR delete your Google Play Games account (removes everything via Google).
๐How to Completely Remove Your Data
If you want to completely erase your presence from the app, you must:
- Delete Your Google Play Games Account
- Open Google Play Games app
- Tap Profile > Settings
- Select "Delete Play Games account & data"
- Effect: All GPGS data deleted within 30 days (managed by Google)
- Uninstall Sudoku Puzzle
- Long-press app icon > Uninstall
- Effect: All local device data deleted immediately
- Request Server Data Cleanup (Optional)
- Email contact.thecatsizerlab@gmail.com
- Provide proof of GPGS account deletion
- We will delete: Orphaned server records (scores, friendships, etc.) within 90 days
- We will retain: Purchase records (7 years - legal requirement)
- Your former Player ID (if known)
- Your former display name
- Screenshot of GPGS account deletion confirmation
Processing time: 30 days maximum
โ๏ธGDPR Compliance Justification
We comply with GDPR while maintaining service integrity through these legal bases:
- Article 6.1.b (Contract Necessity): Your game data, stats, and friends are necessary to provide the service you signed up for. Deleting them would render your account non-functional.
- Article 17.3.b (Public Interest): Leaderboard integrity is a public interest for all competitive players. Retroactive score deletion would unfairly manipulate rankings.
- Article 17.3.b (Legal Obligation): Purchase records must be retained 7 years for tax compliance (French/EU law).
- Article 6.1.f (Legitimate Interest): Match history used for anti-cheat and matchmaking balance.
Conclusion: If you want to stop using the app but keep your GPGS account active, simply uninstall the app. If you want complete erasure, you must delete your Google Play Games account (which we don't control).
7.3.1 Partial Data Deletion
You can request deletion of specific types of data without deleting everything:
| Data Type | How to Delete | Impact |
|---|---|---|
| Leaderboard Scores | Email request with Player ID | Your scores removed from public leaderboards |
| Friends List | Settings > Friends > Remove individual friends | Removes specific friendships only |
| Daily Challenge History | Email request with Player ID | Your daily challenge scores removed from rankings |
| Match History | Email request with Player ID | Past game records deleted from our database |
| Local Device Data | App Settings > Storage > Clear Data | All local progress and settings deleted |
| GPGS Cloud Saves | Google Play Games > Settings > Delete saved game | Cloud backup removed (local data remains) |
| Purchase History | Cannot be deleted | Legal requirement (7 years retention) |
| GPGS Achievements | Cannot be selectively deleted | Must delete entire GPGS profile via Google |
To request partial deletion: Email contact.thecatsizerlab@gmail.com with your Player ID and specify exactly which data you want deleted.
7.4 Right to Data Portability (GDPR Article 20)
You can request your data in a structured, portable format.
How: Email a request to contact.thecatsizerlab@gmail.com with proof of identity
7.5 Right to Object (GDPR Article 21)
- Personalized Ads: Modify your Google Ads settings
- Analytics: Opt-out via device privacy settings
- Marketing: Unsubscribe from marketing lists (if applicable)
7.6 Right to Restrict Processing (GDPR Article 18)
You can request to limit how your data is processed while addressing
โ๏ธ8. Legal Compliance
8.1 GDPR (European Union)
Sudoku Puzzle complies with the General Data Protection Regulation (GDPR):
- Data Controller: TheCatsizerLab
- Legal Basis: Consent + Contract + Legitimate Interest
- Consent Process: Modal displayed on first launch
- Right to Withdraw: Changeable anytime in Settings > Privacy
- Data Processing Agreement: Available upon request
8.2 CCPA (California, USA)
For California residents, you have additional rights:
- Right to Know: Demand information on data collection
- Right to Delete: Request data deletion (with exceptions)
- Right to Opt-Out: Deny "sale" of personal information (see Section 9)
- Right to Non-Discrimination: No penalties for exercising your rights
CCPA Request Process: Send verified request to contact.thecatsizerlab@gmail.com with:
- Proof of identity
- Proof of California residence
- Detailed description of requested data
Response Time: 45 days
8.3 France - Loi Informatique et Libertรฉs
Sudoku Puzzle complies with French Law nยฐ78-17 of January 6, 1978:
- Data processing declarations compliant
- Right to object to processing
- Right of access to personal data
- DPO contact available
8.4 Other Jurisdictions
- UK: Compliant with UK GDPR
- Switzerland: Compliant with Federal Data Protection Act (LPD)
- Canada: Compliant with PIPEDA
- Australia: Compliant with Privacy Act 1988
๐ฏ9. Consent & Preference Management
9.1 Initial Consent
A consent modal is displayed on the first app launch containing:
| Option | Description |
|---|---|
| โ Personalized Ads | Allow AdMob to show targeted advertisements |
| โ Game Data | Allow cloud synchronization of progression |
| ๐ Link to Policy | Direct access to this privacy policy |
Actions:
- Accept All (recommended for full experience)
- Reject All (app functional, no personalization)
- Customize (granular control per category)
- Direct link in consent modal (first launch)
- Settings > Privacy & Security > View Privacy Policy
- Permanent URL: https://thecatsizer-dev.github.io/SudokuPuzzle-PrivacyPolicy/
9.2 Managing Your Preferences
Modify consent anytime via: Settings > Privacy & Security
| Setting | Impact if Disabled | Can Disable? |
|---|---|---|
| Personalized Ads | Generic ads instead of targeted | โ Yes |
| Game Analytics | Collecte automatique (requis pour le fonctionnement) | โ No |
| Cloud Sync | Local storage only | โ Yes |
| Push Notifications | Silent mode | โ Yes |
9.3 Withdraw Consent
You can withdraw consent at any time by:
- Changing preferences in the app settings
- Emailing us at contact.thecatsizerlab@gmail.com
- Disabling services in Google Privacy Dashboard
Withdrawal is effective immediately. Previously collected data remains processed per this policy.
a๐ช10. Cookies & Tracking Technologies
10.1 Local Storage
The app uses SharedPreferences (Android local storage) to store:
- User preferences (theme, language, audio settings)
- Session tokens (JWT authentication)
- Consent status (privacy preferences)
- Match history (last 5 matches)
- Achievement progress tracking
- Audio preferences (volume, enabled/disabled)
Cloud storage via Google Play Games Services for:
- Game progression (cloud saves, encrypted by Google)
- Leaderboard scores
- Unlocked achievements
Technically these are not "cookies" but persistent local files.
10.2 Firebase Analytics & Crashlytics
๐Firebase Analytics
Google Firebase Analytics collects usage data automatically:
- Game events: Match start, victory, defeat, abandonment (manually logged via code)
- App performance metrics: Session duration, screen views, app startup time
- User properties: Device type, OS version, app version, user cohorts
- Ad interaction events: Ad impressions, clicks, rewarded ad completions
Storage: Anonymized and aggregated, retained 14 months by Google
Legal Basis: Legitimate interest (GDPR Article 6.1.f - analytics for service improvement)
โ ๏ธFirebase Crashlytics
Automatic crash reporting system (see Section 3.2 for full details):
- Crash reports: Fatal errors with stack traces
- Device state: Memory, storage, battery at crash time
- Session data: App version, crash timestamp
Storage: Firebase servers (Google Cloud, USA), retained 90 days
Legal Basis: Legitimate interest (technical maintenance)
Opt-Out:
- Analytics: Device Settings > Google > Manage Account > Privacy > Analytics
- Crashlytics: Cannot be disabled (required for technical maintenance)
10.3 Google Advertising ID
Google assigns you a unique advertising ID for:
- Targeted ads in AdMob
- Ad frequency limiting
- Campaign performance measurement
Manage: Settings > Google > Manage Account > Privacy > Ad Settings
Reset: Settings > Google > Privacy > Reset Advertising ID
10.4 Tracking Links (UTM)
Promotional links may include UTM parameters to measure campaign effectiveness.
๐ถ11. Children's Privacy (COPPA & GDPR)
11.1 Age Requirements
- US (COPPA): โฅ 13 years old
- Europe (GDPR): โฅ 16 years old (varies by country)
- France: โฅ 13 years old
11.2 Minors' Data Protection
If you are under the age of digital consent in your jurisdiction:
- Your data receives enhanced protection
- Parent/guardian consent is required
- Data collection is minimized
- No profile-based ad targeting
- Data deletion upon reaching majority (on request)
11.3 Parental Controls
Parents/guardians can:
- Restrict IAP: Google Play > Parental Controls > Require Authentication
- Limit Ads: Disable personalized advertising
- View History: Google Play Family Library
- Delete Account: Request via email with proof
11.4 Report Inappropriate Content
If you find content unsuitable for children: contact.thecatsizerlab@gmail.com with screenshot
๐12. International Data Transfers
12.1 Server Locations
- Europe: Google Cloud (Frankfurt/Ireland)
- Outside EU: Data shared with Google (USA-based)
- Fly.io: Decentralized CDN infrastructure (USA)
12.2 Legal Safeguards
For transfers outside EU to USA, we rely on:
- Standard Contractual Clauses (SCCs): EU-USA model
- Google Data Processing Terms: SCC-compliant
- Adequacy Decisions: Switzerland/UK/Canada recognized
12.3 Your Control
You can request:
- Copy of contractual safeguards
- Information on specific transfers
- Limitation of transfers (may impact service)
๐13. Policy Changes
13.1 Right to Modify
We may update this policy for:
- Legal compliance changes
- Error corrections
- Practice changes
- Clarifications
13.2 Notification
- Major Changes: In-app notification 30 days before
- Minor Changes: Published on this page with date
- Acceptance: New consent required for major changes
13.3 Version History
| Version | Date | Changes |
|---|---|---|
| 1.0 | December 19, 2025 | Initial publication |
| 1.1 | December 20, 2025 | Added: Daily Challenge system, Friends system, Challenge system, JWT tokens, PostgreSQL database, Purchase validation details |
| 1.2 | December 27, 2025 | Added: Socket.IO (WebSocket) real-time data, Backend server infrastructure details (Fly.io, Neon PostgreSQL), Rewarded/Interstitial ads timing, Audio preferences, Achievement tracking, Cloud sync conflict resolution, Request retry logic, Private GPGS leaderboards, Friend code validation format, Purchase restoration process, Vibration permission clarification |
| 1.3 | January 10, 2026 | Clarified: Local storage uses SharedPreferences (not Hive), encryption details corrected to reflect actual implementation (GPGS cloud encryption, PostgreSQL server encryption) |
๐14. Contact & Complaints
14.1 Questions or Issues
Email: contact.thecatsizerlab@gmail.com
Response Time: 7 business days
Required Information:
- Subject (data access, concern, rights exercise)
- Detailed description
- Supporting documents if applicable
14.2 File a Complaint with Authorities
If you believe we violate your rights, you can lodge complaints with:
- CNIL (France): www.cnil.fr
- Your Country's DPA: Contact your local data protection authority
- CCPA (California): California Attorney General
- OAIC (Australia): www.oaic.gov.au
14.3 Complaint Procedure
Before escalating to authorities:
- Contact us directly (see 14.1)
- Allow 30 days for resolution
- Provide evidence of resolution attempts
โน๏ธ15. Additional Information
15.1 Sensitive Data
We NEVER collect:
- โ Biometric data
- โ Health data
- โ Genetic data
- โ Religious/political beliefs
- โ Sexual orientation data
- โ National ID numbers
15.2 Profiling & Automated Decisions
- Multiplayer Matching: Algorithm by level/rank (no profiling)
- Theme Recommendations: Usage statistics only
- Ads: Google targeting (you control)
- No automated decisions affecting your rights
15.3 External Links
This policy does NOT cover:
- Google Play Store
- Google Services (Gmail, YouTube, etc.)
- External websites
Please review their privacy policies separately.
โก16. Final Provisions
16.1 Complete Agreement
This policy is the complete agreement between you and TheCatsizerLab regarding personal data processing. It supersedes all previous versions.
16.2 Severability
If any provision is invalid, remaining clauses remain enforceable.
16.3 No Waiver
Non-exercise of a right does not constitute waiver of that right.
16.4 Governing Law
- Jurisdiction: Zigliara, South Corsica, France
- Governing Law: French Law + GDPR
- Competent Courts: District Courts of Ajaccio, Corsica
16.5 Prescription Period
GDPR rights must be exercised within 3 years of becoming aware of the violation.
๐17. Glossary
General Data Protection Regulation (European Union data protection law)
California Consumer Privacy Act (US state law)
Children's Online Privacy Protection Act (US federal law)
Data Protection Officer
Standard Contractual Clauses (for international data transfers)
In-App Purchase
Google Play Games Services
Android local key-value storage system for app preferences
Backend hosting platform with global CDN
Real-time WebSocket library for multiplayer synchronization
JSON Web Token - Secure authentication token format
Serverless PostgreSQL database provider
Explicit user agreement to data processing
โค๏ธThank You
Thank you for taking the time to read our privacy policy. Your trust is important to us.
This document contains the complete Privacy Policy for Sudoku Puzzle by TheCatsizerLab.
Total Sections: 17 complete sections covering all data collection, processing, security, and user rights.
Last Updated: January 10, 2026 (Version 1.3)