Volver a la wiki

Servicio connector._register_local_token · Depósito del token en el SaaS

Resumen

Método connector._register_local_token() en terminal/agent/core/connector.py (+42 líneas). Ejecutado en cada conexión WebSocket exitosa con el SaaS, deposita el token local del Agent en el servidor para que el frontend pueda descargarlo e inyectarlo en las llamadas locales.

Best-effort: reintenta en cada reconexión; fallos silenciosos, nunca tumban la conexión principal.


Firmas y datos

async def _register_local_token(self):
    """Deposita el token de auth de la API local en el SaaS (Fase 3).

    Best-effort: el SaaS lo custodia cifrado y solo lo entrega a la sesión
    del tenant dueño (GET /api/agent/local-token). Si falla, el frontend
    sigue sin token y el middleware local lo rechazará — se reintenta en
    cada reconexión.
    """
    import aiohttp

    if getattr(sys, "frozen", False):
        from core.local_token import get_or_create_local_token
    else:
        from .local_token import get_or_create_local_token

    try:
        url = f"{self.auth.saas_url}/api/agent/register-local-token"
        headers = {"Authorization": f"Bearer {self.auth.access_token}"}
        async with (
            aiohttp.ClientSession() as session,
            session.post(
                url,
                json={"local_token": get_or_create_local_token()},
                headers=headers,
                timeout=aiohttp.ClientTimeout(total=15),
            ) as resp,
        ):
            if resp.status == 200:
                logger.info("Local token registered with SaaS")
            else:
                logger.warning(f"Local token registration failed: HTTP {resp.status}")
    except Exception as e:  # noqa: BLE001 — nunca tumbar la conexión por esto
        logger.warning(f"Local token registration error: {e}")

Ubicación en el flujo de conexión

En _connect_websocket() (conexión principal WS con el SaaS):

async def _connect_websocket(self):
    # ... login, negociación, etc.
    
    if on_connect:
        await on_connect()
    
    await self._send_agent_status()
    await self._register_local_token()  # ← AQUÍ, después de status
    
    # ... receive_loop

Timing: Tras confirmar que la conexión WS está viva y autenticada.


HTTP POST /api/agent/register-local-token

URL

POST https://<saas_url>/api/agent/register-local-token

Ej: https://crearack.com/api/agent/register-local-token

Headers

Request body (JSON)

{
  "local_token": "<TOKEN_OPACO_EJEMPLO_43-44_CHARS>"
}

Campo local_token: token opaco 43-44 caracteres de get_or_create_local_token().

Response esperada (HTTP 200)

{}

o vacío (la semántica es “depositado OK”).

Fallos tolerables

HTTPQué pasaAcción
200Token depositadoLog info, continua
401/403Credencial del Agent inválida o SaaS offlineLog warning, reintenta en próxima conexión
500SaaS error internoLog warning, reintenta en próxima conexión
Timeout (>15s)SaaS no responde rápidoLog warning, no bloquea WS
Exception (red abajo, DNS, etc.)Error de conectividadLog warning, caught, nunca propaga

Nunca levanta excepción: el except Exception final es genérico (noqa: BLE001) porque esta operación NO debe impedir la apertura de la conexión WS principal.


Semántica best-effort

El patrón es fire-and-forget asincrónico con reintentos automáticos:

  1. Primera conexión WS: intenta depositar token.
  2. Si SaaS no responde rápido (timeout 15s): continúa sin esperar.
  3. Reconexión WS: intenta de nuevo.
  4. Eventualmente converge (el frontend solo obtiene token cuando se deposita).

Ventaja: si el SaaS está lento/offline, el Agent sigue funcionando (compat); el frontend simplemente no recibe token y los 401 del gate local lo guían a re-autenticar.


Integración con Fase 2 (frontend)

El frontend (navegador, Fase 2 ya en PROD) hace:

// En el SaaS (Fase 2)
GET /api/agent/local-token
  → SaaS busca el token depositado por este Agent
  → Comprueba que la sesión es del tenant dueño
  → Retorna {"local_token": "..."}

// En el navegador
postMessage({
  type: 'SET_AUTH_TOKEN',
  token: local_token  // ← Recibido del SaaS
}, '*');  // → a terminal.html (iframe)

De ahí en adelante: terminal.html injeta el token en Bearer en todas las llamadas HTTP al Agent local.


Monitoreo / observabilidad

En producción, contar warnings de local_token_registration_failed ayuda a detectar problemas de conectividad SaaS ↔ Agent.


Compatibilidad

EscenarioQué pasa
SaaS Fase 1 PROD, Agent 2.1.0Token depositado OK; SaaS lo custodia.
SaaS Fase 1 PROD, Agent 2.0.24 (viejo)El endpoint aún no existe; POST 404 → log warning, ignored.
Agent vinculado a SaaS offlineTimeout/error → log warning, reintenta en próxima conexión.
Agent pre-activaciónauth.saas_url es None → _register_local_token() nunca se llama (compat).

Seguridad


Véase también

Subir