Mike (@mikerb95)CodeByMike

Formato extendido (precondiciones, flujo principal, flujos alternos, excepciones y postcondiciones) para los 10 casos de uso más críticos del sistema: los que involucran dinero, seguridad o estado que debe ser consistente ante fallos.

Caso de usoCU-04Iniciar sesión como administradorAdministrador (Mike)
DescripciónEl administrador se autentica con GitHub y accede al panel si su login está en la allowlist.
PrecondiciónEl administrador tiene una cuenta de GitHub válida. Su login está registrado en la allowlist de src/lib/auth.ts.
Secuencia normal
PasoAcción
1El administrador visita /admin sin sesión activa.
2El middleware detecta ausencia de sesión y redirige a /api/auth/signin.
3El administrador autoriza la app OAuth de GitHub.
4Auth.js valida el login contra la allowlist.
5Se emite un JWT de sesión y se registra el dispositivo en admin_sessions.
6El administrador es redirigido al panel /admin.
Flujos alternos
Login no autorizado
  1. 1.GitHub autentica correctamente pero el login no está en la allowlist.
  2. 2.Auth.js rechaza la sesión y muestra error de acceso denegado.
PostcondiciónEl administrador tiene una sesión JWT activa y un registro en admin_sessions con IP y user-agent.
Excepciones
PasoAcción
1GitHub OAuth no disponible: el login falla con mensaje de error genérico, sin exponer detalles internos.
Caso de usoCU-09Recibir alerta de monitor caídoCron externo (cron-job.org / Vercel Cron)
DescripciónEl cron externo dispara el chequeo, detecta una caída, abre un incidente y notifica por push.
PrecondiciónExiste un monitor activo y no pausado en la tabla monitors. El cron externo tiene configurado el CRON_SECRET válido.
Secuencia normal
PasoAcción
1El cron externo llama a /api/cron/uptime-check con el secreto.
2El sistema itera los monitores activos y hace la petición HTTP configurada (método, texto esperado, umbral de latencia).
3La respuesta falla (status inesperado, timeout o texto ausente).
4Se inserta un monitor_check con ok=false.
5Si es el primer fallo consecutivo, se abre un monitor_incidents con startedAt.
6Se actualiza monitors.lastStatus a "down" y se dispara una notificación push (ntfy).
Flujos alternos
Recuperación
  1. 1.Un chequeo posterior tiene éxito.
  2. 2.Se cierra el incidente abierto con resolvedAt y durationSec.
  3. 3.Se notifica la recuperación.
Degradación por latencia
  1. 1.La respuesta es exitosa pero supera latencyThresholdMs.
  2. 2.lastStatus pasa a "degraded" sin abrir incidente.
PostcondiciónEl estado materializado del monitor refleja el último chequeo; el historial permite reconstruir el SLO.
Excepciones
PasoAcción
1El endpoint del monitor no responde en absoluto (timeout de red): se registra como fallo con error de timeout.
Caso de usoCU-12Procesar un pago con idempotenciaPasarela de pagos (Wompi)
DescripciónLa pasarela envía un webhook de pago; el sistema aplica el evento respetando idempotencia y orden.
PrecondiciónExiste un payment en estado created o pending con un idempotencyKey único.
Secuencia normal
PasoAcción
1La pasarela (Wompi) envía un webhook con el resultado de la transacción.
2El sistema busca el payment por reference/gatewayTxId.
3Se registra el evento crudo en payment_events (incluyendo si es duplicado o fuera de orden).
4Si el evento es válido y en orden, se aplica la transición de estado (created→pending→approved/declined).
5Se responde 200 a la pasarela para confirmar recepción.
Flujos alternos
Evento duplicado
  1. 1.El gatewayTxId ya fue procesado.
  2. 2.Se marca duplicate=true en payment_events.
  3. 3.No se modifica el estado del payment.
Evento fuera de orden
  1. 1.Llega un evento "pending" después de uno "approved".
  2. 2.Se marca outOfOrder=true.
  3. 3.El estado terminal previo se conserva (nunca retrocede).
