Skip to content

Requisitos Tecnicos

Requisitos de infraestructura, integraciones y configuracion que Ontime debe resolver para desplegar PROXIMITI en produccion. Cada seccion describe el estado actual (v2.5 local), lo que debe cambiar, y el esfuerzo estimado.

Resumen de Esfuerzo

Punto de integracionEsfuerzoDescripcion
Autenticacion (Keycloak → Azure AD)ALTOReescritura de role converter, cambio de issuer en 11 componentes, mapeo de claims
Integracion ERP — ALINAMEDIOOutbox pattern ya implementado; solo requiere HTTP client real + credenciales
Notificaciones — NOVAMEDIOStub reemplazado por HTTP client real; canales email/SMS por definir
Proveedores — Kanguro / HublockerBAJOSolo cambiar URLs y credenciales; adapter framework ya operativo
Almacenamiento — MinIO → Azure BlobMEDIONueva implementacion de DocumentStoragePort para Azure Blob + SAS tokens
Base de datos — PostgreSQL 16MUY BAJOMantener PostgreSQL en produccion; migracion a Oracle seria ESFUERZO MUY ALTO
Variables de entornoBAJO~50 variables a configurar en el orquestador de produccion
Red, CORS y despliegueALTOSSL/TLS, load balancing, K8s, secrets management, monitoring — nada existe aun
Chat de soporteBAJOStub devuelve token fake; requiere proveedor real

1. Autenticacion e Identidad (Keycloak → Azure AD)

Estado actual

Keycloak 24.0.5 como Identity Provider local. Todos los servicios validan JWTs con:

yaml
issuer-uri: http://keycloak:8080/realms/proximiti
jwk-set-uri: http://keycloak:8080/realms/proximiti/protocol/openid-connect/certs

Los roles se extraen de realm_access.roles (estructura anidada en el JWT de Keycloak) mediante un KeycloakRoleConverter custom en cada servicio.

Que debe cambiar

ElementoValor actual (Keycloak)Valor produccion (Azure AD)
Issuer URIhttp://keycloak:8080/realms/proximitihttps://login.microsoftonline.com/{tenant-id}/v2.0
JWKS URI.../protocol/openid-connect/certshttps://login.microsoftonline.com/{tenant-id}/discovery/v2.0/keys
Token endpoint.../protocol/openid-connect/tokenhttps://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Role claim pathrealm_access.roles (anidado)roles (top-level) o appRoles segun configuracion Azure AD
Custom claimcenter_code (user attribute mapper)center_code (extension attribute o claims mapping policy)
Client IDproximiti-bffApp Registration client ID de Azure AD

Roles requeridos

RolDescripcionEndpoints protegidos
USER_PUDOOperador de punto PUDOEnvios, recepcion, entrega, capacidad
USER_CARRIERTransportista / conductorMulti-drop, handshake, recogida caducados
USER_ADMINAdministrador de plataformaPanel admin, gestion usuarios, integraciones
USER_CUSTOMERCliente / remitentePortal cliente, mis envios, direcciones
USER_BILLINGFacturacionEndpoints de billing

Componentes afectados (11 total)

ComponenteArchivo a modificarCambio requerido
ws-pprx-bffSecurityConfig.javaKeycloakRoleConverterReescribir para Azure AD claim structure
ws-pprx-shipmentsSecurityConfig.javaKeycloakRoleConverterIdem
ws-pprx-centersSecurityConfig.javaKeycloakRoleConverterIdem
ws-pprx-usersSecurityConfig.javaKeycloakRoleConverterIdem
ws-pprx-notificationsSecurityConfig.javaKeycloakRoleConverterIdem
ws-pprx-expiredSecurityConfig.javaKeycloakRoleConverterIdem
ws-pprx-issuesSecurityConfig.javaKeycloakRoleConverterIdem
ws-pprx-adapterSecurityConfig.javaKeycloakRoleConverterIdem
client-portalsrc/config/oidc.tsCambiar authority, metadata endpoints, client_id
pudo-manager-applib/config/app_config.dartCambiar keycloakIssuer, clientId, redirectUri
carrier-applib/config/app_config.dartCambiar keycloakIssuer, clientId, redirectUri

