---
name: metabase_client_from_pass
kind: function
lang: py
domain: infra
version: "1.0.0"
purity: impure
signature: "def metabase_client_from_pass(pass_key: str, base_url: str, mode: str = 'auto') -> MetabaseClient | dict"
description: "Lee las credenciales de Metabase desde pass y devuelve un MetabaseClient autenticado, en una sola llamada. Elimina el patron inline repetido de cargar la credencial del password store y montar el cliente. Soporta dos instancias: API-key (metabase/aurgi-api-key -> header X-API-KEY) y usuario/password (captacion/metabase multi-linea -> login POST /api/session). mode='auto' detecta el formato. Compone pass_get_secret + parse_metabase_secret + metabase_auth/MetabaseClient sin reimplementarlos. Devuelve el cliente o {status:error, error} sin lanzar."
tags: [metabase, pass, secret, credential, auth, client]
uses_functions: ["pass_get_secret_py_infra", "parse_metabase_secret_py_infra", "metabase_auth_py_infra"]
uses_types: []
params:
  - name: pass_key
    desc: "Ruta del secreto en el password store (p.ej. 'metabase/aurgi-api-key' o 'captacion/metabase')."
  - name: base_url
    desc: "URL base de la instancia Metabase (p.ej. 'https://reports.autingo.es' o 'http://localhost:3030')."
  - name: mode
    desc: "'api_key', 'session' o 'auto' (default). En auto se detecta el formato del secreto: una sola linea de clave -> api_key; multi-linea con email/usuario -> session."
output: "MetabaseClient autenticado en exito. En fallo (sin lanzar): {status:'error', error:str} para secreto inexistente en pass, formato no parseable, o fallo de autenticacion contra Metabase."
returns: []
returns_optional: true
error_type: "error_go_core"
imports: [subprocess, httpx]
tested: true
tests: ["test_api_key_builds_client_with_x_api_key", "test_session_secret_parsed_and_auth_called", "test_auto_mode_detects_session", "test_missing_secret_returns_error_dict", "test_session_without_email_returns_error_dict"]
test_file_path: "python/functions/metabase/metabase_client_from_pass_test.py"
file_path: "python/functions/metabase/metabase_client_from_pass.py"
---

## Ejemplo

```python
import sys
sys.path.insert(0, "python/functions")
from metabase.metabase_client_from_pass import metabase_client_from_pass

# Aurgi (API-key en pass, header X-API-KEY):
client = metabase_client_from_pass(
    "metabase/aurgi-api-key", "https://reports.autingo.es", mode="api_key")
# client.request("GET", "/api/user/current")

# Captacion (usuario/password multi-linea en pass, login /api/session):
client = metabase_client_from_pass(
    "captacion/metabase", "http://localhost:3030", mode="session")

# Sin especificar mode: se autodetecta por el formato del secreto.
client = metabase_client_from_pass("metabase/aurgi-api-key", "https://reports.autingo.es")
```

## Cuando usarla

Cuando necesites un `MetabaseClient` autenticado y la credencial vive en `pass`:
en vez de escribir a mano el `pass show ...` + parseo + `metabase_auth` /
`MetabaseClient(...)`, llama a esta funcion con la ruta del secreto y la URL.
Cubre tanto instancias con API-key (Aurgi) como con usuario/password
(captacion). Es el punto de entrada unico para abrir un cliente desde el
password store.

## Gotchas

- **Impura**: lanza el subproceso `pass show` y abre conexion HTTP a Metabase.
  El secreto nunca se logea, pero el `MetabaseClient` retornado lleva el token en
  memoria.
- En `mode='session'` el secreto debe tener una linea de usuario con prefijo
  `email:` / `login:` / `username:` / `user:`; si falta, devuelve error dict (no
  lanza).
- La deteccion de API-key se basa en que la clave empieza por `mb_` (lo gestiona
  `MetabaseClient`). Una API-key con otro prefijo se enviaria como session token
  -> usa `mode='api_key'` explicito si tu key no empieza por `mb_`.
- Cierra el cliente cuando termines: `client.close()` o usalo como context
  manager (`with metabase_client_from_pass(...) as client:`).
- Los fallos de auth (401, instancia caida) se devuelven como
  `{status:'error', error}` — comprueba el tipo del retorno antes de usarlo.
