Muévete por Bucaramanga sin efectivo.

Plataforma de movilidad urbana multi-tenant: buses en vivo, wallet prepago y QR dinámico firmado.

José Alejandro Téllez PradaU00060479 · Arquitectura
Marcos Valera DazaU00177223 · Backend
Jaime Alejandro Vega BarbosaU00178766 · App móvil
Backend · Sexto semestre
UNAB · 2026

En pocas palabras

Pagar el bus con el celular, sin que nadie pierda un peso.

BUCARATRANSIT une a las transportadoras de Bucaramanga en una sola plataforma. El pasajero recarga un saldo, muestra un QR y el conductor lo cobra con su teléfono. Cada empresa ve solo lo suyo y todo queda registrado de forma auditable.

Wallet prepagoLedger de doble entradaQR firmado · 60 s · un solo usoMulti-tenant en 3 capasChaos Engineering304 pruebas verdes

Problema y justificación

Tres fricciones diarias en el bus de Bucaramanga.

01 · EFECTIVO

Cobro manual

El conductor maneja dinero y vuelto mientras conduce: lento, riesgoso y sin trazabilidad. Cada pasaje en efectivo es una fuga potencial de recaudo.

02 · FRAGMENTACIÓN

Cada empresa, un silo

No existe un medio de pago ni una vista de rutas común entre transportadoras. El pasajero y la ciudad pagan el costo de la desconexión.

03 · INCERTIDUMBRE

¿Cuándo llega mi bus?

Sin ubicación en vivo ni tiempo estimado, planear un trayecto es adivinar. El tiempo de espera se pierde sin información.

Justificación: una plataforma neutral que unifique pago, rutas y datos sin que ninguna empresa vea a las otras.

Referente teórico

Cada decisión de diseño tiene una base.

MULTI-TENANCY

Esquema compartido

Una base de datos, una discriminación por transportadora_id: menor costo operativo, mayor riesgo de fuga si falla el aislamiento. [1][2]

DINERO COMO INFRAESTRUCTURA

Ledger e idempotencia

Asientos inmutables de doble entrada, montos enteros y operaciones idempotentes para tolerar reintentos sin duplicar cobros. [3][4]

AUTENTICIDAD

HMAC y un solo uso

Un código firmado con clave del servidor no se puede falsificar; un TTL corto y consumo atómico impiden la reutilización. [5][6][7]

RESILIENCIA

Chaos Engineering

Inyectar fallas controladas para validar patrones de degradación elegante, fallback, bulkhead y cache-aside. [8][9][10]

IDENTIDAD Y API

REST + tokens

API REST sin estado con tokens personales (Sanctum) y OAuth 2.0 para el ingreso con Google. [11][12]

MARCO NORMATIVO

Datos y calidad

Tratamiento de datos personales (Ley 1581 de 2012) y atributos de calidad de software (ISO/IEC 25010). [13][14]

La solución

Una plataforma, tres actores.

  • Pasajero. Mapa en vivo, ETA, wallet y QR de pago.
  • Conductor. Su teléfono es el mPOS: escanea y cobra.
  • Transportadora. Panel propio de flota, rutas y tarifas.
  • Plataforma. Super admin con vista global y kill-switch.

Figura 1 · Arquitectura general

Seis contenedores, una sola entrada.

CLIENTES App móvilKotlin Multiplatform Panel /empresaFilament · 1 tenant Panel /adminFilament · super admin Nginx TLS · Let's EncryptRate limitingCabeceras de seguridadArchivos estáticos punto único de entrada Laravel 12 · PHP-FPM API REST /api/v1 · Sanctum EnsureTenantScope · GlobalScope WalletService QrPaymentService BrandingService ETA · GPS Paneles Filament (admin / empresa) MySQL 8tenants · wallets · ledger · QR RedisGPS 30 s · rutas 24 h Worker + Schedulercolas · notificaciones push SERVICIOS EXTERNOS (OPCIONALES) Google OAuth GPS del proveedor Firebase FCM Teselas OpenFreeMap

Aislamiento multi-tenant

Tres capas para que una empresa nunca vea a otra.

CAPA 1 · DATOS

GlobalScope

El trait BelongsToTenant filtra automáticamente toda consulta por transportadora_id cuando hay un tenant en contexto.

CAPA 2 · API

Middleware

EnsureTenantScope verifica que el recurso de la ruta pertenezca al tenant y activa el contexto durante toda la petición.

CAPA 3 · RESPUESTA

404 silencioso

Pedir un recurso ajeno devuelve 404, nunca 403: ni siquiera se revela que existe.

Verificado en TenantIsolationTest: el usuario del tenant A recibe 404 en recursos del tenant B.

Figura 2 · Modelo de datos esencial

El dinero vive en un libro que no se edita.

transportadoras id · slug UNIQUEnombre · nit · planactivo (kill-switch)branding · versiónraíz del tenant users role: super_admin · tenant_admindriver · pasajerotransportadora_id (nulo = ciudad)email · google_id buses · fares buses UNIQUE(transportadora_id, placa)fares: monto, vigenciatransportadora_id stops · routesdatos compartidos de ciudad wallets 1 por usuariobalance_centavos BIGINT ≥ 0version (lock optimista)proyección del ledger wallet_transactions · LEDGER append-only credit · debit · ajuste · monto_centavos · balance_afterreference UNIQUE → idempotenciasin UPDATE ni DELETE: el modelo lanza excepción qr_payment_tokenstoken_hash SHA-256 · monto_snapshot · expires_at · used_at 1 ─ N1 ─ 11 ─ N

