Skip to content

Commit 4bf8857

Browse files
committed
Merge branch 'codex/sanitize-client-error-observability'
# Conflicts: # docs/architecture/adrs/index.md # docs/governance/construction/ddd-design/03-identity-context.md # docs/governance/construction/ddd-design/04-authorization-context.md # src/apps/ums.api/Ums.Infrastructure/Persistence/Seeders/AuthorizationDevDataSeeder.cs
2 parents 7701eb6 + 77a9d16 commit 4bf8857

289 files changed

Lines changed: 22221 additions & 1677 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.bmad-core/rules/global-rules.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,6 @@ This document establishes the mandatory rule configuration for the AI agent harn
152152
* **Scope**: `architect`, `dev`
153153
* **Trigger Condition**: Any dependency update, stack modernization, tooling change, or agent configuration update.
154154
* **Instruction**: Once a project version is adopted, it must be pinned explicitly in code and documented consistently in agent configs, architecture docs, and contribution guidance. Agent descriptions, prompts, and repo-level instructions must be updated whenever the stack changes materially.
155+
156+
## UI Guidelines
157+
* **UI Rule - No Raw GUIDs**: Raw GUIDs must NEVER be exposed or rendered in the User Interface (UI), unless explicitly requested. Always use semantic representations (e.g. Code, Name) instead. See ADR 0065 for details.

docs/MASTER_INDEX.es.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Especificaciones de Ingeniería y Ciclo de Vida del Producto para el User Manage
3434
- [Diseño de Base de Datos ER](./architecture/blueprints-es/database-design-er.md)
3535
- [Formatos de Exportación ER](./architecture/blueprints-es/er-export-formats.md)
3636
- [Arquitectura de Librerías Shell](./architecture/blueprints-es/shell-library-architecture.md)
37+
- [Arquitectura de Notificaciones y Feedback](./architecture/blueprints-es/notification-feedback-architecture.md)
3738
- [Portal de Arquitectura](./architecture/index.es.md)
3839

3940
### Fase 04 -- Construccion y Diseño de Dominio
@@ -52,9 +53,10 @@ Especificaciones de Ingeniería y Ciclo de Vida del Producto para el User Manage
5253
- [Flujos Cross-Contexto](./governance/construction/ddd-design/10-cross-context-flows.md)
5354
- [Primitivas DDD](./governance/construction/ddd-design/11-ddd-primitives.md)
5455
- [ADR-0054: Aislamiento de Librerías Shell](./architecture/adrs/0054-shell-library-isolation.md)
55-
- [ADR-0061: Patrón Execution Context Accessor](./architecture/adrs/0061-execution-context-accessor.md) _(⬆ candidato Evolith)_
56-
- [ADR-0062: Configuración Serilog Segura de PII](./architecture/adrs/0062-pii-safe-serilog-configuration.md) _(⬆ candidato Evolith)_
57-
- [ADR-0063: Middleware de Clave de Idempotencia](./architecture/adrs/0063-idempotency-middleware.md) _(⬆ candidato Evolith)_
56+
- [ADR-0061: Patrón Execution Context Accessor](./architecture/adrs/0061-execution-context-accessor.md) _(candidato Evolith)_
57+
- [ADR-0062: Configuración Serilog Segura de PII](./architecture/adrs/0062-pii-safe-serilog-configuration.md) _(candidato Evolith)_
58+
- [ADR-0063: Middleware de Clave de Idempotencia](./architecture/adrs/0063-idempotency-middleware.md) _(candidato Evolith)_
59+
- [ADR-0066: Contrato de Errores Accionables](./architecture/adrs/0066-actionable-user-error-contract.es.md) _(candidato Evolith)_
5860
- [Índice ADR](./architecture/adrs/index.md)
5961
- [Índice de Patrones Canónicos](./architecture/artifacts/canonical-patterns/index.md)
6062
- **Guías de Desarrollo de Librerías Shell**[Visión General](./architecture/shell-libraries/README.md) · [DDD](./architecture/shell-libraries/ddd.md) · [Factory](./architecture/shell-libraries/factory.md) · [AOP](./architecture/shell-libraries/aop.md) · [Bootstrapper](./architecture/shell-libraries/bootstrapper.md) · [Uso Combinado](./architecture/shell-libraries/combined-usage.md) · [Aspectos del API](./architecture/shell-libraries/api-aspects.es.md)

