# Agent validation via Trust Registry

> Configure Trust Check queries against trust registries and enforce access using Policy decisions on Trust Check outcomes.
This guide explains how to validate caller trust with the Trust Check node and enforce the final access decision with a Policy node.

Trust Check verifies trust evidence. Policy decides allow or deny.

## What Trust Check verifies

The Trust Check node verifies whether a caller can be trusted before traffic reaches downstream components (for example, a Managed Agent). Verification can include:

- Caller identity validation

- Trust Registry recognition checks

- Authorisation checks

- Policy-input enrichment for enforcement

## Important behaviour

Trust Check itself does not block requests.

Trust Check only produces structured results. The final decision is made by Policy, typically by evaluating input.trust_check_results.* fields.

## Typical execution flow

```text
Access Point
  ↓
Identity Node
  ↓
Trust Check
  ↓
Policy
  ↓
Managed Agent
```

The first step is establishing caller identity. Identity is typically derived from request payload fields and transformed into an identity object for trust verification.

## Supported Trust Check query types

A Trust Check node can contain multiple verification queries. Two query types are supported:

- Recognition queries

- Authorisation queries

You can configure up to 10 trust registry queries in a single Trust Check node.

If multiple trust registries are relevant, configure all required registries and evaluate them in one Trust Check stage.

### Recognition

Recognition verifies whether an identity is recognised by the selected Trust Registry.

### Authorization

Authorization verifies whether an identity is allowed to perform a specific action on a specific resource.

For example, Authorization can answer the question:

Is this caller allowed to send a message?

Authorization supports custom actions and resources.

## How queries are executed

Trust Check executes all configured queries against the selected Trust Registry configuration from the node sidebar.

The output is written into Trust Check result fields and then consumed by Policy.

## Enforce with Policy (allow or deny)

Use a surface policy to enforce Trust Check outcomes. A common pattern is to require every caller-leg Trust Check result to be successful:

```rego
package surface.policy

default allow = false

allow if {
    every r in input.trust_check_results.caller { r.ok }
}
```

In this model:

- Trust Check produces evidence

- Policy enforces access

- Failed conditions typically result in 403 Forbidden

## Authority sources for verification

Authority can come from:

- Surface configuration

- Provider information carried in Trust Registry extensions in the payload

When payload trust metadata is present, the provider ID from that metadata can be used as verification authority.

## Observe and troubleshoot with logs

Trust verification results should be visible in logs.

Example (shortened) runtime sequence for a successful caller-leg validation:

```text
2026-07-07T04:31:05.891647Z  INFO Found matching response for thread bd3e031a-22d3-4b29-ba34-bdb0e6819a28: https://affinidi.com/didcomm/protocols/trqp/1.0/query-authorization/response
2026-07-07T04:31:05.907647Z  INFO Received response: https://affinidi.com/didcomm/protocols/trqp/1.0/query-authorization/response
2026-07-07T04:31:05.968448Z  INFO Found matching response for thread 891a1d37-a954-4447-8a58-36138c6be7b2: https://affinidi.com/didcomm/protocols/trqp/1.0/query-recognition/response
2026-07-07T04:31:05.984913Z  INFO Received response: https://affinidi.com/didcomm/protocols/trqp/1.0/query-recognition/response
2026-07-07T04:31:06.324767Z  INFO [OPA-INPUT] Channel policy input before eval: {"http":{"method":"POST","path":"/","headers":{"x-forwarded-for":"[REDACTED-IP]","user-agent":"PostmanRuntime/7.54.0","host":"[REDACTED-IP]:8839","content-type":"application/json"}},"gateway":{"direction":"inbound"},"channel":{"config_id":"b96cff84-1bab-42dd-a923-cfc7cd46390e","name":"OSCAR"},"trust_check_results":{"caller":[{"query_type":"authorization","ok":true,"name":"isProviderAuthorized_registry_agents"},{"query_type":"recognition","ok":true,"name":"isProviderRecognized_is_registeredDepartment"},{"query_type":"recognition","ok":true,"name":"isEntityRecognized_is_ownedAgent"}],"target":[]}} channel="b96cff84-1bab-42dd-a923-cfc7cd46390e"
2026-07-07T04:31:06.360911Z  INFO [CHANNEL:b96cff84-1bab-42dd-a923-cfc7cd46390e] ✅ MULTI_CHANNEL_HANDLER: Received success response with status 200 OK
```

How to read this sequence:

- TRQP response lines confirm the registry answered both Authorization and Recognition queries.

- The [OPA-INPUT] line shows trust_check_results.caller[*].ok values available to surface policy.

- A final 200 OK means policy conditions passed for this request path.

- If policy denies, expect the same sequence up to OPA input, followed by a deny outcome (typically 403).

Use logs to determine:

- Which trust queries were executed.

- Whether Recognition passed or failed.

- Whether Authorisation passed or failed.

- Why Policy returned a 403.

For request tracing and policy decision details, see [Observability](/products/affinidi-trust-fabric/agent-gateway/concepts/observability.md).

## Trust Recorder

The Trust Recorder is a configurable component that publishes trust recognition records for Managed Agents into one or more configured Trust Registries.

The Trust Recorder provides a verifiable trust footprint for Managed Agents without impacting runtime request handling. It publishes recognition records that establish:

- Which agents are owned by a particular issuer.

- Additional trust assertions about the agent.

- Trust relationships that can later be evaluated through Trust Check operations.

The recorder acts as a publisher of trust metadata and is not involved in runtime authorisation decisions.

### Configuration model

A surface can have one or more Trust Recorder configurations. Each configuration consists of:

- Target Trust Registry

- Issuer DID

- Optional custom actions

```yaml
trustRecorder:
  - trustRegistry: alpha-registry
    issuer: did:web:example.com:issuer

  - trustRegistry: beta-registry
    issuer: did:web:regional.com:issuer
```

### Trust Registry selection

A single surface may publish to one or multiple Trust Registries. Each Trust Registry configuration is processed independently.

```yaml
trustRecorder:
  - trustRegistry: alpha-registry
    issuer: did:web:alpha.com:issuer

  - trustRegistry: beta-registry
    issuer: did:web:beta.com:issuer

  - trustRegistry: gamma-registry
    issuer: did:web:gamma.com:issuer
```

### Trust chain model

The Trust Recorder follows the same trust-anchor hierarchy used in Trust Registry integrations:

```
Trust Authority
      │
      ▼
   Issuer
      │
      ▼
Managed Agent
```

Three trust relationships must be established:

1. Issuer registration

```
Authority : Trust Authority
Entity    : Issuer
Action    : is
Resource  : registeredDepartment
```

2. Issuer agent registration rights

```
Authority : Trust Authority
Entity    : Issuer
Action    : register
Resource  : agents
```

3. Managed Agent ownership (automatically generated by the Trust Recorder)

```
Authority : Issuer
Entity    : Agent
Action    : is
Resource  : ownedAgent
```

### Default recording behavior

Whenever a Managed Agent successfully returns an HTTP 200 response, the Trust Recorder creates a default ownership record:

```json
{
  "authority": "did:web:example.com:issuer",
  "entity": "did:web:example.com:bravo",
  "action": "is",
  "resource": "ownedAgent"
}
```

This record establishes that the Managed Agent belongs to the configured Issuer.