Cambios de codigo necesarios

  1. KeycloakRoleConverter — reescribir para leer roles desde claim top-level (roles) en lugar de realm_access.roles. Renombrar la clase a AzureAdRoleConverter o parametrizar el claim path.

  2. center_code claim — actualmente mapeado como user attribute en Keycloak. Azure AD requiere: extension attribute en App Registration, o claims mapping policy, o Graph API lookup en runtime.

  3. Client portal oidc.ts — las URLs de metadata estan hardcodeadas con path Keycloak (/protocol/openid-connect/*). Cambiar a OIDC discovery automatico o URLs Azure AD.

  4. Flutter app_config.dartkeycloakIssuer y clientId son constantes compiladas via String.fromEnvironment. Requiere cambio de valores en build flags.

  5. Flutter redirectUri — actualmente com.proximiti.pudomanager://callback. Debe registrarse como redirect URI valido en Azure AD App Registration.


2. Integracion ERP — ALINA

Estado actual

El servicio ws-pprx-expired implementa el transactional outbox pattern completo. La tabla tp_pprx_alina_outbox almacena ordenes de recogida para envios caducados.

Tabla outbox:

ColumnaTipoDescripcion
idBIGINT IDENTITYPK
shipment_idBIGINTFK al envio caducado
alina_order_idVARCHARID de orden ALINA (idempotency key)
estadoVARCHARPENDINGSENTCONFIRMED / DEAD_LETTER
payloadJSONBPayload completo para ALINA
attempt_countINTEGERIntentos realizados
next_attempt_atTIMESTAMPTZSiguiente intento programado
error_classVARCHARNON_RETRYABLE o TRANSIENT_EXHAUSTED
error_detailTEXTDetalle del error
dead_letter_atTIMESTAMPTZTimestamp de DLQ

Que hace el stub

AlinaOutboxProcessor.dispatchToAlina() solo escribe un log:

java
// In production, this would be an HTTP call to ALINA API:
// alinaClient.post().uri("/api/pickup-requests")...

Que necesita produccion

AspectoImplementacion requerida
HTTP clientWebClient o RestClient hacia endpoint ALINA real
EndpointPOST /api/pickup-requests (confirmacion pendiente con equipo ALINA)
AutenticacionPor definir (API key, OAuth2, certificado mutuo)
IdempotencyHeader X-Idempotency-Key: {alinaOrderId}:{attemptCount}
RetryExponential backoff: base 30s, max 900s, max 5 intentos
DLQRecords con DEAD_LETTER — panel admin para retrigger manual
CorrelationX-Correlation-Id en cada request

CronJobs (ya implementados)

JobScheduleFuncion
mark-expiredDiario 02:00Marca envios caducados, crea outbox records
notify-alinaCada 15 minProcesa batch de outbox (max 200 records/batch)

Informacion que el cliente debe proporcionar

  • URL base del API ALINA
  • Credenciales de autenticacion (tipo y valores)
  • Schema del payload esperado por ALINA
  • Contrato de respuesta (codigos HTTP, body de confirmacion)
  • Contacto tecnico para validacion de integracion

3. Notificaciones — NOVA (Mulesoft)

Estado actual

NotificationService en ws-pprx-notifications es un stub que solo escribe logs. El flag nova.enabled: false esta desactivado.

Patron de comunicacion

Pattern B: Fire-and-forget — el servicio de notificaciones NO bloquea la accion principal del negocio.

ParametroValor
Timeout500ms maximo
Impacto en negocioNinguno — si falla, el envio sigue su flujo normal
ReintentosResponsabilidad de NOVA, no de PROXIMITI
DeduplicacionX-Idempotency-Key en cada trigger

Eventos que generan notificaciones

EventoTriggerDestinatario
Envio creadoCambio estado → CREADORemitente
Envio en transitoCambio estado → EN_TRANSITORemitente
Envio recepcionadoCambio estado → RECEPCIONADODestinatario
Envio entregadoCambio estado → ENTREGADORemitente + destinatario
Envio caducadoCambio estado → CADUCADORemitente + operador PUDO
Proximidad caducidad24h antes de expirarDestinatario

Notificaciones in-app (YA funcionales)

La tabla tp_pprx_notificacion_usuario almacena notificaciones in-app que SI funcionan en v2.5. Estas son independientes de NOVA y no requieren integracion externa.

Informacion que el cliente debe proporcionar

ElementoDescripcion
URL NOVA MulesoftEndpoint base del API
Autenticacion NOVAOAuth2 client credentials, API key, o equivalente
Canal emailSMTP o API (SendGrid, AWS SES, etc.)
Canal SMSGateway SMS (Twilio, etc.)
Canal pushFirebase Cloud Messaging o APNs (para apps Flutter)
TemplatesDefinir contenido por idioma (ES, EN, CA, EU, GL)

4. Proveedores — Kanguro y Hublocker

Estado actual

El servicio ws-pprx-adapter implementa un framework completo de integracion con proveedores externos. Cada proveedor tiene un adapter que implementa la interfaz ProviderAdapter:

java
public interface ProviderAdapter {
    String getProviderCode();
    AvailabilityResponse getAvailability(String centerCode);
    ReceptionAckResponse notifyReception(String barcode, String centerCode);
    TrackingResponse getTracking(String barcode);
    CatalogSyncResult syncCatalog();
}

Kanguro (OAuth2 client_credentials)

Endpoint stubMetodoPathFuncion
AuthPOST/tokenObtener access token
CatalogGET/catalogLista de puntos Kanguro
AvailabilityGET/{code}/availabilityDisponibilidad del punto
ReceptionPOST/receptionNotificar recepcion de paquete
TrackingGET/{barcode}/trackingEstado del envio

Configuracion actual:

yaml
adapter.kanguro:
  base-url: http://stub-kanguro:8098      # → URL real Kanguro
  client-id: kanguro-client                # → Client ID real
  client-secret: kanguro-secret            # → Client secret real
  webhook-secret: kanguro-webhook-hmac-key # → HMAC key real

Hublocker (API Key)

Endpoint stubMetodoPathFuncion
CatalogGET/catalogLista de lockers
AvailabilityGET/{code}/compartments/availabilityCompartimentos disponibles
ReservePOST/{code}/reserveReservar compartimento
StatusGET/{barcode}/statusEstado del paquete

Configuracion actual:

yaml
adapter.hublocker:
  base-url: http://stub-hublocker:8097  # → URL real Hublocker
  api-key: hublocker-api-key            # → API key real
  webhook-api-key: hublocker-webhook-key # → Webhook validation key

Resilience

Circuit breakers Resilience4j ya configurados por proveedor:

ParametroValor
Failure rate threshold50%
Sliding window10 calls (COUNT_BASED)
Wait in open state30s
Half-open calls3

Catalogo sync

ParametroValor
FrecuenciaCada 5 minutos (0 */5 * * * *)
Stale threshold15 minutos
Error failure count3 consecutivos → circuit open
Error timeout30 minutos

