Ledgerline
Una API de eventos en el edge con escrituras exactly-once y una cadena de hashes a prueba de alteraciones.
Código privado. 68 pruebas corren dentro del runtime real de workerd. Pídeme un recorrido.
La idea
Todo ledger, registro de auditoría y sistema de facturación comparte el mismo núcleo de integridad: un stream ordenado de eventos que debe aceptar cada escritura exactamente una vez y probar, después, que nada fue alterado. Ledgerline es ese núcleo, bien construido, corriendo en el edge de Cloudflare. No hay producto alrededor ni interfaz. Las garantías son el producto.
Lo que construí
Un Durable Object es dueño del lado de escritura de cada stream. Como es de un solo hilo, el orden fuerte por stream sale de la estructura, no de locks: números de secuencia monotónicos, registros de idempotencia, la cadena de hashes y los rollups por minuto se confirman en una sola escritura atómica en lote. D1 refleja los eventos como modelo de lectura eventualmente consistente, para paginación y consultas. Es un CQRS pequeño y honesto donde cada lado hace lo que le sale bien por estructura.
Cada evento se hashea sobre una forma canónica de JSON y se encadena a su antecesor. El endpoint de verificación recalcula la cadena desde el génesis y señala exactamente dónde se rompe, y detecta el truncado de la cola, no solo ediciones in situ. La forma canónica está fijada con vectores de prueba de respuesta conocida que coinciden con json.dumps de Python, así que un auditor externo puede verificar un stream sin correr mi código. La autenticación usa llaves hasheadas con SHA-256, un stream ajeno devuelve 404 y no 403 para que la existencia nunca se filtre, y el rate limiting es un token bucket por llave viviendo en su propio Durable Object.
Lo difícil
01
Exactly-once, definido con honestidad
La mayoría de los esquemas de idempotencia expiran las llaves con un TTL, lo que en realidad significa “exactamente una vez, por un rato”. Ledgerline reserva cada llave de idempotencia de por vida del stream, porque esa nota al pie es de las que terminan en incidente.
02
Serialización sin locks
Un Durable Object es de un solo hilo, pero un await dentro de un handler deja que otra petición se intercale. blockConcurrencyWhile cierra la ventana donde dos escritores podrían leer la misma cabeza y anexar los dos después de ella.
03
Verificación que detecta truncados
Una cadena de hashes que solo detecta eventos editados no ve una cola borrada: la cadena sigue verificando, solo que más corta. Mantener un registro de cabeza en O(1) hace que “alguien cortó el final” sea tan detectable como “alguien cambió el evento 42”.
Lo que sigue
Un pequeño stream público de solo lectura, para poder tocar el endpoint de verificación en vivo.