# Propuesta de Arquitectura Técnica — Gobierno360

> SaaS de gestión municipal + despacho policial para ciudades inteligentes. Multi-tenant, tiempo real, GIS, apps móviles, soporte en tailandés.

---

## 1. Resumen Ejecutivo

Gobierno360 es una plataforma SaaS que centraliza la operación municipal y el despacho policial. Requiere:
- **Multi-tenancy** por municipio/ciudad
- **Tiempo real** para incidentes y unidades en campo
- **GIS** para mapas, geocercas y rutas
- **Móvil** para policías y supervisores
- **Multilenguaje** incluyendo tailandés

La arquitectura prioriza simplicidad operativa, bajo costo de infraestructura y escalabilidad horizontal cuando sea necesario.

---

## 2. Stack Tecnológico

### 2.1 Frontend Web
**Next.js 14+ (App Router)**
- **Razón:** SSR/SSG híbrido, rutas API integradas, optimización de imágenes, React Server Components. Astro es excelente para contenido estático, pero Next.js gana para dashboards interactivos con estado complejo, tablas, formularios y mapas.
- **UI:** TailwindCSS + shadcn/ui para componentes accesibles
- **Mapas:** MapLibre GL (open source, sin licencia) o Leaflet para funcionalidades GIS básicas
- **I18n:** next-intl para tailandés, español e inglés (RTL si se expande)
- **Estado:** Zustand para cliente, React Query (TanStack Query) para servidor

### 2.2 Backend
**Node.js + Express / Fastify**
- **Razón:** Node.js es la elección pragmática cuando el frontend es Next.js. Comparte tipos (TypeScript), un solo ecosistema npm, y permite SSR colocation en Vercel/Node si se despliega junto. Fastify es más rápido que Express; Express tiene más middleware maduro.
- **Alternativa Python/FastAPI:** FastAPI es superior para ciencia de datos/ML, pero Gobierno360 es principalmente CRUD + tiempo real + GIS. Node.js reduce context-switching del equipo.
- **API:** REST para CRUD, WebSocket/SSE para tiempo real
- **Validación:** Zod (comparte schemas con frontend)

### 2.3 Base de Datos
**PostgreSQL 16 + PostGIS**
- **Razón:** Postgres es el estándar para SaaS. PostGIS añade soporte GIS nativo (puntos, polígonos, distancias, índices espaciales). JSONB para campos flexibles por tenant.
- **Multi-tenancy:** Row-Level Security (RLS) + campo `tenant_id` en cada tabla. Más simple que schemas separados o bases separadas.
- **Migraciones:** Drizzle ORM (TypeScript-first, ligero, tipos seguros) o Prisma. Drizzle es más performante y sin generación de cliente pesado.

### 2.4 Caché y Sesiones
**Redis 7**
- Sesiones, rate limiting, caché de queries GIS frecuentes, pub/sub para eventos entre instancias Node.js
- **Razón:** Ligero, omnipresente, excelente soporte en cloud providers

### 2.5 Tiempo Real
**Socket.IO** (sobre Node.js + Redis adapter)
- WebSocket con fallback a SSE/long-polling
- Salas por tenant y por incidente para aislamiento multi-tenant
- Eventos: ubicación de unidades, nuevo incidente, cambio de estado, alertas

### 2.6 Autenticación y Autorización
**Clerk** (managed) o **Lucia + OAuth** (self-hosted)
- Clerk reduce tiempo de desarrollo: MFA, SSO, roles, sesiones, webhooks
- Roles: Superadmin (plataforma), Admin Municipal, Supervisor, Oficial, Ciudadano
- **Razón:** Clerk es rentable para SaaS B2B. Si requiere on-premise total, usar Lucia + argon2 + OAuth.

### 2.7 Almacenamiento de Archivos
**AWS S3 / MinIO** con presigned URLs
- Fotos de incidentes, evidencias, documentos ciudadanos
- **Razón:** MinIO es compatible S3 si se necesita self-hosted

### 2.8 Colas y Background Jobs
**BullMQ** (Redis-based)
- Notificaciones push, generación de reportes, sincronización de datos GIS
- **Razón:** Mismo stack Node.js, buena observabilidad

### 2.9 Búsqueda
**PostgreSQL Full-Text Search**
- Para búsquedas de ciudadanos, incidentes y documentos
- **Razón:** Evita añadir Elasticsearch hasta que sea realmente necesario. Postgres FTS en tailandés requiere configuración de diccionarios.

