diag: keep channel/playlist ids in the dogfood scrub profile
All checks were successful
build-apk / build-and-publish (push) Successful in 8m20s

The dogfood profile already skips the channel/playlist/video-id replacements,
but the always-on LONG_TOKEN pass (20+ chars w/ a digit) then redacted the
24-char channel ids and long playlist ids to <token> — so channel_info logs
showed "[channel <token>]" instead of the real id. LONG_TOKEN on the dogfood
profile now keeps a token that is exactly a channel (UC…) or playlist
(PL/UU/LL/RD/OLAK5uy_…) id, while every other high-entropy run (visitorData,
hashes) still redacts. Full profile unchanged. +2 unit tests.
This commit is contained in:
Cobb 2026-08-06 09:48:32 -07:00
parent 4d3ddf502f
commit 417456ad49
2 changed files with 40 additions and 3 deletions

View file

@ -211,9 +211,24 @@ object LogDump {
}
}
// Long high-entropy runs (hashes, visitor data, unlabeled
// tokens): 20+ [A-Za-z0-9_-] chars containing a digit. Scrubbed
// in BOTH profiles — visitorData & friends are creds, not signal.
s = LONG_TOKEN_RE.replace(s, "<token>")
// tokens): 20+ [A-Za-z0-9_-] chars containing a digit. Scrubbed in
// BOTH profiles — visitorData & friends are creds, not signal. On the
// dogfood profile a token that is exactly a channel/playlist id
// (UC…, PL…/UU…/LL…/RD…/OLAK5uy_…) is KEPT — those ride past the
// skipped id passes above but LONG_TOKEN would otherwise redact them,
// and they're the same triage signal as the video id we keep. Every
// other high-entropy run (visitorData, hashes) still redacts.
s = if (keepIdentifiers) {
LONG_TOKEN_RE.replace(s) { m ->
if (CHANNEL_ID_RE.matches(m.value) || PLAYLIST_ID_RE.matches(m.value)) {
m.value
} else {
"<token>"
}
}
} else {
LONG_TOKEN_RE.replace(s, "<token>")
}
// IP addresses (v4 + v6 — v6 patterns are shaped so threadtime
// HH:MM:SS timestamps can never match).
s = IPV4_RE.replace(s, "<ip>")

View file

@ -72,6 +72,28 @@ class LogDumpScrubTest {
assertFalse(LogDump.scrubLine(line).contains("dQw4w9WgXcQ"))
}
@Test
fun dogfoodKeepsChannelAndPlaylistIdFullScrubs() {
// These are ≥20 chars so LONG_TOKEN would otherwise redact them even
// on the dogfood profile; the channel/playlist exemption keeps them.
val channelId = "UCuAXFkgsw1L7xaCfnd5JJOw" // UC + 22, has digits
val playlistId = "PLbpi6ZahtOH6Blw3RGYpWkSByi_T7Rygb"
assertEquals(channelId, LogDump.scrubLineDogfood(channelId))
assertEquals(playlistId, LogDump.scrubLineDogfood(playlistId))
// Full profile redacts them to their labelled placeholders.
assertEquals("<channelId>", LogDump.scrubLine(channelId))
assertEquals("<playlistId>", LogDump.scrubLine(playlistId))
}
@Test
fun dogfoodStillScrubsGenericHighEntropyToken() {
// visitorData-shaped: ≥20 chars with a digit, NOT a channel/playlist
// prefix → still `<token>` on the dogfood profile (it's a cred).
val visitorData = "CgtVQzEyMzQ1Njc4OTBhYg"
assertEquals("<token>", LogDump.scrubLineDogfood(visitorData))
assertEquals("<token>", LogDump.scrubLine(visitorData))
}
// ---- B2: dogfood profile STILL scrubs real credentials / PII ---------
@Test