# Implementer — F-052 (iteración 2) ## Cambios (completos) ### Código - `apps/admin/src/app/api/upload/route.ts`: tras `writeFile`, copia a `frontend/public/uploads/` y `storefront/public/uploads/` con `Promise.allSettled`. La copia no bloquea el upload principal. - `project/scripts/monolith.sh`: nueva función `sync_uploads()` que se invoca al final de `build_prod()` y antes de `spawn_service` en `start_all()` para cubrir el caso "arranque en frío sin uploads aún". - **`frontend/src/app/uploads/[filename]/route.ts`** y **`storefront/src/app/uploads/[filename]/route.ts`**: handlers dinámicos (idénticos al del admin) que leen cada petición de `public/uploads/` directamente del disco. Imprescindible: Next.js sirve los estáticos de `public/` cacheados al build time, por lo que cualquier archivo subido después devolvería 404 sin esta ruta. ### Assets - `frontend/public/uploads/` y `storefront/public/uploads/` creados. - Archivos sincronizados manualmente para evitar esperar al próximo restart. ### Servicios - `next build` re-ejecutado para admin, frontend y storefront. - Servicios reiniciados. ## Verificación end-to-end ### Imágenes existentes (en build) ``` GET 3004 /uploads/fa7a31db-...jpg → 200 image/jpeg 129711 GET 3003 /uploads/fa7a31db-...jpg → 200 image/jpeg 129711 GET 3005 /uploads/fa7a31db-...jpg → 200 image/jpeg 129711 ``` ### Imagen subida en caliente (sin rebuild) ``` POST 3004 /api/upload (admin) → 201 {url: /uploads/a7e3aa30-...jpg} GET 3004 /uploads/a7e3aa30-...jpg → 200 image/jpeg GET 3003 /uploads/a7e3aa30-...jpg → 200 image/jpeg GET 3005 /uploads/a7e3aa30-...jpg → 200 image/jpeg ``` ### Favicons siguen 200 ``` GET 3004 /favicon.ico → 200 GET 3005 /favicon.ico → 200 ``` ## Por qué fue necesaria la 2ª iteración El `mirrorToPeers` del admin copia el archivo al disco de frontend/storefront, pero los servicios en producción cachean el listado de `public/` al build. Sin una ruta dinámica `/uploads/[filename]/`, los archivos nuevos solo se sirven si existían al hacer `next build`. La ruta dinámica los lee frescos del disco en cada request, igual que hace el admin desde F-050.