# auth.md — MenteX

You are an agent. Este documento describe cómo registrarte y autenticarte contra la API pública de MenteX
(https://mentex.com.mx). Resumen en una línea: **todos los endpoints son públicos; registrarte es opcional y gratuito,
y te da una identidad atribuible**. Sólo las credenciales emitidas por MenteX amplían el límite de peticiones.

Métodos, de menor a mayor compromiso:

| Método | Qué necesitas | Qué obtienes |
|---|---|---|
| **anonymous (sin registro)** | Nada. | Acceso completo; cuota de 10 peticiones/minuto por IP. |
| **anonymous (registrado)** | `POST /agent/auth` (Step 3). | Identidad `agt_…` atribuible en cada petición; misma cuota por IP. |
| **client_credentials** | `client_id` + `client_secret` emitidos por MenteX. | Scope `api:extended`: 60 peticiones/minuto por cliente. |

## Step 1 — Discover

- Metadata del recurso protegido (RFC 9728): https://mentex.com.mx/.well-known/oauth-protected-resource — también la enlaza la cabecera `WWW-Authenticate` de cualquier `401`.
- Metadata del servidor de autorización (RFC 8414): https://mentex.com.mx/.well-known/oauth-authorization-server — contiene el bloque `agent_auth` con `register_uri`, `identity_types_supported` y `skill` (la URL de este documento).
- Claves de verificación (JWKS, Ed25519/EdDSA): https://mentex.com.mx/oauth/jwks.json
- Catálogo de APIs (RFC 9727): https://mentex.com.mx/.well-known/api-catalog
- Especificación OpenAPI 3.1: https://mentex.com.mx/api/openapi.json — declara el esquema `oauth2ClientCredentials` como opcional.
- Documentación legible: https://mentex.com.mx/docs/api
- Estado del servicio: https://mentex.com.mx/api/health
- Servidor MCP (Streamable HTTP, sin autenticación): https://mentex.com.mx/api/mcp — tarjeta en https://mentex.com.mx/.well-known/mcp/server-card.json
- Agente A2A (JSON-RPC 2.0, sin autenticación): https://mentex.com.mx/api/a2a — tarjeta en https://mentex.com.mx/.well-known/agent-card.json
- Skills para agentes (Agent Skills Discovery): https://mentex.com.mx/.well-known/agent-skills/index.json
- Manifiesto ARD con todos los recursos anteriores: https://mentex.com.mx/.well-known/ai-catalog.json

No se publica `/.well-known/openid-configuration`: no hay OpenID Connect, usuarios finales ni ID Tokens.

## Step 2 — Pick a method

`agent_auth.identity_types_supported` = `["anonymous"]`.

- **anonymous**: único tipo de registro admitido. No necesitas ninguna identidad de usuario.
- **identity_assertion** (ID-JAG) y **service_auth** (email verificado): no habilitados. MenteX no tiene cuentas de usuario
  a las que vincular al agente; el endpoint de registro responde `identity_assertion_not_enabled` / `service_auth_not_enabled`.
- Si MenteX te ha entregado `client_id` y `client_secret`, salta a **Step 5b**.
- Si sólo quieres llamar a la API, salta a **Step 6**: no hace falta nada de lo anterior.

## Step 3 — Register

```http
POST /agent/auth HTTP/1.1
Host: mentex.com.mx
Content-Type: application/json

{ "type": "anonymous" }
```

Respuesta `200`:

```json
{
  "registration_id": "agt_…",
  "registration_type": "anonymous",
  "identity_assertion": "<JWT firmado por MenteX>",
  "assertion_expires": "<ISO 8601, 24 h después>",
  "scopes": [],
  "exchange": { "token_endpoint": "https://mentex.com.mx/oauth/token", "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer" }
}
```

Guarda `identity_assertion` en memoria: es tu credencial de registro durante 24 horas. No se devuelve `claim_token`
(no hay ceremonia de reclamación) y `scopes` es vacío: el registro anónimo aporta identidad, no cuota. El registro no
persiste nada en servidor: puedes repetirlo cuando caduque.

## Step 4 — Claim ceremony

No aplica. No hay cuentas de usuario, ni `claim_uri`, ni códigos de verificación. Para que un humano "tome posesión"
del agente y obtenga cuota ampliada, pide credenciales `client_credentials` en https://mentex.com.mx/#contacto.

## Step 5 — Exchange for an access_token

Token endpoint: `POST https://mentex.com.mx/oauth/token`. Respuesta en ambos casos:
`{ "access_token": "<JWT>", "token_type": "Bearer", "expires_in": 3600, "scope": "…" }`.
No hay refresh tokens: cuando expire, repite este paso.

### 5a. Agente registrado (jwt-bearer, RFC 7523)

```http
POST /oauth/token HTTP/1.1
Host: mentex.com.mx
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<identity_assertion>
```

Sin autenticación de cliente: la assertion firmada es la prueba. El `scope` resultante es vacío. Si recibes
`invalid_grant`, la assertion caducó o no verifica: vuelve al Step 3.

### 5b. Integrador con credenciales (client_credentials)

```http
POST /oauth/token HTTP/1.1
Host: mentex.com.mx
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&scope=api:extended
```

También se acepta `client_secret_post` (credenciales en el cuerpo). Las credenciales las emite MenteX manualmente
(no hay RFC 7591); solicítalas en https://mentex.com.mx/#contacto.
El `authorization_endpoint` publicado responde siempre `unsupported_response_type`; no existe flujo interactivo.

## Step 6 — Use the API

Llama a los endpoints directamente. Con token: `Authorization: Bearer <access_token>`.

| Método | Ruta | Descripción |
|---|---|---|
| `GET` | `/api/health` | Estado del servicio |
| `POST` | `/api/lead` | Registrar solicitud de contacto B2B |
| `POST` | `/api/cotizacion` | Registrar cotización estimada de proyecto |
| `POST` | `/api/diagnostico` | Diagnóstico de madurez tecnológica con IA |
| `POST` | `/api/evaluacion` | Evaluación de infraestructura y riesgo con IA |

Reglas:

- Cuerpo en `application/json` con los campos descritos en la especificación OpenAPI, salvo `/api/lead`,
  que recibe `application/x-www-form-urlencoded` y responde con redirección 303 a `/gracias` en caso de éxito.
- Límite: 10 peticiones por minuto por IP en todas las rutas `/api/*` (incluido `/api/mcp`), con o sin registro anónimo;
  60 por cliente con Bearer token válido y scope `api:extended`.
- Un Bearer inválido o caducado produce `401` en cualquier ruta `/api/*`, aunque sea pública. Retira la cabecera o renueva el token.
- Alternativa MCP: los mismos endpoints están disponibles como tools (`cotizar_proyecto`, `diagnostico_madurez_tecnologica`,
  `evaluacion_infraestructura`, `registrar_lead`, `perfil_mentex`) en el servidor MCP indicado arriba.
- Puedes pedir cualquier página HTML como Markdown enviando `Accept: text/markdown`.

### Identificación alternativa (Web Bot Auth)

Si prefieres no registrarte, puedes firmar tus peticiones con HTTP Message Signatures (RFC 9421) y publicar tu propio
directorio de claves. MenteX publica el suyo en https://mentex.com.mx/.well-known/http-message-signatures-directory para que otros sitios verifiquen
las peticiones que envía. La verificación de firmas entrantes no es obligatoria: una petición sin firma se atiende igual.

## Errors

| Código | Endpoint | Significado | Qué hacer |
|---|---|---|---|
| `400 invalid_request` | `/agent/auth`, `/oauth/token` | Cuerpo o parámetros mal formados. | Corrige la petición según este documento. |
| `400 unsupported_identity_type` | `/agent/auth` | `type` desconocido. | Usa `anonymous`. |
| `400 identity_assertion_not_enabled` / `service_auth_not_enabled` | `/agent/auth` | Método no habilitado. | Cambia a `anonymous`. |
| `400 invalid_grant` | `/oauth/token` | `identity_assertion` caducada, mal firmada o ajena. | Vuelve al Step 3. |
| `401 invalid_client` | `/oauth/token` | `client_id`/`client_secret` incorrectos o cliente desactivado. | Revisa las credenciales o usa el método anónimo. |
| `400 invalid_scope` | `/oauth/token` | Pediste un scope no asignado a tu sujeto. | Omite `scope` o pide sólo los permitidos. |
| `400 unsupported_grant_type` | `/oauth/token` | Grant distinto de los dos publicados. | Usa `client_credentials` o jwt-bearer. |
| `400` | `/api/*` | Cuerpo inválido según el esquema del endpoint. | Corrige los campos indicados en OpenAPI y reintenta. |
| `401 invalid_token` | `/api/*` | Bearer inválido o caducado (cabecera `WWW-Authenticate` con `resource_metadata`). | Renueva el token (Step 5) o llama sin `Authorization`. |
| `404` | cualquiera | Recurso inexistente. | No reintentes; revisa el catálogo de APIs. |
| `406` | páginas HTML | Pediste `text/markdown` para un recurso que no es HTML. | Solicita el recurso con su tipo nativo. |
| `429` | cualquiera | Límite de peticiones por minuto excedido. | Espera 60 segundos antes de reintentar. |
| `503 temporarily_unavailable` | `/oauth/token` | No se pudo validar el cliente. | Reintenta con retroceso exponencial. |
| `500` | cualquiera | Error interno; nunca expone detalles. | Reintenta con retroceso exponencial. |

## Revocation

- **Registro anónimo**: la `identity_assertion` caduca a las 24 horas y no hay `revocation_uri` ni eventos
  (`events_supported` es vacío): no existe estado que revocar. Un `invalid_grant` en el canje significa "regístrate de nuevo".
- **Access tokens**: duran 60 minutos y no hay endpoint de revocación (RFC 7009).
- **Clientes client_credentials**: MenteX desactiva el cliente y deja de emitirle tokens; los ya emitidos caducan solos.

## Contacto

Para credenciales `client_credentials`, cuotas superiores o acceso a APIs de clientes del ERP, escribe a través
de https://mentex.com.mx/#contacto.