Esfuerzo: BAJO

Solo cambiar URLs base y credenciales en variables de entorno. El codigo no requiere cambios si los APIs reales respetan los contratos de los stubs.


5. Almacenamiento — MinIO → Azure Blob

Buckets actuales

BucketRetencionContenido
proximiti-pod-signatures90 dias (ILM)Firmas digitales de POD (signature, photo, ID)
proximiti-evidence90 dias (ILM)Evidencia de entrega
proximiti-documents30 dias (ILM)Documentos temporales
proximiti-profile-photosPermanenteFotos de perfil de usuario

Abstraccion de storage

La interfaz DocumentStoragePort existe en dos servicios:

  • ws-pprx-shipments/storage/DocumentStoragePort.java — POD, evidencia
  • ws-pprx-centers/storage/DocumentStoragePort.java — documentos de centro
java
public interface DocumentStoragePort {
    UploadTokenResponse generateUploadToken(String container, String blobPath, Duration ttl);
    InputStream download(String container, String blobPath);
    void delete(String container, String blobPath);
}

Actualmente implementado por MinioS3StorageAdapter (usa AWS S3 SDK compatible con MinIO).

Que necesita produccion

TareaDescripcion
AzureBlobStorageAdapterNueva implementacion de DocumentStoragePort usando Azure Storage SDK
Presigned URLs → SAS tokensgenerateUploadToken() debe generar SAS tokens en lugar de presigned S3 URLs
BFF profile photosProfilePhotoStorage en BFF usa MinIO directamente — necesita refactoring al port
Lifecycle managementConfigurar lifecycle rules en Azure Blob equivalentes a ILM de MinIO
CORS en storageAzure Blob necesita CORS configurado para upload directo desde Flutter

