Files
service_manager/CAMBIOS_v1.10.0.md
icamarillo 517297e89a feat: Version 1.10.0 - Refactorizacion, optimizacion UI y mejoras de seguridad
- Extraccion de helpers en backend: audit_helpers.py, helpers.py
- Modularizacion de schemas en archivos individuales por dominio
- Reduccion de audit.py en 953 lineas (74% del archivo)
- Reduccion de tickets.py en 655 lineas (60% del archivo)
- Expansion de auth.py con recuperacion de contrasenia y tokens
- Nuevos modulos: core/email.py, core/cache.py
- Reorganizacion de scripts a backend/scripts/
- Frontend: refactorizacion de audit page con array-driven components
- Frontend: correccion de 11 errores ortograficos en tickets page
- Frontend: proxy Docker corregido en vite.config.js
- Frontend: nuevas rutas forgot-password, reset-password, organization, profile
- Nuevas utilidades TS: colorUtils.ts, dateFormats.ts
- 5 nuevos archivos de tests unitarios en backend/tests/unit/
- Eliminacion de 3 scripts temporales de prueba
- Documentacion tecnica: CAMBIOS_v1.10.0.md, OPTIMIZACIONES_RENDIMIENTO.md
2026-02-19 13:48:21 -07:00

25 KiB
Raw Blame History

ServiceManagerWeb — Versión 1.10.0

Reporte Técnico de Cambios y Mejoras


Proyecto: ServiceManagerWeb Mesa de Ayuda B2B Multi-tenant
Versión: 1.10.0
Versión base: 1.8.0 (commit e644039) / 1.9.0 (commit 16d795e)
Fecha: 19 de Febrero de 2026
Estado: Sistema Funcional — Producción MVP
Empresa: Aduanasoft
Autor: Equipo de Desarrollo


Resumen Ejecutivo

La versión 1.10.0 representa una fase de refactorización técnica profunda, optimización de rendimiento, y mejoras significativas en la interfaz de usuario. Los cambios abarcan el ciclo completo del sistema: backend (Python/FastAPI), frontend interno (SvelteKit), frontend cliente (SvelteKit) y la capa de infraestructura (Docker).

Métricas Globales de esta Versión

Indicador Valor
Archivos modificados 31 archivos
Líneas añadidas (total) ~3,250 líneas
Líneas eliminadas (total) ~3,440 líneas
Reducción neta de código ~190 líneas (refactorización limpia)
Archivos nuevos creados 14 archivos
Archivos eliminados 3 scripts de prueba temporales
Scripts reorganizados 3 (movidos a backend/scripts/)

1. Backend — Python / FastAPI

1.1 backend/app/api/v1/endpoints/audit.py

Cambios: +166 líneas añadidas / 1,119 líneas eliminadas
Balance neto: 953 líneas (reducción del 74% del archivo)

Problema detectado

El archivo audit.py tenía 1,285 líneas en la versión 1.8.0. Toda la lógica de detección de amenazas, análisis de seguridad y transformación de datos estaba inline dentro de las funciones de cada endpoint, generando duplicación masiva y dificultando el mantenimiento.

Cambios realizados

a) Extracción de lógica a módulo auxiliar
Se creó el archivo backend/app/api/v1/audit_helpers.py (nuevo, ver sección 1.8) con las siguientes funciones extraídas del archivo original:

# ANTES — en audit.py líneas 420-580 (inline)
# Toda la lógica de detección de amenazas vivía dentro de la función
# get_security_analysis() sin separación alguna

# DESPUÉS — importado desde audit_helpers.py
from app.api.v1.audit_helpers import (
    audit_log_to_dict,
    apply_tenant_filter,
    get_count_stat,
    get_top_items,
    detect_mass_deletions,
    detect_brute_force,
    detect_privilege_escalation
)

b) Docstrings compactados
Los docstrings multilínea extensos se compactaron a una sola línea donde el nombre era autoexplicativo:

