Round-3 audit (on vc=69) caught three real HIGHs plus three worth-fixing
MEDs. All in the same family: 'isAllowedYtUrl gate missing at consumer
side.'
HIGH-1 — ChannelScreen ignored the round-2 loadedUrl gate
Round 2 added loadedUrl to ChannelUiState but ChannelScreen never
read it. Channel A → back → Channel B showed A's data for one frame
before vm.load(B) cleared it. Same shape as the VideoDetailScreen
fix; matching gate added.
HIGH-2 — PlaybackService.tryAutoplay missing allowlist
Both the SameChannel path (channelInfo(uploaderUrl)) and the
candidate-resolve path (streamInfo(candidateUrl)) hit strawcore
with extractor-derived URLs. Gate added on both call sites, plus
the picker's intermediate uploaderUrl check.
HIGH-3 — VideoActionsSheet.enqueue missing allowlist
Long-press on a poisoned related-card / channel video → 'Add to
queue' invoked uniffi.strawcore.streamInfo on the raw target.url.
Bail with Toast before launching the resolve coroutine.
MED-1 — FeedRefreshWorker doesn't retry on RequiresLogin
reCAPTCHA challenges clear minutes-to-hours later. Treating them
as permanent ate a full refresh cycle. Catch
StrawcoreException.RequiresLogin → Result.retry().
MED-3 — VideoDetail.uploaderUrl persisted raw extractor value
Round-2 added safeFresh for the avatar but the uploaderUrl saved
to VideoDetail.detail was still info.uploaderUrl. NowPlaying →
PlaybackService picked up the raw value. Validate once and persist
the SAFE value so the whole downstream chain inherits it.
MED-4 — enrich-job filter rebuilt Set per iteration
.filter { it.url in channelsSnapshot.map { c -> c.url }.toSet() }
was O(N²). Hoist via mapTo(HashSet()) once.
Bonus sweep — gated two more uniffi.strawcore.* sites the round-3
agent's category prediction caught:
* SubscriptionFeedViewModel.enrichVisibleItems → enrichFeedItem
now skips items failing isAllowedYtUrl.
* PlaybackService autoplay candidate-resolve already covered
under HIGH-2 above.
|
||
|---|---|---|
| .. | ||
| src/main | ||
| build.gradle.kts | ||
| proguard-rules.pro | ||