Actualizado el 18-oct-2026. Primera versión de la arquitectura de esta épica.
Qué responde. Cómo funciona por dentro FT-PLT-01: 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-01.json, generada con generar.py; la ficha de la épica es trazabilidad/features/FT-PLT-01-fundamentos-de-gobierno-de-plantillas.md.
En 30 segundos
Plantillas, atributos y listas las usan todos los portales y SAP, así que un cambio mal hecho afecta a miles de productos. Esta épica pone las reglas comunes de toda escritura del catálogo: cada objeto conserva su identificador para siempre, todo cambio queda como solicitud pendiente hasta que otra persona autorizada lo aprueba, y cada campo cambiado deja su antes y su después en la bitácora. Así nada llega a la captura sin control y siempre se sabe quién cambió qué.
- Módulo dueño: MS-01 Catálogo. También participan: MS-13 Identidad y acceso, MS-14 Avisos y ayuda, MS-05 Auditoría, MS-02 Producto, MS-03 Migración y convivencia, MS-15 IA y enriquecimiento.
- Etapa C · Configura el catálogo. Recibe «PE-T · Usuario con permisos y bitácora» y entrega «PE-C · Catálogo vigente».
- APIs: construye 8 y usa 7 que construyen otras épicas.
- Eventos: publica 1 y consume 2.
1. Dónde encaja
Recibe
| De | Qué |
|---|---|
| PE-T · Usuario con permisos y bitácora | El usuario ya identificado, con sus roles del directorio de MS-13 y la bitácora de MS-05 lista para guardar cada cambio. |
| FT-USR-02 · Matriz de roles y permisos por módulo, acción, negocio y… | La hoja del catálogo de la matriz firmada (qué rol consulta, propone, aprueba o captura un ID en cada tipo de objeto y negocio), que Seguridad carga en MS-01 con API-01-110. |
| FT-ARQ-02 · Bitácora inmutable y versionado de producto, plantilla y… | La bitácora inmutable de MS-05, que guarda cada evento del catálogo con el antes y el después por campo. |
| FT-IA-04 · Integración de los modelos de IA existentes | La plantilla que propone la IA, como solicitud de cambio con canal IA que Gobierno de Producto aprueba o rechaza. |
Entrega
| A | Qué |
|---|---|
| PE-C · Catálogo vigente | Sólo lo aprobado entra al catálogo vigente: cada cambio aplicado sale en catalog.governance.changed con su versión y sus cambios por campo. |
| FT-PLT-02 · Catálogo de atributos | El mecanismo común de escritura (plan, solicitud, aprobación, recibo e identificadores) para el catálogo de atributos. |
| FT-PLT-05 · Taxonomía de plantillas por familia, metadatos de… | El mismo mecanismo para el árbol de plantillas, con la secuencia EU{nivel+1}-{número} que asigna el ID al aprobar. |
| FT-PLT-09 · Carga masiva de configuración de plantillas con… | La solicitud de cambio con canal IMPORT, API o IA, para que una carga masiva siga el mismo control que la pantalla. |
| FT-PLT-07 · Reglas de atributos | La confirmación común de planes (API-01-004) y, para las reglas que pidan aprobación, la solicitud y su decisión (API-01-103). |
| FT-MIG-02 · Migración de plantillas, atributos y listas de valores | La ruta de carga de la migración (API-01-053): conserva los ID de P360, no publica eventos y deja la secuencia en el máximo migrado más uno. |
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 | Da de alta una plantilla nueva sin capturar su ID | — |
| 2 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Pide el plan del alta bajo su familia | API-01-023 |
| 3 | MS-01 Catálogo | MS-13 Identidad y acceso | Pide los roles del usuario y los cruza con su matriz | API-13-001 |
| 4 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Confirma el plan y abre la solicitud de cambio | API-01-004 |
| 5 | MS-01 Catálogo | Base pim | Guarda la solicitud pendiente con su antes y después | — |
| 6 | MS-01 Catálogo | MS-14 Avisos y ayuda | Avisa a los aprobadores que hay una solicitud | API-14-005 |
| 7 | Administración del catálogo | Entrada Única · Vendor Center | Otro administrador abre su bandeja de solicitudes | — |
| 8 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Lista las solicitudes pendientes que puede decidir | API-01-101 |
| 9 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Abre el cambio campo por campo | API-01-102 |
| 10 | Entrada Única · Vendor Center | MS-01 Catálogo (por el BFF) | Aprueba la solicitud | API-01-103 |
| 11 | MS-01 Catálogo | Base pim | Asigna el siguiente EU4 y crea la plantilla activa | — |
| 12 | MS-01 Catálogo | Eventos | Avisa el alta de la plantilla | catalog.governance.changed/TEMPLATE_CHANGED |
| 13 | Eventos | MS-05 Auditoría | Entrega el cambio para la bitácora por campo | catalog.governance.changed/TEMPLATE_CHANGED |
| 14 | Eventos | MS-02 Producto | Entrega el cambio: la captura ya puede ofrecerla | catalog.governance.changed/TEMPLATE_CHANGED |
3.1 Si el aprobador rechaza
3.2 Cambios que llegan por carga masiva o por la IA
3.3 Migración con los ID de P360 y su historia
4. Si algo sale mal
- El aprobador rechaza. La solicitud se cierra como rechazada, el catálogo no cambia y MS-14 avisa al solicitante con el motivo; puede abrir otra solicitud corregida.
- Alguien cambió el objeto mientras la solicitud esperaba. Al aprobar, MS-01 vuelve a comparar las versiones: si alguna cambió, la solicitud queda en conflicto sin aplicar nada (409 VERSION_CONFLICT) y el solicitante recibe el aviso para pedirla otra vez sobre la versión vigente.
- Nadie decide la solicitud. A los 23 días MS-14 le recuerda al solicitante y a los aprobadores; a los 30 la solicitud vence sola sin tocar el catálogo y queda en su recibo como vencida.
- Quien pidió el cambio intenta aprobarlo. La decisión responde 403 AUTHORIZATION_ERROR: nadie aprueba lo que pidió, y la bandeja no le muestra el botón (canDecide en falso).
- Alguien captura un ID sin permiso o intenta cambiar uno existente. El plan responde 403 AUTHORIZATION_ERROR o 409 IMMUTABLE_ID y no se abre ninguna solicitud; si el ID ya es de otro objeto, 409 ID_ALREADY_EXISTS.
5. APIs
Las que construye esta épica (8)
POST /api/v2/catalog-plans/{planId}/apply · Confirmar un plan del catálogo
| Campo | Valor |
|---|---|
| API | API-01-004 · MS-01 Catálogo |
| Para qué | Confirma cualquier plan de MS-01. Si el cambio pide aprobación (todo lo que define la plantilla: atributos, listas, grupos, árboles, metadatos y configuración), lo deja como solicitud pendiente y no toca el catálogo. Si no la pide (un diccionario así marcado, o una regla según lo que fije FT-PLT-07), lo aplica con su recibo y su aviso. |
| En esta épica | Confirmar cualquier plan de MS-01: abre la solicitud o aplica directo |
| Quién la llama | BFF del portal, MS-15 IA y enriquecimiento |
| Permiso | El mismo usuario o servicio que pidió el plan |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key |
| Parámetros | planId = pln-a41c09 |
| Escribe en | governance_rules, reference_tables, governance_receipts, governance_outbox |
| Publica | catalog.governance.changed/RULE_CHANGED, catalog.governance.changed/REFERENCE_TABLE_CHANGED |
| También la usan | FT-ACT-01, FT-ARQ-02, FT-CAT-04, FT-CAT-05, FT-IA-03, FT-INT-03, FT-PLT-02, FT-PLT-03, FT-PLT-04, FT-PLT-05, FT-PLT-06, FT-PLT-07, FT-PLT-10, FT-REF-01, FT-REF-02, FT-USR-02 |
Request
{
"comment": "Atributo pedido para las licuadoras de alta potencia"
}
Response · 202
{
"success": true,
"data": {
"requestId": "req-8e41a0",
"status": "PENDING_APPROVAL",
"changeRequestId": "chg-2a71c4",
"receiptUrl": "/api/v2/catalog-receipts/req-8e41a0"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | El plan no existe o es de otro usuario |
| 409 | PLAN_EXPIRED | Pasaron más de 10 minutos desde la vista previa |
| 409 | VERSION_CONFLICT | Algún objeto cambió después de la vista previa |
| 409 | IDEMPOTENCY_MISMATCH | Se repite la llave de idempotencia con otro plan |
| 409 | WRITE_DISABLED | P360 todavía es la fuente del catálogo (antes del corte de R1) |
GET /api/v2/catalog-change-requests · Bandeja de solicitudes del catálogo
| Campo | Valor |
|---|---|
| API | API-01-101 · MS-01 Catálogo |
| Para qué | Lista las solicitudes de cambio del catálogo con filtros por estado, tipo de objeto, canal y área que la pidió. Marca cuáles puede decidir quien llama: nadie decide lo que él mismo pidió. |
| En esta épica | La bandeja de solicitudes del catálogo |
| Quién la llama | BFF del portal |
| Permiso | CAT-E ve las suyas; el aprobador del catálogo ve las que puede decidir |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | status = PENDING, objectType = TEMPLATE_NODE, channel = PORTAL, requestedByArea = GOBIERNO-PRODUCTO, page = 1, size = 50 |
Request
null
Response · 200
{
"success": true,
"data": {
"items": [
{
"changeRequestId": "chg-2a71c4",
"status": "PENDING",
"channel": "PORTAL",
"objectType": "TEMPLATE_NODE",
"operation": "CREATE",
"summary": "Alta de la plantilla «Licuadoras de inmersión» bajo EU3-0398",
"objectCount": 1,
"requestedBy": {
"userId": "usr-1042",
"area": "GOBIERNO-PRODUCTO"
},
"requestedAt": "2027-01-12T15:05:00Z",
"expiresAt": "2027-02-11T15:05:00Z",
"canDecide": true
}
],
"page": 1,
"size": 50,
"total": 1
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 400 | VALIDATION_ERROR | Un filtro trae un estado, tipo o canal que no existe |
GET /api/v2/catalog-change-requests/{changeRequestId} · Detalle de una solicitud de cambio
| Campo | Valor |
|---|---|
| API | API-01-102 · MS-01 Catálogo |
| Para qué | Muestra lo que se pide cambiar, objeto por objeto y campo por campo (antes y después), con su impacto en plantillas y productos, para que el aprobador decida con todo a la vista. |
| En esta épica | El detalle de una solicitud, campo por campo |
| Quién la llama | BFF del portal |
| Permiso | Quien la pidió y los aprobadores del catálogo |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | changeRequestId = chg-2a71c4 |
| También la usan | FT-IA-04 |
Request
null
Response · 200
{
"success": true,
"data": {
"changeRequestId": "chg-2a71c4",
"status": "PENDING",
"channel": "PORTAL",
"operation": "CREATE",
"version": 1,
"comment": "Familia nueva pedida por Compras Hogar",
"requestedBy": {
"userId": "usr-1042",
"area": "GOBIERNO-PRODUCTO"
},
"requestedAt": "2027-01-12T15:05:00Z",
"expiresAt": "2027-02-11T15:05:00Z",
"objects": [
{
"objectType": "TEMPLATE_NODE",
"objectId": null,
"idAssignedOn": "APPROVAL",
"idPattern": "EU4-{número}",
"baseVersion": null,
"diff": [
{
"path": "name.es",
"before": null,
"after": "Licuadoras de inmersión"
},
{
"path": "parentId",
"before": null,
"after": "EU3-0398"
},
{
"path": "keywords",
"before": null,
"after": [
"licuadora de mano",
"batidora de inmersión"
]
}
]
}
],
"impact": {
"templates": 1,
"views": 3,
"products": 0
},
"decision": null
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | La solicitud no existe o no es visible para quien llama |
POST /api/v2/catalog-change-requests/{changeRequestId}/decision · Aprobar o rechazar una solicitud
| Campo | Valor |
|---|---|
| API | API-01-103 · MS-01 Catálogo |
| Para qué | El aprobador decide. Al aprobar, MS-01 vuelve a comparar las versiones, asigna los ID nuevos, aplica cada objeto con su recibo y publica sus avisos; si algo cambió entretanto, la solicitud queda en conflicto sin aplicar nada. Al rechazar, cierra la solicitud con su motivo. |
| En esta épica | Aprobar o rechazar una solicitud |
| Quién la llama | BFF del portal |
| Permiso | Aprobador del catálogo para ese tipo de objeto; nunca quien pidió la solicitud |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key, If-Match |
| Parámetros | changeRequestId = chg-2a71c4 |
| Escribe en | attributes, attribute_groups, lovs, lov_values, taxonomies, taxonomy_nodes, template_views, governance_rules, reference_table_defs, reference_tables, id_sequences, governance_receipts, governance_outbox |
| Publica | catalog.governance.changed/ATTRIBUTE_CHANGED, catalog.governance.changed/LOV_CHANGED, catalog.governance.changed/LOV_VALUE_CHANGED, catalog.governance.changed/TEMPLATE_CHANGED, catalog.governance.changed/TEMPLATE_VIEW_CHANGED, catalog.governance.changed/REFERENCE_TABLE_CHANGED, catalog.governance.changed/RULE_CHANGED, catalog.governance.changed/TAXONOMY_NODE_CHANGED |
| También la usan | FT-IA-04, FT-PLT-02, FT-PLT-03, FT-PLT-04, FT-PLT-05, FT-PLT-06, FT-PLT-07, FT-PLT-09 |
Request
{
"decision": "APPROVE",
"comment": "Revisado contra la guía de familias de cocina"
}
Response · 202
{
"success": true,
"data": {
"requestId": "req-c90d17",
"status": "ACCEPTED",
"changeRequestId": "chg-2a71c4",
"receiptUrl": "/api/v2/catalog-receipts/req-c90d17"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 403 | AUTHORIZATION_ERROR | Quien llama no puede aprobar ese tipo de objeto o es quien pidió la solicitud |
| 409 | NOT_EDITABLE_IN_STATUS | La solicitud ya se decidió, se aplicó o venció |
| 409 | VERSION_CONFLICT | Algún objeto cambió desde que se pidió: la solicitud queda en CONFLICTO y hay que pedirla otra vez |
| 422 | VALIDATION_ERROR | Un rechazo llega sin motivo |
GET /api/v2/catalog-receipts/{requestId} · Recibo de una escritura del catálogo
| Campo | Valor |
|---|---|
| API | API-01-034 · MS-01 Catálogo |
| Para qué | Dice en qué quedó una escritura confirmada: pendiente de aprobar, aplicada, rechazada, en conflicto o vencida, y qué pasó con cada objeto (con su ID nuevo y su versión). |
| En esta épica | El recibo de cualquier escritura del catálogo |
| Quién la llama | BFF del portal, MS-15 IA y enriquecimiento |
| Permiso | Quien hizo la operación y los aprobadores del catálogo |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | requestId = req-8e41a0 |
| También la usan | FT-PLT-07 |
Request
null
Response · 200
{
"success": true,
"data": {
"requestId": "req-8e41a0",
"status": "DONE",
"changeRequestId": "chg-2a71c4",
"finishedAt": "2027-01-12T18:02:11Z",
"items": [
{
"objectType": "ATTRIBUTE",
"objectId": "ATR-0003001",
"result": "APPLIED",
"version": 1
}
]
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 404 | NOT_FOUND | No existe el recibo o no es de quien llama |
POST /internal/governance/bulk-load/{coleccion} · Carga de la migración
| Campo | Valor |
|---|---|
| API | API-01-053 · MS-01 Catálogo |
| Para qué | MS-03 carga por lotes lo que se migra de P360: conserva cada ID de P360, actualiza si la llave ya es del mismo objeto, no publica eventos y, al terminar cada colección, deja la secuencia de ID en el máximo migrado más uno y calcula las vistas efectivas. |
| En esta épica | La carga de la migración con los ID de P360 |
| 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 |
| Parámetros | coleccion = taxonomy_nodes |
| Escribe en | attributes, attribute_groups, lovs, lov_values, taxonomies, taxonomy_nodes, template_views, reference_table_defs, reference_tables, governance_rules, categories, brands, id_sequences |
| También la usan | FT-CAT-01, FT-MIG-02, FT-PLT-02, FT-PLT-03, FT-PLT-04, FT-PLT-06, FT-REF-01, FT-REF-02 |
Request
{
"runId": "mig-run-0007",
"batch": 12,
"documents": [
{
"_id": "EU4-0412",
"taxonomy": "PRODUCT",
"level": 4,
"parentId": "EU3-0398",
"name": {
"es": "Licuadoras"
},
"keywords": [
"licuadora",
"blender"
],
"status": "ACTIVE",
"attributeBindings": [],
"legacy": {
"owner": "P360"
}
}
]
}
Response · 200
{
"success": true,
"data": {
"runId": "mig-run-0007",
"batch": 12,
"upserted": 1,
"rejected": 0,
"items": [
{
"_id": "EU4-0412",
"result": "CREATED"
}
],
"sequenceAfterLoad": {
"TEMPLATE_NODE:EU4": "EU4-4087"
}
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 409 | IMMUTABLE_ID | La llave ya existe y es de otro tipo de objeto: el registro se rechaza y va a cuarentena de MS-03 |
| 422 | VALIDATION_ERROR | Un registro no cumple el modelo (sin padre, lista inactiva, tipo desconocido) |
| 409 | IDEMPOTENCY_MISMATCH | El mismo lote llega otra vez con contenido distinto |
GET /api/v2/catalog-permissions · Matriz de permisos del catálogo
| Campo | Valor |
|---|---|
| API | API-01-109 · MS-01 Catálogo |
| Para qué | Muestra la tabla con la que MS-01 decide los permisos de dominio del catálogo: por rol del directorio, qué puede hacer (consultar, proponer, aprobar, mover, desligar, capturar un ID) en cada tipo de objeto y en qué negocios. Se guarda como un diccionario de MS-01 cuya área dueña es Seguridad. |
| En esta épica | La matriz de permisos del catálogo: rol, tipo de objeto, acciones y negocios |
| Quién la llama | BFF del portal |
| Permiso | Seguridad y Gobierno de Producto (consulta) |
| Cabeceras | Authorization, X-Request-Id |
| Parámetros | roleId = GOBIERNO_PRODUCTO, object = ATTRIBUTE |
Request
null
Response · 200
{
"success": true,
"data": {
"matrixVersion": 8,
"version": 3,
"updatedAt": "2027-01-08T16:00:00Z",
"rows": [
{
"roleId": "GOBIERNO_PRODUCTO",
"object": "ATTRIBUTE",
"actions": [
"READ",
"PROPOSE",
"APPROVE",
"CAPTURE_ID"
],
"businesses": [
"MER",
"SUB",
"MKP"
]
}
]
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 403 | AUTHORIZATION_ERROR | Quien llama no es de Seguridad ni de Gobierno de Producto |
POST /api/v2/catalog-permissions/plans · Plan de carga de la matriz de permisos del catálogo
| Campo | Valor |
|---|---|
| API | API-01-110 · MS-01 Catálogo |
| Para qué | Revisa sin escribir la hoja del catálogo de la matriz firmada (rol, tipo de objeto, acciones y negocios): valida contra MS-13 que cada rol exista (API-13-005) y dice qué permisos se agregan, cambian o quitan. Se confirma con API-01-004 y, como todo cambio de permisos, pide aprobación de otra persona. |
| En esta épica | Cargar con vista previa la hoja del catálogo de la matriz firmada |
| Quién la llama | BFF del portal |
| Permiso | Seguridad |
| Cabeceras | Authorization, X-Request-Id, Idempotency-Key, If-Match |
| También la usan | FT-USR-02 |
Request
{
"version": 3,
"matrixVersion": 9,
"rows": [
{
"roleId": "CATEGORY",
"object": "CATEGORY",
"actions": [
"CREATE",
"UPDATE",
"MOVE",
"UNLINK",
"APPROVE"
],
"businesses": [
"MER",
"MKP",
"SUB"
]
},
{
"roleId": "GOBIERNO_PRODUCTO",
"object": "ATTRIBUTE",
"actions": [
"READ",
"PROPOSE",
"APPROVE",
"CAPTURE_ID"
],
"businesses": [
"MER",
"SUB",
"MKP"
]
}
]
}
Response · 200
{
"success": true,
"data": {
"planId": "pln-61f2c8",
"expiresAt": "2027-01-08T16:10:00Z",
"requiresApproval": true,
"summary": {
"rowsAdded": 0,
"rowsChanged": 1,
"rowsRemoved": 0
},
"unknownRoles": [],
"changes": [
{
"roleId": "CATEGORY",
"object": "CATEGORY",
"before": [
"CREATE",
"UPDATE",
"MOVE",
"UNLINK"
],
"after": [
"CREATE",
"UPDATE",
"MOVE",
"UNLINK",
"APPROVE"
]
}
],
"applyUrl": "/api/v2/catalog-plans/pln-61f2c8/apply"
}
}
Errores
| HTTP | Código | Cuándo |
|---|---|---|
| 422 | VALIDATION_ERROR | Un rol no existe en el directorio de MS-13, o una acción o un tipo de objeto no existen |
| 403 | AUTHORIZATION_ERROR | Quien llama no es de Seguridad |
| 409 | VERSION_CONFLICT | La matriz cambió desde que se leyó |
Las que usa y construye otra épica (7)
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-023 | POST /api/v2/structures/{id}/nodes/plans | Ejemplo de plan: el alta de un nodo de plantilla | FT-PLT-05 · Taxonomía de plantillas por familia, metadatos de… |
| API-01-031 | POST /api/v2/catalog-imports | La IA propone por la misma carga que valida la pantalla | FT-PLT-09 · Carga masiva de configuración de plantillas con… |
| API-01-032 | POST /api/v2/catalog-imports/{id}/apply | Aplicar la carga: abre la solicitud con su canal | FT-PLT-09 · Carga masiva de configuración de plantillas con… |
| API-13-001 | GET /internal/identity/permissions?userId= | Los roles y capacidades del usuario, con caché, para decidir los permisos de dominio del catálogo | FT-USR-01 · Identidad y autenticación de usuarios internos… |
| API-13-005 | GET /api/v2/roles | Validar que los roles de la matriz existan en el directorio | FT-USR-02 · Matriz de roles y permisos por módulo, acción, negocio y… |
| API-14-005 | POST /internal/notifications/messages | Avisar a aprobadores y solicitantes | FT-RAC-05 · Estatus del producto y motivos visibles para seller y… |
| API-05-001 | GET /api/v2/audit/entities/{entityType}/{entityId}/events | La historia por campo de un objeto del catálogo | FT-ARQ-02 · Bitácora inmutable y versionado de producto, plantilla y… |
6. Eventos
Publica
| Evento | Cuándo | Quién lo consume |
|---|---|---|
catalog.governance.changed/TEMPLATE_CHANGED | Se aprueba el alta o el cambio de una plantilla, también las que propone la IA | FT-ARQ-02, FT-PLT-08 |
Consume
| Evento | Para qué | Quién lo publica |
|---|---|---|
catalog.governance.changed/TEMPLATE_CHANGED | MS-05 guarda en la bitácora el antes y el después de cada campo, con el actor, el canal y la solicitud | esta misma épica |
catalog.governance.changed/TEMPLATE_CHANGED | MS-02 refresca su copia del catálogo y la captura ya puede ofrecer la plantilla | 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 |
|---|---|---|---|
governance_change_requests | MS-01 | Cada solicitud de cambio del catálogo: qué objetos toca, el antes y el después por campo, el canal (pantalla, carga, API, IA o migración), quién la pidió y quién la decidió, su estado (pendiente, aprobada, rechazada, aplicada, en conflicto o vencida) y su recibo. | escribe |
taxonomy_nodes | MS-01 | Plantillas y nodos de grupo de artículo, con la configuración de atributos de cada plantilla. | escribe |
template_views | MS-01 | La vista efectiva ya resuelta por plantilla y negocio: qué atributos pide y cuáles son obligatorios. | 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 |
taxonomies | MS-01 | Los árboles: plantillas, grupos de artículo y sitios web. | lee |
taxonomy_nodes | MS-01 | Plantillas y nodos de grupo de artículo, con la configuración de atributos de cada plantilla. | lee |
attributes | MS-01 | Cada atributo: tipo, lista, restricciones, grupos e identificadores externos. | lee |
8. Historias que cubre
| Historia | Prioridad | Cómo la cubre |
|---|---|---|
| FT-PLT-01·H1 · IDs estables | P1 | pasos 1, 2, 11; flujo «Migración con los ID de P360 y su historia»; API-01-023, API-01-053 |
| FT-PLT-01·H2 · Nada surte efecto sin aprobación | P1 | pasos 4, 5, 6, 7, 8, 9, 10, 11; flujo «Cambios que llegan por carga masiva o por la IA», «Si el aprobador rechaza»; API-01-004, API-01-101, API-01-102, API-01-103 |
| FT-PLT-01·H3 · Historia por campo | P2 | pasos 12, 13; flujo «Migración con los ID de P360 y su historia»; API-05-001 |
| FT-PLT-01·H4 · Sólo roles autorizados | P2 | pasos 3; API-13-001, API-01-109, API-01-110, API-13-005 |
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-01-1. Toda escritura de lo que define la plantilla (atributos, listas, grupos, árbol, metadatos y configuración), venga de pantalla, carga masiva, API o IA, queda como solicitud en una colección propia de MS-01 y surte efecto sólo cuando otra persona con permiso la aprueba. Nadie aprueba lo que pidió. Por qué: La ERF 1.1 §3.4 pide que nada surta efecto sin aprobación y DEC-ARQ-12 lo metió al alcance. El plan dura minutos y no sirve para esperar una aprobación de días; guardar la solicitud aparte del objeto evita versiones a medias en el catálogo vigente. Se apoya en DEC-ARQ-12, DEC-PLT-05, PD-01.
- D-PLT-01-2. Qué pide aprobación lo fija una política de MS-01 por tipo de objeto. Lo que el PIM no gobierna no la pide: los catálogos que manda SAP (API-01-050 a 052) y la carga de la migración (API-01-053) se aplican directo con su recibo. Cada diccionario y cada tipo de regla dicen en su definición si la piden (FT-REF-01 y FT-PLT-07). Por qué: SAP es el dueño de sus catálogos: aprobar en el PIM lo que SAP ya decidió sólo crea desfases. Una sola política evita que cada pantalla invente su regla. Se apoya en DUD-21, DUD-23, DEC-ARQ-12.
- D-PLT-01-3. Los ID de P360 se conservan y ningún ID de plantilla, atributo o lista se modifica. Los nuevos salen de id_sequences con el formato de hoy (EU{nivel+1}-{número} en plantillas) y se asignan al aprobar; capturar un ID al crear exige un permiso propio. Si una carga trae un ID existente, actualiza cuando es el mismo tipo de objeto y falla con ID_ALREADY_EXISTS si es otro. Por qué: Entrada Única, Foro, SAP y la tienda resuelven sus referencias con esos ID; cambiarlos exigiría equivalencias en cada consumidor. Se apoya en PD-16, DEC-PLT-06, DUD-18.
- D-PLT-01-4. La historia por campo la guarda sólo MS-05, a partir de los eventos de catalog.governance.changed, que llevan el antes y el después, el actor, el canal y la solicitud. MS-01 no lleva bitácora propia. Lo migrado empieza su historia en la carga: la de P360 no se migra. Por qué: Un dueño para la bitácora. P360 no guarda el valor anterior ni el nuevo, así que no hay historia que traer. Se apoya en DEC-ARQ-09, PD-05, ADR-12.
- D-PLT-01-5. Los permisos de dominio del catálogo los decide MS-01: cruza los roles del usuario que da el directorio (API-13-001, con caché) con su matriz del catálogo (rol, tipo de objeto, acción y negocio), que Seguridad carga de la hoja firmada (API-01-110) y que se guarda como un diccionario de MS-01. El BFF sólo decide los de pantalla. Sin matriz firmada no se concede ningún permiso por suposición: la operación se niega. Por qué: Decisión 19 del backend compartido que adopta ADR-12: los permisos de dominio viven en el servicio dueño con los roles del directorio. La matriz no se inventa; la trae FT-USR-02. Se apoya en ADR-12, DEC-PLT-09, DUD-22.
- D-PLT-01-6. Hasta el corte del catálogo en R1, P360 es la fuente: MS-01 sólo recibe la carga de MS-03 y responde WRITE_DISABLED a toda escritura de pantalla. Desde el corte, P360 congela sus plantillas y el PIM es la única fuente. Por qué: Escribir en los dos lados es una doble escritura que sólo cubre una parte del catálogo; congelar cuesta poco y es lo que recomienda el diseño (opción A). Se apoya en PD-12, DEC-PLT-13.
- D-PLT-01-7. Una solicitud pendiente vence a los 30 días sin decisión, con recordatorio a los 23. Al aprobar, MS-01 vuelve a validar contra la versión de cada objeto y, si alguno cambió, la deja en conflicto sin aplicar nada. Por qué: Nunca se aplica un cambio sobre una base distinta de la que vio el aprobador, y las solicitudes olvidadas no se acumulan. Se apoya en DEC-PLT-05.
Qué falta decidir
| ID | Qué falta |
|---|---|
| DUD-22 | Seguridad con Gobierno de Producto firman la matriz: qué rol propone, quién captura un ID y quién aprueba cada tipo de objeto. |
| PD-16 | Arquitectura con Gobierno de Producto ratifica que ningún ID se modifica (propuesta del 17-oct); un atributo mal nombrado se corrige con uno nuevo. |
| DUD-18 | Gobierno de Producto fija qué campos definen «el mismo objeto» por tipo; aquí se usa el tipo de objeto más su ID. |
| PD-12 | Arquitectura con Gobierno de Datos confirma el orden de corte; aquí se asume congelar plantillas en P360 desde el corte de R1. |
Fuentes
- [D]
trazabilidad/features/FT-PLT-01-fundamentos-de-gobierno-de-plantillas.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.