> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Gobernanza

> Gestiona mapeos de PII de actores, lista archivos de logs de auditoría y descarga sus objetos, y verifica la cadena de hash de auditoría de Matcher, que permite detectar manipulaciones.

La superficie de gobernanza de Matcher agrupa tres capacidades bajo `/v1/governance`: **mapeos de actores** (vinculan IDs de actores opacos con PII, con operaciones de seudonimización y eliminación), **archivos** (lista archivos de logs de auditoría completados y descarga objetos de archivos desde almacenamiento de objetos) y **logs de auditoría** (historial inmutable, encadenado por hash, con una comprobación de integridad de solo lectura). Con `AUTH_PROVIDER=plugin-auth` en modo multi-tenant, la identidad del tenant viene del JWT; Matcher rechaza el arranque cuando `MULTI_TENANT_ENABLED=true` y `PLUGIN_AUTH_ENABLED=false`. `workos` actualmente resuelve las solicitudes verificadas en el tenant predeterminado configurado, así que no lo uses para seleccionar tenants.

<Note>Cada ruta de gobernanza está delimitada al inquilino del llamante. Las lecturas de mapeos de actores se dividen en dos niveles de autorización: la lista (que omite `displayName` y `email`) frente a la lectura de des-anonimización de un solo registro, para que la resolución de identidad se mantenga separable del acceso de navegación.</Note>

## Mapeos de actores

***

Un mapeo de actor vincula un `actorId` opaco (por ejemplo `user:550e8400-e29b-41d4-a716-446655440000`) con PII legible (`displayName`, `email`). Fuera de los entornos local, desarrollo y prueba, define `ACTOR_PII_ENCRYPTION_KEY` con una clave de 32 bytes codificada en base64 antes de usar mapeos de actores. Si no se define, Matcher sigue funcionando, pero las operaciones de mapeo que manejan PII (upsert, lectura de un solo registro y seudonimización) devuelven un error de encryptor-required; las rutas de lista y eliminación, libres de PII, no requieren un encryptor. La PII de los mapeos nunca se almacena en texto claro. Las filas de la lista omiten los campos de PII del mapeo (`displayName`, `email`) **por diseño**, pero sí devuelven el propio `actorId`. Al hacer upsert, Matcher recorta los espacios al inicio y al final, y rechaza IDs vacíos, compuestos solo por espacios o de más de 255 caracteres. No impone un formato de ID opaco ni enmascara el valor, así que un `actorId` que contenga PII (como una dirección de correo) aparece en las filas de la lista con su valor almacenado y se conserva durante la seudonimización; usa identificadores opacos si el acceso a la lista debe mantenerse libre de PII. La respuesta del `PUT` y el `GET` de un solo registro devuelven la identidad en texto claro. Solo el `GET` de un solo registro está protegido por el permiso `deanonymize`: la respuesta del `PUT` está protegida únicamente por el acceso de escritura y devuelve el registro almacenado completo, incluido cualquier campo almacenado que el llamante no haya enviado, así que trata el acceso de escritura a los mapeos de actores como un acceso que revela PII. Los logs de auditoría pueden conservar el `actorId` sin procesar, que puede ser una dirección de correo.

### Listar mapeos de actores

Filas paginadas por cursor que omiten `displayName` y `email`. Filtra por un prefijo de ID de actor.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/actor-mappings?actorId=user:&limit=25" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "items": [
    {
      "actorId": "user:550e8400-e29b-41d4-a716-446655440000",
      "createdAt": "2026-01-15T10:30:00Z",
      "updatedAt": "2026-01-15T10:30:00Z"
    }
  ],
  "limit": 25
}
```

Parámetros de consulta: `actorId` (filtro por prefijo), `limit` (predeterminado 25, con tope de 100) y `cursor`.

### Upsert de un mapeo de actor

Crea o actualiza la PII de un ID de actor. `PUT` es idempotente — la misma llamada crea el registro en el primer uso y lo actualiza a partir de entonces. Debes proporcionar al menos uno de `displayName` o `email`.

```bash theme={null}
curl -X PUT "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "John Doe",
    "email": "john.doe@example.com"
  }'
