Kevin_Ramirez b9a0c55719 fix(observability): RequestLoggingMiddleware debe envolver a Tenant/License
Estaba registrado antes que Tenant/License, así que su cronómetro arrancaba
DESPUÉS de que ambos ya habían corrido — el Duration: en los logs nunca
incluyó el costo de verify-license/auth-me contra el Hub, dando la falsa
impresión de que todo respondía en 2-5ms. Reordenado para que sea el más
externo de los tres (CORS sigue siendo el más externo de todos).
2026-07-21 16:32:27 -05:00
2026-07-21 13:59:00 -05:00
2026-07-21 13:59:00 -05:00
2026-07-21 13:59:00 -05:00
2026-07-21 13:59:00 -05:00

Plantilla Workspace — Aduanasoft

Plantilla base para nuevos proyectos del ecosistema Workspace de Aduanasoft. Incluye autenticación SSO con Keycloak/Hub, arquitectura multi-tenant, y un dashboard funcional listo para extender.


Stack

Capa Tecnología
Frontend SvelteKit 5 + Tailwind CSS
Backend FastAPI + SQLAlchemy + PostgreSQL
Auth Keycloak (OpenID Connect) vía Workspace Hub
Cache / Queue Valkey (Redis) + Celery
Storage MinIO (S3-compatible)
Contenedores Docker Compose

Estructura del proyecto

├── backend/
│   ├── api/v1/modules/
│   │   ├── core/          # Auth, usuarios, tenants, permisos, licencias
│   │   └── example/       # Módulo de referencia — copia y renombra
│   ├── core/              # Config, seguridad, DB, middleware
│   └── alembic/           # Migraciones (solo esquema core)
│
├── frontend/
│   ├── src/routes/
│   │   ├── auth/          # Callback OAuth2, SSO, logout
│   │   ├── login/         # Login local (dev) o redirect al workspace
│   │   └── dashboard/     # Shell + rutas stub
│   └── src/lib/
│       ├── server/        # workspace-auth, workspace-apps, api SSR
│       └── stores/        # company, system, workspace-apps
│
└── scripts/
    └── auth-mode.sh       # Alterna entre modo local y workspace

Inicio rápido

1. Clonar y configurar

git clone https://git.aduanasoft.com/ADUANASOFT/plantillas-proyectos.git mi-proyecto
cd mi-proyecto

Renombrar el proyecto en .env y docker-compose.yml:

  • CORE_DB_NAME=app_coremi_proyecto_core
  • name: app en docker-compose.ymlmi-proyecto

2. Levantar en modo local (sin workspace)

./scripts/auth-mode.sh local
docker compose up -d

Abre http://localhost:5173 → click "Entrar como dev".

3. Conectar al workspace

./scripts/auth-mode.sh workspace
# Pregunta:
#   URL del workspace    → https://workspace.aduanasoft.com
#   Keycloak Realm       → master
#   Keycloak Client ID   → nombre-del-client

El equipo del Hub debe registrar la app y agregar el redirect URI: http://localhost:5173/auth/callback


Variables de entorno

El .env usa una sola URL base para derivar toda la configuración del workspace:

# Una variable, todo se deriva de aquí
WORKSPACE_URL=https://workspace.aduanasoft.com
KEYCLOAK_REALM=master
KEYCLOAK_CLIENT_ID=mi-app-frontend

# Auth local (desarrollo sin workspace)
DEV_LOCAL_AUTH=False   # True = botón "Entrar como dev"
SECRET_KEY=...         # Se genera automáticamente con auth-mode.sh local

El docker-compose.yml construye automáticamente:

  • HUB_URL = ${WORKSPACE_URL}
  • VITE_KEYCLOAK_URL = ${WORKSPACE_URL}/kcauth

Agregar un módulo nuevo

Backend

Copia backend/api/v1/modules/example/ y renombra:

my_module/
├── __init__.py
├── models.py    # SQLAlchemy — hereda TenantScopedMixin + TimestampMixin
├── dto.py       # Pydantic v2 — Request / Response separados
├── service.py   # Lógica de negocio, recibe db + tenant_id + company_id
└── routes.py    # FastAPI router, usa Depends(get_current_user)

Registrar en backend/api/v1/router.py:

from .modules.my_module.routes import router as my_router
router.include_router(my_router, prefix="/my-module", tags=["my-module"])

Frontend

Crear frontend/src/routes/dashboard/my-module/+page.svelte y agregar al sidebar en frontend/src/lib/components/sidebar/modules.ts:

{ title: 'Mi módulo', url: '/dashboard/my-module', icon: MyIcon }

Script auth-mode

./scripts/auth-mode.sh status     # Ver modo actual
./scripts/auth-mode.sh local      # Activar login local (dev sin workspace)
./scripts/auth-mode.sh workspace  # Configurar y conectar al workspace

Al cambiar de modo el script pregunta si reiniciar los contenedores automáticamente.


Convenciones

  • Commits: Conventional Commits (feat:, fix:, refactor:, chore:)
  • Branches: feature/DESC, fix/DESC
  • Nombres en código: inglés; comentarios de lógica de negocio en español
  • Backend: Pydantic v2, async por default, routers por dominio
  • Frontend: SvelteKit 5 runes ($state, $derived, $effect), Tailwind utility-first
Description
No description provided
Readme 11 MiB
Languages
Python 45.8%
Svelte 19%
HTML 17.3%
TypeScript 16.8%
Shell 0.6%
Other 0.4%