00-day-brief.md
00 — Day brief · 2026-08-27 · PIÑÓN
Decisiones ALS-2 BRIEF
| Campo | Valor |
|---|---|
| Fecha | 2026-08-27 |
| Nombre | PIÑÓN |
| Complejidad | Nivel 2 (no L1 consecutivo tras BOBINA) |
| Sector | Movilidad urbana / taller de bicicletas de barrio (nave Arganzuela · Legazpi) |
| Tipo | Bento del taller + configurador de encargo + mesa MECÁNICO JWT |
| Plataforma | Web responsive (bento en el móvil · mesa en el portátil del mostrador) |
| Registro | R-HY — identidad de oficio clásica + bento/configurador |
| Shell | S-TOP — Taller · Encargo · Mesa |
| Home | H-BENTO foto-led Deriva — tile de nave a sangre (≥40 % del recorte 16/10) + 3 datos + 4 bicis |
| Flujo | F-CMP — configurar el arreglo (rueda / frenos / cadena / revisión), luego dejar la bici |
| Por qué no BOBINA | No S-DOCK / H-FEED / F-STORY; no cineclub; no velvet |
| Por qué no LOMO | No S-CMD / H-DATA / F-LEAD; no archivo; no mesa de ejemplares |
| Por qué no MATIZ | MATIZ era S-BOTTOM+H-BENTO+F-EDIT (N−8). Aquí S-TOP + F-CMP; el núcleo es el configurador, no el editor de gramos |
| Por qué no ZAGUÁN | ZAGUÁN era S-WIZ+H-WIZARD+F-CMP. Aquí no hay wizard de criterios; hay bento de taller |
| Por qué no TROCHA | No flota de última milla; la bici se deja, no se reparte |
| Por qué no VOLTA | No club ni plaza; encargo ≠ cita de fitness |
Terna unicidad
R-HY · S-TOP · H-BENTO · F-CMP
0 códigos iguales a N−1 (BOBINA: R-IN · S-DOCK · H-FEED · F-STORY).
≥2 distintos vs N−2 (LOMO: S-CMD · H-DATA · F-LEAD) y N−3 (ONDA: S-RAIL · H-GALLERY · F-SEARCH).
S-TOP, H-BENTO y F-CMP no están en los últimos 5.
R-HY cumple la mezcla de 4 días (BOBINA R-IN, LOMO R-CL, ONDA R-HY).
Ground (CRON §5.6)
- Familia: G-GRAPHITE
- Hex:
#2C3033 - Por qué: suelo de nave y esmalte de cuadro, no terciopelo (BOBINA), no caliza (LOMO), no cartel blanco (ONDA), no hielo (RAMAL), no tinta de flight case (TEMPLE).
Mood visual (Paper)
- Candidatos: nocturnal/fixie neón (primer instinto taller cool), industrial, rusted, arid, botanical
- Elegido: industrial — no el primer instinto Rapha/neón. Un taller de Legazpi se lee con esmalte, hormigón y naranja de reflector, no con LED de tienda de fixies.
- Paleta:
#2C3033grafito de nave (ground)#F3F1ECficha / cream#1A1C1Bcard oscura#E24A17naranja de reflector (mark)#8B8E8Amute#C5C8C4cromo (poco)
- Tipo: Spectral display · Sora UI
Home foto-led (D-P1-09)
UI-01 = Deriva en bento: tile de la nave a sangre (≥40 % del recorte 16/10) + lead + 3 datos (en taller / listas / esperan) + 4 bicis. No feed. No H-DATA tabla. Cuota last 6: BOBINA+LOMO = 2 → PIÑÓN es el 3º.
Alcance L2 must
- Home bento foto-led: 4 bicis + 3 métricas
- Configurador de arreglo (F-CMP)
- Dejar la bici (nombre, teléfono, color del cuadro)
- Success con código de encargo
- Login JWT MECÁNICO
- Mesa de ganchos (EN_TALLER / LISTA / ESPERA) — no kanban
- Empty / error / loading / mobile bento
- ≥12 UX + ≥10 UI
Microcopy duro
- Dejar la bici ≠ comprar el taller. No se vende una bici nueva.
- Encargo ≠ cita de fitness. No reserva una clase.
- Recoger ≠ alquilar. No es un bike-share.
- PIÑÓN no es Decathlon.
Supuestos
- S1: El taller atiende 2–4 bicis/día en el slice; demo 4. [SUPUESTO]
- S2: El vecino deja la bici sin cuenta. JWT solo MECÁNICO. [SUPUESTO]
- S3: Repartidor y dueño de la nave fuera del producto. [SUPUESTO]
- S4: Sin e-commerce, sin GPS, sin chat, sin kanban. [DECISIÓN]
Hipótesis
| ID | Señal |
|---|---|
| H1 | Un bento de ganchos reduce «¿está lista?» por WhatsApp |
| H2 | El configurador evita el «arréglame lo que sea» que no cabe en un L2 |
| H3 | Cuatro bicis bastan; no hace falta el stock de Decathlon |
Seed demo
| Código | Bici | Arreglo | Estado |
|---|---|---|---|
| PIN-2701 | Orbea urbana verde | Frenos | EN_TALLER |
| PIN-2702 | BH paseo crema | Revisión | LISTA |
| PIN-2703 | Classic fold negra | Rueda | EN_TALLER |
| PIN-2704 | Trek niño azul | Cadena | ESPERA |
Modelos son catálogo demo. No es un taller real ni un acuerdo con Orbea. [SUPUESTO de taller]
JWT
nuria@pinon.taller / password123 · rol MECANICO · API :3027
00-paper-reference.md
Paper reference · PIÑÓN
| URL | https://app.paper.design/file/01M110K5JHDQ899C360KC4D0WD |
| File ID | 01M110K5JHDQ899C360KC4D0WD |
UX-count: 12 UI-count: 12
UX process (prefijo UX- · mínimo 12)
| ID | Nombre | Contenido |
|---|---|---|
| UX-00 | Cover | Identidad industrial, terna, foto nave |
| UX-01 | Stakeholders | Nuria MECÁNICO, Pablo VECINO, fuera de slice |
| UX-02 | Personas | Pablo 34 / Nuria 41 |
| UX-03 | JTBD | Funcional / emocional / social |
| UX-04 | Stories | Must dejar bici / configurar / mesa |
| UX-05 | Journey | Descubrir → configurar → dejar → código |
| UX-06 | Blueprint | Frontstage / mesa / Neon / 409 |
| UX-07 | Site map | S-TOP Taller · Encargo · Mesa |
| UX-08 | Flujos | POST encargos + JWT mesa |
| UX-09 | Datos + permisos | Bike / Request / User |
| UX-10 | Métricas | North star encargos recogidos |
| UX-11 | Research notes | Etiquetado COMPROBADO/SUPUESTO/HIPÓTESIS/DECISIÓN |
UI producto (prefijo UI- · mínimo 10)
| ID | Nombre | Flujo |
|---|---|---|
| UI-01 | Taller bento foto-led | Home Deriva-split ≥40 % |
| UI-02 | Configurador | F-CMP 4 piezas |
| UI-03 | Dejar bici | Nombre + teléfono |
| UI-04 | Success | PIN-2705 copy duro |
| UI-05 | Login | JWT MECÁNICO |
| UI-06 | Mesa | 4 ganchos, no kanban |
| UI-07 | Empty | No hay ganchos hoy |
| UI-08 | Error | 409 cupo ESPERA |
| UI-09 | Loading | Skeletons |
| UI-10 | Tokens | G-GRAPHITE industrial |
| UI-11 | Mobile bento | Core mobile |
| UI-12 | Mobile encargo | Configurador 390 |
Media
assets/hero.jpgassets/bicis/orbea.jpgassets/bicis/bh.jpgassets/bicis/fold.jpgassets/bicis/trek.jpg
01-project-definition.md
01 — Definición de proyecto — PIÑÓN
1. Identidad
| Campo | Valor |
|---|---|
| Nombre | PIÑÓN |
| Significado | Piñón es el engranaje del taller de barrio, no el lineal de una gran superficie. Se entra a la nave; se sale habiendo dejado la bici. |
| Eslogan | «El gancho, no el lineal.» |
| Una frase | Bento foto-led de ganchos + configurador de arreglo + dejar la bici + mesa MECÁNICO JWT. |
| Sector | Movilidad urbana / taller de bicicletas de barrio (nave Arganzuela · Legazpi, Madrid) |
| Tipo | Web L2 — bento H-BENTO Deriva + chrome S-TOP + configurador F-CMP + mesa JWT — Nivel 2, vertical slice de taller |
| Plataforma | Web responsive (bento en el móvil · mesa en el portátil del mostrador) |
| Mercado demo | España · Madrid · Arganzuela / Legazpi (un taller de nave, no Decathlon) |
| Idioma | es-ES |
| Fecha caso | 2026-08-27 |
| Terna | R-HY · S-TOP · H-BENTO · F-CMP |
[COMPROBADO] Nombre, terna, nivel, sector, ground y paleta salen de docs/00-day-brief.md.
[SUPUESTO de taller] Arganzuela / Legazpi / Orbea / BH / Trek es atrezzo de mercado, no un taller real ni un acuerdo de marca.
Tras BOBINA (L1 cineclub, 2026-08-26) el día elige L2 taller, no otro L1 consecutivo. N−1 es BOBINA. [DECISIÓN]
2. Problema
Principal (hipótesis de diseño)
[HIPÓTESIS] El vecino de Legazpi no necesita comprar una bici nueva ni reservar una clase: necesita dejar la suya y saber si está lista sin preguntar por WhatsApp. Hoy eso vive en un recado al mostrador, un grupo del barrio y una expectativa de «tienda». Dejar la bici se lee como comprar el taller; el encargo se lee como cita de fitness; recoger se lee como alquilar; el producto se lee como Decathlon. [SUPUESTO] Un taller de barrio atiende 2–4 bicis/día; no opera un lineal ni un GPS de flota.
Secundarios
| Problema | Quién lo sufre | Efecto |
|---|---|---|
| «¿Está lista?» por WhatsApp | VECINO (Pablo) | Pregunta, espera, pasa de recoger |
| Dejar la bici se lee como comprar | VECINO + Nuria | Esperan catálogo, talla, precio de cuadro nuevo |
| El encargo se lee como cita | Pablo | Esperan slot, coach, clase |
| Recoger se lee como alquilar | Pablo + Amparo | Esperan candado, app de bike-share, minutos |
| La mesa MECÁNICO se lee como kanban | MECÁNICO (Nuria) | Esperan Recibido / En curso / Cerrado |
| El dueño pide lineal y GPS el día 1 | Nave | El L2 se vuelve Decathlon + TROCHA |
Supuestos (no investigación primaria propia)
- S1: El taller atiende 2–4 bicis/día en el slice; demo 4. [SUPUESTO]
- S2: El vecino deja la bici sin cuenta. JWT solo MECÁNICO. [SUPUESTO]
- S3: Repartidor y dueño de la nave fuera del producto. [SUPUESTO]
- S4: Sin e-commerce, sin GPS, sin chat, sin kanban. [DECISIÓN]
Hipótesis de producto
| ID | Hipótesis | Señal de validación (futura) |
|---|---|---|
| H1 | Un bento de ganchos reduce «¿está lista?» por WhatsApp | % de visitas a / que consultan estado sin mensaje |
| H2 | El configurador evita el «arréglame lo que sea» que no cabe en un L2 | POST /encargos con job explícito (rueda / frenos / cadena / revisión) |
| H3 | Cuatro bicis bastan; no hace falta el stock de Decathlon | 0 catálogo de venta; Nuria opera 4 ganchos |
No se afirman estadísticas de taller inventadas. Todo lo anterior es razonamiento de diseño etiquetado.
3. Propuesta de valor
| Para | Valor |
|---|---|
| VECINO (Pablo Mora) | Ve 4 ganchos en el bento, configura el arreglo, deja la bici, se lleva el código. Nadie le pide cuenta ni le vende un cuadro. |
| MECÁNICO (Nuria Vega) | Ve la mesa de ganchos (ESPERA / EN_TALLER / LISTA). No mueve columnas. No vende bicis. |
| VECINA MAYOR (Amparo Díaz) | Fuera del login; la documentación y a11y la contemplan (contraste cream/grafito, targets, copy legible). |
| Taller PIÑÓN | Una superficie mínima: bento + configurador + mesa, sin Decathlon y sin GPS. |
No es PIÑÓN
| Excluido | Por qué |
|---|---|
| Lineal / venta de bici nueva | Dejar la bici ≠ comprar el taller |
| Cita de fitness / slot de clase | Encargo ≠ cita de fitness |
| Alquiler / bike-share / minutos | Recoger ≠ alquilar |
| Decathlon / gran superficie | PIÑÓN no es Decathlon |
| Catálogo completo / miles de SKU | H3 · S1 |
| Chat de vecinos / kanban | Eso fue PREGÓN (H-CHAT / F-KAN) |
| Flota de última milla / GPS | Eso fue TROCHA |
| Club / plaza / reserva de clase | Eso fue VOLTA (encargo ≠ cita) |
| Wizard de criterios inmobiliarios | Eso fue ZAGUÁN (S-WIZ / H-WIZARD / F-CMP de fincas) |
| Editor de gramos / fichas de color | Eso fue MATIZ (S-BOTTOM / F-EDIT) |
| Feed de noches / pedir butaca | Eso fue BOBINA (H-FEED / F-STORY) |
| Mesa de ejemplares + comando | Eso fue LOMO (H-DATA / S-CMD / F-LEAD) |
| Hero 2-col + 3 cards de «tu taller» | Anti-patrón AP-12; contradice H-BENTO Deriva |
| App de 40.000 SKU y CMS | L2 compacto, no Decathlon |
4. Objetivos
Negocio / caso de estudio
- Demostrar vertical slice L2 taller de barrio con Bike + Request + JWT MECÁNICO.
- Portfolio coherente: Paper (12 UX + 12 UI) + docs + app runnable.
- Terna R-HY · S-TOP · H-BENTO · F-CMP frente a BOBINA (dock/feed/story), LOMO (cmd/datos/lead) y ONDA (rail/galería/archivo).
- No encadenar otro L1 tras BOBINA. [DECISIÓN]
Usuario
| Rol | Objetivo medible en demo |
|---|---|
| VECINO | Ver 4 bicis, configurar un arreglo, dejar la bici y ver el success en < 90 s, sin cuenta |
| MECÁNICO | Entrar a mesa, ver ganchos ESPERA / EN_TALLER / LISTA en < 45 s |
| VECINA MAYOR | No encuentra login; a11y y docs la contemplan; no es rol de sistema |
No objetivos v1 (explícitos)
- E-commerce, precio, pago, lineal de bicis nuevas
- GPS, tracking, flota, última milla
- Cita de fitness, slot, coach, plaza
- Alquiler, bike-share, candado conectado
- Chat, kanban, columnas Recibido / En curso
- Cuenta de vecino, socio, newsletter
- Multi-nave, multi-mecánico
- App nativa ni notificaciones push
- Rol repartidor / dueño autenticado
- Sesiones, butacas, PROGRAMADOR (BOBINA es otro día)
- Ejemplares, BIBLIO, comando (LOMO es otro día)
- Programas, repeticiones, CONDUCTOR (ONDA es otro día)
- Fórmulas, COLORISTA, editor de gramos (MATIZ es otro día)
5. Roles y permisos (resumen)
| Acción | Anónimo (vecino) | MECÁNICO | VECINA MAYOR |
|---|---|---|---|
Ver taller / | Sí | Sí | Sin cuenta; usa la pública |
Ver configurador /encargo | Sí | Sí (no es el job) | — |
| POST dejar bici | Sí | Sí (no es el job) | Sí (mismo form público) |
Ver success /ok/:code | Sí (código en URL) | Sí | — |
Ver mesa /mesa | No (401 / redirect) | Sí | No |
GET /api/mesa | 401 | Sí | — |
| Ver teléfonos de encargos | No | Sí (mesa) | — |
| Vender bici nueva | No (no existe) | No | Fuera |
| GPS / reparto | Copy: fuera | Copy: fuera | Oficio fuera de app |
[DECISIÓN] Un solo rol autenticado: MECÁNICO. El vecino no es un usuario del sistema: es autor/autora de un request. Amparo no es un rol de sistema el día 1.
6. Métricas (modelo, no instrumentadas en v1 salvo base)
| Tipo | Métrica | Definición |
|---|---|---|
| North Star | % de bicis LISTA recogidas sin un WhatsApp de «¿está lista?» | Oficio de gancho, no pageviews |
| Activación vecino | 1.er POST /api/encargos con code | H2 |
| Integridad de expectativa | Reclamaciones «¿compro la bici?» / «¿es una cita?» / «¿alquilo?» | H2 + microcopy |
| Integridad de auth | GET /api/mesa sin token → 401; POST /api/encargos sin token → 201 | Bento público + mesa MECÁNICO cerrada |
| Salud | Error rate API bicis / encargos | 4xx/5xx |
7. Alcance funcional v1 (L2)
| Módulo | Incluido |
|---|---|
| Home bento | GET /api/bicis · tile de nave a sangre + 3 métricas + 4 bicis |
| Configurador | /encargo paso 1 · rueda / frenos / cadena / revisión |
| Dejar bici | /encargo paso 2 · nombre, teléfono, color del cuadro |
| Encargo | POST /api/encargos → success; dejar ≠ comprar |
| Auth | POST /api/auth/login → JWT MECÁNICO |
| Mesa MECÁNICO | GET /api/mesa JWT · ganchos ESPERA / EN_TALLER / LISTA, no kanban |
| Estados UI | Empty (0 bicis), loading skeleton, error de red |
| Mobile | Bento ~390px · S-TOP Taller · Encargo · Mesa · targets ≥44px |
| Seed | 1 MECÁNICO, 4 bicis (2 EN_TALLER, 1 LISTA, 1 ESPERA) |
| Salud | GET /api/health → { ok: true, service: "pinon-api" } |
8. Criterios de aceptación de producto
/es el bento foto-led Deriva (tile de nave a sangre ≥40 % del recorte 16/10 + lead + 3 datos + 4 bicis). No pide cuenta. No es un hero 2-col + 3 cards. No es un feed. No es una mesa de datos.- Un vecino puede ver 4 bicis, configurar un arreglo, dejar la bici y obtener success en
/ok/PIN-XXXX. /ok/:codedice explícitamente que dejar la bici no es comprar el taller y que encargo no es cita de fitness.- La UI dice explícitamente que recoger no es alquilar y que PIÑÓN no es Decathlon.
- Sin token, GET
/api/mesaresponde 401. POST/api/encargosy GET/api/bicisson públicos. - Un POST de encargo no crea user, no cobra, no abre un lineal, no mueve kanban, no enciende GPS.
- Un MECÁNICO inicia sesión y ve 4 bicis (2 EN_TALLER, 1 LISTA, 1 ESPERA) en el seed.
- El tablero autenticado es una mesa de ganchos. No es un kanban de 3 columnas. No es un split lista | ficha.
- Fotos reales en las cubiertas seed (assets
bicis/*). - Chrome S-TOP: Taller · Encargo · Mesa. Home sin dock de cineclub y sin comando de archivo.
- Rutas solo las del doc 03. No existen
/buscar,/sesion,/pedir,/lomo,/cita,/tienda. GET /api/healthdevuelveservice: "pinon-api"(nobobina-api, nolomo-api).- El bento público no muestra teléfonos de otros vecinos; la mesa MECÁNICO sí muestra encargos con nombre y teléfono.
- PIN-2702 aparece LISTA; PIN-2704 aparece ESPERA; no se vende ninguna.
9. Stack y artefactos
| Capa | Detalle |
|---|---|
| Frontend | Angular + Tailwind · puerto 4200 |
| Backend | NestJS · puerto 3027 |
| DB | Neon PostgreSQL · project dedicado PIÑÓN (DATABASE_URL) |
| Auth | JWT (MECÁNICO) |
| Diseño | Paper 01M110K5JHDQ899C360KC4D0WD |
| Repo app | /Users/cristian/orca/pinon-app/ · GH Criscode2022/pinon-app |
| Package | pnpm |
[COMPROBADO] Puerto, Paper file ID y path de app constan en el encargo.
El código vive en pinon-app con este contrato. Este doc es la fuente de verdad del slice L2.
10. Riesgos y mitigaciones
| Riesgo | Impacto | Mitigación v1 |
|---|---|---|
| Expectativa de Decathlon | «¿Compro la bici?» | Copy «Dejar la bici ≠ comprar el taller» |
| Expectativa de fitness | Slot, clase, coach | Copy «Encargo ≠ cita de fitness» |
| Expectativa de alquiler | Bike-share, minutos | Copy «Recoger ≠ alquilar» |
| Expectativa de gran superficie | Lineal, SKU, talla | Copy «PIÑÓN no es Decathlon» |
| Expectativa de kanban | Recibido / En curso | Mesa de ganchos, no columnas de flujo |
| Leftover BOBINA | sesiones, PROGRAMADOR, bobina-api | Contrato PIÑÓN; health pinon-api; 0 copy de sala |
| Leftover LOMO | ejemplares, BIBLIO, comando | Dominio bicis + requests + MECANICO |
| E-commerce el día 1 | Alcance L3 disfrazado | H3: cuatro ganchos |
| GPS el día 1 | Alcance TROCHA | S4; roadmap L3 |
| Cuenta de vecino | Rompe S2 | Sin signup; POST público con nombre + teléfono |
| Home percibida como landing de tienda | Pérdida de H-BENTO / AP-12 | Deriva tile + 3 datos + 4 bicis |
| Home percibida como feed | Confundir con BOBINA | H-BENTO, no H-FEED |
| Home percibida como mesa de datos | Confundir con LOMO | Bento, no métricas tabulares ni comando |
| Confundir con VOLTA (cita) | Expectativa de clase | Encargo de arreglo, no plaza |
| Confundir con TROCHA (flota) | Expectativa de GPS | La bici se deja, no se reparte |
| 0 bicis | Bento vacío sin oficio | Empty «Aún no hay ganchos.» |
| WhatsApp paralelo | H1 no se mide | North star etiquetada como modelo |
| Mark naranja como texto de párrafo | Contraste WCAG | Mark pinta CTA/foco; cream escribe sobre grafito |
11. Glosario
| Término | Definición en PIÑÓN |
|---|---|
| Piñón | Engranaje / oficio del taller; el producto, no el lineal ni el alquiler |
| Bici | Cuadro en gancho (bicis); no es un SKU de Decathlon |
| Código | PIN-XXXX; identifica el encargo / la bici |
| Encargo | Arreglo configurado (rueda / frenos / cadena / revisión); no es cita de fitness |
| Gancho | Plaza física en la nave; superficie de la mesa |
| Taller | Superficie H-BENTO pública de ganchos; bento sobre foto de nave |
| Mesa (MECÁNICO) | Superficie JWT de Nuria (ganchos por estado, no kanban) |
| Request | POST 201; no significa compra ni alquiler |
| Success | Código (PIN-XXXX); no es un ticket de tienda |
| Espera | Estado ESPERA; aún no se ha puesto a trabajar |
| En taller | Estado EN_TALLER; está en el gancho de trabajo |
| Lista | Estado LISTA; se puede recoger |
| Entregada | Estado ENTREGADA; ya no cuelga; fuera de la mesa v1 |
| S-TOP | Chrome: Taller · Encargo · Mesa |
| MECÁNICO | Usuario autenticado que opera la mesa |
| VECINO | Autor/autora del encargo; no tiene fila en users |
| VECINA MAYOR | Persona de docs / a11y; fuera del login |
| Decathlon | Gran superficie; fuera. Dejar ≠ comprar |
| Fitness | Cita / clase; fuera. Encargo ≠ cita |
| Alquiler | Bike-share; fuera. Recoger ≠ alquilar |
| Industrial | Mood: esmalte, hormigón, naranja de reflector; no LED de fixie |
| Ground | Grafito de nave #2C3033 |
| Cream | Texto / ficha #F3F1EC |
| Card | Superficie oscura #1A1C1B |
| Mark | Naranja de reflector #E24A17 |
| Mute | #8B8E8A |
| Chrome | Cromo #C5C8C4, poco |
| Deriva | Home foto-led: tile de nave a sangre + 3 datos + 4 bicis |
12. Decisiones de diseño (cierre de brief)
| ID | Decisión | Alternativa descartada |
|---|---|---|
| D1 | Home = bento foto-led Deriva (H-BENTO) | Hero 2-col + 3 cards (AP-12) · feed (BOBINA) · mesa de datos (LOMO) |
| D2 | Shell top Taller · Encargo · Mesa (S-TOP) | Dock de cineclub · comando de archivo · rail de radio · bottom tabs MATIZ |
| D3 | Registro híbrido: oficio clásico + bento/configurador (R-HY) | Neón Rapha/fixie (primer instinto) · velvet BOBINA · mineral LOMO |
| D4 | Flujo F-CMP (configurar arreglo → dejar bici) | F-STORY, F-LEAD, F-EDIT, F-KAN, wizard de criterios |
| D5 | Mood industrial | Nocturnal/fixie neón (primer instinto), rusted, arid, botanical |
| D6 | Un rol autenticado MECÁNICO | Multi-rol repartidor / vecino / dueño |
| D7 | Status ESPERA / EN_TALLER / LISTA / ENTREGADA | Kanban de 3 columnas; «vendida»; «en ruta» |
| D8 | Vecino sin cuenta | Signup, socio, carnet de taller |
| D9 | Bento público no lista teléfonos | Tablero público enumerable |
| D10 | POST público de encargo con nombre + teléfono + color | Formulario de DNI + pago + talla |
| D11 | Ground G-GRAPHITE #2C3033 | G-VELVET, G-STONE, G-SIGN, G-ICE, G-INK |
| D12 | Success en /ok/:code | Toast único sin pantalla |
| D13 | Configurador y dejar bici en /encargo (dos pasos, una ruta) | POST oculto en el tile; wizard 5 pasos |
| D14 | Mesa MECÁNICO = ganchos por estado, no kanban ni split | Recibido / En curso / Cerrado; lista | ficha RAMAL |
| D15 | Bento público + mesa JWT (no auth-first total) | Todo cerrado (rompería S2) · todo abierto (rompería mesa) |
| D16 | Sin e-commerce / GPS | Precio + tracking |
| D17 | Leftover BOBINA no es el producto | Mantener sesiones / PROGRAMADOR / bobina-api |
| D18 | Health pinon-api · puerto 3027 | leftover bobina-api · :3026 |
| D19 | Job de arreglo = una pieza (rueda | frenos | cadena | revisión) | «Arréglame lo que sea»; carrito multi-SKU |
| D20 | Encargo nuevo entra en ESPERA | Entra directo EN_TALLER (saltaría el gancho de cola) |
13. Relación con el día anterior
| Case | Terna | Por qué PIÑÓN no lo copia |
|---|---|---|
| BOBINA (N−1) | R-IN · S-DOCK · H-FEED · F-STORY | No cineclub, no feed, no dock, no butaca, no PROGRAMADOR |
| LOMO (N−2) | R-CL · S-CMD · H-DATA · F-LEAD | No archivo, no ejemplares, no comando, no BIBLIO, no mesa de datos |
| ONDA (N−3) | R-HY · S-RAIL · H-GALLERY · F-SEARCH | Comparte R-HY; no radio, no cubiertas, no repetición, no rail |
| MATIZ (N−8) | R-HY · S-BOTTOM · H-BENTO · F-EDIT | Comparte H-BENTO; aquí S-TOP + F-CMP; el núcleo es el configurador, no el editor de gramos |
| ZAGUÁN | R-IN · S-WIZ · H-WIZARD · F-CMP | Comparte F-CMP; no hay wizard de criterios; hay bento de taller |
| TROCHA | — | No flota de última milla; la bici se deja, no se reparte |
| VOLTA | — | No club ni plaza; encargo ≠ cita de fitness |
[COMPROBADO] El brief fija terna R-HY · S-TOP · H-BENTO · F-CMP. 0 códigos iguales a N−1 (BOBINA). ≥2 distintos vs N−2 (LOMO) y N−3 (ONDA). S-TOP, H-BENTO y F-CMP no están en los últimos 5. Ground G-GRAPHITE #2C3033, no G-VELVET ni G-STONE.
02-ux-research-strategy.md
02 — Estrategia de investigación UX — PIÑÓN
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].
1. Objetivos de investigación (del caso)
| Objetivo | Método en este caso | Salida |
|---|---|---|
| Entender actores del taller de barrio | Modelado de stakeholders + personas | §3–4 |
| Definir job «dejar la bici y saber si está lista sin WhatsApp» | JTBD + stories Must | §5–6 |
| Mapear fricción WhatsApp / Decathlon / fitness / alquiler → bento + configurador | Journey + service blueprint | §7–8 |
| Traducir a requisitos L2 bento + F-CMP + dejar + mesa | Matriz hallazgo → requisito → feature | §9 |
2. Fuentes y límites
Fuentes admisibles (secundarias / operativas)
- Conocimiento general de talleres de barrio (mostrador, gancho, recado de «¿está lista?», 2–4 bicis al día, mecánica que opera la nave, dueño y reparto fuera del producto día 1).
- Analogía operativa con superficie pública + panel JWT de la serie daily.
- Restricciones ALS-2: no Decathlon, no cita de fitness, no alquiler, no flota GPS, no cineclub, no archivo, no editor de gramos.
Límites éticos de verdad
| Prohibido | Permitido |
|---|---|
| «El 58% de vecinos de Legazpi pregunta por WhatsApp si está lista» sin fuente | «[SUPUESTO] Pablo abre el taller desde el móvil» |
| Citas de entrevistas ficticias como campo real | Quotes de persona etiquetadas como constructo de diseño |
| Volumen medido «23 Orbea/semana» como KPI de mercado | Bicis de seed de producto, etiquetadas como demo |
| Taller oficial Orbea / BH en Arganzuela 2026 | Bicis de seed; Nuria, Pablo y Amparo son personas de diseño |
| «Pablo existe y nos dijo…» | Pablo Mora es persona de diseño |
3. Stakeholders
| Stakeholder | Influencia | Interés | Necesidad principal |
|---|---|---|---|
| MECÁNICO (Nuria) | Alta | Muy alta | Ver ganchos sin kanban ni lineal |
| VECINO (Pablo) | Alta en el encargo | Muy alta | Dejar la bici y saber el código, sin cuenta |
| VECINA MAYOR (Amparo) | Media formal, baja en producto día 1 | Alta | Leer el taller con contraste y targets; sin login forzado |
| Nave / taller de barrio | Alta formal | Alta | Que se vea qué cuelga; que no se confunda con Decathlon ni con un gimnasio |
| Decathlon / gran superficie | Competencia / analogía falsa | — | Fuera de alcance; no clonar lineal |
| Club de fitness / VOLTA | Analogía falsa de cita | — | Fuera; Encargo ≠ cita de fitness |
| Bike-share / alquiler | Analogía falsa de recoger | — | Fuera; Recoger ≠ alquilar |
| TROCHA / flota | Anti-patrón de GPS | — | Fuera; la bici se deja, no se reparte |
| BOBINA / cineclub | Anti-patrón N−1 | — | Fuera; no sesiones, no butaca, no feed |
| LOMO / archivo | Anti-patrón N−2 | — | Fuera; no ejemplares, no BIBLIO, no comando |
| Grupo de WhatsApp del barrio | Canal paralelo | — | No es el backoffice; H1 apunta a reducirlo |
| Dueño de la nave / repartidor | S3 fuera | — | Fuera del JWT |
Mapa de poder (resumen)
- Decisor de adopción: el taller (quién cuelga las bicis) y, en uso diario, Nuria (quien mira ganchos).
- Usuario frecuente de dejar bici: VECINO (bento + configurador + form, sin cuenta).
- Usuario frecuente de oficio: MECÁNICO (mesa
/mesa). - Riesgo de rechazo: si el success parece un ticket de tienda; si el tile parece un SKU de Decathlon; si hay que crear cuenta; si la mesa parece un kanban; si el encargo parece una cita.
4. Personas
P1 — Nuria Vega · MECÁNICO
| Campo | Detalle |
|---|---|
| Edad / contexto | 39 años; mecánica del taller PIÑÓN en nave de Arganzuela / Legazpi; mesa de ganchos, no de lineal |
| Digital | Fluida en el portátil del mostrador; el bento público no es su herramienta principal, pero lo mira |
| Goals | Ver qué bicis esperan, cuáles están en taller, cuáles están listas para recoger |
| Pains | WhatsApp a deshora; «¿me venden una Orbea?»; un kanban que no es su oficio; un GPS que no es su job de hoy |
| Quote de diseño | «Quiero ver los ganchos. No una tienda y no un gimnasio.» |
| Email demo | nuria@pinon.taller / password123 |
Escenario: Entra a /login, abre /mesa, lee PIN-2702 BH paseo LISTA, ve los encargos. El copy dice que recoger no es alquilar.
[COMPROBADO] Nombre de cuenta, email demo y rol salen del encargo. Edad y apellido son constructo de diseño. [DECISIÓN]
P2 — Pablo Mora · VECINO
| Campo | Detalle |
|---|---|
| Edad / contexto | 34 años; vive en Legazpi; deja la bici cuando falla un freno o una rueda; no quiere «otra cuenta de tienda» |
| Digital | Móvil desde la acera o el sofá; no se hace socio si puede evitarlo |
| Goals | Ver qué cuelga en la nave; configurar el arreglo; dejar la bici; llevarse un código |
| Pains | El WhatsApp dice «creo que está lista el jueves»; abre Decathlon; le venden un cuadro; cree que reserva una clase |
| Quote de diseño | «Solo quiero dejar la bici. No me hagas una tienda.» |
Escenario: Abre / en el móvil, ve 4 ganchos, toca Encargo, elige frenos, escribe nombre y teléfono y color, lee «dejar la bici ≠ comprar el taller» y el código PIN-XXXX.
[COMPROBADO] El gesto (vecino, deja sin cuenta) sale del encargo. Nombre y edad son constructo de diseño. [DECISIÓN]
Pablo no tiene fila en users. [DECISIÓN]
P3 — Amparo Díaz · VECINA MAYOR (docs / a11y)
| Campo | Detalle |
|---|---|
| Edad / contexto | 71 años; vecina de Arganzuela; lee el taller con calma; contraste y tamaño importan |
| Digital | No tiene login en el slice L2; usa la superficie pública si el contraste y los targets aguantan |
| Goals | Entender cómo dejar la bici, sin mistificarse con Decathlon ni con un alquiler |
| Pains | Texto mute sobre grafito; botones pequeños; copy de gran superficie |
| Quote de diseño | «Si no leo el gancho, no dejo la bici. No me vendáis una.» |
[DECISIÓN] no hay cuenta de Amparo en v1; a11y la contempla en docs 10. Nombre y edad son constructo de diseño.
5. JTBD
Job principal (vecino)
Cuando la bici falla (rueda, frenos, cadena o toca revisión), quiero configurar el arreglo y dejarla en el taller sin preguntar por WhatsApp, para que Nuria la cuelgue sin que eso signifique compra, cuenta, cita ni alquiler.
Job principal (mecánica)
Cuando hay ganchos ocupados y encargos nuevos, quiero ver ESPERA / EN_TALLER / LISTA, para mover el oficio del taller sin un kanban ni un lineal.
Jobs que PIÑÓN no hace
| Job | Por qué no |
|---|---|
| Comprar una bici nueva | Dejar la bici ≠ comprar el taller · S4 |
| Reservar una clase / plaza | Encargo ≠ cita de fitness |
| Alquilar / desbloquear una bici | Recoger ≠ alquilar |
| Sustituir a Decathlon | PIÑÓN no es Decathlon |
| Rastrear GPS / última milla | ≠ TROCHA · S4 |
| Pedir butaca de cineclub | ≠ BOBINA |
| Pedir mesa de un lomo | ≠ LOMO |
| Editar gramos de color | ≠ MATIZ |
| Comparar 3 fincas | ≠ ZAGUÁN |
6. Stories Must (v1)
| ID | Como | Quiero | Para |
|---|---|---|---|
| US-01 | Vecino | Ver bento foto-led de 4 bicis + 3 métricas | Distinguir taller de Decathlon / feed / tabla |
| US-02 | Vecino | Configurar el arreglo (rueda / frenos / cadena / revisión) | Evitar «arréglame lo que sea» |
| US-03 | Vecino | Dejar la bici (nombre, teléfono, color) y ver success PIN-XXXX | Dejar constancia, no comprar |
| US-04 | Mecánica | Entrar con JWT | Abrir la mesa de ganchos |
| US-05 | Mecánica | Ver ESPERA / EN_TALLER / LISTA + encargos | Oficio sin kanban |
| US-06 | Ambos | Ver empty / error / loading | No quedarse en blanco |
| US-07 | Vecino | Usar S-TOP en 390 | Taller · Encargo · Mesa sin hamburger |
Could (fuera de L2, solo L3): GPS, e-commerce, login de Amparo, pago, chat, cuenta de vecino.
7. Journey (resumen)
- Pablo abre
/. Ve tile de nave a sangre + 3 datos (en taller / listas / esperan) + 4 bicis. PIN-2702 LISTA; PIN-2704 ESPERA. [H1] - Toca Encargo →
/encargo. Elige Frenos. [H2] - Paso 2: escribe «Pablo Mora», teléfono, color del cuadro. POST →
/ok/PIN-XXXX. Lee las cuatro oposiciones. - Nuria entra a
/login→/mesa. Ganchos por estado + encargos. - Lee PIN-2702 LISTA y el encargo nuevo de Pablo en ESPERA. Copy: recoger no es alquilar.
Backstage: Nest + Neon + JWT. Repartidor y dueño no entran. No hay Decathlon. No hay GPS.
8. Blueprint (resumen)
| Capa | Qué pasa |
|---|---|
| Frontstage (nave / calle) | Bento Deriva en móvil. Configurador. Form dejar bici. Success. S-TOP. |
| Backstage (mostrador) | Nuria mira /mesa. El arreglo físico es oficio, no un lineal. GPS y caja de tienda están fuera de app. |
| Soporte | Nest · Neon dedicado PIÑÓN · JWT MECÁNICO · Paper industrial |
9. Matriz hallazgo → requisito → feature
| Hallazgo (etiquetado) | Requisito | Feature v1 |
|---|---|---|
| [HIPÓTESIS H1] Bento de ganchos reduce WhatsApp | 4 bicis + 3 métricas en fold sobre tile | / H-BENTO Deriva |
| [HIPÓTESIS H2] Job explícito evita «lo que sea» | Configurador de 4 arreglos | /encargo paso 1 |
| [HIPÓTESIS H3] Cuatro bicis bastan | Sin lineal | Seed 4 · no Decathlon |
| [SUPUESTO S2] Sin cuenta de vecino | POST público | POST /api/encargos |
| [SUPUESTO S3] Una mecánica | Un rol JWT | MECANICO |
| [DECISIÓN S4] Sin e-commerce / GPS / chat / kanban | No pago, no tracking, no hilo, no columnas | Fuera de alcance · L3 GPS/e-commerce |
10. Preguntas que este case no responde
- ¿Cuántas bicis reales se dejan en Legazpi en 2026?
- ¿Qué taller opera un acuerdo con Orbea?
- ¿Pablo preferiría el WhatsApp?
- ¿Amparo necesita un modo tipográfico mayor permanente?
- ¿Nuria marcaría LISTA antes de las 19:00 de verdad?
Esas preguntas piden campo. Aquí hay un vertical slice de diseño, no un estudio.
11. Cierre
Investigación = modelado etiquetado + restricciones ALS-2.
No hay entrevistas inventadas.
Paper UX-00…11 documenta el mismo arco. [COMPROBADO] inventario en 00-paper-reference.md.
03-information-architecture.md
03 — Arquitectura de información — PIÑÓN
1. Principios de IA
| Principio | Aplicación |
|---|---|
| Bento first | La home es tile de nave a sangre + 3 datos + 4 bicis. No hay landing de marca por delante. No hay feed. No hay mesa de datos. |
| Público / mesa | Pablo deja la bici sin cuenta; Nuria entra con JWT |
| Configurar → dejar → success | Profundidad 2 desde el taller hasta el código (F-CMP) |
| El núcleo es el configurador | F-CMP: arreglo (rueda / frenos / cadena / revisión) antes de los datos personales |
| Mesa MECÁNICO = ganchos | ESPERA / EN_TALLER / LISTA en una mesa; no kanban, no split lista | ficha |
| Lenguaje de dominio | Bici, gancho, encargo, taller, mesa — no «SKU», «cita», «sesión», «ejemplar» |
| Dejar no es comprar | El success no tiene precio ni lineal |
| Taller no es Decathlon | No hay talla, no hay carrito, no hay stock de venta |
| Chrome de oficio | S-TOP Taller · Encargo · Mesa; bento sin dock de cineclub |
2. Sitemap
/ Taller bento público (Deriva) H-BENTO
/encargo Configurador + dejar bici F-CMP · público
/ok/:code Success post-encargo público
/login Login JWT MECÁNICO público
/mesa Ganchos ESPERA / EN_TALLER / LISTA auth
/** → redirect /
Árbol por audiencia
| Audiencia | Nodos relevantes |
|---|---|
| VECINO | Taller → Encargo (configurar → dejar) → Ok. No ve /mesa |
| MECÁNICO | Login → Mesa · (puede leer el taller y el configurador) |
| VECINA MAYOR | Taller / Encargo públicos; sin login |
[COMPROBADO] Cinco rutas del encargo L2. No se inventan /buscar, /sesion, /pedir, /lomo, /cita, /tienda, /gps.
El configurador sí es ruta (/encargo): F-CMP necesita URL compartible y un paso antes del POST. [DECISIÓN]
Dejar bici no es ruta extra: es el paso 2 de /encargo (UI-03). L2 compacto. [DECISIÓN]
/ok/:code usa el código de bici (PIN-2705), no un código de petición distinto. [DECISIÓN]
No hay /buscar: no hay S-CMD. El hallazgo es el bento. [DECISIÓN]
No hay /bici/:code de ficha pública: el oficio de estado vive en el bento y en la mesa. Could L3. [DECISIÓN]
3. Navegación
Top (S-TOP · todas las superficies salvo login/ok pueden mostrarlo)
| Slot | Destino | Visibilidad | Notas |
|---|---|---|---|
| Taller | / | Todos | Vuelve al bento Deriva. No es hero de marca |
| Encargo | /encargo | Todos | Entra al configurador (paso 1) |
| Mesa | /mesa | MECÁNICO; si guest → /login?next=/mesa | Oficio JWT |
[DECISIÓN] El top es la navegación primaria. No hay dock (BOBINA), no hay comando (LOMO), no hay rail (ONDA), no hay bottom tabs (MATIZ), no hay wizard chrome (ZAGUÁN).
Desktop ≥960px: barra superior fija grafito; wordmark PIÑÓN a la izquierda; slots a la derecha.
Mobile ~390px: top compacto Taller · Encargo · Mesa; no hamburger. [DECISIÓN] En 390 el top no se esconde detrás de un menú.
Taller público (H-BENTO Deriva)
| Elemento | Destino | Notas |
|---|---|---|
| Tile de nave a sangre | — | ≥40 % del recorte 16/10; foto-led |
| Wordmark PIÑÓN | / | Sello mark sobre grafito |
| Eslogan | — | «El gancho, no el lineal.» |
| 3 datos | — | En taller / Listas / Esperan (números del seed) |
| Tile de bici | contexto; no ficha | 4 bicis; modelo, color, job, estado |
| CTA Encargo | /encargo | Arranque de F-CMP |
| Slot Mesa (mute) | /login o /mesa si hay token | Oficio, no CTA de marca |
[DECISIÓN] El taller no tiene tabs de marketing, no tiene «Tienda / Clases / Alquiler». El bento basta para hallar.
Chrome de encargo (F-CMP)
| Slot | Destino | Notas |
|---|---|---|
| ← Taller | / | Un paso atrás, no stepper de 5 |
| Paso 1 Configurar | /encargo | 4 opciones de arreglo; una activa |
| Paso 2 Dejar | /encargo (mismo path, paso 2) | Nombre, teléfono, color del cuadro |
| Enviar | POST → /ok/:code | Una acción |
[DECISIÓN] El paso 2 no se alcanza sin job elegido. No hay wizard de criterios tipo ZAGUÁN (zona / presupuesto / musts). Hay dos gestos de oficio: qué se arregla, quién deja la bici.
Chrome de mesa (/mesa autenticado)
| Slot | Destino | Visibilidad | Notas |
|---|---|---|---|
| Mesa | /mesa | Auth | Titular de oficio |
| Ganchos | — | Auth | Agrupados ESPERA / EN_TALLER / LISTA |
| Encargos | — | Auth | Nombre + teléfono + código; no columnas de flujo |
| Taller | / | Auth | Secundario vía S-TOP |
| Salir | limpia token → / | Auth | Cabecera de mesa, no cuarto slot del top |
[DECISIÓN] No hay S-SPLIT (RAMAL). No hay kanban (PREGÓN). No hay /mesa/:code: L2 lee ganchos + encargos. ENTREGADA no se lista en mesa v1.
4. Etiquetas de IA (UI)
| Concepto | Label |
|---|---|
| Home | Taller (no «Inicio», no «Cartelera», no «Hoy», no «Galería») |
| Flujo | Encargo (no «cita», no «pedido de tienda», no «reserva») |
| Form paso 1 | Qué se arregla |
| Form paso 2 | Dejar la bici |
| Success | Dejada / código |
| Staff | Mesa (no «Backoffice», no «Kanban», no «Hoy» JWT) |
| Auth | Mecánica (no «Área cliente», no «Programadora») |
| CTA | Dejar la bici (no «Comprar», no «Reservar clase», no «Alquilar») |
En docs puede decirse «taller bento» para H-BENTO y «mesa MECÁNICO» para el oficio JWT. En UI pública el titular es Taller. En UI autenticada el titular es Mesa. [DECISIÓN]
5. Contenido de cada nodo de IA
| Ruta | Qué hay | Qué no hay |
|---|---|---|
/ | Tile de nave, eslogan, 3 métricas, 4 tiles de bici, S-TOP | Precios, login de vecino, talla, GPS, feed de noches |
/encargo paso 1 | 4 opciones de arreglo, lead, copy irrenunciable | Carrito, SKU, «lo que sea» libre |
/encargo paso 2 | Nombre, teléfono, color, job en solo lectura | DNI, email, pago, socio, modelo obligatorio |
/ok/:code | Código + 4 oposiciones | Contrato, ticket, «ya está inscrito», QR de tienda |
/login | Email / clave MECÁNICO | Signup de vecino |
/mesa | Ganchos de 4 + encargos | Columnas Recibido / En curso; split ficha; mapa GPS |
6. Error / empty / loading (sitio)
Viven en las mismas rutas, no en URLs extra. Artboards: UI-07 empty · UI-08 error · UI-09 loading.
| Estado | Superficie |
|---|---|
| Loading | Skeletons de tile + 3 datos + 4 bicis / pasos de encargo / lista de mesa |
| Empty taller | «Aún no hay ganchos.» |
| Empty mesa | «No hay encargos.» (pueden existir 0 requests con 4 bicis seed) |
| Error red | «La red no responde» + Reintentar |
| 404 código | «Ese encargo no está» en success |
| Encargo sin job | CTA Dejar disabled · «Elige qué se arregla.» |
7. Profundidad y hallazgo
No hay búsqueda Must: el hallazgo es el bento de 4 bicis. Introducir /buscar copiaría LOMO y rompería la terna. [DECISIÓN]
Nuria no filtra la mesa con chips en v1: ve los tres grupos de ganchos. Could L3: filtro; no se cuela como deuda del L2.
8. Códigos y URLs
| Pieza | Forma |
|---|---|
| Bici / encargo | PIN-2701 … PIN-2704 (PIN versales, guion, 4 dígitos) |
| Encargo nuevo | PIN-2705+ secuencial al POST |
| Configurador | /encargo |
| Success | /ok/PIN-2705 |
9. Mapa Paper → rutas
| Artboard | Ruta | Componente |
|---|---|---|
| UI-01 Home bento | / | TallerPage |
| UI-11 Mobile bento | / @390 | TallerPage |
| UI-02 Configurador | /encargo paso 1 | EncargoPage |
| UI-03 Dejar bici | /encargo paso 2 | EncargoPage |
| UI-12 Mobile encargo | /encargo @390 | EncargoPage |
| UI-04 Success | /ok/:code | OkPage |
| UI-05 Login | /login | LoginPage |
| UI-06 Mesa | /mesa | MesaPage |
| UI-07 Empty | mismas rutas | estados |
| UI-08 Error | mismas rutas | estados |
| UI-09 Loading | mismas rutas | estados |
| UI-10 Tokens | theme | Tailwind |
[COMPROBADO] Mapeo alineado a docs/00-paper-reference.md.
04-user-flows.md
04 — Flujos de usuario — PIÑÓN
1. Convenciones
| Token | Significado |
|---|---|
| F-CMP | Configurar el arreglo y luego dejar la bici; la home no es el form |
| Mesa | Ganchos MECÁNICO, JWT |
| 201 | Encargo creado (bici ESPERA + request) |
| 400 | Job ausente / nombre / teléfono / color inválidos |
| 401 | Mesa sin token |
| 404 | Código inexistente |
2. F1 — Vecino deja la bici desde el bento (Must)
/ → GET /api/bicis
→ ve 3 métricas (en taller / listas / esperan) + 4 bicis
→ tap Encargo → /encargo
→ elige job «Frenos» (UI-02)
→ continúa a dejar bici (UI-03)
→ escribe nombre «Pablo Mora», teléfono, color «verde»
→ POST /api/encargos { name, phone, color, job }
→ 201 { code: PIN-2705, model?, color, job, status: ESPERA }
→ /ok/PIN-2705
Entrada: taller bento, sin cuenta.
Salida: código visible + copy «dejar la bici ≠ comprar el taller».
Errores: red (reintentar), 400 validación, 0 bicis (empty del taller; el encargo sigue permitido).
AC
- El form no pide email, DNI, pago ni signup.
- POST no cobra, no crea user, no abre lineal, no mueve kanban, no enciende GPS.
/ok/PIN-2705muestra las cuatro oposiciones.- El paso configurador existe: F-CMP no es un POST oculto en el tile. [DECISIÓN]
- El paso dejar bici existe en la misma ruta: no es un modal efímero sin URL. [DECISIÓN]
- Job es uno de rueda / frenos / cadena / revisión. [DECISIÓN]
3. F2 — Vecino intenta enviar sin configurar (Must · estado)
/encargo → tap Dejar la bici sin job
→ CTA disabled o 400 local
→ copy «Elige qué se arregla.»
AC
- No se permite POST sin
job(400 si se fuerza). - Copy: no «arréglame lo que sea». No «añadir al carrito».
- Pablo puede elegir Frenos y continuar.
4. F3 — Mecánica entra a mesa (Must)
/login → POST /api/auth/login
→ JWT MECANICO
→ /mesa
→ GET /api/mesa
AC
- Sin token,
/mesaredirige a/login?next=/mesa. - GET
/api/mesasin Bearer → 401. - Ganchos: 4 filas agrupadas ESPERA / EN_TALLER / LISTA + encargos (nombre, teléfono, código). No columnas Recibido / En curso.
- Desktop: grupos + encargos en el panel. 390: apilado bajo el S-TOP.
- ENTREGADA no aparece. [DECISIÓN]
5. F4 — Estados de sistema
| Estado | Trigger | UI |
|---|---|---|
| Loading taller | GET bicis en vuelo | Skeletons de tile + 3 datos + 4 tiles (UI-09) |
| Empty taller | 200 { bicis: [] } | «Aún no hay ganchos.» (UI-07) |
| Error taller | 5xx / red | Reintentar (UI-08) |
| Loading encargo | — | Form listo; submit pending (UI-09) |
| Encargo sin job | paso 2 forzado | «Elige qué se arregla.» |
| Loading mesa | GET mesa en vuelo | Skeletons de gancho + encargos |
| Empty mesa encargos | 200 { requests: [] } | «No hay encargos.» (los 4 ganchos seed pueden existir) |
| Login 401 | credenciales | «Email o contraseña no valen.» |
| 404 success | código inexistente | «Ese encargo no está.» |
6. Flujos que no existen
| Flujo | Por qué |
|---|---|
| Signup vecino | S2 · Dejar ≠ socio |
| Comprar bici / lineal | S4 · Dejar ≠ comprar el taller |
| Cita de fitness / slot | Encargo ≠ cita · ≠ VOLTA |
| Alquilar / desbloquear | Recoger ≠ alquilar |
| GPS / ruta / última milla | ≠ TROCHA · S4 |
| Chat | ≠ PREGÓN |
| Pedir butaca | ≠ BOBINA |
| Pedir mesa de lomo / comando | ≠ LOMO |
| Editor de gramos | ≠ MATIZ |
| Wizard 1—2—3 de criterios | F-CMP de arreglo, no de finca |
| Login Amparo | Slice L2 · docs / a11y |
| PATCH estado de bici | Nuria lee ganchos; no mueve columnas en v1 |
| Catálogo Decathlon | H3 · S4 |
Búsqueda ?q= | Sin S-CMD |
7. Tiempos de demo (modelo)
| Actor | Recorrido | Techo |
|---|---|---|
| Pablo | Taller → Encargo → dejar → dejada | < 90 s |
| Pablo (sin job) | Encargo → bloqueo → elige Frenos → dejar | < 90 s |
| Nuria | Login → mesa → leer PIN-2702 LISTA | < 45 s |
No son KPIs medidos. Son techos de diseño para el guión. [HIPÓTESIS]
8. Guión de demo canónico
/— tile de nave a sangre + 3 datos (2 en taller / 1 lista / 1 espera) + 4 bicis. Eslogan. S-TOP.- Lectura rápida: PIN-2701 Orbea EN_TALLER frenos; PIN-2702 BH LISTA revisión; PIN-2703 fold EN_TALLER rueda; PIN-2704 Trek ESPERA cadena.
- Encargo —
/encargo· elige Frenos. - Dejar la bici — nombre Pablo Mora · teléfono · color verde.
- Enviar —
/ok/PIN-2705. Copy ×4. /login—nuria@pinon.taller/password123./mesa— ganchos ESPERA / EN_TALLER / LISTA; PIN-2702 LISTA; encargo de Pablo en ESPERA si se hizo el POST.- 390: bento + S-TOP; no carousel; targets ≥44px.
- API down: error + Reintentar.
9. Contratos de error de API (flujo)
| Caso | HTTP | UI |
|---|---|---|
| POST encargo, job ausente / inválido | 400 | «Elige qué se arregla.» |
| POST encargo, nombre vacío | 400 | «Escribe un nombre.» |
| POST encargo, teléfono vacío / corto | 400 | «Escribe un teléfono.» |
| POST encargo, color vacío | 400 | «Di el color del cuadro.» |
| POST encargo, red | — | mark + Reintentar; no navega a ok |
| GET mesa sin JWT | 401 | redirect login |
| Login malo | 401 | copy de login |
GET /ok code 404 | 404 | «Ese encargo no está.» |
10. S-TOP en flujo
| Desde | Slot Encargo | Comportamiento |
|---|---|---|
/ | Encargo | /encargo paso 1 |
/encargo paso 1 | Encargo | aria-current |
/encargo paso 2 | Encargo | aria-current; atrás vuelve a paso 1 |
/ok/:code | Taller | Vuelve al bento |
/ guest | Mesa | /login?next=/mesa |
/ con token | Mesa | /mesa |
[DECISIÓN] El slot Encargo no inventa un quinto SKU; abre el configurador vacío (job aún no elegido).
05-data-model.md
05 — Modelo de datos — PIÑÓN
1. Visión general
Dominio L2 de ganchos de taller + configurador de arreglo + encargo autenticable:
| Entidad | Tabla SQL | Propósito |
|---|---|---|
| User | users | Identidad de oficio (rol MECANICO) |
| Session | sessions | Sesión JWT / token persistido |
| Bike | bicis | Cuadro en gancho (código PIN-XXXX, modelo, color, job, estado, cover) |
| Request | requests | Encargo anónimo de cuenta sobre una bici (nombre, teléfono) |
Base: PostgreSQL (Neon project dedicado PIÑÓN · DATABASE_URL) · IDs: serial + texto estable (PIN-2701).
[DECISIÓN] ensureSchema es válido si el contrato de tablas se cumple; el brief de stack no exige Prisma.
Contrato de producto: bicis + requests + JWT MECANICO.
No sesiones / pedidos / ejemplares / programas / nodes / altas / bookings.
2. Enums (aplicación; persistidos como TEXT + check)
Role
| Valor | Descripción |
|---|---|
MECANICO | Mecánica de la mesa; único rol autenticado v1 |
JobPart
| Valor | Label UI | Descripción |
|---|---|---|
RUEDA | Rueda | Pinchazo, radio, cubo |
FRENOS | Frenos | Zapatas, disco, líquido |
CADENA | Cadena | Cadena, piñón, tensado |
REVISION | Revisión | Pase general, no «lo que sea» |
[DECISIÓN] Un encargo lleva un job. Multi-pieza y «arréglame todo» quedan fuera (H2).
BiciStatus
| Valor | Descripción |
|---|---|
ESPERA | Colgada, aún no se trabaja |
EN_TALLER | En el gancho de trabajo |
LISTA | Se puede recoger |
ENTREGADA | Ya no cuelga; fuera de la mesa v1 |
Un POST de encargo siempre crea la bici en ESPERA. [DECISIÓN]
Nuria no hace PATCH de estado en v1: la mesa es lectura de ganchos. [DECISIÓN]
3. Diagrama ER (texto)
users
id, email, password_hash, name, role(MECANICO)
created_at
1 ──< sessions
sessions
id, user_id → users
expires_at, revoked_at
created_at
bicis
id
code (unique, PIN-XXXX)
model, color
job (RUEDA|FRENOS|CADENA|REVISION)
status (ESPERA|EN_TALLER|LISTA|ENTREGADA)
cover
sort_order
created_at, updated_at
1 ──< requests
requests
id
bici_id → bicis
code (denorm PIN-XXXX)
name
phone
created_at
v1: una sola MECÁNICO opera sobre el conjunto global.
No hay FK de vecino-usuario: el vecino no se loguea.
requests.namees el nombre de mostrador (oral), no una cuenta.
requests.phonees el recado para avisar que está LISTA; no se pinta en el bento público.
4. Tablas
users
| Columna | Tipo | Notas |
|---|---|---|
| id | BIGSERIAL PK | |
| TEXT UNIQUE | nuria@pinon.taller | |
| password_hash | TEXT | bcrypt 12 · seed $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m |
| name | TEXT | Nuria Vega |
| role | TEXT | MECANICO |
| created_at | TIMESTAMPTZ |
sessions
| Columna | Tipo | Notas |
|---|---|---|
| id | UUID PK | sid del JWT |
| user_id | BIGINT FK | |
| expires_at | TIMESTAMPTZ | |
| revoked_at | TIMESTAMPTZ | logout |
| created_at | TIMESTAMPTZ |
bicis
| Columna | Tipo | Notas |
|---|---|---|
| id | BIGSERIAL PK | |
| code | TEXT UNIQUE | PIN-2701 |
| model | TEXT | Orbea urbana · BH paseo · Classic fold · Trek niño · o «bici» si el POST no trae modelo |
| color | TEXT | verde / crema / negra / azul / el del form |
| job | TEXT | RUEDA | FRENOS | CADENA | REVISION |
| status | TEXT | ESPERA | EN_TALLER | LISTA | ENTREGADA |
| cover | TEXT | /assets/bicis/orbea.jpg (seed); POST nuevo puede ir sin cover |
| sort_order | INTEGER | 1 = primer tile del bento |
| created_at / updated_at | TIMESTAMPTZ |
requests
| Columna | Tipo | Notas |
|---|---|---|
| id | BIGSERIAL PK | |
| bici_id | BIGINT FK | |
| code | TEXT | Denorm PIN-2701 para mesa sin join extra |
| name | TEXT | Nombre de mostrador (Pablo Mora) |
| phone | TEXT | Teléfono de recado |
| created_at | TIMESTAMPTZ |
Sin email, sin DNI, sin pago, sin GPS. Dejar la bici ≠ comprar el taller. [DECISIÓN]
Índices: bicis(code), bicis(status), bicis(sort_order), users(email), requests(bici_id), requests(created_at DESC).
5. Seed
MECÁNICO
nuria@pinon.taller / password123 · Nuria Vega · MECANICO
Hash bcrypt fijo: $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m
Bicis
| code | model | color | job | status | cover |
|---|---|---|---|---|---|
| PIN-2701 | Orbea urbana | verde | FRENOS | EN_TALLER | /assets/bicis/orbea.jpg |
| PIN-2702 | BH paseo | crema | REVISION | LISTA | /assets/bicis/bh.jpg |
| PIN-2703 | Classic fold | negra | RUEDA | EN_TALLER | /assets/bicis/fold.jpg |
| PIN-2704 | Trek niño | azul | CADENA | ESPERA | /assets/bicis/trek.jpg |
Métricas derivadas del seed: en taller 2 · listas 1 · esperan 1. ENTREGADA = 0.
[SUPUESTO de taller] Modelos, colores y marcas son atrezzo. No es un taller oficial ni un acuerdo con Orbea / BH / Trek.
[DECISIÓN] sort_order 1…4 = PIN-2701…2704.
Requests seed
| code | name | phone |
|---|---|---|
| PIN-2701 | Elena Ortiz | 612440271 |
| PIN-2702 | Luis Castro | 625118903 |
| PIN-2703 | Marta Gil | 633772014 |
| PIN-2704 | Iván Soto | 647331890 |
El POST de smoke crea el de Pablo Mora sobre un código nuevo (PIN-2705).
El seed idempotente restaura las 4 bicis de catálogo (estados y jobs) para que el demo sea repetible. [DECISIÓN]
Re-seed no borra PIN-2705+ salvo flag explícito de demo. [DECISIÓN]
6. JSON (camelCase)
API: sortOrder, createdAt, requestCount, enTaller, listas, esperan, cover, status, model, color, job, code, name, phone.
SQL: sort_order, created_at, request_count derivado.
GET /api/bicis
{
"metrics": { "enTaller": 2, "listas": 1, "esperan": 1 },
"bicis": [
{
"code": "PIN-2701",
"model": "Orbea urbana",
"color": "verde",
"job": "FRENOS",
"status": "EN_TALLER",
"cover": "/assets/bicis/orbea.jpg",
"sortOrder": 1
}
]
}
Lista pública: no incluye name ni phone de requests (evita enumerar vecinos). [DECISIÓN]
Métricas no cuentan ENTREGADA. [DECISIÓN]
GET /api/bicis/:code
Mismo shape de item; 404 si no existe. El success puede usarlo para pintar modelo/color/job.
POST /api/encargos
Request:
{ "name": "Pablo Mora", "phone": "600123123", "color": "verde", "job": "FRENOS", "model": "urbana" }
model opcional. name obligatorio, trim, min 2. phone obligatorio, dígitos ≥ 9. color obligatorio, trim, min 3. job obligatorio, enum. [DECISIÓN]
Response 201:
{
"code": "PIN-2705",
"color": "verde",
"job": "FRENOS",
"status": "ESPERA",
"dejada": true
}
Algoritmo: INSERT bici (status ESPERA, code siguiente) + INSERT request. Transacción única. [DECISIÓN]
GET /api/mesa (JWT)
{
"metrics": { "enTaller": 2, "listas": 1, "esperan": 1 },
"ganchos": {
"ESPERA": [ /* bicis */ ],
"EN_TALLER": [ /* bicis */ ],
"LISTA": [ /* bicis */ ]
},
"requests": [
{
"id": 1,
"code": "PIN-2701",
"name": "Elena Ortiz",
"phone": "612440271",
"job": "FRENOS",
"status": "EN_TALLER",
"createdAt": "2026-08-27T09:12:00.000Z"
}
]
}
7. Reglas de integridad
| Regla | Detalle |
|---|---|
| Unicidad de código | bicis.code UNIQUE |
| Job enum | Si job ∉ {RUEDA,FRENOS,CADENA,REVISION} → 400 |
| Encargo siempre ESPERA | POST no escribe EN_TALLER / LISTA |
| Sin user en request | No FK a users desde requests |
| Mesa privada | GET /api/mesa exige JWT role MECANICO |
| Bento público | GET /api/bicis sin auth |
| Teléfono no público | GET /api/bicis sin phone ni name |
| ENTREGADA oculta en mesa | ganchos solo ESPERA / EN_TALLER / LISTA |
8. Fuera del modelo v1
| Concepto | Por qué fuera |
|---|---|
| Precio / pago / SKU / talla | Dejar ≠ comprar |
| Email del vecino | Minimización; S2. El recado es el teléfono |
| GPS / lat-lng / ruta | S4 · L3 |
Tabla sesiones / pedidos | Leftover BOBINA |
Tabla ejemplares | Leftover LOMO |
| PATCH status | Mesa de lectura; no kanban |
| Multi-tenant nave | L2 compacto |
9. Naming vs leftover
| Prohibido (leftover) | Contrato PIÑÓN |
|---|---|
sesiones / pedidos | bicis / requests |
| PROGRAMADOR | MECANICO |
bobina-api | pinon-api |
| BOB-XXXX | PIN-XXXX |
| ABIERTA / COMPLETA | ESPERA / EN_TALLER / LISTA / ENTREGADA |
ejemplares / BIBLIO | bicis / MECANICO |
| puerto 3026 | 3027 |
06-tech-stack.md
06 — Stack técnico — PIÑÓN
1. Resumen
| Capa | Elección | Notas |
|---|---|---|
| Frontend | Angular (standalone) + Tailwind | Puerto 4200 |
| Backend | NestJS | Puerto 3027 · prefijo /api |
| DB | Neon PostgreSQL | Project dedicado PIÑÓN · DATABASE_URL |
| Auth | JWT Bearer | Rol MECANICO |
| Package | pnpm | Apps independientes (pnpm --filter) |
| Diseño | Paper | File 01M110K5JHDQ899C360KC4D0WD |
| Repo | /Users/cristian/orca/pinon-app | GH Criscode2022/pinon-app |
[COMPROBADO] Angular + NestJS + Neon + Tailwind, puerto API 3027, Paper file ID y path de app salen del encargo.
2. Por qué este stack
| Decisión | Razón | Alternativa descartada |
|---|---|---|
| Angular standalone | Coherencia serie ALS-2 daily | Next/React (rompería espejo de cases) |
| NestJS | Mismo contrato API que BOBINA/LOMO | Express suelto sin módulos |
| Neon | Postgres managed; project dedicado | SQLite local (no portfolio cloud) |
| Tailwind | Tokens industrial rápidos | CSS modules sin design tokens |
| JWT | Mesa cerrada; bento abierto | Session cookie-only sin Bearer documentado |
| pnpm filter | Monorepo ligero sin npm workspaces | Turborepo pesado para L2 |
3. Puertos y health
| Servicio | Puerto | Health |
|---|---|---|
| API | 3027 | GET /api/health → { ok: true, service: "pinon-api" } |
| Web | 4200 | Angular dev server |
Leftover bobina-api / puerto 3026 / lomo-api no son el producto. [DECISIÓN]
4. Estructura de repo (contrato)
pinon-app/
apps/
api/ NestJS · PORT=3027
web/ Angular · 4200
package.json pnpm workspaces o filter
Proxy web → API en dev (/api → http://localhost:3027). [DECISIÓN]
5. Variables de entorno (API)
| Variable | Uso |
|---|---|
DATABASE_URL | Neon connection string (project PIÑÓN) |
JWT_SECRET | Firma HS256 |
PORT | 3027 |
NODE_ENV | development / production |
No commitear secretos. .env local; ejemplo en .env.example sin credenciales reales. [DECISIÓN]
6. Auth
| Pieza | Detalle |
|---|---|
| Login | POST /api/auth/login { email, password } |
| Hash | bcrypt 12 · seed fijo del encargo |
| Token | JWT · claims sub, email, role: MECANICO |
| Guard | Bearer en GET /api/mesa |
| Público | health, bicis, bicis/:code, POST encargos, login |
| Storage web | localStorage o memory + interceptor; logout limpia |
[COMPROBADO] Credenciales demo: nuria@pinon.taller / password123.
7. Endpoints (contrato)
| Método | Ruta | Auth | Respuesta clave |
|---|---|---|---|
| GET | /api/health | No | pinon-api |
| GET | /api/bicis | No | metrics + array 4 |
| GET | /api/bicis/:code | No | item |
| POST | /api/encargos | No | 201 / 400 |
| POST | /api/auth/login | No | { accessToken } |
| GET | /api/mesa | JWT | ganchos + requests |
CORS: origen http://localhost:4200 en dev. [DECISIÓN]
8. Frontend — rutas y componentes
| Ruta | Componente | Guard |
|---|---|---|
/ | TallerPage | — |
/encargo | EncargoPage | — |
/ok/:code | OkPage | — |
/login | LoginPage | — |
/mesa | MesaPage | authGuard MECANICO |
Chrome: TopNavComponent (S-TOP). Tokens Tailwind: ground, cream, card, mark, mute, chrome.
9. Assets
| Origen case | Destino app |
|---|---|
2026-08-27-pinon/assets/hero.jpg | Tile Deriva / cover |
assets/bicis/*.jpg | apps/web/public/assets/bicis/ o equivalente |
Covers en DB como paths /assets/bicis/orbea.jpg etc. [DECISIÓN]
10. Calidad y toolchains
| Herramienta | Uso v1 |
|---|---|
| TypeScript | Strict en api y web |
| ESLint / Prettier | Serie daily |
| Vitest / Jest | Smoke API del slice |
| Playwright | Smoke S01–S12 del plan QA (doc 13) |
11. Anti-stack (no introducir)
| Tecnología | Por qué no |
|---|---|
| Prisma obligatorio | Brief no lo exige; ensureSchema + pg válido |
| Stripe / pago | Dejar ≠ comprar |
| Firebase Auth | JWT propio MECANICO |
| GraphQL | REST L2 |
| Socket.io / chat | ≠ PREGÓN |
| Mapbox / GPS | ≠ TROCHA · L3 |
| Player video | ≠ BOBINA / Filmin |
| OPAC / Absys libs | ≠ LOMO |
12. Criterios de aceptación técnicos
GET /api/health→service: "pinon-api".- Seed idempotente: 1 MECÁNICO + 4 bicis + 4 requests.
- POST encargo crea bici ESPERA + request y devuelve
PIN-XXXX. - GET mesa sin token → 401.
- Web en 4200 consume API 3027 sin mixed-content local.
- 0 referencias de producto a
sesiones, PROGRAMADOR,bobina-apien runtime.
[COMPROBADO] Contrato alineado a docs 01, 05 y README.
07-creative-direction.md
07 — Dirección creativa — PIÑÓN
1. Concepto
PIÑÓN es una nave de esmalte y hormigón: se entra a un tile de taller a sangre con tres números y cuatro ganchos, y se sale habiendo dejado una bici, no una landing de «tu bike shop». El ground es grafito. El naranja de reflector puntúa, poco. El cromo marca meta, poco.
Mood elegido: industrial.
Primer instinto descartado: nocturnal / fixie neón (tienda Rapha). Un taller de Legazpi se lee con esmalte, hormigón y naranja de reflector, no con LED de fixie.
[COMPROBADO] Mood, ground y paleta salen de docs/00-day-brief.md.
2. Territorio visual
| Eje | Sí | No |
|---|---|---|
| Superficie | Grafito #2C3033, cream #F3F1EC, card #1A1C1B, mark #E24A17 | Velvet BOBINA, caliza LOMO, cartel ONDA, hielo RAMAL |
| Tipo | Spectral + Sora | Cormorant+Manrope (BOBINA), Source Serif+Outfit (LOMO), Instrument Serif |
| Foto | Nave, gancho, esmalte de cuadro, barrio Arganzuela | LED de fixie, lineal Decathlon, stock Rapha, GPS de furgoneta |
| Grid | Deriva: tile nave ≥40 % 16/10 + 3 datos + 4 bicis | Hero 2-col + 3 cards (AP-12) · feed (BOBINA) · mesa de datos (LOMO) |
| Acento | Mark en CTA/foco/slot activo; cromo en meta | Brass de sala, cinta amarilla ONDA, amatista MATIZ |
| Chrome | S-TOP Taller · Encargo · Mesa | Dock cineclub, comando archivo, rail, bottom tabs |
3. Paleta
| Token | Hex | Rol |
|---|---|---|
| Ground / G-GRAPHITE | #2C3033 | Suelo de nave y esmalte de cuadro. Fondo de página. |
| Cream | #F3F1EC | Texto primario, ficha legible sobre grafito. |
| Card | #1A1C1B | Gancho / tarjeta de bici. Superficie elevada. |
| Mark | #E24A17 | Naranja de reflector: CTA Dejar, foco, wordmark. Poco. |
| Mute | #8B8E8A | Meta, labels, job secundario, idle S-TOP |
| Chrome | #C5C8C4 | Cromo: filetes, idle fino. Poco. No pinta el header. |
Jerarquía de color: el grafito carga; el mark puntúa; el cromo filetea. Si el mark pinta fondos enteros, deja de ser reflector y se vuelve «brand naranja Decathlon». El cromo no decora la cabecera: solo puntual (bordes, meta). El texto sobre grafito es cream; nunca mute como párrafo largo. Cream sobre grafito debe pasar contraste WCAG 2.2 AA. [DECISIÓN]
Candidatos de mood descartados: nocturnal/fixie neón (primer instinto taller cool), rusted, arid, botanical.
4. Tipografía
| Uso | Familia | Tamaños de referencia |
|---|---|---|
| Wordmark | Spectral 600 | 24–28 desktop · 22 mobile |
| Titular de taller / mesa | Spectral 600 | 32–44 |
| Código PIN-XXXX | Spectral 600 | 28–36 |
| Modelo de bici | Spectral 600 | 22–28 |
| Cuerpo / disclaimers | Sora 400 | 16–17 / 26–28 lh |
| UI, S-TOP, form, lista | Sora 400/500/600 | 14 / 16 |
| Meta (job, status, color) | Sora 500 | 12–13, tracking 0.08em, cream o mute |
Prohibido: Spectral por debajo de 18px (se rompe). Sora en el wordmark de taller (se vuelve SaaS). Mark como color de texto de párrafo largo (contraste).
Fuentes vetadas de la serie reciente cuando el brief fija otras: Cormorant / Manrope (BOBINA), Source Serif 4 / Outfit (LOMO), DM Serif Display / IBM Plex Sans, Newsreader / Figtree, Fraunces / Atkinson. Spectral + Sora sí entran: el brief los fija. [COMPROBADO]
5. Fotografía
| Asset | Debe | No debe |
|---|---|---|
| hero.jpg | Nave de taller: hormigón, ganchos, luz de industrial, barrio | Lineal Decathlon, LED Rapha, stock Unsplash de fixie neón |
| orbea.jpg | Orbea urbana verde; esmalte, barrio | Póster de catálogo 2026 con precio |
| bh.jpg | BH paseo crema; LISTA se lee en UI | Banner de gran superficie |
| fold.jpg | Classic fold negra; gancho, rueda | Thumbnail de e-commerce |
| trek.jpg | Trek niño azul; ESPERA se lee en UI | Foto de club / cita fitness |
Alt: modelo + color, no «imagen1». Ver doc 09.
[COMPROBADO] Los cuatro covers y el hero existen en assets/.
6. Registro R-HY
Híbrido: identidad de oficio clásica (S-TOP de taller, wordmark Spectral, ganchos) + bento/configurador (H-BENTO + F-CMP). No es un dashboard de seguros. No es un kiosk de horas. No es una mesa de datos de archivo. No es neón de fixie.
La innovación está en H-BENTO Deriva + S-TOP + F-CMP, no en un look «bike LED». [DECISIÓN]
7. Anti-moods
| Mood | Por qué no |
|---|---|
| Neón / nocturnal fixie | Primer instinto; es Rapha / tienda cool |
| Candlelit / velvet | Fue BOBINA |
| Mineral / caliza | Fue LOMO |
| Signage / cinta amarilla | Fue ONDA |
| Ice institucional | Fue RAMAL |
| Chapel amatista | Fue MATIZ |
| Vehicle dashboard | Fue TEMPLE / TROCHA |
| Highlighter fog | Fue PREGÓN |
8. Densidad (AP-21)
En el recorte Deriva: eslogan + tile de nave dominante + 3 datos (en taller / listas / esperan) + 4 tiles con modelo, color, job y estado visibles sin hover. Headline huérfano + foto = card hueca. [COMPROBADO] CRON §5.8 / D-P1-09 foto-led.
Tile de nave ≥40 % del recorte 16/10. Los 3 datos y las 4 bicis no tapan el oficio de la foto: legibles, no sticker. [DECISIÓN]
9. Motion
| Gesto | Tratamiento |
|---|---|
| Entrada bento | Fade corto 120–160ms; tile estático (no Ken Burns agresivo) |
| Hover tile desktop | Ring mark 2px; sin lift excesivo |
| S-TOP activo | Mark en label; idle mute |
| Reduced motion | 0ms; tile sin parallax |
10. Voice visual ↔ copy
El mood industrial refuerza el microcopy: gancho de nave, no lineal. Si la UI parece Decathlon (precio, talla, naranja de marca a pantalla completa) o Rapha (neón, kit), el copy irrenunciable pierde fuerza. [DECISIÓN]
08-design-system.md
08 — Sistema de diseño — PIÑÓN
1. Tokens
| Token | Valor | Uso |
|---|---|---|
--ground | #2C3033 | Fondo de página (grafito de nave) |
--cream | #F3F1EC | Texto primario, títulos |
--card | #1A1C1B | Tarjeta de bici, form, mesa |
--mark | #E24A17 | CTA, foco, S-TOP activo |
--mute | #8B8E8A | Meta, idle |
--chrome | #C5C8C4 | Filetes, cromo puntual |
--font-display | Spectral | Titulares |
--font-sans | Sora | UI |
--target | 44×44 min | Toques |
Tailwind: bg-ground, text-cream, bg-card, bg-mark, text-mute, text-chrome, font-display.
La tarjeta vive sobre --card; el ground es grafito alrededor. [DECISIÓN]
2. Contraste (obligatorio)
| Par | Uso | Nota |
|---|---|---|
Cream #F3F1EC sobre Grafito #2C3033 | Cuerpo y títulos | Debe pasar WCAG 2.2 AA |
Cream sobre Card #1A1C1B | Texto en tarjeta | Verificar AA |
| Mark sobre Grafito | Solo UI chrome / iconos, no párrafos largos | No sustituye cream |
| Mute sobre Grafito | Meta corta; no cuerpo | Evitar párrafos mute |
| Chrome sobre Grafito | Filete / meta corta | No cuerpo |
[DECISIÓN] Mark nunca como color de párrafo. Mute nunca como único color de disclaimer largo.
3. Escala de tipo
| Rol | Size / leading |
|---|---|
| Display taller | clamp(2.2rem, 5vw, 3.6rem) / 0.95 |
| H1 mesa / success | 2.5rem / 1 |
| H2 modelo | 28px / 32px |
| Cuerpo | 16–17 / 26 |
| Meta | 12–13 / 16, tracking 0.08em |
| S-TOP | 12–14 / 16, Sora 500 |
4. Componentes
Tile de bici (bento)
Cover recorte + modelo Spectral · color · job · status. Toda la tarjeta es el hit de lectura (no abre ficha pública). Orden por sort_order.
Tile Deriva (UI-01)
Imagen de nave a sangre ≥40 % del frame 16/10; gradient grafito→transparente para legibilidad del bento; wordmark + eslogan + 3 datos (en taller / listas / esperan).
Dato (métrica de gancho)
Número cream grande + label mute («en taller», «listas», «esperan»). Tres en fila desktop; wrap en 390. No es un sparkline ni una tabla H-DATA.
Configurador (UI-02)
Cuatro opciones exclusivas: Rueda · Frenos · Cadena · Revisión. Opción activa: ring mark + aria-checked. CTA Continuar (paso 2) disabled sin selección.
Form dejar bici (UI-03)
Nombre, teléfono, color del cuadro, job en solo lectura, disclaimer, submit mark.
Success (UI-04)
Código Spectral enorme + bloque card con job y color + 4 oposiciones en cream/mute.
Gancho de mesa MECÁNICO (UI-06)
Grupos ESPERA / EN_TALLER / LISTA. Fila: código · modelo · color · job · status. Encargos debajo: name · phone · code · hora. Sin acciones PATCH en v1.
Login (UI-05)
Wordmark + dos inputs + CTA mark. Ayuda mute con demo.
Top nav (S-TOP)
Tres slots: Taller · Encargo · Mesa. Activo: mark. Idle: mute. Fondo ground. Targets ≥44px.
Skeleton (UI-09)
animate-pulse bg-card. aria-busy.
Error (UI-08)
Titular display + cuerpo cream/mute + Reintentar mark.
Empty (UI-07)
Titular Spectral + mute. Sin CTA de Decathlon ni de cita.
Sello ESPERA / EN_TALLER / LISTA
Texto «Espera» / «En taller» / «Lista» + mark o mute. Nunca solo el color. Poco: un sello por tile, no un header naranja.
5. Layouts
| Superficie | Grid |
|---|---|
| Taller 1440 | Tile nave full-bleed 16/10; 3 datos en fila; 4 tiles 2×2; S-TOP |
| Taller 390 | Tile + 3 datos wrap + stack de 4; S-TOP fijo superior |
| Encargo / Ok / login | Columna max-w-lg |
| Mesa MECÁNICO | Grupos + encargos; stacked < lg |
Max page 1440px. Padding 20 / 40 / 48.
6. Estados de control
| Estado | Tratamiento |
|---|---|
| Default | Card + cream |
| Hover | Ring mark 2px |
| Focus visible | Outline mark 2px offset 2 |
| Active / pressed | Mark fill breve |
| Disabled | Opacity 0.45 · no hit · aria-disabled |
| Pending | disabled + aria-busy |
| Error | Borde mark + mensaje |
| Job seleccionado | Ring mark + check visible en texto |
7. Iconografía
S-TOP: pictogramas simples (nave / llave / mesa). Stroke 1.5–2px. No icon packs «carrito» ni «bici de share». [DECISIÓN]
8. Elevación y bordes
| Superficie | Tratamiento |
|---|---|
| Card sobre grafito | Sin sombra dura; borde 1px chrome/20 o mute/20 |
| S-TOP | Barra ground; filete chrome 1px inferior; no material neón |
| Modal (si hubiera) | No en v1 Must |
9. Mapa a Paper UI
| UI | Componentes clave |
|---|---|
| UI-01 / 11 | Tile nave + 3 datos + 4 bicis + S-TOP |
| UI-02 | Configurador 4 opciones |
| UI-03 | Form dejar bici |
| UI-04 | Success |
| UI-05 | Login |
| UI-06 | Mesa ganchos |
| UI-07 | Empty |
| UI-08 | Error |
| UI-09 | Loading |
| UI-10 | Tokens |
| UI-12 | Encargo 390 |
[COMPROBADO] Inventario en 00-paper-reference.md.
09-content-guide.md
09 — Guía de contenido — PIÑÓN
1. Voz
PIÑÓN habla como taller de nave, no como lineal ni como club de fitness.
| Eje | Sí | No |
|---|---|---|
| Tono | Seco, breve, de barrio | Corporativo Decathlon, hype de bici nueva |
| Persona | «Dejamos la bici» / tuteo de mostrador | «Adquiere tu cuadro» / «reserva tu clase» |
| Ritmo | Frases cortas. Una idea por línea en disclaimers | Párrafos legales de gran superficie |
| Humor | Seco, poco | Memes, jerga de fixie |
[DECISIÓN] Tuteo en UI. Nuria en mesa puede verse en usted solo en docs, no en labels.
2. Microcopy irrenunciable
Presente en taller (pie o banner), encargo, success y pie de mesa:
| Oposición | Copy canónico |
|---|---|
| Dejar vs comprar | Dejar la bici ≠ comprar el taller. |
| Encargo vs cita | Encargo ≠ cita de fitness. |
| Recoger vs alquilar | Recoger ≠ alquilar. |
| Barrio vs gran superficie | PIÑÓN no es Decathlon. |
No se parafrasean hasta diluirlas. Pueden acortarse en UI estrecha manteniendo ≠. [DECISIÓN]
3. Glosario UI
| Concepto | Label canónico | Evitar |
|---|---|---|
| Home | Taller | Inicio, Cartelera, Hoy, Galería, Catálogo |
| Item | Bici / Gancho | SKU, unidad, sesión, ejemplar |
| Flujo | Encargo | Cita, reserva, pedido de tienda |
| CTA paso 1 | Continuar | Añadir al carrito, Reservar |
| CTA paso 2 | Dejar la bici | Comprar, Alquilar, Reservar clase |
| Success | Dejada | Confirmación de compra, Ticket listo |
| Staff | Mesa | Backoffice, Admin, Kanban |
| Estado | Espera / En taller / Lista | Disponible / Agotado (retail), En ruta (TROCHA) |
| Persona auth | Mecánica | Programadora, Coach, Admin |
| Arreglo | Rueda / Frenos / Cadena / Revisión | Pack, SKU, «lo que sea» |
4. Pantalla a pantalla
Taller /
| Slot | Copy |
|---|---|
| Wordmark | PIÑÓN |
| Eslogan | El gancho, no el lineal. |
| Dato 1 | {n} en taller |
| Dato 2 | {n} listas |
| Dato 3 | {n} esperan |
| CTA | Encargo |
| Empty | Aún no hay ganchos. |
| Error | La red no responde. · Reintentar |
Encargo /encargo paso 1 (UI-02)
| Slot | Copy |
|---|---|
| Título | Qué se arregla |
| Opciones | Rueda · Frenos · Cadena · Revisión |
| CTA | Continuar |
| Disabled | Elige qué se arregla. |
| Aviso | Dejar la bici ≠ comprar el taller. |
Encargo /encargo paso 2 (UI-03)
| Slot | Copy |
|---|---|
| Título | Dejar la bici |
| Label nombre | Tu nombre |
| Label teléfono | Teléfono |
| Label color | Color del cuadro |
| Job (solo lectura) | Arreglo: {job} |
| Submit | Dejar la bici |
| Disclaimer | No es una compra. No hay cita. Recoger ≠ alquilar. |
| Error nombre | Escribe un nombre. |
| Error teléfono | Escribe un teléfono. |
| Error color | Di el color del cuadro. |
Success /ok/:code
| Slot | Copy |
|---|---|
| Titular | Dejada. |
| Código | {code} |
| Cuerpo | Encargo de {job} · cuadro {color}. En espera en el gancho. |
| Oposiciones | Las cuatro líneas irrenunciables |
| Volver | Volver al taller |
Login /login
| Slot | Copy |
|---|---|
| Título | Mesa |
| Ayuda | Solo mecánica. |
| Demo | nuria@pinon.taller |
| Error | Email o contraseña no valen. |
Mesa /mesa
| Slot | Copy |
|---|---|
| Título | Mesa |
| Grupos | Espera · En taller · Lista |
| Empty encargos | No hay encargos. |
| Salir | Salir |
| Pie | Dejar la bici ≠ comprar el taller. |
5. Alt text de imágenes
| Asset | Alt (modelo) |
|---|---|
| hero | Nave de taller de bicis, ganchos y hormigón, luz industrial |
| orbea | Orbea urbana verde en gancho |
| bh | BH paseo crema lista para recoger |
| fold | Classic fold negra, arreglo de rueda |
| trek | Trek de niño azul en espera |
Evitar «imagen1», «bike.jpg», copy de catálogo con precio. [DECISIÓN]
6. Modelos seed (atrezzo)
Orbea / BH / Classic / Trek son catálogo demo. En UI no se afirma «distribuidor oficial». Los blurbs pueden recordar dejar ≠ comprar. [SUPUESTO de taller]
7. Tono de error
| Caso | Copy |
|---|---|
| Red | La red no responde. |
| 404 | Ese encargo no está. |
| 400 job | Elige qué se arregla. |
| 401 mesa | Entra como mecánica. |
Sin culpa al usuario. Sin jerga HTTP en UI.
8. Anti-copy (vetado)
| Vetado | Por qué |
|---|---|
| Comprar / carrito / talla / SKU / precio | Decathlon |
| Reservar clase / plaza / coach | VOLTA / fitness |
| Alquilar / desbloquear / minutos | Bike-share |
| En ruta / GPS / parada | TROCHA |
| Pedir butaca / sesión / taquilla | BOBINA |
| Pedir mesa / lomo / signatura | LOMO |
| Recibido / En curso / Cerrado | PREGÓN kanban |
| «El 80% de vecinos…» | Estadística inventada |
| Arréglame lo que sea | Rompe H2 |
9. Criterios de aceptación de contenido
- Las cuatro oposiciones aparecen al menos en success y en una superficie de taller o encargo.
- Ningún CTA dice Comprar / Alquilar / Reservar clase.
- LISTA se etiqueta «Lista», no «Disponible» retail.
- Códigos se muestran como
PIN-XXXXen versales. - Docs y UI no inventan KPIs numéricos de Legazpi como hecho.
10-accessibility.md
10 — Accesibilidad — PIÑÓN
1. Objetivo
Cumplir WCAG 2.2 AA en el vertical slice L2. Ground oscuro (grafito): el par cream sobre grafito es el contrato de legibilidad. Amparo Díaz (71) es persona de diseño que fuerza contraste, tamaño y targets; no tiene login. [COMPROBADO] requisito del encargo · [DECISIÓN] persona Amparo en docs.
2. Contraste
| Par | Ratio objetivo | Uso |
|---|---|---|
#F3F1EC sobre #2C3033 | ≥ 4.5:1 (texto) / ≥ 3:1 (UI grande) | Cuerpo, títulos |
#F3F1EC sobre #1A1C1B | ≥ 4.5:1 | Texto en card |
#E24A17 sobre #2C3033 | ≥ 3:1 para UI no texto | Foco, iconos; no párrafos |
#8B8E8A sobre #2C3033 | Verificar; limitar a meta corta | Labels |
#C5C8C4 sobre #2C3033 | Meta / filete; no cuerpo | Cromo |
[DECISIÓN] Si mute falla AA en párrafo, se asciende a cream. Mark no escribe disclaimers.
Verificación: contraste en tokens al build de UI; no se afirman ratios inventados sin medir en implementación. [HIPÓTESIS operativa] cream/grafito pasa; se valida en QA (doc 13).
3. Tipografía y lectura
| Regla | Aplicación |
|---|---|
| Cuerpo ≥ 16px | Sora 16–17 |
| Display no < 18px | Spectral solo en titulares |
| Line-height ≥ 1.5 en cuerpo | 26–28 lh |
| Zoom 200% | Layout no rompe S-TOP ni form |
| Sin justificado forzado | Alineación start |
4. Targets y pointer
| Elemento | Mínimo |
|---|---|
| Slots S-TOP | 44×44 CSS px |
| CTA Dejar la bici / Continuar | ≥ 44 px alto |
| Opción de arreglo | Hit area completa ≥ 44 alto |
| Tile de bici | Lectura; no es el único camino al encargo |
| Inputs | ≥ 44 alto |
Spacing entre slots del top ≥ 8px. [DECISIÓN]
5. Teclado y foco
| Superficie | Comportamiento |
|---|---|
| Taller | Tab por S-TOP → Encargo |
| Configurador | Tab por 4 opciones → Continuar |
| Form dejar | Nombre → teléfono → color → submit |
| Login | Email → password → entrar |
| Mesa | Grupos legibles; salir alcanzable |
| Focus visible | Outline mark 2px offset 2 |
| Skip link | «Saltar al taller» en / si el tile decorativo es largo |
Sin keyboard traps. Esc no es obligatorio en v1 (sin modales Must).
Opciones de job: radiogroup + radio o botones con aria-pressed. [DECISIÓN]
6. Semántica y nombres
| UI | Rol / nombre |
|---|---|
| S-TOP | navigation · aria-label «PIÑÓN» |
| Slot activo | aria-current="page" |
| 3 datos | list o group «Ganchos» · cada dato con texto «{n} en taller» no solo el número |
| Tiles bici | article «{model} {color}» + status en texto |
| Job | radiogroup «Qué se arregla» |
| Form | label asociado; errores con aria-live="polite" |
| Loading | aria-busy="true" en región |
| Success código | Texto real, no solo imagen |
7. Imágenes y tile
| Caso | Tratamiento |
|---|---|
| Tile Deriva | alt descriptivo corto o alt="" si puro decorativo y el bento encima lleva el oficio |
| Covers bici | Alt «{model} {color}» |
| Iconos S-TOP | aria-hidden si hay label texto visible |
[DECISIÓN] Preferir tile con alt útil en cover UX; en producto, si el overlay ya nombra PIÑÓN y los ganchos, evitar alt redundante largo.
8. Motion
| Preferencia | Comportamiento |
|---|---|
prefers-reduced-motion: reduce | Transiciones 0ms; sin parallax del tile |
| Default | 120–160ms ease-out |
9. Estados y color
ESPERA / EN_TALLER / LISTA / error nunca se comunican solo con color: texto + sello. Mark refuerza, no sustituye. [DECISIÓN]
10. Auth y a11y
- Login solo MECÁNICO; Amparo no necesita cuenta para leer el taller ni dejar bici.
- Mensajes de error de login claros, sin enumerar si el email existe (seguridad + claridad).
/mesaredirige a login con foco en email.
11. Mobile 390
- S-TOP fijo no tapa el CTA final: padding-top del contenido ≥ altura top; en encargo, el submit queda por encima del teclado.
- Formularios:
autocompletename on; teltel; passwordcurrent-password. - Viewport meta; sin zoom bloqueado. [DECISIÓN]
- UI-11 bento y UI-12 encargo cubren el recorte 390. No carousel.
12. Criterios de aceptación a11y
- Cream sobre grafito usado en cuerpo; mute limitado a meta.
- Targets S-TOP y CTA ≥ 44×44.
- Focus visible mark en todos los interactivos.
- Status y métricas con texto, no solo color o número huérfano.
- Reduced motion respetado.
- Form con labels y errores anunciables.
- Ningún toast único sin pantalla como único success (hay
/ok/:code).
13. Fuera de v1 (L3, no deuda)
- Modo tipográfico «letra grande» persistente para Amparo.
- App nativa con VoiceOver de taller físico.
- ATAG de CMS (no hay CMS).
11-privacy-security.md
11 — Privacidad y seguridad — PIÑÓN
1. Principios
| Principio | Aplicación v1 |
|---|---|
| Minimización | Request = nombre + teléfono; sin email, DNI, GPS |
| Separación público / oficio | Bento y POST encargo públicos; mesa JWT |
| Sin cuenta de vecino | Pablo y Amparo no se registran |
| Transparencia de copy | Success dice que no es compra ni alquiler |
| Secretos fuera del repo | DATABASE_URL, JWT_SECRET en env |
[DECISIÓN] No se inventa un aviso legal largo de cadena de tiendas; hay disclaimer de producto y minimización real.
2. Datos tratados
| Dato | Dónde | Base operativa (modelo) | Retención v1 |
|---|---|---|---|
| Nombre de encargo | requests.name | Prestación del taller (apuntar quién deja) | Mientras el seed/demo viva; sin política de mercado afirmada |
| Teléfono | requests.phone | Recado cuando está LISTA | Igual |
| Color / job / modelo | bicis | Oficio del gancho | Igual |
| Email MECÁNICO | users.email | Cuenta de oficio | Cuenta demo |
| Password hash | users.password_hash | Auth | bcrypt 12 |
| JWT sid | sessions | Sesión de mesa | Expiración + revoke |
No se tratan: pago, tarjeta, geolocalización, ID de dispositivo publicitario, mensajes de chat, talla, IBAN.
[SUPUESTO] El taller demo opera en España; el slice no implementa un RGPD completo de empresa real.
3. Superficies públicas vs privadas
| Superficie | Público | Privado |
|---|---|---|
GET /api/bicis | Sí · sin nombres ni teléfonos | — |
GET /api/bicis/:code | Sí · sin teléfono | — |
| POST encargos | Sí · crea request | — |
GET /api/mesa | No · 401 | Sí · requests con name + phone |
| Bento UI | Sin listar quién dejó | — |
| Mesa UI | — | Lista encargos |
[DECISIÓN] Enumerar teléfonos en el bento rompería privacidad de nave; solo Nuria ve recados.
4. AuthN / AuthZ
| Control | Detalle |
|---|---|
| Password | bcrypt cost 12 · hash seed canónico del encargo |
| JWT | HS256 · secret env · role claim |
| Guard mesa | role === MECANICO |
| Login rate | No es deuda del L2; demo sin brute-force engine |
| Logout | Revoke session + clear client token |
| HTTPS | Obligatorio en deploy; localhost HTTP en dev |
Credenciales demo en docs: nuria@pinon.taller / password123. No reutilizar en producción real. [COMPROBADO] demo · [DECISIÓN] rotar fuera del case.
5. Amenazas y mitigaciones L2
| Amenaza | Mitigación |
|---|---|
| POST encargo spam | Job enum + validación teléfono; L3 rate-limit (no es hueco del slice) |
| Enumeración de teléfonos | No en API pública |
| JWT robado | Expiración corta + logout; HTTPS en prod |
| IDOR mesa | Guard JWT; sin IDs de request públicos |
| XSS | Angular escaping; no innerHTML de name/phone |
| SQLi | Parámetros prepared / query builder |
| Leftover ADMIN / PROGRAMADOR | Un solo rol MECANICO |
6. Contenido de teléfono y nombre
phone es recado, no tracking. Se muestra a Nuria en mesa. Formato: dígitos, min 9. [DECISIÓN]
No se pide dirección, salud ni datos de terceros sensibles en el form.
name es texto libre corto (min 2, max 80).
7. Cookies y tracking
v1 no incluye analytics de terceros ni banners de cookies de ads. North star es modelo (doc 12). [DECISIÓN]
Token JWT puede vivir en localStorage (XSS risk aceptado en demo) o memory; documentar en handoff.
8. Logs
| Qué sí | Qué no |
|---|---|
| Errores de API sin PII | Passwords, JWT completos |
| code de bici en logs de encargo | Teléfono completo en logs públicos |
9. Criterios de aceptación
- GET mesa sin Bearer → 401.
- GET bicis no incluye
nameniphone. - POST encargos no exige auth ni pago ni GPS.
- Password solo como hash bcrypt.
.envno versionado con secretos reales.- Copy de success no implica contrato de compra ni de alquiler.
10. Fuera de v1 (L3 / org real, no deuda)
DPO, ROPA formal, exportaciones ARCO automatizadas, SSO, 2FA, WAF, geolocalización. Roadmap L3 si el taller deja de ser demo (GPS, e-commerce).
12-analytics.md
12 — Analytics y métricas — PIÑÓN
1. Norte
| Tipo | Métrica | Definición |
|---|---|---|
| North Star | % de bicis LISTA recogidas sin un WhatsApp de «¿está lista?» | Oficio de gancho: el vecino ve el estado (o lo asume por el código) sin recado |
[COMPROBADO] North star alineada a H1 del day brief.
[DECISIÓN] En v1 es modelo: no hay instrumentación obligatoria ni dashboard. No se afirman porcentajes medidos inventados.
2. Por qué esta north star
| Alternativa descartada | Por qué no |
|---|---|
Pageviews de / | Vanidad; no mide gancho |
| Ingresos de lineal | Dejar ≠ comprar; no hay e-commerce |
| % de clases reservadas | Encargo ≠ cita · ≠ VOLTA |
| % de paradas GPS cerradas | ≠ TROCHA |
| % de noches con butaca antes de las 18:00 | Eso es BOBINA |
El WhatsApp de «¿está lista?» es el recado que el bento y la mesa pretenden absorber. [SUPUESTO] operativo de diseño, no dato de campo.
3. Métricas de soporte (modelo)
| Métrica | Definición | Hipótesis |
|---|---|---|
| Activación vecino | 1.er POST /api/encargos exitoso por visitante | H2 |
| Tasa taller → encargo | / → /encargo | H1 |
| Tasa encargo → POST | /encargo → 201 | H2 copy no frena |
| Mix de jobs | Conteo RUEDA / FRENOS / CADENA / REVISION | H2 |
| Integridad auth | 401 en mesa sin token | Seguridad |
| Salud | 5xx rate API | Ops |
4. Eventos (contrato si se instrumenta en un L3)
| Evento | Props | PII |
|---|---|---|
taller_view | metrics snapshot (conteos) | No |
encargo_job | job | No |
encargo_submit | job | No nombre, no teléfono |
encargo_success | code, job | No |
encargo_invalid | http:400 | No |
login_success | role | No |
mesa_view | — | No |
[DECISIÓN] Nunca enviar name ni phone a analytics.
Instrumentar eventos no es un hueco del L2: el slice cierra sin tracker. [DECISIÓN]
5. Cálculo north star (modelo)
listas = bicis con status LISTA en la ventana
listas_sin_whatsapp =
(no medible en v1: no hay canal WhatsApp en producto)
proxy de diseño = visitas a / o /mesa que cubren el estado
frente a recados paralelos (cualitativo)
[DECISIÓN] v1 no persiste un flag whatsapp_asked. El north star queda como modelo de oficio, no como SQL fingido.
Timezone: Europe/Madrid. [DECISIÓN]
6. Integridad de expectativa (cualitativa)
Señales a vigilar en demo / soporte (no KPIs inventados):
- «¿Compro la bici?»
- «¿Reservo una clase?»
- «¿Esto es un alquiler?»
- «¿Es Decathlon?»
- «¿Dónde está el GPS?»
Mitigación: microcopy irrenunciable (doc 09). [HIPÓTESIS H2]
7. Qué no medir en v1
| Vetado | Por qué |
|---|---|
| Heatmaps de terceros sin decisión | Privacidad |
| Funnel de pago | No hay pago |
| DAU de Decathlon | No hay lineal |
| Estadísticas de Legazpi inventadas | Ética de verdad |
| Tracking GPS | S4 · L3 |
8. Criterios de aceptación
- Docs y UI no muestran un % inventado como hecho.
- North star documentada y alineada a H1.
- Si hay eventos en un L3, sin PII de requests.
- Health y 401 mesa son checks de integridad, no vanidad.
9. Relación con seed
Seed tiene 2 EN_TALLER + 1 LISTA + 1 ESPERA. Un guión con POST sobre un encargo nuevo es el ejemplo narrativo de activación; no es un dato de mercado. [SUPUESTO de demo]
13-qa-test-plan.md
13 — Plan de QA — PIÑÓN
1. Alcance
Smoke y regresión del vertical slice L2: bento, configurador, dejar bici, success, login, mesa, empty/error/loading, mobile 390, contraste cream/grafito.
No incluye campo real de Legazpi ni load test de gran superficie.
2. Entornos
| Entorno | URL | Notas |
|---|---|---|
| API local | http://localhost:3027 | Neon dedicado PIÑÓN |
| Web local | http://localhost:4200 | Proxy /api |
| Credenciales | nuria@pinon.taller / password123 | Solo demo |
3. Smoke crítico (Must pasar)
| ID | Caso | Pasos | Esperado |
|---|---|---|---|
| S01 | Health | GET /api/health | ok · service: "pinon-api" |
| S02 | Bento | GET /api/bicis · abrir / | 4 bicis · 3 métricas · Deriva visible |
| S03 | Métricas seed | Leer datos | 2 en taller · 1 lista · 1 espera |
| S04 | Configurador | /encargo · sin job | Continuar disabled |
| S05 | Dejar | Frenos + Pablo + teléfono + color · submit | 201 · /ok/PIN-XXXX |
| S06 | Copy success | Leer /ok/:code | 4 oposiciones visibles |
| S07 | 400 | Forzar POST sin job | 400 · mensaje arreglo |
| S08 | Login | /login Nuria | JWT · /mesa |
| S09 | Mesa auth | GET /api/mesa con token | ganchos + requests |
| S10 | Mesa 401 | GET /api/mesa sin token | 401 |
| S11 | Mobile | / y /encargo @390 | S-TOP · 4 bicis · targets |
| S12 | Seed | Tras re-seed | 2 EN_TALLER · 1 LISTA · 1 ESPERA |
4. Regresión funcional
| ID | Área | Check |
|---|---|---|
| R01 | POST crea ESPERA | Nueva bici status ESPERA |
| R02 | Request ligado | Mesa muestra nombre + teléfono del POST |
| R03 | Nombre vacío | 400 · no navega a ok |
| R04 | Teléfono corto | 400 |
| R05 | Code inventado | /ok/PIN-9999 · 404 UI |
| R06 | Guard ruta | /mesa sin token → login ?next= |
| R07 | Logout | Token limpio · mesa 401 |
| R08 | S-TOP | Taller / Encargo / Mesa navegables |
| R09 | Público sin teléfonos | JSON bicis sin phone / name |
| R10 | Leftover | 0 bobina-api / sesiones / PROGRAMADOR en UI |
| R11 | Job enum | POST job: "LO_QUE_SEA" → 400 |
| R12 | ENTREGADA | No aparece en ganchos de mesa |
5. Accesibilidad (muestra)
| ID | Check |
|---|---|
| A01 | Cream sobre grafito en cuerpo (inspección / contraste) |
| A02 | Focus visible mark en tab order |
| A03 | S-TOP slots ≥ 44×44 |
| A04 | Status con texto, no solo color |
| A05 | prefers-reduced-motion sin parallax |
| A06 | Labels en form dejar y login |
| A07 | aria-busy en loading bento |
| A08 | Job como radiogroup / aria-pressed |
6. Contenido
| ID | Check |
|---|---|
| C01 | Ningún CTA «Comprar» / «Alquilar» / «Reservar clase» |
| C02 | Eslogan en taller |
| C03 | LISTA = «Lista» no «Disponible» retail |
| C04 | Códigos PIN-XXXX |
| C05 | Cuatro oposiciones en success |
7. Visual / Paper
| ID | Check |
|---|---|
| V01 | Tile nave a sangre + 3 datos + 4 bicis (no hero 2-col, no feed) |
| V02 | Mood industrial (no neón fixie) |
| V03 | Covers seed cargan (orbea/bh/fold/trek) |
| V04 | Mesa = ganchos por estado (no kanban de columnas) |
| V05 | S-TOP no dock |
8. API negativa
| Caso | HTTP |
|---|---|
| Login malo | 401 |
| Encargo sin nombre | 400 |
| Encargo sin job | 400 |
| Encargo job inválido | 400 |
| Encargo code 404 GET | 404 |
| Mesa sin auth | 401 |
9. Datos de prueba
| Actor | Dato |
|---|---|
| Vecino | Pablo Mora · 600123123 · color verde · job FRENOS |
| Bici happy seed | PIN-2702 LISTA |
| Bici espera seed | PIN-2704 |
| MECÁNICO | nuria@pinon.taller |
Tras smoke: re-seed para restaurar las 4 de catálogo. [DECISIÓN]
10. Criterio de salida
Smoke S01–S12 en verde. Sin P0 (health mal, encargo roto, mesa abierta sin auth, copy Decathlon ausente en success).
P1 visual puede quedar anotado; no reabre el alcance L2.
11. Fuera de alcance QA v1
Penetration test, auditoría RGPD formal, GPS, pasarela de pago, compatibilidad IE, métricas reales de north star instrumentadas. Eso es L3 u org real, no un agujero de este slice.
14-dev-handoff.md
14 — Handoff a desarrollo — PIÑÓN
1. Contrato vivo
| Artefacto | Path |
|---|---|
| Brief | docs/00-day-brief.md |
| Paper ref | docs/00-paper-reference.md |
| Producto | docs/01-project-definition.md |
| IA / rutas | docs/03-information-architecture.md |
| Flujos | docs/04-user-flows.md |
| Datos | docs/05-data-model.md |
| Stack | docs/06-tech-stack.md |
| DS / tokens | docs/08-design-system.md |
| Copy | docs/09-content-guide.md |
| Build | docs/20-implementation.md |
| App | /Users/cristian/orca/pinon-app |
| GH | Criscode2022/pinon-app |
| Paper | 01M110K5JHDQ899C360KC4D0WD |
| API | :3027 · pinon-api |
Si código y docs divergen, alinear ambos; no silenciar leftover BOBINA como producto. [DECISIÓN]
2. Definition of Done (DoD) L2
| # | Criterio |
|---|---|
| 1 | Rutas / /encargo /ok/:code /login /mesa |
| 2 | Home = Deriva H-BENTO (tile nave + 3 datos + 4 bicis), no H-FEED ni H-DATA ni hero 2-col |
| 3 | Chrome S-TOP Taller · Encargo · Mesa |
| 4 | F-CMP: configurar job y luego dejar bici en /encargo |
| 5 | POST encargo público; success con 4 oposiciones |
| 6 | JWT MECÁNICO; mesa 401 sin token |
| 7 | Seed 4 bicis · 2 EN_TALLER · 1 LISTA · 1 ESPERA |
| 8 | Health pinon-api · puerto 3027 |
| 9 | Tokens industrial + Spectral/Sora |
| 10 | Empty / error / loading |
| 11 | Mobile 390 usable (bento + encargo) |
| 12 | 0 dominio sesiones / PROGRAMADOR / bobina-api |
El DoD cubre todo el slice. No queda producto in-scope como «siguiente sprint». [DECISIÓN]
3. Mapa Paper → Angular
| UI | Ruta | Componente |
|---|---|---|
| UI-01 / 11 | / | TallerPage |
| UI-02 / 03 / 12 | /encargo | EncargoPage |
| UI-04 | /ok/:code | OkPage |
| UI-05 | /login | LoginPage |
| UI-06 | /mesa | MesaPage |
| UI-07 / 08 / 09 | estados | mismos components |
| UI-10 | theme | Tailwind |
4. API checklist
| Método | Ruta | Auth |
|---|---|---|
| GET | /api/health | No |
| GET | /api/bicis | No |
| GET | /api/bicis/:code | No |
| POST | /api/encargos | No |
| POST | /api/auth/login | No |
| GET | /api/mesa | JWT MECANICO |
Body encargo: { name: string, phone: string, color: string, job: JobPart, model?: string }.
INSERT bici ESPERA + request en transacción. [DECISIÓN] ver doc 05.
5. Seed y credenciales
| Item | Valor |
|---|---|
nuria@pinon.taller | |
| Password | password123 |
| Hash | $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m |
| Codes | PIN-2701…2704 |
| Covers | /assets/bicis/{orbea,bh,fold,trek}.jpg |
6. Anti-patrones de implementación
| No hacer | Hacer |
|---|---|
| Puerto 3026 / health bobina-api | 3027 / pinon-api |
| Tabla sesiones / pedidos | bicis / requests |
| Dock S-DOCK | S-TOP |
| Feed H-FEED | Bento Deriva |
| Kanban mesa | Ganchos por estado |
| Pago / Stripe / catálogo | POST nombre + teléfono + color + job |
| GPS / Mapbox | Fuera · L3 |
| Hero 2-col marketing | Deriva foto-led |
| Wizard 5 pasos | Dos pasos F-CMP |
7. Assets
Copiar desde case:
assets/bicis/orbea.jpgassets/bicis/bh.jpgassets/bicis/fold.jpgassets/bicis/trek.jpgassets/hero.jpg(tile Deriva / cover)
[COMPROBADO] existen en el case.
8. QA mínimo antes de merge
Ejecutar smoke S01–S12 (doc 13). Verificar copy irrenunciable en /ok/:code.
9. Open questions (no reabren L2)
| Pregunta | Default ya decidido |
|---|---|
¿Prisma o pg + ensureSchema? | ensureSchema válido |
| ¿localStorage vs memory token? | localStorage demo OK |
| ¿Teléfono maxlength? | 15 dígitos |
| ¿Cover del POST nuevo? | Vacío o placeholder; seed sí tiene foto |
| ¿PATCH status? | No en v1 |
10. Contacto de diseño
Paper file + docs 07–09. No reinventar neón fixie. Mood industrial. Ground #2C3033. Mark #E24A17.
15-roadmap.md
15 — Roadmap — PIÑÓN
1. Horizonte
| Fase | Nombre | Intención |
|---|---|---|
| L2 | Slice actual | Bento + configurador + dejar bici + mesa JWT · cerrado en esta iteración |
| L3 | Nice-to-have de otro producto | Solo GPS y e-commerce, y solo con brief nuevo |
[DECISIÓN] El L2 no deja producto ni código in-scope como «próximos pasos». Este roadmap no es un cajón de deuda. Empty, error, loading, mobile, auth, seed, copy y API están en el slice de hoy.
2. Hecho en L2 (Must · cerrado)
| Pieza | Estado |
|---|---|
| H-BENTO Deriva 4 bicis + 3 métricas | Must · cerrado |
| F-CMP configurador (rueda / frenos / cadena / revisión) | Must · cerrado |
| Dejar la bici sin cuenta | Must · cerrado |
| Success + 4 oposiciones | Must · cerrado |
| Login MECÁNICO | Must · cerrado |
| Mesa de ganchos ESPERA / EN_TALLER / LISTA | Must · cerrado |
| Empty / error / loading / 390 | Must · cerrado |
| Docs 00–20 + README + executive | Must · cerrado |
| Paper 12 UX + 12 UI (inventario) | Must (ref) · cerrado |
Contrato pinon-app · API :3027 · health pinon-api | Must · cerrado |
Nada de la tabla se reabre como backlog de «el código ya vendrá». El case L2 cierra en una iteración. [DECISIÓN]
3. L3 only (nice-to-have · otro brief)
| ID | Idea | Por qué L3 | Riesgo |
|---|---|---|---|
| L3-01 | GPS de la bici / aviso de llegada | Rompe S4; huele a TROCHA (la bici se deja, no se reparte) | Flota disfrazada |
| L3-02 | E-commerce de recambios o cuadros | Rompe «dejar ≠ comprar»; huele a Decathlon | Lineal el día 2 |
Estas dos ideas no completan PIÑÓN. Completarían otro producto. [DECISIÓN]
4. Anti-roadmap (no disfrazar)
| Pedido típico | Respuesta |
|---|---|
| «Pon un lineal / precio / talla» | No · Dejar la bici ≠ comprar el taller |
| «Pon GPS» | No en L2 · L3-01 con brief nuevo |
| «Pon cita / clase» | No · Encargo ≠ cita de fitness |
| «Pon alquiler» | No · Recoger ≠ alquilar |
| «Pon búsqueda tipo LOMO» | No · rompe terna H-BENTO |
| «Pon kanban» | No · ≠ PREGÓN |
| «Pon feed de cineclub» | No · N−1 ya fue BOBINA |
| «Empty / loading los dejamos para después» | No · están en el L2 de hoy |
| «El código es el próximo paso del case» | No · el contrato L2 está cerrado; no se lista como roadmap de producto |
5. Dependencias del slice cerrado
| Dependencia | Nota |
|---|---|
| Neon dedicado PIÑÓN | L2 (DATABASE_URL) |
Paper file 01M110K5JHDQ899C360KC4D0WD | Diseño; inventario en 00 |
pinon-app · GH Criscode2022/pinon-app | Contrato de build (doc 20) |
6. Criterios para abrir un L3
- Smoke L2 en verde (doc 13).
- Copy irrenunciable intacto.
- El brief L3 nombra GPS o e-commerce sin reabrir ganchos, F-CMP ni mesa.
- North star sigue siendo modelo o se instrumenta sin PII.
7. Cierre
L2 está completo en una iteración. El roadmap es un muro contra el lineal y el GPS, no una lista de lo que «faltó». [DECISIÓN]
16-interaction-specs.md
16 — Especificación de interacción — PIÑÓN
1. Convenciones
| Token | Valor |
|---|---|
| Duración corta | 120–160ms |
| Easing | ease-out |
| Reduced motion | 0ms |
| Target | ≥44×44 |
| Pending | control disabled + aria-busy |
Loading, empty y error viven con los gestos (UI-07 / UI-08 / UI-09). [DECISIÓN]
2. Home bento (UI-01) + mobile (UI-11) · H-BENTO Deriva
| Gesto | Resultado |
|---|---|
| Primera carga | Loading (UI-09): skeleton tile + 3 datos + 4 tiles card; aria-busy |
| 200 con 4 | Tile de nave a sangre + 3 datos + 4 bicis. Modelo, color, job, estado |
| 200 con 0 | UI-07 empty «Aún no hay ganchos.» |
| Error 5xx / red | UI-08 + Reintentar (repite GET bicis) |
| Tap Encargo (S-TOP o CTA) | /encargo paso 1 |
| Tap Mesa (S-TOP) | /login o /mesa si hay token |
| Hover tile desktop | Ring 2px mark. Sin lift excesivo |
AC: modelo, color, job y estado visibles sin hover. Tile nave ≥40 % del recorte 16/10 (AP-21 / D-P1-09). Tres datos con texto («2 en taller»), no solo cifra. Cero botones Comprar / Alquilar / Reservar clase.
El aviso «PIÑÓN no es Decathlon» es texto, no un CTA de tienda. [DECISIÓN]
390: mismas 4 bicis apiladas. No carousel. S-TOP visible. [DECISIÓN]
3. Configurador (UI-02) + mobile encargo (UI-12) · F-CMP paso 1
| Gesto | Resultado |
|---|---|
| Carga | 4 opciones; ninguna seleccionada; Continuar disabled |
| Tap Rueda / Frenos / Cadena / Revisión | Selección exclusiva; ring mark; Continuar enabled |
| Tap Continuar | Paso 2 en la misma ruta (UI-03) |
| Tap ← Taller | / |
AC: una sola pieza. Cero «lo que sea». Cero carrito. Cero wizard de criterios (ZAGUÁN).
4. Dejar bici (UI-03) · F-CMP paso 2
| Gesto | Resultado |
|---|---|
| Carga | Form + job en solo lectura + disclaimer |
| Atrás | Vuelve a paso 1 conservando el job |
| Nombre / teléfono / color vacío + submit | Error de campo · no POST |
| Submit válido | POST · pending en botón |
| 201 | /ok/:code con state |
| 400 | mark + mensaje de campo |
| Red | seal + Reintentar; no navega a ok |
AC: no email, no DNI, no pago. Dejar la bici ≠ comprar el taller visible.
5. Success (UI-04)
| Gesto | Resultado |
|---|---|
| Entrada desde 201 | Código PIN-XXXX grande + job + color + 4 oposiciones |
| Tap Volver | / |
| Deep link directo | GET /api/bicis/:code; 404 → «Ese encargo no está.» |
AC: las cuatro oposiciones están. No QR. No «ticket listo». No mapa GPS.
6. Login (UI-05)
| Gesto | Resultado |
|---|---|
| Submit válido | POST login · guarda JWT · /mesa o next |
| 401 | «Email o contraseña no valen.» |
Guest en /mesa | Redirect /login?next=/mesa |
AC: sin signup. Ayuda demo mute.
7. Mesa MECÁNICO (UI-06)
| Gesto | Resultado |
|---|---|
| Primera carga | Loading skeletons grupos + encargos |
| 200 | Ganchos ESPERA / EN_TALLER / LISTA + requests (name, phone, code, hora) |
| Empty encargos | «No hay encargos.» |
| 401 | Redirect login |
| Salir | Limpia token → / |
| Tap fila | Sin /mesa/:code en v1; lectura |
AC: no columnas Recibido / En curso. No PATCH estado. No split lista|ficha. No mapa.
8. S-TOP · chrome
| Gesto | Resultado |
|---|---|
| Tap Taller | / |
| Tap Encargo | /encargo paso 1 |
| Tap Mesa | Auth → /mesa; guest → login |
| Activo | Mark + aria-current |
| Idle | Mute |
AC: tres slots. No hamburger. No dock. Targets ≥44px. Fijo en 390.
9. Empty / Error / Loading (UI-07 / UI-08 / UI-09)
| Estado | UI |
|---|---|
| Loading | Pulse card; aria-busy |
| Empty taller | Display + mute + sin CTA de Decathlon |
| Empty mesa encargos | Mute |
| Error | Titular + Reintentar mark |
10. Motion
| Gesto | Default | Reduced |
|---|---|---|
| Aparición bento | Fade 140ms | Instant |
| Hover ring | 120ms | Instant |
| Tile nave | Estático | Estático |
Sin Ken Burns agresivo sobre Deriva. [DECISIÓN]
11. Guión de interacción demo
/loading → tile + 3 datos + 4 bicis.- Leer PIN-2702 LISTA / PIN-2704 ESPERA.
- Encargo → Frenos → form Pablo → pending → success.
- S-TOP Mesa → login → mesa con gancho ESPERA nuevo.
- 390: S-TOP no tapa CTA; scroll con padding.
12. Criterios de aceptación de interacción
- F-CMP no salta el configurador.
- POST sin job no navega a ok.
- Pending no doble-envía.
- S-TOP siempre alcanzable en 390.
- Focus visible en todo el recorrido teclado.
17-prototype-map.md
17 — Mapa de prototipo — PIÑÓN
1. Fuentes
| Fuente | ID / path |
|---|---|
| Paper | https://app.paper.design/file/01M110K5JHDQ899C360KC4D0WD |
| File ID | 01M110K5JHDQ899C360KC4D0WD |
| UX-count | 12 |
| UI-count | 12 |
| App | /Users/cristian/orca/pinon-app |
| Case assets | 2026-08-27-pinon/assets/ |
[COMPROBADO] conteos y file ID en docs/00-paper-reference.md.
2. UX process → docs
| UX | Nombre | Doc espejo |
|---|---|---|
| UX-00 | Cover | README · executive · 07 |
| UX-01 | Stakeholders | 02 §3 |
| UX-02 | Personas | 02 §4 |
| UX-03 | JTBD | 02 §5 |
| UX-04 | Stories | 02 §6 |
| UX-05 | Journey | 02 §7 · 04 |
| UX-06 | Blueprint | 02 §8 |
| UX-07 | Site map | 03 |
| UX-08 | Flujos | 04 |
| UX-09 | Datos+permisos | 05 · 01 §5 · 11 |
| UX-10 | Métricas | 12 |
| UX-11 | Research | 02 |
3. UI producto → rutas / componentes
| UI | Nombre | Ruta | Componente Angular |
|---|---|---|---|
| UI-01 | Home bento | / | TallerPage |
| UI-02 | Configurador | /encargo paso 1 | EncargoPage |
| UI-03 | Dejar bici | /encargo paso 2 | EncargoPage |
| UI-04 | Success | /ok/:code | OkPage |
| UI-05 | Login | /login | LoginPage |
| UI-06 | Mesa | /mesa | MesaPage |
| UI-07 | Empty | mismas rutas | estados |
| UI-08 | Error | mismas rutas | estados |
| UI-09 | Loading | mismas rutas | estados |
| UI-10 | Tokens | — (theme) | Tailwind config / styles |
| UI-11 | Mobile bento | / @390 | TallerPage |
| UI-12 | Mobile encargo | /encargo @390 | EncargoPage |
4. Flujo prototipo clickable (orden demo)
UI-01 Home bento
├─→ UI-02 Configurador (Frenos)
│ └─→ UI-03 Dejar bici → UI-04 Success
├─→ UI-11 (mismo /, viewport 390)
├─→ UI-12 (mismo /encargo, viewport 390)
└─→ S-TOP Mesa → UI-05 Login → UI-06 Mesa
Estados: UI-07 empty · UI-08 error · UI-09 loading se prueban desconectando API o seed vacío.
Tokens: UI-10.
5. Datos de prototipo = seed
| Code | Modelo | Color | Job | Estado | Cover asset |
|---|---|---|---|---|---|
| PIN-2701 | Orbea urbana | verde | Frenos | EN_TALLER | bicis/orbea.jpg |
| PIN-2702 | BH paseo | crema | Revisión | LISTA | bicis/bh.jpg |
| PIN-2703 | Classic fold | negra | Rueda | EN_TALLER | bicis/fold.jpg |
| PIN-2704 | Trek niño | azul | Cadena | ESPERA | bicis/trek.jpg |
Hotspots Paper deben usar estos códigos en labels si muestran URL. [DECISIÓN]
POST demo → PIN-2705 (Pablo Mora, frenos, verde).
6. Breakpoints de artboard
| Artboard | Ancho ref |
|---|---|
| Desktop bento / encargo / mesa | ~1280–1440 |
| Mobile bento (UI-11) | 390 |
| Mobile encargo (UI-12) | 390 |
| Tokens (UI-10) | según Paper |
7. Terna visible en prototipo
| Código | Evidencia en UI |
|---|---|
| R-HY | Oficio clásico (S-TOP, ganchos) + configurador |
| S-TOP | Taller · Encargo · Mesa en UI-01 / 11 / 06 |
| H-BENTO | UI-01 Deriva: tile + 3 datos + 4 bicis |
| F-CMP | UI-02 antes de UI-03 |
8. Gaps conscientes
| Gap | Notas |
|---|---|
| GPS / e-commerce | L3 · no son huecos del prototipo L2 |
| PATCH de estado | Fuera · mesa de lectura |
| Analytics en prototipo | Modelo 12 |
Ningún gap es producto in-scope aplazado. [DECISIÓN]
9. Criterios de aceptación del mapa
- Cada UI-01…12 tiene fila en esta tabla.
- Cada ruta Must tiene artboard.
- No hay artboard de
/buscar,/sesion, tienda, GPS o cita. - Mobile 390 cubierto (UI-11, UI-12).
- UX-00…11 cubiertos.
18-completeness-audit.md
18 — Auditoría de cierre — PIÑÓN
1. Alcance L2 · una iteración
El vertical slice cierra en esta iteración. No hay segunda pasada de producto in-scope. Empty, error, loading, mobile, auth, seed, copy y contrato de código forman parte del cierre, no de un roadmap.
| Pieza | Estado |
|---|---|
| Docs 01–20 + README + executive | OK (este set) |
00-day-brief | Intactos (fuente de verdad) |
00-paper-reference | OK · UX-count 12 · UI-count 12 |
| Paper 12 UX + 12 UI | Inventario en 00 · file 01M110K5JHDQ899C360KC4D0WD |
App path /Users/cristian/orca/pinon-app | OK · GH Criscode2022/pinon-app |
API :3027 · health pinon-api | Contrato |
| Código bicis + requests + JWT MECANICO | Contrato doc 20 |
| Cierre sin deuda del L2 | OK · roadmap solo L3 GPS / e-commerce |
2. Terna y diversidad
| Check | Evidencia |
|---|---|
| R-HY · S-TOP · H-BENTO · F-CMP | Brief + 01 + 07 |
| 0 códigos = BOBINA | BOBINA era R-IN · S-DOCK · H-FEED · F-STORY |
| ≥2 vs LOMO / ONDA | Top/Bento/Cmp vs cmd/data/lead y rail/gallery/search |
| S-TOP, H-BENTO, F-CMP no en últimos 5 | Brief |
Ground G-GRAPHITE #2C3033 | 00 + 07 + Tailwind |
| No leftover BOBINA | 0 sesiones / PROGRAMADOR / dock en el contrato |
| Mood industrial ≠ neón fixie | 07 |
| H-BENTO ≠ MATIZ | S-TOP + F-CMP; no editor de gramos |
3. Copy irrenunciable
Presente en taller, encargo, success, pie de mesa. Ver doc 09.
- Dejar la bici ≠ comprar el taller
- Encargo ≠ cita de fitness
- Recoger ≠ alquilar
- PIÑÓN no es Decathlon
4. Anti-patrones vigilados
| AP | Mitigación |
|---|---|
| AP-12 hero 2-col | H-BENTO Deriva tile + 3 datos + 4 bicis |
| AP-21 card hueca | Modelo/color/job/estado visibles |
| Leftover como estado | Contrato PIÑÓN; no se anota BOBINA como producto vivo |
| Entrevistas inventadas | 02 etiquetado |
| sesiones/PROGRAMADOR/bobina-api | 0 en dominio; 05 + 20 |
| ejemplares/BIBLIO | 0 en dominio |
| H-FEED / S-DOCK | Bento + S-TOP |
| H-DATA / S-CMD | No mesa de datos ni comando |
| Kanban | Mesa de ganchos |
| GPS / e-commerce en L2 | S4 · solo L3 |
| Estadísticas inventadas | Etiquetas [HIPÓTESIS]/[SUPUESTO] |
| Roadmap con deuda L2 | Doc 15 solo GPS / e-commerce |
5. Seed
4 bicis · 2 EN_TALLER · 1 LISTA · 1 ESPERA · Nuria MECÁNICO · Pablo sin cuenta · Amparo fuera de login.
| code | model | job | status |
|---|---|---|---|
| PIN-2701 | Orbea urbana verde | Frenos | EN_TALLER |
| PIN-2702 | BH paseo crema | Revisión | LISTA |
| PIN-2703 | Classic fold negra | Rueda | EN_TALLER |
| PIN-2704 | Trek niño azul | Cadena | ESPERA |
Métricas: en taller 2 · listas 1 · esperan 1.
6. Assets
| Archivo | Presente |
|---|---|
assets/hero.jpg | [COMPROBADO] case |
assets/bicis/orbea.jpg | [COMPROBADO] |
assets/bicis/bh.jpg | [COMPROBADO] |
assets/bicis/fold.jpg | [COMPROBADO] |
assets/bicis/trek.jpg | [COMPROBADO] |
7. Huecos conscientes (fuera · L3)
GPS, e-commerce. Nada más se etiqueta como «faltó del L2».
Login Amparo, email transaccional, instrumentación analytics, PATCH de estado, ficha /mesa/:code no son deuda: son decisiones de corte (S2, S4, D14).
8. Checklist archivos suite
| Archivo | Estado |
|---|---|
| README.md | OK |
| presentation/executive-summary.md | OK |
| docs/00-day-brief.md | Preexistente |
| docs/00-paper-reference.md | OK |
| docs/01 … docs/20 | OK |
9. Veredicto
Slice L2 cerrado en una iteración. El contrato de pinon-app (docs 14 y 20) no se lista como próximo paso de producto: es el mismo alcance, ya definido. Paper file 01M110K5JHDQ899C360KC4D0WD. Si el repo diverge (leftover BOBINA), gana docs 05 + 20 tras alinear ambos.
Cierre: Must cubierto. Roadmap = L3 GPS y e-commerce únicamente.
10. SCORE ALS-2 (cierre)
| Eje | Score | Nota |
|---|---|---|
| Diversidad | 5 | Taller de barrio nuevo; L2 no L1; no cineclub/feed/dock |
| Docs | 4 | Suite 00–20 + brief + presentation |
| Paper craft UI | 5 | 12 UI tokens/taller Deriva/configurador/dejar/success/login/mesa/empty/error+loading + 2 mobile |
| Paper UX process | 5 | 12 UX · gate UX=12 UI=12 |
| Media | 5 | Hero nave + 4 bicis |
| Canvas org | 5 | Bandas § UX / IA / UI / Estados origen 0,0 |
| Código E2E | 5 | GET bicis + POST encargos 201 PIN-2705 + JWT MECANICO; ng build |
| Paridad app | 4 | S-TOP + H-BENTO Deriva + tokens G-GRAPHITE |
| Unicidad estructura | 5 | R-HY · S-TOP · H-BENTO · F-CMP |
| Cierre admin | 5 | Registry+Excel+GitHub+Paper gate+portfolio UI-01 |
| Media | ~4.8 |
Gate: node scripts/check-paper-reference.mjs 2026-08-27-pinon → OK.
19-backlog-completo.md
19 — Backlog completo — PIÑÓN
1. Leyenda
| Estado | Significado |
|---|---|
| Done | Definido y aceptado en la suite ALS L2 (esta iteración) |
| Won’t L2 | Fuera; L3 GPS / e-commerce u otro case |
No hay columna «Must (después)». El slice no deja producto in-scope a medias. [DECISIÓN]
2. Épica A — Taller H-BENTO Deriva
| ID | Ítem | Estado |
|---|---|---|
| A1 | Deriva tile nave a sangre + 3 métricas + 4 bicis | Done |
| A2 | Tile: modelo, color, job, status | Done |
| A3 | CTA Encargo → /encargo | Done |
| A4 | Empty / loading / error | Done |
| A5 | Mobile 390 + assets covers | Done |
| A6 | Búsqueda comando /buscar | Won’t L2 (≠ LOMO) |
| A7 | Feed de noches | Won’t L2 (≠ BOBINA) |
3. Épica B — Configurador F-CMP
| ID | Ítem | Estado |
|---|---|---|
| B1 | /encargo paso 1 · 4 jobs | Done |
| B2 | Selección exclusiva rueda / frenos / cadena / revisión | Done |
| B3 | Continuar disabled sin job | Done |
| B4 | Copy irrenunciable en encargo | Done |
| B5 | «Arréglame lo que sea» / multi-SKU | Won’t L2 (H2) |
4. Épica C — Dejar la bici
| ID | Ítem | Estado |
|---|---|---|
| C1 | /encargo paso 2 · name + phone + color | Done |
| C2 | POST público 201 / 400 | Done |
| C3 | Crea bici ESPERA + request | Done |
| C4 | /ok/:code + 4 oposiciones | Done |
| C5 | Pago / lineal / talla | Won’t L2 (≠ Decathlon · L3 e-commerce) |
| C6 | Signup vecino | Won’t L2 (S2) |
| C7 | GPS al dejar | Won’t L2 (L3) |
5. Épica D — Mesa MECÁNICO
| ID | Ítem | Estado |
|---|---|---|
| D1 | Login JWT Nuria | Done |
| D2 | /mesa ganchos ESPERA / EN_TALLER / LISTA | Done |
| D3 | GET mesa 401 sin token | Done |
| D4 | Logout | Done |
| D5 | Requests con name + phone | Done |
| D6 | Kanban columnas | Won’t L2 (≠ PREGÓN) |
| D7 | PATCH estado / ficha pedido | Won’t L2 (mesa de lectura) |
6. Épica E — Chrome S-TOP
| ID | Ítem | Estado |
|---|---|---|
| E1 | Top Taller · Encargo · Mesa | Done |
| E2 | aria-current + targets 44 | Done |
| E3 | Mesa guest → login | Done |
| E4 | Dock BOBINA / comando LOMO / bottom MATIZ | Won’t L2 |
7. Épica F — Design system & a11y
| ID | Ítem | Estado |
|---|---|---|
| F1 | Tokens grafito/cream/card/mark/mute/chrome | Done |
| F2 | Spectral + Sora | Done |
| F3 | Contraste cream/grafito AA | Done |
| F4 | Reduced motion | Done |
| F5 | Modo letra grande Amparo | Won’t L2 (corte a11y, no deuda) |
8. Épica G — Plataforma
| ID | Ítem | Estado |
|---|---|---|
| G1 | Nest :3027 · health pinon-api | Done |
| G2 | Neon dedicado schema+seed | Done |
| G3 | Angular rutas + guard | Done |
| G4 | pnpm apps independientes | Done |
| G5 | GPS / Mapbox | Won’t L2 · L3 |
| G6 | E-commerce / Stripe | Won’t L2 · L3 |
9. Épica H — Documentación & diseño
| ID | Ítem | Estado |
|---|---|---|
| H1 | docs 00–20 + README + executive | Done |
| H2 | Paper UX 12 + UI 12 inventario | Done |
| H3 | File 01M110K5JHDQ899C360KC4D0WD | Done (ref) |
10. Orden de build (mismo alcance, no roadmap)
- Schema + seed + health
- GET bicis + TallerPage Deriva
- EncargoPage paso 1 + paso 2
- POST encargos + OkPage copy
- Auth + MesaPage
- S-TOP + 390 + empty/error/loading
- Pulido tokens / a11y / smoke S01–S12
Ese orden no es «próximos pasos de producto»: es la receta del mismo L2 ya cerrado. [DECISIÓN]
11. Contadores
| Tipo | Count (aprox) |
|---|---|
| Done L2 | ~40 |
| Won’t L2 / L3 | GPS, e-commerce + analogías vetadas |
| Docs Done | Suite completa |
No se inventan story points ni velocidades de equipo. [DECISIÓN]
20-implementation.md
20 — Implementación — PIÑÓN
1. Resumen ejecutivo técnico
| Campo | Valor |
|---|---|
| App path | /Users/cristian/orca/pinon-app |
| GH | Criscode2022/pinon-app |
| API | NestJS · puerto 3027 · prefijo /api |
| Web | Angular standalone · puerto 4200 |
| Package | apps independientes (pnpm --filter) |
| DB | Neon PostgreSQL · project dedicado PIÑÓN (DATABASE_URL) |
| Tablas | users, bicis, requests, sessions |
| Auth | JWT Bearer · role MECANICO (/mesa); bento y POST encargos públicos |
| Dominio | User, Bike, Request |
| Fecha | 2026-08-27 |
| Health | pinon-api (leftover bobina-api → sustituir) |
Este documento es la especificación de build del L2 ya cerrado. No es un roadmap: si el repo diverge, gana el contrato de docs 05 + este archivo tras actualizar ambos.
Contrato: bicis + requests + JWT MECANICO. Puerto 3027. Health pinon-api.
[COMPROBADO] Path, puerto y Paper salen del encargo.
El repo no debe contener leftover BOBINA (sesiones, PROGRAMADOR, bobina-api, puerto 3026) ni leftover LOMO (ejemplares, BIBLIO). Eso no es PIÑÓN.
2. Cómo arrancar
cd /Users/cristian/orca/pinon-app
# instalar dependencias por app (pnpm --filter; no npm workspaces)
# apps/api/.env
# DATABASE_URL=<neon PIÑÓN>
# JWT_SECRET=<secret>
# PORT=3027
# schema + seed
# api → http://localhost:3027
# web → http://localhost:4200
Credenciales
| Rol | Password | |
|---|---|---|
| MECANICO | nuria@pinon.taller | password123 |
Hash seed: $2b$12$OEKcNck63neDJ.CrVP0lNOaXp2NG2zd2aMiGmnYY221h4ZAZ58x1m
Vecino / vecina mayor: sin cuenta. Pablo deja en /encargo. Amparo no entra por login.
3. Schema
Al boot o vía migrate:
CREATE TABLEdeusers,sessions,bicis,requests(doc 05).- Índices:
bicis(code),bicis(status),bicis(sort_order),users(email),requests(bici_id),requests(created_at DESC). - Seed idempotente:
- upsert MECANICO
nuria@pinon.taller(hash bcrypt canónico) - upsert
bicisporcode(PIN-2701…PIN-2704) restaurando status, job, color, cover - upsert 4
requestsseed (Elena, Luis, Marta, Iván)
- upsert MECANICO
- Dominio: solo bicis + requests + users. [DECISIÓN]
Upsert de bicis por code sí restaura status/job de catálogo para que el guión sea repetible. [DECISIÓN]
POST de encargo sí genera código nuevo (PIN-2705+). El success usa ese código.
Tablas (recordatorio)
| Tabla | Contenido |
|---|---|
users | MECÁNICO Nuria Vega |
bicis | 4 ganchos (+ las del POST) |
requests | Encargos (seed + POST) |
sessions | sid + expires_at |
DROP leftover sesiones, pedidos, ejemplares, programas si existen en el mismo Neon. [DECISIÓN] El project es de PIÑÓN.
Seed SQL (modelo)
| code | model | color | job | status | cover |
|---|---|---|---|---|---|
| PIN-2701 | Orbea urbana | verde | FRENOS | EN_TALLER | /assets/bicis/orbea.jpg |
| PIN-2702 | BH paseo | crema | REVISION | LISTA | /assets/bicis/bh.jpg |
| PIN-2703 | Classic fold | negra | RUEDA | EN_TALLER | /assets/bicis/fold.jpg |
| PIN-2704 | Trek niño | azul | CADENA | ESPERA | /assets/bicis/trek.jpg |
[SUPUESTO de taller] Modelos demo.
4. Módulos API a implementar
Auth
POST /api/auth/login- Valida email/password; compara bcrypt; emite JWT con
sub, email, role. - Guard JWT +
role === MECANICOprotege/mesa. - Públicos: health, bicis, bicis/:code, POST encargos, login.
Oficio
| Método | Ruta | Auth | Notas |
|---|---|---|---|
| GET | /api/health | No | { ok: true, service: "pinon-api" } |
| GET | /api/bicis | No | metrics + sort_order asc sin name/phone |
| GET | /api/bicis/:code | No | item |
| POST | /api/encargos | No | INSERT bici ESPERA + request; 400 si job/name/phone/color inválidos |
| GET | /api/mesa | JWT | ganchos agrupados + requests con PII de mostrador |
Health (referencia de implementación)
{ "ok": true, "service": "pinon-api" }
Cualquier leftover "bobina-api" o "lomo-api" falla el DoD.
POST encargos — algoritmo
1. Validar body.job ∈ {RUEDA,FRENOS,CADENA,REVISION} else 400
2. Validar body.name (trim, length >= 2) else 400
3. Validar body.phone (dígitos >= 9) else 400
4. Validar body.color (trim, length >= 3) else 400
5. model = body.model?.trim() || 'bici'
6. code = siguiente PIN-XXXX (max existente + 1, piso PIN-2705)
7. INSERT bicis (code, model, color, job, status=ESPERA)
8. INSERT requests (bici_id, code, name, phone)
9. 201 { code, color, job, status: ESPERA, dejada: true }
Transacción única. [DECISIÓN]
GET bicis — shape
{
"metrics": { "enTaller": 2, "listas": 1, "esperan": 1 },
"bicis": [ { "code", "model", "color", "job", "status", "cover", "sortOrder" } ]
}
Métricas: count status EN_TALLER / LISTA / ESPERA. No ENTREGADA. [DECISIÓN]
GET mesa — shape
{
"metrics": { "enTaller": n, "listas": n, "esperan": n },
"ganchos": {
"ESPERA": [ /* bicis */ ],
"EN_TALLER": [ /* bicis */ ],
"LISTA": [ /* bicis */ ]
},
"requests": [ { "id", "code", "name", "phone", "job", "status", "createdAt" } ]
}
Orden requests: created_at DESC. [DECISIÓN]
5. Frontend Angular
Rutas
| Path | Component | Guard |
|---|---|---|
'' | TallerPage | — |
encargo | EncargoPage | — |
ok/:code | OkPage | — |
login | LoginPage | — |
mesa | MesaPage | authGuard |
** | redirect '' | — |
Servicios
| Service | Responsabilidad |
|---|---|
BicisApi | GET list/detail |
EncargosApi | POST encargos |
AuthApi | login, token store, logout |
MesaApi | GET mesa con Bearer |
TopNavState | slot activo |
UI Must
TallerPage— tile + 3 datos + 4 bicis (Deriva), no feed ni tabla.EncargoPage— F-CMP paso 1 y 2.OkPage— código + 4 oposiciones.LoginPage/MesaPage.TopNavComponent— S-TOP.- Estados empty/error/loading.
Tailwind tokens
ground: #2C3033
cream: #F3F1EC
card: #1A1C1B
mark: #E24A17
mute: #8B8E8A
chrome: #C5C8C4
font-display: Spectral
font-sans: Sora
6. Assets en app
Copiar desde el case a apps/web/public/assets/bicis/ (o path equivalente servido):
orbea.jpgbh.jpgfold.jpgtrek.jpg
hero.jpg → tile Deriva (/assets/hero.jpg).
Paths en DB alineados a /assets/bicis/.... [DECISIÓN]
7. Checklist anti-leftover
| Prohibido en runtime | Sustituto |
|---|---|
bobina-api | pinon-api |
| puerto 3026 | 3027 |
sesiones / pedidos | bicis / requests |
| PROGRAMADOR | MECANICO |
| BOB-XXXX | PIN-XXXX |
/sesion /pedir | / /encargo |
| ABIERTA/COMPLETA | ESPERA/EN_TALLER/LISTA |
| Cormorant / Manrope velvet | Spectral / Sora industrial |
G-VELVET #1A1210 | G-GRAPHITE #2C3033 |
| Dock Cartelera · Pedir · Mesa | S-TOP Taller · Encargo · Mesa |
8. DoD técnico (merge)
- Smoke S01–S12 (doc 13) en verde.
- Health
pinon-api. - Seed idempotente.
- Mesa 401 sin token.
- Success muestra las 4 oposiciones.
- 390 + S-TOP usable.
- 0 referencias de producto a sesiones/PROGRAMADOR/bobina-api.
- Cream sobre grafito en cuerpo.
9. Fuera de esta especificación
- GPS (L3).
- E-commerce (L3).
- Instrumentación analytics (doc 12 modelo).
- PATCH de estado (mesa de lectura).
Ninguno de esos ítems es un «siguiente paso» del L2. [DECISIÓN]
10. Cierre
Implementación = contrato ejecutable del case 2026-08-27-pinon, cerrado en una iteración. [COMPROBADO] alcance L2.