Saltar a contenido

Levantar el panel en local y entrar por primera vez

Al final de este tutorial vas a estar mirando la lista real de clientes de Gastro y Travel en tu navegador, con tu propio operador. Toma unos 10 minutos.

Se asume que tienes Docker corriendo y el monorepo clonado. No necesitas saber nada del panel.

1. Levanta la infraestructura compartida

El panel no tiene Postgres propio: usa el compartido del monorepo.

./manage.sh up infra-core
docker ps --format "{{.Names}}" | grep timeliber-postgres

Si no ves timeliber-postgres, el resto no va a funcionar. Revisa el troubleshooting del manual raíz.

2. Comprueba que existe operator_db

Postgres corre los scripts de infra/postgres/init/ solo la primera vez que se inicializa su volumen. Si tu volumen es anterior a que existiera Operator, la base no está:

docker exec timeliber-postgres psql -U timeliber_admin -lqt | grep operator_db

Si no aparece nada, créala corriendo el init a mano:

docker exec -i \
  -e POSTGRES_USER=timeliber_admin -e POSTGRES_DB=postgres \
  -e OPERATOR_DB_USER=operator_user \
  -e OPERATOR_DB_PASSWORD="<el de infra/core/.env>" \
  timeliber-postgres bash < infra/postgres/init/07_operator.sh

Ojo: no es idempotente. Si el rol ya existe, CREATE ROLE falla y el script aborta — correcto, porque el caso "ya está creado" no debería sobreescribir nada en silencio.

Por qué un usuario aislado y no el admin maestro: si el BFF se compromete, el atacante llega hasta operator_users y no un centímetro más. Las bases de las verticales le quedan cerradas — ni siquiera tiene credenciales para ellas.

3. Configura el backend

cd apps/operator/backend
cp .env.example .env

Abre .env y llena tres cosas:

  • OPERATOR_JWT_SECRET — genera uno con openssl rand -hex 32.
  • OPERATOR_DB_PASSWORD y el password dentro de OPERATOR_DATABASE_URL — el mismo que está en infra/core/.env.
  • OPERATOR_GASTRO_INTERNAL_TOKEN y OPERATOR_TRAVEL_INTERNAL_TOKEN — cópialos de GASTRO_INTERNAL_TOKEN (en apps/gastro/backend/.env) e INTERNAL_API_KEY (en apps/travel/backend/.env) respectivamente.

Si dejas un token vacío el panel arranca igual: esa vertical simplemente aparece como caída. Es degradación deliberada, no un error.

La referencia completa de variables está en 03_REFERENCE/environment.md.

4. Levanta el backend

cd ../../..              # raíz del monorepo
./manage.sh up operator_back
curl -s localhost:8012/api/v1/health/live
# {"status":"ok"}

5. Crea tu operador

No hay registro público: el panel administra clientes reales, así que los operadores se siembran a mano.

docker exec -it timeliber-operator-api python -m app.cli create-operator \
  --email tu@correo.com --full-name "Tu Nombre"

Te va a pedir la contraseña por prompt (mínimo 12 caracteres). Se pide por prompt a propósito: pasarla por argumento la dejaría escrita en el historial de tu shell.

6. Abre el panel

Para desarrollo, corre el frontend con Vite apuntando a tu backend local:

cd apps/operator/frontend
npm install
echo 'VITE_API_URL=http://localhost:8012' > .env.local
npm run dev

Abre http://localhost:5173 y entra con el email y la contraseña del paso 5.

./manage.sh up operator_front es otra cosa: construye la imagen nginx de producción, que no publica ningún puerto al host porque se sirve por Traefik en ops.timeliber.com.co. Para mirar el panel en tu máquina, usa npm run dev.

Vas a ver el selector de verticales a la izquierda. Elige Gastro: aparecen los tenants reales con su plan, su estado y su fecha de vencimiento. Cambia a Travel y la misma tabla te muestra las properties — mismo idioma, aunque por debajo cada vertical hable distinto.

Qué acabas de montar

Tu navegador solo habló con el BFF. Fue el BFF quien, server-side, le preguntó a Gastro y a Travel por HTTP usando los tokens internos — que nunca salieron del servidor. Por eso el panel puede leer dos bases de datos a las que tu navegador no tiene, ni tendrá, acceso.

Siguiente paso