PostcondiciónEl estado del payment refleja fielmente la transacción real, con bitácora completa auditable para sustentación.
Excepciones
PasoAcción
1El monto del evento no coincide con el del payment: se marca amountMismatch=true y se genera una alerta; el evento nunca se aplica.
Caso de usoCU-14Bloquear una IP maliciosaAdministrador (Mike)
DescripciónEl sensor clasifica un request hostil; el administrador (o el auto-block) añade la IP a la blocklist con TTL.
PrecondiciónEl sensor de seguridad (sensor.ts) está observando requests entrantes.
Secuencia normal
PasoAcción
1Llega un request al middleware.
2observeRequest clasifica el request contra las firmas conocidas (classify.ts).
3Se detecta una firma de severidad alta/crítica (p. ej. intento de path traversal).
4Se registra un security_events con category, severity y ruleId.
5El cron de auto-block evalúa la reincidencia de esa IP y decide bloquearla con TTL escalonado (1h → 24h → 7d).
6La IP queda en blocked_ips con expiresAt obligatorio.
Flujos alternos
Bloqueo manual
  1. 1.El administrador revisa un evento en el panel y decide bloquear la IP manualmente.
  2. 2.Se inserta en blocked_ips con source=manual.
PostcondiciónRequests posteriores de esa IP reciben 403 seco hasta que expire el bloqueo.
Excepciones
PasoAcción
1La lectura de blocklist falla (timeout de DB): el middleware falla abierto y deja pasar el request (nunca bloquea por error interno).
Caso de usoCU-18Consultar documentación del proyectoAdministrador (Mike)
DescripciónEl administrador navega /docs para revisar requerimientos, casos de uso, diagramas y el kanban del propio portfolio.
PrecondiciónEl administrador tiene sesión activa en /admin.
Secuencia normal
PasoAcción
1El administrador hace clic en "Documentación" en la sidebar.
2Se muestra el hub /docs con visión general, alcance y mapa de subpáginas.
3El administrador navega a una subpágina (RF, RNF, CU, diagramas o kanban) usando DocsNav.
4La página renderiza el contenido desde src/data/documentacion.ts o src/data/iteraciones-portfolio.ts.
Flujos alternos
Consulta de diagrama Mermaid
  1. 1.El administrador entra a una página de diagrama de secuencia, clases u objetos.
  2. 2.El navegador renderiza el diagrama Mermaid desde el texto embebido en la página.
Consulta de diagrama con motor propio
  1. 1.El administrador entra a una página de diagrama BPMN, de despliegue, de comunicación, de actividades o de componentes.
  2. 2.El servidor genera el SVG desde el modelo tipado de src/data/ con el motor de layout correspondiente de src/lib/; el navegador no ejecuta JavaScript para dibujarlo.
PostcondiciónEl administrador cuenta con la documentación de ingeniería completa del proyecto sin salir del panel.
Caso de usoCU-06Registrar y dar seguimiento a un proyectoAdministrador (Mike)
DescripciónEl administrador crea un proyecto, registra interacciones de seguimiento y documenta decisiones de arquitectura.
PrecondiciónEl administrador tiene sesión activa. Opcionalmente existe un cliente en la tabla clients al que asociar el proyecto.
Secuencia normal
PasoAcción
1El administrador crea el proyecto desde /admin/projects con POST /api/admin/projects (requiere slug y title), quedando en estado "activo" y no visible al público.
2Registra una interacción de seguimiento (llamada, reunión, tarea) con POST /api/admin/interactions, insertando en la tabla interactions con tipo, título, cuerpo y próxima acción.
3Marca la interacción como resuelta con PUT /api/admin/interactions (done, doneAt).
4Documenta una decisión de arquitectura con POST /api/admin/projects/[id]/adrs, insertando en project_adrs (contexto, decisión, justificación, estado).
5Opcionalmente marca el ADR como isPublic para exponerlo en la vitrina pública del proyecto.
Flujos alternos
Actualizar estado del proyecto
  1. 1.El administrador cambia el estado con PUT /api/admin/projects/[id] a pausado, completado o archivado.
Editar o borrar un ADR
  1. 1.El administrador corrige o elimina una decisión previa vía PUT/DELETE sobre project_adrs.
