Drop the redundant force-ssl scope, and reject the playlistItems "fix"
force-ssl is gone from the requested scope. Its grant ("see, edit, and
permanently delete your videos, ratings, comments and captions") is a strict
subset of auth/youtube's ("Manage your YouTube account"), and Google's own
liveBroadcasts.insert reference lists auth/youtube as an accepted ALTERNATIVE
to force-ssl, so every endpoint this app calls — channels, liveBroadcasts,
liveStreams, liveChat, playlistItems — is covered by the one we keep. Two
consent lines became one, and one fewer scope to justify. Removing a scope
cannot narrow capability when the scope being kept is the broader of the two,
and there is no forced re-consent: a refresh token keeps the scopes it was
originally granted, so existing sessions are untouched.
The playlistItems change is NOT being made, and the map entry recommending it
was wrong. It came out of the verification hunt on the theory that public data
should not ride on user credentials. Walking the code kills it: ChannelStats-
Service is built with one HttpClient, and channels?mine=true on the same
service genuinely needs the session. Splitting it means a second unauthenticated
client PLUS a Google API key, since every YouTube Data API request needs a
credential and the call 403s without one. So the fix would ship a new
extractable, quota-abusable credential inside the binary to replace a token the
app already holds, buying zero verification-surface reduction (the data is
public, no scope involved) and zero correctness. Strictly worse. Recorded as a
do-not-do so it is not "helpfully" reintroduced later.
Test: ExactlyOneScopeIsRequested_AndItIsTheBroadOne asserts on the const's
parsed VALUE rather than scanning the file — a file-wide DoesNotContain
fails on the doc comment that names force-ssl to explain its removal, which is
the same trap I hit and documented earlier today in the locator test. Suite
380/380, 0 warnings.
This commit is contained in:
+21
-12
@@ -59,18 +59,27 @@ re-consent. Parking verification does not fix that; it accepts it for the solo-u
|
||||
real work the moment a *second real user* needs to sign in, or at Store submission (TASK 48). The
|
||||
sensitive-vs-restricted classification was never read and is moot until then.
|
||||
|
||||
**These two survive the tabling** — neither needs verification to land, and both shrink the surface
|
||||
if it ever comes back:
|
||||
- `Services/YouTubeAuthService.cs:18` requests `auth/youtube` **+ `auth/youtube.force-ssl`**.
|
||||
`force-ssl` is **redundant** — Google's liveChat docs list `auth/youtube` as an acceptable
|
||||
alternative, and it is the broader of the two ("Manage your YouTube account" ⊃ "see/edit/delete
|
||||
your videos, ratings, comments, captions"). Drop it: one fewer scope to justify, one fewer consent line.
|
||||
- `Services/ChannelStatsService.cs:104,107` — `playlistItems.list` on the creator's own uploads
|
||||
playlist (`UU…`) is **public data needing no OAuth scope at all** (API key suffices); it currently
|
||||
rides on the user's session token. Does not change the requested scope (`auth/youtube` is forced by
|
||||
`liveBroadcasts.*`/`liveStreams.list` regardless) but that fetch should not need user credentials.
|
||||
The `channels?mine=true` call on the same service **does** need the session — do not "fix" it.
|
||||
- `auth/youtube` is **unavoidable**: no narrower scope covers live broadcast create/transition.
|
||||
**One of these two survives the tabling, and the other was a bad idea (corrected 2026-09-28):**
|
||||
- ✅ **DONE — `Services/YouTubeAuthService.cs` no longer requests `auth/youtube.force-ssl`.**
|
||||
It is **redundant**: its grant is *"see, edit, and permanently delete your YouTube videos,
|
||||
ratings, comments and captions"*, a strict subset of `auth/youtube`'s *"Manage your YouTube
|
||||
account"*, which is the scope we keep. Google's own `liveBroadcasts.insert` reference lists
|
||||
`auth/youtube` as an accepted **alternative** to `force-ssl`, so every endpoint this app calls
|
||||
(`channels`, `liveBroadcasts`, `liveStreams`, `liveChat`, `playlistItems`) is covered.
|
||||
Two consent lines became one. **No forced re-consent** — a refresh token keeps the scopes it
|
||||
was originally granted, so existing sessions are untouched; the reduced set applies at the
|
||||
next fresh sign-in. Removing a scope cannot narrow capability when the one kept is broader.
|
||||
- ❌ **NOT doing this, and the earlier note recommending it was wrong: moving
|
||||
`playlistItems.list` off the user's session token.** It was written during the verification
|
||||
hunt on the theory that "public data should not ride on user credentials". Walking the code
|
||||
kills it: `ChannelStatsService` is built as `new ChannelStatsService(_youtubeAuth)` with **one**
|
||||
`HttpClient`, and `channels?mine=true` (same service) **genuinely needs the session**. To split
|
||||
it you would need a second unauthenticated client **plus a Google API key**, because every
|
||||
YouTube Data API request needs a credential — without a key the call 403s. So the "fix" means
|
||||
**shipping a new extractable credential in the binary, subject to quota abuse, to replace a
|
||||
token the app already holds.** It buys **zero** verification-surface reduction (the data is
|
||||
public; no scope is involved) and zero correctness. Strictly worse. ⛔ Do not "fix" this later
|
||||
without a new ruling.
|
||||
|
||||
## ✅ DECIDED 2026-09-27 — pricing: `$10/mo` subscription, or `$400` lifetime, **no annual**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user