Figura 3 · Diagrama de secuencia del pago con QR

Un QR que se usa una sola vez.

Pasajero · app Servidor Laravel MySQL · ledger Conductor · mPOS ① Solicita QR de pago ② Guarda hash(selector), monto, expira +60 s ③ Devuelve selector.HMAC ④ Muestra el QR (rota) ⑤ Escanea y envía el código ⑥ Verifica firma · vigencia · no usado ⑦ TX atómica:marca usado · débito pasajero · crédito empresa ⑧ Éxito: pantalla verde con el monto · si falla → 422, no se mueve nada

App móvil · Kotlin Multiplatform

Lo que ve el pasajero.

Marca dinámica
Elige tu parada
Siguiendo el bus
Wallet y QR
Modo conductor

Paneles de administración

Cada empresa ve solo lo suyo.

/empresa · mapa filtrado a su propia flota

/admin · varias transportadoras, plan y kill-switch

Tabla 1 · Resultados de Chaos Engineering

Apagamos cosas a propósito.

Falla inyectadaPatrón evaluadoComportamiento observadoResultado
GPS externo caídoDegradación eleganteEl endpoint responde 503 con mensaje claro; no hay excepción sin manejarResiste
Google OAuth caídoFallbackEl inicio de sesión con correo y contraseña toma el relevoResiste
MySQL o Redis caídosBulkhead · cache-asideContenedores aislados: la caída de uno no tumba a Nginx; sin Redis la app degradaResiste
Worker de colas caídoProceso asíncronoLa API sigue respondiendo; las notificaciones se encolanResiste
20 intentos seguidos de loginRate limitingDesde la petición 11 el servidor responde HTTP 429Resiste
Nginx caído—Sin proxy la app es inaccesible: punto único de fallaMitigar: balanceador

Verificación

Lo que decimos, lo probamos.

304
pruebas automatizadas pasando
1253
aserciones
60 s
vida de cada QR, un solo uso
0
fugas entre tenants en las pruebas de aislamiento

Suites clave: TenantIsolationTest · WalletServiceTest · QrHardeningTest · QrIdempotencyTest · RateLimitingTest. Al cierre del pivote eran 88 pruebas y 257 aserciones.

Limitaciones y desafíos

Lo que todavía no está resuelto.

LimitaciónImpactoSiguiente paso
Recarga simuladaNo entra dinero real al walletProveedor de pagos con webhooks idempotentes (F4)
Una sola VMPunto único de falla (Nginx, host)Balanceador y varias instancias
Secretos en el historialClaves antiguas en commits previosRotar claves y evaluar limpiar el historial
iOS y UI sin probarCobertura solo de lógica y APIPruebas de pantallas y simulador iOS
Cobro solo por QRExige cámara y datos en el busNFC y modo sin conexión con conciliación

Trabajo futuro

De prototipo verificado a servicio de ciudad.

F0–F3 · HECHO

Fundamentos

Tenancy, wallets y ledger, QR de pago, paneles y mPOS conductor.

F4 · SIGUIENTE

Pagos reales

Proveedor de pagos, webhooks idempotentes y conciliación.

F5 · FUTURO

NFC y rutas

Pago por NFC y motor de enrutamiento multiempresa.

OPERACIÓN

Alta disponibilidad

Balanceador, réplicas y monitoreo continuo.

Referencias

Bibliografía (IEEE).

  1. [1]C.-P. Bezemer and A. Zaidman, “Multi-tenant SaaS applications: maintenance dream or nightmare?,” in Proc. IWPSE-EVOL, 2010.
  2. [2]F. Chong and G. Carraro, “Architecture strategies for catching the long tail,” Microsoft Corp., 2006.
  3. [3]M. Kleppmann, Designing Data-Intensive Applications. O’Reilly Media, 2017.
  4. [4]M. Fowler, Patterns of Enterprise Application Architecture. Addison-Wesley, 2002.
  5. [5]H. Krawczyk, M. Bellare and R. Canetti, “HMAC: Keyed-hashing for message authentication,” RFC 2104, IETF, 1997.
  6. [6]OWASP Foundation, “OWASP API Security Top 10,” 2023.
  7. [7]NIST, “Secure Hash Standard (SHS),” FIPS PUB 180-4, 2015.
  8. [8]A. Basiri et al., “Chaos engineering,” IEEE Software, vol. 33, no. 3, pp. 35–41, 2016.
  9. [9]C. Rosenthal and N. Jones, Chaos Engineering: System Resiliency in Practice. O’Reilly Media, 2020.
  10. [10]M. T. Nygard, Release It!, 2nd ed. Pragmatic Bookshelf, 2018.
  11. [11]R. T. Fielding, “Architectural styles and the design of network-based software architectures,” Ph.D. dissertation, UC Irvine, 2000.
  12. [12]D. Hardt, “The OAuth 2.0 authorization framework,” RFC 6749, IETF, 2012.
  13. [13]Congreso de Colombia, “Ley Estatutaria 1581 de 2012: Protección de datos personales,” 2012.
  14. [14]ISO/IEC, “Systems and software quality requirements and evaluation (SQuaRE): System and software quality models,” ISO/IEC 25010, 2011.

Bucaramanga se mueve mejor cuando todos se mueven juntos.

bucaratransit.lat

Paneles en /admin y /empresa · Código en github.com/JaimeMrF/bus_unab

0:00
← → navegar · N notas · T reiniciar reloj · F pantalla completa