00-day-brief.md
Abrir documentoDay brief — 2026-08-09 — ALS-2
1. LOAD — restricciones del día
| Eje | Decisión | Motivo (diversidad) |
|---|---|---|
| Complejidad | Nivel 2 | Tras VOLTA (L1 fitness) no se repite L1. L2 = multi-rol JWT, CRUD de entidad core + máquina de estados + stats. |
| Sector | Energía / consumo doméstico | Primera vez en la serie (fitness, agro, mascotas, logística, legal, mayores, salud, museo, cocina). Prioridad en cola §6.2 memory. |
| Tipo de producto | Panel de lecturas de contador multi-rol | Tool ops RESIDENT + ADVISOR; no lead form público + inbox staff (anti-patrón post-VOLTA). |
| Auth | JWT multi-rol RESIDENT + ADVISOR | Directiva D-P1-05; todo el dominio de lecturas detrás de JWT. |
| Craft mínimo | ≥ VOLTA / SURCO densificado | L2 no baja craft visual ni profundidad de docs (D-P0-01). |
| Cierre | §1.1 completo en una iteración | Docs + Paper + app + Neon + smoke; sin “próximos pasos del L2 del día”. |
| Puerto API | 3009 | Evitar colisión con VOLTA (3008) y SURCO (3007). |
Anti-patrones a evitar (top del catálogo)
| ID | Anti-patrón | Mitigación hoy |
|---|---|---|
| AP-thin-docs | Docs de 1–2 líneas | Suite 00–20 con tablas, AC y criterios de aceptación |
| AP-generic-ui | UI “SaaS genérico” / “básica porque L2” | Palette maritime fog × navy × sea × coral; Sora + Nunito Sans |
| AP-no-auth | Panel sin login | JWT obligatorio en /api/readings* |
| AP-marketplace-copy | Lógica de marketplace / checkout | No catálogo, no ratings, no matching de proveedores |
| AP-lead-form-only | Solo form público + inbox staff (VOLTA-like) | Ambos roles autenticados; residente crea lecturas, asesor revisa |
| AP-fitness-agro | Reutilizar dominio de días previos | Energía hogar; Reading + Home + CUPS |
| AP-fake-research | Estadísticas inventadas como primarias | Solo hipótesis y supuestos etiquetados |
| AP-open-debt | Backlog de features del L2 del día | Vertical slice cerrado: home, login, list+stats, create, detail+status |
| AP-canvas-chaos | Paper sin bandas § | §1 UX · §2 Design+Public · §3 App · §4 Mobile · §5 States |
Barra de calidad actual (ratchet)
- Paper: bandas §1–§5, ≥8 artboards UX densos + DS + app + mobile + states.
- Angular alineado a tokens (fog/navy/sea/coral; no default Tailwind genérico).
- API Nest + Prisma + Neon con seed demo usable (2 users, 1 home, 5 readings).
- Smoke: login RESIDENT + POST reading + login ADVISOR + list + patch status;
ng buildo serve OK. - Docs en español, profundidad tipo portfolio (no stubs).
2. BRIEF — concepto del día
| Campo | Valor |
|---|---|
| Nombre | RELE |
| Eslogan | ”El consumo, a la vista.” |
| Una frase | Panel de lecturas de contador del hogar (kWh / periodo) con roles residente y asesor energético. |
| Tipo | Tool ops L2 — lecturas multi-rol (no marketplace, no lead form-only, no fitness/agro) |
| Roles | RESIDENT (Elena Marín) · ADVISOR (Toni Gil) |
| Dominio | User + Home + Reading (DRAFT | SUBMITTED | REVIEWED | FLAGGED) |
| Estilo | Fog #EEF1F4 × Navy #0C2340 × Sea #2F8F8C × Coral #E07A5F |
| Tipo | Sora (display) + Nunito Sans (UI) |
| Stack | Angular + NestJS + Prisma + Neon + Tailwind + JWT |
| Paper | https://app.paper.design/file/01KZJNCCMJ1FDHHPZZ923RWDWY |
| Neon | sparkling-snow-59844541 · API :3009 · Web :4200 |
| App | /Users/cristian/orca/rele-app/ · GitHub Criscode2022/rele-app |
Por qué L2 energía (y no otra cosa)
- Diversidad de sector: la serie no había tocado energía / sostenibilidad del hogar (primera de la cola memory §6.2).
- Complejidad L2 justa: dos roles con vistas filtradas, máquina de estados de lectura, create solo RESIDENT, patch status solo ADVISOR, stats con kWh agregados.
- Diferenciación vs VOLTA: VOLTA es form público + inbox coach; RELE es tool autenticado multi-rol (ambos JWT, no lead-form-only).
- Diferenciación vs SURCO: SURCO es cuaderno agro de parcelas/tareas; RELE es consumo energético (kWh, periodo, CUPS, nota de asesor).
- Metáfora de marca: rele evoca relé eléctrico / “releer” el contador; promesa de claridad del consumo, no de marketplace energético ni de app fitness.
Must-have del día (alcance L2)
| # | Entrega | Criterio done |
|---|---|---|
| 1 | Home marketing | Hero real, 3 pasos, CTAs por rol, footer demo |
| 2 | Login JWT | RESIDENT y ADVISOR; redirect a /lecturas |
| 3 | Lista lecturas + stats | Filtro por rol; chips de estado; kWh Σ; empty/error |
| 4 | Nueva lectura (solo RESIDENT) | period, kWh, costEur opcional, notes |
| 5 | Detalle + PATCH status (solo ADVISOR) | REVIEWED / FLAGGED + advisorNote |
| 6 | Empty / error | Sin lecturas; fallo de red en lista |
| 7 | Paper §1–§5 | UX process + DS + app + mobile + states |
| 8 | Docs 00–20 + README + executive | Portfolio ES, sin stubs |
Explicitamente fuera de alcance (no son deuda del día)
- Integración con contadores inteligentes / API de distribuidora
- Facturación, pagos o cambio de comercializadora
- Multi-vivienda avanzada / multi-tenant asesoría
- Gráficos históricos avanzados / forecasting
- Notificaciones email/SMS/push
- App nativa offline-first
- Compliance regulatorio (CNMC, etc.) como producto
3. Directivas activas aplicadas
| ID | Aplicación en RELE |
|---|---|
| D-P0-01 | L2 no reduce craft ni profundidad de docs |
| D-P0-02 | Hi-fi con media real (assets/hero.jpg), microcopy energía hogar |
| D-P0-03 | Angular + Nest + Neon + Tailwind + repo app |
| D-P0-04 | Canvas Paper en bandas §1–§5 con labels |
| D-P0-05 | Hero fotorrealista en case y app |
| D-P0-06 | Cierre §1.1 sin backlog del alcance L2 |
| D-P1-01 | ≥8 artboards UX en Paper (stakeholders → datos) |
| D-P1-02 | Tokens fog/navy/sea/coral en Angular |
| D-P1-03 | apps/api + apps/web independientes |
| D-P1-05 | JWT en todas las rutas de lecturas |
| D-P1-06 | Smoke login + GET/POST/PATCH readings |
4. Cuentas demo
| Rol | Nombre | Password | |
|---|---|---|---|
| RESIDENT | Elena Marín | casa@rele.energy | password123 |
| ADVISOR | Toni Gil | asesor@rele.energy | password123 |
Seed de referencia: vivienda Piso Ruzafa (C/ Sueca 18, 3º · València · CUPS ES0021000000000001AB); 5 Reading con códigos RE-0809-01…05 (estados REVIEWED, SUBMITTED, FLAGGED).
Supuestos (no investigación primaria)
- Hogares y asesores energéticos coordinan lecturas por WhatsApp, Excel y capturas de contador.
- El residente necesita un historial por periodo con referencia corta.
- El asesor necesita una cola de revisión con nota y estados claros (ok / revisar tarifa).
5. Criterio de cierre del día
- Brief de diversidad y anti-patrones documentado
- Producto definido (no marketplace, no fitness, no agro, no lead-form-only)
- Implementación runnable API :3009 / web :4200
- Documentación portfolio 00–20 + presentation + README
- Paper file enlazado y referenciado por bandas
- Hipótesis vs investigación marcadas (sin stats falsas)
Estado del brief: listo para EXECUTE y entrega de caso.
00-paper-reference.md
Abrir documentoReferencia Paper — RELE
| Campo | Valor |
|---|---|
| File ID | 01KZJNCCMJ1FDHHPZZ923RWDWY |
| URL | https://app.paper.design/file/01KZJNCCMJ1FDHHPZZ923RWDWY |
| Nombre | RELE — Daily UX 2026-08-09 |
| Producto | Panel lecturas kWh multi-rol RESIDENT + ADVISOR (L2) |
| Artboards | ~22 (+ labels de banda) |
| Bandas | §1 UX · §2 Design + Public · §3 App · §4 Mobile · §5 States |
| Idioma UI | es-ES |
| Media | assets/hero.jpg (contador / entorno doméstico energía) |
1. Mapa de canvas (bandas jerárquicas)
| § | Banda | Propósito | Artboards clave |
|---|---|---|---|
| 1 | UX PROCESS | Investigación y modelo de servicio (densidad visual) | Cover, Stakeholders, Personas, JTBD, Journey, Blueprint, IA, Datos |
| 2 | DESIGN + PUBLIC | Sistema visual y cara pública | Design System, Home marketing, Login |
| 3 | APP | Flujos autenticados desktop | Lecturas list + stats, Nueva lectura, Detalle |
| 4 | MOBILE | Móvil residente / asesor en visita | List / create mobile |
| 5 | STATES | Resiliencia UI | Empty lecturas, Error red |
Layout canvas (referencia): origen (0,0) · gaps ~80px · bandas Y orientativas: UX ~100 / Design ~2180 / App ~3980 / Mobile ~4880 / States ~5680.
2. Inventario de artboards
§1 — UX PROCESS
| Label | Nombre | Contenido |
|---|---|---|
| 1-0 | §1 UX PROCESS | Etiqueta de banda |
| 2-0 | UX-00 Cover | Portada RELE, eslogan, fecha 2026-08-09, L2 energía, roles, navy + sea |
| 3-0 | UX-01 Stakeholders | Mapa interés/influencia: residente, asesor, familia, comercializadora (bajo), regulador (fuera v1) |
| 4-0 | UX-02 Personas | Elena Marín (RESIDENT) · Toni Gil (ADVISOR) — goals, pains, quote |
| 5-0 | UX-03 JTBD | Job principal + funcional/emocional/social + MoSCoW / stories Must |
| 6-0 | UX-04 Journey | 5 fases residente: descubre → entra → registra lectura → espera revisión → ve nota |
| 7-0 | UX-05 Blueprint | Frontstage panel · backstage asesor · sistemas Neon/JWT · fallos red/estado |
| 8-0 | UX-06 IA | Sitemap público/auth; navegación y permisos por rol |
| 9-0 | UX-07 Datos | ERD: User, Home, Reading + enums Role, ReadingStatus |
§2 — DESIGN + PUBLIC
| Label | Nombre | Contenido |
|---|---|---|
| A-0 | §2 DESIGN + PUBLIC | Etiqueta de banda |
| B-0 | 00 Design System | Color fog/navy/sea/coral, tipo Sora+Nunito Sans, botones, badges estado, cards |
| C-0 | 01 Home | Nav, hero + media, 3 pasos, CTAs rol, footer demo |
| D-0 | 02 Login | Split navy/form; email/password; hint demo |
§3 — APP (desktop)
| Label | Nombre | Contenido |
|---|---|---|
| E-0 | §3 APP | Etiqueta de banda |
| F-0 | 03 Lecturas | Lista + stats (total, abiertas, kWh Σ); badge rol; CTA nueva (RESIDENT) |
| G-0 | 04 Nueva lectura | Form period / kWh / coste / notas |
| H-0 | 05 Detalle | Código RE-…, kWh, coste, estado, notas, acciones ADVISOR |
§4 — MOBILE
| Label | Nombre | Contenido |
|---|---|---|
| I-0 | §4 MOBILE | Etiqueta de banda |
| J-0 | 06 Mobile list / new | Vista ~390px; touch targets ≥44px |
§5 — STATES
| Label | Nombre | Contenido |
|---|---|---|
| K-0 | §5 STATES | Etiqueta de banda |
| L-0 | 07 Empty | Sin lecturas; CTA registrar (RESIDENT) |
| M-0 | 08 Error | Fallo de carga / red; reintento |
3. Checklist de densidad (anti thin-frames)
| Criterio | §1 UX | §2 DS/Public | §3–4 App | §5 States |
|---|---|---|---|---|
| Jerarquía tipográfica visible | Sí | Sí | Sí | Sí |
| Microcopy real (no lorem) | Sí | Sí | Sí | Sí |
| Tokens de color aplicados | — | Sí | Sí | Sí |
| Datos de seed creíbles | Personas | Demo emails | Códigos RE-… | Empty realista |
| Media / iconografía | Cover | Hero | Badges | Alertas |
4. Mapeo Paper → Angular
| Artboard | Ruta app | Componente |
|---|---|---|
| C-0 Home | / | HomePage |
| D-0 Login | /login | LoginPage |
| F-0 Lecturas | /lecturas | ReadingsPage |
| G-0 Nueva | /lecturas/nueva | ReadingNewPage |
| H-0 Detalle | /lecturas/:id | ReadingDetailPage |
| J-0 Mobile | mismas rutas, viewport estrecho | responsive |
| L-0 Empty | /lecturas (0 items) | empty state en lista |
| M-0 Error | lecturas | mensajes error en página |
5. Tokens de diseño en Paper
| Token | Valor | Uso |
|---|---|---|
| Fog / bg | #EEF1F4 | Fondo de página |
| Surface | #FFFFFF | Cards, header |
| Navy / ink | #0C2340 | Primary dark, texto fuerte, CTAs navy |
| Navy soft | #D8E4F0 | Fondos suaves / secciones |
| Navy strong | #071628 | Hover / énfasis |
| Sea | #2F8F8C | Acento marca, CTAs primarios mar |
| Sea soft | #D4EDEC | Badges REVIEWED, nota asesor |
| Sea strong | #247370 | Hover sea |
| Coral | #E07A5F | Alertas, FLAGGED, abiertas |
| Coral soft | #F8E4DD | Fondos error / flag |
| Muted | #5A6B7D | Texto secundario |
| Border | #D0D8E0 | Bordes cards |
| Display | Sora | Títulos |
| UI | Nunito Sans | Cuerpo y UI |
6. Notas de handoff visual
- Badges de estado: DRAFT muted · SUBMITTED navy soft · REVIEWED sea · FLAGGED coral.
- Login split: panel izquierdo navy con claim; form a la derecha sobre fog/surface.
- Stats strip: TOTAL | ABIERTAS (coral) | kWh Σ (sea soft).
- Código de lectura siempre monospaced o tracking-wide en sea:
RE-MMDD-XXX.
01-project-definition.md
Abrir documento01 — Definición de proyecto — RELE
1. Identidad
| Campo | Valor |
|---|---|
| Nombre | RELE |
| Significado | Relé eléctrico + “releer” el contador: el consumo deja de ser opaco |
| Eslogan | ”El consumo, a la vista.” |
| Una frase | Panel de lecturas de contador del hogar (kWh por periodo) con revisión del asesor energético. |
| Sector | Energía / sostenibilidad del hogar |
| Tipo | Tool ops multi-rol JWT — Nivel 2 |
| Plataforma | Web responsive (móvil residente + desktop asesor) |
| Mercado demo | España (vivienda en València en seed) |
| Idioma | es-ES |
| Fecha caso | 2026-08-09 |
2. Problema
Principal ([HIPÓTESIS] de diseño)
Los hogares y asesores energéticos gestionan lecturas de contador por WhatsApp, Excel y capturas borrosas. El residente no tiene un historial con referencia; el asesor no tiene una cola con estado (enviada / revisada / a revisar) ni nota estructurada.
Secundarios
| Problema | Quién lo sufre | Efecto |
|---|---|---|
| “Te mando foto del contador” en hilos | Residente | No hay acuse ni código de referencia |
| Hojas sueltas / Excel local | Asesor | Difícil priorizar revisiones del mes |
| Sin periodo ni kWh estructurados | Ambos | Llamadas de ida y vuelta |
| Sin máquina de estados | Asesor | Se pierde qué ya se validó o se marcó anómalo |
Supuestos (no investigación primaria propia)
- S1 [SUPUESTO]: Hogares y asesorías pequeñas no necesitan un EMS industrial; sí un panel de lecturas con estado.
- S2 [SUPUESTO]: El residente prefiere registrar periodo + kWh en 1 pantalla a crear tickets genéricos.
- S3 [SUPUESTO]: El valor inmediato está en captura estructurada + pipeline de revisión, no en IoT ni cambio de comercializadora.
Hipótesis de producto
| ID | Hipótesis | Señal de validación (futura) |
|---|---|---|
| H1 | Un form de lectura con periodo y kWh reduce capturas ambiguas | ↓ “¿de qué mes era?” post-envío |
| H2 | Inbox con estados SUBMITTED→REVIEWED/FLAGGED acelera el cierre de revisión | Mediana tiempo SUBMITTED→REVIEWED |
| H3 | Códigos cortos RE-MMDD-XXX facilitan referencia oral | Uso del código en WhatsApp/llamada |
| H4 | Nota de asesor visible para el residente cierra el loop de confianza | % lecturas con advisorNote leída |
No se afirman estadísticas de mercado inventadas. Todo lo anterior es razonamiento de diseño etiquetado.
3. Propuesta de valor
| Para | Valor |
|---|---|
| Residente (Elena) | Registra kWh por periodo, ve histórico y notas del asesor. |
| Asesor (Toni) | Cola de revisiones, marca REVIEWED o FLAGGED con nota. |
| Asesoría / hogar | Canal digital mínimo viable sin marketplace ni EMS enterprise. |
No es RELE
| Excluido | Por qué |
|---|---|
| Marketplace de tarifas o comercializadoras | Matching multi-proveedor ≠ tool de lecturas |
| App fitness / club / lead form (VOLTA) | Dominio y patrón de producto distintos |
| Cuaderno agro / flota / legal | Dominios de otros días de la serie |
| SaaS multi-tenant con billing IoT | Complejidad L3/L4 |
| Integración contador inteligente nativa | Fuera del job “lectura a la vista” v1 |
4. Objetivos
Negocio / caso de estudio
- Demostrar vertical slice L2 energía con JWT multi-rol y dominio Reading + Home.
- Portfolio coherente: Paper + docs + app runnable.
Usuario
| Rol | Objetivo medible en demo |
|---|---|
| Residente | Crear lectura en < 2 min; ver código RE-… en lista |
| Asesor | Marcar REVIEWED / FLAGGED en < 3 taps desde el detalle |
No objetivos v1 (explícitos)
- Lectura automática del contador / OCPP / API distribuidora
- Comparador de tarifas con contratación
- Multi-vivienda con permisos granulares por hogar
- Chat in-app
- Export contable fiscal
5. Roles y permisos (resumen)
| Acción | Público | RESIDENT | ADVISOR |
|---|---|---|---|
| Ver home marketing | Sí | Sí | Sí |
| Login JWT | — | Sí | Sí |
| Listar lecturas | No | Propias | Todas (demo) |
| Ver stats summary | No | Propias | Globales |
| POST lectura | No | Sí | No (403) |
| Ver detalle | No | Si residentId propio | Sí |
| PATCH status + advisorNote | No | No (403) | Sí |
6. Métricas (modelo, no instrumentadas en v1 salvo base)
| Tipo | Métrica | Definición |
|---|---|---|
| North Star | Lecturas REVIEWED / mes | Revisiones realmente cerradas |
| Activación | 1ª lectura SUBMITTED del residente | POST create |
| Ops | % SUBMITTED revisadas en 7 días | SUBMITTED → REVIEWED/FLAGGED |
| Calidad datos | % FLAGGED / total | Señal de anomalía o tarifa |
| UX | Tiempo form complete | Mediana en analytics futuro |
7. Alcance funcional v1 (L2)
| Módulo | Incluido |
|---|---|
| Home pública | Hero, 3 pasos, CTAs rol, footer demo |
| Auth | POST /api/auth/login → JWT accessToken |
| Lecturas | GET list, GET stats, GET by id, POST create, PATCH status |
| UI estados | Loading implícito, empty, error de red |
| Seed | 2 users, 1 home, 5 readings |
8. Criterios de aceptación de producto
- Un residente autenticado puede crear una lectura (period + kWh) y recibir un código
RE-…. - Sin token, GET/POST/PATCH
/api/readings*responden 401. - Un asesor puede iniciar sesión, ver la cola completa y stats (total, open, kwhTotal).
- El detalle permite al asesor transicionar a REVIEWED o FLAGGED con nota opcional.
- El residente no puede PATCH status (403); el asesor no puede POST create (403).
- La home comunica energía hogar y claridad de consumo, no marketplace ni fitness.
9. Stack y artefactos
| Capa | Detalle |
|---|---|
| Frontend | Angular + Tailwind · puerto 4200 |
| Backend | NestJS · puerto 3009 |
| DB | Neon PostgreSQL · Prisma · project sparkling-snow-59844541 |
| Auth | JWT (passport/strategy en API) |
| Diseño | Paper 01KZJNCCMJ1FDHHPZZ923RWDWY |
| Repo app | /Users/cristian/orca/rele-app/ · GitHub Criscode2022/rele-app |
10. Riesgos y mitigaciones
| Riesgo | Impacto | Mitigación v1 |
|---|---|---|
| Expectativa de lectura automática | Decepción | Copy “registras la lectura”; sin IoT |
| Confundir con comparador de tarifas | Expectativa marketplace | Marca panel de lecturas, no matching |
| PII + CUPS en lecturas | Privacidad | Solo JWT; doc 11; seed demo |
| kWh mal tipados | Datos basura | Validación @IsNumber() @Min(0) server |
| Confundir FLAGGED con error técnico | Ansiedad usuario | Microcopy “revisar tarifa / anomalía” en guía de contenido |
02-ux-research-strategy.md
Abrir documento02 — Estrategia de investigación UX — RELE
Importante: este documento contiene artefactos de diseño y razonamiento secundario.
No hay entrevistas de campo primarias ni estadísticas inventadas presentadas como dato medido.
Etiquetas: [COMPROBADO] en producto, [SUPUESTO], [HIPÓTESIS], [DECISIÓN DE DISEÑO].
1. Objetivos de investigación (del caso)
| Objetivo | Método en este caso | Salida |
|---|---|---|
| Entender roles hogar + asesoría energética | Modelado de stakeholders + personas | §3–4 |
| Definir job principal | JTBD + stories Must | §5 |
| Mapear fricción de coordinación | Journey + service blueprint | §6–7 |
| Traducir a requisitos L2 | Matriz hallazgo → requisito → feature | §8 |
2. Fuentes y límites
Fuentes admisibles (secundarias / operativas)
- Conocimiento general de consumo doméstico (factura, contador, periodo de facturación).
- Analogía operativa con tools multi-rol de la serie (SURCO tareas, FIRME casos) — no copiar dominio.
- Restricciones ALS-2 de diversidad (sector energía libre; no marketplace; no lead-form-only; no fitness/agro).
Límites éticos de verdad
| Prohibido | Permitido |
|---|---|
| “El 68% de hogares pierde lecturas por WhatsApp” sin fuente | “[SUPUESTO] la coordinación informal es frecuente en asesoría doméstica” |
| Citas de usuarios ficticios como entrevistas reales | Quotes de persona etiquetadas como constructo de diseño |
| NPS inventado | Hipótesis H1–H4 con métrica futura |
3. Stakeholders
| Stakeholder | Influencia | Interés | Necesidad principal |
|---|---|---|---|
| Residente titular (RESIDENT) | Alta | Muy alta | Registrar y ver consumo por periodo |
| Asesor energético (ADVISOR) | Media–Alta | Alta | Cola de revisión y cierre con nota |
| Familia conviviente | Baja formal | Media | Entender picos (fuera de multi-user v1) |
| Comercializadora | Media potencial | Baja en v1 | No es marketplace ni integración |
| Regulador / CNMC | Alta potencial | Baja en v1 | Fuera de alcance L2 (no simular compliance) |
| Fabricante de contadores | Baja | Baja | IoT fuera de v1 |
Mapa de poder (resumen)
- Decisor de adopción en hogar: RESIDENT (titular de la vivienda / factura).
- Usuario frecuente de revisión: ADVISOR.
- Riesgo de rechazo: si la app pide más datos que un Excel sin devolver claridad de estado y nota.
4. Personas
P1 — Elena Marín · RESIDENT
| Campo | Detalle |
|---|---|
| Edad / contexto | ~38 años; piso en Ruzafa (València); trabaja híbrido |
| Digital | Alta (banca, apps); poca paciencia con formularios largos |
| Goals | Tener el consumo “a la vista”; no perder lecturas en el chat |
| Pains | Capturas de contador; no sabe si el asesor ya miró el mes |
| Quote de diseño | “Si no está en el panel, no cuentes con que lo he mandado.” |
| Email demo | casa@rele.energy |
Escenario: A mediados de agosto registra la lectura de 2026-08 (245 kWh), ve código RE-… y espera REVIEWED o nota FLAGGED.
P2 — Toni Gil · ADVISOR
| Campo | Detalle |
|---|---|
| Edad / contexto | ~44 años; asesor energético independiente / pequeña asesoría |
| Digital | Media–alta; prefiere desktop para revisión, móvil en visita |
| Goals | Ver cola SUBMITTED, validar o flaggear, dejar nota útil |
| Pains | Excel mezclado; no sabe qué ya revisó; sin CUPS a mano |
| Quote de diseño | “Dame periodo, kWh y CUPS. Yo marco si hay que revisar tarifa.” |
| Email demo | asesor@rele.energy |
Escenario: Abre RELE, filtra abiertas, entra en RE-0809-03, marca REVIEWED o FLAGGED con nota.
Anti-persona
| Quién | Por qué no es target v1 |
|---|---|
| Operador de EMS industrial multi-sede | Necesita SCADA, multi-tenant y SLAs → L3/L4 |
| Usuario solo “comparar tarifas y contratar” | Producto marketplace/comparador, no lecturas |
| Coach de club deportivo | Dominio VOLTA; no energía |
5. JTBD y user stories
Job principal
Cuando llega el cierre de periodo o la visita del asesor,
quiero registrar o revisar lecturas de contador con kWh y estado,
para tener el consumo a la vista sin perseguirse por WhatsApp.
Jobs secundarios
| Job | Rol |
|---|---|
| Ver cuántas lecturas abiertas hay | Ambos (scope distinto) |
| Dejar una nota de revisión legible | ADVISOR |
| Referir una lectura por código corto en llamada | Ambos |
Stories Must (v1)
| ID | Story | AC resumido |
|---|---|---|
| E1 | Como usuario, inicio sesión con email/password y recibo JWT | 200 + accessToken; 401 si mal |
| E2 | Como RESIDENT, listo mis lecturas y un summary (total, open, kwhTotal) | GET list + stats filtrados |
| E3 | Como ADVISOR, listo todas las lecturas de la demo | GET sin filtro resident |
| E4 | Como RESIDENT, creo lectura con period y kWh | POST; status SUBMITTED; code RE-… |
| E5 | Como ADVISOR, cambio estado a REVIEWED o FLAGGED con nota | PATCH status + advisorNote |
| E6 | Como RESIDENT, no puedo PATCH status | 403 |
| E7 | Como visitante, entiendo el valor en la home | CTAs “Soy residente / Soy asesor” |
Should / Could (fuera de L2 del día, no deuda)
- Selector multi-vivienda.
- Gráfico de tendencia kWh.
- Adjunto foto del contador.
- Notificaciones al marcar FLAGGED.
- Filtros UI por estado.
6. Journey — mes de Elena (happy path)
| Fase | Acción | Pensamiento | Touchpoint | Emoción |
|---|---|---|---|---|
| 1 Descubre | Llega a la home RELE | “¿Esto sustituye el Excel?” | / | Curiosidad |
| 2 Entra | Login casa@… | “Mis datos, no un form anónimo” | /login | Confianza |
| 3 Registra | period + kWh + coste | “En un minuto lo dejo” | /lecturas/nueva | Alivio |
| 4 Espera | Ve SUBMITTED en lista | “Toni lo verá” | /lecturas | Neutra |
| 5 Cierra loop | Ve REVIEWED + nota | “Tiene sentido el pico de AC” | /lecturas/:id | Satisfacción |
Journey asesor (paralelo)
| Fase | Acción | Touchpoint |
|---|---|---|
| Login | asesor@… | /login |
| Cola | Stats abiertas + lista | /lecturas |
| Revisión | Detalle kWh/CUPS | /lecturas/:id |
| Cierre | REVIEWED o FLAGGED + nota | PATCH |
7. Service blueprint (resumen)
| Capa | Elementos |
|---|---|
| Frontstage | Home, login, lista, form, detalle |
| Backstage humano | Asesor interpreta picos, decide flag |
| Sistemas | Angular :4200 · Nest :3009 · Prisma · Neon · JWT |
| Soporte | Seed demo, códigos RE-…, badges estado |
| Fallos | Red caída → error + reintento; 403 por rol; 401 sin token |
8. Matriz hallazgo → requisito → feature
| ID | Hallazgo (tipo) | Requisito | Feature L2 |
|---|---|---|---|
| F1 | Coordinación informal pierde contexto [SUPUESTO] | Captura estructurada period+kWh | POST /api/readings |
| F2 | Asesor necesita cola priorizable [HIPÓTESIS] | Lista + open count | GET list + stats |
| F3 | Cierre de revisión debe ser explícito [HIPÓTESIS] | Estados REVIEWED/FLAGGED | PATCH status |
| F4 | Confianza del residente en feedback [HIPÓTESIS] | Nota visible | advisorNote en detalle |
| F5 | Referencia oral en llamada [SUPUESTO] | Código corto único | code RE-MMDD-XXX |
| F6 | Ambos roles necesitan auth [DECISIÓN] | JWT multi-rol | login + guards |
| F7 | Vivienda ancla CUPS [DECISIÓN] | Entidad Home | seed + include en list |
9. Preguntas abiertas (investigación futura, no bloqueantes)
- ¿El asesor gestiona N hogares o 1:1 en la práctica real de la demo extendida?
- ¿DRAFT se usa en flujo real o basta SUBMITTED al crear? ([DECISIÓN v1]: create → SUBMITTED; DRAFT en enum para evolución.)
- ¿costEur lo rellena el residente o se estima? ([DECISIÓN v1]: opcional en form.)
10. Síntesis para diseño
| Principio | Aplicación en UI |
|---|---|
| Claridad del número | kWh y periodo prominentes; stats kWh Σ |
| Honestidad de estado | Badges DRAFT/SUBMITTED/REVIEWED/FLAGGED |
| Roles sin ambigüedad | CTA home dual; acciones create vs patch por rol |
| Referencia | Código RE-… siempre visible |
| Marca marítima calmada | Fog/navy/sea; coral solo para alerta |
Cierre de verdad: ninguna cifra de mercado en este doc es primaria. Las personas y journeys son constructos de diseño para alinear producto, Paper y código.
03-information-architecture.md
Abrir documento03 — Arquitectura de información — RELE
1. Principios de IA
| Principio | Aplicación |
|---|---|
| Poca profundidad | Máx. 2 niveles bajo auth (/lecturas → detalle o nueva) |
| Roles en el mismo shell | Mismas rutas; acciones condicionales por role |
| Público vs app | Home marketing abierta; dominio lecturas solo JWT |
| Códigos como ancla | RE-… visible en lista y detalle |
| No marketplace | Sin catálogo, carrito ni matching |
2. Sitemap
/ Home marketing (público)
/login Login JWT (RESIDENT | ADVISOR)
/lecturas Lista + stats (auth)
/lecturas/nueva Crear lectura (RESIDENT; auth)
/lecturas/:id Detalle + acciones ADVISOR (auth)
/** → redirect /
3. Navegación
Pública
| Elemento | Destino | Notas |
|---|---|---|
| Logo RELE | / | Display Sora |
| Entrar | /login | Link muted |
| Abrir panel | /login | CTA sea |
| Soy residente / Soy asesor | /login | Mismo form; seed distinto |
App autenticada (header)
| Elemento | Visible | Acción |
|---|---|---|
| Logo | Ambos | /lecturas |
| Nombre · rol | Ambos | Solo lectura |
| Nueva lectura | Solo RESIDENT | /lecturas/nueva |
| Salir | Ambos | logout + /login o / |
4. Inventario de pantallas
| ID | Pantalla | Ruta | Auth | Rol |
|---|---|---|---|---|
| S0 | Home | / | No | Público |
| S1 | Login | /login | No | — |
| S2 | Lecturas | /lecturas | Sí | Ambos |
| S3 | Nueva lectura | /lecturas/nueva | Sí | RESIDENT |
| S4 | Detalle | /lecturas/:id | Sí | Ambos (scope) |
5. Objetos de contenido
| Objeto | Campos clave en UI | Dónde |
|---|---|---|
| Reading | code, period, kwh, costEur, status, notes, advisorNote | Lista, detalle, form |
| Home | label, address, cups | Detalle, subtítulo lista |
| User | name, email, role | Header, login |
| Stats | total, open, byStatus, kwhTotal | Strip lista |
6. Taxonomía de estados
| Status | Significado UX | Color sugerido |
|---|---|---|
DRAFT | Borrador (reservado; no create v1) | muted |
SUBMITTED | Enviada, pendiente de revisión | navy soft |
REVIEWED | Revisada OK por asesor | sea |
FLAGGED | Requiere atención (tarifa / anomalía) | coral |
Open (ops): SUBMITTED + FLAGGED (contador “ABIERTAS” en stats).
7. Permisos por ruta (matriz)
| Ruta / acción | Anónimo | RESIDENT | ADVISOR |
|---|---|---|---|
| GET home | ✓ | ✓ | ✓ |
| POST login | ✓ | ✓ | ✓ |
| GET lecturas | ✗ | propias | todas |
| GET stats | ✗ | propias | globales |
| POST lectura | ✗ | ✓ | ✗ |
| GET detalle ajeno | ✗ | ✗ | ✓ |
| PATCH status | ✗ | ✗ | ✓ |
8. Etiquetado y copy de nav (es-ES)
| UI | Label |
|---|---|
| Producto | RELE |
| Login | Iniciar sesión / Entrar |
| Lista | Lecturas |
| Create | Nueva lectura / Registrar lectura |
| Logout | Salir |
| Back | ← Lecturas |
9. SEO / URLs
- URLs en español legible (
lecturas,nueva). - IDs técnicos solo en detalle (
:idcuid). - Sin query params de filtro en v1.
10. Extensiones futuras (no en IA v1)
| Módulo | Ruta hipotética | Nivel |
|---|---|---|
| Multi-vivienda | /viviendas | L2+ |
| Tendencias | /lecturas/tendencia | L2+ |
| Perfil | /cuenta | L2+ |
| Export CSV | acción en lista | L2+ |
04-user-flows.md
Abrir documento04 — Flujos de usuario — RELE
1. Mapa de flujos
| ID | Flujo | Actor | Éxito |
|---|---|---|---|
| F0 | Descubrimiento home | Visitante | Entiende valor y va a login |
| F1 | Login | RESIDENT / ADVISOR | JWT + redirect /lecturas |
| F2 | Consultar lecturas + stats | Ambos | Lista y strip stats |
| F3 | Crear lectura | RESIDENT | Reading SUBMITTED con código |
| F4 | Revisar y cambiar estado | ADVISOR | REVIEWED o FLAGGED + nota |
| F5 | Empty state | RESIDENT (0 items) | CTA a nueva lectura |
| F6 | Error de red | Ambos | Mensaje + reintento |
| F7 | Logout | Ambos | Limpia token |
2. F0 — Home → Login
[/] → CTA "Soy residente" | "Soy asesor" | "Abrir panel"
→ [/login]
| Paso | UI | Notas |
|---|---|---|
| 1 | Hero + media + 3 pasos | Copy: sin Excel / WhatsApp |
| 2 | Click CTA | Ambos CTAs a /login (mismo form; [DECISIÓN]) |
| 3 | Login prefill residente | casa@rele.energy por defecto en demo |
3. F1 — Login JWT
[/login] → email + password → POST /api/auth/login
OK → localStorage (rele_token, rele_user) → [/lecturas]
KO → mensaje "Credenciales inválidas"
| Campo | Validación cliente | Server |
|---|---|---|
| required, type email | @IsEmail() | |
| password | required, min práctico | @MinLength(6) + bcrypt |
Errores
| Caso | Respuesta | UI |
|---|---|---|
| Password incorrecta | 401 | coral “Credenciales inválidas” |
| API caída | network error | mismo mensaje genérico o red |
4. F2 — Lista + stats
[/lecturas] (token required)
→ GET /api/readings/stats/summary
→ GET /api/readings
→ render cards + badges
| Rol | Datos |
|---|---|
| RESIDENT | Solo residentId = me; include home + advisor |
| ADVISOR | Todas; include home + resident |
Soft auth UI: si no hay token → navigateByUrl('/login').
Variantes
| Estado | Condición | UI |
|---|---|---|
| Loading | petición en curso | lista vacía / sin empty (loading flag) |
| Empty | 200 + [] | “Sin lecturas todavía” + CTA si RESIDENT |
| Error | HTTP error | panel coral + Reintentar |
| Success | items ≥ 1 | lista ordenada createdAt desc |
5. F3 — Crear lectura (RESIDENT)
[/lecturas] → "Nueva lectura" → [/lecturas/nueva]
→ period, kwh, costEur?, notes?
→ POST /api/readings
→ OK → [/lecturas] (o detalle según impl.)
→ ADVISOR que intenta POST → 403
| Campo | Req | Ejemplo |
|---|---|---|
| period | Sí | 2026-08 |
| kwh | Sí, ≥ 0 | 245 |
| costEur | No | 56.1 |
| notes | No | Lectura contador 14 ago |
Server [COMPROBADO en código]:
- Solo
role === RESIDENT. - Resuelve
Homedel residente (primera o crea default). status = SUBMITTED,code = RE-MMDD-XXX.
6. F4 — Detalle + status (ADVISOR)
[/lecturas] → click card → [/lecturas/:id]
→ GET /api/readings/:id
→ (si ADVISOR) textarea nota + botones REVIEWED | FLAGGED
→ PATCH /api/readings/:id/status { status, advisorNote? }
→ UI actualiza item
| Transición típica | Desde | Hacia |
|---|---|---|
| Validar OK | SUBMITTED | REVIEWED |
| Anomalía / tarifa | SUBMITTED o REVIEWED | FLAGGED |
| Re-validar | FLAGGED | REVIEWED |
Permisos
| Actor | Puede ver detalle | Puede PATCH |
|---|---|---|
| RESIDENT dueño | Sí | No |
| RESIDENT ajeno | 403 | No |
| ADVISOR | Sí | Sí |
7. F5 — Empty
| Condición | Mensaje | CTA |
|---|---|---|
| RESIDENT 0 lecturas | “Sin lecturas todavía…” | Registrar lectura |
| ADVISOR 0 lecturas | Mismo empty sin CTA create | — |
8. F6 — Error de red (lista)
GET fallan → error string → panel "No se pudieron cargar las lecturas"
→ [Reintentar] → load()
9. F7 — Logout
click Salir → ApiService.logout() → limpia localStorage → login/home
10. Diagrama de estados Reading
create (RESIDENT)
│
▼
SUBMITTED ◄──────────────┐
/ \ │
/ \ │
▼ ▼ │
REVIEWED FLAGGED ──────────┘
\ / (PATCH ADVISOR)
\ /
▼ ▼
(ambos pueden re-etiquetarse vía PATCH libre en v1)
Nota [DECISIÓN]: la API acepta cualquier ReadingStatus en PATCH (enum); no hay máquina de estados rígida server-side más allá de rol ADVISOR. DRAFT existe en enum para evolución, no se emite en create v1.
11. Criterios de aceptación por flujo
| Flujo | AC |
|---|---|
| F1 | Login demo 200; mal password mensaje visible |
| F2 | Stats total/open/kwhTotal coherentes con seed |
| F3 | POST crea SUBMITTED con code RE- |
| F4 | PATCH REVIEWED asigna advisorId |
| F5 | Empty sin crash |
| F6 | Reintentar re-lanza GETs |
05-data-model.md
Abrir documento05 — Modelo de datos — RELE
1. Visión general
Dominio mínimo de lecturas energéticas L2:
| Entidad | Propósito |
|---|---|
| User | Identidad RESIDENT o ADVISOR |
| Home | Vivienda del residente (label, address, CUPS) |
| Reading | Lectura de contador por periodo con estado y notas |
Base: PostgreSQL (Neon) · ORM: Prisma · IDs: cuid().
2. Enums
Role
| Valor | Descripción |
|---|---|
RESIDENT | Titular / habitante que registra lecturas |
ADVISOR | Asesor que revisa y anota |
ReadingStatus
| Valor | Descripción |
|---|---|
DRAFT | Borrador (reservado; no usado en create v1) |
SUBMITTED | Enviada por residente (default create) |
REVIEWED | Revisada OK por asesor |
FLAGGED | Marcada para atención (tarifa / anomalía) |
3. Diagrama ER (texto)
User
id, email, passwordHash, name, role
homes[] (RESIDENT)
readings[] (como resident)
reviews[] (como advisor)
Home
id, label, address, cups
residentId → User
readings[]
Reading
id, code (unique)
period, kwh, costEur?, notes, advisorNote
status (default SUBMITTED)
homeId → Home
residentId → User
advisorId? → User
createdAt, updatedAt
4. Tablas / modelos Prisma
User
| Campo | Tipo | Constraints |
|---|---|---|
| id | String | PK, cuid |
| String | unique | |
| passwordHash | String | bcrypt |
| name | String | |
| role | Role | RESIDENT | ADVISOR |
| createdAt | DateTime | default now |
| updatedAt | DateTime | updatedAt |
Home
| Campo | Tipo | Constraints |
|---|---|---|
| id | String | PK, cuid |
| label | String | ej. “Piso Ruzafa” |
| address | String | |
| cups | String | código punto suministro (demo) |
| residentId | String | FK User |
| createdAt | DateTime |
Reading
| Campo | Tipo | Constraints |
|---|---|---|
| id | String | PK, cuid |
| code | String | unique, formato RE-MMDD-XXX |
| period | String | ej. 2026-08 |
| kwh | Float | ≥ 0 |
| costEur | Float? | opcional |
| notes | String | default "" |
| advisorNote | String | default "" |
| status | ReadingStatus | default SUBMITTED |
| homeId | String | FK Home |
| residentId | String | FK User |
| advisorId | String? | FK User (advisor) |
| createdAt / updatedAt | DateTime |
5. Reglas de integridad y negocio
| Regla | Implementación |
|---|---|
| Auth lecturas | JwtAuthGuard en controller readings → 401 sin token |
| Create solo RESIDENT | ForbiddenException si no RESIDENT |
| Status solo ADVISOR | ForbiddenException si no ADVISOR |
| Get RESIDENT | Solo si reading.residentId === userId |
| Código único | code unique; generación RE- + MMDD + random 100–999 |
| Home en create | Primera home del residente o create default |
| Notes | Coalesce a "" si omitidas |
| Orden listado | createdAt desc |
| Password | Nunca en claro; solo passwordHash |
6. Contratos API (resumen)
POST /api/auth/login
Body: { email, password }
Response 200:
{
"accessToken": "<jwt>",
"user": { "id": "...", "email": "...", "name": "...", "role": "RESIDENT" }
}
GET /api/readings (JWT)
Array Reading + includes (home, resident|advisor según rol).
GET /api/readings/stats/summary (JWT)
{
"total": 5,
"open": 3,
"byStatus": {
"DRAFT": 0,
"SUBMITTED": 2,
"REVIEWED": 2,
"FLAGGED": 1
},
"kwhTotal": 921
}
open = SUBMITTED + FLAGGED.
kwhTotal = suma de kWh del scope del rol.
GET /api/readings/:id (JWT)
Reading con home + resident + advisor, o 404/403.
POST /api/readings (JWT RESIDENT)
Body
| Campo | Tipo | Req |
|---|---|---|
| period | string | sí (min 4) |
| kwh | number | sí ≥ 0 |
| costEur | number | no |
| notes | string | no |
| homeLabel | string | no (solo si se crea home) |
Response: Reading + home; status SUBMITTED.
PATCH /api/readings/:id/status (JWT ADVISOR)
Body: { status: ReadingStatus, advisorNote?: string }
Efecto: actualiza status, advisorId = me, advisorNote si se envía.
7. Seed de referencia
| Entidad | Datos |
|---|---|
| RESIDENT | Elena Marín · casa@rele.energy · password123 |
| ADVISOR | Toni Gil · asesor@rele.energy · password123 |
| Home | Piso Ruzafa · C/ Sueca 18, 3º · València · CUPS ES0021000000000001AB |
| RE-0809-01 | 2026-07 · 212 kWh · 48.6 € · REVIEWED |
| RE-0809-02 | 2026-06 · 168 kWh · 39.2 € · REVIEWED |
| RE-0809-03 | 2026-08 · 245 kWh · 56.1 € · SUBMITTED |
| RE-0809-04 | 2026-05 · 141 kWh · 33.4 € · FLAGGED |
| RE-0809-05 | 2026-04 · 155 kWh · 36.0 € · SUBMITTED |
8. Índices y rendimiento (v1)
| Necesidad | Enfoque v1 |
|---|---|
| List by resident | where residentId (volumen demo bajo) |
| Unique code | constraint unique Prisma |
| Stats | groupBy status + aggregate kwh |
Índices adicionales (residentId, status) = L2+ si crece volumen.
9. Privacidad de campos
| Campo | Sensibilidad | Quién lo ve |
|---|---|---|
| PII | self + advisor en list | |
| cups | identificador suministro | ambos roles en scope |
| passwordHash | secreto | nunca en API response |
| advisorNote | semi-sensible | ambos en detalle |
06-tech-stack.md
Abrir documento06 — Stack tecnológico — RELE
1. Resumen
| Capa | Tecnología | Notas |
|---|---|---|
| Frontend | Angular (standalone components) | Puerto 4200 |
| Estilos | Tailwind CSS | Tokens en tailwind.config.js |
| Backend | NestJS | Prefijo global /api, puerto 3009 |
| ORM | Prisma | schema en apps/api/prisma |
| DB | Neon PostgreSQL | project sparkling-snow-59844541 |
| Auth | JWT (Bearer) | accessToken en login |
| Validación | class-validator + ValidationPipe | whitelist + transform |
| Repo | /Users/cristian/orca/rele-app/ | GitHub Criscode2022/rele-app |
2. Estructura monorepo app
rele-app/
├── package.json # scripts api / web
├── apps/
│ ├── api/ # NestJS
│ │ ├── prisma/
│ │ │ ├── schema.prisma
│ │ │ └── seed.ts
│ │ ├── src/
│ │ │ ├── auth/
│ │ │ ├── readings/
│ │ │ ├── prisma/
│ │ │ ├── app.module.ts
│ │ │ └── main.ts
│ │ └── package.json
│ └── web/ # Angular
│ ├── src/app/
│ │ ├── core/api.service.ts
│ │ └── pages/...
│ ├── tailwind.config.js
│ └── package.json
└── README.md
[DECISIÓN / D-P1-03]: apps independientes (npm install --prefix), sin workspaces npm que rompan Angular.
3. Frontend
| Aspecto | Detalle |
|---|---|
| Componentes | Standalone + templates inline |
| Routing | app.routes.ts |
| HTTP | HttpClient vía ApiService |
| Estado auth | localStorage keys rele_token, rele_user |
| API base | http://localhost:3009/api |
| Fonts | Google Fonts Sora + Nunito Sans en styles.css |
Rutas web
| Path | Página |
|---|---|
/ | HomePage |
/login | LoginPage |
/lecturas | ReadingsPage |
/lecturas/nueva | ReadingNewPage |
/lecturas/:id | ReadingDetailPage |
4. Backend
| Aspecto | Detalle |
|---|---|
| Prefijo | /api |
| CORS | origin: true, credentials |
| Puerto | process.env.PORT || 3009 |
| Módulos | AuthModule, ReadingsModule, PrismaModule |
Endpoints
| Método | Ruta | Auth | Rol |
|---|---|---|---|
| POST | /api/auth/login | No | — |
| GET | /api/readings | JWT | ambos |
| GET | /api/readings/stats/summary | JWT | ambos |
| GET | /api/readings/:id | JWT | scope |
| POST | /api/readings | JWT | RESIDENT |
| PATCH | /api/readings/:id/status | JWT | ADVISOR |
5. Base de datos
| Campo | Valor |
|---|---|
| Provider | PostgreSQL |
| Hosting | Neon serverless |
| Project | sparkling-snow-59844541 |
| URL | DATABASE_URL en .env (no commitear secretos) |
| Seed | prisma/seed.ts → 2 users, 1 home, 5 readings |
6. Auth JWT
| Pieza | Rol |
|---|---|
| Login | bcrypt compare + sign JWT |
| Payload | sub/userId, email, role |
| Guard | JwtAuthGuard en ReadingsController |
| Strategy | passport-jwt Bearer |
| Cliente | header Authorization: Bearer <token> |
7. Variables de entorno
| Variable | Servicio | Descripción |
|---|---|---|
DATABASE_URL | API | Connection string Neon |
JWT_SECRET | API | Firma de tokens |
PORT | API | Opcional, default 3009 |
Web: URL API fija en api.service.ts (localhost:3009) en v1.
8. Scripts habituales
cd /Users/cristian/orca/rele-app
npm install --prefix apps/api
npm install --prefix apps/web
npm --prefix apps/api run prisma:migrate
npm --prefix apps/api run prisma:seed
npm run api # :3009
npm run web # :4200
9. Decisiones técnicas
| Decisión | Razón |
|---|---|
| Puerto 3009 | Diversidad vs VOLTA 3008 / SURCO 3007 |
| Soft guards en Angular | Autoridad real en API; L2 simple |
| Create → SUBMITTED | Menos fricción que DRAFT+submit |
| Stats con kwhTotal | Dominio energía visible en strip |
| Templates inline | Velocidad daily; componentes autocontenidos |
| accessToken camelCase | Alineado a SURCO; evita snake_case mismatch |
10. Dependencias clave (orientativo)
| API | Web |
|---|---|
| @nestjs/* | @angular/* |
| @prisma/client | tailwindcss |
| passport-jwt | rxjs |
| bcrypt | — |
| class-validator | — |
11. Despliegue (recomendado, no obligatorio v1)
| Capa | Opción |
|---|---|
| API | Railway / Fly / Render |
| Web | Vercel / Netlify / static ng build |
| DB | Neon (ya) |
Documentar CORS y API URL de producción al desplegar.
07-creative-direction.md
Abrir documento07 — Dirección creativa — RELE
1. Concepto de marca
| Campo | Valor |
|---|---|
| Nombre | RELE |
| Eslogan | ”El consumo, a la vista.” |
| Promesa | Claridad calmada del gasto energético del hogar, con un asesor en el loop. |
| Tono | Técnico-humano, sereno, mediterráneo marítimo — no alarmista “eco-green” ni industrial cold. |
| Metáfora | Relé / relectura del contador: un clic mental que enciende visibilidad. |
2. Posicionamiento visual
| Eje | RELE elige | RELE evita |
|---|---|---|
| Temperatura | Marítimo frío-cálido (navy + sea + coral) | Lime athletic (VOLTA), leaf pastoral (SURCO) |
| Densidad | Cards generosas, números legibles | Dashboard IoT denso con 40 KPIs |
| Emoción | Confianza y calma | Urgencia climática panic-red |
| Referencia | Panel de energía doméstica / asesoría | Marketplace, fitness, agro |
3. Personalidad (adjetivos)
- Clara — kWh y periodo primero.
- Serena — fog y navy, no neon cyber.
- Precisa — códigos
RE-…, CUPS, estados. - Cercana — microcopy de piso y factura, no jerga de TSO.
- Honesta — FLAGGED no es “error del usuario”.
4. Paleta (ancla)
| Nombre | Hex | Rol |
|---|---|---|
| Fog | #EEF1F4 | Fondo |
| Surface | #FFFFFF | Cards |
| Navy | #0C2340 | Ink / primary dark |
| Sea | #2F8F8C | Acento marca / CTAs |
| Coral | #E07A5F | Alerta / FLAGGED / abiertas |
| Muted | #5A6B7D | Secundario |
| Border | #D0D8E0 | Separadores |
Mood: costa mediterránea al atardecer suave — niebla marina, azul profundo, agua, terracota suave.
5. Tipografía
| Uso | Familia | Peso |
|---|---|---|
| Display / logos / H1 | Sora | 600–800 |
| UI / cuerpo | Nunito Sans | 400–700 |
Por qué: Sora da geometría moderna energética sin frío tech; Nunito Sans aporta legibilidad amable en formularios y listas.
6. Imaginería
| Uso | Descripción |
|---|---|
| Hero | Contador / entorno doméstico de energía fotorrealista (assets/hero.jpg) |
| Empty | Tipografía + CTA, sin ilustración clipart |
| No usar | Iconos de rayo cartoon, paneles solares stock genéricos a full-bleed sin contexto |
7. Motion (principios)
| Principio | v1 |
|---|---|
| Sutil | Hover de cards y botones |
| Sin confetti | Éxito = lista actualizada / badge |
| Feedback estado | Cambio inmediato de badge tras PATCH |
8. Voz visual por pantalla
| Pantalla | Énfasis |
|---|---|
| Home | Claim grande + hero + dual CTA |
| Login | Split navy / form; promesa de roles |
| Lista | Números y badges; strip stats |
| Form | Campos claros, un CTA sea |
| Detalle | Grid kWh / coste / estado; nota sea soft |
9. Diferenciación en la serie
| Proyecto | Estilo | RELE se diferencia |
|---|---|---|
| VOLTA | Chalk/ink/lime · fitness | No lime; no lead form |
| SURCO | Bone/leaf · agro | No pastoral; energía |
| CORREA | Sage/terracotta · pets | No marketplace |
| TROCHA | Asphalt/amber · log | No flota |
10. Anti-moodboard (qué no)
- Gradientes “AI SaaS purple”.
- Glassmorphism excesivo.
- Dark mode full como default (login split navy sí; app en fog).
- Iconografía de rayo amarillo genérico de stock.
11. Criterio de aceptación creativa
- Un screenshot de home se reconoce como “energía hogar serena”, no gym ni finca.
- Tokens Tailwind coinciden con Paper (fog/navy/sea/coral).
- Hero real presente en case y app.
- Coral solo en alerta / flag / open — no en brand principal.
08-design-system.md
Abrir documento08 — Design system — RELE
1. Tokens de color
| Token Tailwind | Hex | Uso |
|---|---|---|
bg | #EEF1F4 | Fondo página |
surface | #FFFFFF | Cards, header |
ink | #0C2340 | Texto principal |
ink-muted | #5A6B7D | Texto secundario |
primary | #0C2340 | Navy primary |
primary-soft | #D8E4F0 | Secciones suaves |
primary-strong | #071628 | Hover navy |
sea | #2F8F8C | CTA principal, acentos |
sea-soft | #D4EDEC | Badge REVIEWED, nota asesor |
sea-strong | #247370 | Hover sea |
coral | #E07A5F | FLAGGED, errores, abiertas |
coral-soft | #F8E4DD | Fondos error |
border | #D0D8E0 | Bordes |
Contraste (orientativo WCAG)
| Par | Uso | Nota |
|---|---|---|
| ink sobre bg | Cuerpo | Alto |
| white sobre sea | Botones | Alto |
| white sobre ink | Botones navy | Alto |
| white sobre coral | Botones flag | Alto |
| ink-muted sobre bg | Secundario | Verificar ≥ 4.5:1 en UI real |
2. Tipografía
| Rol | Familia | Clase | Tamaños guía |
|---|---|---|---|
| Display | Sora | font-display | H1 4xl–5xl · H2 3xl · logo 2xl |
| UI | Nunito Sans | font-sans | body base · labels xs bold · meta 11px |
Tracking: labels de sección tracking-[0.16em] en sea/uppercase corto.
3. Espaciado y layout
| Token | Valor |
|---|---|
| Page max | max-w-6xl home · max-w-5xl lista · max-w-2xl detalle/form |
| Header height | 72px home · 64px app |
| Card radius | rounded-2xl (16px) · botones rounded-full |
| Gap secciones | py-14 home · py-8 app |
| Padding card | p-4 / p-6 |
4. Componentes
4.1 Botones
| Variante | Clases clave | Uso |
|---|---|---|
| Primary sea | rounded-full bg-sea text-white font-bold | CTA principal |
| Primary ink | rounded-full bg-ink text-white | CTA secundario fuerte |
| Outline | rounded-full border border-border bg-surface | CTA alternativo |
| Danger/Flag | rounded-full bg-coral text-white | FLAGGED |
| Ghost text | font-bold text-ink | Salir |
Estados: hover sea-strong / opacidad; disabled no implementado en v1 salvo implícito form.
4.2 Badges de estado
| Status | Estilo sugerido |
|---|---|
| DRAFT | muted border |
| SUBMITTED | bg-primary-soft text-ink |
| REVIEWED | bg-sea-soft text-sea |
| FLAGGED | bg-coral-soft text-coral |
4.3 Cards
- Border
border-border, fondosurface, hover listahover:border-sea. - Meta code:
text-[11px] font-bold tracking-wide text-sea. - Título: period · kWh · coste muted.
4.4 Stats chips
| Chip | Contenido | Acento |
|---|---|---|
| TOTAL | count | ink |
| ABIERTAS | open | coral text |
| kWh Σ | kwhTotal | sea soft bg |
4.5 Formularios
| Elemento | Spec |
|---|---|
| Label | text-xs font-bold text-ink-muted |
| Input | rounded-xl border border-border px-4 py-3 w-full |
| Textarea | rows 2–3, mismo borde |
| Error | text-sm text-coral |
4.6 Header app
Logo display + Nombre · ROL + acciones. Sticky no obligatorio en app (sí en home marketing).
4.7 Empty / Error
| Tipo | Contenedor |
|---|---|
| Empty | rounded-2xl border bg-surface p-12 text-center |
| Error | rounded-2xl border-coral/40 bg-coral-soft p-6 + botón Reintentar ink |
5. Iconografía
v1: sin librería de iconos pesada; chevron/back como texto “←”.
Extensión L2+: set outline navy/sea coherente.
6. Elevación y bordes
| Nivel | Tratamiento |
|---|---|
| Flat | border only |
| Hero media | shadow-lg + rounded-[20px] |
| Sticky header home | bg-surface/95 + border-b |
7. Grid responsive
| Breakpoint | Comportamiento |
|---|---|
| < md | 1 col hero, form full |
| md+ | hero 2 col; login split 2 col; stats row |
| Mobile lista | card full width; targets ≥ 44px |
8. Mapeo Paper ↔ código
| Token Paper | Tailwind |
|---|---|
| Fog | bg-bg |
| Navy | text-ink / bg-ink / primary |
| Sea | bg-sea / text-sea |
| Coral | bg-coral / text-coral |
| Sora | font-display |
| Nunito Sans | font-sans |
9. Do / Don’t
| Do | Don’t |
|---|---|
| Usar sea para acción primaria de producto | Usar coral como brand principal |
| Números en extrabold display | Párrafos largos en H1 |
| Badges de estado siempre | Inventar estados “OK/KO” fuera del enum |
| Fog de fondo app | Fondo blanco puro full-bleed sin surface cards |
10. Checklist de paridad
- Colores en
tailwind.config.js - Fonts en
styles.css - Badges en lista
- Login split navy
- Stats strip
09-content-guide.md
Abrir documento09 — Guía de contenido — RELE
1. Voz y tono
| Atributo | Cómo suena RELE | Cómo no suena |
|---|---|---|
| Clara | “Registra la lectura del periodo.” | “Optimiza tu stack energy-as-a-service.” |
| Serena | “El consumo, a la vista.” | “¡Tu factura te está arruinando!” |
| Precisa | “245 kWh · SUBMITTED” | “Mucho consumo este mes 😱” |
| Cercana | “Piso Ruzafa” | “Nodo de suministro N-42” sin contexto |
| Honesta | “Marcar FLAGGED — revisar tarifa” | “Error: lectura inválida” si solo es duda de tarifa |
Idioma: es-ES. Tratamiento de tú implícito en CTAs cortos; sin vosotros institucional.
2. Nombres de producto
| Correcto | Evitar |
|---|---|
| RELE | ReleApp, Rele Energy Suite |
| Lectura / lecturas | Ticket, lead, solicitud de plaza |
| Residente / Asesor | User / Admin genéricos en UI |
| Periodo | “Billing cycle” en UI |
| kWh | “Consumo units” |
3. Microcopy por pantalla
Home
| Elemento | Copy |
|---|---|
| Eyebrow | ENERGÍA · HOGAR |
| H1 | El consumo, a la vista. |
| Lead | Lecturas de contador y revisión del asesor energético en un solo panel. Sin Excel sueltos ni capturas por WhatsApp. |
| CTA 1 | Soy residente |
| CTA 2 | Soy asesor |
| Paso 01 | Registras la lectura — Periodo, kWh y coste estimado de la factura. |
| Paso 02 | El asesor revisa — Marca REVIEWED o FLAGGED con una nota. |
| Paso 03 | Queda en el histórico — Código corto para referir en una llamada. |
Login
| Elemento | Copy |
|---|---|
| Panel izq. | Panel de lecturas del hogar |
| Sub | Residente envía kWh. Asesor valida y anota. |
| Título form | Iniciar sesión |
| Error | Credenciales inválidas |
| Hint demo | casa@rele.energy · asesor@rele.energy · password123 |
Lista
| Elemento | Copy |
|---|---|
| H1 | Lecturas |
| Sub RESIDENT | Tu histórico de contador |
| Sub ADVISOR | Cola de revisión energética |
| Stats | TOTAL · ABIERTAS · kWh Σ |
| Empty title | Sin lecturas todavía |
| Empty body | Cuando registres un periodo, aparecerá aquí. |
| Empty CTA | Registrar lectura |
| Error title | No se pudieron cargar las lecturas |
| Error CTA | Reintentar |
Nueva lectura
| Campo / UI | Copy |
|---|---|
| Título | Nueva lectura |
| period | Periodo (ej. 2026-08) |
| kwh | kWh |
| costEur | Coste estimado (€) — opcional |
| notes | Notas |
| Submit | Enviar lectura |
Detalle
| Elemento | Copy |
|---|---|
| Back | ← Lecturas |
| Labels | kWh · COSTE · ESTADO · NOTAS RESIDENTE · NOTA ASESOR |
| CTA sea | Marcar REVIEWED |
| CTA coral | Marcar FLAGGED |
| Placeholder nota | (textarea libre) |
4. Estados — lenguaje para humanos
| Código | Label UI (v1) | Explicación corta (tooltips futuros) |
|---|---|---|
| DRAFT | DRAFT | Borrador no enviado |
| SUBMITTED | SUBMITTED | Enviada; pendiente de revisión |
| REVIEWED | REVIEWED | Revisada por el asesor |
| FLAGGED | FLAGGED | Atención: tarifa o anomalía |
[DECISIÓN v1]: se muestran códigos de estado en inglés de dominio (enum) para alinear API/UI; la guía de contenido documenta significado en español. L2+ puede localizar a “Enviada / Revisada / A revisar”.
5. Códigos y datos
| Tipo | Formato | Ejemplo |
|---|---|---|
| Código lectura | RE-MMDD-XXX | RE-0809-03 |
| Periodo | YYYY-MM preferido | 2026-08 |
| kWh | número | 245 |
| Coste | N € | 56.1 € |
| CUPS | string demo | ES0021000000000001AB |
6. Mensajes de error
| Caso | Mensaje |
|---|---|
| Login fail | Credenciales inválidas |
| Red lista | No se pudieron cargar las lecturas + detalle técnico corto si hay |
| 403 create | (API) Forbidden — UI no muestra botón a ADVISOR |
| 403 patch | (API) Forbidden — UI no muestra botones a RESIDENT |
| 404 | (futuro) Lectura no encontrada |
7. Accesibilidad de texto
- No usar solo color para estado: badge con texto del enum.
- Alt hero: “Contador y entorno doméstico de energía”.
- Evitar “clic aquí”; preferir verbos de acción.
8. Tono en notas (asesor)
| Bueno | Malo |
|---|---|
| “Pico coherente con ola de calor.” | “Mal.” |
| “Revisar tarifa PVPC vs fija.” | “Eres tonto con la tarifa.” |
| “Dentro de rango.” | “OK lol” |
9. Footer / demo (si aplica)
Incluir en home o login los emails demo sin passwords en marketing largo; password solo en hint de login/demo interno.
10. Checklist de contenido
- Eslogan único y consistente
- CTAs duales por rol
- Empty y error con acción
- Notas de seed creíbles (no lorem)
- Sin copy de marketplace / fitness / agro
10-accessibility.md
Abrir documento10 — Accesibilidad — RELE
1. Objetivo
Orientar el vertical slice L2 a WCAG 2.2 AA en lo razonable para una app daily de portfolio: contraste, teclado, labels, estados no solo-color, y mensajes de error.
No se declara certificación formal AA. Esto es checklist de diseño e implementación.
2. Principios aplicados
| Principio | Aplicación en RELE |
|---|---|
| Perceptible | Contraste navy/fog; badges con texto; alt en hero |
| Operable | Targets ≥ 44px en CTAs; formularios nativos |
| Comprensible | Labels visibles; errores en texto; estados con nombre |
| Robusto | HTML semántico razonable; Angular standalone |
3. Contraste
| Par | Uso | Meta |
|---|---|---|
#0C2340 sobre #EEF1F4 | Texto body | ≥ 4.5:1 |
#FFFFFF sobre #2F8F8C | Botón sea | ≥ 4.5:1 |
#FFFFFF sobre #0C2340 | Botón ink / login panel | ≥ 4.5:1 |
#FFFFFF sobre #E07A5F | Botón coral | ≥ 4.5:1 |
#5A6B7D sobre fog | Muted | Verificar; subir a ink si falla |
Acción: si muted falla en labels pequeños, usar ink o subir peso.
4. Teclado y foco
| Control | Expectativa |
|---|---|
| Links nav | Tab order lógico logo → entrar → CTA |
| Login | email → password → submit |
| Lista | cada card es link; Tab entre items |
| Form nueva | campos en orden DOM → submit |
| Detalle ADVISOR | nota → REVIEWED → FLAGGED |
Mejora L2+: focus ring visible (focus-visible:ring-2 ring-sea) en todos los interactivos.
5. Formularios
| Requisito | v1 |
|---|---|
| Label asociado | <label> con span + input (implícito wrapping) |
| required | atributos HTML en login |
| Errores | texto coral bajo el form |
| type email/password | sí |
| No placeholder-only | labels siempre visibles |
6. Color y estado
| Riesgo | Mitigación |
|---|---|
| Solo color para status | Badge incluye texto del enum |
| Coral = error y flag | Contexto de pantalla distinto + texto |
| Stats “abiertas” en coral | Label ABIERTAS presente |
7. Media
| Elemento | a11y |
|---|---|
| Hero home | alt="Contador y entorno doméstico de energía" |
| Decorative | no hay iconos vacíos críticos |
8. Estructura semántica
| Pantalla | Estructura |
|---|---|
| Home | header + sections + headings jerárquicos |
| Login | headings h1/h2; form |
| Lista | header + main + h1 + lista ul/li |
| Detalle | main + h1 periodo |
9. Auth y timeouts
- No hay timeout de sesión UI en v1; JWT expira según config server.
- Logout explícito limpia storage.
- Mensajes de 401 en flujos protegidos: redirect login (soft).
10. Lectores de pantalla (notas)
| Área | Recomendación |
|---|---|
| Stats | Preferir texto “Total 5” legible; evitar solo dígitos sueltos sin label |
| Badges | El texto del status es suficiente |
| Botones estado | “Marcar REVIEWED” es verboso y correcto |
11. Mobile
| Requisito | v1 |
|---|---|
| Touch target | botones rounded-full con py suficiente |
| Zoom | no bloquear scale en viewport meta de forma hostil |
| Orientación | layout apilado ok |
12. Matriz de pruebas a11y (manual)
| # | Prueba | Criterio pass |
|---|---|---|
| A1 | Tab por home y login | Foco no se pierde |
| A2 | Login solo teclado | Submit OK |
| A3 | Zoom 200% lista | Sin solapamiento crítico |
| A4 | Contraste botones | Texto legible |
| A5 | Empty/error | Mensaje en texto, no solo color |
| A6 | Badge status | Nombre del estado anunciable |
13. Deuda a11y aceptada (no bloquea L2)
| Ítem | Prioridad |
|---|---|
| Focus rings sistemáticos | L2+ |
| Live regions al patch status | L2+ |
| Route guards + anuncios de página | L2+ |
| Auditoría axe automatizada en CI | L2+ |
| i18n de enums a español | L2+ |
14. Criterio de aceptación a11y v1
- No hay información crítica solo por color.
- Hero tiene alt descriptivo.
- Forms tienen labels visibles.
- Errores de login y lista son textuales.
- CTAs principales son alcanzables por teclado.
11-privacy-security.md
Abrir documento11 — Privacidad y seguridad — RELE
1. Alcance
Vertical slice L2 con datos de consumo doméstico, identidad de usuario y CUPS de demo. Documento de decisiones de producto/seguridad, no dictamen legal.
2. Datos tratados
| Dato | Categoría | Dónde | Quién accede |
|---|---|---|---|
| email, name | PII | User | self; advisor ve resident en list |
| passwordHash | secreto | User | nadie vía API |
| JWT | credencial | cliente + server | portador |
| address, cups | identificador hogar | Home | resident + advisor en scope |
| period, kwh, costEur | consumo / económico | Reading | scope por rol |
| notes, advisorNote | contenido libre | Reading | scope por rol |
3. Roles y autorización
| Acción | RESIDENT | ADVISOR |
|---|---|---|
| Ver propias lecturas | Sí | — |
| Ver todas (demo) | No | Sí |
| Crear lectura | Sí | No (403) |
| Patch status | No (403) | Sí |
| Ver lectura ajena | No (403) | Sí |
Autoridad: NestJS JwtAuthGuard + checks en ReadingsService.
UI: oculta botones; no sustituye al server.
4. Autenticación
| Aspecto | Implementación |
|---|---|
| Método | Email + password |
| Hash | bcrypt (seed y login) |
| Token | JWT Bearer accessToken |
| Storage cliente | localStorage keys rele_token, rele_user |
| Transporte | HTTPS en producción (requerido al desplegar) |
Riesgos localStorage [SUPUESTO de amenaza]
| Riesgo | Mitigación v1 | L2+ |
|---|---|---|
| XSS roba token | No HTML user raw; Angular escape default | CSP, httpOnly cookie |
| Token largo | Secret fuerte en env | Expiry corto + refresh |
5. Superficie API
| Endpoint | Auth | Notas |
|---|---|---|
| POST /api/auth/login | Público | Rate limit futuro |
| GET/POST/PATCH readings* | JWT | Validación DTO |
- Prefijo
/api. ValidationPipewhitelist + transform.- CORS
origin: trueen dev; restringir en prod.
6. Secretos y configuración
| Secreto | Ubicación correcta |
|---|---|
DATABASE_URL | .env local / secret host |
JWT_SECRET | .env / secret host |
| Passwords demo | Solo docs de demo, no prod real |
Nunca commitear .env con credenciales Neon reales en repos públicos sin rotación.
7. Privacidad por diseño (v1)
| Principio | Aplicación |
|---|---|
| Minimización | No DNI, no IBAN, no geolocalización |
| Limitación finalidad | Lecturas y revisión; no ads |
| Transparencia demo | Cuentas demo visibles en login |
| Separación roles | 403 cross-action |
8. CUPS y datos energéticos
El CUPS identifica el punto de suministro. En demo es ficticio/seed.
| Buena práctica | v1 |
|---|---|
| No exponer listados públicos de CUPS | JWT required |
| No loguear bodies con PII en prod | console mínimo |
| Soft-delete | No; hard data en demo |
9. Amenazas y mitigaciones
| Amenaza | Impacto | Mitigación |
|---|---|---|
| Credenciales débiles demo | Alto en prod real | Solo entorno demo; password123 documentado |
| IDOR lectura | Medio | check residentId en get |
| Escalada rol en JWT | Alto | role firmado en token; no confiar en body |
| Spam create | Medio | JWT + validación; rate limit L2+ |
| Inyección | Medio | Prisma parametrizado |
10. Cumplimiento (orientación, no legal advice)
| Tema | Nota |
|---|---|
| RGPD | Base demo; en producto real: base legal, derechos ARCO, DPA con Neon |
| Cookies | v1 localStorage no cookie banner; reevaluar si analytics |
| Menores | No target |
11. Logging y auditoría
| Evento | v1 | Futuro |
|---|---|---|
| Login fail | HTTP 401 | contador / alert |
| Patch status | DB updatedAt + advisorId | audit log |
| Export | No | CSV con authz |
12. Checklist seguridad cierre
- Passwords hasheados
- JWT en lecturas
- 403 por rol en create/status
- 403 resident en get ajeno
- Validación DTO
- Rate limit login (L2+)
- HTTPS enforced en deploy
- CSP / httpOnly (L2+)
13. Incidente demo (procedimiento mínimo)
- Rotar
JWT_SECRETy forzar re-login. - Rotar password hashes de seed.
- Revisar Neon access.
- Documentar en registry si aplica.
12-analytics.md
Abrir documento12 — Analytics y métricas — RELE
1. Norte del producto
| Tipo | Métrica | Definición |
|---|---|---|
| North Star | Lecturas REVIEWED por mes | Revisiones cerradas con valor de asesoría |
| Guardrail | % FLAGGED / total | Calidad o anomalía de datos / tarifa |
| Guardrail | Tasa error API create/list | Confiabilidad |
Instrumentación real (Segment, PostHog, etc.) no está cableada en v1. Este doc define el modelo de medición.
2. Árbol de métricas
North Star: REVIEWED / mes
├── Activación residente: 1ª lectura SUBMITTED
├── Activación asesor: 1er PATCH status
├── Engagement: lecturas / residente / mes
├── Ops: mediana tiempo SUBMITTED → REVIEWED|FLAGGED
└── Calidad: kWh reportados vs outliers (futuro)
3. Eventos propuestos
| Evento | Props | Cuándo |
|---|---|---|
home_viewed | — | load / |
login_submitted | role_hint? | submit form |
login_succeeded | role | 200 login |
login_failed | reason | 401 |
readings_list_viewed | role, total | load lista |
reading_created | period, kwh, code | POST OK |
reading_detail_viewed | id, status, role | GET detalle |
reading_status_patched | id, from, to | PATCH OK |
empty_state_viewed | role | empty |
error_state_viewed | surface | error red |
logout | role | click salir |
4. Funnels
Funnel residente
home_viewedlogin_succeeded(RESIDENT)reading_created- (async)
reading_status_patched→ REVIEWED
Funnel asesor
login_succeeded(ADVISOR)readings_list_viewedreading_detail_viewedreading_status_patched
5. KPIs operativos (panel futuro)
| KPI | Cálculo | Fuente |
|---|---|---|
| Abiertas | SUBMITTED + FLAGGED | stats.summary.open |
| kWh mes | sum kwh period actual | aggregate |
| SLA revisión | p50 hours SUBMITTED→close | timestamps |
| Nota coverage | % con advisorNote no vacía | DB |
6. Analytics de producto vs privacidad
| Regla | Detalle |
|---|---|
| No enviar password | Nunca |
| Minimizar PII en eventos | Preferir user_id hash / role |
| CUPS | No en analytics v1 |
| IP | Según política host |
7. Implementación sugerida L2+
| Capa | Opción |
|---|---|
| Product analytics | PostHog self-host o cloud EU |
| Errores | Sentry |
| Uptime API | Better Stack / Checkly |
| SQL métricas | Neon + vista readings_by_status |
8. Dashboards (wire conceptual)
| Vista | Widgets |
|---|---|
| Founder | North Star, activaciones, error rate |
| Ops asesor | Abiertas, p50 revisión, FLAGGED rate |
| Calidad | Distribución kWh, outliers |
9. Experimentos (hipótesis)
| Exp | Hipótesis | Métrica |
|---|---|---|
| E1 | Prefill periodo mes actual ↑ create completion | reading_created / form start |
| E2 | Badge FLAGGED en coral ↑ tiempo a patch | time-to-patch |
| E3 | Nota obligatoria en FLAGGED ↑ calidad feedback | % note non-empty |
Todas las filas son [HIPÓTESIS] hasta A/B real.
10. Qué medir en smoke diario (manual)
| Check | Señal |
|---|---|
| Seed carga 5 lecturas | lista length |
| Stats open > 0 | strip ABIERTAS |
| Create +1 total | POST |
| Patch REVIEWED | badge update |
11. Criterio de aceptación analytics v1
- Modelo North Star documentado.
- Eventos nombrados (aunque no instrumentados).
- Funnels de ambos roles definidos.
- Sin stats de mercado inventadas presentadas como reales.
13-qa-test-plan.md
Abrir documento13 — Plan de QA — RELE
1. Alcance
Smoke y regresión del vertical slice L2: auth multi-rol, CRUD lecturas, stats, estados UI, tokens visuales.
Entornos: local API :3009 · web :4200 · Neon sparkling-snow-59844541.
2. Cuentas de prueba
| Rol | Password | |
|---|---|---|
| RESIDENT | casa@rele.energy | password123 |
| ADVISOR | asesor@rele.energy | password123 |
3. Smoke API (obligatorio D-P1-06)
| # | Paso | Expectativa |
|---|---|---|
| S1 | POST /api/auth/login casa@… | 200 + accessToken + role RESIDENT |
| S2 | GET /api/readings con Bearer | 200 array ≥ 1 |
| S3 | GET /api/readings/stats/summary | total, open, byStatus, kwhTotal |
| S4 | POST /api/readings period+kwh | 201/200 · status SUBMITTED · code RE-… |
| S5 | Login asesor | role ADVISOR |
| S6 | GET /api/readings asesor | ve lecturas de Elena |
| S7 | PATCH /api/readings/:id/status REVIEWED | 200 · advisorId set |
| S8 | Sin token GET readings | 401 |
| S9 | RESIDENT PATCH status | 403 |
| S10 | ADVISOR POST reading | 403 |
Ejemplo curl (orientativo)
# Login residente
TOKEN=$(curl -s -X POST http://localhost:3009/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"casa@rele.energy","password":"password123"}' | jq -r .accessToken)
curl -s http://localhost:3009/api/readings -H "Authorization: Bearer $TOKEN" | jq length
curl -s http://localhost:3009/api/readings/stats/summary -H "Authorization: Bearer $TOKEN" | jq .
4. Smoke web
| # | Paso | Expectativa |
|---|---|---|
| W1 | Abrir / | Hero, eslogan, CTAs, imagen |
| W2 | Ir a login | Split navy/form |
| W3 | Login residente | Redirect /lecturas · nombre Elena · badge RESIDENT |
| W4 | Stats visibles | TOTAL / ABIERTAS / kWh Σ |
| W5 | Nueva lectura | Form → submit → vuelve lista con item |
| W6 | Detalle | kWh, estado, notas |
| W7 | Logout + login asesor | Cola con nombres residentes |
| W8 | Detalle → REVIEWED | Badge actualiza |
| W9 | FLAGGED + nota | Nota visible sea soft |
| W10 | Empty (DB limpia opcional) | Empty state sin crash |
| W11 | API apagada | Error + Reintentar |
5. Regresión de dominio
| Caso | Resultado |
|---|---|
| Código único tras varios creates | No colisión (retry manual si 500 raro) |
| costEur null | Muestra “—” en detalle |
| notes vacías | No bloque de notas |
| Orden lista | Más reciente primero |
6. Regresión visual / craft
| Check | Pass |
|---|---|
| Colores fog/navy/sea/coral | No palette default indigo Tailwind |
| Fonts Sora + Nunito Sans | Títulos display |
| Badges por status | Colores distintos |
| Mobile 390px lista | Sin overflow horizontal crítico |
7. Seguridad básica
| Check | Pass |
|---|---|
| password no en responses | Sí |
| 401 sin token | Sí |
| 403 cross-role | Sí |
| XSS en notes | Angular escape; no innerHTML raw |
8. Accesibilidad smoke
Ver doc 10 §12 (A1–A6).
9. Build
| Check | Comando / criterio |
|---|---|
| API compile | nest start / tsc sin error |
| Web build | ng build OK o serve estable |
| Seed | consola RELE seed OK |
10. Matriz de riesgos QA
| Riesgo | Severidad | Detección |
|---|---|---|
| API URL mal puerto | Alta | lista error |
| Token key mismatch accessToken | Alta | login no guarda |
| Guard no aplicado | Crítica | GET sin token 200 |
| Role check missing | Crítica | resident patch |
11. Criterio de salida QA día
- S1–S10 o subset documentado en implementation
- W1–W9 en demo
- Seed + 2 roles
- Sin bloqueantes de authz
12. Fuera de alcance QA v1
- e2e Playwright suite CI
- Load test Neon
- Penetration test formal
- Compatibilidad IE
14-dev-handoff.md
Abrir documento14 — Handoff de desarrollo — RELE
1. Enlaces canónicos
| Artefacto | Ubicación |
|---|---|
| Case | /Users/cristian/orca/ux-projects/2026-08-09-rele/ |
| App | /Users/cristian/orca/rele-app/ |
| GitHub | https://github.com/Criscode2022/rele-app |
| Paper | https://app.paper.design/file/01KZJNCCMJ1FDHHPZZ923RWDWY |
| Neon | sparkling-snow-59844541 |
| API local | http://localhost:3009 |
| Web local | http://localhost:4200 |
2. Arranque en 5 minutos
cd /Users/cristian/orca/rele-app
cp apps/api/.env.example apps/api/.env # si existe; si no, crear .env
# DATABASE_URL=... JWT_SECRET=dev-secret PORT=3009
npm install --prefix apps/api
npm install --prefix apps/web
npm --prefix apps/api run prisma:migrate
npm --prefix apps/api run prisma:seed
npm run api
npm run web
3. Credenciales demo
| Rol | Password | |
|---|---|---|
| RESIDENT | casa@rele.energy | password123 |
| ADVISOR | asesor@rele.energy | password123 |
4. Mapa docs → implementación
| Doc | Uso para dev |
|---|---|
| 03 IA | Rutas y nav |
| 04 Flows | Edge cases |
| 05 Data | Schema + contratos |
| 06 Stack | Puertos y módulos |
| 08 DS | Tokens Tailwind |
| 09 Content | Strings UI |
| 11 Security | Authz rules |
| 13 QA | Smoke |
| 16 Interactions | Detalle UI |
| 20 Implementation | Archivos y decisiones |
5. Contratos críticos (no romper)
- Login response usa
accessToken(camelCase). - Todas las lecturas bajo JWT.
- POST create →
SUBMITTED+codeRE-…. - PATCH status solo ADVISOR.
- Stats incluyen
kwhTotal. - Storage keys:
rele_token,rele_user.
6. Estructura de código a tocar
| Cambio | Archivos |
|---|---|
| Nuevo campo lectura | schema.prisma, DTO, seed, Reading type web, UI |
| Nuevo estado | enum Prisma + badges + stats open formula |
| Nuevo rol | enum Role + service checks + UI condicional |
| Copy | templates páginas |
| Tokens | tailwind.config.js, styles.css |
7. Convenciones
| Tema | Convención |
|---|---|
| IDs | cuid |
| Fechas | ISO DateTime Prisma; period string YYYY-MM |
| Roles | UPPER enum |
| Status | UPPER enum |
| API prefix | /api |
| Idioma UI | es-ES |
8. Definition of Done (feature nueva)
- Schema + migrate si aplica
- Authz test manual
- UI empty/error si lista
- Tokens DS
- Doc 05/04 actualizados si contrato cambia
- Smoke curl o UI
9. Entorno y secretos
| Variable | Requerida |
|---|---|
| DATABASE_URL | Sí |
| JWT_SECRET | Sí |
| PORT | No (3009) |
10. Paridad Paper
Implementar respetando:
- Palette maritime
- Sora + Nunito Sans
- Login split
- Stats strip
- Badges estado
Inventario: docs/00-paper-reference.md.
11. Problemas conocidos / no-bugs
| Síntoma | Explicación |
|---|---|
| Soft auth solo en ngOnInit | Deep link sin token redirige; no hay interceptor global |
| DRAFT no aparece al crear | Create fuerza SUBMITTED |
| ADVISOR ve todas las lecturas | Scope demo L2; multi-tenant fuera |
| Enum en inglés en UI | Decisión contenido v1 |
12. Contacto de diseño (proceso)
Cambios visuales: actualizar Paper + tokens Angular en la misma PR mental del daily. No “solo código gris”.
15-roadmap.md
Abrir documento15 — Roadmap — RELE
1. Principio
El L2 del día está cerrado. Este roadmap solo lista subidas de nivel o extensiones explícitamente fuera del alcance 2026-08-09.
No es deuda del vertical slice actual (CRON §1.1 / D-P0-06).
2. Hecho (L2 — 2026-08-09)
| Entrega | Estado |
|---|---|
| Home marketing + hero | Hecho |
| JWT multi-rol RESIDENT + ADVISOR | Hecho |
| Lista + stats (total, open, kwhTotal) | Hecho |
| Create lectura SUBMITTED | Hecho |
| Detalle + PATCH REVIEWED/FLAGGED | Hecho |
| Empty / error | Hecho |
| Seed 5 lecturas + Home + CUPS | Hecho |
| Docs 00–20 + Paper + Neon + GitHub | Hecho |
3. L2+ (mismo producto, más craft/ops)
| Item | Valor | Esfuerzo |
|---|---|---|
| Filtros por estado en lista | Ops asesor | S |
| Localizar badges a español | UX | S |
| Focus rings + a11y axe | Calidad | S |
| Route guards Angular formales | Robustez | S |
| Interceptor 401 global | Auth UX | S |
| Foto contador (upload) | Evidencia | M |
| Periodo prefill mes actual | Activación | S |
| Export CSV lecturas | Ops | M |
| e2e Playwright smoke | CI | M |
4. L3 (producto más amplio)
| Item | Notas |
|---|---|
| Multi-vivienda por residente | CRUD Home + selector |
| Asesor multi-cliente / tenant | Aislamiento datos |
| Invitaciones y onboarding | Magic link |
| Gráficos tendencia kWh | Charts |
| Notificaciones email al FLAGGED | Provider |
| Notas hilo (timeline) | Historial |
| Roles ADMIN asesoría | Permisos |
5. L4 / exploratorio
| Item | Notas |
|---|---|
| Integración contador inteligente / distribuidora | APIs externas, consentimientos |
| Recomendación tarifaria automatizada | No marketplace checkout sin diseño |
| App nativa offline-first | Sync conflict |
| Billing de la propia asesoría SaaS | Multi-tenant comercial |
6. No-roadmap (explícitamente no RELE)
| Idea | Por qué no |
|---|---|
| Marketplace de comercializadoras | Otro producto |
| Fitness / club lead form | VOLTA |
| Cuaderno de parcelas | SURCO |
| Flota GPS | TROCHA |
7. Priorización sugerida post-demo
| Prioridad | Item | Razón |
|---|---|---|
| P1 | Filtros estado + badges ES | Usabilidad ops inmediata |
| P1 | Interceptor 401 | Menos soft-auth frágil |
| P2 | Multi-vivienda | Realismo dominio |
| P2 | Upload foto | Confianza de lectura |
| P3 | Charts | Storytelling consumo |
| P3 | Integraciones IoT | Solo con partner |
8. Métricas para decidir build
| Señal [HIPÓTESIS] | Acción |
|---|---|
| Asesores piden filtros | L2+ filtros |
| Residentes confunden FLAGGED | Copy + i18n + tooltip |
| >1 vivienda por user en entrevistas | L3 multi-home |
| Demanda de foto contador | Upload L2+ |
9. Criterio de no reabrir L2
No reabrir el case del día para:
- “Añadir un gráfico pequeño” sin nuevo brief.
- Cambiar a lead-form público.
- Mezclar sector fitness/agro.
Cualquier pivot de sector/tipo → nuevo día ALS-2.
16-interaction-specs.md
Abrir documento16 — Especificaciones de interacción — RELE
1. Convenciones
| Parámetro | Valor |
|---|---|
| Duración hover | ~150ms CSS default |
| Feedback crítico | Inmediato al response HTTP |
| Navegación | Angular router, sin full reload |
| Toasts | No en v1; UI actualiza in-place |
2. Home
| Interacción | Comportamiento |
|---|---|
| Hover CTA sea | hover:bg-sea-strong |
| Hover CTA outline | border/ink enfatizado |
| Click CTAs rol | → /login |
| Sticky header | sticky top-0 + surface/95 |
| Hero image | object-cover, no zoom interaction |
3. Login
| Interacción | Comportamiento |
|---|---|
| Prefill | email residente demo |
| Submit | disable visual no; espera HTTP |
| Error | muestra coral bajo form; no limpia password |
| Success | navigate /lecturas |
| Link ← Inicio | / |
4. Lista lecturas
| Interacción | Comportamiento |
|---|---|
| Load | paralelo list + stats (subscribe independientes) |
| Click card | → /lecturas/:id |
| Hover card | hover:border-sea |
| Nueva lectura (RESIDENT) | → /lecturas/nueva |
| Salir | logout + clear storage |
| Reintentar | re-ejecuta load() |
| Empty CTA | → nueva lectura |
Badges
| Status | Clase orientativa (impl.) |
|---|---|
| SUBMITTED | soft navy |
| REVIEWED | sea-soft |
| FLAGGED | coral-soft |
| DRAFT | muted |
5. Nueva lectura
| Interacción | Comportamiento |
|---|---|
| Campos | two-way ngModel |
| Submit | POST; on success volver a lista (o stay — según page impl.) |
| Validación | HTML required en period/kwh; server refuerza |
| Cancel / back | link a lista |
6. Detalle
| Interacción | Comportamiento |
|---|---|
| Load | GET by id; 403/404 → vacío o redirect futuro |
| RESIDENT view | sin botones patch |
| ADVISOR note | textarea bindeada |
| Marcar REVIEWED | PATCH status REVIEWED + note |
| Marcar FLAGGED | PATCH status FLAGGED + note |
| Success patch | item = response in-place; sin toast |
7. Estados de superficie
Loading
| Superficie | v1 |
|---|---|
| Lista | loading=true evita empty flash hasta respuesta |
| Detalle | no skeleton; aparece al next |
Empty
| Condición | UI |
|---|---|
| items.length===0 && !error && !loading | panel centrado + copy |
Error
| Condición | UI |
|---|---|
| HTTP error list | panel coral-soft + Reintentar |
| Login error | texto coral |
8. Responsive
| Viewport | Ajuste |
|---|---|
| < md | hero 1 col; login stack (form abajo); stats wrap |
| ≥ md | hero 2 col; login split; stats row |
| Touch | botones full/rounded-full con padding ≥ 10px vertical |
9. Teclado
| Atajo implícito | Resultado |
|---|---|
| Enter en login | submit form |
| Tab order | ver doc 10 |
| Esc | no cierra modales (no hay modal v1) |
10. Movimiento y reduced motion
v1 no define animaciones custom largas.
L2+: respetar prefers-reduced-motion si se añaden transitions de lista.
11. Edge cases de interacción
| Caso | Comportamiento esperado |
|---|---|
| Doble click submit create | posible double POST; L2+ debounce |
| Patch concurrente | last write wins |
| Token expira mid-session | próximo GET falla → error/relogin |
| Deep link detalle sin token | redirect login |
12. Criterios de aceptación interacción
- Card hover visible.
- Patch actualiza badge sin reload full page.
- Error lista recuperable con Reintentar.
- Empty no muestra lista fantasma.
- ADVISOR no ve botón “Nueva lectura”.
17-prototype-map.md
Abrir documento17 — Mapa de prototipo — RELE
1. Fuentes de verdad
| Capa | Rol |
|---|---|
| Paper | Hi-fi visual + UX process (no clicable nativo vía MCP) |
| App Angular | Prototipo interactivo end-to-end |
| Docs 00–20 | Especificación y narrativa portfolio |
Paper file: https://app.paper.design/file/01KZJNCCMJ1FDHHPZZ923RWDWY
2. Mapa de clics (app)
[/]
├─ Entrar / Abrir panel / Soy residente / Soy asesor → [/login]
└─ (footer/demo si aplica)
[/login]
├─ ← Inicio → [/]
└─ submit OK → [/lecturas]
[/lecturas]
├─ Nueva lectura (RESIDENT) → [/lecturas/nueva]
├─ card → [/lecturas/:id]
├─ Reintentar → reload
└─ Salir → login/home + clear
[/lecturas/nueva]
├─ back → [/lecturas]
└─ submit OK → [/lecturas]
[/lecturas/:id]
├─ ← Lecturas → [/lecturas]
└─ (ADVISOR) REVIEWED | FLAGGED → same page update
3. Paper artboard → ruta
| Artboard | Ruta | Notas de paridad |
|---|---|---|
| 01 Home | / | Hero, 3 pasos, CTAs |
| 02 Login | /login | Split navy |
| 03 Lecturas | /lecturas | Stats + lista |
| 04 Nueva | /lecturas/nueva | Form |
| 05 Detalle | /lecturas/:id | Acciones advisor |
| 06 Mobile | mismas | viewport |
| 07 Empty | /lecturas | 0 items |
| 08 Error | /lecturas | API down |
4. Guiones de demo (prototipo vivo)
Guión A — Residente (3 min)
- Home: leer claim “El consumo, a la vista.”
- Login
casa@rele.energy/password123. - Señalar stats y códigos
RE-0809-…. - Nueva lectura periodo actual + kWh.
- Abrir detalle; mostrar notas si hay.
Guión B — Asesor (3 min)
- Login
asesor@rele.energy. - Cola con nombres de residente.
- Abrir SUBMITTED.
- Nota + FLAGGED o REVIEWED.
- Volver a lista; badge actualizado.
Guión C — Resiliencia (1 min)
- Parar API.
- Reintentar lista → error.
- Arrancar API → Reintentar OK.
5. Datos del prototipo (seed)
| Código | Periodo | kWh | Status |
|---|---|---|---|
| RE-0809-01 | 2026-07 | 212 | REVIEWED |
| RE-0809-02 | 2026-06 | 168 | REVIEWED |
| RE-0809-03 | 2026-08 | 245 | SUBMITTED |
| RE-0809-04 | 2026-05 | 141 | FLAGGED |
| RE-0809-05 | 2026-04 | 155 | SUBMITTED |
Vivienda: Piso Ruzafa · CUPS ES0021000000000001AB.
6. Limitaciones del prototipo
| Limitación | Impacto demo |
|---|---|
| Sin guards de ruta Angular formales | Deep link sin token redirige en ngOnInit |
| Sin notificaciones | Loop asesor→residente es visual en detalle |
| Sin multi-home UI | Una vivienda seed |
| Enum EN en badges | Explicar en narración |
7. Checklist de paridad pre-demo
- API :3009 up + seed
- Web :4200 up
- Tokens marítimos visibles
- Ambos logins
- Create + patch
- Paper abierto en segunda ventana opcional
8. Entrega de prototipo
| Audiencia | Qué mostrar |
|---|---|
| Portfolio | Paper §1–§5 + app guión A/B |
| Tech | Network tab JWT + PATCH |
| Producto | Diferencia vs marketplace/lead-form |
18-completeness-audit.md
Abrir documento18 — Auditoría de completitud — RELE (2026-08-09)
1. Alcance auditado
Vertical slice L2: lecturas de contador multi-rol RESIDENT+ADVISOR, con docs, Paper, Angular+Nest+Prisma+Neon.
2. Checklist CRON / ALS-2
| Requisito | Estado | Evidencia |
|---|---|---|
| Diversidad sector/tipo/nivel | OK | Energía L2; no fitness/agro/marketplace; no lead-form-only |
| Day brief + anti-patrones | OK | docs/00-day-brief.md |
| Paper bandas §1–§5 | OK | file 01KZJNCCMJ1FDHHPZZ923RWDWY |
| Docs 00–20 | OK | suite en docs/ |
| JWT multi-rol | OK | RESIDENT / ADVISOR |
| API + seed + Neon | OK | sparkling-snow-59844541, port 3009 |
| Web Angular tokens | OK | Sora/Nunito, fog/navy/sea/coral |
| Smoke login+readings | OK | plan doc 13 |
| Cierre sin deuda del L2 | OK | roadmap solo L2+/L3 |
| Hipótesis no fake stats | OK | etiquetas en doc 02 |
3. Cobertura funcional
| Feature brief | Implementado | UI | API | Docs |
|---|---|---|---|---|
| Home | Sí | Sí | — | 01,09 |
| Login | Sí | Sí | POST login | 04,06 |
| Lista + stats | Sí | Sí | GET + summary | 05 |
| Create | Sí | Sí | POST | 04 |
| Detail + status | Sí | Sí | GET + PATCH | 04 |
| Empty | Sí | Sí | — | 16 |
| Error red | Sí | Sí | — | 16 |
| Roles demo | Sí | badge | JWT payload | seed |
| Home entity + CUPS | Sí | detalle | include | 05 |
4. Cobertura Paper
| Banda | Inventario | Notas |
|---|---|---|
| §1 UX | Cover→Datos | doc 00-paper-reference |
| §2 DS+Public | DS + Home + Login | tokens marítimos |
| §3 App | List + New + Detail | |
| §4 Mobile | list/new | |
| §5 States | empty + error |
5. Rúbrica de calidad (auto SCORE orientativo)
| Eje | Score 1–5 | Comentario |
|---|---|---|
| Diversidad | 5 | Sector energía nuevo; L2 post-VOLTA L1 |
| Craft visual | 4–5 | Palette maritime + tipo + hero |
| Densidad UX docs | 5 | Suite completa |
| Completitud código L2 | 4–5 | Vertical slice runnable |
| Authz | 5 | Guard + role checks create/status |
| Verdad investigación | 5 | Sin stats falsas; hipótesis marcadas |
6. Huecos aceptados (no regresiones de cierre)
| Hueco | Clasificación |
|---|---|
| IoT / contador inteligente | Fuera L2 |
| e2e automatizado | Preferible L2+ |
| Route guards formales | L2+ |
| Multi-tenant asesoría | L3 |
| i18n estados ES | L2+ |
7. Anti-patrones verificados
| Anti-patrón | ¿Evitarlo? |
|---|---|
| Thin docs | Sí |
| UI genérica | Sí (tokens) |
| Sin auth | Sí |
| Marketplace | Sí |
| Lead-form-only | Sí (ambos JWT) |
| Fitness/agro copy | Sí |
| Fake research | Sí |
8. Veredicto
COMPLETO para entrega de caso 2026-08-09 tras documentación portfolio y app alineada al brief.
Cualquier ampliación multi-tenant/IoT/marketplace requiere nuevo brief de diversidad, no parche silencioso.
19-backlog-completo.md
Abrir documento19 — Backlog completo — RELE
1. Leyenda
| Estado | Significado |
|---|---|
| DONE | En el vertical slice L2 del 2026-08-09 |
| OUT | Fuera de alcance del día (no deuda) |
| NEXT | Candidato L2+/L3 con brief |
2. Backlog por épica
E0 — Fundación
| ID | Item | Estado |
|---|---|---|
| E0-1 | Repo app Angular+Nest | DONE |
| E0-2 | Prisma schema User/Home/Reading | DONE |
| E0-3 | Neon project + migrate + seed | DONE |
| E0-4 | JWT login | DONE |
| E0-5 | Tokens Tailwind marítimos | DONE |
| E0-6 | Paper §1–§5 | DONE |
| E0-7 | Docs 00–20 + README + executive | DONE |
E1 — Residente
| ID | Item | Estado |
|---|---|---|
| E1-1 | Lista lecturas propias | DONE |
| E1-2 | Stats propias + kwhTotal | DONE |
| E1-3 | Crear lectura SUBMITTED | DONE |
| E1-4 | Ver detalle + nota asesor | DONE |
| E1-5 | Multi-vivienda UI | OUT → NEXT L3 |
| E1-6 | Prefill periodo | OUT → NEXT L2+ |
| E1-7 | Upload foto contador | OUT → NEXT L2+ |
E2 — Asesor
| ID | Item | Estado |
|---|---|---|
| E2-1 | Cola global demo | DONE |
| E2-2 | PATCH REVIEWED/FLAGGED | DONE |
| E2-3 | advisorNote | DONE |
| E2-4 | Filtros por estado | OUT → NEXT L2+ |
| E2-5 | Asignación multi-cliente | OUT → NEXT L3 |
| E2-6 | SLA dashboard | OUT → NEXT L3 |
E3 — UX craft
| ID | Item | Estado |
|---|---|---|
| E3-1 | Home multi-sección | DONE |
| E3-2 | Empty + error | DONE |
| E3-3 | Badges estado | DONE |
| E3-4 | Mobile usable | DONE (responsive) |
| E3-5 | Focus rings sistemáticos | OUT → NEXT |
| E3-6 | i18n badges ES | OUT → NEXT |
E4 — Plataforma
| ID | Item | Estado |
|---|---|---|
| E4-1 | Rate limit login | OUT |
| E4-2 | Refresh tokens | OUT |
| E4-3 | e2e CI | OUT |
| E4-4 | Deploy prod | OUT |
| E4-5 | Analytics SDK | OUT |
| E4-6 | Integración distribuidora | OUT L4 |
3. Matriz MoSCoW del día (histórico)
| Prioridad | Items |
|---|---|
| Must | Login, list, stats, create, detail, patch, seed, docs, Paper |
| Should | Empty, error, hero real, dual CTA |
| Could | DRAFT workflow, filtros, charts |
| Won’t (día) | IoT, marketplace, multi-tenant, pagos |
4. Bugs conocidos (ninguno bloqueante)
| ID | Descripción | Severidad | Acción |
|---|---|---|---|
| — | Soft auth sin interceptor global | Baja | NEXT L2+ |
| — | Posible double-submit create | Baja | debounce NEXT |
5. Ideas aparcadas (no contaminan L2)
- Comparador de tarifas con CTA a comercializadora (otro producto).
- Gamificación de ahorro (riesgo fitness-copy).
- Comunidad de vecinos por escalera (social L3).
- Predicción ML de factura (L4 + datos).
6. Criterio de “DONE del día”
| Check | OK |
|---|---|
| Must implementados | Sí |
| Roadmap no disfraza deuda L2 | Sí |
| Hipótesis etiquetadas | Sí |
| Demo 2 roles | Sí |
7. Transferencia a día N+1
Solo vía memory.md §8 (diversidad), no como features pendientes de RELE L2.
20-implementation.md
Abrir documento20 — Implementación — RELE
1. Resumen ejecutivo técnico
| Campo | Valor |
|---|---|
| App path | /Users/cristian/orca/rele-app/ |
| GitHub | https://github.com/Criscode2022/rele-app |
| API | NestJS · puerto 3009 · prefijo /api |
| Web | Angular standalone · puerto 4200 |
| DB | Neon PostgreSQL · Prisma · sparkling-snow-59844541 |
| Auth | JWT Bearer · roles RESIDENT | ADVISOR |
| Dominio | User, Home, Reading |
| Fecha | 2026-08-09 |
| Case | /Users/cristian/orca/ux-projects/2026-08-09-rele/ |
2. Cómo arrancar
cd /Users/cristian/orca/rele-app
# Dependencias (apps independientes, sin workspaces)
npm install --prefix apps/api
npm install --prefix apps/web
# Entorno API: DATABASE_URL (Neon) + JWT_SECRET
# cp apps/api/.env.example apps/api/.env # si existe
npm --prefix apps/api run prisma:migrate
npm --prefix apps/api run prisma:seed
npm run api # Nest → http://localhost:3009
npm run web # Angular → http://localhost:4200
Credenciales
| Rol | Nombre | Password | |
|---|---|---|---|
| RESIDENT | Elena Marín | casa@rele.energy | password123 |
| ADVISOR | Toni Gil | asesor@rele.energy | password123 |
3. Módulos API implementados
Auth
POST /api/auth/login- Valida email/password; compara bcrypt; emite JWT.
- Response:
{ accessToken, user: { id, email, name, role } }. JwtStrategy+JwtAuthGuardprotegen readings.
Readings
| Método | Ruta | Notas |
|---|---|---|
| GET | /api/readings | filtro por rol (resident propias / advisor todas) |
| GET | /api/readings/stats/summary | total, open, byStatus, kwhTotal |
| GET | /api/readings/:id | ownership check resident |
| POST | /api/readings | solo RESIDENT; home resolve/create; status SUBMITTED |
| PATCH | /api/readings/:id/status | solo ADVISOR; advisorId + advisorNote |
Prisma
Enums Role, ReadingStatus; modelos User, Home, Reading; seed 2 users + 1 home + 5 readings.
4. Frontend implementado
| Página | Path | Responsabilidad |
|---|---|---|
| HomePage | / | marketing, hero, pasos, CTAs rol |
| LoginPage | /login | form → ApiService.login → /lecturas |
| ReadingsPage | /lecturas | stats + list + empty/error + logout |
| ReadingNewPage | /lecturas/nueva | form create (resident) |
| ReadingDetailPage | /lecturas/:id | get + patch status (advisor) |
ApiService centraliza base URL http://localhost:3009/api, storage rele_token / rele_user, métodos HTTP tipados.
5. Decisiones de implementación
| Decisión | Razón |
|---|---|
| Puerto API 3009 | Evitar colisión con VOLTA 3008 / SURCO 3007 |
| Soft auth en páginas | Simple L2; API es autoridad |
| Create → SUBMITTED | Menos fricción que DRAFT |
| Home implícita en create | Menos pantallas CRUD L2 |
| open = SUBMITTED + FLAGGED | Ops de “requiere atención” |
| kwhTotal en stats | Dominio energía visible |
| Templates inline standalone | Velocidad daily |
| accessToken camelCase | Alineado serie (SURCO) |
6. Variables de entorno
| Variable | Servicio | Descripción |
|---|---|---|
DATABASE_URL | API | Neon connection string |
JWT_SECRET | API | Firma tokens |
PORT | API | opcional, 3009 |
Web: URL de API en apps/web/src/app/core/api.service.ts.
7. Smoke de implementación (mínimo)
- Seed OK en consola (
RELE seed OK). - Login residente 200 +
accessToken. - List length ≥ 1; stats con
kwhTotal. - Create reading 200/201 · code
RE-…· SUBMITTED. - Login asesor ve lecturas de Elena.
- Patch REVIEWED/FLAGGED 200.
- RESIDENT patch → 403; ADVISOR create → 403.
- Web muestra palette maritime + badges.
8. Estructura de ficheros clave
rele-app/
├── package.json
├── README.md
└── apps/
├── api/
│ ├── prisma/schema.prisma
│ ├── prisma/seed.ts
│ └── src/
│ ├── main.ts # port 3009, prefix api
│ ├── app.module.ts
│ ├── auth/
│ │ ├── auth.controller.ts
│ │ ├── auth.service.ts
│ │ ├── jwt.strategy.ts
│ │ └── jwt-auth.guard.ts
│ ├── readings/
│ │ ├── readings.controller.ts
│ │ ├── readings.service.ts
│ │ └── readings.module.ts
│ └── prisma/
└── web/
├── tailwind.config.js # fog/navy/sea/coral · Sora/Nunito
├── src/styles.css
└── src/app/
├── app.routes.ts
├── core/api.service.ts
└── pages/
├── home/home.page.ts
├── login/login.page.ts
├── readings/readings.page.ts
├── reading-new/reading-new.page.ts
└── reading-detail/reading-detail.page.ts
9. Tokens implementados (web)
| Token | Valor |
|---|---|
| bg | #EEF1F4 |
| ink | #0C2340 |
| sea | #2F8F8C |
| coral | #E07A5F |
| border | #D0D8E0 |
| display | Sora |
| sans | Nunito Sans |
10. Seed detallado
| Código | Periodo | kWh | € | Status | Nota asesor |
|---|---|---|---|---|---|
| RE-0809-01 | 2026-07 | 212 | 48.6 | REVIEWED | Pico coherente con ola de calor. |
| RE-0809-02 | 2026-06 | 168 | 39.2 | REVIEWED | Dentro de rango. |
| RE-0809-03 | 2026-08 | 245 | 56.1 | SUBMITTED | — |
| RE-0809-04 | 2026-05 | 141 | 33.4 | FLAGGED | Revisar tarifa PVPC vs fija. |
| RE-0809-05 | 2026-04 | 155 | 36.0 | SUBMITTED | — |
Home: Piso Ruzafa · C/ Sueca 18, 3º · València · CUPS ES0021000000000001AB.
11. Endpoints — tabla de contratos
| Método | Ruta | Auth | Body / notes |
|---|---|---|---|
| POST | /api/auth/login | No | { email, password } |
| GET | /api/readings | JWT | — |
| GET | /api/readings/stats/summary | JWT | — |
| GET | /api/readings/:id | JWT | — |
| POST | /api/readings | JWT RESIDENT | { period, kwh, costEur?, notes?, homeLabel? } |
| PATCH | /api/readings/:id/status | JWT ADVISOR | { status, advisorNote? } |
12. Paridad con Paper y case
| Artefacto | Ref |
|---|---|
| Paper | 01KZJNCCMJ1FDHHPZZ923RWDWY |
| Hero | assets/hero.jpg (case + web) |
| Docs | 2026-08-09-rele/docs/* |
| Executive | presentation/executive-summary.md |
13. Criterio de cierre implementación
- API runnable :3009
- Web runnable :4200
- Neon + seed
- Multi-rol authz
- Vertical slice lecturas
- Tokens no genéricos
- GitHub
Criscode2022/rele-app