600 lines
25 KiB
Markdown
600 lines
25 KiB
Markdown
# Anexo76 - Resumen de Arquitectura Técnica
|
|
|
|
## 📋 Índice
|
|
1. [Visión General](#visión-general)
|
|
2. [Stack Tecnológico](#stack-tecnológico)
|
|
3. [Arquitectura del Sistema](#arquitectura-del-sistema)
|
|
4. [Arquitectura de Schemas y Módulos](#arquitectura-de-schemas-y-módulos)
|
|
5. [Estructura del Proyecto](#estructura-del-proyecto)
|
|
6. [Flujos Principales](#flujos-principales)
|
|
7. [Seguridad](#seguridad)
|
|
8. [Base de Datos](#base-de-datos)
|
|
9. [API Reference](#api-reference)
|
|
|
|
---
|
|
|
|
## Visión General
|
|
|
|
Anexo76 es una aplicación SaaS multi-tenant para gestión de comercio exterior en México, enfocada en cumplir con los Anexos 24, 31 y 22 del SAT.
|
|
|
|
### Objetivos de Negocio
|
|
- Gestión de inventarios para maquilas e IMMEX
|
|
- Control de pedimentos aduanales
|
|
- Manejo de facturas de importación/exportación
|
|
- Cumplimiento normativo SAT
|
|
- Licenciamiento flexible por planes
|
|
|
|
---
|
|
|
|
## Stack Tecnológico
|
|
|
|
### Backend
|
|
- **Framework**: FastAPI 0.110+ (Python 3.11+)
|
|
- **ORM**: SQLAlchemy 2.0
|
|
- **Autenticación**: Keycloak (OpenID Connect)
|
|
- **Base de Datos**: PostgreSQL 15+
|
|
- **Validación**: Pydantic 2.6+
|
|
- **Testing**: Pytest
|
|
|
|
### Frontend
|
|
- **Framework**: SvelteKit 2.0+ (Svelte 5)
|
|
- **Lenguaje**: TypeScript
|
|
- **Auth Client**: keycloak-js
|
|
- **Estilos**: TailwindCSS 4.1+
|
|
- **Build**: Vite 7+
|
|
|
|
### Infraestructura
|
|
- **Containerización**: Docker / Docker Compose
|
|
- **Orquestación**: Kubernetes (futuro)
|
|
- **CI/CD**: GitHub Actions / GitLab CI
|
|
- **Monitoreo**: Prometheus + Grafana
|
|
|
|
---
|
|
|
|
## Arquitectura del Sistema
|
|
|
|
### Patrón Arquitectónico: Modular Layered (estilo NestJS)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ FRONTEND │
|
|
│ SvelteKit + Keycloak-js + TailwindCSS │
|
|
└────────────────┬────────────────────────────────────────┘
|
|
│ HTTP/REST + JWT
|
|
┌────────────────▼────────────────────────────────────────┐
|
|
│ API GATEWAY (FastAPI) │
|
|
│ Middleware: Tenant | License | Logging | CORS │
|
|
└────────────────┬────────────────────────────────────────┘
|
|
│
|
|
┌────────┴────────┐
|
|
│ │
|
|
┌───────▼──────┐ ┌──────▼────────┐
|
|
│ MODULES │ │ CORE LAYER │
|
|
│ │ │ │
|
|
│ • auth │ │ • config.py │
|
|
│ • tenants │ │ • database.py │
|
|
│ • licenses │ │ • security.py │
|
|
│ • ... │ │ • middleware │
|
|
└───────┬──────┘ └───────────────┘
|
|
│
|
|
┌───────▼──────────────────────────┐
|
|
│ DATABASE LAYER (Multi-tenant) │
|
|
│ │
|
|
│ ┌──────────┐ ┌──────────────┐ │
|
|
│ │ Core DB │ │ Tenant 1 DB │ │
|
|
│ │ (shared) │ │ (dedicated) │ │
|
|
│ └──────────┘ └──────────────┘ │
|
|
└──────────────────────────────────┘
|
|
```
|
|
|
|
### Estructura Modular (por módulo)
|
|
|
|
Cada módulo sigue el patrón:
|
|
|
|
```
|
|
modules/{module_name}/
|
|
├── models.py # ORM Models (SQLAlchemy)
|
|
├── dto.py # Data Transfer Objects (Pydantic)
|
|
├── service.py # Business Logic Layer
|
|
├── routes.py # API Endpoints (FastAPI)
|
|
└── __init__.py # Module exports
|
|
```
|
|
|
|
#### Responsabilidades por Capa
|
|
|
|
1. **models.py**: Representación de entidades en BD
|
|
- Define tablas con SQLAlchemy
|
|
- Relaciones entre entidades
|
|
- Constraints y validaciones a nivel DB
|
|
|
|
2. **dto.py**: Contratos de entrada/salida de datos
|
|
- DTOs de request (CreateDTO, UpdateDTO)
|
|
- DTOs de response (ResponseDTO)
|
|
- Validaciones de Pydantic
|
|
|
|
3. **service.py**: Lógica de negocio
|
|
- Operaciones CRUD
|
|
- Validaciones de negocio
|
|
- Orquestación de operaciones complejas
|
|
|
|
4. **routes.py**: Exposición HTTP
|
|
- Definición de endpoints
|
|
- Documentación OpenAPI automática
|
|
- Manejo de dependencias (auth, db)
|
|
|
|
---
|
|
|
|
## Arquitectura de Schemas y Módulos
|
|
|
|
### Estructura de Schemas en Base de Datos
|
|
|
|
La aplicación utiliza una arquitectura de schemas para organizar lógicamente las tablas según su funcionalidad y alcance:
|
|
|
|
#### **Schema `a24` (Anexo 24)**
|
|
Contiene todas las tablas relacionadas con el **Anexo 24 del SAT** (control de inventarios para empresas IMMEX):
|
|
- Gestión de inventarios
|
|
- Control de entradas y salidas de mercancías
|
|
- Reportes de existencias
|
|
- Cumplimiento de obligaciones fiscales del Anexo 24
|
|
|
|
#### **Schema `a76` (Anexo 76)**
|
|
Contiene todas las tablas relacionadas con el **Anexo 76 del SAT** (comercio exterior):
|
|
- Pedimentos aduanales
|
|
- Facturas de importación/exportación
|
|
- Documentación de comercio exterior
|
|
- Cumplimiento normativo de comercio exterior
|
|
|
|
#### **Schema `public` (Catálogos Fijos)**
|
|
Contiene **catálogos compartidos** y datos de referencia que no cambian frecuentemente:
|
|
- Catálogos del SAT (tipos de material, unidades de medida, etc.)
|
|
- Códigos de país
|
|
- Catálogos de aduanas
|
|
- Tipos de documento
|
|
- Datos maestros compartidos entre módulos
|
|
|
|
### Convención de Prefijos de Tablas
|
|
|
|
Para mantener claridad y trazabilidad, las tablas utilizan prefijos que identifican su módulo funcional:
|
|
|
|
#### **Prefijo `inv_` (Inventarios)**
|
|
Tablas relacionadas con el **control de inventarios**:
|
|
- `inv_products`: Productos en inventario
|
|
- `inv_movements`: Movimientos de entrada/salida
|
|
- `inv_warehouses`: Almacenes
|
|
- `inv_balances`: Saldos de inventario
|
|
|
|
**Nota histórica**: Anteriormente se utilizaba el prefijo `s` (SCAII - Sistema de aduanas e Inventarios).
|
|
|
|
#### **Prefijo `fa_` (Fixed Assets / Activos Fijos)**
|
|
Tablas relacionadas con la **gestión de activos fijos**:
|
|
- `fa_assets`: Registro de activos fijos
|
|
- `fa_depreciation`: Depreciación de activos
|
|
- `fa_maintenance`: Mantenimiento de activos
|
|
- `fa_transfers`: Transferencias de activos
|
|
|
|
**Nota histórica**: Anteriormente se utilizaba el prefijo `q` (SCAF - Sistema de Control de Activos Fijos).
|
|
|
|
### Diagrama de Arquitectura de Schemas
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ DATABASE: anexo76_db │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │
|
|
│ │ Schema: a24 │ │ Schema: a76 │ │Schema: public │ │
|
|
│ │ (Anexo 24) │ │ (Anexo 76) │ │ (Catálogos) │ │
|
|
│ ├────────────────┤ ├────────────────┤ ├───────────────┤ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ inv_products │ │ pedimentos │ │ material_types│ │
|
|
│ │ inv_movements │ │ facturas │ │ uom_codes │ │
|
|
│ │ inv_warehouses │ │ customs_docs │ │ countries │ │
|
|
│ │ inv_balances │ │ export_ops │ │ customs_list │ │
|
|
│ │ │ │ │ │ document_types│ │
|
|
│ │ fa_assets │ │ │ │ │ │
|
|
│ │ fa_depreciation│ │ │ │ │ │
|
|
│ │ fa_maintenance │ │ │ │ │ │
|
|
│ │ fa_transfers │ │ │ │ │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ └────────────────┘ └────────────────┘ └───────────────┘ │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Ventajas de esta Arquitectura
|
|
|
|
1. **Separación Lógica**: Cada schema representa un dominio específico del negocio
|
|
2. **Escalabilidad**: Facilita la adición de nuevos módulos sin afectar los existentes
|
|
3. **Seguridad**: Permite aplicar permisos a nivel de schema
|
|
4. **Mantenibilidad**: Código y migraciones organizados por dominio
|
|
5. **Claridad**: Los prefijos hacen evidente la funcionalidad de cada tabla
|
|
6. **Migración Gradual**: Permite actualizar sistemas legados (SCAII/SCAF) sin interrupciones
|
|
|
|
### Mapeo de Sistemas Legados
|
|
|
|
| Sistema Legacy | Prefijo Antiguo | Sistema Nuevo | Prefijo Nuevo | Schema |
|
|
|----------------------|-----------------|-------------------|---------------|----------|
|
|
| SCAII (Inventarios) | `s` | Inventarios | `inv_` | `a24` |
|
|
| SCAF (Activos Fijos) | `q` | Fixed Assets | `fa_` | `a24` |
|
|
| Winsaii (Pedimentos) | `w` | - | - | `a22` |
|
|
| - | `g` | Comercio Exterior | - | `a76` |
|
|
| - | `g` | Catálogos SAT | - | `public` |
|
|
|
|
---
|
|
|
|
## Estructura del Proyecto
|
|
|
|
```
|
|
anexo76/
|
|
├── backend/
|
|
│ ├── main.py # Aplicación FastAPI principal
|
|
│ ├── requirements.txt # Dependencias
|
|
│ ├── init_db.py # Script de inicialización
|
|
│ ├── Dockerfile
|
|
│ │
|
|
│ ├── core/ # Capa core (shared)
|
|
│ │ ├── config.py # Configuración (Pydantic Settings)
|
|
│ │ ├── database.py # Gestión de BD multi-tenant
|
|
│ │ ├── security.py # Auth Keycloak + JWT
|
|
│ │ ├── middleware.py # Middlewares personalizados
|
|
│ │ └── __init__.py
|
|
│ │
|
|
│ └── api/
|
|
│ └── v1/
|
|
│ ├── router.py # Router principal v1
|
|
│ ├── common/ # Utilidades compartidas
|
|
│ │ ├── base_models.py
|
|
│ │ ├── crud_routes.py
|
|
│ │ ├── dto_mixins.py
|
|
│ │ └── tenant_crud_routes.py
|
|
│ │
|
|
│ └── modules/ # Módulos de negocio por schema
|
|
│ ├── a24/ # Módulo Anexo 24 (Inventarios)
|
|
│ │ ├── inventarios/
|
|
│ │ └── activos_fijos/
|
|
│ │
|
|
│ ├── a76/ # Módulo Anexo 76 (Comercio Exterior)
|
|
│ │ ├── pedimentos/
|
|
│ │ └── facturas/
|
|
│ │
|
|
│ └── public/ # Catálogos compartidos
|
|
│ ├── material_types/
|
|
│ ├── uom_codes/
|
|
│ └── countries/
|
|
│
|
|
├── frontend/
|
|
│ ├── src/
|
|
│ │ ├── routes/ # Páginas SvelteKit
|
|
│ │ │ ├── +layout.svelte # Layout global con Keycloak
|
|
│ │ │ ├── +page.svelte # Dashboard principal
|
|
│ │ │ └── callback/ # OAuth callback
|
|
│ │ │
|
|
│ │ └── lib/
|
|
│ │ ├── auth.ts # Servicio de autenticación
|
|
│ │ └── api.ts # Cliente API
|
|
│ │
|
|
│ ├── static/
|
|
│ │ └── silent-check-sso.html
|
|
│ ├── package.json
|
|
│ └── Dockerfile
|
|
│
|
|
├── docs/
|
|
│ ├── KEYCLOAK_SETUP.md # Guía de configuración
|
|
│ └── ARCHITECTURE.md # Este documento
|
|
│
|
|
├── docker-compose.yml # Orquestación completa
|
|
├── start.sh # Script de inicio rápido
|
|
├── README.md # Documentación principal
|
|
└── .gitignore
|
|
```
|
|
|
|
---
|
|
|
|
## Flujos Principales
|
|
|
|
### 1. Flujo de Autenticación
|
|
|
|
```
|
|
┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
│ Frontend │ │ Keycloak │ │ Backend │
|
|
└────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
│ │ │
|
|
│ 1. Clic "Login" │ │
|
|
├────────────────────────────>│ │
|
|
│ │ │
|
|
│ 2. Formulario de login │ │
|
|
│<────────────────────────────┤ │
|
|
│ │ │
|
|
│ 3. Credenciales │ │
|
|
├────────────────────────────>│ │
|
|
│ │ │
|
|
│ 4. Redirigir + auth code │ │
|
|
│<────────────────────────────┤ │
|
|
│ │ │
|
|
│ 5. Intercambiar code x token│ │
|
|
├────────────────────────────>│ │
|
|
│ │ │
|
|
│ 6. JWT (access + refresh) │ │
|
|
│<────────────────────────────┤ │
|
|
│ │ │
|
|
│ 7. Request con Bearer token │ │
|
|
├─────────────────────────────┼──────────────────────────>│
|
|
│ │ │
|
|
│ │ 8. Validar token │
|
|
│ │<──────────────────────────┤
|
|
│ │ │
|
|
│ │ 9. Public key │
|
|
│ ├──────────────────────────>│
|
|
│ │ │
|
|
│ 10. Respuesta con datos │ │
|
|
│<─────────────────────────────┼───────────────────────────┤
|
|
│ │ │
|
|
```
|
|
|
|
### 2. Flujo de Request Multi-tenant
|
|
|
|
```
|
|
Request con JWT
|
|
↓
|
|
TenantMiddleware
|
|
├─ Extrae tenant_id del token
|
|
├─ Valida tenant existe y está activo
|
|
└─ Agrega tenant_id a request.state
|
|
↓
|
|
LicenseValidationMiddleware
|
|
├─ Consulta licencia del tenant
|
|
├─ Valida estado (active/expired)
|
|
├─ Valida fecha de vigencia
|
|
└─ Agrega license_info a request.state
|
|
↓
|
|
Endpoint Handler
|
|
├─ Obtiene tenant_id de request.state
|
|
├─ Selecciona BD (shared o dedicated)
|
|
└─ Procesa request
|
|
↓
|
|
Response
|
|
```
|
|
|
|
### 3. Flujo de Selección de Base de Datos
|
|
|
|
```python
|
|
# Pseudocódigo
|
|
tenant_id = request.state.tenant_id
|
|
|
|
tenant = db.query(Tenant).filter(Tenant.id == tenant_id).first()
|
|
|
|
if tenant.type == "SHARED":
|
|
# Usar BD compartida (core_db)
|
|
db_session = CoreSessionLocal()
|
|
# Queries incluyen tenant_id en WHERE
|
|
|
|
elif tenant.type == "DEDICATED":
|
|
# Usar BD dedicada del tenant
|
|
db_config = json.loads(tenant.db_config)
|
|
db_session = get_tenant_db(tenant_id, db_config)
|
|
# No necesita filtrar por tenant_id
|
|
```
|
|
|
|
---
|
|
|
|
## Seguridad
|
|
|
|
### Autenticación
|
|
- **Keycloak** como Identity Provider
|
|
- **OpenID Connect** (OIDC)
|
|
- **JWT** con RS256 (firma asimétrica)
|
|
- **Refresh tokens** para renovación
|
|
|
|
### Autorización
|
|
- **RBAC** (Role-Based Access Control)
|
|
- Roles: `admin`, `user`, `auditor`, `system`
|
|
- Middleware `has_role()` para proteger endpoints
|
|
|
|
### Multi-tenancy
|
|
- **Aislamiento por tenant_id** en JWT
|
|
- **Row-level security** en BD compartida
|
|
- **BD dedicada** para mayor aislamiento (enterprise)
|
|
|
|
### Row-Level Security (RLS) en BD compartida
|
|
|
|
> Convención alineada al skill `aduanasoft-dev-standards` (sección 10).
|
|
> La capa API sigue siendo responsable del control fino (roles/permisos
|
|
> con Keycloak + `PermissionService`); RLS añade **defensa en profundidad**
|
|
> a nivel de BD para que un bug en un `WHERE` no permita salirse del tenant.
|
|
|
|
#### Variables de sesión (`SET LOCAL`)
|
|
|
|
| GUC | Origen | Comportamiento RLS |
|
|
|-----|--------|--------------------|
|
|
| `app.tenant_id` | JWT (`TenantMiddleware`) → `request.state.tenant_id` | Obligatoria. Si está vacía, `app.current_tenant_id()` retorna `NULL` y las políticas devuelven `0` filas (fail-closed). |
|
|
| `app.company_id` | Header `X-Company-Id` o cookie `active_company_id` | Opcional. Si está vacía, el tenant ve **todas sus compañías** (útil para selectores de compañía y bootstrap). |
|
|
|
|
Ambas se fijan con `SET LOCAL` al inicio de cada transacción —
|
|
**nunca** con `SET` global, para no contaminar conexiones del pool.
|
|
|
|
Helpers SQL definidos por la migración `d1a2b3c4e5f6_enable_rls_tenant_company`:
|
|
|
|
```sql
|
|
CREATE FUNCTION app.current_tenant_id() RETURNS INTEGER LANGUAGE sql STABLE AS
|
|
$$ SELECT NULLIF(current_setting('app.tenant_id', true), '')::INTEGER $$;
|
|
CREATE FUNCTION app.current_company_id() RETURNS INTEGER LANGUAGE sql STABLE AS
|
|
$$ SELECT NULLIF(current_setting('app.company_id', true), '')::INTEGER $$;
|
|
```
|
|
|
|
#### Tipos de política
|
|
|
|
1. **Solo `tenant_id`** (p.ej. `a76.company`, `core.licenses`):
|
|
`tenant_id = app.current_tenant_id()`.
|
|
2. **`tenant_id` + `company_id`** (`TenantScopedMixin`, mayoría de tablas
|
|
`a24/`a76/`core`): además exige `company_id = app.current_company_id()`
|
|
cuando esa GUC está fijada.
|
|
3. **Solo `company_id`** (algunas tablas `a76.company_*`): valida el
|
|
`tenant_id` indirectamente vía `EXISTS` contra `a76.company`.
|
|
|
|
Todas las tablas usan `FORCE ROW LEVEL SECURITY` para que la política
|
|
aplique también al owner. Las únicas tablas core **excluidas** son
|
|
`core.tenants` y `core.user_tenants` — necesarias para el bootstrap del
|
|
selector de tenant antes de tener contexto fijado.
|
|
|
|
#### Propagación del contexto
|
|
|
|
| Camino | Cómo se fija el contexto |
|
|
|--------|--------------------------|
|
|
| HTTP request | `TenantMiddleware` rellena `request.state.tenant_id`/`company_id`; `get_core_db` / `get_async_core_db` leen esos valores y los guardan en `Session.info`. Un listener `after_begin` ejecuta `SET LOCAL` por transacción. |
|
|
| `LicenseValidationMiddleware` | Usa `scoped_core_db(tenant_id=...)` para que la consulta de licencia entre con contexto RLS válido. |
|
|
| Tareas Celery | `track_and_dispatch` inyecta `rls_tenant_id` / `rls_company_id` en los headers del task; los signals `task_prerun`/`task_postrun` los copian a `ContextVar`s del worker, que el listener `after_begin` consume como fallback. Tareas críticas (imports/exports de invoices, expediente) abren la sesión con `scoped_core_db(tenant_id=..., company_id=...)`. |
|
|
| Tests | Las suites de pytest pueden usar `scoped_core_db(...)` o emular el flujo con `set_config('app.tenant_id', ...)` antes del query. Hay un set de tests en `backend/tests/integration/test_rls_tenant_company.py` que valida aislamiento A vs B usando un rol sin `BYPASSRLS`. |
|
|
|
|
#### Reparto de responsabilidades
|
|
|
|
| Capa | Decide |
|
|
|------|--------|
|
|
| **API (FastAPI + Keycloak + `PermissionService`)** | Roles, permisos por compañía, accesos a recursos concretos (`validate_access_to_resource`), reglas de negocio. |
|
|
| **RLS (PostgreSQL)** | Límite estructural duro: `tenant_id` y `company_id`. **No** modela roles/permisos para evitar duplicar lógica fina con la API. |
|
|
|
|
#### Operación / DevOps
|
|
|
|
- En **producción** la API debe conectar con un rol **sin** `BYPASSRLS`
|
|
(`postgres` superusuario lo bypassea por diseño). El `docker-compose.yml`
|
|
de desarrollo usa `postgres` deliberadamente para no romper migraciones;
|
|
los tests crean un rol `anexo76_rls_test` para ejercitar las políticas.
|
|
- Los jobs/ETL/migraciones que necesiten ver todos los tenants deben usar
|
|
un rol técnico explícito con `BYPASSRLS` o fijar `app.tenant_id` por
|
|
iteración — nunca asumir que la sesión global "ve todo".
|
|
- La migración `d1a2b3c4e5f6_enable_rls_tenant_company` tiene `downgrade()`
|
|
completo (drop policies + `DISABLE ROW LEVEL SECURITY`) para revertir.
|
|
|
|
### Validación de Licencias
|
|
- Middleware verifica en cada request:
|
|
- ✓ Licencia activa
|
|
- ✓ No expirada
|
|
- ✓ Límites no excedidos
|
|
|
|
---
|
|
|
|
## Base de Datos
|
|
|
|
### Modelo Híbrido Multi-tenant
|
|
|
|
#### BD Core (Compartida)
|
|
Tablas principales:
|
|
- `tenants`: Información de clientes
|
|
- `licenses`: Control de licencias por tenant
|
|
- `license_usage`: Métricas de uso
|
|
- `users` (futuro): Usuarios por tenant
|
|
|
|
Todas las tablas operacionales incluyen `tenant_id` para segmentación.
|
|
|
|
#### BD Dedicadas (Enterprise)
|
|
- Una BD PostgreSQL por tenant
|
|
- Configuración almacenada en `tenants.db_config`
|
|
- Migración automática desde BD compartida
|
|
|
|
### Ejemplo de Tabla Multi-tenant
|
|
|
|
```sql
|
|
CREATE TABLE inventories (
|
|
id SERIAL PRIMARY KEY,
|
|
tenant_id INTEGER NOT NULL REFERENCES tenants(id),
|
|
product_code VARCHAR(50) NOT NULL,
|
|
quantity INTEGER NOT NULL,
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
|
|
-- Índice compuesto para queries eficientes
|
|
INDEX idx_tenant_product (tenant_id, product_code)
|
|
);
|
|
```
|
|
|
|
### Migración y Upgrade
|
|
|
|
```python
|
|
# Tenant en BD compartida → BD dedicada
|
|
tenant_service.upgrade_to_dedicated(
|
|
tenant_id=123,
|
|
db_config={
|
|
"host": "dedicated-postgres.example.com",
|
|
"port": 5432,
|
|
"name": "tenant_123_db",
|
|
"user": "tenant_123_user",
|
|
"password": "secure_password"
|
|
}
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## API Reference
|
|
|
|
### Módulo: Authentication (`/v1/auth`)
|
|
|
|
| Endpoint | Método | Descripción | Auth |
|
|
|----------|--------|-------------|------|
|
|
| `/auth/login` | POST | Login con Keycloak | Público |
|
|
| `/auth/refresh` | POST | Renovar access token | Público |
|
|
| `/auth/me` | GET | Info del usuario actual | Bearer |
|
|
| `/auth/logout` | POST | Cerrar sesión | Bearer |
|
|
| `/auth/health` | GET | Health check | Público |
|
|
|
|
### Módulo: Tenants (`/v1/tenants`)
|
|
|
|
| Endpoint | Método | Descripción | Rol Requerido |
|
|
|----------|--------|-------------|---------------|
|
|
| `/tenants` | POST | Crear tenant | admin |
|
|
| `/tenants` | GET | Listar tenants | admin |
|
|
| `/tenants/{id}` | GET | Obtener tenant | user |
|
|
| `/tenants/{id}` | PUT | Actualizar tenant | admin |
|
|
| `/tenants/{id}` | DELETE | Eliminar tenant | admin |
|
|
| `/tenants/slug/{slug}` | GET | Obtener por slug | user |
|
|
|
|
### Módulo: Licenses (`/v1/licenses`)
|
|
|
|
| Endpoint | Método | Descripción | Rol Requerido |
|
|
|----------|--------|-------------|---------------|
|
|
| `/licenses` | POST | Crear licencia | admin |
|
|
| `/licenses/tenant/{id}` | GET | Obtener licencia | user |
|
|
| `/licenses/tenant/{id}` | PUT | Actualizar licencia | admin |
|
|
| `/licenses/validate/{id}` | GET | Validar licencia | user |
|
|
| `/licenses/usage/{id}` | GET | Uso de licencia | user |
|
|
| `/licenses/my-license` | GET | Mi licencia | user |
|
|
|
|
### Planes de Licencia
|
|
|
|
| Plan | Usuarios | Storage | Operaciones/mes | Features |
|
|
|------|----------|---------|-----------------|----------|
|
|
| Free | 5 | 10 GB | 1,000 | API básica |
|
|
| Basic | 20 | 50 GB | 10,000 | + Reportes |
|
|
| Professional | 100 | 200 GB | 50,000 | + Integraciones |
|
|
| Enterprise | ∞ | ∞ | ∞ | + Soporte + BD dedicada |
|
|
|
|
---
|
|
|
|
## Próximas Implementaciones
|
|
|
|
### Backend
|
|
- [ ] Módulo de inventarios
|
|
- [ ] Módulo de pedimentos
|
|
- [ ] Módulo de facturas
|
|
- [ ] Webhooks para integraciones
|
|
- [ ] Reportes avanzados
|
|
- [ ] Export/Import de datos
|
|
|
|
### Frontend
|
|
- [ ] Dashboard con gráficas
|
|
- [ ] Gestión de inventarios UI
|
|
- [ ] Formularios de pedimentos
|
|
- [ ] Panel de administración
|
|
- [ ] Reportes interactivos
|
|
|
|
### DevOps
|
|
- [ ] CI/CD pipeline
|
|
- [ ] Tests automatizados
|
|
- [ ] Monitoreo con Prometheus
|
|
- [ ] Dashboards de Grafana
|
|
- [ ] Deploy a Kubernetes
|
|
- [ ] Backup automatizado
|
|
|
|
---
|
|
|
|
**Última actualización**: Octubre 2025
|
|
**Versión del documento**: 1.0
|