- Archived historical documents for DTO design and naming conventions. - Added normative documentation for HTTP request flow and module boundaries. - Introduced testing guidelines for backend layers. - Updated onboarding module documentation and clarified onboarding requirements. - Deprecated backend prompt base and prompt auth documents. - Adjusted paths in testing documentation for consistency.
3.0 KiB
Flujo HTTP y entrada a Application
Estado: NORMATIVO. Define la frontera Express/Application para código nuevo y refactors futuros.
Flujo normal
RequestSchema
↓ validateRequest
RequestDTO
↓
Controller
↓
UseCase({ dto, context })
↓
I<Input>Mapper
↓
Value Objects / Application Props
↓
Application services / Domain
Este es el patrón de CreateCustomer, CreateProforma y CompleteInitialOnboarding.
Routes y guards
Las routes registran endpoints, guards, validateRequest, obtienen el internal del propio módulo y pueden construir controllers ligeros. No crean repositories, transaction managers, servicios de Application, Value Objects ni lógica de negocio.
Los guards viven en routes: requireAuthenticatedGuard(), requireCompanyContextGuard(), forbidQueryFieldGuard(...) y validateRequest(...). Algunos controllers históricos de customers y proformas aún registran guards; es deuda de alineación, no una segunda norma para código nuevo.
El schema vive junto al DTO. La route ejecuta validateRequest(SomeRequestSchema, "body" | "params" | "query"); el controller no vuelve a ejecutar Zod sobre esa entrada validada.
Controllers
Un controller lee request validada, obtiene contexto HTTP autenticado, invoca el caso de uso y traduce Result a HTTP. No crea Value Objects, no ejecuta InputMappers, no resuelve servicios de otros módulos y no contiene lógica de negocio.
Los identificadores controlados por el servidor (accountId, companyId, tenantId, actorId) no forman parte del RequestDTO ni llegan de body, query o path. Por ejemplo, onboarding usa dto = req.body, obtiene accountId = req.user.userId y ejecuta useCase.execute({ dto, accountId }).
InputMapper de Application
Cuando existe transformación de transporte a Application, el nombre preferido es I<CreateX>InputMapper / CreateXInputMapper. Recibe DTO y contexto, devuelve Result<Props | Params> y puede crear Value Objects, adaptar primitivas, convertir null/undefined a Maybe y acumular ValidationErrorDetail en una ValidationErrorCollection cuando la operación necesita varios errores de validación.
No conoce Express, repositories ni HTTP, y no construye agregados salvo un diseño explícito distinto. Se inyecta nominalmente en el use case desde DI.
RequestMapper opcional
Un RequestMapper solo se usa cuando tiene una responsabilidad HTTP propia, por ejemplo combinar body, params, query o contexto para producir un Command. IssueProformaByIdRequestMapper es el ejemplo actual.
No se crea un RequestMapper solo para transformar snake_case a camelCase si Application volverá a transformar los mismos datos.
Result y Maybe
Los InputMappers, servicios, use cases y repositories usan Result para fallos esperables según sus contratos. La frontera DTO conserva undefined y null; Application decide Maybe.some() o Maybe.none(). Las responses pueden materializar ausencia como null conforme a su DTO.
Para reglas de schema, estructura y naming, véase DTOs y schemas.