Pulso · panel de obra

v0.0.2 · uat · 0 de 7 fases cerradas

0123456

Solo lectura

Para poder marcar veredictos, entra con tu correo: te llega un enlace y listo.

Comprobado de verdad

Nada de esto se afirma de memoria. Se llamó y se miró la respuesta.

0 Fundaciones ¿Hay dónde construir y cómo mirarlo? 1/4

esperando tu veredicto · v0.0.2

Qué queda construido

  • Worker desplegado en una URL viva con health público
  • D1 pulso-db / pulso-obra, KV pulso-cache, R2 pulso-media (uat y producción separados)
  • Este panel de obra, con los veredictos persistidos en D1 pulso-obra
  • Dependencias fijadas exactas, con un test que falla si alguien las desfija
  • Entrada por magic link: sin contraseña, sesión firmada con HMAC. Se adelantó aquí porque la auth era el bloqueo del proyecto y había que probarla el día 1
  • Esquema completo de D1 aplicado (la fase 1 solo tendrá que sembrar y consultar)

Guión de pruebas

  1. Abre https://uat-api.pulso.travel/entrar en el móvil, con datos, no en wifi. → Sale un campo de correo. El teclado del móvil aparece con la arroba a mano.
  2. Escribe lc@cooweb.co y toca «Enviarme el enlace». → Sale un mensaje verde diciendo que si ese correo tiene acceso, le llega un enlace.
  3. Abre el correo. Mira también en spam si no lo ves en un minuto. → Ha llegado un correo de Pulso con un botón «Entrar».
  4. Toca «Entrar» en el correo. → Vas directo al panel de obra, ya dentro, y arriba aparece tu correo.
  5. Sin girar el móvil, desliza de arriba abajo toda la página del panel. → Nada se sale por el lado. No hay barra de scroll horizontal ni hace falta zoom.
  6. Despliega la Fase 0 y lee los criterios del gate. → Entiendes cada criterio sin preguntarme qué significa.
  7. Marca ✓ o ✗ en cada criterio humano de la Fase 0. En al menos uno, escribe un comentario. → El botón se queda marcado. Aparece «guardado» con la hora.
  8. Vuelve a tocar el enlace del correo, el mismo de antes. → Dice que ese enlace ya no vale. Un magic link se usa una vez y solo una.
  9. Cierra el navegador del todo y vuelve a abrir https://uat-api.pulso.travel/obra → Sigues dentro y tus ✓/✗ y tu comentario siguen ahí. Nada se ha perdido.
  10. Lee la sección «Pendiente de atender» arriba del panel. → Tu comentario y cualquier ✗ aparecen ahí, esperando respuesta.

Gate

  • autoGET /v1/public/health responde 200 con status ok, versión y entorno

    Falla si: No responde 200, o el JSON no trae version y environment

  • autoNinguna dependencia usa rango (^, ~, *, x): todas fijadas exactas

    Falla si: Cualquier versión en package.json no es exacta

  • autoUn veredicto enviado al panel se guarda en D1 y reaparece al recargar

    Falla si: El veredicto no vuelve en GET /obra/api/estado

  • autoToda fase tiene pregunta, al menos un criterio auto y al menos uno humano

    Falla si: Una fase sin pregunta o sin gate humano

  • autoUna cookie de sesión manipulada, caducada o mal formada se rechaza

    Falla si: Cualquiera de los tres casos entra

  • autoUn magic link usado dos veces no entra la segunda, y caduca a los 15 minutos

    Falla si: El mismo enlace sirve dos veces

  • autoA un correo que no está en la lista no se le envía nada, y la respuesta es idéntica: no se filtra quién tiene acceso

    Falla si: La respuesta permite distinguir un correo con acceso de uno sin acceso

  • Abro la URL desde el móvil y el panel se lee sin hacer zoom ni scroll lateral

    Falla si: Tengo que hacer zoom, o algo se sale de la pantalla

  • Pido el enlace en /entrar, me llega al correo, lo toco y entro. Ya puedo marcar veredictos

    Falla si: No llega, llega a spam, o al tocarlo no entro

  • El plan de 7 fases que veo es el que quiero para Pulso, en ese orden

    Falla si: Falta algo importante, o el orden no tiene sentido para mí

  • Puedo marcar ✓/✗ y dejar un comentario en tres toques, sin teclear nada raro

    Falla si: Me cuesta encontrar dónde opinar, o se pierde lo que escribo

1 El feed, con datos sembrados ¿Esto se entiende y apetece? 0/3

sin empezar

Qué queda construido

  • Esquema D1 completo de Pulso y migración aplicada
  • 20 eventos reales de Castellón sembrados a mano, con sus locations
  • GET /v1/events, /events/:id, /events/nearby con bounding box + Haversine
  • Vista del feed a 360 px, sin auth, para juzgar si apetece

Gate

  • autoGET /v1/events?city=Castellón devuelve los eventos sembrados paginados
  • autoGET /v1/events/nearby filtra por radio real (Haversine), verificado con distancias conocidas
  • autoHaversine y bounding box tienen test con coordenadas de Castellón y distancias conocidas
  • Miro el feed y me apetece tocar algo. No parece una tabla de base de datos

    Falla si: Lo veo y no me dice nada, o no sé qué hacer con él

  • De un evento entiendo qué es, cuándo y dónde sin abrirlo

    Falla si: Tengo que abrir el detalle para saber si me interesa

  • Los 20 eventos me parecen de verdad de Castellón, no de relleno

    Falla si: Reconozco que son inventados

