fix: render prompt museum media

This commit is contained in:
2026-08-18 12:32:34 +08:00
parent 11b19832a3
commit f8d82e6c19
9 changed files with 609 additions and 37 deletions

View File

@@ -0,0 +1,57 @@
# 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.