# ANTES (líneas 1-7 del archivo original)
"""
Audit Endpoints - ServiceManagerWeb

Endpoints para consulta de logs de auditoría.
Solo accesible por roles: ADMIN, SUPPORT_MANAGER, AUDITOR
"""

# DESPUÉS (línea 1)
"""Audit Endpoints - ServiceManagerWeb"""

c) Firma de función require_auditor_role refactorizada

# ANTES (líneas 32-47) — 16 líneas
def require_auditor_role(current_user: User = Depends(get_current_user)) -> User:
    """
    Dependency que verifica que el usuario tenga rol de auditor.
    Solo ADMIN, SUPPORT_MANAGER y AUDITOR pueden ver logs de auditoría.
    """
    allowed_roles = [UserRole.ADMIN, UserRole.SUPPORT_MANAGER, UserRole.AUDITOR]
    if current_user.role not in allowed_roles:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Solo usuarios con rol ADMIN, SUPPORT_MANAGER o AUDITOR..."
        )
    return current_user

# DESPUÉS (líneas 20-24) — 5 líneas
def require_auditor_role(current_user: User = Depends(get_current_user)) -> User:
    """Verifica que el usuario tenga rol de auditor"""
    if current_user.role not in [UserRole.ADMIN, UserRole.SUPPORT_MANAGER, UserRole.AUDITOR]:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
            detail="Solo usuarios con rol ADMIN, SUPPORT_MANAGER o AUDITOR pueden acceder")
    return current_user

d) Firma del endpoint get_audit_logs compactada

# ANTES (líneas 49-72) — 24 líneas de parámetros separados

# DESPUÉS — parámetros agrupados en 6 líneas
async def get_audit_logs(
    page: int = Query(default=1, ge=1),
    per_page: int = Query(default=50, ge=1, le=100),
    user_id: Optional[uuid.UUID] = Query(None),
    action: Optional[str] = Query(None),
    ...

e) Corrección del schema SecurityAnalysisResponse
Se añadieron todos los campos requeridos que causaban error 500 al serializar la respuesta. Los campos faltantes eran:

  • analysis_period_hours
  • total_threats_detected
  • suspicious_ips_count
  • critical_actions_count

1.2 backend/app/api/v1/endpoints/auth.py

Cambios: +369 líneas añadidas / 40 líneas eliminadas
Balance neto: +329 líneas

Cambios realizados

Se amplió la cobertura de autenticación con:

  • Manejo robusto de tokens de refresco
  • Validación mejorada de credenciales con mensajes de error específicos
  • Soporte para recuperación de contraseña por email
  • Integración con el servicio de email (app/core/email.py)
  • Logging estructurado con structlog en todos los endpoints críticos

1.3 backend/app/api/v1/endpoints/tickets.py

Cambios: +217 líneas añadidas / 872 líneas eliminadas
Balance neto: 655 líneas (reducción del 60%)

Problema detectado

Igual que audit.py, el archivo de tickets tenía lógica de negocio repetida y funciones helper inline.

Cambios realizados

a) Extracción a backend/app/api/v1/helpers.py
Se creó un módulo auxiliar general (nuevo, ver sección 1.9) con funciones reutilizables como:

  • build_ticket_query() — construye queries SQLAlchemy con filtros dinámicos
  • paginate_query() — paginación genérica reutilizable
  • format_ticket_response() — serialización consistente

b) Corrección del error de sla_breached

# ANTES — causaba AttributeError / 500 en producción
response.sla_breached = ticket.sla_breached    # ← propiedad no existía

# DESPUÉS — removido, calculado dinámicamente
# sla_breached se calcula desde sla_deadline vs datetime.utcnow()

1.4 backend/app/api/schemas/__init__.py

Cambios: +54 líneas añadidas / 4 líneas eliminadas

Se reorganizaron los schemas en módulos separados:

# ANTES — un archivo monolítico schemas/__init__.py con todo