Informacion que el cliente debe proporcionar

ElementoDescripcion
Storage account nameNombre de la cuenta Azure Storage
Access key o connection stringCredencial de acceso
Container names4 containers equivalentes a los buckets
RegionRegion Azure para el storage account

6. Base de Datos — PostgreSQL 16 + PostGIS

Recomendacion: mantener PostgreSQL en produccion

PROXIMITI utiliza funcionalidades especificas de PostgreSQL. La recomendacion es desplegar Azure Database for PostgreSQL — Flexible Server en produccion.

Funcionalidades PostgreSQL utilizadas

FuncionalidadUso en PROXIMITIEquivalente OracleComplejidad migracion
BIGINT GENERATED ALWAYS AS IDENTITYTodas las PKs (30+ tablas)GENERATED ALWAYS AS IDENTITYBAJA — Oracle 12c+ soporta
JSONBHorarios, payloads, configuracionJSON (Oracle 21c+) o CLOBMEDIA — operadores JSONB incompatibles
geometry(Polygon, 4326) PostGISPoligonos de clustersOracle Spatial SDO_GEOMETRYALTA — API completamente diferente
Partial unique indexesContratos activos, T&C vigenteFunction-based indexMEDIA — reescritura de DDL
PARTITION BY RANGETracking events por fechaParticionado OracleBAJA — sintaxis similar
TIMESTAMPTZTodos los timestampsTIMESTAMP WITH TIME ZONEBAJA — equivalente directo
pgcrypto extensionGeneracion UUIDSYS_GUID() o DBMS_CRYPTOBAJA
GiST spatial indexesidx_cluster_polygonSpatial indexes OracleALTA — requiere Oracle Spatial
CHECK constraints con stringsEstados (e.g., CREADO, EN_TRANSITO)CHECK constraintsBAJA — equivalente
PL/pgSQL functionsMigraciones, triggersPL/SQLMEDIA — reescritura

Esfuerzo total migracion a Oracle: MUY ALTO — se desaconseja. PostGIS y JSONB son los principales obstaculos.

Nota sobre busqueda de proximidad

La busqueda de puntos PUDO cercanos usa calculo Haversine a nivel de aplicacion (no PostGIS). Esto es database-agnostic. PostGIS solo se usa para los poligonos de clusters del Network Manager.


7. Variables de Entorno

Infraestructura (todos los servicios Java)

VariableEjemplo produccionServicios
SPRING_DATASOURCE_URLjdbc:postgresql://{host}:5432/proximiti8 servicios
SPRING_DATASOURCE_USERNAME(secreto)8 servicios
SPRING_DATASOURCE_PASSWORD(secreto)8 servicios
SPRING_ZIPKIN_BASE_URLhttp://{zipkin-host}:94118 servicios
TRACING_SAMPLING_PROBABILITY0.1 (10%)8 servicios
SPRING_PROFILES_ACTIVEproduction8 servicios

Autenticacion OIDC (todos los servicios Java)

VariableEjemplo produccionServicios
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URIhttps://login.microsoftonline.com/{tid}/v2.08 servicios
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URIhttps://login.microsoftonline.com/{tid}/discovery/v2.0/keys8 servicios
KEYCLOAK_CLIENT_SECRET(secreto — BFF Swagger OAuth)BFF

BFF (ws-pprx-bff)

VariableEjemplo produccion
WS_CENTERS_URLhttp://ws-pprx-centers:8091
WS_SHIPMENTS_URLhttp://ws-pprx-shipments:8092
WS_USERS_URLhttp://ws-pprx-users:8093
WS_NOTIFICATIONS_URLhttp://ws-pprx-notifications:8094
WS_ISSUES_URLhttp://ws-pprx-issues:8096
ADAPTER_SERVICE_URLhttp://ws-pprx-adapter:8086
MINIO_ENDPOINTAzure Blob endpoint
MINIO_ACCESS_KEY(secreto)
MINIO_SECRET_KEY(secreto)
MINIO_PROFILE_BUCKETproximiti-profile-photos
MINIO_REGIONwesteurope
CORS_ALLOWED_ORIGINShttps://app.proximiti.ontime.es

Adaptador (ws-pprx-adapter)

