UpdateChannelHandler silently coerced a Mirror-mode request back to Generated when the channel had a playout — returning 200 with a value the client never asked for. Now the invalid transition (request PlayoutSource=Mirror AND channel already has a playout) is rejected with 422; Playouts is .Include()-loaded so the check is non-vacuous, and a GET→PUT round-trip of an unchanged Generated channel is unaffected.
Second commit repairs a data-integrity bug the independent review caught: ApplyUpdateRequest had a dead else-branch (Mirror-only fields were nulled for non-Mirror channels, then unconditionally overwritten two lines later), so removing the old coercion would let a stray MirrorSourceChannelId/PlayoutOffset persist onto a Generated channel. Fixed by scoping the assignment to the Mirror branch; negative-controlled (new test fails pre-fix, passes post-fix). 10/10 tests green.
Review: write-path — independent cold review found + I verified the dead-else regression; fix commit re-reviewed against the prescribed diff. Review-verdict posted below.
UpdateChannelHandler silently coerced a Mirror-mode request back to Generated when the channel had a playout — returning 200 with a value the client never asked for. Now the invalid transition (request PlayoutSource=Mirror AND channel already has a playout) is rejected with 422; `Playouts` is `.Include()`-loaded so the check is non-vacuous, and a GET→PUT round-trip of an unchanged Generated channel is unaffected.
Second commit repairs a **data-integrity bug the independent review caught**: `ApplyUpdateRequest` had a dead else-branch (Mirror-only fields were nulled for non-Mirror channels, then unconditionally overwritten two lines later), so removing the old coercion would let a stray `MirrorSourceChannelId`/`PlayoutOffset` persist onto a Generated channel. Fixed by scoping the assignment to the Mirror branch; negative-controlled (new test fails pre-fix, passes post-fix). 10/10 tests green.
**Review:** write-path — independent cold review found + I verified the dead-else regression; fix commit re-reviewed against the prescribed diff. Review-verdict posted below.
fixes #401
Closes review finding: stray MirrorSourceChannelId/PlayoutOffset could persist onto a Generated channel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review-verdict: MERGEABLE @ 10d891ba63
Write-path. Independent cold review found a real data-integrity regression (dead else-branch → stray MirrorSourceChannelId/PlayoutOffset could persist on a Generated channel); fixed in commit 10d891ba63 and negative-controlled (new test fails pre-fix, passes post-fix). Fix commit re-reviewed against the prescribed diff. 10/10 tests green.
Review-verdict: MERGEABLE @ 10d891ba63572add9c9f7aa7daeb69bc872a8d51
Write-path. Independent cold review found a real data-integrity regression (dead else-branch → stray MirrorSourceChannelId/PlayoutOffset could persist on a Generated channel); fixed in commit 10d891ba63572add9c9f7aa7daeb69bc872a8d51 and negative-controlled (new test fails pre-fix, passes post-fix). Fix commit re-reviewed against the prescribed diff. 10/10 tests green.
Live-E2E PASSED (scripts/e2e-local.sh, real /api endpoints, machine-key auth). Every mutation round-trips through a subsequent GET — the write-path requirement per docs/e2e-local.md is satisfied. Proceeding to merge.
Live-E2E PASSED (scripts/e2e-local.sh, real /api endpoints, machine-key auth). Every mutation round-trips through a subsequent GET — the write-path requirement per docs/e2e-local.md is satisfied. Proceeding to merge.
timothy
merged commit ca87336600 into main2026-07-18 18:27:26 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
UpdateChannelHandler silently coerced a Mirror-mode request back to Generated when the channel had a playout — returning 200 with a value the client never asked for. Now the invalid transition (request PlayoutSource=Mirror AND channel already has a playout) is rejected with 422;
Playoutsis.Include()-loaded so the check is non-vacuous, and a GET→PUT round-trip of an unchanged Generated channel is unaffected.Second commit repairs a data-integrity bug the independent review caught:
ApplyUpdateRequesthad a dead else-branch (Mirror-only fields were nulled for non-Mirror channels, then unconditionally overwritten two lines later), so removing the old coercion would let a strayMirrorSourceChannelId/PlayoutOffsetpersist onto a Generated channel. Fixed by scoping the assignment to the Mirror branch; negative-controlled (new test fails pre-fix, passes post-fix). 10/10 tests green.Review: write-path — independent cold review found + I verified the dead-else regression; fix commit re-reviewed against the prescribed diff. Review-verdict posted below.
fixes #401
Review-verdict: MERGEABLE @
10d891ba63Write-path. Independent cold review found a real data-integrity regression (dead else-branch → stray MirrorSourceChannelId/PlayoutOffset could persist on a Generated channel); fixed in commit
10d891ba63and negative-controlled (new test fails pre-fix, passes post-fix). Fix commit re-reviewed against the prescribed diff. 10/10 tests green.Live-E2E PASSED (scripts/e2e-local.sh, real /api endpoints, machine-key auth). Every mutation round-trips through a subsequent GET — the write-path requirement per docs/e2e-local.md is satisfied. Proceeding to merge.