# Arquitectura

## Componentes

```text
Tablet / navegador
  ├─ PWA + Service Worker
  ├─ Editor SVG
  ├─ Pointer Events (pluma/dedo/mouse)
  ├─ Modelo CAD JSON
  ├─ Cálculo inmediato de métricas
  └─ Exportador DXF local
            │ HTTPS / JSON
            ▼
PHP 8.2+
  ├─ Sesión y CSRF
  ├─ API de proyectos
  ├─ Repositorio PDO
  ├─ Recalculador de métricas
  ├─ Importador/exportador DXF
  ├─ Renderizador SVG
  └─ Generador PDF
            │
            ▼
MySQL/MariaDB o SQLite
```

## Decisiones principales

### SVG como lienzo CAD

SVG permite interacción directa con entidades, hit-testing, vectores nítidos y exportación del mismo modelo a PDF. El sistema no guarda una captura de pantalla: guarda geometría estructurada.

### Pointer Events

Un mismo flujo de eventos atiende pluma, mouse y touch. El editor usa `pointerType`, captura del puntero y presión informativa. La precisión final no depende del trazo libre: el usuario puede escribir longitud, ángulo y coordenadas exactas.

### Modelo interno en milímetros

Todas las entidades se normalizan a milímetros para evitar ambigüedad al exportar DXF y calcular metros lineales. `settings.inputUnit = cm` solo controla la presentación.

### Métricas duplicadas cliente/servidor

El navegador calcula para retroalimentación inmediata. PHP recalcula al guardar y persiste el resultado autoritativo, reduciendo la posibilidad de manipulación o diferencias de versión.

### DXF propio y acotado

El paquete implementa un subconjunto explícito de DXF ASCII. Esto hace el flujo controlable, pero exige validación con el CAM/CNC real.

## Modelo de dibujo

Ejemplo simplificado:

```json
{
  "version": 1,
  "units": "mm",
  "settings": {
    "inputUnit": "cm",
    "gridSpacing": 100,
    "snapSpacing": 10,
    "snap": true,
    "ortho": false,
    "isometric": false,
    "penOnly": true
  },
  "layers": [
    {
      "id": "ACABADO",
      "name": "Acabado / canto",
      "color": "#E53935",
      "dxfColor": 1,
      "semantic": "finish",
      "countLength": true
    }
  ],
  "entities": [
    {
      "id": "e_001",
      "type": "line",
      "layer": "ACABADO",
      "p1": { "x": 0, "y": 0 },
      "p2": { "x": 2400, "y": 0 }
    },
    {
      "id": "e_002",
      "type": "sink",
      "layer": "TARJA_BAJO",
      "mount": "undermount",
      "center": { "x": 1200, "y": 500 },
      "width": 800,
      "height": 500,
      "rotation": 0
    }
  ]
}
```

## Entidades soportadas

- `line`
- `polyline`
- `rectangle`
- `circle`
- `arc`
- `dimension`
- `text`
- `sink`
- `cooktop`

Los isométricos básicos se guardan como grupos de líneas con un `groupId` compartido.

## Cálculo de longitud

- Línea: distancia euclidiana entre extremos.
- Polilínea: suma de segmentos y cierre opcional.
- Rectángulo: `2 × (ancho + alto)`.
- Círculo: `2πr`.
- Arco: `radio × ángulo en radianes`.

Solo se suman entidades cuyo `countLength` efectivo sea verdadero.

## Área y piezas

Se contabilizan como piezas los contornos cerrados en la semántica `contour`:

- polilínea cerrada;
- rectángulo;
- círculo.

La suma de área es geométrica y aproximada. No descuenta automáticamente tarjas/parrillas ni resuelve operaciones booleanas entre polígonos en esta versión.

## Persistencia

La tabla `projects` guarda:

- datos del pedido;
- `drawing_json`;
- `metrics_json`;
- versión optimista;
- autor y fechas;
- borrado lógico.

`audit_log` registra creación, actualización y eliminación. `attachments` queda preparado para fotos/documentos, aunque la interfaz de adjuntos no forma parte del MVP actual.

## Concurrencia

Cada proyecto tiene un número `version`. Una actualización solo se aplica cuando la versión enviada coincide con la del servidor. Si otra persona guardó primero, la API responde `409 VERSION_CONFLICT` y el borrador local se conserva.

## Seguridad implementada

- cookies de sesión `HttpOnly`, `SameSite=Lax` y `Secure` configurable;
- regeneración del ID de sesión al iniciar sesión;
- `password_hash`/`password_verify`;
- tokens CSRF para operaciones mutables;
- PDO con emulación desactivada y parámetros preparados;
- límite de tamaño y extensión para DXF;
- escape de salida HTML/SVG;
- `DocumentRoot` aislado en `public/`;
- bitácora básica.

## Seguridad pendiente para una versión empresarial

- roles y permisos por acción;
- segundo factor;
- límite de intentos y rate limiting;
- recuperación de contraseña;
- revocación de sesiones;
- política de retención;
- cifrado de adjuntos;
- monitoreo centralizado;
- CSP con nonce;
- antivirus para adjuntos cuando se implemente su carga.
