ADR-082: Rutas de app Subscriber B2C (sin slug en URL)
Estado
Accepted — 2026-09-09
Contexto
La fábrica FoodHub modelaba muchos tenants en una misma instalación: el usuario elegía “en qué restaurante entrar” y la URL llevaba el slug (/t/{slug}/login → hoy /s/{slug}/login tras FEAT-004).
IVPrior es B2C (DOC-002): V1 = un humano = un Subscriber. El email identifica la cuenta; el JWT ya incluye subscriberId. Exigir /s/demo/login confunde al trader (“¿qué es demo?”) y replica un patrón B2B que no aplica.
FEAT-004 fijó /s/{subscriberSlug}/… como paso intermedio del rename tenant→subscriber. Este ADR enmienda esa decisión de rutas de producto hacia URLs planas orientadas al usuario final.
El subscriber.slug sigue existiendo en base de datos (unicidad, emails de soporte, integraciones futuras) pero deja de ser segmento de ruta en la app autenticada y en el login.
Decisión
Superficie pública y auth
| Ruta | Uso |
|---|---|
/ | Marketing (S-100) |
/signup | Alta self-serve (S-003) |
/login | Sign-in Subscriber global (S-001) — email + password |
/forgot-password, /reset-password, /verify-email | Flujos de identidad (sin slug) |
Prohibido en copy nueva: “ingresa el slug de tu workspace”, “elige tu cuenta”, URLs del tipo /s/{slug}/login.
App autenticada del Subscriber
Prefijo canónico: /app/*
Ejemplos (paridad con sitemap actual):
| Hoy (legacy) | Target |
|---|---|
/s/{slug}/dashboard | /app/dashboard |
/s/{slug}/scanner | /app/scanner |
/s/{slug}/scanner/watchlist | /app/scanner/watchlist |
/s/{slug}/billing | /app/billing |
/s/{slug}/settings | /app/settings |
El middleware/layout resuelve el Subscriber desde el JWT (subscriberId), no desde un param de ruta.
Platform (sin cambio)
/platform/login y /platform/* permanecen para PlatformUser (universo JWT distinto, ADR-023).
Corte y compatibilidad
Alineado a FEAT-004 (sin aliases permanentes):
- Tras el slice de migración, rutas
/s/{slug}/…y/t/{slug}/…responden 404 (no redirect 301/308 indefinido). - Opcional una release con redirect temporal documentado en el change OpenSpec (solo login y dashboard) si hace falta para demos internas; se elimina en el mismo epic antes de producción.
- Emails y deep links se actualizan a
/loginy/app/…en el mismo PR que el corte.
API
- Los endpoints REST del Subscriber ya usan
subscriberIddel token; no requieren slug en path. - Endpoints públicos que hoy usan
/public/subscribers/{slug}para branding se reevalúan: en B2C V1 el branding es global de plataforma o por sesión, no por slug en URL.
Alternativas
| Opción | Nota |
|---|---|
Mantener /s/{slug} | Rechazada — modelo mental tenant, fricción en signup/login |
/login + /app/* | Elegida — estándar B2C SaaS |
Subdominio {slug}.ivprior.com | Rechazada V1 — complejidad DNS/SSL sin beneficio B2C |
| Slug solo post-login en settings | Aceptada — campo interno / URL de perfil opcional, no gate de auth |
Consecuencias
- Epic FEAT-006 (
docs/product/features/FEAT-006-subscriber-flat-routes/brief.md): slices OpenSpec web + emails + e2e. - Actualizar
docs/ux/sitemap.md, pantallas S-001, tests Playwright,SubscriberShellnav links. subscriber.slugse genera en signup (unicidad) pero no se muestra en la barra de direcciones.- FEAT-004 brief: la fila “App Subscriber
/s/{slug}” queda supersedida por este ADR para rutas de producto; el rename tenant→subscriber en código/API sigue vigente. - ADR-081 (GTM): zona M1 incluirá
/loginglobal cuando exista la ruta.
Referencias
- DOC-002 §8 — leftover de fábrica
- FEAT-004 — remap vocabulario (parcialmente enmendado en rutas)
- FEAT-006 — brief de implementación