### 2.10 Mobile
**Expo + React Native**
- **Razón:** Una sola codebase para iOS y Android. Reutiliza lógica de negocio y componentes de React. Geolocalización nativa, push notifications, cámara para evidencias.
- **Alternativa PWA:** Descartada. Policías en campo necesitan confiabilidad offline-first, push garantizado y acceso nativo a GPS/cámara. PWA tiene limitaciones en iOS.
- **Offline:** WatermelonDB o RxDB para sincronización offline-first de incidentes y formularios

---

## 3. Modelo de Datos (Overview)

```
Tenant
├── id, slug, name, config_jsonb, region, timezone, locale

User
├── id, tenant_id, email, role, name, phone, badge_number, department

Unit (patrulla/vehículo)
├── id, tenant_id, unit_code, type, status, current_lat, current_lng, last_seen_at

Incident
├── id, tenant_id, reporter_id, type, priority, status, lat, lng
├── address, description, assigned_unit_id, created_at, resolved_at
├── geom (PostGIS POINT), geofence_id

Dispatch
├── id, tenant_id, incident_id, unit_id, dispatched_at, arrived_at, closed_at
├── status (dispatched | arrived | en_route | closed)

Geofence
├── id, tenant_id, name, type (restriction | alert | zone)
├── geom (PostGIS POLYGON), alert_rules_jsonb

CitizenReport
├── id, tenant_id, citizen_phone, category, lat, lng, media_urls
├── status, created_at

AuditLog
├── id, tenant_id, user_id, action, entity, entity_id, metadata_jsonb, created_at
```

**Índices clave:**
- `tenant_id` en todas las tablas + índice compuesto con `created_at`
- Índice espacial GIST en `geom` para Incident y Geofence
- Full-text index en `Incident.description` y `CitizenReport` (tailandés requiere `text search dictionary`)

---

## 4. Arquitectura de Despliegue

### 4.1 Infraestructura (Docker + Kubernetes)

**Razón:** Docker es obligatorio. Kubernetes solo si se espera >10 tenants con alta carga. Para inicio, Docker Compose en VPS o PaaS (Railway, Render, Fly.io) es más pragmático. El diagrama describe K8s como objetivo a mediano plazo.

```
┌─────────────────────────────────────────────────────────────┐
│                         CDN (CloudFront)                     │
│              Next.js static assets + S3 media                │
└────────────────────┬──────────────────────────────────────────┘
                     │
┌────────────────────▼──────────────────────────────────────────┐
│                     Ingress Controller (NGINX)                 │
│              SSL termination, rate limiting, routing             │
└────────────────────┬──────────────────────────────────────────┘
                     │
       ┌─────────────┼─────────────┐
       │             │             │
┌──────▼────┐  ┌─────▼─────┐  ┌────▼─────┐
│ Next.js   │  │  Node.js  │  │ Node.js  │
│ Web App   │  │  API #1   │  │  API #2  │
│ (Pods x3) │  │ (Pods x3) │  │(Pods x3) │
└───────────┘  └─────┬─────┘  └────┬─────┘
                     │              │
                     └──────┬───────┘
                            │
              ┌─────────────▼─────────────┐
              │    PostgreSQL + PostGIS     │
              │      (Primary + Replica)    │
              └─────────────┬─────────────┘
                            │
              ┌─────────────▼─────────────┐
              │        Redis Cluster       │
              │  (Sessions, Cache, PubSub) │
              └───────────────────────────┘
```

### 4.2 Servicios Cloud sugeridos (costo-eficiente)

| Capa | Servicio | Alternativa self-hosted |
|------|----------|------------------------|
| Frontend | Vercel / Cloudflare Pages | NGINX en VPS |
| API | Railway / Render / Fly.io | VPS + Docker Compose |
| DB | AWS RDS Postgres + PostGIS / Supabase | VPS + Postgres |
| Cache | Upstash Redis / AWS ElastiCache | Redis Docker |
| Storage | AWS S3 / Cloudflare R2 | MinIO |
| Auth | Clerk | Lucia + Postgres |
| Mobile builds | EAS Build (Expo) | GitHub Actions + self-hosted runner |
| Monitoreo | Datadog / Sentry | Grafana + Loki + Prometheus |

---

## 5. Multi-Tenancy: Estrategia

**Row-Level Security (RLS) — Isolation Lógica**
- Cada tabla tiene `tenant_id` NOT NULL
- Políticas RLS: `current_setting('app.current_tenant')::uuid = tenant_id`
- El backend establece el tenant por request según el JWT o subdomain