```

```json theme={null}
{
  "actorId": "user:550e8400-e29b-41d4-a716-446655440000",
  "displayName": "John Doe",
  "email": "john.doe@example.com",
  "createdAt": "2026-01-15T10:30:00Z",
  "updatedAt": "2026-01-15T10:30:00Z"
}
```

### Obtener un mapeo de actor (des-anonimizar)

Devuelve la PII en texto claro de un solo ID de actor. Esta **es** la primitiva de des-anonimización, por lo que está protegida por el permiso más restringido `deanonymize` en lugar de la lectura simple.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}" \
  -H "Authorization: Bearer $TOKEN"
```

### Pseudonimizar

Reemplaza `displayName` y `email` del mapeo con `[REDACTED]` mientras conserva el registro y su vínculo con `actorId`. Esto depura la PII solo del mapeo: los registros de auditoría inmutables conservan el `actorId` sin procesar con el que se escribieron (que puede ser una dirección de correo), así que los logs de auditoría históricos y los archivos archivados no se redactan. Responde `204 No Content`.

```bash theme={null}
curl -X POST "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}/pseudonymize" \
  -H "Authorization: Bearer $TOKEN"
```

### Eliminar un mapeo

Elimina permanentemente el mapeo. Responde `204 No Content`.

```bash theme={null}
curl -X DELETE "https://api.matcher.example.com/v1/governance/actor-mappings/{actorId}" \
  -H "Authorization: Bearer $TOKEN"
```

<Note>Pseudonimizar mantiene el registro (con la PII depurada); eliminar lo borra por completo. Elige pseudonimizar cuando debas conservar el vínculo de auditoría, y eliminar cuando el propio registro no deba persistir.</Note>

## Archivos

***

El worker de archivado está desactivado de forma predeterminada (`ARCHIVAL_WORKER_ENABLED=false`). Cuando lo habilitas y configuras el almacenamiento de archivado, las particiones de logs de auditoría que caducan se comprimen y se mueven a almacenamiento de objetos. Las rutas de recuperación de archivos se registran cuando el almacenamiento de objetos de archivado está disponible, independientemente de si el worker está habilitado. El endpoint de lista devuelve archivos completados; el de descarga emite URLs con tiempo limitado para objetos de archivos.

### Listar archivos

Paginados por offset. Filtra por rango de fechas.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/archives?from=2024-01-01&to=2024-03-31&limit=20&offset=0" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "partitionName": "audit_logs_2024_q1",
      "dateRangeStart": "2024-01-01T00:00:00Z",
      "dateRangeEnd": "2024-03-31T23:59:59Z",
      "rowCount": 150000,
      "compressedSizeBytes": 10485760,
      "storageClass": "GLACIER",
      "checksum": "sha256:abc123def456...",
      "status": "COMPLETE",
      "archivedAt": "2024-04-01T02:30:00Z"
    }
  ],
  "limit": 20,
  "hasMore": true
}
```

Parámetros de consulta: `from`, `to` (`YYYY-MM-DD` o RFC 3339), `limit` (1–200, predeterminado 20) y `offset`. Solo se listan los archivos `COMPLETE` — los archivos en curso y fallidos nunca se exponen.

### Descargar un archivo

Devuelve una URL prefirmada más el checksum para la verificación de integridad.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/archives/{id}/download" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "downloadUrl": "https://s3.amazonaws.com/bucket/archive.gz?X-Amz-Signature=...",
  "expiresAt": "2026-02-05T13:00:00Z",
  "checksum": "sha256:abc123def456..."
}
```

<Warning>El handler de descarga confirma la propiedad del tenant, pero no comprueba `COMPLETE`; pre-firma la `archiveKey` almacenada. Esa clave y su checksum se asignan cuando un archivo llega a `UPLOADED`, antes de `COMPLETE`. Trata `GET /v1/governance/archives/{id}/download` como una ruta directa a la clave del objeto, no como prueba de que el archivado terminó. Si necesitas solo archivos completados, selecciona los IDs desde el endpoint de lista.</Warning>

<Warning>La disponibilidad del archivo depende del backend de almacenamiento compatible con S3 y de la política de ciclo de vida configurados. Confirma cualquier requisito de restauración con el responsable de ese despliegue de almacenamiento antes de depender de una URL de descarga.</Warning>

## Logs de auditoría

***

