# Trust elements

> Field reference for the Trust Check and Trust Recorder canvas elements: TRQP verification queries against trust registries, and writing agent-registration records into trust registries.

Two canvas elements operate on trust registries. Trust Check runs TRQP queries against a registry at request time and exposes the results to OPA policies. Trust Recorder writes agent-registration records into registries as requests pass through the surface.

For conceptual background, see [Trust registries](/products/affinidi-trust-fabric/agent-gateway/concepts/connections/trust-registry.md).

## Trust Check

Drop a Trust Check element on a surface edge to run a TRQP query against a trust registry at request time. The Trust Check stage runs all configured elements in parallel and writes results into input.trust_check_results for OPA evaluation.

Two placements are available, each checking a different agent:

- Access Point → Managed Agent edge (caller leg): verifies the inbound caller. Available on all protocols.

- Managed Agent → Transit Point edge (target leg): verifies the downstream agent at the Transit Point destination. The drop slot is available on A2A and AP2 Transit Points only. MCP Transit Points do not offer this slot.

Results are written to OPA under input.trust_check_results.caller and input.trust_check_results.target respectively.

For the OPA fields these results populate, see [OPA policies reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/opa-policies.md).

### Panel

The sidebar panel shows the configured queries as a read-only list (query type and trust registry name). Open the fullscreen editor to add or edit queries. Each leg allows a maximum of 10 queries.

### Query fields

Each query in the fullscreen editor has these fields.

| Field | Required | Description |
| Trust Registry | Yes | Trust registry to query. Selected from your configured trust registries. |
| Record Type | Yes | Authorization: is this entity authorised to perform this action on this resource? Recognition: does this authority recognise this entity? |
| Authority ID | Yes (target leg). Auto on caller leg. | Issuer or Authority DID selected from the gateway’s configured Issuers and Authorities. On the caller leg, leaving this blank defaults to the verified agent-identity-credential issuer ({{ input.agent.identity_issuer_did }}). On the target leg, an explicit selection is required. |
| Entity ID | No | Named-subject dropdown. On the caller leg: the caller’s agent DID (default, {{ input.agent.did }}) or the gateway’s managed-identity DID ({{ input.extension_identity.did }}). On the target leg: the target’s agent DID (default, {{ input.agent.did }}). |
| Action | Yes (Authorization only) | TRQP action string. Required for Authorization queries. Optional for Recognition queries; defaults to is when blank. |
| Resource | Yes (Authorization only) | TRQP resource string. Required for Authorization queries. Optional for Recognition queries; defaults to ownedAgent when blank. |

The id field is auto-generated for each query and used by OPA to address results in input.trust_check_results.{caller|target}[]. It is not editable in the UI.

### Validation constraints

- Each leg allows a maximum of 10 queries.

- Authority ID must be non-blank on the target leg.

- On the caller leg, a stored {{ … }} template other than the verified-issuer default is invalid. Replace it with an explicit Issuer or Authority selection.

- Action and Resource are required for Authorization queries and must not be blank.

- Query id values are auto-generated and must be unique within a leg.

### Template syntax

All four query fields accept {{ }} templates resolved against the input.* JSON the gateway builds for the same request. Templates follow the OPA input namespace, so a value from the policy input is available using the same path you would use in a Rego rule.

```text
{{ input.agent.provider_did }}         → resolved DID of the agent's department/provider
{{ input.agent.did }}                  → effective caller DID
{{ input.source_auth.claims.sub }}     → JWT subject claim (jwt_bearer auth only)
{{ input.http.path }}                  → request path
```

A || fallback operator is supported for fields that may be absent:

```text
{{ input.extension_identity.did || input.agent.did }}
```

The right-hand side is used only when the left-hand side is missing or null. A non-scalar value (array, object) or a malformed template short-circuits with TEMPLATE_RESOLUTION_FAILED and does not fall through to the right-hand side.