**Ventajas:**
- Una sola base de datos, backups simples
- Escalado horizontal sin shards complejos
- Query performance aceptable con índices correctos hasta ~1000 tenants activos

**Alternativa (futuro):** Schemas separados por tenant si se requiere aislamiento físico para gobiernos con compliance estricto.

---

## 6. Tiempo Real: Flujo de Incidentes

```
Ciudadano reporta -> POST /api/incidents
                      -> Guarda en Postgres
                      -> Pub a Redis: "incident:new:{tenant_id}"
                      -> Socket.IO room "tenant:{tenant_id}" broadcast
                      -> Notificación push a unidades disponibles vía Expo

Unidad acepta -> PATCH /api/dispatches/{id}
                 -> Actualiza estado
                 -> Socket.IO broadcast a room del incidente
                 -> Ciudadano recibe actualización en app/web

Ubicación unidad -> POST /api/tracking (cada 5s)
                    -> Redis Geo (geospatial) para posición actual
                    -> Socket.IO broadcast a supervisores
```

---

## 7. Mobile (React Native / Expo)

**Módulos:**
- **Autenticación:** Expo SecureStore para tokens
- **Mapa:** react-native-mapbox-gl o react-native-maps
- **GPS:** expo-location en background (geofencing de unidades)
- **Cámara:** expo-camera para evidencias
- **Offline:** WatermelonDB para crear incidentes offline, sincronizar al recuperar red
- **Push:** expo-notifications

**Flujo offline-first:**
1. Oficial crea reporte sin red -> WatermelonDB local
2. Al recuperar conexión -> sync queue -> API -> confirmación -> limpia local

---

## 8. Seguridad y Compliance

- **TLS 1.3** en todo tráfico
- **Hash:** argon2id para contraseñas (si self-hosted)
- **RBAC:** middleware por rol en cada endpoint
- **Audit logs:** todas las mutaciones de incidentes y usuarios
- **Rate limiting:** Redis-based por IP y por usuario
- **GDPR/PDPA Tailandia:** soft deletes, export de datos por tenant, retención configurable
- **Backup:** pg_dump diario + WAL-E/WAL-G para point-in-time recovery

---

## 9. Roadmap de Evolución

| Fase | Enfoque |
|------|---------|
| **MVP (0-3 meses)** | Next.js + Express + Postgres + Redis en VPS. Single-tenant. Web dashboard + mobile básica. |
| **Beta (3-6 meses)** | Multi-tenant RLS, Socket.IO tiempo real, Expo app con offline-first. |
| **Producción (6-12 meses)** | K8s, read replicas Postgres, CDN, CI/CD automatizado, monitoreo. |
| **Escala (>12 meses)** | Sharding por región (Tailandia / LATAM), edge functions para mapas, ML para predicción de incidentes. |

---

## 10. Decisiones Clave y Trade-offs

| Decisión | Alternativa descartada | Por qué |
|----------|----------------------|---------|
| Next.js | Astro | Dashboards interactivos necesitan React full, no islands architecture |
| Node.js | Python/FastAPI | Unificación de stack, SSR colocation, ecosistema SaaS maduro |
| Postgres + PostGIS | MongoDB + GeoJSON | Transacciones ACID, RLS, GIS maduro, operadores espaciales |
| React Native | Flutter/PWA | Reutiliza conocimiento React del equipo web. PWA limitado para iOS/cámara/GPS |
| Socket.IO | SSE puro / Ably | Socket.IO da rooms, fallback y reconexión gratis. Ably es costoso a escala |
| Clerk | Auth0/Keycloak | Clerk es más rápido de integrar para SaaS B2B con roles |
| K8s (objetivo) | Nomad / Docker Swarm | K8s es el estándar, hiring más fácil, managed services everywhere |

---

## 11. Estimación de Infraestructura Inicial (MVP)

- **VPS:** 2 vCPU / 4GB RAM (Hetzner ~€6/mes o DigitalOcean $24/mes)
- **Postgres:** 1 vCPU / 2GB RAM compartido o managed Supabase Free/Pro
- **Redis:** Upstash Free o contenedor compartido
- **S3/MinIO:** ~$5/mes para <100GB
- **Clerk:** Free tier hasta 10k MAU
- **Vercel:** Pro ($20/mes) para equipo
- **Expo:** Free tier EAS
- **Dominio + SSL:** $12/año + Let's Encrypt

**Total MVP estimado: $50-80/mes**

---

*Documento generado para Gobierno360. Revisar y ajustar según restricciones de compliance y presupuesto del cliente.*
