# aiguard — SDK de Gobernanza de IA para LATAM

Middleware Python ligero (**< 5ms overhead**) que envuelve cualquier pipeline de IA
(OpenAI, Anthropic, LangChain, LlamaIndex, modelos locales) y aplica políticas
de gobernanza + kill switch en tiempo real contra AI Guard LATAM.

## Instalación

```bash
pip install aiguard
# o desde este repo:
pip install -e /app/sdk
```

## Uso rápido

```python
import asyncio
from aiguard import GovernanceClient, FailMode

guard = GovernanceClient(
    api_key="jwt-de-tu-empresa",
    base_url="https://api.aiguardlatam.com",
    model_id="c9e51abf-1c26-4cdd-a78d-44662318a163",
    fail_mode=FailMode.FAIL_CLOSE,   # bancos, salud, sector público
    timeout_ms=200,
)

async def demo():
    async with guard:
        # ANTES de invocar al modelo (INPUT):
        await guard.enforce_input(text="¿Cuál es mi número de tarjeta?")
        # tu llamada a OpenAI/Anthropic aquí...
        output = "Tu tarjeta es 4111 1111 1111 1111"
        # DESPUÉS (OUTPUT):
        await guard.enforce_output(text=output)
        return output

asyncio.run(demo())
# → AIGovernanceViolationError: "La operación ha sido interrumpida por políticas de control y seguridad institucional"
```

## Modo decorador

```python
@guard.protect(stage="OUTPUT")
async def generate_response(prompt: str) -> str:
    return await openai_client.chat.completions.create(...)
```

## Fail-Safe Modes

- `FailMode.FAIL_OPEN` — si nuestro SaaS no responde (timeout, 5xx), la IA del cliente CONTINÚA. Ideal marketing, chatbots no-críticos.
- `FailMode.FAIL_CLOSE` — si nuestro SaaS no responde, la IA del cliente se DETIENE. Ideal bancos, hospitales, gobierno.

## Performance

- Cliente httpx compartido con connection pool (HTTP/2 keep-alive).
- Cálculo de métricas heurísticas ~1ms; llamada al SaaS P95 ~30-50ms; overhead SDK propio ~2ms.
- Circuit breaker: 5 fallos consecutivos abre el circuito 30s (respeta fail_mode).

---

## 🛡️ Zero-Knowledge Perimeter Wall (v0.2.0)

Muro de anonimización local que garantiza a las instituciones financieras que
**ningún dato en texto plano** cruza la frontera hacia AI Guard SaaS.

### Componentes

| Módulo | Responsabilidad |
|---|---|
| `RedactionEngine` | Detecta PII (PAN Luhn, CLABE checksum, CBU, RFC, CURP, CPF, RUT, IBAN, email, teléfono, nombres propios, montos) y sustituye por `[TOKEN_<TYPE>_<HASH>]` |
| `TokenVault` | Mapping token→plaintext en RAM (nunca a disco), aislado por `session_id`, con TTL |
| `PrivacyAuditor` | Log encadenado (Merkle-like) + `verify_no_pii_leaked()` como última muralla antes del socket |

### Uso completo

```python
import os
from aiguard import GovernanceClient, RedactionEngine, PrivacyAuditor

engine  = RedactionEngine(salt=os.environ["AIGUARD_REDACTION_SALT"])
auditor = PrivacyAuditor(engine=engine, strict=True)   # aborta ante fuga

guard = GovernanceClient(
    api_key="gov_live_...",
    base_url="https://api.aiguardlatam.com",
    model_id="chatbot-atencion",
    redactor=engine,
    auditor=auditor,
)

async with guard:
    result = await guard.enforce_input(
        text="Cliente Juan Pérez transfirió MX$50,000 desde tarjeta 4111 1111 1111 1111",
        session_id="chat-9821",
    )
    # El SaaS solo vio: "Cliente [TOKEN_NAME_...] transfirió [TOKEN_AMOUNT_...] desde tarjeta [TOKEN_PAN_...]"

# Auditoría local (nunca sale del cliente)
print(auditor.summary())
print("Chain OK:", auditor.log.verify_chain())
```

### Garantías criptográficas

- **Tokens deterministas por tenant**: `HMAC-SHA256(salt, kind||plaintext)[:16]`. El mismo cliente
  con distintos salts produce tokens distintos (aislamiento inter-tenant).
- **Bit ácora tamper-evident**: cada entrada del audit log firma la anterior; `verify_chain()` detecta manipulación.
- **Wipe seguro**: `TokenSession.close()` sobreescribe y descarta el mapping.

### SLO de latencia

- 5 KB con todos los detectores: **< 2 ms**
- 50 KB: **< 15 ms**
- Verificado en `tests/test_zero_knowledge.py::test_latency_under_15ms_for_5kb`

### Ejecutar tests

```bash
cd /app/sdk
PYTHONPATH=src python -m pytest tests/ -v
```
