Skip to content

Stack técnico

Stack actual (implementado)

CapaTecnologíaVersión
RuntimeNode.js24 LTS
LenguajeTypeScript (strict)5.x
HTTPFastify5.x
Almacenamiento SQLbetter-sqlite311.x
Validaciónzod3.x
Cripto (Ed25519)hypercore-crypto (libsodium)3.x
Seeds BIP-39@scure/bip391.x
Loggerpino9.x
Monorepopnpm workspaces9.x
Testsvitest3.x
DocsVitePress1.x
FirmwarePlatformIO + framework Arduino (ESP32)

Planificado / en evaluación

CapaTecnologíaEstado
Serialización canónicaProtobuf (@bufbuild/protobuf en Node, nanopb en ESP32)Los esquemas existen, codegen inactivo — consulta ADR-001
Geolocalizaciónh3-jsPlanificado con las funciones de mapa
Operaciones de conjunto en filtrosRoaring BitmapsPlanificado con los filtros
App de escritorioTauri 2.xFase futura
Replicación de nodosLog de eventos firmado + sync entre paresEn diseño — consulta la Hoja de ruta

Estructura del repositorio

raiznet/
├── apps/
│   ├── server/          # Nodo Fastify (endpoints público + local)
│   ├── cli/             # Herramienta de operación y depuración
│   ├── website/         # Landing page raiznet.com
│   ├── dashboard/       # Dashboard web
│   └── prototype/       # Canvas de diseño de la UI (React + Vite)
├── packages/
│   ├── protocol/        # Esquemas .proto (formato canónico, planificado)
│   ├── crypto/          # Derivación de claves, firma, AES-256-GCM
│   └── core/            # Abstracciones compartidas
├── firmware/
│   ├── safraSense/      # Firmware ESP32 de referencia (sensor completo)
│   └── esp32-sensor/    # Ejemplo mínimo
└── docs/                # Este sitio

El firmware de producción del hardware SafraSense de Arateki vive en un repositorio separado; el firmware de este repositorio es la implementación de referencia abierta del protocolo.

Decisiones de diseño

No introducir sin discusión:

  • NestJS — demasiado pesado
  • Express — obsoleto frente a Fastify
  • ORMs — better-sqlite3 directo
  • Redis — no se justifica en esta etapa
  • Docker en dev — corre local
  • Kafka — innecesario

El papel de SQLite

Hoy, SQLite es el almacenamiento local primario del nodo: la ingesta valida un bloque y lo escribe directamente en raiznet_public.db / raiznet_private.db.

El objetivo de diseño es que la fuente de verdad pase a ser un log de eventos firmado y de solo anexado, con SQLite como índice derivado que puede borrarse y reconstruirse reproduciendo el log (consulta ADR-002). El esquema de tabla ancha ya está moldeado para eso:

  • Consultas agregadas rápidas (columnas REAL fijas por sensor)
  • Sin ORM — SQL directo con resultados tipados
  • Los nuevos tipos de sensor requieren añadir tres columnas (_plain, _cipher, _nonce) por campo