# Decision tokens

Cuando un punto de control llega a una decisión terminal, Maetra emite un **decisión token** - un JWT firmado en `decision_token`. Se une la decisión al sobre de acción canónica, las versiones exactas de política, el espacio de trabajo y el ejecutante previsto.

Verificarlo localmente para el rechazo rápido, luego consumirlo a través de `POST /v1/executions/authorize` inmediatamente antes de la acción externa. Ese cheque autorizado impone la revocación y la semántica de un uso.

### Llaves públicas (JWKS)

`GET /.well-known/jwks.json` — **No se requiere autenticación.** Devuelve el conjunto clave utilizado para firmar tokens de decisión. Coge una vez y cache; la cabecera de token `kid` Identifica qué clave lo firmó.

#### cURL

```bash
curl "https://api.maetra.io/.well-known/jwks.json" \
  -H "Authorization: Bearer $MAETRA_API_KEY"
```

#### JavaScript

```javascript
const res = await fetch("https://api.maetra.io/.well-known/jwks.json", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = await res.json();
console.log(data);
```

#### TypeScript

```typescript
const res = await fetch("https://api.maetra.io/.well-known/jwks.json", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.MAETRA_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`Maetra API ${res.status}`);
const data = (await res.json());
```

#### Python

```python
import os, requests

res = requests.get(
    "https://api.maetra.io/.well-known/jwks.json",
    headers={"Authorization": f"Bearer {os.environ['MAETRA_API_KEY']}"},
)
res.raise_for_status()
print(res.json())
```

#### Rust

```rust
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("MAETRA_API_KEY")?;
    let client = reqwest::Client::new();
    let res = client
        .get("https://api.maetra.io/.well-known/jwks.json")
        .bearer_auth(&key)
        .send()
        .await?;
    let data: serde_json::Value = res.json().await?;
    println!("{data:#}");
    Ok(())
}
```

#### C++

```cpp
#include <curl/curl.h>
#include <cstdlib>
#include <string>

int main() {
    CURL* curl = curl_easy_init();
    std::string auth = "Authorization: Bearer " + std::string(std::getenv("MAETRA_API_KEY"));
    struct curl_slist* headers = nullptr;
    headers = curl_slist_append(headers, auth.c_str());
    curl_easy_setopt(curl, CURLOPT_URL, "https://api.maetra.io/.well-known/jwks.json");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_perform(curl);   // response is written to stdout by default
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    return 0;
}
```

#### Java

```java
import java.net.URI;
import java.net.http.*;

var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.maetra.io/.well-known/jwks.json"))
    .header("Authorization", "Bearer " + System.getenv("MAETRA_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
```


```json
{ "keys": [ { "kty": "OKP", "crv": "Ed25519", "alg": "EdDSA", "kid": "…", "x": "…" } ] }
```

### Verificando una ficha

Las fichas de decisión se firman con **EdDSA usando Ed25519**. Verifica con una biblioteca JWT que soporta Ed25519 y el JWKS arriba.

#### JavaScript / TypeScript

```typescript
import { jwtVerify, createRemoteJWKSet } from "jose";

const JWKS = createRemoteJWKSet(new URL("https://api.maetra.io/.well-known/jwks.json"));

export async function verifyDecision(token: string) {
  const { payload } = await jwtVerify(token, JWKS, {
    algorithms: ["EdDSA"],
    issuer: "maetra-govern",
    audience: "payments-worker",
  });
  if (payload.status !== "approved" || payload.maxUses !== 1) {
    throw new Error(`Action not approved: ${payload.status}`);
  }
  return payload; // identifies the checkpoint, action, decision, and expiry
}
```

#### Python

```python
import jwt  # PyJWT
from jwt import PyJWKClient

jwks = PyJWKClient("https://api.maetra.io/.well-known/jwks.json")

def verify_decision(token: str) -> dict:
    key = jwks.get_signing_key_from_jwt(token).key
    payload = jwt.decode(token, key, algorithms=["EdDSA"], issuer="maetra-govern", audience="payments-worker")
    if payload.get("status") != "approved":
        raise ValueError(f"Action not approved: {payload.get('status')}")
    return payload
```

#### Go

```go
// Use github.com/lestrrat-go/jwx/v2/jwk + /jwt
keySet, _ := jwk.Fetch(ctx, "https://api.maetra.io/.well-known/jwks.json")
tok, err := jwt.Parse(raw, jwt.WithKeySet(keySet), jwt.WithValidate(true))
if err != nil { /* reject */ }
if status, _ := tok.Get("status"); status != "approved" {
    // do not perform the action
}
```


#### Qué hacer para comprobar

* **Firma** - debe validar contra una llave en el JWKS.
* **`status`** - Proceder sólo cuando `approved`.
* **Gastos** - rechazar fichas caducadas (estándar) `exp`).
* **Periodista y público** - Requerimientos `iss=maetra-govern` y su ejecutor es exacto `aud` valor.
* **Binding** — recomputar y comparar `actionEnvelopeHash`, entonces compare `checkpointId`, `workspaceId`, y `policyDigest`.
* **Uso del techo** - Requerimientos `maxUses=1` y autorizar a través de Maetra para que una ficha repetida o revocada falla en la ejecución.

> **Note**
> Tratar el token como una capacidad de vida corta y de un uso. `decision_token_expires_at` atado el token; punto de control `expires_at` es el tiempo de aprobación.