Documents the MediaAsset model, future GET/POST/DELETE/PATCH /media contract, and the MediaRepository interface (Mock IndexedDB-backed now, Http later via DI swap) that Sprint 4 will implement against. Media assets never enter the Bootstrap model, consistent with ADR-0001.
2.7 KiB
2.7 KiB
id, title, status, date, tags
| id | title | status | date | tags | ||||
|---|---|---|---|---|---|---|---|---|
| ADR-0002 | Media Manager backend contract and mock storage adapter | active | 2026-07-15 |
|
Context
Sprint 4 (Media Manager) needs a media library: upload, browse, delete, and pick
images/files for use across Product Editor, Static Pages (CMS), and Branding.
No media backend exists yet — /media currently routes to a "coming soon"
placeholder (BackofficeComingSoonPageComponent), and docs/BACKEND.md does
not document any upload/storage endpoint. This mirrors the already-documented
draft-publish-flow gap in the Project Editor (see PE-20260713T010000Z-0003):
build the real contract, then implement a client-side mock adapter behind the
same interface so the UI never needs to change when the backend ships.
Decision
- Domain model
MediaAsset:{ id, url, thumbnailUrl?, filename, mimeType, size, width?, height?, altText?: Record<locale, string>, tags?: string[], createdAt }.altTextfollows the platform'stranslations.{lang}rule (ADR-0001) — never a flat string. - Repository contract (future backend, to be implemented server-side):
GET /media?page=&pageSize=&search=→ paginatedMediaAsset[]POST /media/upload(multipart) →MediaAssetDELETE /media/:id→ 204PATCH /media/:id(altText/tags only) →MediaAsset
- Frontend abstraction: a
MediaRepositoryinterface (Repository pattern, perdocs/context/features/*conventions) with two implementations selected via DI token:MockMediaRepository— stores assets in IndexedDB (not localStorage: binary blobs need it) as an interim store until the backend exists. Data URLs are generated for rendering; the shape returned matchesMediaAssetexactly.HttpMediaRepository— thin wrapper over the endpoints above, added when the backend ships. Swapping providers is the only change required.
- Media never enters the Bootstrap model. Like products/orders/users, media assets are runtime admin data, not tenant configuration — consistent with ADR-0001's rule that Bootstrap contains only what's needed before the app starts.
- Media Picker is a standalone, reusable dialog (built on the existing
app-dialogDesign System primitive) so Product Editor and CMS editors consume the same selection UI instead of each building their own.
Consequences
- Any feature needing to reference an image (product gallery, static page
hero, branding logo) does so via
MediaAsset.url/id, obtained through the shared Media Picker — never a raw file input duplicated per feature. - When the backend ships, only
MediaRepository's DI provider changes; no component or facade code should need to change.