Signperu
Firma electrónica de documentos PDF: el emisor arma un sobre, los firmantes firman desde un enlace con código por correo, y el PDF final se sella y se puede verificar públicamente.

El problema
Un contrato enviado por mensaje deja a cada parte esperando a ciegas, sin versiones ni un cierre claro, y nada impide que el archivo cambie después de firmado.
Qué construí
Construí un monolito modular (Spring Boot 4, Java 21, DDD hexagonal) con un frontend Angular 22. Los firmantes entran sin cuenta con un enlace y un código por correo; al completar, el sistema estampa las firmas, añade una página de evidencia y sella el PDF con PAdES y un sello de tiempo.
Resultado
Producto propio de acceso privado, con el ciclo completo: sobre, firma, sellado y verificación pública.
Decisiones que importaron
- 01
Evidencia, no solo una imagen
Cada firma guarda correo verificado, IP, navegador, hora, hash del PDF y la versión del consentimiento aceptado. La bitácora se encadena con hashes: alterar un registro rompe la cadena.
- 02
El PDF final se prueba solo
Se sella con PAdES B-T: firma con certificado propio más un sello de tiempo RFC 3161 de una autoridad externa, con una de respaldo. Sin sello, el sobre sigue en SELLANDO y se reintenta.
- 03
El enlace no basta
El token viaja en el fragmento de la URL, en la base solo queda su hash y hay que ingresar un código de 6 dígitos, con 5 intentos como máximo.
- 04
Eventos con outbox
Cada cambio de estado escribe sus eventos en una tabla outbox dentro de la misma transacción. Las tareas de fondo usan FOR UPDATE SKIP LOCKED y también se pueden disparar desde Cloud Scheduler.
- 05
Monolito, a propósito
Sin microservicios, Kafka ni Redis: costo sin beneficio a este volumen. Los contextos (sobres, documentos, identidad, notificaciones, auditoría) se hablan por fachadas y eventos.
- 06
Pensado para Cloud Run
Imagen Docker sin root, PDFs en un bucket privado, clave del sello en Secret Manager y Cloud Scheduler disparando las tareas de fondo.
Tecnologías
- Java 21
- Spring Boot 4
- PostgreSQL
- Angular 22
- PDFBox
- BouncyCastle
- Resend
- Cloud Run
- Cloud Storage
Modelo C4. La línea con pulso es el recorrido principal de una solicitud.
Nivel 1 · quién usa el sistema y con qué se conecta
Nivel 2 · las aplicaciones y almacenes que lo componen
Nivel 3 · los componentes dentro de la API
- Persona
- Sistema
- Contenedor
- Base de datos
- Externo
- Recorrido principal
- 01Emisor sube el PDF
- 02Sobre y campos
- 03Enlace y código
- 04Firma con evidencia
- 05Sellado PAdES
- 06Verificación pública