Actualizado el 18-oct-2026. Primera versión de la arquitectura de esta épica.
Qué responde. Cómo funciona por dentro FT-ACT-02: qué piezas participan, en qué orden hablan, qué APIs hay que construir con su request y su response, y qué le entrega a la épica siguiente.
Para quién. Los equipos que van a construir la épica, QA y arquitectura.
Estado. [Propuesta] del TL del Nuevo PIM, 18-oct-2026, construida sobre ADR-12. La spec de cada épica dice el qué; estas páginas, el cómo.
Fuente. docs/arquitectura/por-epica/epicas/FT-ACT-02.json, generada con generar.py; la ficha de la épica es trazabilidad/features/FT-ACT-02-registro-congelado-publicacion-urls.md.
En 30 segundos
Cuando un producto ya tiene SKU y la foto la pone el proveedor, éste sube sus imágenes en el portal. Esta épica guarda cada archivo una sola vez en Activos digitales, lo valida, lo nombra con el SKU, hace la copia congelada que se publica y le pasa a Producto la URL congelada de cada variante. Así la tienda sólo recibe imágenes estables y una variante sin principal no frena a su familia.
- Módulo dueño: MS-11 Activos digitales. También participan: MS-02 Producto, MS-14 Avisos y ayuda.
- Etapa 6 · Imágenes. Recibe «PE-6 · SKU asignado» y entrega «PE-7 · Imágenes listas».
- APIs: construye 11 y usa 9 que construyen otras épicas.
- Eventos: publica 9 y consume 5.
1. Dónde encaja
Recibe
| De | Qué |
|---|---|
| PE-6 · SKU asignado | La familia En enriquecimiento con SKU en cada variante y, si la foto la pone el proveedor y todavía no cumple el mínimo de aprobación, la tarea Carga de imagen abierta. |
| FT-ACT-01 · Tipos de activo digital y reglas de imágenes por… | Los tipos de activo con su ficha, nombre, sufijo y carpeta, y la revisión de cumplimiento por plantilla, negocio y etapa. |
Entrega
| A | Qué |
|---|---|
| PE-7 · Imágenes listas | La tarea Carga de imagen cerrada: las imágenes en MS-11 con URL congelada, ligadas a su variante y posición, y su copia en el producto. |
| FT-INT-01 · Publicación a e-commerce | La copia de URL congeladas por variante, con «procede» o «no procede», que lee la foto de publicación (API-02-054): sin principal congelada no se publica. |
| FT-ACT-03 · Imágenes del seller por URL con validación y corrección… | El registro, la validación, el congelado al asignar el SKU y los recibos que usa la imagen del seller por URL. |
| FT-ACT-06 · Recepción del trabajo de Foro y control de edición… | La consulta de las imágenes que ya tiene cada variante y el congelado al validar, que usa el cierre de la edición del estudio. |
| FT-ACT-04 · Variantes a partir de imágenes y herencia de imágenes por… | El registro de activos, el congelado y la copia de URL congeladas en el producto, sobre los que se resuelve la herencia por color. |
| FT-MIG-03 · Migración inicial de productos desde P360 | La carga de activos migrados (API-11-016): cada URL de trabajo y congelada de P360 queda una vez en MS-11, sin copiar archivos ni cambiar URL. |
Tareas que abre o cierra: Carga de imagen.
2. Diagrama de contexto
Quién participa y cómo se conecta. Las pantallas llegan por el BFF del portal, que valida el token y compone; cada módulo vuelve a validar el token y decide sus permisos con los roles de MS-13.
🟩 Verde: nuevo, se construye · 🟦 Azul: ya existe y se queda, se reutiliza su código · 🟧 Naranja: temporal o se retira (se apaga en R3) · ⬜ Gris: sistema externo · ★ módulo dueño
3. Diagrama de flujo
El camino principal, paso por paso. Cuando una pantalla llama a un módulo se ven dos flechas: la pantalla al BFF y el BFF al módulo. Los eventos salen del outbox del módulo después de guardar; quien los consume ignora los repetidos.
Los pasos en texto
| Paso | De | A | Qué hace | API o evento |
|---|---|---|---|---|
| 1 | Proveedor | Entrada Única · Vendor Center | Abre su tarea Carga de imagen y elige sus fotos | — |
| 2 | Entrada Única · Vendor Center | MS-11 Activos digitales (por el BFF) | Pide permiso para subir cada archivo | API-11-004 |
| 3 | MS-11 Activos digitales | MS-02 Producto | Revisa que el proveedor pueda cambiar las imágenes | API-02-027 |
| 4 | Entrada Única · Vendor Center | Archivos e imágenes (almacén y CDN) | Sube el archivo directo con la URL firmada | — |
| 5 | Entrada Única · Vendor Center | MS-11 Activos digitales (por el BFF) | Avisa que terminó la carga | API-11-005 |
| 6 | MS-11 Activos digitales | Archivos e imágenes (almacén y CDN) | Valida la ficha, nombra con el SKU y congela | — |
| 7 | MS-11 Activos digitales | Eventos | Avisa el activo validado y congelado | catalog.asset.changed/ASSET_FROZEN |
| 8 | Eventos | MS-02 Producto | Entrega el activo congelado | catalog.asset.changed/ASSET_FROZEN |
| 9 | MS-02 Producto | MS-11 Activos digitales | Lee la galería congelada de cada variante | API-11-007 |
| 10 | MS-02 Producto | Base pim | Copia las URL congeladas y marca procede por variante | — |
| 11 | Entrada Única · Vendor Center | MS-02 Producto (por el BFF) | Pide el plan para enviar sus imágenes | API-02-028 |
| 12 | MS-02 Producto | MS-11 Activos digitales | Revisa el mínimo de su plantilla y negocio | API-11-014 |
| 13 | Entrada Única · Vendor Center | MS-02 Producto (por el BFF) | Confirma el envío de las imágenes | API-02-057 |
| 14 | MS-02 Producto | Eventos | Cierra Carga de imagen y sigue a calidad | catalog.product.changed/TASK_CHANGED |
3.1 Congelado al asignar el SKU (la tubería de la imagen)
3.2 Rechazar o cambiar imágenes de un producto ya publicado
3.3 Carga masiva de imágenes
4. Si algo sale mal
- Un archivo no cumple la ficha de su tipo. MS-11 lo rechaza con el motivo de hoy («Error en proporción», «DPI insuficiente», «Imagen corrupta o formato no correcto») y publica ASSET_REJECTED. El proveedor lo ve en el recibo y en su campana (MS-14); la tarea sigue abierta.
- El proveedor envía sin el mínimo de su plantilla. El plan de MS-02 responde bloqueado con lo que falta por variante, que sale de API-11-014; la tarea Carga de imagen sigue abierta y nada se escribe.
- El producto entra al estudio mientras el proveedor sube fotos. MS-11 responde 423 LOCKED porque el motor dice que sólo el estudio cambia las imágenes; el proveedor ve «En proceso Liverpool» y no queda nada a medias.
- MS-02 no está disponible cuando llega un activo congelado. El evento se vuelve a entregar. MS-02 siempre relee la galería completa (API-11-007), así que no importan el orden ni los repetidos.
- Una variante sigue sin principal congelada. Esa variante queda «no procede» y no viaja a la tienda; el resto de la familia se publica (FT-INT-01) y el proveedor ve «Sin imagen principal» en el motivo del SKU (FT-RAC-05).
5. APIs
Las que construye esta épica (11)
POST /api/v2/assets/uploads · Pedir permiso para subir un archivo
| Campo | Valor |
|---|---|
| API | API-11-004 · MS-11 Activos digitales |
| Para qué | Antes de subir una foto, video o documento, quien carga dice qué es, de qué producto, variante o color, y cuánto pesa. MS-11 revisa la ficha del tipo, el máximo de la plantilla y que el producto se pueda editar (pregunta al motor de MS-02), y devuelve el identificador del activo y una URL firmada de 15 minutos para subir el archivo directo al almacén. El archivo nunca pasa por el BFF ni por MS-02. |
| En esta épica | Permiso de carga: revisa la ficha, el máximo y el bloqueo, y da la URL firmada |
| Quién la llama | BFF del portal, Agente del estudio, Gateway de terceros /partner/v1 |
| Permiso | El proveedor o seller dueño del producto; el estudio mientras la tarea Foro está abierta; Repoblamiento en productos publicados; el agente del estudio con su credencial de equipo |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| Escribe en | assets |
| También la usan | FT-ACT-01, FT-ACT-04, FT-ACT-05, FT-ACT-06, FT-PLT-06, FT-PLT-07, FT-PRD-07, FT-REF-04, FT-USR-01 |
Request
{
"productId": "PRD-0004812",
"scope": "VARIANT",
"variantId": "VAR-0004812-01",
"assetType": "DETALLE",
"position": 3,
"fileName": "1000004812_2p.jpg",
"contentType": "image/jpeg",
"sizeBytes": 734003,
"origin": "AGENTE",
"purpose": "PRODUCT",
"replacesAssetId": null
}
Response · 201
{
"success": true,
"data": {
"assetId": "ast-7c21e6",
"status": "UPLOAD_PENDING",
"uploadUrl": "almacen.ejemplo.mx/carga/ast-7c21e6?firma=<firma>&vence=900",
"uploadMethod": "PUT",
"uploadHeaders": {
"Content-Type": "image/jpeg"
},
"expiresAt": "2026-10-18T16:15:00Z",
"expected": {
"widthPx": 940,
"heightPx": 1215,
"dpi": 72,
"formats": [
"jpg"
],
"maxBytes": 1048576
},
"completeUrl": "/api/v2/assets/ast-7c21e6/complete"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 422 | VALIDATION_ERROR | El archivo declarado pesa más que el máximo de su tipo (por ejemplo, una principal de 1.5 MB contra 1 MB) o su formato no está permitido |
| 422 | VALIDATION_ERROR | La posición no existe para el tipo (por ejemplo, la 21: hay 20 posiciones, la principal y 19 detalles) |
| 422 | BUSINESS_ERROR | Ya se alcanzó el máximo de ese tipo en la plantilla (la sexta foto de detalle con «Mínimo 2 - Máximo 5»), o es un boceto y el producto no es un placeholder |
| 423 | LOCKED | El producto está en el estudio (tarea Foro abierta) y quien llama no es del estudio |
| 403 | AUTHORIZATION_ERROR | Quien llama no es dueño del producto ni tiene el permiso de imágenes en su tarea |
| 404 | NOT_FOUND | El producto, la variante o el color no existen |
POST /api/v2/assets/{assetId}/complete · Avisar que terminó la carga
| Campo | Valor |
|---|---|
| API | API-11-005 · MS-11 Activos digitales |
| Para qué | Quien subió el archivo avisa que ya está en el almacén. MS-11 lo valida contra la ficha técnica (medidas, DPI, peso, formato), lee el sufijo del nombre si viene (3P es el tercer detalle), le quita los metadatos EXIF, lo deja como copia de trabajo y, si el producto ya tiene SKU, lo renombra y lo congela. Responde con un recibo y avisa con eventos. |
| En esta épica | Fin de carga: valida, nombra y, con SKU, congela |
| Quién la llama | BFF del portal, Agente del estudio, Gateway de terceros /partner/v1 |
| Permiso | Quien pidió subir el archivo (el mismo token o la misma credencial de equipo) |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| Parámetros | assetId = ast-7c21e6 |
| Escribe en | assets, asset_outbox |
| Publica | catalog.asset.changed/ASSET_UPLOADED, catalog.asset.changed/ASSET_VALIDATED, catalog.asset.changed/ASSET_REJECTED, catalog.asset.changed/ASSET_FROZEN |
| También la usan | FT-ACT-01, FT-ACT-04, FT-ACT-05, FT-FLU-07, FT-PRD-07, FT-PRD-08, FT-REF-04 |
Request
{
"sizeBytes": 734003,
"checksum": "sha256:9b1d2c0e7f"
}
Response · 202
{
"success": true,
"data": {
"requestId": "req-4a7e90",
"assetId": "ast-7c21e6",
"status": "ACCEPTED",
"receiptUrl": "/api/v2/asset-receipts/req-4a7e90"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 422 | VALIDATION_ERROR | El archivo no llegó al almacén o su tamaño o su huella no coinciden con lo declarado |
| 409 | IDEMPOTENCY_MISMATCH | Se repite la llave de idempotencia con otro archivo |
| 404 | NOT_FOUND | El activo no existe o su permiso de carga ya venció |
GET /api/v2/assets?productId=&variantId= · Galería de un producto
| Campo | Valor |
|---|---|
| API | API-11-007 · MS-11 Activos digitales |
| Para qué | Devuelve los activos de un producto o de una variante, por posición, con su validación, su URL de trabajo y su URL congelada. Con view=effective resuelve la galería de cada variante: lo propio, lo heredado de su color (y de qué color viene) y el video de la familia. Un producto sin imágenes devuelve listas vacías, no un error. |
| En esta épica | La galería de cada variante; vacía si no tiene imágenes, no un error |
| Quién la llama | BFF del portal, MS-02 Producto, MS-12 Estudio fotográfico |
| Permiso | Quien puede leer el producto (ENT-L); los módulos con su cuenta de servicio |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | productId = PRD-0004812, variantId = `, view = effective, include = work,frozen` |
| También la usan | FT-ACT-04, FT-ACT-05 |
Request
null
Response · 200
{
"success": true,
"data": {
"productId": "PRD-0004812",
"assetsVersion": 9,
"family": [
{
"assetId": "ast-7c21f0",
"assetType": "VIDEO",
"scope": "FAMILY",
"kind": "FILE",
"name": "1000004811.mp4",
"frozenUrl": "cdn.ejemplo.mx/v/1000004811.mp4",
"status": "FROZEN"
}
],
"variants": [
{
"variantId": "VAR-0004812-01",
"sku": "1000004812",
"colorCode": "AZUL",
"gallery": [
{
"position": 1,
"assetType": "PRINCIPAL",
"assetId": "ast-7c21e4",
"scope": "COLOR",
"inherited": false,
"name": "1000004812.jpg",
"workUrl": "cdn.ejemplo.mx/trabajo/ast-7c21e4.jpg",
"frozenUrl": "cdn.ejemplo.mx/i/1000004812.jpg",
"status": "FROZEN"
},
{
"position": 2,
"assetType": "DETALLE",
"assetId": "ast-7c21e5",
"scope": "COLOR",
"inherited": false,
"name": "1000004812_1p.jpg",
"workUrl": "cdn.ejemplo.mx/trabajo/ast-7c21e5.jpg",
"frozenUrl": "cdn.ejemplo.mx/i/1000004812_1p.jpg",
"status": "FROZEN"
}
]
},
{
"variantId": "VAR-0004812-02",
"sku": "1000004813",
"colorCode": "AZUL",
"gallery": [
{
"position": 1,
"assetType": "PRINCIPAL",
"assetId": "ast-7c21e4",
"inherited": true,
"inheritedFrom": {
"scope": "COLOR",
"colorCode": "AZUL"
},
"name": "1000004812.jpg",
"frozenUrl": "cdn.ejemplo.mx/i/1000004812.jpg",
"status": "FROZEN"
},
{
"position": 2,
"assetType": "DETALLE",
"assetId": "ast-7c21e5",
"inherited": true,
"inheritedFrom": {
"scope": "COLOR",
"colorCode": "AZUL"
},
"name": "1000004812_1p.jpg",
"frozenUrl": "cdn.ejemplo.mx/i/1000004812_1p.jpg",
"status": "FROZEN"
}
]
},
{
"variantId": "VAR-0004812-04",
"sku": "1000004815",
"colorCode": "ROJO",
"gallery": []
}
]
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | El producto no existe o no es visible para quien llama (un producto sin imágenes no es error) |
| 400 | VALIDATION_ERROR | Falta productId o view trae un valor que no existe |
GET /api/v2/assets/{assetId} · Detalle de un activo
| Campo | Valor |
|---|---|
| API | API-11-008 · MS-11 Activos digitales |
| Para qué | Detalle de un activo: a qué producto, variante o color pertenece, su tipo y posición, la original y la corregida o editada, su validación, su rechazo si lo tiene, sus URL y una URL firmada de 10 minutos para previsualizarlo, también si es un documento de respaldo que no se publica. |
| En esta épica | Previsualizar una imagen o un documento de respaldo con URL firmada corta |
| Quién la llama | BFF del portal |
| Permiso | Quien puede leer el producto (ENT-L); los documentos de respaldo, sólo los roles autorizados de su tipo |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | assetId = ast-7c21e6 |
| También la usan | FT-REF-04 |
Request
null
Response · 200
{
"success": true,
"data": {
"assetId": "ast-7c21e6",
"productId": "PRD-0004812",
"scope": "COLOR",
"colorCode": "AZUL",
"assetType": "DETALLE",
"position": 3,
"status": "FROZEN",
"version": 3,
"origin": "AGENTE",
"replacesAssetId": null,
"renditions": {
"original": {
"sizeBytes": 734003,
"widthPx": 940,
"heightPx": 1215,
"dpi": 72,
"format": "jpg"
},
"work": {
"url": "cdn.ejemplo.mx/trabajo/ast-7c21e6.jpg"
},
"frozen": {
"url": "cdn.ejemplo.mx/i/1000004812_2p.jpg",
"name": "1000004812_2p.jpg",
"frozenAt": "2026-10-18T16:03:10Z"
}
},
"validation": {
"result": "PASSED",
"checks": [
"MEDIDAS",
"DPI",
"PESO",
"FORMATO"
],
"corrections": [],
"exifRemoved": true
},
"rejection": null,
"previewUrl": "cdn.ejemplo.mx/vista/ast-7c21e6?firma=<firma>&vence=600"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | El activo no existe o no es visible para quien llama |
| 403 | AUTHORIZATION_ERROR | Es un documento de respaldo y quien llama no tiene el rol que lo puede ver |
POST /api/v2/assets/placements/plans · Acomodar los activos de un producto (vista previa)
| Campo | Valor |
|---|---|
| API | API-11-009 · MS-11 Activos digitales |
| Para qué | Prepara cambios en la galería de un producto: ordenar, mover de posición, heredar por color (total o sólo lo que falta), volver propia una imagen, quitar o marcar que no se publique. Dice cómo queda la galería de cada variante, qué nombres cambian y qué imágenes propias se pisarían; no pisa nada sin overwriteOwn. |
| En esta épica | Ordenar, quitar o marcar que no se publique una imagen |
| Quién la llama | BFF del portal |
| Permiso | El dueño del contenido del producto; el estudio mientras la tarea Foro está abierta; Repoblamiento en productos publicados |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key, If-Match |
| También la usan | FT-ACT-04, FT-ACT-06 |
Request
{
"productId": "PRD-0004812",
"assetsVersion": 9,
"overwriteOwn": false,
"actions": [
{
"op": "INHERIT_BY_COLOR",
"colorCode": "AZUL",
"fromVariantId": "VAR-0004812-01",
"mode": "PARTIAL",
"assetIds": [
"ast-7c21e4",
"ast-7c21e5",
"ast-7c21e6",
"ast-7c21e7"
]
},
{
"op": "REORDER",
"colorCode": "AZUL",
"order": [
"ast-7c21e4",
"ast-7c21e6",
"ast-7c21e5",
"ast-7c21e7"
]
}
]
}
Response · 200
{
"success": true,
"data": {
"planId": "pln-c90e12",
"expiresAt": "2026-10-18T16:40:00Z",
"preview": [
{
"variantId": "VAR-0004812-01",
"sku": "1000004812",
"before": 4,
"after": 4,
"inherited": 0
},
{
"variantId": "VAR-0004812-02",
"sku": "1000004813",
"before": 0,
"after": 4,
"inherited": 4
},
{
"variantId": "VAR-0004812-03",
"sku": "1000004814",
"before": 1,
"after": 4,
"inherited": 3,
"keptOwn": [
{
"assetId": "ast-7c2201",
"assetType": "PRINCIPAL"
}
]
}
],
"renames": [
{
"assetId": "ast-7c21e6",
"from": "1000004812_2p.jpg",
"to": "1000004812_1p.jpg"
}
],
"conflicts": [
{
"variantId": "VAR-0004812-03",
"assetType": "PRINCIPAL",
"message": "La talla XG tiene principal propia; se conserva (overwriteOwn=false)"
}
],
"applyUrl": "/api/v2/asset-plans/pln-c90e12/apply"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 409 | VERSION_CONFLICT | La galería cambió desde que se leyó |
| 423 | LOCKED | El producto está en el estudio y quien llama no es del estudio |
| 422 | BUSINESS_ERROR | El color no existe en el producto o una acción deja a una variante con dos principales |
POST /api/v2/assets/freeze · Volver a congelar los activos de un producto
| Campo | Valor |
|---|---|
| API | API-11-010 · MS-11 Activos digitales |
| Para qué | MS-11 congela solo al recibir SKU_ASSIGNED y al validar un activo de un producto que ya tiene SKU. Este comando sirve a MS-02 para pedir un congelado explícito: después de corregir un SKU o en un repoblamiento. Copia la galería válida al almacén de congelados con el nombre final; si se reemplaza una congelada, la URL nueva lleva su versión para que la tienda no muestre la vieja guardada en caché. |
| En esta épica | Volver a congelar después de corregir un SKU o en un repoblamiento |
| Quién la llama | MS-02 Producto |
| Permiso | Sólo MS-02 (cuenta de servicio) |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| Escribe en | assets, asset_outbox |
| Publica | catalog.asset.changed/ASSET_FROZEN |
Request
{
"productId": "PRD-0004812",
"variantIds": [
"VAR-0004812-01",
"VAR-0004812-02"
],
"reason": "SKU_CORRECTED"
}
Response · 202
{
"success": true,
"data": {
"requestId": "req-8c51aa",
"status": "ACCEPTED",
"receiptUrl": "/api/v2/asset-receipts/req-8c51aa"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 422 | BUSINESS_ERROR | Alguna variante todavía no tiene SKU |
| 404 | NOT_FOUND | El producto no tiene activos registrados |
POST /api/v2/asset-jobs · Carga masiva de imágenes
| Campo | Valor |
|---|---|
| API | API-11-011 · MS-11 Activos digitales |
| Para qué | Carga muchas imágenes de una vez: un archivo comprimido, una carpeta del almacén con su archivo que liga fotos y SKU, o una lista de URL. Cada archivo se asocia por su nombre (SKU y sufijo) o por su renglón, se valida igual que uno suelto y la herencia por color se puede prender o apagar. Responde 202 con el trabajo. |
| En esta épica | Carga masiva por archivo comprimido, carpeta o lista de URL |
| Quién la llama | BFF del portal, MS-02 Producto |
| Permiso | El proveedor o seller dueño de los productos; el estudio; MS-02 para las URL de una carga masiva de productos |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| Escribe en | asset_jobs |
| Publica | catalog.asset.changed/ASSET_UPLOADED, catalog.asset.changed/ASSET_VALIDATED, catalog.asset.changed/ASSET_REJECTED, catalog.asset.changed/ASSET_FROZEN |
| También la usan | FT-ACT-03 |
Request
{
"source": "BUCKET_FOLDER",
"fileRef": "cargas/estudio/2026-10-18/lote-07/",
"manifest": "lote-07.txt",
"business": "SUB",
"inheritance": "ON",
"origin": "FORO"
}
Response · 202
{
"success": true,
"data": {
"jobId": "job-a1b2c3",
"status": "QUEUED",
"links": {
"self": "/api/v2/asset-jobs/job-a1b2c3"
}
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 422 | VALIDATION_ERROR | El archivo comprimido o la carpeta no existen o el archivo que liga fotos y SKU no se puede leer |
| 429 | RATE_LIMITED | Quien llama ya tiene el máximo de cargas masivas en curso |
GET /api/v2/asset-jobs/{jobId} · Avance de una carga masiva de imágenes
| Campo | Valor |
|---|---|
| API | API-11-012 · MS-11 Activos digitales |
| Para qué | Dice cómo va una carga masiva y el resultado de cada archivo: congelado, rechazado con su motivo o pendiente, con una liga firmada al reporte en CSV. |
| En esta épica | Avance y resultado por archivo de una carga masiva |
| Quién la llama | BFF del portal, MS-02 Producto |
| Permiso | Quien lanzó la carga |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | jobId = job-a1b2c3 |
| También la usan | FT-ACT-03 |
Request
null
Response · 200
{
"success": true,
"data": {
"jobId": "job-a1b2c3",
"status": "DONE_WITH_ERRORS",
"startedAt": "2026-10-18T16:05:00Z",
"finishedAt": "2026-10-18T16:09:41Z",
"totals": {
"files": 3,
"frozen": 2,
"rejected": 1,
"pending": 0
},
"items": [
{
"file": "1000004812.jpg",
"result": "FROZEN",
"assetId": "ast-7c2310",
"sku": "1000004812"
},
{
"file": "1000004812_1p.jpg",
"result": "FROZEN",
"assetId": "ast-7c2311",
"sku": "1000004812"
},
{
"file": "1000009999_2p.jpg",
"result": "REJECTED",
"reason": {
"code": "SKU_NO_EXISTE",
"message": "El SKU del nombre no existe"
}
}
],
"reportUrl": "almacen.ejemplo.mx/reportes/job-a1b2c3.csv?firma=<firma>&vence=3600"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | La carga no existe o no es de quien llama |
GET /api/v2/asset-receipts/{requestId} · Recibo de una operación de Activos
| Campo | Valor |
|---|---|
| API | API-11-013 · MS-11 Activos digitales |
| Para qué | Dice si un comando de MS-11 ya terminó y qué pasó con cada activo: validado, corregido, congelado o rechazado con el motivo que ve el proveedor o seller. |
| En esta épica | Recibo de cada comando de Activos |
| Quién la llama | BFF del portal, Agente del estudio, Gateway de terceros /partner/v1, MS-02 Producto |
| Permiso | Quien hizo la operación |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | requestId = req-6b0d13 |
| También la usan | FT-ACT-03 |
Request
null
Response · 200
{
"success": true,
"data": {
"requestId": "req-6b0d13",
"status": "DONE",
"finishedAt": "2026-10-18T16:02:14Z",
"items": [
{
"assetId": "ast-9e40a2",
"result": "VALIDATED",
"corrections": [
"DPI_A_72",
"CENTRADO"
],
"frozen": false,
"reason": null
},
{
"assetId": "ast-9e40a3",
"result": "REJECTED",
"frozen": false,
"reason": {
"code": "URL_NO_PUBLICA",
"message": "No se pudo leer la imagen sin credenciales"
}
}
]
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | No existe el recibo o no es de quien llama |
POST /api/v2/assets/{assetId}/rejections · Rechazar una imagen concreta
| Campo | Valor |
|---|---|
| API | API-11-015 · MS-11 Activos digitales |
| Para qué | QA (o quien revisa) rechaza una sola imagen con un motivo del catálogo de su tipo y un comentario. La imagen sale de la galería que se publica, las demás siguen igual, y MS-02 registra el rechazo en el producto para que el proveedor lo vea. |
| En esta épica | Rechazar una imagen concreta con motivo y tipo |
| Quién la llama | BFF del portal |
| Permiso | QA, Gobierno de Datos o el estudio, según la tarea que tengan abierta |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key, If-Match |
| Parámetros | assetId = ast-7c21e5 |
| Escribe en | assets, asset_outbox |
| Publica | catalog.asset.changed/ASSET_REJECTED |
Request
{
"version": 3,
"reason": {
"code": "LOGO_VISIBLE",
"type": "ESTETICA",
"comment": "Se ve el logotipo de otra tienda en la etiqueta"
}
}
Response · 200
{
"success": true,
"data": {
"assetId": "ast-7c21e5",
"productId": "PRD-0004812",
"status": "REJECTED",
"version": 4,
"reason": {
"code": "LOGO_VISIBLE",
"type": "ESTETICA"
},
"rejectedAt": "2026-10-18T17:20:00Z"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 409 | VERSION_CONFLICT | La imagen cambió desde que se revisó |
| 422 | VALIDATION_ERROR | El motivo no existe para ese tipo de activo |
| 403 | AUTHORIZATION_ERROR | Quien llama no tiene una tarea de revisión abierta sobre el producto |
POST /internal/assets/bulk-load · Carga de activos migrados
| Campo | Valor |
|---|---|
| API | API-11-016 · MS-11 Activos digitales |
| Para qué | MS-03 registra los activos que ya existen en P360 con su URL de trabajo y su URL congelada, sin copiar archivos ni cambiar URL; queda un registro por archivo y lo que no se puede aparear queda como incidencia. No publica eventos. |
| En esta épica | La migración (FT-MIG-03) carga los activos de P360 con su URL de trabajo y su URL congelada, sin copiar archivos |
| Quién la llama | MS-03 Migración y convivencia |
| Permiso | Sólo MS-03 (cuenta de servicio) |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| Escribe en | assets |
| También la usan | FT-MIG-03 |
Request
{
"runId": "mig-run-0007",
"items": [
{
"legacyKey": "P360:1000004812:ProductImageDetail:0000.0002.RK",
"productId": "PRD-0004812",
"variantId": "VAR-0004812-01",
"assetType": "DETALLE",
"position": 2,
"workUrl": "cdn.ejemplo.mx/i/trabajo-1000004812_1p.jpg",
"frozenUrl": "cdn.ejemplo.mx/i/1000004812_1p.jpg",
"frozenName": "1000004812_1p.jpg"
}
]
}
Response · 200
{
"success": true,
"data": {
"runId": "mig-run-0007",
"loaded": 1,
"skipped": 0,
"issues": []
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 409 | IDEMPOTENCY_MISMATCH | El mismo lote llega otra vez con contenido distinto |
| 422 | VALIDATION_ERROR | Un renglón no trae tipo o producto; se reporta como incidencia y no detiene el lote |
Las que usa y construye otra épica (9)
Su request y su response están en la página de la épica que la construye.
| API | Método y ruta | Para qué, aquí | La construye |
|---|---|---|---|
| API-11-003 | POST /api/v2/asset-plans/{planId}/apply | Confirmar el plan de la galería | FT-ACT-01 · Tipos de activo digital y reglas de imágenes por… |
| API-11-014 | GET /api/v2/assets/compliance?productId=&stage= | Revisar el mínimo antes de cerrar la tarea | FT-ACT-01 · Tipos de activo digital y reglas de imágenes por… |
| API-02-027 | GET /api/v2/workflow/capabilities?productIds= | El motor dice si quien carga puede cambiar las imágenes del producto en su estado y tarea | FT-FLU-01 · Motor de estados configurable con dos carreteras y reglas… |
| API-02-028 | POST /api/v2/workflow/actions/plans | Plan de la acción SUBMIT_IMAGES que cierra Carga de imagen | FT-FLU-01 · Motor de estados configurable con dos carreteras y reglas… |
| API-02-057 | POST /api/v2/product-plans/{planId}/apply | Confirmar la acción | FT-FLU-01 · Motor de estados configurable con dos carreteras y reglas… |
| API-02-020 | GET /api/v2/products/{id}/media | La copia de imágenes que guarda Producto, para la ficha y la publicación | FT-PRD-01 · Modelo canónico de producto |
| API-14-006 | GET /api/v2/help/articles?q=&screen= | La pantalla de carga muestra la ayuda de cómo deben ser las fotos | FT-RAC-05 · Estatus del producto y motivos visibles para seller y… |
| API-14-007 | GET /api/v2/help/articles/{articleId} | Leer el artículo de ayuda de la ficha técnica | FT-RAC-05 · Estatus del producto y motivos visibles para seller y… |
| API-14-003 | GET /api/v2/notifications/preferences | Las preferencias del proveedor para los avisos de imagen (el de rechazo es obligatorio) | FT-RAC-05 · Estatus del producto y motivos visibles para seller y… |
6. Eventos
Publica
| Evento | Cuándo | Quién lo consume |
|---|---|---|
catalog.asset.changed/ASSET_UPLOADED | Un archivo llegó al almacén | FT-ACT-05 |
catalog.asset.changed/ASSET_VALIDATED | Un archivo cumple su ficha | FT-FLU-07, FT-PRD-07, FT-PRD-08, FT-PRD-10 |
catalog.asset.changed/ASSET_REJECTED | Un archivo no cumple su ficha o QA rechaza una imagen | FT-ACT-03, FT-ACT-05, FT-RAC-04, FT-RAC-06 |
catalog.asset.changed/ASSET_FROZEN | Un activo de un producto con SKU queda congelado con su nombre final | FT-ACT-03, FT-ACT-04, FT-ACT-06, FT-ARQ-02, FT-IA-04 |
catalog.asset.changed/ASSET_DELETED | Se quita una imagen de la galería | MS-05 (bitácora) |
catalog.asset.changed/ASSET_JOB_FINISHED | Termina una carga masiva de imágenes | MS-05 (bitácora) |
catalog.product.changed/MEDIA_CHANGED | Producto actualizó su copia de URL congeladas | FT-IA-05 |
catalog.product.changed/TASK_CHANGED | Se cierra Carga de imagen | FT-ACT-05, FT-ACT-06, FT-ARQ-02, FT-CAT-06, FT-FLU-01, FT-IA-06, FT-PRD-02, FT-PRD-05, FT-PRD-06, FT-PRD-07, FT-PRD-08, FT-RAC-02, FT-RAC-03, FT-RAC-04, FT-RAC-05, FT-RAC-06 |
catalog.product.publication/PUBLICATION_REQUESTED | Cambió la galería de un producto ya publicado | FT-CAT-05, FT-CAT-06, FT-INT-01, FT-INT-02, FT-INT-05, FT-INT-07, FT-PLT-08, FT-PRD-05, FT-RAC-03 |
Consume
| Evento | Para qué | Quién lo publica |
|---|---|---|
catalog.product.changed/SKU_ASSIGNED | MS-11 congela lo que ya estaba cargado con el SKU de cada variante | FT-INT-03, FT-PRD-02 |
catalog.asset.changed/ASSET_FROZEN | MS-02 relee la galería y guarda la copia de URL congeladas y «procede» | esta misma épica |
catalog.asset.changed/ASSET_DELETED | MS-02 relee la galería y quita la URL de su copia | esta misma épica |
catalog.asset.changed/ASSET_REJECTED | MS-14 avisa al proveedor; MS-02 registra el rechazo en el producto y lo saca de su copia | esta misma épica |
catalog.asset.changed/ASSET_JOB_FINISHED | MS-14 avisa a quien lanzó la carga masiva | esta misma épica |
7. Datos
Cada colección tiene un solo dueño, el único que escribe en ella.
| Colección | Dueño | Qué guarda | Esta épica |
|---|---|---|---|
assets | MS-11 | Cada archivo una vez: a qué producto, variante y posición pertenece, su validación técnica, URL de trabajo y URL congelada. | escribe |
asset_jobs | MS-11 | Cargas masivas de imágenes, por archivo comprimido, carpeta o lista de URL. | escribe |
asset_outbox | MS-11 | Los cambios de activos que esperan salir como evento. | escribe |
products | MS-02 | La familia del producto con sus variantes, valores, imágenes (URL), clasificaciones, estado, tareas abiertas y rechazos. | escribe |
tasks | MS-02 | Todo el trabajo asignado: visto bueno, corrección, Gobierno de Datos, foto, secciones, QA, revisión del cambio y repoblamiento. | escribe |
asset_types | MS-11 | Los tipos de activo (principal, detalle, isométrica, video, certificado…) con su ficha técnica: medidas, peso, formato, máximo y si se publica. | lee |
template_views | MS-01 | La vista efectiva ya resuelta por plantilla y negocio: qué atributos pide y cuáles son obligatorios. | lee |
8. Historias que cubre
| Historia | Prioridad | Cómo la cubre |
|---|---|---|
| FT-ACT-02·H1 · Registrar URLs | P1 | pasos 1, 2, 4, 5, 6, 9, 10; API-11-004, API-11-005, API-11-007 |
| FT-ACT-02·H2 · Consultar antes de enviar | P1 | API-11-007 |
| FT-ACT-02·H3 · Publicar la congelada | P1 | pasos 6, 7, 10; flujo «Congelado al asignar el SKU (la tubería de la imagen)»; API-11-010, API-02-020 |
| FT-ACT-02·H4 · Variante sin principal | P1 | pasos 10, 12; API-11-014 |
| FT-ACT-02·H5 · Cambiar imágenes de un publicado | P2 | flujo «Rechazar o cambiar imágenes de un producto ya publicado»; API-11-009 |
| FT-ACT-02·H6 · Rechazo por imagen | P2 | flujo «Rechazar o cambiar imágenes de un producto ya publicado»; API-11-015 |
| FT-ACT-02·H7 · Previsualizar | P3 | API-11-008 |
| FT-ACT-02·H8 · Conservar los canales de carga | P1 | flujo «Carga masiva de imágenes»; API-11-004, API-11-011, API-11-012 |
| FT-ACT-02·H9 · Activos que no salen a comercio | P2 | API-11-008 |
| FT-ACT-02·H10 · La tubería de la imagen | P1 | pasos 6; flujo «Congelado al asignar el SKU (la tubería de la imagen)» |
9. Decisiones de esta épica
Las tomó el TL como arquitecto; quedan como [Propuesta] hasta que el equipo de la épica las revise.
- D-ACT-02-1. Se conserva la copia congelada: cada activo tiene su original, su copia de trabajo y, con SKU, su copia congelada con el nombre final. Sólo la congelada se copia al producto y se publica. Por qué: Decide la mitad de PD-21 que toca al congelado: es lo que hoy publica P360 y evita que un cambio en la copia de trabajo llegue a la tienda sin revisión. Se apoya en PD-21, RSG-23, DUD-29.
- D-ACT-02-2. Se congela al tener SKU: MS-11 escucha SKU_ASSIGNED y congela lo válido; lo que llega después se congela al validarse. Si se reemplaza una imagen ya congelada, la URL nueva lleva su versión para que la tienda no muestre la vieja guardada en caché. Por qué: El nombre final usa el SKU (principal = SKU) y hoy la copia a congelados se dispara con el SKU; la versión en la URL evita depender de borrar la caché de la red de entrega. Se apoya en DUD-29, RF-IMG-12, ADR-12.
- D-ACT-02-3. MS-11 es dueño de los archivos y de sus URL públicas; MS-02 es dueño de la liga de cada activo con su variante, la principal, el orden, «procede» y la copia de la URL congelada. Con cada evento de activo, MS-02 relee la galería efectiva (API-11-007) en lugar de aplicar cambios sueltos; la URL de trabajo y la validación se leen en MS-11. Por qué: Una sola entrada de activos para el portal, el estudio y los sellers, y Producto sigue siendo el dueño de lo que se publica. Releer todo hace al consumidor inmune al orden y a los repetidos. Se apoya en DUD-29, ADR-12, FT-PRD-01.
- D-ACT-02-4. Carga de imagen se cierra cuando el proveedor envía (acción SUBMIT_IMAGES del motor) y el plan confirma el mínimo de aprobación de su plantilla y negocio con API-11-014; si vence el plazo de FT-PRD-08, el reloj de MS-02 la cierra como vencida y abre Foro por rescate (FT-ACT-05). MS-02 sólo abre esta tarea si la revisión de aprobación no pasa al asignarse el SKU. Por qué: El TO-BE pregunta «¿el proveedor la envió a QA?»; cerrar sola al primer mínimo cortaría al proveedor que sigue subiendo fotos, y abrirla cuando ya cumple sería trabajo de más. Se apoya en PD-29, FT-FLU-01, FT-PRD-08.
- D-ACT-02-5. Los binarios nunca pasan por el BFF ni por MS-02: la pantalla o el agente suben directo al almacén con una URL firmada de 15 minutos que da MS-11 después de preguntar al motor si quien carga puede cambiar las imágenes (API-02-027). Por qué: El BFF compone pantallas y no mueve archivos pesados; el permiso de dominio lo decide el motor de MS-02 y MS-11 lo aplica antes de firmar. Se apoya en ADR-12, DUD-33.
- D-ACT-02-6. Cambiar imágenes de un producto publicado no lo regresa a captura: la imagen pasa la validación técnica, se congela y MS-02 pide republicar sólo sus canales. Lo pueden hacer el dueño del contenido, el estudio si la foto es de Liverpool y Repoblamiento; QA rechaza una imagen sola con API-11-015. Por qué: Lo pide la ERF (alta, cambio y baja sin revalidar) y deja propuesta la regla de P-35 mientras la ERF de flujos no exista. Se apoya en P-35, DUD-09.
- D-ACT-02-7. Los activos de respaldo (certificado sostenible, carta responsiva) y los bocetos no tienen URL pública: viven en la zona privada del almacén y sólo los roles de su tipo los ven, con URL firmada de 10 minutos. Por qué: S16: son respaldo, no salen a comercio ni generan URL; una URL pública los dejaría a la vista de cualquiera. Se apoya en S16-RF-01, DUD-33.
- D-ACT-02-8. LasImagenes2 y KeepFinalMediaAssetURLs2 no se construyen (decisión 20): las pantallas del portal pasan al BFF en R1 y el estudio deja de copiar al bucket y de avisar dos veces. Los canales de carga de hoy (portal, estudio, generador de links y carga desde bucket) se conservan como pruebas de no afectación sobre MS-11. Por qué: Una foto de Foro hoy llega dos veces a P360 por dos caminos; con un solo registro no hay nada que reconciliar. Se apoya en ADR-12, PD-06, RSG-29.
- D-ACT-02-9. Ninguna URL lleva cadenas pegadas ni credenciales: el acceso a lo privado es por URL firmada que vence, nunca por un texto fijo concatenado a la URL. Por qué: La cadena que hoy se pega a la URL podría ser un token (PEN-145); con URL firmadas deja de hacer falta. Se apoya en PEN-145, RSG-44.
- D-ACT-02-10. Avisos (MS-14): se entera de qué avisar consumiendo eventos (ASSET_REJECTED, ASSET_JOB_FINISHED, STATUS_CHANGED, REJECTION_ADDED, TASK_CHANGED) y por API-14-005 cuando no basta un evento; resuelve a quién le llega con el directorio de MS-13 sin copiar correos; guarda las preferencias de cada persona como su documento de ajustes en notifications; un aviso obligatorio (rechazo, plazo por vencer) no se puede apagar, y la misma llave de duplicado no repite el aviso. Por qué: Un solo lugar para avisar a proveedores, sellers, estudio y áreas, sin el correo y las notificaciones duplicados de Entrada Única y Foro; las preferencias son de MS-14 y no hay otra colección suya donde guardarlas. Se apoya en P-02, PEN-17, ADR-12.
Qué falta decidir
| ID | Qué falta |
|---|---|
| PD-21 | Sigue abierta la mitad del seller (URL propias o carga por Entrada Única); aquí se propone conservar la copia congelada. |
| DUD-29 | Arquitectura con Publicación confirma en ADR-04 que MS-11 es dueño de las URL públicas que sirve la red de entrega. |
| P-35 | Prod E-commerce con Foro confirma quién cambia una imagen publicada y si vuelve a calidad. |
| DUD-09 | La ERF de flujos sigue sin escribirse; aquí se propone cambiar imágenes publicadas sin revalidar. |
| DUD-33 | Seguridad revisa la carga directa al almacén con URL firmada y la credencial de equipo del agente. |
Fuentes
- [D]
trazabilidad/features/FT-ACT-02-registro-congelado-publicacion-urls.md: la ficha de la épica, con sus historias, reglas y bloqueos. - [D] ADR-12 · Un solo sistema: backend compartido y una sola base (sección 3.4).
- [D]
docs/arquitectura/por-epica/base/: piezas, colecciones, eventos y el hilo de punta a punta. - [D]
docs/arquitectura/omega-a-pim-headless/contratos-api.md: convenciones y endpoints de partida. - [D]
docs/arquitectura/maquina-de-estados-to-be/propuesta-maquina-de-estados.md§7: estados, tareas y canales. - [I] Las decisiones de la sección 9 son del TL sobre esas fuentes.