feat: version 4.10.0 -- Conectores de datos externos y conector FoxPro

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Milton Gonzalez
2026-10-29 11:32:08 -05:00
parent 28444b1485
commit d0f90542e9
23 changed files with 945 additions and 9 deletions
+50
View File
@@ -0,0 +1,50 @@
# Conectores de datos externos — contrato v1
El sistema **no se conecta directo** a las bases de datos de los clientes. En cada servidor origen
se instala un **conector**: una API HTTP de solo lectura que expone tablas elegidas. El sistema
habla siempre el mismo contrato, sin importar la tecnología de origen (FoxPro, SQL Server, Excel…).
| Conector | Carpeta | Estado |
|---|---|---|
| FoxPro (DBF/FPT/CDX) | `foxpro/` | 1.0.0 |
## Reglas que todo conector debe cumplir
1. **Solo lectura.** Únicamente `GET`; cualquier otro método → `405`. Nunca escribe en el origen.
2. **Token Bearer** (`Authorization: Bearer <token>`). El conector guarda solo el SHA-256; el
sistema guarda el token cifrado (AES-256-GCM). Se admiten varios hashes para rotar sin cortar.
3. **Lista de IPs permitidas** (backend del sistema), en el conector y en el firewall del servidor.
4. **El administrador del origen decide qué sale:** tablas permitidas, campos permitidos y campos
denegados (sueldos, claves…). Lo no permitido no existe para el sistema (`404`/`400`).
5. **Sin SQL ni rutas libres:** tablas y campos se validan contra la lista real del origen.
6. **Protege al origen:** límite de peticiones por minuto, lecturas simultáneas, tamaño de página
y tiempo máximo por petición. Responde `429`/`503` en vez de cargar el servidor.
7. **Log de acceso** sin tokens ni valores buscados (pueden ser datos personales).
## Endpoints
| Método y ruta | Respuesta |
|---|---|
| `GET /v1/health` | `{ ok, connector, contract: "v1", version, time }` |
| `GET /v1/sources` | `{ sources: [{ id, name }] }` — carpetas/bases configuradas |
| `GET /v1/sources/:source/tables` | `{ tables: [{ name, records, fields, version, modifiedAt }] }` |
| `GET /v1/sources/:source/tables/:table/schema` | `{ table, records, version, modifiedAt, fields: [{ name, type, size, decimals }] }` |
| `GET /v1/sources/:source/tables/:table/rows` | `{ table, version, modifiedAt, total, offset, limit, fields, rows }` |
Parámetros de `rows`:
- `fields=A,B` columnas a devolver (por defecto todas las permitidas).
- `limit` (1…máximo del conector, def. 100) y `offset` para paginar.
- `q=texto` y `qFields=A,B`: contiene, sin distinguir mayúsculas ni tildes.
- `eq.CAMPO=valor`: igualdad exacta (sin distinguir mayúsculas). Se pueden combinar varios.
- `includeDeleted=1`: incluye los registros marcados como borrados (`_deleted`).
Cada fila trae `_recno` (posición en el origen). `version` cambia cuando el origen se modifica:
el sistema la compara para saber si hace falta volver a sincronizar.
Tipos de dato en JSON: texto recortado (vacío → `null`), números, booleanos, fecha `YYYY-MM-DD`,
fecha-hora ISO 8601.
Errores: `{ error: "mensaje" }` con `400` parámetro inválido, `401` token, `403` IP, `404`
fuente/tabla, `405` método, `423` tabla bloqueada en el origen, `429` exceso de peticiones,
`503` conector ocupado, `500` error interno (detalle solo en el log del conector).