Documentación · para integradores

Integrar un sistema con el agente

Lo que necesita saber quien conecta una aplicación existente: qué se le pregunta al agente, qué responde y qué queda registrado.

Panorama

El agente es un servicio HTTP que corre dentro de su infraestructura, junto a la base de datos. Su aplicación le pregunta antes de entregar un dato personal, y el agente responde tres cosas: si el acceso es lícito, qué campos corresponden a la finalidad invocada y dónde quedó la constancia.

La integración tiene tres piezas, y sólo la primera es código suyo:

  • La llamada. Su aplicación declara quién pide, para qué y qué recurso.
  • El mapeo. Un archivo que dice qué tabla y qué columna es cada dato, y de qué categoría.
  • El paquete normativo. El régimen aplicable, como configuración. Para salud ya existe.

El agente es determinista: la misma solicitud con el mismo paquete produce siempre la misma decisión. No usa aprendizaje automático. Cada decisión se puede explicar citando la regla que la tomó.

Autenticación

Toda ruta, salvo la de salud del servicio, exige la cabecera X-Consta-Key con la clave del agente. Sin clave o con una clave errónea la respuesta es 401 y no se registra nada: un tercero sin clave no puede llenar la cadena de eventos.

Cabeceras
Content-Type: application/json
X-Consta-Key: <clave del agente>

Autorizar un acceso

POST /v1/authorize responde la decisión y los nombres de los campos habilitados, sin leer ningún valor. Sirve para saber qué está permitido antes de pedir el recurso.

PeticiónPOST /v1/authorize
{
  "actor": {
    "id": "prof_alfa_07",
    "rol": "medico_tratante",
    "organizacion": "org_alfa"
  },
  "finalidad": "asistencia_sanitaria",
  "titular": "pac_00042",
  "recurso": {"tipo": "condicion", "id": "cnd_00042"},
  "campos": ["diagnostico"]
}
CampoQué es
actor.idIdentificador opaco del profesional. Obligatorio. Nunca su RUT ni su nombre.
actor.rolEl rol con que actúa, en el vocabulario del paquete.
actor.organizacionLa organización a la que pertenece. Un actor sólo accede a recursos de la suya.
finalidadPara qué se pide el dato. Sin finalidad admisible, se deniega.
recursoEl tipo y el identificador del recurso, tal como los declara el mapeo.
camposLos campos que se piden. Nunca se entrega uno que no se pidió.

Lo que la petición no decide

Ni la procedencia ni la categoría las decide quien pide. La procedencia la resuelve el agente en la fuente, recurso por recurso; la categoría la declara el mapeo, campo por campo. Si la petición las trae, se aceptan pero no deciden, y si difieren de lo resuelto la discrepancia queda registrada.

Respuesta403 · denegado
{
  "decision": "denegar",
  "motivo": "procedencia_prohibida",
  "articulo": "Ley 19.628, art. 16 bis inc. 3°",
  "detalle": [],
  "paquete": "clinguard@0.7.1",
  "registro": {"id": 34, "hash": "a7217279…8c7e54"}
}

articulo viene sólo cuando la norma funda la decisión, y siempre tomado del paquete. Las denegaciones que nacen de la lista blanca, como una combinación que nadie habilitó, llevan null: atribuirles un artículo sería decir que la ley tomó una decisión que no tomó.

Autorizar y leer en una operación

POST /v1/resources/read recibe la misma petición, autoriza y entrega los valores de los campos habilitados. Es la forma recomendada de integrarse: la aplicación nunca recibe el registro completo para decidir después qué mostrar.

Respuesta200 · permitido
{
  "decision": "permitir",
  "recurso": {
    "tipo": "paciente",
    "id": "pac_00002",
    "nombre": "Javiera",
    "telefono": "+56 9 0000 5487"
  },
  "omitidos": [
    {"campo": "prevision", "motivo": "no_habilitado", "categoria": "prevision"},
    {"campo": "rut",       "motivo": "no_mapeado",    "categoria": null}
  ],
  "paquete": "clinguard@0.7.1",
  "registro": {"id": 35, "hash": "3d7df4c4…73727096"}
}

Una recepcionista pidió nombre, teléfono y previsión para agendar. La previsión está en la misma fila, pero es otra categoría y esa finalidad no la habilita: se omite, y ni siquiera se pide a la base.

