Files
marketplaces/docs/context/adrs/ADR-0002-media-manager-contract.md
sdarbinyan b75e753d98 docs: add ADR-0002 for Media Manager backend contract and mock adapter
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.
2026-07-15 04:51:10 +04:00

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
architecture
media
backend-gap
repository-pattern

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 }. altText follows the platform's translations.{lang} rule (ADR-0001) — never a flat string.
  • Repository contract (future backend, to be implemented server-side):
    • GET /media?page=&pageSize=&search= → paginated MediaAsset[]
    • POST /media/upload (multipart) → MediaAsset
    • DELETE /media/:id → 204
    • PATCH /media/:id (altText/tags only) → MediaAsset
  • Frontend abstraction: a MediaRepository interface (Repository pattern, per docs/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 matches MediaAsset exactly.
    • 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-dialog Design 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.