# Agent API — integración máquina-a-máquina (agentes LLM, pipelines)

gampify expone una API REST completa para que sistemas externos (agentes LLM,
CI/CD, ERPs) creen y gestionen paquetes de validación GAMP 5 de forma
programática. Esta guía describe el flujo recomendado, el contrato de datos y
las reglas regulatorias que el sistema aplica **por diseño**.

- **Base URL producción**: `https://gampify.org` (canónico; `www` redirige aquí)
- **Formato**: JSON en todos los requests/responses
- **Auth**: `Authorization: Bearer <token-o-api-key>`

---

## 1. Modelo de autenticación: sesión vs API key

|                | Sesión (humano)        | API key (máquina)                 |
| -------------- | ---------------------- | --------------------------------- |
| Se obtiene con | `POST /api/auth/login` | `POST /api/auth/api-keys`         |
| Duración       | 7 días (TTL fijo)      | Sin TTL (revocación manual)       |
| Formato        | token opaco (hex 64)   | `gampify_` + 48 hex chars         |
| Ideal para     | navegador, UI          | agentes LLM, CI/CD, integraciones |

Las API keys **heredan los permisos RBAC del usuario** que las crea. Una key
de un usuario QA puede firmar… pero solo si ese QA tiene 2FA activo y presenta
el TOTP en cada firma (ver §4 — la firma es humana por diseño).

### Crear una API key

```bash
# 1. Registrar el usuario de servicio (una sola vez)
curl -X POST https://gampify.org/api/auth/register \
  -H "content-type: application/json" \
  -d '{"name":"Agente LLM","email":"agente@tuempresa.com","password":"<min-8-chars>","role":"implementer"}'

# 2. Login y crear la key
TOKEN=$(curl -s -X POST https://gampify.org/api/auth/login \
  -H "content-type: application/json" \
  -d '{"email":"agente@tuempresa.com","password":"<pass>"}' | jq -r .token)

curl -X POST https://gampify.org/api/auth/api-keys \
  -H "authorization: Bearer $TOKEN" -H "content-type: application/json" \
  -d '{"name":"agente-produccion"}'
# → {"key":"gampify_…48-hex…", ...}  ⚠️ se muestra UNA sola vez — guardala
```

Gestión:

```bash
curl https://gampify.org/api/auth/api-keys -H "authorization: Bearer $TOKEN"   # listar (sin raw)
curl -X DELETE https://gampify.org/api/auth/api-keys/<id> -H "authorization: Bearer $TOKEN"  # revocar
```

---

## 2. Flujo recomendado para un agente LLM

```
 ┌──────────────┐         ┌──────────────────────────────────────────┐
 │ Agente LLM   │         │ gampify                                   │
 └──────┬───────┘         └──────────────────────────────────────────┘
        │ 1. POST /api/projects {answers}          ← crea proyecto + 39 docs
        │ 2. GET  /api/projects/:id                ← revisa gaps/compliance
        │ 3. PUT  /api/projects/:id/docs/:type     ← ajusta docs (opcional)
        │ 4. POST /api/projects/:id/self-test      ← corre checks técnicos
        │ 5. POST /api/projects/:id/audit-link     ← link read-only para QA
        ▼
 ┌──────────────┐
 │ QA humano    │  6. Abre el audit-link, revisa, activa 2FA,
 └──────┬───────┘     firma cada doc con TOTP + signing_meaning
        ▼
   Paquete GxP firmado y verificable públicamente (/verify + audit trail)
```

**La regla de oro:** el agente _prepara_; el QA humano _aprueba y firma_.
Esto no es una limitación técnica sino un requisito regulatorio:

- 21 CFR Part 11 §11.200(a): identificación única al momento de la firma (TOTP).
- GAMP 5 v2 §6.2.3 (Quality Unit — independence) / §6.1.4 (Supplier relationships): independencia — quien genera el trabajo no firma su
  propia validación. El sistema rechaza con 403 si `implementer_email == QA`.

---

## 3. Contrato del `answers` (payload de creación)

`POST /api/projects` con `{"answers": {...}}` — 100KB máx. Estructura completa
de referencia: [`data/sample.json`](../data/sample.json). Resumen:

```jsonc
{
  "proyecto": {
    "sistema": "Mi LIMS",              // requerido
    "version_sistema": "1.0",
    "descripcion": "...",
    "pais": "AR",                       // ANMAT|FDA|EMA según país
    "regulador": "ANMAT",               // auto-completado si vacío
    "categoria_gamp": "Cat 4+5"         // auto-completado si vacío
  },
  "equipo": {
    "implementador": { "email": "agente@tuempresa.com" },   // ← quien crea
    "qa": { "email": "qa@tuempresa.com" },                  // ← humano firmante
    "management": { "email": "..." }
  },
  "regulatorio": { "normativas": ["ANMAT 5330/97", ...] },
  "tecnico": { "lenguajes": [], "db": "", "backups": "", "seguridad": [], ... },
  "proveedores": [ { "nombre": "...", "producto_servicio": "...", "critico_gxp": true } ],
  "procesos": [], "riesgos": [],                  // vacíos → auto-generados (FMEA)
  "requisitos_funcionales": [], "modulos_funcionales": [],
  "modelo_datos": [], "componentes_custom": [], "docs_existentes": [],
  "comercial": { ... }
}
```

**Automatización incluida**: si `riesgos`, `proveedores`, `categoria_gamp`,
`normativas` o `deadline_regulatorio` vienen vacíos, gampify los completa
automáticamente (FMEA con hasta 8 riesgos, Vendor Assessment, etc.). La respuesta
incluye `automation_note` con lo que se completó.