PostcondiciónEl proyecto queda con un historial trazable de interacciones y decisiones arquitectónicas en interactions y project_adrs.
Excepciones
PasoAcción
1El POST de creación llega sin slug o title: la API responde 400 sin tocar la base de datos.
Caso de usoCU-08Registrar costos y calcular P&LAdministrador (Mike)
DescripciónEl administrador registra el costo de un servicio, quién lo paga y cuánto se factura al cliente.
PrecondiciónEl proyecto existe. ENCRYPTION_KEY está configurada si el costo incluye credenciales cifradas. Existen tasas de cambio en app_settings para costos que no están en USD.
Secuencia normal
PasoAcción
1El administrador registra un servicio o costo (ciclo de facturación, moneda, quién paga y a quién se factura) insertando en project_services.
2Registra el ingreso cobrado o pendiente en la tabla finances.
3La vista del proyecto invoca projectPnL() (src/lib/pnl.ts) con los servicios, las finanzas y las tasas de cambio.
4projectPnL calcula el costo mensual equivalente en USD por servicio y lo proyecta desde la fecha de inicio del proyecto.
5Se obtiene el margen estimado restando el costo acumulado a los ingresos cobrados.
6El panel muestra ingresos, costo mensual/anual, costo acumulado y margen, coloreado según sea positivo o negativo.
Flujos alternos
Editar o eliminar un servicio
  1. 1.El administrador ajusta o borra un costo; el P&L se recalcula en el siguiente render, sin job asíncrono.
Costo sin tasa de cambio
  1. 1.Un costo en moneda sin tasa configurada se excluye del total y se muestra como advertencia con link a /admin/settings.
PostcondiciónEl P&L del proyecto refleja el nuevo costo o ingreso desde el siguiente GET del detalle, sin desfase.
Excepciones
PasoAcción
1Falta ENCRYPTION_KEY al guardar credenciales de un servicio: la API responde 500 pidiendo configurar la clave de cifrado.
Caso de usoCU-11Ejecutar backup manualAdministrador (Mike)
DescripciónEl administrador dispara un backup de la base de datos hacia Blob storage desde el panel.
PrecondiciónEl administrador tiene sesión activa (o, en el modo automático, el cron externo dispone del CRON_SECRET). Vercel Blob está habilitado en el proyecto.
Secuencia normal
PasoAcción
1El administrador dispara el backup manual desde /admin/backup.
2runBackup() consulta en paralelo las tablas de negocio (clients, projects, messages, finances, projectServices, projectAdrs, briefings, entre otras).
3Arma un dump JSON con metadatos de versión y fecha, más el contenido de cada tabla.
4Sube el dump a Vercel Blob como backups/portfolio-{fecha}-{timestamp}.json con acceso privado.
5Devuelve al panel la URL, el tamaño y el pathname del backup generado.
6El panel lista los últimos 30 backups ordenados por fecha para verificación visual.
Flujos alternos
Backup automático por cron
  1. 1.Vercel Cron llama al mismo endpoint con el CRON_SECRET en lugar de sesión de administrador, ejecutando runBackup() sin intervención manual.
Consultar historial sin ejecutar
  1. 1.El administrador solo lista los backups existentes, sin generar uno nuevo.
PostcondiciónQueda un archivo JSON inmutable en Vercel Blob con una fotografía completa de las tablas de negocio en ese momento.
Excepciones
PasoAcción
1Falla la conexión a la base de datos durante el respaldo: el endpoint responde 500 y el fallo queda registrado en logs, sin generar un blob parcial.
Caso de usoCU-13Inyectar un fallo de chaos engineeringAdministrador (Mike)
DescripciónEl administrador activa un flag de fallo temporal en una ruta y observa cómo el monitoreo lo detecta.
PrecondiciónEl administrador tiene sesión activa. La ruta objetivo no pertenece a /admin, /api/admin ni /api/auth (protegidas contra auto-sabotaje).
Secuencia normal
PasoAcción
1El administrador crea un flag de chaos desde /admin/lab/chaos, indicando tipo (latencia, error 500 o caída de servicio), ruta objetivo y TTL.
2El sistema valida el tipo y la ruta, aplica topes de seguridad (latencia máxima y TTL máximo) y calcula la expiración.
3El flag se inserta activo en la tabla chaos_flags y se invalida la caché para que aplique de inmediato.
4En cada request, el middleware evalúa los flags activos (con caché corta) y busca una coincidencia con la ruta solicitada.
5Si coincide, aplica el fallo simulado: introduce latencia, o responde error 500/503 con un header que identifica que es chaos.
6El chequeo de uptime del cron detecta la caída simulada en su siguiente sondeo, igual que detectaría una caída real.
Flujos alternos
Expiración natural
  1. 1.Al vencer el TTL, el flag deja de aplicarse automáticamente, sin que el administrador tenga que desactivarlo.
