workspace-v1/core/orchestration/impactos/IMPACTO-CAMBIOS-API.md
rckrdmrd 66161b1566 feat: Workspace-v1 complete migration with NEXUS v3.4
Sistema NEXUS v3.4 migrado con:

Estructura principal:
- core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles)
- core/catalog: Catalogo de funcionalidades reutilizables
- shared/knowledge-base: Base de conocimiento compartida
- devtools/scripts: Herramientas de desarrollo
- control-plane/registries: Control de servicios y CI/CD
- orchestration/: Configuracion de orquestacion de agentes

Proyectos incluidos (11):
- gamilit (submodule -> GitHub)
- trading-platform (OrbiquanTIA)
- erp-suite con 5 verticales:
  - erp-core, construccion, vidrio-templado
  - mecanicas-diesel, retail, clinicas
- betting-analytics
- inmobiliaria-analytics
- platform_marketing_content
- pos-micro, erp-basico

Configuracion:
- .gitignore completo para Node.js/Python/Docker
- gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git)
- Sistema de puertos estandarizado (3005-3199)

Generated with NEXUS v3.4 Migration System
EPIC-010: Configuracion Git y Repositorios
2026-01-04 03:37:42 -06:00

16 KiB

IMPACTO DE CAMBIOS EN API

Version: 1.0.0 Fecha: 2025-12-08 Prioridad: OBLIGATORIA - Consultar antes de modificar endpoints Sistema: SIMCO + CAPVED


PROPOSITO

Documentar el impacto de modificar endpoints REST (Controllers), rutas, metodos HTTP, y contratos de API en el sistema.


1. CLASIFICACION DE CAMBIOS API

╔══════════════════════════════════════════════════════════════════════╗
║  TIPOS DE CAMBIOS EN API                                             ║
╠══════════════════════════════════════════════════════════════════════╣
║                                                                       ║
║  BREAKING CHANGES (⚠️ ROMPEN CLIENTES):                              ║
║  • Eliminar endpoint                                                  ║
║  • Cambiar ruta de endpoint                                          ║
║  • Cambiar metodo HTTP                                               ║
║  • Eliminar campo de response                                        ║
║  • Cambiar tipo de campo en response                                 ║
║  • Agregar campo requerido a request                                 ║
║  • Cambiar formato de error                                          ║
║                                                                       ║
║  NON-BREAKING CHANGES (✅ COMPATIBLES):                              ║
║  • Agregar endpoint nuevo                                            ║
║  • Agregar campo opcional a request                                  ║
║  • Agregar campo a response                                          ║
║  • Agregar nuevo codigo de error                                     ║
║  • Mejorar mensaje de error                                          ║
║                                                                       ║
╚══════════════════════════════════════════════════════════════════════╝

2. CAMBIOS EN RUTAS (BREAKING)

2.1 Cambiar Ruta de Endpoint

// ANTES
@Get('users/by-email/:email')

// DESPUES
@Get('users/search/email/:email')

Impacto:

Componente Impacto Accion Requerida
Frontend Service ROMPE Actualizar URL
Frontend Hooks ROMPE Actualizar llamadas
Documentacion Desactualizada Actualizar
Clientes externos ROMPE Notificar + migrar
Tests e2e ROMPE Actualizar URLs

Proceso de Migracion:

OPCION A: Migracion Inmediata (proyectos internos)
═══════════════════════════════════════════════════════════════
1. Actualizar Frontend primero (cambiar URL)
2. Actualizar Backend (cambiar ruta)
3. Deploy coordinado

OPCION B: Deprecacion Gradual (APIs publicas)
═══════════════════════════════════════════════════════════════
1. Agregar nueva ruta (mantener vieja)
2. Marcar vieja como @Deprecated
3. Notificar clientes
4. Periodo de gracia (30-90 dias)
5. Eliminar ruta vieja

Implementacion Deprecacion:

// Mantener ambas rutas temporalmente
@Get('users/by-email/:email')
@ApiOperation({
    summary: 'Buscar por email (DEPRECATED)',
    deprecated: true,
    description: 'Use GET /users/search/email/:email instead'
})
async findByEmailDeprecated(@Param('email') email: string) {
    return this.findByEmail(email);
}