---

## 4. Firma: qué puede y qué no puede hacer la máquina

| Acción                       | ¿El agente puede? | Por qué                                                         |
| ---------------------------- | ----------------- | --------------------------------------------------------------- |
| Crear/editar/regenerar docs  | ✅                | draft — sin valor regulatorio aún                               |
| Agregar evidencia IQ/OQ/PQ   | ✅                | queda encadenada con hash, firmable luego                       |
| Correr self-test             | ✅                | genera evidencia técnica                                        |
| Crear audit-link             | ✅                | solo lectura, expira en 30 días                                 |
| **Firmar un doc**            | ❌ **human-only** | exige TOTP del QA real (§11.200(a)) + independencia             |
| Crear/aprobar Change Control | ⚠️ parcial        | el agente crea; la aprobación es de QA distinto del solicitante |

El intento de firma sin 2FA devuelve:

```json
403 {"error": "firmantes QA/admin requieren 2FA habilitado. Activá vía /api/auth/2fa/enable primero."}
```

---

## 5. Ejemplo end-to-end en Python (para un agente)

```python
import requests

BASE = "https://gampify.org"
s = requests.Session()
s.headers["authorization"] = "Bearer gampify_TU_API_KEY"

# 1. Crear el proyecto con el wizard completo
answers = {
    "proyecto": {"sistema": "LIMS Farma v2", "pais": "AR", "regulador": "ANMAT"},
    "equipo": {
        "implementador": {"email": "agente@tuempresa.com"},
        "qa": {"email": "qa@tuempresa.com"},          # ← el humano que firma
    },
    # ... resto del wizard; lo vacío se auto-completa
}
r = s.post(f"{BASE}/api/projects", json={"answers": answers}).json()
pid, docs = r["project"]["id"], r["docs"]
print(f"Proyecto {pid}: {len(docs)} docs, compliance promedio alto → revisar gaps")

# 2. Iterar sobre los docs con gaps y corregir contenido (opcional)
for d in docs:
    if d["gaps"]:
        doc = s.get(f"{BASE}/api/projects/{pid}/docs/{d['template_type']}").json()
        nuevo = doc["content_md"].replace("⚠️ GAP", "A completar")  # tu lógica
        s.put(f"{BASE}/api/projects/{pid}/docs/{d['template_type']}",
              json={"content_md": nuevo, "change_reason": "Completado por agente LLM"})

# 3. Self-test técnico + audit-link para el QA humano
selftest = s.post(f"{BASE}/api/projects/{pid}/self-test", json={}).json()
link = s.post(f"{BASE}/api/projects/{pid}/audit-link").json()
print(f"Handoff → {BASE}{link['url']}  (expira: {link['expires_at']})")
# 4. El QA humano revisa el link, activa 2FA y firma. El agente puede monitorear:
sig = s.get(f"{BASE}/api/projects/{pid}/docs/URS/verify").json()
print("¿Ya firmado?", sig.get("valid"), sig.get("signing_meaning"))
```

---

## 6. Referencia rápida de endpoints

| Método | Ruta                                           | Descripción                                              |
| ------ | ---------------------------------------------- | -------------------------------------------------------- |
| POST   | `/api/auth/register`                           | Registro (`role`: implementer/qa/management/viewer)      |
| POST   | `/api/auth/login`                              | Login → `{token}` (agrega `totp` si 2FA activo)          |
| POST   | `/api/auth/api-keys`                           | Crea API key (raw visible una vez)                       |
| GET    | `/api/auth/api-keys`                           | Lista keys del usuario                                   |
| DELETE | `/api/auth/api-keys/:id`                       | Revoca key                                               |
| POST   | `/api/projects`                                | Crea proyecto + 39 docs (ver §3)                         |
| GET    | `/api/projects` / `/api/projects/:id`          | Lista / detalle con gaps                                 |
| PUT    | `/api/projects/:id/docs/:type`                 | Edita doc (v+1; si estaba firmado exige CC)              |
| POST   | `/api/projects/:id/docs/:type/sign`            | **Solo QA humano** con `{signing_totp, signing_meaning}` |
| GET    | `/api/projects/:id/docs/:type/verify`          | Verificación pública de firma                            |
| POST   | `/api/projects/:id/docs/IQ-Protocolo/evidence` | Evidencia con hash chain                                 |
| POST   | `/api/projects/:id/self-test`                  | Checks técnicos automatizados                            |
| POST   | `/api/projects/:id/audit-link`                 | Link read-only (30 días)                                 |
| GET    | `/api/audit-data/:token`                       | Paquete completo para auditor (público)                  |
| GET    | `/api/audit`                                   | Audit trail + verificación de hash chain                 |
| GET    | `/api/health`                                  | Health check                                             |

Errores estándar: `400` input inválido · `401` no autenticado · `403` sin
permiso / independencia GxP · `404` no encontrado · `409` conflicto (ya firmado,
CC requerido) · `429` rate limit (10 req/5min en auth) · `503` TSA no disponible.

---

## 7. Buenas prácticas para agentes

1. **Un usuario de servicio por agente/integración** — no compartas keys.
2. **Guardá la key en un secret manager**, nunca en el prompt del LLM ni en logs.
3. **Seteá `equipo.qa.email` a un humano real** — es quien va a firmar.
4. **No fuerces contenido regulatorio**: los docs con `gaps` sin resolver tienen
   compliance_score bajo y el QA lo va a ver en el audit-link.
5. **Monitoreá con `GET /api/projects/:id/audit`** — `chain_ok: true` garantiza
   que el audit trail no fue alterado.
6. **Revocá keys no usadas** — la revocación es inmediata.
