Port the Chad Music cloud streaming feature from macOS MixBoard to iOS MixBoard. Users connect to a self-hosted Chad Music REST API server (Tailnet) to browse and stream their cloud music library. Cloud tracks can be mixed into the same playlists as local tracks.
| File | Location | Purpose |
|---|---|---|
| ChadMusic.swift | Models/ | API response models (ChadCategory, ChadAlbum, ChadTrack, ChadStats, ChadCategoryType) |
| ChadMusicAPIClient.swift | Services/ | HTTP client — Bearer auth, URL composition, JSON decoding |
| StreamingPlayer.swift | Services/ | AVPlayer-based streaming (separate from AVAudioEngine) |
| KeychainService.swift | Services/ | Keychain wrapper for API key storage |
| CloudBrowserView.swift | Views/ | Browse categories → albums → tracks with play/add-to-playlist |
| File | Changes |
|---|---|
| Track.swift | Add isCloud, cloudStreamPath, cloudTrackId + fromCloud() factory |
| PlayerViewModel.swift | Add StreamingPlayer, dual-source routing, cloud transport |
| SettingsView.swift | Add "Chad Music" section (URL, API key, test connection) |
| ContentView.swift | Add cloud browser sheet trigger |
| MiniPlayerView.swift | Buffering indicator, cloud icon |
| MixBoardApp.swift | Bump DB reset to dbResetV7 |
isCloud=true in SwiftDataisCloud, builds stream URL, uses StreamingPlayerisCloudPlayback flagCloudBrowserView is presented as a sheet from a toolbar button in PlaylistListView — consistent with the existing Library/Settings sheet pattern.
Nuclear reset approach (existing pattern): bump dbResetV6 → dbResetV7 to force schema recreation with new Track fields.