@Get('users/search/email/:email')
@ApiOperation({ summary: 'Buscar usuario por email' })
async findByEmail(@Param('email') email: string) {
    return this.userService.findByEmail(email);
}

2.2 Cambiar Prefijo de Controller

// ANTES
@Controller('products')

// DESPUES
@Controller('catalog/products')

Impacto: TODOS los endpoints del controller cambian de ruta.

ANTES:
GET  /api/products
POST /api/products
GET  /api/products/:id

DESPUES:
GET  /api/catalog/products
POST /api/catalog/products
GET  /api/catalog/products/:id

Checklist:

[ ] 1. Buscar en frontend: grep -rn "/products" apps/
[ ] 2. Actualizar TODOS los services que usan estos endpoints
[ ] 3. Actualizar tests e2e
[ ] 4. Actualizar documentacion
[ ] 5. Verificar Swagger refleja cambios

3. CAMBIOS EN METODO HTTP (BREAKING)

Cambiar Metodo

// ANTES: Actualizar con POST
@Post(':id/update')
async update() {}

// DESPUES: Actualizar con PUT (RESTful correcto)
@Put(':id')
async update() {}

Impacto Frontend:

// ANTES
const response = await api.post(`/users/${id}/update`, data);

// DESPUES
const response = await api.put(`/users/${id}`, data);

Checklist:

[ ] 1. Identificar todos los lugares que llaman al endpoint
[ ] 2. Actualizar metodo HTTP en frontend service
[ ] 3. Actualizar tests
[ ] 4. Si API publica: periodo de deprecacion

4. CAMBIOS EN REQUEST DTO

4.1 Agregar Campo Requerido (BREAKING)

// ANTES
export class CreateOrderDto {
    productId: string;
    quantity: number;
}

// DESPUES - Nuevo campo requerido
export class CreateOrderDto {
    productId: string;
    quantity: number;
    @IsNotEmpty()
    deliveryAddress: string;  // ← BREAKING: requerido
}

Impacto:

Componente Impacto Accion
Frontend Form ROMPE Agregar campo
Frontend Zod ROMPE Agregar validacion
Clientes existentes ROMPE Falla validacion
Tests ROMPE Actualizar fixtures

Mitigacion:

// OPCION 1: Hacer opcional con default
@IsOptional()
@IsString()
deliveryAddress?: string = 'Por definir';

// OPCION 2: Migrar en fases
// Fase 1: Agregar como opcional
// Fase 2: Poblar datos existentes
// Fase 3: Hacer requerido

4.2 Agregar Campo Opcional (NON-BREAKING)

// Agregar campo opcional - NO rompe
export class CreateOrderDto {
    productId: string;
    quantity: number;

    @IsOptional()
    @IsString()
    notes?: string;  // ← NON-BREAKING: opcional
}

Impacto:

Componente Impacto Accion
Frontend Ninguno inmediato Agregar si se quiere usar
Clientes existentes Ninguno Siguen funcionando
Tests Ninguno Siguen pasando

4.3 Eliminar Campo de Request (BREAKING si requerido)

// ANTES
export class CreateUserDto {
    email: string;
    password: string;
    legacyCode: string;  // ← Se va a eliminar
}

// DESPUES
export class CreateUserDto {
    email: string;
    password: string;
    // legacyCode eliminado
}

Proceso:

1. Hacer campo opcional primero (si era requerido)
2. Marcar como @Deprecated en Swagger
3. Ignorar en backend (no procesar)
4. Notificar clientes
5. Eliminar despues de periodo de gracia

4.4 Cambiar Validacion (Puede ser BREAKING)

// ANTES: email cualquier formato
@IsString()
email: string;

// DESPUES: email debe ser valido
@IsEmail()
email: string;

Impacto: Requests que antes pasaban ahora fallan.

Mitigacion:

// Agregar transformacion para casos edge
@IsEmail()
@Transform(({ value }) => value?.toLowerCase().trim())
email: string;

5. CAMBIOS EN RESPONSE DTO

5.1 Eliminar Campo de Response (BREAKING)

// ANTES
export class UserResponseDto {
    id: string;
    email: string;
    legacyCode: string;  // ← Se elimina
}

// DESPUES
export class UserResponseDto {
    id: string;
    email: string;
    // legacyCode eliminado
}

Impacto Frontend:

// Si frontend usa el campo, ROMPE
const UserCard = ({ user }) => {
    return <div>{user.legacyCode}</div>;  // ← TypeError: undefined
};

Proceso Seguro:

1. Buscar uso en frontend: grep -rn "legacyCode" apps/
2. Eliminar uso en frontend primero
3. Luego eliminar de ResponseDto
4. Deploy coordinado

5.2 Agregar Campo a Response (NON-BREAKING)

// Agregar campo - NO rompe
export class UserResponseDto {
    id: string;
    email: string;
    createdAt: Date;  // ← Nuevo campo
}

Impacto:

  • Frontend puede ignorar campos nuevos
  • TypeScript mostrara warning si interface no coincide
  • Actualizar interface en frontend eventualmente

5.3 Cambiar Tipo de Campo (BREAKING)

// ANTES
export class ProductResponseDto {
    price: number;  // 99
}

// DESPUES
export class ProductResponseDto {
    price: string;  // "99.00"
}

Impacto Frontend:

// ANTES funcionaba
const total = product.price * quantity;

// DESPUES rompe (string * number = NaN)
const total = product.price * quantity;  // NaN!

// Debe cambiar a
const total = parseFloat(product.price) * quantity;

5.4 Cambiar Estructura de Response (BREAKING)

// ANTES: Array directo
@Get()
async findAll(): Promise<UserResponseDto[]> {
    return this.users;
}
// Response: [{ id: 1 }, { id: 2 }]

// DESPUES: Objeto paginado
@Get()
async findAll(): Promise<PaginatedResponse<UserResponseDto>> {
    return { data: this.users, total: 100, page: 1 };
}
// Response: { data: [...], total: 100, page: 1 }

Impacto Frontend:

// ANTES
const users = await api.get('/users');
users.map(u => ...);

// DESPUES
const response = await api.get('/users');
response.data.map(u => ...);  // Acceder a .data

6. CAMBIOS EN CODIGOS DE ERROR

6.1 Agregar Nuevo Codigo (NON-BREAKING)

// Agregar nueva excepcion - generalmente no rompe
throw new ConflictException('Email already registered');
// HTTP 409 - nuevo codigo

Impacto: Frontend deberia manejar, pero no rompe si no lo hace.

6.2 Cambiar Codigo Existente (BREAKING)

// ANTES: 400 para duplicado
throw new BadRequestException('Email exists');

// DESPUES: 409 para duplicado (correcto)
throw new ConflictException('Email exists');

Impacto: Frontend que verifica status code especifico rompe.

// Frontend que rompe
if (error.status === 400 && error.message.includes('Email')) {
    // Ya no entra aqui
}

// Frontend robusto
if (error.status === 409 || error.message.includes('Email')) {
    // Maneja ambos casos
}

6.3 Cambiar Formato de Error (BREAKING)

// ANTES
{
    "statusCode": 400,
    "message": "Validation failed"
}

// DESPUES
{
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "Validation failed",
        "details": [...]
    }
}

Impacto: TODO el manejo de errores en frontend debe cambiar.


7. VERSIONADO DE API

Cuando Usar Versionado

USA VERSIONADO CUANDO:
• API es consumida por clientes externos
• Cambios breaking frecuentes
• Necesitas mantener compatibilidad largo plazo

NO NECESITAS VERSIONADO CUANDO:
• Solo frontend interno consume la API
• Puedes coordinar deploys
• Equipo pequeno con comunicacion directa

Implementacion de Versiones

// Opcion 1: En URL
@Controller('v1/users')
export class UsersV1Controller {}

@Controller('v2/users')
export class UsersV2Controller {}

// Opcion 2: En Header
@Controller('users')
@ApiHeader({ name: 'Api-Version', enum: ['1', '2'] })
export class UsersController {
    @Get()
    findAll(@Headers('Api-Version') version: string) {
        if (version === '2') {
            return this.findAllV2();
        }
        return this.findAllV1();
    }
}

8. CHECKLIST POR TIPO DE CAMBIO

Agregar Endpoint Nuevo

[ ] 1. Crear metodo en Controller
[ ] 2. Agregar decoradores Swagger (@ApiOperation, @ApiResponse)
[ ] 3. Crear/actualizar DTOs si necesario
[ ] 4. Implementar en Service
[ ] 5. Agregar tests
[ ] 6. Actualizar Frontend service
[ ] 7. Crear Frontend hook si necesario
[ ] 8. Verificar Swagger