Los flujos de gobernanza instrumentados escriben registros de auditoría inmutables por tenant. Cada registro se enlaza en una cadena de hash SHA-256 que permite detectar manipulaciones (`recordHash` = `SHA-256(prevHash || contenido canónico)`), de modo que los cambios inconsistentes son detectables. Usa el endpoint de verificación de abajo para obtener el veredicto de integridad del lado del servidor.

### Listar logs de auditoría

Paginados por cursor, con filtros detallados.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/audit-logs?actor=user@example.com&action=CREATE&entity_type=context&date_from=2025-01-01&date_to=2025-01-31&limit=20" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "tenantId": "550e8400-e29b-41d4-a716-446655440001",
      "entityType": "reconciliation_context",
      "entityId": "550e8400-e29b-41d4-a716-446655440002",
      "action": "CREATE",
      "actorId": "user@example.com",
      "changes": { },
      "truncated": false,
      "originalSize": 0,
      "createdAt": "2025-01-15T10:30:00Z",
      "tenantSeq": 1,
      "recordHash": "dd3f8a09dda3a8fdcd1e5c54ef76a9168bbabbfd92ad1dd736400d03a3f8a585",
      "prevHash": "0000000000000000000000000000000000000000000000000000000000000000",
      "hashVersion": 1
    }
  ],
  "limit": 20,
  "hasMore": false
}
```

Parámetros de consulta: `actor`, `action`, `entity_type`, `date_from`, `date_to` (`YYYY-MM-DD` o RFC 3339), `limit` (1–200, predeterminado 20) y `cursor`.

`actor` filtra por el valor `actorId` del registro: el identificador de actor sin procesar capturado cuando se escribió el registro (una dirección de correo en este ejemplo). Los registros de auditoría almacenan ese identificador tal cual; no tiene que ser un `actorId` de mapeo de actores.

Cuando un diff excede el tope de payload del outbox, `changes` lleva un envoltorio con marcador de truncamiento en lugar del diff completo, y `truncated` pasa a `true`, con `originalSize` informando el tamaño en bytes previo al truncamiento.

### Verificar la cadena de auditoría

Vuelve a verificar que cada registro inspeccionado se enlaza con el anterior y coincide con su hash almacenado. La verificación recorre un tramo contiguo desde el inicio de la cadena, limitado por `maxRecords`, por lo que `intact` habla solo de ese tramo inspeccionado. En el endpoint HTTP, el `maxRecords` proporcionado debe estar entre 1 y 10 000 (los valores fuera de ese rango devuelven `422`); si lo omites, Matcher usa el valor predeterminado de 10 000 registros. La comprobación es estrictamente de solo lectura: detecta manipulaciones, nunca modifica un registro.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/audit-logs/verify?maxRecords=10000" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "intact": true,
  "verifiedCount": 1024,
  "truncated": false
}
```

`intact` es `true` cuando todo el tramo inspeccionado está intacto; si se encuentra una rotura, `firstBrokenSeq` informa el `tenantSeq` del primer registro que falla y `verifiedCount` informa cuántos se mantuvieron antes de él. `truncated` es `true` cuando la cadena contiene más registros de los que permitía el límite de inspección `maxRecords`.

### Obtener un log de auditoría

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/governance/audit-logs/{id}" \
  -H "Authorization: Bearer $TOKEN"
```

<Note>También puedes listar el historial de una entidad directamente con `GET /v1/governance/entities/{entityType}/{entityId}/audit-logs` (paginado por cursor), lo cual resulta conveniente cuando ya conoces la entidad que estás auditando.</Note>

## Códigos de respuesta

***

| Estado | Significado                                                                                                             |
| ------ | ----------------------------------------------------------------------------------------------------------------------- |
| `200`  | Datos de mapeo, archivo o auditoría devueltos                                                                           |
| `204`  | Mapeo de actor pseudonimizado o eliminado                                                                               |
| `400`  | Entrada inválida a nivel de aplicación (falta displayName/email o la fecha no es válida)                                |
| `403`  | Falta el nivel de permiso requerido (p. ej. `deanonymize` para PII de un solo registro)                                 |
| `404`  | Mapeo de actor, archivo o log de auditoría no encontrado                                                                |
| `422`  | Falló la validación de la solicitud o del esquema (p. ej. formato de email inválido o un valor de consulta restringido) |