When a template fails to resolve, the element produces ok = false with error.code = TEMPLATE_RESOLUTION_FAILED and no TRQP network call is made.

### Result fields

Each element in input.trust_check_results.caller and input.trust_check_results.target has this shape:

```json
{
  "id": "tc-caller-1",
  "trust_registry_id": "tr-main",
  "query_type": "recognition",
  "ok": true,
  "error": null,
  "name": "Verify caller department",
  "authority_id": "did:web:authority.example.com",
  "entity_id": "did:web:caller.example.com",
  "action": "is",
  "resource": "ownedAgent",
  "query_resolved": true
}
```

| Field | Type | Description |
| id | string | Mirrors TrustCheckElement.id. Use this to address the result in Rego. |
| trust_registry_id | string | The registry the query ran against. |
| query_type | string | "recognition" or "authorization". |
| ok | boolean | true when the trust registry allowed the request. false for both clean denials (NOT_RECOGNIZED, NOT_AUTHORIZED) and stage failures. |
| error | object or null | null only when ok is true. Present for all other outcomes: clean denials (NOT_RECOGNIZED, NOT_AUTHORIZED) and stage failures alike. |
| error.code | string | One of the error codes below. |
| error.message | string | Human-readable detail. For TRUST_REGISTRY_PROBLEM_REPORT, this is the registry-supplied problem report code; Rego can branch on it without the gateway taking a position on whether it represents a denial or a transport error. |
| name | string or null | Mirrors TrustCheckElement.name when set. Absent from the wire when the element has no name. |
| authority_id | string or null | The TRQP authority DID as actually sent. Post-template-substitution when query_resolved is true; raw template string on TEMPLATE_RESOLUTION_FAILED. Absent for AGENT_CARD_UNAVAILABLE, TRUST_REGISTRY_METADATA_UNAVAILABLE, IDENTITY_VP_VERIFICATION_FAILED, and TARGET_AGENT_IDENTITY_UNAVAILABLE — the pipeline did not reach the resolution step on those paths. |
| entity_id | string or null | The TRQP entity DID as actually sent. Absent on the same four codes as authority_id. |
| action | string | The TRQP action as sent. For recognition queries with no operator-set value, the wire default "is" is used. Always present. |
| resource | string | The TRQP resource as sent. For recognition queries with no operator-set value, the wire default "ownedAgent" is used. Always present. |
| query_resolved | boolean | true when every template placeholder resolved. false when the executor fell back to raw template strings because resolution failed (TEMPLATE_RESOLUTION_FAILED) or because agent card or trust-registry metadata was unavailable. Always present. |

### Error codes

