Actualizado el 18-oct-2026. Primera versión de la arquitectura de esta épica.
Qué responde. Cómo funciona por dentro FT-PLT-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-PLT-02.json, generada con generar.py; la ficha de la épica es trazabilidad/features/FT-PLT-02-catalogo-de-atributos.md.
En 30 segundos
Cada dato que se le pide a un producto es un atributo del catálogo: su tipo, sus restricciones, su lista de valores y a qué sistemas viaja. Hoy esas reglas están regadas en tablas y en código, y cada canal valida distinto. Esta épica deja un solo catálogo de atributos que dicta cómo se valida un valor en la pantalla, la carga masiva y la API, y qué viaja a cada sistema, incluidos los bloques de varias filas y los atributos que aparecen según otro.
- Módulo dueño: MS-01 Catálogo. También participan: MS-13 Identidad y acceso, MS-02 Producto, MS-08 Adaptadores de salida.
- Etapa C · Configura el catálogo. Recibe «PE-T · Usuario con permisos y bitácora» y entrega «PE-C · Catálogo vigente».
- APIs: construye 4 y usa 6 que construyen otras épicas.
- Eventos: publica 1 y consume 3.
1. Dónde encaja
Recibe
| De | Qué |
|---|---|
| PE-T · Usuario con permisos y bitácora | El administrador de Gobierno de Producto ya identificado, con sus roles del directorio de MS-13. |
| FT-PLT-01 · Fundamentos de gobierno de plantillas | El mecanismo común de escritura: plan, solicitud con aprobación, ID inmutables y recibo; cada cambio aprobado sale como evento con su antes y después. |
Entrega
| A | Qué |
|---|---|
| PE-C · Catálogo vigente | Los atributos vigentes con su tipo, restricciones, lista, bloque, regla condicional y metadatos por sistema, que todos leen de MS-01 y refrescan con ATTRIBUTE_CHANGED. |
| FT-PLT-03 · Listas de valores y modelo canónico con equivalencias por… | Los atributos de tipo lista, cada uno con su lista y la que usa cada negocio. |
| FT-PLT-04 · Grupos de atributos y mínimos de información por sistema… | La relevancia de cada atributo por destino y su pertenencia a grupos, de donde sale la salida por sistema. |
| FT-PLT-06 · Configuración de atributos por plantilla y por negocio… | El catálogo del que se toman los atributos para configurar cada plantilla, con sus restricciones y su regla condicional por omisión. |
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 | Administración del catálogo | Entrada Única · Vendor Center | Busca si ya existe un atributo parecido | — |
| 2 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Busca por código o nombre en el catálogo | API-01-001 |
| 3 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Abre el detalle con tipo, lista y metadatos | API-01-002 |
| 4 | Administración del catálogo | Entrada Única · Vendor Center | Captura tipo, restricciones y destinos del atributo nuevo | — |
| 5 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Pide el plan del alta del atributo | API-01-003 |
| 6 | MS-01 Catálogo | MS-13 Identidad y acceso | Revisa que pueda administrar atributos | API-13-001 |
| 7 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Confirma y abre la solicitud de cambio | API-01-004 |
| 8 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Otro administrador aprueba la solicitud | API-01-103 |
| 9 | MS-01 Catálogo | Base pim | Guarda el atributo activo con su ID nuevo | — |
| 10 | MS-01 Catálogo | Eventos | Avisa el atributo nuevo | catalog.governance.changed/ATTRIBUTE_CHANGED |
| 11 | Eventos | MS-08 Adaptadores de salida | Entrega el cambio: ya sabe a qué destinos viaja | catalog.governance.changed/ATTRIBUTE_CHANGED |
| 12 | Eventos | MS-02 Producto | Entrega el cambio para validar contra tipo y restricciones | catalog.governance.changed/ATTRIBUTE_CHANGED |
3.1 Cambiar el tipo de un atributo de lista
3.2 Bloques de filas y atributos condicionales
3.3 Lo que no es de SAP no viaja a SAP
4. Si algo sale mal
- Se quiere cambiar el tipo o la lista de un atributo que ya tiene valores. El plan responde 409 IMMUTABLE_ID con cuántos productos tienen valor. Se crea un atributo nuevo y el viejo se desactiva; los productos conservan su valor en el viejo.
- Se pide borrar un atributo usado por una plantilla, una regla o un producto. El plan responde 422 BUSINESS_ERROR y ofrece desactivarlo: deja de pedirse en las capturas nuevas y nadie pierde un valor.
- Un valor capturado no cumple las restricciones (101 caracteres en un texto de 100). La validación en línea de MS-02 lo rechaza con VALIDATION_ERROR en la ruta del campo; la regla sale del atributo y es la misma en la pantalla, la carga masiva y la API.
- Un usuario sin perfil intenta crear, editar o borrar un atributo. MS-01 decide con los roles de MS-13 y responde 403 AUTHORIZATION_ERROR; no se abre ninguna solicitud.
5. APIs
Las que construye esta épica (4)
GET /api/v2/attributes · Buscar atributos
| Campo | Valor |
|---|---|
| API | API-01-001 · MS-01 Catálogo |
| Para qué | Busca en el catálogo de atributos por código o nombre, con filtros por tipo, estado, grupo y destino, y dice cuántos hay. Con esto Gobierno de Producto decide un cambio sin abrir P360. |
| En esta épica | Buscar atributos por código o nombre, con su total |
| Quién la llama | BFF del portal, MS-02 Producto, MS-15 IA y enriquecimiento |
| Permiso | CAT-L (consulta del catálogo); los módulos, con su cuenta de servicio |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | q = potencia, status = ACTIVE, dataType = DECIMAL, groupId = CARACTERISTICAS, relevantFor = TIENDA, page = 1, size = 50 |
| También la usan | FT-IA-05, FT-PLT-06, FT-REF-01 |
Request
null
Response · 200
{
"success": true,
"data": {
"items": [
{
"attributeId": "ATR-0003001",
"name": {
"es": "Potencia",
"en": "Power"
},
"dataType": "DECIMAL",
"constraints": {
"min": 0,
"max": 5000,
"decimals": 1,
"unit": "W"
},
"multivalued": false,
"lovId": null,
"groups": [
"CARACTERISTICAS",
"DESTINO:TIENDA"
],
"relevantFor": [
"TIENDA",
"MARKETPLACE",
"DWH"
],
"systemOfRecord": "PIM",
"origin": "LIVERPOOL",
"status": "ACTIVE",
"version": 3
}
],
"page": 1,
"size": 50,
"total": 1
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 400 | VALIDATION_ERROR | Un filtro trae un tipo, un estado o un destino que no existe |
GET /api/v2/attributes/{id} · Detalle de un atributo
| Campo | Valor |
|---|---|
| API | API-01-002 · MS-01 Catálogo |
| Para qué | Muestra un atributo completo: nombre por idioma, tipo, restricciones, lista (y la que usa cada negocio), bloque de filas, regla condicional por omisión, metadatos por sistema, identificadores de SAP y de dónde viene. |
| En esta épica | Ver un atributo completo |
| Quién la llama | BFF del portal, MS-02 Producto, MS-15 IA y enriquecimiento |
| Permiso | CAT-L; los módulos, con su cuenta de servicio |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | id = MARCA |
Request
null
Response · 200
{
"success": true,
"data": {
"attributeId": "MARCA",
"name": {
"es": "Marca",
"en": "Brand"
},
"helpText": {
"es": "La marca comercial del producto, como la registra SAP"
},
"dataType": "LOV",
"lov": {
"lovId": "MARCAS_ECC_LOV",
"lovByBusiness": {
"SUB": "MARCAS_S4H_LOV"
},
"newValuePolicy": "REJECT"
},
"multivalued": false,
"constraints": {},
"composite": null,
"dependency": null,
"metadata": {
"systemOfRecord": "SAP",
"origin": "ERP",
"relevantFor": [
"SAP",
"TIENDA",
"OMS",
"MARKETPLACE",
"SENALIZACION",
"DWH"
],
"uniqueByBusiness": false,
"validity": [
"TODOS"
],
"variantLevel": "GENERIC"
},
"externalIds": {
"ECC": "BRAND_ID",
"S4H": "BRAND_ID"
},
"groups": [
"DATOS_MAESTROS",
"DESTINO:SAP",
"DESTINO:TIENDA",
"SECCION:DATOS_BASE"
],
"status": "ACTIVE",
"version": 7,
"audit": {
"origin": "MIGRATION",
"loadedAt": "2026-12-05T06:00:00Z",
"updatedAt": "2027-01-12T17:40:00Z"
}
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | El atributo no existe |
POST /api/v2/attributes/plans · Plan de alta o cambio de atributos
| Campo | Valor |
|---|---|
| API | API-01-003 · MS-01 Catálogo |
| Para qué | Revisa sin escribir el alta, el cambio, la activación o la baja de hasta 200 atributos y dice qué va a pasar. Si el cambio toca el tipo o la lista, pregunta a Producto si algún producto ya tiene valor. El ID nuevo se asigna al aprobar. |
| En esta épica | Alta, cambio, activación o baja de atributos |
| Quién la llama | BFF del portal |
| Permiso | CAT-E; capturar el ID al crear exige además el permiso de capturar ID |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| También la usan | FT-USR-02 |
Request
{
"operation": "CREATE",
"channel": "PORTAL",
"items": [
{
"attributeId": null,
"name": {
"es": "Potencia",
"en": "Power"
},
"helpText": {
"es": "Potencia del motor en watts"
},
"dataType": "DECIMAL",
"constraints": {
"min": 0,
"max": 5000,
"decimals": 1,
"unit": "W"
},
"multivalued": false,
"metadata": {
"systemOfRecord": "PIM",
"origin": "LIVERPOOL",
"relevantFor": [
"TIENDA",
"MARKETPLACE",
"DWH"
],
"variantLevel": "GENERIC"
},
"groups": [
"CARACTERISTICAS"
]
}
]
}
Response · 200
{
"success": true,
"data": {
"planId": "pln-a41c09",
"expiresAt": "2027-01-12T15:14:05Z",
"requiresApproval": true,
"summary": {
"create": 1,
"update": 0,
"blocked": 0
},
"items": [
{
"attributeId": null,
"idAssignedOn": "APPROVAL",
"idPattern": "ATR-{número}",
"action": "CREATE",
"changes": [
{
"path": "dataType",
"before": null,
"after": "DECIMAL"
},
{
"path": "constraints.max",
"before": null,
"after": 5000
}
]
}
],
"applyUrl": "/api/v2/catalog-plans/pln-a41c09/apply"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 403 | AUTHORIZATION_ERROR | Quien llama no tiene CAT-E o captura un ID sin el permiso de capturar ID |
| 409 | IMMUTABLE_ID | Cambia el código, o el tipo o la lista de un atributo que ya tiene valores en productos |
| 409 | ID_ALREADY_EXISTS | El ID capturado ya es de otro objeto del catálogo |
| 422 | BUSINESS_ERROR | Pide borrar un atributo usado por una plantilla, una regla o un producto: se ofrece desactivarlo |
| 409 | WRITE_DISABLED | P360 todavía es la fuente del catálogo (antes del corte de R1) |
POST /internal/product/catalog-usage · Producto cuenta cuántos productos usan una plantilla, un atr
| Campo | Valor |
|---|---|
| API | API-02-113 · MS-02 Producto |
| Para qué | Producto cuenta cuántos productos usan una plantilla, un atributo o un valor de lista, por negocio y por estado, para que el catálogo muestre el impacto de un cambio antes de aprobarlo y decida si un tipo o una lista todavía se pueden cambiar. |
| En esta épica | Saber si algún producto ya tiene valor antes de cambiar tipo o lista |
| También la usan | FT-PLT-03, FT-PLT-05, FT-PLT-06, FT-PLT-09 |
Request
{
"by": "ATTRIBUTE",
"keys": [
"COLOR_PRINCIPAL"
],
"business": [
"MER",
"SUB",
"MKP"
]
}
Response · 200
{
"success": true,
"data": {
"countedAt": "2027-01-12T15:06:00Z",
"items": [
{
"key": "COLOR_PRINCIPAL",
"products": 0,
"withValue": 0,
"published": 0,
"byStatus": {
"BORRADOR": 0,
"EN_REVISION": 0,
"APROBADO": 0
},
"byBusiness": {
"MER": 0,
"SUB": 0,
"MKP": 0
}
}
]
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 403 | AUTHORIZATION_ERROR | Quien llama no tiene el permiso o no es el módulo autorizado |
| 422 | VALIDATION_ERROR | Falta un dato o viene con un formato inválido; el detalle dice qué campo |
| 409 | IDEMPOTENCY_MISMATCH | Se repite la llave de idempotencia con otro cuerpo |
Las que usa y construye otra épica (6)
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-01-004 | POST /api/v2/catalog-plans/{planId}/apply | Confirmar el plan y abrir la solicitud | FT-PLT-01 · Fundamentos de gobierno de plantillas |
| API-01-103 | POST /api/v2/catalog-change-requests/{changeRequestId}/decision | Aprobar la solicitud del atributo | FT-PLT-01 · Fundamentos de gobierno de plantillas |
| API-13-001 | GET /internal/identity/permissions?userId= | Permisos efectivos de quien administra atributos | FT-USR-01 · Identidad y autenticación de usuarios internos… |
| API-01-105 | GET /api/v2/attribute-outputs | Qué atributos viajan a cada destino | FT-PLT-04 · Grupos de atributos y mínimos de información por sistema… |
| API-02-055 | GET /internal/product/products/{id}/sap-snapshot | La foto del producto que arma los archivos de SAP | FT-PRD-02 · Creación de SKU con SAP |
| API-01-053 | POST /internal/governance/bulk-load/{coleccion} | Migrar los 2,996 atributos con su ID externo y su origen | FT-PLT-01 · Fundamentos de gobierno de plantillas |
6. Eventos
Publica
| Evento | Cuándo | Quién lo consume |
|---|---|---|
catalog.governance.changed/ATTRIBUTE_CHANGED | Se aprueba el alta, el cambio, la activación o la desactivación de un atributo | FT-ARQ-02, FT-PLT-04, FT-PLT-06 |
Consume
| Evento | Para qué | Quién lo publica |
|---|---|---|
catalog.governance.changed/ATTRIBUTE_CHANGED | MS-02 refresca el tipo, las restricciones y la regla condicional con que valida en línea | esta misma épica |
catalog.governance.changed/ATTRIBUTE_CHANGED | MS-08 refresca a qué destinos viaja cada atributo | esta misma épica |
catalog.governance.changed/ATTRIBUTE_CHANGED | MS-05 guarda el antes y el después de cada campo del atributo | 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 |
|---|---|---|---|
attributes | MS-01 | Cada atributo: tipo, lista, restricciones, grupos e identificadores externos. | escribe |
id_sequences | MS-01 | El siguiente identificador de plantillas y catálogos. | escribe |
governance_receipts | MS-01 | El recibo de cada escritura confirmada en el catálogo (antes operation_receipts). | escribe |
governance_outbox | MS-01 | Los cambios del catálogo que esperan salir como evento (antes outbox). | escribe |
attributes | MS-01 | Cada atributo: tipo, lista, restricciones, grupos e identificadores externos. | lee |
lovs | MS-01 | Cabecera de cada lista de valores. | lee |
attribute_groups | MS-01 | Grupos de atributos, incluidos los de permiso (quién ve y quién edita). | lee |
8. Historias que cubre
| Historia | Prioridad | Cómo la cubre |
|---|---|---|
| FT-PLT-02·H1 · Consultar el catálogo | P1 | pasos 1, 2, 3; API-01-001, API-01-002, API-01-053 |
| FT-PLT-02·H2 · Tipo y restricciones | P1 | pasos 4, 5, 6, 7, 8, 9; flujo «Cambiar el tipo de un atributo de lista»; API-01-003, API-02-113 |
| FT-PLT-02·H3 · Metadatos de comportamiento | P2 | pasos 4, 11; flujo «Lo que no es de SAP no viaja a SAP»; API-01-105, API-01-053 |
| FT-PLT-02·H4 · Bloques y condicionales | P2 | flujo «Bloques de filas y atributos condicionales»; API-01-003 |
9. Decisiones de esta épica
Las tomó el TL como arquitecto; quedan como [Propuesta] hasta que el equipo de la épica las revise.
- D-PLT-02-1. Tipos de dato: los ocho de hoy (texto, entero, decimal, verdadero o falso, fecha, fecha y hora, lista y compuesto) más texto enriquecido, moneda y referencia a otro objeto. Las restricciones (longitud, mínimo, máximo, decimales, unidad, patrón) viven en el atributo, no en tablas sueltas, y una plantilla sólo puede endurecerlas. Por qué: DEC-ARQ-12 mete lo que pide la ERF. Hoy ninguna de las 24,217 características usa las cotas del modelo y las restricciones están en la configuración por plantilla. Se apoya en DEC-ARQ-12, PD-14, DUD-01.
- D-PLT-02-2. El código de un atributo nunca cambia. Su tipo y su lista tampoco, en cuanto un producto tiene valor; mientras nadie lo use, el plan permite cambiarlos y exige el tipo nuevo al quitar la lista. Para saberlo, MS-01 le pregunta a Producto (PEDIDA-PLT-02-1). Por qué: Concilia lo que pide la ERF (quitar la lista exige el tipo nuevo) con la inmutabilidad que protege los valores ya capturados. Se apoya en PD-16, DEC-PLT-06.
- D-PLT-02-3. Los metadatos de comportamiento son campos del atributo: sistema dueño, origen (ERP o Liverpool, como los …VaD), relevancia por destino, único por negocio, validez por tipo de producto y si se captura por variante. Ningún adaptador guarda listas de campos en código: MS-08 y MS-10 leen la salida de MS-01 (API-01-105). Por qué: Hoy la relevancia vive en tres diccionarios y las salidas la deciden con listas propias; con un solo dueño, cambiar qué viaja a un sistema es una solicitud, no un despliegue. Se apoya en DEC-PLT-08, DEC-ARQ-09.
- D-PLT-02-4. Atributos condicionales: la regla por omisión (mostrar, ocultar o volver obligatorio según el valor de otro atributo) se declara en el atributo; cada plantilla puede cambiarla en su configuración y la vista efectiva resuelve cuál aplica, con más de un nivel de dependencia. Por qué: Hoy la dependencia es una propiedad suelta de la configuración y sólo llega a un nivel; sin la fachada de compatibilidad (decisión 20) no hay que copiar esa limitación. Se apoya en DEC-ARQ-12, DEC-PLT-11, ADR-12.
- D-PLT-02-5. Los bloques de N filas son el tipo compuesto, con sus campos (porcentaje, material, parte) y un máximo de filas. La composición textil aplanada en cinco atributos se convierte al migrar con la regla que valide Gobierno de Producto. Por qué: Guardar filas en vez de columnas numeradas deja capturar los materiales que haga falta y validarlos igual. Se apoya en DEC-PLT-07.
- D-PLT-02-6. La validez por tipo de producto se modela desde ya y se llena con los seis tipos propuestos cuando se ratifiquen; mientras, todo atributo vale para todos los tipos. Las hijas de rechazo no son atributos: el motivo de rechazo viaja con el producto (MS-02). Por qué: No se bloquea el catálogo esperando una tabla que no existe, y no se migran 2,632 árboles de rechazo como si fueran atributos. Se apoya en PD-17, DUD-19, DEC-ARQ-09.
Qué falta decidir
| ID | Qué falta |
|---|---|
| DUD-01 | Gobierno de Producto con Seguridad fijan las etiquetas que admite el texto enriquecido. |
| PD-17 | Gobierno de Producto ratifica la tabla de tipos de producto que usa la validez de cada atributo. |
| PD-03 | Confirmar con tres plantillas reales que la lista de atributos es la de la configuración más lo global y lo heredado. |
| DUD-02 | Revisar las specs de atributos contra la ERF 1.1 del 24-sep (sección del portal en el atributo o en la plantilla). |
Fuentes
- [D]
trazabilidad/features/FT-PLT-02-catalogo-de-atributos.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.