Modificar Endpoint Existente (NON-BREAKING)

[ ] 1. Verificar que cambio es non-breaking
[ ] 2. Actualizar Controller
[ ] 3. Actualizar DTOs si necesario
[ ] 4. Actualizar Swagger decoradores
[ ] 5. Actualizar tests
[ ] 6. Actualizar Frontend si aprovecha nuevas features

Modificar Endpoint Existente (BREAKING)

[ ] 1. Evaluar: ¿se puede hacer non-breaking?
[ ] 2. Buscar todos los consumidores: grep -rn "endpoint" apps/
[ ] 3. Planear estrategia de migracion
[ ] 4. Si API publica: crear version nueva, deprecar vieja
[ ] 5. Si API interna: coordinar con frontend
[ ] 6. Actualizar Frontend PRIMERO (apuntar a nuevo)
[ ] 7. Actualizar Backend
[ ] 8. Actualizar tests
[ ] 9. Deploy coordinado
[ ] 10. Eliminar codigo deprecated despues de periodo

Eliminar Endpoint

[ ] 1. Buscar todos los usos: grep -rn "endpoint" apps/ tests/
[ ] 2. Eliminar uso en Frontend
[ ] 3. Eliminar tests del endpoint
[ ] 4. Marcar como @Deprecated (si API publica)
[ ] 5. Periodo de gracia
[ ] 6. Eliminar de Controller
[ ] 7. Limpiar Service si metodos quedan sin usar

9. FRONTEND: ADAPTARSE A CAMBIOS API

Service Layer Pattern

// Encapsular llamadas API en service
// Facilita cambiar cuando API cambia

// user.service.ts
export const userService = {
    // Si cambia la ruta, solo cambiar aqui
    getAll: () => api.get<User[]>('/users'),

    // Si cambia estructura response
    getAllPaginated: async (page: number) => {
        const response = await api.get<PaginatedResponse<User>>('/users', { params: { page } });
        return response.data;  // Extraer data aqui
    },

    // Si cambia metodo HTTP
    update: (id: string, data: UpdateUserDto) =>
        api.put<User>(`/users/${id}`, data),  // Cambiar post→put aqui
};

Type Guards para Cambios de Estructura

// Manejar diferentes versiones de response
interface UserV1 {
    name: string;
}

interface UserV2 {
    firstName: string;
    lastName: string;
}

function isUserV2(user: UserV1 | UserV2): user is UserV2 {
    return 'firstName' in user;
}

function getDisplayName(user: UserV1 | UserV2): string {
    if (isUserV2(user)) {
        return `${user.firstName} ${user.lastName}`;
    }
    return user.name;
}

10. MATRIZ DE DECISION

¿Es BREAKING CHANGE?
        │
        ▼
   ┌────────────┐
   │ ¿Cambio de │───NO───▶ Implementar directamente
   │   ruta?    │          Actualizar Swagger
   └────────────┘          Actualizar Frontend (opcional)
        │
       YES
        │
        ▼
   ┌────────────┐
   │ ¿API       │───NO───▶ Actualizar Frontend PRIMERO
   │ publica?   │          Luego actualizar Backend
   └────────────┘          Deploy coordinado
        │
       YES
        │
        ▼
   ┌────────────────────────────────────────┐
   │ 1. Crear endpoint nuevo               │
   │ 2. Deprecar endpoint viejo            │
   │ 3. Notificar clientes                 │
   │ 4. Periodo de gracia (30-90 dias)     │
   │ 5. Eliminar endpoint viejo            │
   └────────────────────────────────────────┘

11. COMANDOS UTILES

# Ver todos los endpoints actuales
curl http://localhost:3000/api-json | jq '.paths | keys'

# Ver detalle de un endpoint
curl http://localhost:3000/api-json | jq '.paths["/users/{id}"]'

# Buscar uso de endpoint en frontend
grep -rn "users" apps/*/services/
grep -rn "/api/users" apps/

# Comparar Swagger entre versiones
diff <(curl -s http://localhost:3000/api-json | jq -S) \
     <(curl -s http://production/api-json | jq -S)

Version: 1.0.0 | Sistema: SIMCO | Tipo: Guia de Impacto