# DESPUÉS — módulos independientes por dominio:
backend/app/api/schemas/
├── __init__.py          (re-exports, 58 líneas totales)
├── auth.py              (NUEVO — schemas de autenticación)
├── category.py          (NUEVO — schemas de categorías)
├── system.py            (NUEVO — schemas de sistemas)
├── tenant.py            (NUEVO — schemas de tenants)
├── ticket.py            (NUEVO — schemas de tickets)
└── user.py              (NUEVO — schemas de usuarios)

1.5 backend/app/middleware/tenant.py

Cambios: +103 líneas añadidas / 37 líneas eliminadas
Balance neto: +66 líneas

Cambios realizados

  • Mejora del middleware de contexto multi-tenant con mejor manejo de headers X-Tenant-ID
  • Logging detallado de tenant context para debugging
  • Validación más robusta del tenant activo
  • Soporte para tenant bypass en endpoints de health/docs

1.6 backend/app/main.py

Cambios: +7 líneas añadidas / 0 líneas eliminadas

# AÑADIDO — registro de nuevos routers
from app.api.v1.endpoints import profile  # router de perfil de usuario
app.include_router(profile.router, prefix="/api/v1/profile", tags=["profile"])

1.7 backend/app/core/database.py

Cambios: +3 líneas / 2 líneas

# ANTES
engine = create_async_engine(settings.DATABASE_URL, echo=False)

# DESPUÉS — pool tuning para mayor concurrencia
engine = create_async_engine(
    settings.DATABASE_URL,
    pool_pre_ping=True,
    pool_recycle=300
)

1.8 backend/app/api/v1/audit_helpers.py (ARCHIVO NUEVO)

Líneas: ~120 líneas

Módulo auxiliar extraído de audit.py. Contiene:

Función Descripción
audit_log_to_dict(log) Serializa un AuditLog a dict
apply_tenant_filter(query, user, tenant, all_tenants) Aplica filtro multi-tenant
get_count_stat(db, model, filters) Cuenta registros con filtros
get_top_items(db, field, limit) Top N elementos de un campo
detect_mass_deletions(logs) Detecta patrones de eliminación masiva
detect_brute_force(logs) Detecta intentos de brute force
detect_privilege_escalation(logs) Detecta escalada de privilegios

1.9 backend/app/api/v1/helpers.py (ARCHIVO NUEVO)

Líneas: ~80 líneas

Helper general para tickets y recursos compartidos.


1.10 backend/app/core/email.py (ARCHIVO NUEVO)

Módulo de envío de email para notificaciones y recuperación de contraseña, integrado con Celery workers.


1.11 backend/app/core/cache.py (ARCHIVO NUEVO)

Módulo de caché con Redis:

  • cache_get(key) / cache_set(key, value, ttl)
  • Decorador @cached(ttl=300) para funciones async
  • Invalidación por patrón de claves

1.12 backend/migrations/versions/a1b2c3d4e5f6_add_audit_logs_table.py

Cambios: +57 líneas / 1 línea

Migration completada: se añadió la tabla security_incidents con campos:

  • id UUID PRIMARY KEY
  • title VARCHAR(255)
  • description TEXT
  • severity ENUM(low, medium, high, critical)
  • status ENUM(active, investigating, resolved)
  • tenant_id UUID FK
  • created_at TIMESTAMP
  • updated_at TIMESTAMP

1.13 backend/tests/conftest.py

Cambios: +151 líneas / 13 líneas

Se amplió el fixture base para pruebas de integración:

  • Fixtures para multi-tenant testing
  • Fixtures para usuario con rol AUDITOR
  • Data factories para tickets, incidentes y audit logs

1.14 Reorganización de Scripts

# ANTES — en raíz de backend/
backend/check_tenants.py
backend/create_test_user.py
backend/set_test_password.py

# DESPUÉS — carpeta dedicada
backend/scripts/check_tenants.py
backend/scripts/create_test_user.py
backend/scripts/set_test_password.py

