Saltar a contenido

Agregar una vertical nueva al federado

Cuando nace una vertical (digamos retail) y quieres administrar sus clientes desde el panel.

Esto es "Ask First" (ver AGENTS.md): el contrato VerticalConnector es la pieza que mantiene honestas las fronteras entre bounded contexts. Acuérdalo antes de escribir el conector.

1. Primero, la vertical: expón su dominio platform/

El panel no lee bases ajenas, así que la vertical nueva tiene que ofrecer, bajo /api/v1/platform/*, al menos:

  • GET /platform/<recursos> — listado con q, filtros de estado/plan y paginación.
  • GET /platform/<recursos>/{id} — la ficha completa.
  • GET /platform/dashboard — conteos.
  • Las mutaciones que quieras exponer, cada una con su reason obligatorio y su fila de auditoría escrita por la vertical, en la misma transacción que el cambio.
  • GET /platform/<recursos>/{id}/audit-log.

Auth: aceptar X-Internal-Token (un secreto compartido con el BFF) más X-Operator-Actor con el email del humano. Ese email es el que va a la auditoría.

Copia el molde de apps/gastro/backend/app/domains/platform/ o apps/travel/backend/app/domains/platform/ — el segundo es el ejemplo de cómo hacerlo sin tocar la lógica de negocio existente (pasa por las primitivas de billing).

2. Después, el BFF

  1. Settings — en app/core/config.py, agrega OPERATOR_RETAIL_BASE_URL y OPERATOR_RETAIL_INTERNAL_TOKEN: SecretStr | None.
  2. Documenta las variables — súmalas a OPTIONAL_FIELDS y DESCRIPTIONS en scripts/generate_env_docs.py. Si te lo saltas, el CI falla con Settings/environment mismatch. Es a propósito.
  3. Conectorapp/domains/customers/connectors/retail.py, implementando el Protocol VerticalConnector. Aquí es donde se absorbe el vocabulario: si retail llama tier a lo que el panel llama plan, la traducción vive en el conector y en ningún otro sitio. El resto del BFF y todo el frontend solo conocen CustomerCard.
  4. Regístralo en el diccionario de conectores que arma CustomersService.
  5. Tests — con respx mockeando la vertical. Mira tests/test_mutations.py: lo que hay que probar es la traducción de vocabulario, que el actor viaje, y que un 4xx de la vertical se propague tal cual en vez de disfrazarse de 502.

3. Por último, el frontend

  1. npm run generate:api — el tipado sale del openapi del BFF, no se escribe a mano.
  2. Agrega la key a VerticalKey en src/shared/api/types.ts. El BFF tipa la vertical como string (puede federar las que sea sin redeploy del front), pero la UI necesita saber qué planes ofrecer.
  3. Suma sus planes a PLANS en widgets/customer-actions/CustomerActions.tsx.

Lo que NO hay que hacer

  • Conectarse a la base de la vertical nueva. Nunca. Aunque sea "solo una lectura rápida".
  • Poner el token en un VITE_*. El bundle es público.
  • Meter la lógica de sus planes en el BFF: quién puede pasar de qué plan a cuál es decisión de la vertical dueña. El BFF propaga su rechazo, no lo suplanta.