You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fase: 'Fase 19 · Charla Platzi Conf y presentaciones públicas',
816
+
nombre: 'Landing de la charla y presentaciones (slides) con estado en vivo',
817
+
rango: '18 jul 2026',
818
+
ghSince: '2026-07-18',
819
+
ghUntil: '2026-07-18',
820
+
commits: 16,
821
+
resumen:
822
+
'Landing propia para la charla en Platzi Conf con tema visual dedicado, y el módulo de slides (Fase 3) gana un endpoint público de estado de presentación y botón para compartir el enlace, dejando de depender de sesión admin para que la audiencia siga la charla en vivo.',
823
+
historias: [
824
+
{
825
+
id: 'PF-PZ-01',titulo: 'Como asistente a la charla, quiero una landing con la agenda y la forma de contactar al ponente',
fase: 'Fase 20 · Pulido visual y saneamiento de tech stack',
848
+
nombre: 'Fondo con profundidad (blobs), separación de navbar y parser único de tech stack',
849
+
rango: '18 jul 2026',
850
+
ghSince: '2026-07-18',
851
+
ghUntil: '2026-07-18',
852
+
commits: 15,
853
+
resumen:
854
+
'Retoque visual transversal: fondo con blobs degradados en BaseLayout para dar profundidad sin recargar el diseño, y un scrim detrás del navbar para separarlo del contenido al hacer scroll. En paralelo se resuelve una inconsistencia de datos: el tech stack de los proyectos se guardaba en formatos distintos (JSON vs texto plano) y cada vista lo parseaba a su manera; ahora hay un único parseTechStack reutilizado en ProjectCard y las páginas de detalle.',
855
+
historias: [
856
+
{
857
+
id: 'PF-PV-01',titulo: 'Como visitante, quiero una interfaz con más profundidad visual sin perder legibilidad',
fase: 'Fase 21 · Descarga de CV con huella y auditoría',
880
+
nombre: 'Descarga de CV con token de un solo uso, fingerprint y panel de estadísticas',
881
+
rango: '18 – 19 jul 2026',
882
+
ghSince: '2026-07-18',
883
+
ghUntil: '2026-07-19',
884
+
commits: 12,
885
+
resumen:
886
+
'Quién descarga el CV deja de ser invisible: /cv reutiliza el recolector de señales del lab de fingerprinting para capturar un hash de dispositivo antes de emitir un token de un solo uso (ventana de 5 min) que autoriza la descarga real. A diferencia de la demo efímera, aquí el registro es permanente (sin TTL) y las revisitas del mismo dispositivo se acumulan en vez de duplicar filas. /admin/lab/cv-downloads expone el historial completo al administrador.',
887
+
historias: [
888
+
{
889
+
id: 'PF-CV-01',titulo: 'Como visitante, quiero descargar el CV desde la página de contacto',
fase: 'Fase 22 · Rutas de aprendizaje y bloqueo escalado de IPs',
913
+
nombre: 'Open Security Labs con progreso persistente, IP blocking escalado y fixes de revisitas en fingerprinting',
914
+
rango: '19 jul 2026',
915
+
ghSince: '2026-07-19',
916
+
ghUntil: '2026-07-19',
917
+
commits: 20,
918
+
resumen:
919
+
'Se suma una sección educativa nueva: rutas de aprendizaje ("Linux Real" y más) con labs cronometrados y progreso que el visitante puede marcar como completado, persistido en educationLabProgress. En paralelo, la capa de seguridad gana bloqueo escalado de IPs (TTL creciente por reincidencia: 1h → 24h → 7d) con enforcement inline para honeypots además del cron de auto-block, y se corrige un bug de fondo en el lab de fingerprinting: joinDevice no reconocía correctamente las revisitas de un mismo dispositivo cuando el hash de la librería de referencia (libFpHash) variaba entre visitas.',
920
+
historias: [
921
+
{
922
+
id: 'PF-LE-01',titulo: 'Como visitante, quiero seguir rutas de aprendizaje con labs cronometrados y marcar mi progreso',
ok('blockIpEscalated calcula TTL creciente (1h → 24h → 7d) según el historial de bloqueos previos de la IP.'),
937
+
ok('Honeypots tocados se bloquean inline desde el middleware, sin esperar al cron de auto-block.'),
938
+
ok('Tests unitarios de blockIpEscalated y de la lógica de TTL en isBlocked.'),
939
+
],
940
+
},
941
+
{
942
+
id: 'PF-LE-03',titulo: 'Como visitante que revisita la sala de fingerprinting, quiero que el tablero me reconozca aunque el hash de la librería de referencia cambie',
ok('joinDevice usa el ID único de dispositivo (no la etiqueta) para decidir si es una revisita, y ya no depende de que libFpHash coincida exactamente.'),
947
+
ok('Tests con distintos escenarios de libFpHash (coincide, cambia, ausente) validando que la revisita se reconoce igual.'),
0 commit comments