1.15 Nuevos Tests Unitarios (archivos nuevos)

backend/tests/unit/
├── test_audit_service.py    (cobertura del AuditService)
├── test_config.py           (validación de settings)
├── test_middleware.py       (pruebas del middleware tenant)
├── test_schemas.py          (validación de schemas Pydantic)
└── test_security.py         (pruebas de JWT y hashing)

2. Frontend Interno — SvelteKit / TypeScript

2.1 frontend-internal/src/routes/audit/+page.svelte

Cambios: +1,253 líneas añadidas / 554 líneas eliminadas
Líneas totales finales: 2,050 líneas

Este es el archivo con más cambios de toda la versión. Se realizó una refactorización completa de la página de auditoría.

2.1.1 Tipado TypeScript — Corrección de Warnings

// ANTES (líneas 9-17) — tipos implícitos, generaba warnings
let logs = [];
let stats = null;
let users = [];
let incidents = [];
let securityAnalysis = null;
let selectedLog = null;
let selectedIncident = null;

// DESPUÉS — tipos explícitos
let logs: any[] = [];
let stats: any = null;
let users: any[] = [];
let incidents: any[] = [];
let securityAnalysis: any = null;
let selectedLog: any = null;
let selectedIncident: any = null;

2.1.2 Responses de API tipadas

// ANTES — response sin tipo, causaba errores
const response = await api.get('/audit/security/incidents', params);
incidents = response.incidents || [];   // TS error: 'response' is of type 'unknown'

// DESPUÉS — response con tipo explícito
const response: any = await api.get('/audit/security/incidents', params);
incidents = response.incidents || [];

2.1.3 Catch blocks tipados (5 bloques corregidos)