VariableEjemplo produccion
ADAPTER_KANGURO_BASE_URLhttps://api.kanguro.com
ADAPTER_KANGURO_CLIENT_ID(secreto)
ADAPTER_KANGURO_CLIENT_SECRET(secreto)
ADAPTER_KANGURO_WEBHOOK_SECRET(secreto)
ADAPTER_HUBLOCKER_BASE_URLhttps://api.hublocker.com
ADAPTER_HUBLOCKER_API_KEY(secreto)
ADAPTER_HUBLOCKER_WEBHOOK_API_KEY(secreto)
ADAPTER_STALE_THRESHOLD_MINUTES15
ADAPTER_CB_FAILURE_RATE50
ADAPTER_CB_WINDOW_SIZE10

Caducidad (ws-pprx-expired)

VariableEjemplo produccion
EXPIRY_WINDOW_HOURS24
EXPIRY_BATCH_SIZE5000
OUTBOX_BATCH_SIZE200
WS_CENTERS_URLhttp://ws-pprx-centers:8091

Incidencias (ws-pprx-issues)

VariableEjemplo produccion
SUPPORT_CHAT_PROVIDER_URLURL del proveedor de chat real
SUPPORT_CHAT_FALLBACK_MODEMODE_A
ISSUES_SHIPMENTS_BASE_URLhttp://ws-pprx-shipments:8092

Expediciones (ws-pprx-shipments)

VariableEjemplo produccion
PROXIMITI_TRANSIT_DAYS3
PROXIMITI_RETENTION_DAYS7
STORAGE_MINIO_ENDPOINTAzure Blob endpoint
STORAGE_MINIO_ACCESS_KEY(secreto)
STORAGE_MINIO_SECRET_KEY(secreto)
WS_CENTERS_URLhttp://ws-pprx-centers:8091
WS_NOTIFICATIONS_URLhttp://ws-pprx-notifications:8094

Portal cliente (client-portal — compile-time)

VariableEjemplo produccion
VITE_KEYCLOAK_AUTHORITYhttps://login.microsoftonline.com/{tid}/v2.0
VITE_KEYCLOAK_CLIENT_IDApp Registration client ID
VITE_API_BASE_URLhttps://api.proximiti.ontime.es

Flutter apps (compile-time — --dart-define)

VariableEjemplo produccion
BASE_URLhttps://api.proximiti.ontime.es
MINIO_HOSTAzure Blob endpoint
KEYCLOAK_ISSUERhttps://login.microsoftonline.com/{tid}/v2.0

8. Red, CORS y Despliegue

Mapa de puertos

ComponentePuertoProtocoloExposicion
ws-pprx-bff8090HTTPUnico punto de entrada para clientes
ws-pprx-centers8091HTTPSolo red interna
ws-pprx-shipments8092HTTPSolo red interna
ws-pprx-users8093HTTPSolo red interna
ws-pprx-notifications8094HTTPSolo red interna
ws-pprx-expired8095HTTPSolo red interna
ws-pprx-issues8096HTTPSolo red interna
ws-pprx-adapter8086HTTPSolo red interna
stub-kanguro8098HTTPEliminar en produccion
stub-hublocker8097HTTPEliminar en produccion
client-portal80 (nginx)HTTPDetras de CDN/reverse proxy
PostgreSQL5432TCPSolo red interna
MinIO / Azure Blob9000HTTP/HTTPSSolo red interna + CORS para upload
Zipkin9411HTTPSolo red interna (perfil observability)
Prometheus9090HTTPSolo red interna (perfil observability)
Grafana3002HTTPSolo red interna (perfil observability)
Loki3100HTTPSolo red interna (perfil observability)
Keycloak8080HTTPEliminar en produccion (usar Azure AD)
docs-site4173HTTPOpcional — solo desarrollo

CORS

Configuracion actual en BFF:

yaml
cors:
  allowed-origins: http://localhost:3000,http://localhost:5173
  allowed-methods: GET,POST,PUT,DELETE,PATCH,OPTIONS
  allowed-headers: "*"
  allow-credentials: true

