ALEPH — Arquitectura y contrato técnico¶
¿Para qué existe aleph.md?
aleph.md no es un manual de usuario ni un tutorial paso-a-paso.
Es un documento de arquitectura y contrato técnico que responde a estas preguntas clave:
¿Dónde está ALEPH en el código?
¿Cuál es la única forma correcta de conectarse a ALEPH?
¿Cómo se accede a los datos (online vs offline)?
Cómo funciona la ingesta incremental (snapshot inteligente)
Qué entidades están soportadas y cómo se relacionan
Su función principal es evitar regresiones y evitar duplicación caótica en el futuro.
Qué sí vamos a guardar en aleph.md 2.1. Propósito y alcance (breve)
Una sección corta que deje esto explícito:
ALEPH es el sistema fuente de datos operativos (empresas, proyectos, cotizaciones, contratos). Este módulo define cómo se consulta, cómo se congela y cómo se consume esa información dentro de Prodisys.
Esto sirve para que, dentro de 6 meses, nadie se pregunte:
“¿Por qué hay JSONL aquí?” “¿Por qué no consultamos directo la base?”
2.2. Arquitectura oficial (muy importante)
Aquí se deja claro el contrato:
prodisys/ aleph/ db.py ← conexión y ejecución SQL (único lugar) queries.py ← SQL de negocio (fetch_*) ingest/ ingest_aleph.py ← snapshot incremental snapshots.py ← lectura offline
Y se escribe explícitamente:
❌ Prohibido copiar SQL en notebooks o en la APP
❌ Prohibido crear engines en varios sitios
✅ Toda consulta pasa por queries.py
✅ Toda conexión pasa por db.py
Esto no es burocracia: es control de complejidad futura.
2.3. Conexión a ALEPH (sin credenciales)
Aquí no se ponen contraseñas, solo la responsabilidad del módulo:
Ejemplo de texto:
prodisys.aleph.db es el único responsable de:
crear el SQLAlchemy Engine
reutilizar la conexión (singleton)
ejecutar SQL crudo
Ningún otro módulo crea conexiones directas.
Esto sirve para:
debugging
cambiar DSN en un solo sitio
aislar ALEPH si mañana cambia
2.4. Consultas de negocio (queries.py)
Aquí se documenta qué existe, no el SQL completo:
Función Entidad Fuente fetch_empresas() Empresas EMPRESAS fetch_proyectos() Proyectos PROYECTOS fetch_cotizaciones() Cotizaciones COTIZACIONES fetch_cotiza_proyecto() Relación COTIZA_PROYECTO fetch_contratos() Contratos CONTRATOS
Y se aclara:
Las funciones devuelven listas de dicts
Los nombres de campos ya vienen normalizados
Son reutilizables tanto por la ingesta como por la APP
2.5. Snapshot incremental (el corazón del sistema)
Esta es una de las partes más importantes del documento.
Aquí se explica conceptualmente:
Qué es un snapshot incremental
Qué es un índice por entidad
Qué significa “0 registros escritos”
Ejemplo de explicación clara:
Cada corrida compara el hash del payload actual con el último hash conocido por clave lógica.
Si no hay cambios, no se escribe nada.
Por eso una corrida con:
empresas: 0 registros
significa “no hubo cambios”, no “falló”.
También se documenta la clave lógica por entidad:
Entidad Key lógica Empresa NIT Proyecto id_proyecto Cotización id_cotizacion Proyecto–Cotización id_proyecto__id_cotizacion Contrato id_contrato
Esto es oro para mantenimiento futuro.
2.6. Modo online vs modo offline
Aquí se deja cristalino cómo se consume ALEPH:
Modo online:
from prodisys.aleph.queries import fetch_proyectos
Modo offline:
from prodisys.ingest.snapshots import load_latest_by_key
Y se aclara cuándo usar cada uno:
Online → exploración, dashboards vivos, debugging
Offline → análisis, modelos, joins pesados, histórico
2.7. Qué NO va en aleph.md
Esto es igual de importante:
❌ No va SQL completo ❌ No va lógica de pandas ❌ No va documentación de notebooks ❌ No va análisis de negocio ❌ No va ETL hacia otros sistemas
Eso vive en otros documentos.
Qué problema resuelve este documento
Sin aleph.md, en 6–12 meses pasa esto:
alguien copia SQL en un notebook
otro crea otro engine
otro cambia una columna
el incremental “deja de funcionar”
nadie sabe por qué
Con aleph.md:
hay una única fuente de verdad
hay reglas explícitas
el sistema es explicable
Qué haremos después de aleph.md
Una vez esto quede documentado:
docs/vistas_aleph.md → cómo se construyen vistas (joins, columnas finales)
docs/documentos_proyecto.md → dosieres, agendas, notas, PDFs, escaneos (otro dominio)
ALEPH queda cerrado y estable.
Si quiere, en el próximo mensaje puedo:
escribir la versión final de aleph.md lista para commit, o
revisar su borrador y ajustarlo con lenguaje técnico preciso
Usted decide.
You said: ponga la versión final de aleph.md bien documentado ChatGPT said:
Perfecto. A continuación tiene la versión final y estable de docs/aleph.md, redactada como documento de arquitectura y contrato técnico, lista para commit sin ajustes adicionales.
ALEPH — Arquitectura, Ingesta y Consumo de Datos
Propósito
ALEPH es el sistema fuente de información operativa para Prodisys. Contiene entidades maestras y transaccionales como:
Empresas
Proyectos
Cotizaciones
Contratos
Relaciones entre proyectos y cotizaciones
Este documento define la forma oficial y única de:
Conectarse a ALEPH
Consultar datos (modo online)
Congelar datos mediante snapshots incrementales (modo offline)
Consumir información en la APP y en notebooks
Su objetivo principal es garantizar estabilidad, trazabilidad y evitar duplicación de lógica.
Principios de diseño
Una sola fuente de verdad para la conexión
Un solo lugar para el SQL
Separación clara entre consulta, ingesta y consumo
Soporte explícito para trabajo online y offline
Ingesta incremental (no snapshots completos repetidos)
Cualquier código que viole estos principios se considera técnicamente incorrecto.
Estructura de módulos prodisys/ aleph/ db.py # conexión y ejecución SQL (único lugar) queries.py # consultas de negocio (fetch_*) ingest/ ingest_aleph.py # snapshot incremental desde ALEPH snapshots.py # lectura de snapshots JSONL
Reglas obligatorias
❌ No se crean engines fuera de db.py
❌ No se ejecuta SQL fuera de queries.py
❌ No se copian credenciales ni DSN en notebooks o scripts
✅ Toda consulta pasa por queries.py
✅ Toda conexión pasa por db.py
Conexión a ALEPH (prodisys.aleph.db)
Este módulo es el único responsable de:
Crear el Engine de SQLAlchemy
Reutilizar la conexión (singleton)
Ejecutar SQL crudo
Conceptualmente:
from prodisys.aleph.db import run_query
Ningún otro módulo debe:
importar sqlalchemy.create_engine
manejar credenciales
abrir conexiones directas
Esto permite cambiar el DSN, driver o entorno en un solo sitio.
Consultas de negocio (prodisys.aleph.queries)
Las consultas a ALEPH están encapsuladas como funciones fetch_*.
Funciones disponibles Función Entidad Tabla fuente fetch_empresas() Empresas EMPRESAS fetch_proyectos() Proyectos PROYECTOS fetch_cotizaciones() Cotizaciones COTIZACIONES fetch_cotiza_proyecto() Relación proyecto–cotización COTIZA_PROYECTO fetch_contratos() Contratos CONTRATOS Contrato de salida
Devuelven List[Dict[str, Any]]
Los nombres de campos vienen normalizados
No aplican lógica de negocio ni joins complejos
Estas funciones son reutilizadas por:
la ingesta (ingest_aleph.py)
la APP
notebooks exploratorios (modo online)
Ingesta incremental (snapshots)
La ingesta desde ALEPH se realiza mediante snapshots incrementales, no copias completas repetidas.
Archivo responsable prodisys/ingest/ingest_aleph.py
Idea central
Cada entidad tiene una clave lógica
Se calcula un hash del payload
Solo se escribe una nueva versión si el contenido cambió
Por eso es normal y esperado que una corrida muestre:
empresas: 0 registros
Esto significa: no hubo cambios, no que la ingesta falló.
Claves lógicas por entidad Entidad Clave lógica Empresa NIT Proyecto id_proyecto Cotización id_cotizacion Proyecto–Cotización id_proyecto__id_cotizacion Contrato id_contrato
Cada clave se indexa en un archivo JSON independiente dentro de:
data/ingest/index_*.json
Formato de los snapshots
Los snapshots se almacenan como JSONL append-only:
{ «source»: «aleph», «entity»: «proyecto», «key»: «A516», «ts»: «2025-12-05T20:20:48Z», «payload»: { … } }
Nunca se sobrescriben versiones anteriores.
Consumo de datos 9.1. Modo online (consulta directa)
Uso típico:
exploración
dashboards vivos
debugging
from prodisys.aleph.queries import fetch_proyectos import pandas as pd
df = pd.DataFrame(fetch_proyectos())
9.2. Modo offline (snapshots congelados)
Uso típico:
análisis
joins pesados
histórico
reproducibilidad
from prodisys.ingest.snapshots import load_latest_by_key from pathlib import Path
BASE = Path(«data/ingest») proyectos = load_latest_by_key(BASE / «aleph_proyectos.jsonl»)
Ambos modos usan el mismo modelo lógico.
Qué NO cubre este módulo
ALEPH no cubre:
documentos (PDF, imágenes, escaneos)
agendas, notas, dosieres
inventarios
visitas técnicas
lógica de negocio avanzada
reporting final
Esos dominios viven en módulos separados.
Estado actual
ALEPH está considerado estable
La estructura es la referencia oficial
Cambios futuros deben respetar este contrato
Cualquier extensión debe:
reutilizar db.py
reutilizar queries.py
mantener compatibilidad con snapshots existentes
Documentos relacionados
docs/vistas_aleph.md → vistas y joins derivados
docs/documentos_proyecto.md → dosieres, agendas, archivos
docs/ingest.md → reglas generales de ingesta