Botón de pánico
  1. 1.El administrador desactiva todos los flags activos de una sola vez desde el panel.
PostcondiciónLas rutas coincidentes sufren el fallo simulado hasta que el flag expira o se apaga manualmente, permitiendo validar que el monitoreo lo detecta.
Excepciones
PasoAcción
1Si la lectura de flags falla por un problema de base de datos, el middleware falla abierto: el request pasa limpio y nunca se cae el sitio real por un error del propio motor de caos.
Caso de usoCU-16Proyectar una presentación con el público en sincroníaCliente
DescripciónEl administrador proyecta un deck y lo controla desde su celular; el público lo sigue en sus propios dispositivos entrando por un QR o un PIN de cuatro caracteres.
PrecondiciónExiste un deck en la biblioteca: un archivo HTML autónomo con un <deck-stage> del que se extrajeron sus slides al subirlo.
Secuencia normal
PasoAcción
1El administrador pulsa Presentar y confirma en una pantalla que muestra el deck, su número de slides y la caducidad de la sesión.
2El sistema crea la sesión en Redis en estado lobby, con slide 0 y un PIN de cuatro caracteres (dos letras y dos dígitos) comprobado contra las rutas reservadas del sitio y contra los PIN ya en uso.
3La pantalla de reparto ofrece las dos vistas: la pantalla principal para el proyector y el control remoto, este último también como QR para escanearlo con el celular.
4La pantalla principal muestra a pantalla completa el QR hacia codebymike.tech/{pin} y el PIN escrito en grande; es la única vista que los muestra.
5El público escanea o teclea la dirección y ve la pantalla de espera con el título del deck.
6El administrador inicia desde el control remoto, que exige sesión de administrador y valida además el secreto de la sesión.
7Cada comando (anterior, siguiente, salto directo) se valida en el servidor contra el rango de slides, se persiste en Redis y se publica al bus.
8Cada dispositivo del salón, suscrito directamente al bus, recibe el cambio y salta al slide correspondiente en menos de 300 ms.
Flujos alternos
Espectador que llega tarde
  1. 1.Al conectar, el cliente pide el snapshot de la sesión y entra directamente al slide en curso, sin ver los anteriores.
Navegación directa
  1. 1.El administrador abre el selector de slides del control remoto y salta a uno concreto por su número y rótulo, en lugar de avanzar de a uno.
Cierre con feedback
  1. 1.Al pasar del último slide o pulsar Finalizar, las tres vistas muestran la misma pantalla de cierre con un QR hacia /feedback.
PostcondiciónAl terminar, la sesión pasa a estado ended y libera su PIN, que vuelve a quedar disponible para otra sesión. El estado efímero caduca solo por TTL sin dejar rastro en la base de datos.
Excepciones
PasoAcción
1Si se pierde la red del celular, al reconectar el control retoma el slide real: el servidor es la fuente de verdad y el cliente nunca impone su estado.
2Si un mensaje del bus se pierde (pub/sub no garantiza entrega), la resincronización periódica del snapshot corrige la pantalla en menos de diez segundos.
3Si el bus no llega a conectar, cada cliente cae a consultar el snapshot en bucle corto: se degrada la latencia, no la sincronía.
4Si el PIN no existe o la sesión terminó, la vista del público muestra la pantalla de cierre con el enlace de feedback, nunca un error crudo.
5Un texto de un segmento que no tenga forma de PIN devuelve el 404 normal del sitio sin llegar a consultar Redis.