// ANTES — 5 bloques con e sin tipo
} catch (e) {
    console.error('Error:', e);

// DESPUÉS — todos tipados
} catch (e: any) {
    console.error('Error:', e);

2.1.4 Botones de período refactorizados con array tipado

// ANTES — 5 bloques <button> repetidos, ~40 líneas
<button on:click={() => changePeriod('today')} class="...">Hoy</button>
<button on:click={() => changePeriod('yesterday')} class="...">Ayer</button>
<button on:click={() => changePeriod('last7days')} class="...">Últimos 7 días</button>
<button on:click={() => changePeriod('last30days')} class="...">Últimos 30 días</button>
<button on:click={() => changePeriod('custom')} class="...">Personalizado</button>

// DESPUÉS — array con tipo estricto + loop, ~15 líneas
const periodButtons: Array<{
    id: 'today' | 'yesterday' | 'last7days' | 'last30days' | 'custom',
    label: string,
    icon?: boolean
}> = [
    { id: 'today', label: 'Hoy' },
    { id: 'yesterday', label: 'Ayer' },
    { id: 'last7days', label: 'Últimos 7 días' },
    { id: 'last30days', label: 'Últimos 30 días' },
    { id: 'custom', label: 'Personalizado', icon: true }
];

{#each periodButtons as btn}
    <button on:click={() => changePeriod(btn.id)} class="...">
        {btn.label}
    </button>
{/each}

2.1.5 Tarjetas estadísticas refactorizadas con array reactivo

// ANTES — 4 bloques <div> idénticos con ~25 líneas cada uno (~100 líneas totales)
// Total del Acciones — bloque completo
<div class="bg-white rounded-lg ...">
    <div class="..."><svg .../><span>Total de Registros</span></div>
    <div class="text-3xl ...">{stats.total_actions.toLocaleString()}</div>
    ...
</div>
// Acciones Hoy — bloque completo (repetido)
// Esta Semana — bloque completo (repetido)
// Incidentes Críticos — bloque completo (repetido)

// DESPUÉS — array reactivo + loop, ~40 líneas totales
$: statsCards = [
    { label: 'Total de Registros', value: stats?.total_actions, icon: 'clipboard', color: 'gray', desc: '...' },
    { label: 'Actividad Hoy', value: stats?.actions_today, icon: 'zap', color: 'blue', desc: '...' },
    { label: 'Esta Semana', value: stats?.actions_this_week, icon: 'calendar', color: 'indigo', desc: '...' },
    { label: 'Incidentes Críticos', value: stats?.critical_actions_today || 0, icon: 'alert', color: 'red', desc: '...', action: true }
];

{#each statsCards as card}
    <div class="bg-white rounded-lg shadow-sm border border-{card.color}-200 p-5 ...">
        ...
    </div>
{/each}

2.1.6 Sección de Análisis de Seguridad reemplazada por enlace

<!-- ANTES — sección extensa de ~150 líneas con amenazas, acciones recomendadas
     y métricas desplegadas inline en la página principal -->

<!-- DESPUÉS — tarjeta compacta (~50 líneas) con enlace a página dedicada -->
<a href="/audit/security" class="block bg-gradient-to-br from-indigo-500 to-purple-600 rounded-lg ...">
    <!-- Resumen de 3 métricas clave -->
    <!-- Indicador visual del nivel de riesgo -->
    <!-- Enlace "Ir al análisis detallado" -->
</a>

Esta decisión separa la responsabilidad: la página /audit muestra el resumen de actividad, mientras que /audit/security muestra el análisis detallado de amenazas.

2.1.7 Mejoras de espaciado y layout

  • Contenedor principal: px-4 sm:px-6 lg:px-8 py-8 — márgenes responsivos
  • Encabezado de página: añadido con h1 + descripción
  • Separación entre secciones: mb-8 uniforme (antes mb-6 variable)
  • Etiquetas de sección: añadidos <h2> para "Resumen de Actividad", "Incidentes de Seguridad", "Registros de Auditoría"
  • Tarjetas con headers descriptivos: añadidos <h3> en toggles y controles

2.2 frontend-internal/src/routes/tickets/+page.svelte

Cambios: +731 líneas añadidas / 338 líneas eliminadas

Cambios realizados

  • Corrección de ortografía en 11 etiquetas de texto (ej: "priorida" → "prioridad")
  • Mejora del filtro de estado y prioridad con selects correctamente bound a variables reactivas
  • Vista de tabla compacta con rows más ajustados (py-2 en lugar de py-4)
  • Indicadores de color para prioridad (urgente=rojo, alto=naranja, medio=amarillo, bajo=azul)
  • Modal de detalle de ticket con información de SLA sin acceder a propiedades no existentes

2.3 frontend-internal/src/lib/components/Sidebar.svelte

Cambios: +17 líneas / 6 líneas

<!-- ANTES — enlace a Reportes ausente o comentado -->

<!-- DESPUÉS — enlace restaurado y activo -->
<a href="/reports" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md ..."
   class:bg-indigo-700={$page.url.pathname.startsWith('/reports')}>
    Reportes
</a>

2.4 frontend-internal/vite.config.js

Cambios: +20 líneas / 16 líneas

// ANTES — proxy incorrecto durante desarrollo
proxy: {
    '/api': 'http://localhost:8000'  // ← fallaba dentro de Docker
}

// DESPUÉS — proxy correcto para red Docker
proxy: {
    '/api': {
        target: 'http://backend:8000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
    }
}

2.5 Nuevos Utilitarios Frontend (archivos nuevos)

frontend-internal/src/lib/utils/colorUtils.ts (NUEVO, 74 líneas)

// Centraliza todos los mapas de colores del sistema
type ColorType = 'severity' | 'status' | 'action' | 'priority';

export function getColorClass(value: string, type: ColorType = 'status'): string
export function getStatusIcon(status: string): string

frontend-internal/src/lib/utils/dateFormats.ts (NUEVO, 78 líneas)

// Centraliza el formateo de fechas
export function formatDate(dateString: string, format: DateFormat = 'full'): string
export function getRelativeTime(dateString: string): string
export function getDateRangeForPeriod(period: string, from?: string, to?: string): DateRange

3. Frontend Cliente — SvelteKit / TypeScript

3.1 frontend-client/src/routes/profile/+page.svelte

Cambios: +194 líneas / 56 líneas

Nueva funcionalidad de perfil de usuario con:

  • Visualización de datos personales del cliente
  • Formulario de edición de nombre y contacto
  • Cambio de contraseña con validación de fortaleza
  • Indicador visual del tipo de cuenta

3.2 frontend-client/vite.config.js

Cambios: +4 líneas / 0 líneas

// AÑADIDO — proxy para comunicación con backend
server: {
    proxy: {
        '/api': { target: 'http://backend:8000', ... }
    }
}

3.3 Nuevas Rutas Frontend Cliente (archivos nuevos)

frontend-client/src/routes/
├── forgot-password/     (NUEVO — flujo de recuperación de contraseña)
├── reset-password/      (NUEVO — formulario de nueva contraseña con token)
└── organization/        (NUEVO — vista de datos de la organización del cliente)

3.4 frontend-client/src/lib/components/Header.svelte

Cambios: +8 líneas / 2 líneas

  • Añadido enlace a perfil de usuario en el dropdown del header
  • Enlace a "Mi Organización" visible para CLIENT_ADMIN

4. Infraestructura y DevOps

4.1 docker/Dockerfile.backend

Cambios: +3 líneas / 1 línea

# AÑADIDO — dependencias del sistema para compilar bcrypt
RUN apt-get install -y build-essential libffi-dev

4.2 frontend-internal/package.json

Cambios: +1 línea / 1 línea

// ACTUALIZADO — versión de @sveltejs/kit para fix de routing
"@sveltejs/kit": "^1.27.0"   // antes ^1.6.0

5. Archivos Eliminados

Archivo Razón
test_frontend_integration.ps1 (174 líneas) Script de prueba temporal — funcionalidad absorbida por suite de tests
test_manual.ps1 (142 líneas) Script de prueba manual obsoleto
test_tenant_update.ps1 (101 líneas) Script específico para prueba puntual, ya no necesario

Total eliminado: 417 líneas de código temporal/obsoleto


6. Nuevos Archivos Creados

Archivo Líneas Propósito
backend/app/api/v1/audit_helpers.py ~120 Helpers de auditoría extraídos de audit.py
backend/app/api/v1/helpers.py ~80 Helpers generales de tickets y queries
backend/app/api/schemas/auth.py ~60 Schemas Pydantic para autenticación
backend/app/api/schemas/category.py ~30 Schemas de categorías
backend/app/api/schemas/system.py ~30 Schemas de sistemas
backend/app/api/schemas/tenant.py ~40 Schemas de tenants
backend/app/api/schemas/ticket.py ~80 Schemas de tickets
backend/app/api/schemas/user.py ~50 Schemas de usuarios
backend/app/core/email.py ~90 Servicio de envío de email
backend/app/core/cache.py ~70 Módulo de caché Redis
backend/tests/unit/test_audit_service.py ~100 Tests del servicio de auditoría
backend/tests/unit/test_config.py ~50 Tests de configuración
backend/tests/unit/test_middleware.py ~80 Tests del middleware tenant
backend/tests/unit/test_schemas.py ~70 Tests de validación de schemas
backend/tests/unit/test_security.py ~60 Tests de seguridad JWT
frontend-internal/src/lib/utils/colorUtils.ts 74 Centralización de colores
frontend-internal/src/lib/utils/dateFormats.ts 78 Centralización de formatos de fecha
frontend-client/src/routes/forgot-password/ ~80 Flujo de recuperación de contraseña
frontend-client/src/routes/reset-password/ ~90 Formulario reset con token
frontend-client/src/routes/organization/ ~120 Vista de organización del cliente
frontend-internal/src/routes/profile/ ~150 Perfil del usuario interno
OPTIMIZACIONES_RENDIMIENTO.md 344 Guía técnica de optimizaciones futuras

7. Correcciones de Bugs

Bug #1 — Error 500 en /audit/security/analysis

Causa: El schema SecurityAnalysisResponse de Pydantic no incluía los campos analysis_period_hours, total_threats_detected, suspicious_ips_count, critical_actions_count. Al intentar serializar la respuesta, Pydantic lanzaba ValidationError.
Archivo: backend/app/api/v1/endpoints/audit.py
Fix: Se añadieron los campos faltantes al schema de respuesta en backend/app/api/schemas/__init__.py.

Bug #2 — Error 500 en detalle de ticket (/tickets/{id})

Causa: El endpoint accedía a ticket.sla_breached que no es una columna de la tabla, sino un cálculo derivado.
Archivo: backend/app/api/v1/endpoints/tickets.py
Fix: Se eliminó la referencia a ticket.sla_breached y se calcula dinámicamente: sla_breached = ticket.sla_deadline < datetime.utcnow() if ticket.sla_deadline else False

Bug #3 — Proxy 404 en desarrollo con Docker

Causa: vite.config.js apuntaba a localhost:8000 en lugar del hostname Docker backend:8000.
Archivos: frontend-internal/vite.config.js, frontend-client/vite.config.js
Fix: Se actualizó el target del proxy a http://backend:8000 con changeOrigin: true.

Bug #4 — Filtros de tickets no aplicaban

Causa: Los parámetros status y priority del frontend construían query strings con nombres incorrectos (status_filter en vez de status).
Archivo: frontend-internal/src/routes/tickets/+page.svelte
Fix: Corregidos los nombres de parámetros para coincidir con los Query params del backend.

Bug #5 — Archivos con prefijo + causaban error de SvelteKit

Causa: Durante el desarrollo se crearon archivos de respaldo con nombres +page.svelte.backup y +page.svelte.tmp. SvelteKit interpreta cualquier archivo con + como una ruta especial.
Fix: Se eliminaron todos los archivos de respaldo con formato +*.tmp.


8. Correcciones Ortográficas (frontend-internal)

En frontend-internal/src/routes/tickets/+page.svelte se corrigieron 11 errores ortográficos:

Línea aprox. Antes Después
~145 priorida prioridad
~189 Estad Estado
~234 Accionnes Acciones
~267 Assigado Asignado
~310 Fecah Fecha
~345 Prioiridad Prioridad
~389 Ticktes Tickets
~412 Resolucion Resolución
~456 Sataus Status
~478 Critcio Crítico
~501 Asignar → etiqueta incorrecta Texto corregido contextualmente

9. Notas de Migración

Para actualizar de v1.8.0 / v1.9.0 a v1.10.0:

# 1. Actualizar código
git pull origin main
git checkout version-1.10.0

# 2. Aplicar migraciones de base de datos
docker-compose exec backend alembic upgrade head

# 3. Reconstruir imágenes (cambios en Dockerfile)
docker-compose build --no-cache backend

# 4. Reiniciar todos los servicios
docker-compose up -d

# 5. Verificar salud
curl http://localhost:8000/health

10. Estado del Sistema tras v1.10.0

Componente Estado Notas
Backend FastAPI Funcional 0 errores 500 en endpoints principales
Frontend Interno Funcional Proxy Docker correcto
Frontend Cliente Funcional Nuevas rutas de perfil y organización
Base de Datos Migrada Tabla security_incidents disponible
Celery Workers Funcional Integrado con email service
Redis Cache Funcional Módulo cache.py implementado
Tests Unitarios Nuevos 5 nuevos archivos de tests
Docker Compose Funcional Todos los servicios healthy

Documento generado: 19 de Febrero de 2026
Versión del documento: 1.0
ServiceManagerWeb — Aduanasoft