2 MCP y scraping real ¿La pieza cara funciona y trae datos de verdad? 0/2

sin empezar

Qué queda construido

  • Servidor MCP en mcp.pulso.travel con las 9 tools y 4 resources
  • Scraper real de vivecastellon.com con HTMLRewriter
  • Browser Rendering como plan B para las fuentes que van por JS (castello.es, dipcas.es)
  • source_hash para detectar cambios sin duplicar

Gate

  • autoUn cliente MCP se conecta y lista las 9 tools y los 4 resources
  • autoEl scraper extrae ≥10 eventos reales de vivecastellon.com con título y fecha

    Falla si: Extrae menos de 10, o alguno sin fecha parseable

  • autoScrapear dos veces la misma fuente no duplica eventos (source_hash)
  • Desde Claude pregunto "¿qué hay este finde en Castellón?" y me contesta con eventos reales

    Falla si: No conecta, o inventa eventos que no existen

  • Cojo 3 eventos que trajo el scraper y compruebo que existen de verdad

    Falla si: Alguno no existe, o la fecha o el sitio están mal

3 Con memoria: quién eres y qué te gusta ¿Recuerda lo que debe? 0/2

sin empezar

Qué queda construido

  • Preferencias, ubicación y modo acompañante persistidos
  • GET /v1/events/for-you cruzando preferencias × ubicación × compañía
  • Zero Trust conectado de verdad: Access Application sobre pulso-travel, IdP y service token. Solo falta el API token con Access:Edit

Gate

  • autoCon AUTH_MODE=access-jwt, un JWT sin firmar, caducado o con audience ajeno recibe 401, validado contra el JWKS real de pulso-travel

    Falla si: Alguno de los tres casos entra

  • autoEl mismo usuario entrando dos veces no crea dos filas
  • autofor-you ordena por relevance × peso de preferencia, verificado con pesos fijados
  • Entro con mi Google por Zero Trust y la app sabe quién soy sin que le diga nada

    Falla si: Me pide algo más, o no me reconoce al volver

  • Marco mis gustos, vuelvo mañana y el feed sigue ajustado a ellos

    Falla si: Se olvidó de lo que le dije

4 Con tiempo: crons y digest ¿Aguanta el paso de los días? 0/2

sin empezar

Qué queda construido

  • Cron de scraping diario 03:00 UTC vía Queue
  • Digest matutino pre-computado en KV a las 06:00
  • Cron de recordatorios cada 5 min y limpieza semanal
  • Días simulados: 7 ejecuciones seguidas sin duplicar ni romper

Gate

  • autoSimular 7 días de crons no duplica eventos ni deja tareas colgadas

    Falla si: Crecen los duplicados, o alguna tarea queda en running para siempre

  • autoGET /v1/users/me/digest se sirve de KV, no recalcula
  • autoLa limpieza archiva eventos de hace más de 7 días y no toca los vivos
  • Leo el digest de la mañana y me sirve. No es un listado, es un plan

    Falla si: Es un volcado de eventos sin criterio

  • Vuelvo tres días después sin tocar nada y hay eventos nuevos

    Falla si: La base está igual que la dejé

5 El circuito entero: tiempo real y avisos ¿Funciona de punta a punta? 0/2

sin empezar

Qué queda construido

  • Durable Object EventChannel con WebSocket y ring buffer de 50
  • Web Push real con VAPID (esto sí es gratis, va de verdad)
  • Durable Object SocialListener contra stub determinista (no hay claves de X aún)
  • Media a R2, servida por media.pulso.travel

Gate

  • autoDos clientes WS conectados al mismo evento reciben el mismo broadcast
  • autoAl reconectar, el cliente recibe los mensajes que se perdió (hasta 50)
  • autoEl payload de Web Push se cifra correctamente (ECDH + VAPID) y el push service lo acepta
  • autoEl social listening en modo stub lo dice en su respuesta: nunca finge ser real

    Falla si: Devuelve datos inventados sin marcarlos como stub

  • Me suscribo a un evento desde el móvil y me llega la notificación push de verdad

    Falla si: No llega, llega tarde, o llega sin decir de qué evento es

  • Con la app abierta pasa algo en un evento y lo veo aparecer sin recargar

    Falla si: Tengo que recargar para verlo

6 El canal real ¿Alguien lo quiere de verdad? 0/2

sin empezar

Qué queda construido

  • Dominios finales api / mcp / media .pulso.travel en producción
  • Docs con Scalar en /docs, público
  • Rutas entre eventos (nearest neighbour + Nominatim, sin Google)
  • Hot scoring y rate limiting

Gate

  • autoapi., mcp. y media.pulso.travel responden en producción con TLS válido
  • auto/docs y /v1/openapi.json responden sin auth y el spec valida
  • autoLa ruta entre 3 eventos no cruza la ciudad dos veces (orden mejor que el de entrada)
  • Un fin de semana lo uso yo de verdad para decidir qué hacer, sin forzarme

    Falla si: Abro otra cosa para decidir

  • Le paso la URL a alguien de Castellón sin avisar de que es un PoC

    Falla si: Me da vergüenza enseñarlo