# Task: Fix Makelore Prompt Museum media rendering ## Identity - Task ID: 20260818-prompt-museum-client-4f7a - Mode: Feature - Branch: codex/20260818-prompt-museum-client-4f7a-prompt-museum-client - Worktree: D:\mk-4f7a - Base commit: 11b19832a35477d2136c6ea953dd9c408fd84816 - Owner: developer - Status: Ready for integration ## Scope - Permit the server-controlled Prompt Museum media URL shape in strict list/detail DTO projection. - Add an authenticated, fixed-path Main proxy for bounded Prompt Museum raster media. - Resolve relative media through Main in the Renderer while keeping absolute HTTPS images direct and image failures card-local. - Preserve real attribution sources whose optional URL is missing or null without creating an undefined Renderer link. - Cover list, detail, media, invalid-path/response, API conversion, and page success/failure behavior. ## Intent And Constraints - The only relative media URL allowed is `/api/image-prompt-museum/{entry}/media/{thumbnail|number}`, with entry IDs matching `[A-Za-z0-9][A-Za-z0-9._:-]{0,127}`. - Works Bearer credentials remain Main-owned; the existing Host API IPC JSON protocol is unchanged. - Media is limited to 10 MiB and trusted raster MIME types; upstream payloads and errors are not exposed directly. - Absolute credential-free HTTPS images remain directly renderable. A failed image displays a placeholder without failing its card or detail view. - Attribution source URLs are optional: undefined is omitted, null is retained, and present strings remain strict credential-free HTTPS. ## Outcome - Main now accepts controlled relative media URLs in projected cards/details and proxies only the mirrored fixed local media route with Works Bearer refresh behavior. - Main rejects non-raster or oversized responses and returns only `dataBase64` plus normalized trusted `mimeType` for successful media. - Renderer converts relative media responses into data URLs, validates the JSON again, and preserves direct HTTPS rendering. - Museum images load independently; pending and failed images use an accessible placeholder and do not affect card interaction. - Source attribution without a URL renders as plain text; valid HTTPS sources remain links. ## Verification - `pnpm vitest run tests/unit/image-prompt-museum-route.test.ts tests/unit/image-prompt-museum-api.test.ts tests/unit/image-prompt-museum-page.test.tsx`: PASS, 3 files / 27 tests, including missing/null source URL projection and no-link rendering. - `pnpm typecheck`: PASS. - Scoped ESLint across the eight owned source/test files: PASS. - `pnpm build:vite`: PASS; existing dynamic-import and chunk-size warnings only. - Targeted Electron E2E `tests/e2e/image-workspace-conversations.spec.ts --grep "keeps Prompt Museum cards usable when relative media fails"`: PASS, 1/1. The local fixture returned a controlled relative thumbnail and invalid media MIME; the failed-image placeholder remained visible, the card stayed enabled, and its detail sheet opened. - `git diff --check`: PASS; Git emitted only existing LF-to-CRLF checkout warnings. ## Follow-ups - Production validation still requires a real Works account and deployed media endpoint; local automation does not prove production content availability. ## Promotion Candidates - Target: `.project-docs/30-worklog/current-state.md` and Prompt Museum evidence/commitment entries during integration. - Proposal: record that protected relative Prompt Museum media is fetched through a Main-owned bounded authenticated proxy while HTTPS CDN media remains direct. - Evidence: focused 27 tests, typecheck, scoped lint, and Vite/Main/Preload build passed. - Future impact: future Prompt Museum media URL or MIME additions must update the server validator, Main proxy, and Renderer validator together. - Semantic conflicts: none identified; this implements the existing Main-owned Museum boundary. - Human confirmation required: no for integration of this behavior; production deployment/smoke remains an external release decision.