docs/MASTER_INDEX.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Product Lifecycle and Engineering Specifications for the User Management System
3737
- [Interactive ER Viewer](./architecture/blueprints/interactive-er-viewer.html)
3838
- [Service Entity Map](./architecture/blueprints/service-entity-map.md)
3939
- [Shell Library Architecture](./architecture/blueprints/shell-library-architecture.md)
40+
- [Notification and Feedback Architecture](./architecture/blueprints/notification-feedback-architecture.md)
4041
- [Architecture Overview](./architecture/overview.md)
4142
- [Architecture Portal](./architecture/index.md)
4243
- [Traceability Matrix (FS → ADR → TE)](./architecture/traceability-matrix.md)
@@ -65,9 +66,10 @@ Product Lifecycle and Engineering Specifications for the User Management System
6566
- [ADR-0054: Shell Library Isolation](./architecture/adrs/0054-shell-library-isolation.md) _(amended 2026-05-24 — scope extended to AOP + Bootstrapper, dep graph corrected)_
6667
- [ADR-0059: Single API Tier Decision](./architecture/adrs/0059-single-api-tier-decision.md)
6768
- [ADR-0060: AOP Cross-Cutting Concern Strategy](./architecture/adrs/0060-aop-cross-cutting-concern-strategy.md)
68-
- [ADR-0061: Execution Context Accessor Pattern](./architecture/adrs/0061-execution-context-accessor.md) _(⬆ Evolith candidate)_
69-
- [ADR-0062: PII-Safe Serilog Configuration](./architecture/adrs/0062-pii-safe-serilog-configuration.md) _(⬆ Evolith candidate)_
70-
- [ADR-0063: Idempotency Key Middleware](./architecture/adrs/0063-idempotency-middleware.md) _(⬆ Evolith candidate)_
69+
- [ADR-0061: Execution Context Accessor Pattern](./architecture/adrs/0061-execution-context-accessor.md) _(Evolith candidate)_
70+
- [ADR-0062: PII-Safe Serilog Configuration](./architecture/adrs/0062-pii-safe-serilog-configuration.md) _(Evolith candidate)_
71+
- [ADR-0063: Idempotency Key Middleware](./architecture/adrs/0063-idempotency-middleware.md) _(Evolith candidate)_
72+
- [ADR-0066: Actionable User Error Contract](./architecture/adrs/0066-actionable-user-error-contract.md) _(Evolith candidate)_
7173
- [ADR Registry](./architecture/adrs/index.md)
7274
- **Shell Library Developer Guides**[Overview](./architecture/shell-libraries/README.md) · [DDD](./architecture/shell-libraries/ddd.md) · [Factory](./architecture/shell-libraries/factory.md) · [AOP](./architecture/shell-libraries/aop.md) · [Bootstrapper](./architecture/shell-libraries/bootstrapper.md) · [Combined Usage](./architecture/shell-libraries/combined-usage.md) · [API Aspects](./architecture/shell-libraries/api-aspects.md)
7375
- [Design Decisions & Gaps](./governance/construction/ddd-design/12-design-decisions.md)
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# ADR-0066: Contrato de Errores Accionables para Usuarios y Diagnostico Correlacionado
2+
3+
**Estado:** Aceptado
4+
**Fecha:** 2026-05-26
5+
**Responsable:** Arquitectura
6+
**Disposicion Evolith:** Propuesto para adopcion como estandar universal de Evolith
7+
**Relacionados:**
8+
- [ADR-0053: Observabilidad con OpenTelemetry](./0053-opentelemetry-observability.md)
9+
- [ADR-0055: Patron Hibrido GraphQL/REST](./0055-graphql-rest-hybrid-api.md)
10+
- [ADR-0057: Estado con Zustand y TanStack Query](./0057-zustand-tanstack-query-state.md)
11+
- [ADR-0061: Execution Context Accessor](./0061-execution-context-accessor.es.md)
12+
- [ADR-0062: Configuracion Serilog Segura de PII](./0062-pii-safe-serilog-configuration.es.md)
13+
- [Arquitectura de Notificaciones y Feedback](../blueprints-es/notification-feedback-architecture.md)
14+
15+
---
16+
17+
## Contexto
18+
19+
Una revision de calidad del flujo de registro de modulos de System Suite revelo dos modos de falla opuestos:
20+
21+
1. Mensajes tecnicos del API, detalles de excepcion y datos relacionados con la pila podian llegar al navegador.
22+
2. Al suprimir todos los mensajes del backend, las fallas esperadas de validacion quedaron demasiado genericas para que el usuario corrigiera la entrada.
23+
24+
Por ejemplo, un usuario que envia una descripcion de modulo mayor al limite permitido debe saber como corregir sus datos. Ese usuario no debe ver un namespace, nombre de clase, detalle de base de datos, mensaje de excepcion ni stack trace. El equipo de soporte si necesita una referencia que localice el evento tecnico completo en Serilog y Grafana Loki.
25+
26+
La decision aplica a todos los comandos iniciados por usuarios en UMS, no solo al registro de modulos.
27+
28+
## Decision
29+
30+
UMS adopta un contrato de errores con dos canales:
31+
32+
1. **Canal de feedback para usuario:** expone solo informacion de negocio o validacion aprobada y accionable.
33+
2. **Canal de diagnostico:** conserva detalles tecnicos en logs estructurados y telemetria, correlacionados mediante un identificador de error generado por el servidor.
34+
35+
### 1. Clasificacion de Errores
36+
37+
| Clase de error | Ejemplo | Contenido visible para usuario | Logging tecnico |
38+
|---|---|---|---|
39+
| Falla de validacion | Longitud maxima excedida | Correccion accionable y codigo de seguimiento | Evento estructurado opcional |
40+
| Conflicto de negocio | Codigo de modulo duplicado | Razon segura de negocio y codigo de seguimiento | Evento estructurado cuando aporte valor operativo |
41+
| Autorizacion o autenticacion | Acceso rechazado | Declaracion segura de acceso y codigo de seguimiento | Evento estructurado con tratamiento de seguridad |
42+
| Infraestructura o falla inesperada | Base de datos, resolver, excepcion no controlada | Guia generica de reintento y codigo de seguimiento | Excepcion completa sanitizada con correlacion |
43+
44+
### 2. Payload Publico de Error
45+
46+
Las fallas de comandos REST usan Problem Details RFC 7807. El payload publico puede incluir:
47+
48+
```json
49+
{
50+
"type": "https://httpstatuses.io/422",
51+
"title": "Validation Error",
52+
"status": 422,
53+
"detail": "No se pudo completar la operacion porque existen campos invalidos.",
54+
"userMessage": "No se pudo registrar el modulo porque el campo Codigo tiene un formato invalido. Use solo letras, numeros y guion bajo, por ejemplo REPORTS_01. Valor ingresado: DDDD-!.",
55+
"errorCode": "validation.invalid_format",
56+
"messageKey": "system_suite.module.code_invalid_format",
57+
"messageParameters": { "invalidValue": "DDDD-!" },
58+
"errorId": "0cd26dd6-d50e-4b3c-a662-8098a87569a4",
59+
"traceId": "<distributed-trace-id>"
60+
}
61+
```
62+
63+
Reglas:
64+
65+
- `errorId` es un GUID generado por el servidor una sola vez por solicitud fallida. Es obligatorio en la respuesta, el header (`X-Error-Id`) y el evento Serilog correspondiente.
66+
- `traceId` y `X-Correlation-Id` permanecen como identificadores de trazabilidad distribuida y no reemplazan a `errorId`.
67+
- `userMessage`, cuando esta presente, es explicitamente seguro para presentacion.
68+
- `errorCode`, `messageKey` y `messageParameters` son el contrato objetivo para clientes localizados.
69+
- `detail` nunca debe contener stack traces, tipos de excepcion, namespaces, rutas de codigo fuente, sentencias SQL, tokens, secretos ni PII.
70+
- Los clientes no deben mostrar `detail` arbitrario, mensajes GraphQL crudos ni mensajes nativos de excepcion. Solo muestran campos aprobados o un fallback local.
71+
72+
La implementacion actual de UMS produce `userMessage` mediante recursos de localizacion del API seleccionados por `X-Language` o `Accept-Language`. El soporte estable de `messageKey` sigue siendo la evolucion para clientes mas ricos.
73+
74+
### 3. Limite GraphQL
75+
76+
GraphQL se usa para lecturas segun ADR-0055. Los errores GraphQL expuestos al cliente usan mensajes genericos seguros localizados y transportan `errorId`. Las excepciones de resolvers se registran mediante Serilog con el mismo `errorId`, pero no se serializan al navegador.
77+
78+
### 4. Observabilidad y Logging
79+
80+
- Cada respuesta REST o GraphQL fallida obtiene un nuevo GUID `errorId` generado por el servidor.
81+
- Serilog registra `ErrorId` para fallas esperadas y excepciones sanitizadas completas con `ErrorId` para fallas inesperadas; Loki consulta esa propiedad.
82+
- `CorrelationId` y `TraceId` continuan enlazando operaciones distribuidas independientemente del `ErrorId` visible para soporte.
83+
- Las reglas de logging seguro de PII de ADR-0062 aplican antes de cualquier sink.
84+
- Un especialista de soporte usa el codigo visible para localizar el evento detallado del backend.
85+
86+
### 5. Ciclo de Vida de la Notificacion
87+
88+
El feedback para usuario se entrega mediante el mecanismo centralizado de notificaciones:
89+
90+
- El feedback de validacion y negocio es accionable y puede incluir el codigo de seguimiento.
91+
- La expiracion automatica del toast elimina solo la presentacion efimera; el historial puede permanecer disponible.
92+
- El descarte manual mediante el control de cierre es una accion explicita del usuario y elimina la entrada correspondiente del estado activo de notificaciones.
93+
94+
### 6. Ejemplos Requeridos de Mensaje
95+
96+
| Categoria | Ejemplo seguro visible para usuario |
97+
|---|---|
98+
| Validacion | `No se pudo registrar el modulo porque el campo Codigo tiene un formato invalido. Use solo letras, numeros y guion bajo, por ejemplo REPORTS_01. Valor ingresado: DDDD-!.` |
99+
| Regla de negocio | `No se pudo registrar el modulo porque ya existe otro modulo con el mismo Codigo. Ingrese un codigo diferente.` |
100+
| Autorizacion | `No se pudo completar la operacion porque no tiene permisos suficientes. Solicite acceso al administrador.` |
101+
| Inesperado | `No se pudo completar la operacion debido a un error inesperado. Intente nuevamente mas tarde.` |
102+
103+
Cada falla mostrada agrega: `Si necesitas mas detalles, consulta con el administrador e indica este ID de error: {errorId}.`
104+
105+
## Alternativas Rechazadas
106+
107+
### Mostrar todos los valores `detail` del backend
108+
109+
Rechazada. Es conveniente, pero permite que detalles de implementacion o PII escapen cuando un endpoint esta mal configurado.
110+
111+
### Mostrar solo mensajes genericos
112+
113+
Rechazada. Impide que los usuarios corrijan condiciones esperadas de negocio o validacion, aumentando reintentos y solicitudes de soporte.
114+
115+
### Mostrar detalles de pila solo en desarrollo o QA
116+
117+
Rechazada. QA y ambientes compartidos siguen siendo superficies de usuario y pueden contener datos similares a produccion.
118+
119+
## Consecuencias
120+
121+
### Positivas
122+
123+
- Los usuarios reciben informacion suficiente para corregir fallas esperadas y seguras.
124+
- Los diagnosticos tecnicos permanecen disponibles para soporte sin exponerse en la interfaz.
125+
- REST, GraphQL, logging y notificaciones frontend comparten un contrato auditable.
126+
- El contrato puede evolucionar desde texto `userMessage` servido por backend hacia claves de mensaje localizadas en cliente.
127+
128+
### Compromisos
129+
130+
- Los limites del backend deben clasificar que fallas son seguras para publicar.
131+
- Nuevas reglas de validacion requieren texto seguro de presentacion o metadata de localizacion.
132+
- Las pruebas deben cubrir tanto salida accionable como ausencia de filtracion tecnica.
133+
134+
## Mapeo de Implementacion
135+
136+
| Preocupacion | Implementacion UMS |
137+
|---|---|
138+
| Mapeo seguro REST | `Ums.Presentation/Extensions/ResultExtensions.cs` |
139+
| Generacion de Error ID | `Ums.Presentation/Extensions/UserFacingErrorContext.cs` |
140+
| Excepciones no controladas | `Ums.Presentation/Middleware/GlobalExceptionHandler.cs` |
141+
| Sanitizacion GraphQL | `Ums.Presentation/GraphQL/SafeGraphQlErrorFilter.cs` |
142+
| Recursos de localizacion | `Ums.Globalization/Resources/{language}/domain-errors.json` |
143+
| Extraccion segura web | `src/application/errors/http-error.ts` |
144+
| Composicion de notificacion | `src/application/hooks/use-notified-mutation.ts` |
145+
| Descarte manual | `src/application/stores/notification.store.ts` y `src/presentation/shared/components/ToastQueue.tsx` |
146+
147+
## Requisitos de Verificacion
148+
149+
- Las pruebas de integracion afirman campos de validacion accionables, `errorId` generado por servidor, header `X-Error-Id` coincidente y `traceId`.
150+
- Las pruebas de seguridad afirman que stack traces, nombres de excepcion y mensajes internos crudos estan ausentes.
151+
- Las pruebas frontend afirman que solo mensajes aprobados y codigos de seguimiento se renderizan.
152+
- Las pruebas de notificaciones afirman que el cierre manual elimina la notificacion seleccionada.
153+
154+
---
155+
156+
**[Registro ADR](./index.md)** | **[Blueprint de Notificaciones y Feedback](../blueprints-es/notification-feedback-architecture.md)**

0 commit comments

Comments
 (0)