Complete audit covering 6 areas: - Security: 6 CRITICAL issues (plaintext credentials, cert validation) - Memory: 6 leak locations (unbounded caches, untracked subscriptions) - Race Conditions: 4 issues (player state, async reentrancy) - Architecture: God class (4,469 LOC), zero tests, 55 hardcoded colors - Accessibility: 0 Semantics widgets, touch targets below 48dp - Audio/Networking: 6 HIGH issues (no indexes, non-atomic queue) Overall score: 5.5/10 Estimated technical debt: 44-66 dev-days 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
12 KiB
Ensemble Codebase Intensive Audit Prompt
Overview
You are tasked with conducting an intensive, comprehensive audit of the Ensemble Flutter application - a Music Assistant client for Android with multi-device synchronization, local playback, and Sendspin raw audio streaming capabilities.
Codebase Statistics:
- 90 Dart files, ~40,583 lines of code
- 18 screens, 27 services, 6 providers
- Architecture: Provider pattern with ChangeNotifier
- Audio: just_audio + flutter_pcm_sound + audio_service
- Networking: WebSocket (JSON-RPC) + HTTP + Sendspin binary protocol
Audit Scope
Perform a thorough audit covering ALL of the following areas. For each issue found, provide:
- File path and line number(s)
- Severity: CRITICAL / HIGH / MEDIUM / LOW
- Description of the issue
- Impact if left unfixed
- Recommended fix with code example where applicable
SECTION 1: SECURITY AUDIT
1.1 Credential Storage (CRITICAL PRIORITY)
Audit /lib/services/settings_service.dart for:
- Plaintext password storage in SharedPreferences (lines 209-222)
- Auth tokens stored without encryption
- Serialized credentials in JSON format (lines 169-190)
Expected Finding: Credentials stored insecurely. Recommend flutter_secure_storage.
1.2 Certificate Validation
Audit /lib/services/auth/auth_manager.dart for:
- HTTPS redirect handling for local IPs
- Certificate validation disabled scenarios
- MITM vulnerability exposure
1.3 Authentication Strategies
Audit all files in /lib/services/auth/:
basic_auth_strategy.dart- Base64 encoding (not encryption)authelia_strategy.dart- Session cookie handling, timing attack (line 159)ma_auth_strategy.dart- Token refresh mechanismno_auth_strategy.dart- Public server exposure
1.4 Input Validation
Audit /lib/services/music_assistant_api.dart:
- URI construction without validation (lines 1346-1360)
- Provider/itemId injection risks
- WebSocket message validation
1.5 Information Disclosure
- Debug logs exposing sensitive data (check all
_logger.log()calls) - Server version exposure via
server_info - Error messages leaking technical details
SECTION 2: MEMORY MANAGEMENT AUDIT
2.1 Static Memory Leaks
Audit /lib/models/player.dart:
_playerCreationTimesstatic map (lines 96-144) - grows unbounded- Cleanup only removes 50 of 100+ entries
2.2 Unbounded Caches
Audit /lib/services/cache_service.dart:
_albumTracksCache- no size limit_artistAlbumsCache- no TTL expiration_searchCache- never evicted_playerTrackCache- only cleared on disconnect
2.3 Stream/Timer Cleanup
Audit /lib/providers/music_assistant_provider.dart:
_playerStateTimerdisposal (line 4435-4445)_notificationPositionTimermultiple creation paths (lines 2925-2940)_localPlayerEventSubscriptioncleanup_playerUpdatedEventSubscriptioncleanup_playerAddedEventSubscriptioncleanup
Audit /lib/services/hardware_volume_service.dart:
_volumeUpControllernever closed (lines 74-85)_volumeDownControllernever closed
2.4 Stream Subscription Leaks
Audit /lib/providers/music_assistant_provider.dart:
_api!.connectionState.listen()- subscription not stored- Old subscriptions not cancelled before new API instance
SECTION 3: RACE CONDITION AUDIT
3.1 Player State Dual Updates
Audit /lib/providers/music_assistant_provider.dart:
- Timer polling (every 5s) vs WebSocket events racing
_updatePlayerState()called from both paths- No mutex/lock protection
3.2 Async Method Reentrancy
Audit selectPlayer() method:
asyncmethod without guard against concurrent calls_selectedPlayermodified before and afterawait- State could change during await
3.3 Fire-and-Forget Operations
Search for unawaited( and () async { patterns:
_persistPlaybackState()- database save not awaited- Pause operations fire-and-forget (lines 3876-3894)
- Preload operations (line 2707)
3.4 PCM Player State Machine
Audit /lib/services/pcm_audio_player.dart:
- 9-state machine with complex transitions (lines 32-37)
- Auto-recovery race condition (lines 215-229)
- Feed loop during pause transition (lines 174-179)
SECTION 4: ERROR HANDLING AUDIT
4.1 Silent Exception Handlers (CRITICAL)
Find all instances of:
} catch (e) {}
} catch (_) {}
Known locations:
music_assistant_provider.dart(multiple)player_provider.dart(3 instances)recently_played_service.dart
4.2 Missing Error Recovery
- No exponential backoff on connection retry
- No retry logic for failed API calls
- WebSocket timeout handling (30 seconds - too long?)
4.3 Null Safety Violations
Find all ! (null assertion) operators:
search_screen.dart(20+ instances)models/media_item.dartmodels/player.dartitem.mediaItem! as Artistpatterns
SECTION 5: ARCHITECTURAL ISSUES
5.1 God Class
Audit /lib/providers/music_assistant_provider.dart:
- 4,469 lines - violates Single Responsibility
- 386 conditional branches
- Mixing: connection, players, library, sync, audio, position tracking
Recommend splitting into:
- ConnectionProvider (~500 LOC)
- PlayerManager (~800 LOC)
- LibraryProvider (~1000 LOC)
- LocalPlaybackManager (~600 LOC)
5.2 Oversized Widget Files
expandable_player.dart- 2,485 lines (should be <500)global_player_overlay.dart- 737 linesnew_library_screen.dart- 2,521 lines
5.3 Global Key Anti-Pattern
Audit /lib/widgets/global_player_overlay.dart:
globalPlayerKeyfor state access_overlayStateKeyfor overlay state- Should use Provider/context instead
5.4 Primitive Obsession
- View modes as strings ('grid2', 'grid3', 'list')
- Media types as strings ('track', 'album', 'artist')
- Should be strongly-typed enums
SECTION 6: CODE QUALITY ISSUES
6.1 Testing (CRITICAL)
- ZERO test files exist - confirm this
- No unit tests, widget tests, or integration tests
- flutter_test dependency exists but unused
6.2 Hardcoded Values
Find and document all:
- Color hex codes (50+ instances of
Color(0xFF...) - Duration values not using
Timingsconstants - Magic numbers (16, 4, 5, 100, 50)
- String literals for media types
6.3 Mixed Async Patterns
.then()chains alongside async/await.whenComplete()usage- Consolidate to async/await
6.4 Dead Code
@Deprecatedmethods still implementedanimation_debugger.dart- dev-only?- Unused imports
6.5 TODO Comments
Document all actionable TODOs:
queue_screen.dart:214- queue item removalaudiobook_detail_screen.dart:261,312- progress syncmusic_assistant_provider.dart:793,799- playlist modification
SECTION 7: UI/UX AUDIT
7.1 Accessibility (CRITICAL)
Audit for missing:
Semanticswidgets on interactive elementsTooltipon icon buttons- Screen reader support
- Touch target sizes (minimum 48dp)
- Color contrast validation (WCAG AA)
7.2 Performance Issues
Audit /lib/widgets/expandable_player.dart:
- No
RepaintBoundarywrappers - 55+
setState()calls - 3 AnimationControllers with multiple listeners
- Title height cache invalidation (lines 118+)
7.3 Double Opacity Bug
Audit /lib/widgets/player/player_controls.dart:
color: (shuffle == true ? primaryColor : textColor.withOpacity(0.5))
.withOpacity(expandedElementsOpacity),
- Double
.withOpacity()application
7.4 Missing Features
- No landscape orientation support
- No tablet layout optimization
- No loading skeleton animations
- No haptic feedback (except one location)
SECTION 8: AUDIO PLAYBACK AUDIT
8.1 Position Interpolation
Audit /lib/services/position_tracker.dart:
- No timeout on anchor updates - unbounded drift possible
- Duration interpolation can exceed track duration
- Stale timestamp handling (>30 seconds)
8.2 Sendspin Protocol
Audit /lib/services/sendspin_service.dart:
- Proxy auth retry without deduplication (lines 188-209)
- WebSocket binary frame parsing
- Clock synchronization accuracy
8.3 Audio Resource Cleanup
Audit /lib/services/audio/massiv_audio_handler.dart:
- Audio session interrupt listeners not disposed
- Audio focus not explicitly released
8.4 Mixed Playback Modes
- just_audio initialized but unused during Sendspin
- Resource allocation for unused player
- Potential audio focus conflicts
SECTION 9: NETWORKING AUDIT
9.1 WebSocket Lifecycle
Audit /lib/services/music_assistant_api.dart:
- Heartbeat interval (30s) - appropriate?
- Reconnection logic and timing
- Pending request cleanup on disconnect
9.2 Caching Strategy
- No incremental/delta sync (full library every 5 minutes)
- Cache staleness not communicated to UI
- No query result pagination (fetches up to 5000 items)
9.3 Rate Limiting
- No client-side rate limiting
- Search requests not throttled
- Could overload server
9.4 Offline Support
Audit /lib/services/offline_action_queue.dart:
- Queue execution not atomic (lines 118-130)
- Action could execute twice on crash
- Queue stored unencrypted
SECTION 10: DATABASE AUDIT
10.1 Schema Review
Audit /lib/database/database.dart:
- Table indexes for query performance
- Foreign key constraints
- Migration strategy
10.2 Query Patterns
- N+1 query prevention
- Transaction usage for atomic operations
- Connection pooling
10.3 Data Consistency
- Tier 1 (DB) vs Tier 2 (API sync) race conditions
- User modifications during background sync
- Conflict resolution strategy
Deliverables
After completing the audit, provide:
1. Executive Summary
- Overall code quality score (1-10)
- Top 5 critical issues requiring immediate attention
- Estimated technical debt in developer-hours
2. Issue Tracker
Create a prioritized list of all issues found:
| ID | Severity | Category | File:Line | Description | Effort |
|---|
3. Recommended Roadmap
Sprint-based plan to address findings:
- Sprint 1 (Immediate): Security fixes, silent exception handlers
- Sprint 2-3: God class decomposition, test infrastructure
- Sprint 4-6: Memory leak fixes, accessibility
- Long-term: Performance optimization, monitoring
4. Code Examples
For each CRITICAL and HIGH severity issue, provide:
- Current problematic code
- Recommended refactored code
- Migration steps
Files to Prioritize
Start your audit with these critical files:
/lib/providers/music_assistant_provider.dart(4,469 LOC) - God class/lib/services/settings_service.dart- Credential storage/lib/services/music_assistant_api.dart(2,929 LOC) - Networking/lib/widgets/expandable_player.dart(2,485 LOC) - UI complexity/lib/services/auth/directory - Security/lib/models/player.dart- Memory leaks/lib/services/cache_service.dart- Unbounded caches/lib/services/position_tracker.dart- Audio sync issues
Known Critical Issues (Pre-Identified)
These issues have been identified and MUST be verified and documented:
- CRITICAL: Plaintext credential storage - SharedPreferences without encryption
- CRITICAL: Zero test coverage - No unit, widget, or integration tests
- CRITICAL: 4,469 line god class - MusicAssistantProvider violates SRP
- CRITICAL: Silent exception handlers -
catch (e) {}patterns - HIGH: Static memory leak -
_playerCreationTimesunbounded growth - HIGH: Race conditions - Player state polling vs events
- HIGH: No accessibility - Missing Semantics, screen reader support
- HIGH: Certificate validation disabled - MITM vulnerability for local IPs
- MEDIUM: Double opacity bug -
.withOpacity().withOpacity()in player controls - MEDIUM: Position tracker drift - No timeout on anchor updates
Audit Execution Notes
- Use
Greptool to search for patterns across the codebase - Use
Readtool to examine specific file sections - Document line numbers for all findings
- Provide code snippets for context
- Cross-reference related issues across files
- Verify pre-identified issues exist and document their exact locations
Total estimated audit time: 4-6 hours for thorough coverage