omitidos es evidencia, no información para el usuario final: son los nombres de lo que el recurso tenía y no se entregó, con su motivo. Nunca valores. Esa diferencia es la que permite demostrar después que la minimización operó.

Ejemplos con datos sintéticos. Ningún dato de esta página corresponde a una persona real.

Códigos de respuesta

Un cliente que sólo mira el código falla de forma segura: todo lo que no es 200 es «no entregar».

CódigoCuándo¿Queda registrado?
200Permitido.Sí
403Denegado. Incluye el recurso de otra organización y el titular con un bloqueo vigente.Sí
404El recurso no existe en la fuente.Sí
409No se pudo establecer la procedencia o la organización del recurso: no se llegó a evaluar.Sí
422Solicitud inválida, o tipo de recurso que el mapeo no declara.Sí, sin el cuerpo recibido
401Sin clave o con clave errónea.No
503El registro o la fuente no están disponibles. El agente no decide.No: no hubo decisión

El 503 es una garantía, no una falla: sin constancia no hay decisión. Su aplicación debe tratarlo como «no entregar ahora» y reintentar.

El mapeo de la fuente

El agente no sabe qué guarda cada tabla: se lo dice un archivo. Por cada tipo de recurso declara la tabla, la clave, la columna con la procedencia, la columna con la organización y cada campo entregable con su categoría.

mapeos/fuente.yamlextracto
entidades:
  paciente:
    tabla: paciente
    clave: id
    procedencia: procedencia
    organizacion: organizacion_id
    titular: id
    campos:
      nombre:    {columna: nombres,   categoria: administrativo}
      telefono:  {columna: telefono,  categoria: administrativo}
      prevision: {columna: prevision, categoria: prevision}

La categoría va por campo y no por tabla, porque una misma tabla mezcla categorías. Una columna que no aparece en el mapeo no tiene categoría y nunca se entrega: es la forma de dejar fuera el RUT o el correo sin escribir una regla.

Sólo lectura

El agente se conecta con un rol que sólo puede leer. Al arrancar inspecciona los privilegios de ese rol y, si puede escribir en alguna tabla, se detiene. Cada conexión se abre además en modo de sólo lectura.

El paquete normativo

El régimen aplicable es un archivo declarativo que se valida al cargar. Declara las finalidades admisibles, las procedencias admitidas y prohibidas y la matriz de habilitación. Lo que no habilita expresamente se deniega.

Anatomía de un paquete
paquete: <id>
version: <semver>
base_legal: [...]
categorias: {...}
finalidades_admisibles:        # lista cerrada
  - id: <id>
    articulo: <referencia>     # sin artículo, el paquete no carga
    requiere: [<condicion>]    # opcional
procedencias_declaradas:
  <id>:
    prohibida: <bool>
    articulo: <referencia>     # obligatorio si está prohibida
    alcance: [<categoria>]     # opcional: a qué categorías alcanza
matriz_habilitacion: [...]     # rol, finalidad, categoría, procedencia, campos
reglas_deteccion: [...]        # opcional

Un integrador normalmente no escribe un paquete: usa el de su sector. Lo que sí conviene saber es que cada respuesta dice qué paquete y qué versión decidió, en el campo paquete.

Verificar la cadena

Cada decisión se anexa a un registro de sólo anexado, encadenado por SHA-256: cada evento guarda la huella del anterior. El campo registro de cada respuesta trae la posición del evento y su huella.

GET /v1/audit/verify recorre la cadena de punta a punta. Si alguien alteró un evento, eliminó uno o reescribió la historia, la verificación lo detecta e indica la causa: contenido_alterado, continuidad_rota o enlace_roto.

La consola hace la misma comprobación desde fuera, sin ver el registro: guarda la raíz de la cadena en cada sincronización y la compara con la siguiente.

Despliegue

El agente se entrega como contenedor y se levanta con Docker Compose, junto a un PostgreSQL propio para el registro. Su base de datos no se modifica: el agente sólo la lee.

  • Un rol de sólo lectura en su base, para el agente.
  • El archivo de mapeo de su fuente.
  • El paquete normativo de su sector.
  • Las claves del agente, que deben ser distintas entre sí: el agente no arranca si se repiten.

El repositorio incluye un entorno sintético completo, con una clínica de ejemplo, para probar la integración sin tocar datos reales.

Consta es un proyecto de título validado con datos sintéticos; no hay un servicio alojado. Para acceder al repositorio o coordinar una prueba, escriba a contacto@consta.live.