Pulso · panel de obra

v0.4.0 · production · 3 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?

cerrada · 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?

cerrada · v0.1.0

Qué queda construido

  • 18 eventos reales de Castellón y provincia, extraídos de vivecastellon.com, cada uno con su URL de origen para poder comprobarlo
  • 11 sitios con coordenadas reales geocodificadas con Nominatim (OpenStreetMap)
  • GET /v1/events, /events/cities, /events/:id, /events/nearby con bounding box + Haversine
  • Feed en /feed a 360 px, con filtros por ciudad y categoría, y ficha de detalle

Guión de pruebas

  1. Abre https://uat-api.pulso.travel/feed en el móvil. → Sale una lista de planes. Nada se sale por el lado de la pantalla.
  2. Sin abrir ninguno, lee las tres primeras tarjetas. → De cada una sabes qué es, cuándo y dónde. Si tienes que abrirla para saberlo, es un ✗.
  3. Toca los filtros de arriba: prueba «Onda» y luego «Música». → La lista cambia. Los filtros se deslizan a lo ancho sin mover la página entera.
  4. Quita los filtros y toca «Ver por cercanía al centro», al final de la página. → Los planes salen ordenados por distancia, y cada uno dice a cuántos km está.
  5. Abre un evento cualquiera. → Ves cuándo, dónde, la distancia, la descripción y un botón a la fuente.
  6. En la ficha, toca «Ver en la fuente» y compara: título, fechas y sitio. → El evento existe de verdad en vivecastellon.com y los datos coinciden.
  7. Repite el paso 6 con otros dos eventos distintos, elegidos al azar. → Los tres existen. Si alguno es inventado o no cuadra, es un ✗.
  8. Toca «Ver en el mapa» en una ficha que tenga sitio concreto. → El mapa cae en el sitio correcto de Castellón, no en medio del campo ni en el mar.
  9. Vuelve al feed y prueba a combinar «Onda» con «Familia». → Dice que no hay nada con esos filtros, en vez de quedarse en blanco.
  10. Ahora la pregunta de verdad: ¿te apetece tocar algo de lo que ves? → Si el feed te parece una tabla de base de datos y no te dice nada, marca ✗ y dime por qué.

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

  • Cojo tres eventos al azar, abro su enlace a la fuente y compruebo que existen de verdad

    Falla si: Alguno no existe, o su fecha o su sitio no coinciden con la fuente

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

cerrada · v0.2.0

Qué queda construido

  • Servidor MCP en uat-mcp.pulso.travel con 11 tools y 4 resources, transporte Streamable HTTP sin sesión (no necesita Durable Objects)
  • add_event: Luis encuentra algo que falta y el agente lo mete, con geocodificación
  • research_event: el agente va a la web oficial y trae descripción e imagen reales
  • Scraper de vivecastellon.com con HTMLRewriter y dedup por source_hash
  • Las tools que aún no funcionan se niegan diciéndolo, para que el agente no invente

Guión de pruebas

  1. Añade el MCP a Claude Desktop o Codex con la URL y el token que te doy aparte. → Aparece «pulso» conectado, con 11 herramientas.
  2. Pregúntale: «¿qué hay este finde en Castellón?» → Contesta con eventos reales, con hora y sitio. Cada uno con su enlace de origen.
  3. Elige uno y pídele: «cuéntame más de ese». → Usa research_event y te resume lo que encontró, distinguiendo lo que NO encontró.
  4. Dile: «falta un evento, el [algo que tú sepas], es el [fecha] en [sitio]». → Lo añade con add_event y te da el enlace del feed para verlo.
  5. Abre ese enlace en el móvil. → El evento está ahí, con la fecha y el sitio que le dijiste.
  6. Pídele un evento inventado: «busca el Festival de Jazz de Villarreal de 2026». → Dice que no lo encuentra. Si se lo inventa, es un ✗ y el más grave de todos.
  7. Pídele: «avísame de ese evento». → Registra la suscripción Y te advierte de que el aviso todavía no llega (fase 5).
  8. Pídele: «hazme una ruta con tres de estos eventos». → Los ordena por cercanía y te avisa de que son distancias en línea recta.

Gate

  • autoUn cliente MCP se conecta y lista las 11 tools y los 4 resources
  • autoLas tools sin construir devuelven error diciendo en qué fase se hacen, y las que no encuentran nada dicen explícitamente que no se invente el resultado

    Falla si: Alguna devuelve datos vacíos o falsos como si fueran válidos

  • autoadd_event da de alta un evento con fechas en prosa, no duplica al repetirlo, y se niega si no entiende la fecha en lugar de inventarse una
  • autoSi el municipio geocodificado no es el pedido, se avisa en la respuesta al agente

    Falla si: Un evento se coloca en otro pueblo sin decir nada

  • 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)
  • Conecto el MCP en Claude o Codex y le pregunto «¿qué hay este finde en Castellón?»

    Falla si: No conecta, o me contesta con eventos que no existen

  • Le digo a Claude que falta un evento que yo conozco y lo añade. Luego lo veo en el feed

    Falla si: No lo añade, o lo añade con la fecha o el sitio mal

  • Le pido que investigue más sobre un evento y me trae información de la web oficial, no inventada

    Falla si: Se inventa datos, o no distingue lo que encontró de lo que no

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

esperando tu veredicto · v0.3.0

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