From e3c516d6be6431be482d9fbd6d2faf3250200626 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 13 Sep 2026 11:52:06 -0400 Subject: [PATCH] fix: a retired platform leaves the chip maps, and a fixture stops creating pixiv sources (406) e3fd8c6 failed two lanes, both on things pixiv's retirement correctly started refusing. Unit - test_fe_be_contract pins platformColor.js's ICONS keys to known_platform_keys(). I had kept pixiv's icon, colour and label "so existing pixiv posts don't look broken". That was wrong, and the file's own header already said why: unknown platforms fall back to a grey chip with the raw key, and that fallback is deliberately what a retired platform hits - it is how a pre-3069 deviantart row already renders. So pixiv leaves all three maps, and its posts show as a grey "pixiv" chip rather than a broken one. The header now says outright that a retired platform is removed, never kept, since the milestone plan itself got this backwards. Integration - four reassign tests built their fixture source through SourceService.create with platform="pixiv", which the validator now rejects. Reassign never reads the platform and never moves files, so any registered platform serves; the fixture uses hentaifoundry. 1294 other integration tests passed on e3fd8c6, so nothing else used pixiv through a validating path. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SHQB1YukL3VyvMK8rcbmV9 --- frontend/src/utils/platformColor.js | 13 +++++++------ tests/test_source_service.py | 9 ++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/frontend/src/utils/platformColor.js b/frontend/src/utils/platformColor.js index ef759b6..8d57cb1 100644 --- a/frontend/src/utils/platformColor.js +++ b/frontend/src/utils/platformColor.js @@ -1,9 +1,13 @@ // Single source of truth for platform → color + icon mapping. Used by -// PlatformChip and any other GS-style platform-tagged surface. The five +// PlatformChip and any other GS-style platform-tagged surface. The four // platforms FC supports map 1:1 to the GS palette; unknown platforms fall // back to grey + mdi-web — which is deliberately what a retired platform -// hits: a pre-#3069 deviantart source row still renders, as its raw key on -// a grey chip. Operator-confirmed scope 2026-05-27. The ICONS key set is +// hits: a pre-#3069 deviantart source row, or a post from pixiv (retired at +// milestone #406), still renders, as its raw key on a grey chip. So a +// retired platform is REMOVED from these maps, never kept "so old rows +// look right" — the fallback is what makes old rows look right, and keeping +// the entry would break the contract pin below. Operator-confirmed scope +// 2026-05-27. The ICONS key set is // pinned against backend known_platform_keys() by // tests/test_fe_be_contract.py. @@ -12,7 +16,6 @@ const ICONS = { subscribestar: 'mdi-star', hentaifoundry: 'mdi-palette', discord: 'mdi-discord', - pixiv: 'mdi-alpha-p-box', } const COLORS = { @@ -20,7 +23,6 @@ const COLORS = { subscribestar: 'amber', hentaifoundry: 'purple', discord: 'indigo', - pixiv: 'blue', } const LABELS = { @@ -28,7 +30,6 @@ const LABELS = { subscribestar: 'SubscribeStar', hentaifoundry: 'HentaiFoundry', discord: 'Discord', - pixiv: 'Pixiv', } export function platformIcon(platform) { diff --git a/tests/test_source_service.py b/tests/test_source_service.py index 5fb32e9..9f8428b 100644 --- a/tests/test_source_service.py +++ b/tests/test_source_service.py @@ -388,14 +388,17 @@ async def test_update_while_enabled_keeps_failure_state(db): async def _source_with_content(db, svc, artist): """A source under `artist` with one post + one image it contributed.""" from backend.app.models import ImageProvenance, ImageRecord, Post + # Any registered platform will do — reassign never reads the platform, and + # never moves files (the storage path is immutable). This used pixiv until + # pixiv was retired (milestone #406) and `create` began refusing it. rec = await svc.create( - artist_id=artist.id, platform="pixiv", - url=f"https://www.pixiv.net/users/{artist.id}", + artist_id=artist.id, platform="hentaifoundry", + url=f"https://www.hentai-foundry.com/user/{artist.slug}/profile", ) post = Post(source_id=rec.id, artist_id=artist.id, external_post_id="p1") db.add(post) img = ImageRecord( - path=f"/images/{artist.slug}/pixiv/pixiv/1_a_00.jpg", + path=f"/images/{artist.slug}/hentaifoundry/hentaifoundry/1_a_00.jpg", sha256=str(artist.id).rjust(64, "0"), size_bytes=1, mime="image/jpeg", width=1, height=1, origin="imported_filesystem", integrity_status="unknown", artist_id=artist.id,