| Code | Category | Meaning |
| NOT_RECOGNIZED | Clean denial | Recognition query returned a negative verdict — the registry answered that it does not recognise the entity. authority_id, entity_id, action, and resource are populated; query_resolved is true. |
| NOT_AUTHORIZED | Clean denial | Authorization query returned a negative verdict — the registry answered that the entity is not authorised. Same field population as NOT_RECOGNIZED. |
| TRUST_REGISTRY_UNREACHABLE | Stage failure | Outbound TRQP transport could not be established (registry not found, no DIDComm connection, or stale connection). |
| QUERY_FAILED | Stage failure | Transport delivered the exchange but it failed in a way that does not fit a more specific category (for example, a low-level send error). |
| TRUST_REGISTRY_PROBLEM_REPORT | Stage failure | Registry responded with a DIDComm problem report. The registry-supplied code is in error.message; Rego can branch on it without the gateway taking a position on whether the code represents a denial or an error. |
| TRUST_REGISTRY_PARSE_ERROR | Stage failure | Registry response was delivered but could not be parsed into the expected TRQP shape. Distinct from QUERY_FAILED so schema or version drift is observable independently. |
| QUERY_TIMEOUT | Stage failure | The per-element timeout_secs budget elapsed before a response was received. Only emitted when the element carries an explicit timeout override. |
| TEMPLATE_RESOLUTION_FAILED | Stage failure | A {{ }} template could not be resolved against the request context. No network call was made. authority_id and entity_id carry the raw template strings; query_resolved is false. |
| AGENT_CARD_UNAVAILABLE | Stage failure | Target agent card could not be fetched. One result per configured element is synthesised. authority_id and entity_id are absent from the wire. Target leg only. |
| TRUST_REGISTRY_METADATA_UNAVAILABLE | Stage failure | Target agent card was fetched but does not carry a usable trust-registry extension block (provider_did or trust_registry_did absent). Template paths referencing input.agent.provider_did or input.agent.trust_registry_did cannot resolve. authority_id and entity_id are absent. Target leg only. |
| IDENTITY_VP_VERIFICATION_FAILED | Stage failure | Target agent card was fetched, but the agent-identity-credential/v1 Verifiable Presentation it carries failed cryptographic verification (bad proof, expired, or no VCIssuer configured). input.agent.did is cleared so the unverified DID never reaches OPA. authority_id and entity_id are absent. Target leg only. |
| TARGET_AGENT_IDENTITY_UNAVAILABLE | Stage failure | Target agent card was fetched, but it carries no agent-identity-credential/v1 Verifiable Presentation at all. input.agent.did is cleared. authority_id and entity_id are absent. Target leg only. |

### Rego patterns

Address a result by id rather than array index:

```rego
# Allow only when the named element passed
allow if {
  some r in input.trust_check_results.caller
  r.id == "tc-caller-1"
  r.ok == true
}
```

Deny on any stage failure:

```rego
deny if {
  some r in input.trust_check_results.caller
  r.error != null
}
```

Branch on a registry-level problem report code:

```rego
deny if {
  some r in input.trust_check_results.caller
  r.error.code == "TRUST_REGISTRY_PROBLEM_REPORT"
  r.error.message == "AGENT_NOT_RECOGNIZED"
}
```

## Trust Recorder

The Trust Recorder element writes agent-registration records into one or more trust registries on the response leg (Managed Agent → Access Point). It runs after the managed agent responds, so the agent’s DID from the reply is available to record. Each entry targets one registry and specifies the Issuer that signs the records and the Authority that acts as the trust anchor.

### Entry fields

Each row in the entry list configures one registry target.

| Field | Required | Default | Description |
| Trust Registry | Yes | — | Trust registry to write records into. Selected from your configured trust registries. |
| Issuer | Yes | — | Issuer that signs the records written to this registry. Selected from your configured Issuers. |
| Authority | Yes | — | Trust anchor asserting these records. Selected from your configured Authorities or Issuer-derived authority DIDs. |
| Built-in triple | No | On | Checkbox. When on, the gateway writes an ownedAgent record: [Authority] Agent DID is ownedAgent. The agent DID is auto-filled from the response. |

### Custom resources

Each entry can include additional custom records. Custom resources extend the standard owned-agent record with operator-defined registrations.

| Field | Required | Default | Description |
| Action | Yes | — | The action the record authorises or recognises (for example is, invoke). |
| Resource | Yes | — | The resource URI or identifier the action applies to (for example ownedAgent, paymentAgent). |
| Entity target | No | Agent DID | Which DID is written as the entity_id on the record. Options: Agent DID, Issuer DID. |
| Record type | No | recognition | Type of TrAdmin record. Options: recognition, authorization. |

## Related

- [Access Point reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/access-point.md): Trust Check on the caller leg.

- [Managed Agent reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/managed-agent.md): Trust Check on the Managed Agent leg.

- [OPA policies reference](/products/affinidi-trust-fabric/agent-gateway/reference/surfaces/opa-policies.md): how Trust Check results appear as input.trust_check_results in Rego.

- [Trust registries](/products/affinidi-trust-fabric/agent-gateway/concepts/connections/trust-registry.md): conceptual background on TRQP queries and trust registry connections.