Produccion: cambiar allowed-origins a dominios reales (https://app.proximiti.ontime.es). Los headers expuestos (ETag, Location, X-Correlation-Id, Retry-After) deben mantenerse.

Health checks

Todos los servicios Java exponen:

EndpointFuncionUso
/actuator/healthHealth generalMonitoreo
/actuator/health/liveLiveness probeK8s liveness
/actuator/health/readyReadiness probe (DB + disk)K8s readiness
/actuator/metricsMetricas MicrometerPrometheus scraping
/actuator/prometheusMetricas formato PrometheusPrometheus scraping

Rate limiting

Solo aplicado a endpoints del PUDO selector widget (acceso publico):

ParametroValor
Per-IP burst60 requests
Per-IP sustained300 requests / 5 min
Per-subject (autenticado)120 requests

Infraestructura NO incluida (debe implementarse para produccion)

ElementoDescripcionPrioridad
SSL/TLS terminationCertificados HTTPS para BFF y portalCritico
Reverse proxy / load balancerNginx, Azure Application Gateway, o equivalenteCritico
Kubernetes manifestsDeployments, Services, Ingress, HPAAlta
Secrets managementAzure Key Vault o equivalenteCritico
Log aggregationLoki + Promtail implementado en dev; produccion requiere almacenamiento persistenteAlta
APM / monitoringPrometheus + Grafana implementado en dev; produccion requiere alertas y retencionAlta
Database backupspg_dump automatizado o Azure BackupAlta
CI/CD pipelineBuild, test, deploy automatizadoAlta
Container registryAzure Container Registry o equivalenteAlta
DNSRegistros A/CNAME para dominios publicosCritico

9. Chat de Soporte (Stub)

Estado actual

SupportChatService en ws-pprx-issues devuelve un token falso para inicializar sesiones de chat.

Configuracion:

yaml
support:
  chat:
    provider-url: http://stub-chat:8099  # No existe — retorna fake token
    fallback-mode: MODE_A

Para produccion

Seleccionar un proveedor de chat (Zendesk, Intercom, LiveChat, etc.) e implementar el client real en SupportChatService. La interfaz ya espera un ChatTokenResponse con token + URL de sesion.


10. Acciones Prioritarias para Go-Live

Critico (bloquea produccion)

AccionComponentesEsfuerzo
Migrar autenticacion a Azure AD8 servicios Java + React + 2 Flutter2-3 semanas
Implementar client HTTP real para ALINAws-pprx-expired1 semana
Implementar client HTTP real para NOVAws-pprx-notifications1 semana
SSL/TLS termination + reverse proxyInfraestructura1 semana
Secrets management (Azure Key Vault)Todos los servicios1 semana
Configurar CORS con dominios de produccionws-pprx-bff1 dia
Registrar bundle IDs Flutter en Azure ADApps Flutter1 dia
Configurar X-Frame-Options (re-enable)ws-pprx-bff SecurityConfig1 dia

Alta prioridad (primera semana post-launch)

AccionComponentesEsfuerzo
Implementar AzureBlobStorageAdapterws-pprx-shipments, ws-pprx-centers1-2 semanas
Kubernetes manifests + HPAInfraestructura2 semanas
Credenciales DB de produccionPostgreSQL + todos los servicios1 dia
Publicar apps en stores (TestFlight, Play Console)Flutter apps1 semana
Log aggregation — almacenamiento persistente para LokiInfraestructura2-3 dias
Monitoring — reglas de alerta en Grafana + retencion PrometheusInfraestructura1 semana
Metricas de negocio custom + spans personalizadosServicios Java1 semana

Media prioridad (primer mes)

AccionComponentesEsfuerzo
Validar integracion real con Kangurows-pprx-adapter2-3 dias
Validar integracion real con Hublockerws-pprx-adapter2-3 dias
Proveedor de chat realws-pprx-issues1 semana
Backups automatizados de BDPostgreSQL2 dias
Rate limiting avanzado (API Gateway)Infraestructura1 semana
Push notifications (FCM / APNs)Flutter apps + ws-pprx-notifications2 semanas

Baja prioridad (roadmap futuro)

AccionComponentesEsfuerzo
Migracion a Oracle (si requerido)Toda la BD + ORMs3-6 meses
Dark modeReact + Flutter apps2 semanas
Tests unitarios Flutter (cobertura >80%)Flutter apps2-3 semanas
Flutter web buildsFlutter apps (bloqueado por mobile_scanner)Dependencia externa
Internacionalizacion completa (5 idiomas)React + Flutter apps2-3 semanas

Ecosistema PUDO de PROXIMITI — documentacion interna