# Policies

> How Gateway-Level, Surface-Level, and model Rego policies, evaluated by an embedded OPA engine, decide whether a request is allowed.

Guardrails decide whether content is safe. Policy decides whether a caller is allowed to make the request at all, based on identity, context, and organisational rules. Gateway OPA runs before Surface-level OPA, and a gateway deny is final. [Cost and usage governance →](/products/affinidi-trust-fabric/agent-stream/concepts/cost-and-usage-governance.md)

## OPA

OPA is the embedded Rego policy engine used by Agent Stream, so policies are compiled and evaluated in-process with no sidecar or network round trip.

## Gateway-Level Policy

Gateway-Level Policy is the OPA policy attached to the appliance itself and evaluated as the gateway-level gate before any Surface-level checks. A gateway deny is final: no Surface-level policy can override it.

## Surface-Level Policy

Surface-Level Policy is the OPA policy attached to a Surface and evaluated after Gateway-Level Policy. LLM Surface policies use the package llm.policy; IDE Surface policies use the package ide.policy.

## How front-door policy tells discovery apart from dispatch

The IDE Surface’s OPA input distinguishes discovery (GET /v1/models, which a policy can allow unauthenticated) from dispatch (POST /v1/chat/completions, which requires the signed-in caller), so sign-in never hits a chicken-and-egg where a client cannot fetch the sign-in profile because it is not yet signed in.

## How a policy reference points to a reusable definition

- Policy Reference: A pointer from a Surface or a Gateway field to a stored OPA policy definition.

- Policy Definition: Stored Rego source plus metadata that can be reused by many Surfaces or Gateways. Definitions are immutable per version and carry a content hash so audit evidence can prove the exact bytes that ran.

A surface or gateway can also enforce more than one policy at once (policy_definition_ids); the combination is deny-overrides, so every referenced policy must allow a request for it to proceed. An administrator can additionally mark one or more policies as enforced globally across every surface of a type, ANDed with that surface’s own policy set, with a monitor-only rollout mode for observing the effect of a global policy before it blocks anything.

## Model Allow-List

A Model Allow-List is a member-level list of models the Member is permitted to invoke. A request to a model that is not on the allow-list is rejected with 403 model_not_allowed.

## What each of the four policy layers checks

Rego policy is evaluated at four distinct layers, each its own package queried at a fixed path. A deny at any layer stops the request immediately, and a layer earlier in this table cannot be overridden by an allow at a layer later in it:

| Layer | Package | Applies to |
| Trust Fabric | agentstream.policy | Appliance-to-appliance (DIDComm) traffic. Evaluated first; a deny here is final. |
| Surface / fabric | surface.policy | A2A/MCP-style fabric surfaces. Carries the richest input of any layer. |
| LLM Surface | llm.policy | LLM, API, MCP, and Webhook surfaces. |
| IDE front door + per-member Model Policy | ide.policy / llm.policy | The IDE catalogue’s front door, then, after it passes, each catalogue member’s own policy. |

The dashboard labels the first row Trust Fabric; agentstream.policy is retained only as the internal Rego package name, unchanged in stored policies and audit evidence.

  Request
  →
  Trust Fabric policy
  →
  Surface / LLM / IDE policy
  →
  Request continues

## What a policy can see

Agent Stream builds this input document automatically before every evaluation. A policy only ever reads from it and never declares or constructs input itself. Only the fields relevant to the current request are populated, and everything else is omitted:

```json
{
  "http": { "method": "POST", "path": "/v1/chat/completions" },
  "source_auth": { "jwt_bearer": { "subject": "user-123", "claims": { "role": "admin" } } },
  "resource": { "model": "gpt-5.5", "surface_type": "llm" },
  "action": "dispatch",
  "environment": { "now": "2026-01-01T00:00:00Z" },
  "channel": { "variant_alias": "beta" },
  "identity_binding": { "verified": true, "issuer_did": "did:web:issuer.example" }
}
```

A policy reads a value with plain dot notation, such as input.source_auth.claims.role == "admin" to check a JWT claim, or input.resource.model to gate on the requested model. See [Input document →](/products/affinidi-trust-fabric/agent-stream/reference/policies/opa-policies.md#input-document) for the complete field-by-field reference, including the fields not shown here.

## Policies are immutable and versioned

Editing a policy never overwrites it: each save appends a new, numbered version, and prior versions are retained permanently. Every decision, especially a denial, is recorded against the exact version and content hash that was enforced, so any past decision can be proven against the precise policy that produced it. A policy change can also be dry-run against a sample input before it is activated, so a bad global policy doesn’t lock out every surface it applies to.

## Why an embedded, in-process engine matters

Because policy evaluation runs in-process rather than as a network call to a sidecar, a policy decision adds no network latency and has no separate service to keep available.

## Related

- [Guardrails](/products/affinidi-trust-fabric/agent-stream/concepts/guardrails.md): Content-safety checks that run alongside policy in the request pipeline.

- [Cost and attribution](/products/affinidi-trust-fabric/agent-stream/concepts/teams-and-attribution.md): The team gate that runs immediately after Trust Fabric policy.

- [Security and access control](/products/affinidi-trust-fabric/agent-stream/concepts/security-and-access-control.md): How source authentication establishes the identity a policy evaluates.

- [Trust Fabric integration](/products/affinidi-trust-fabric/agent-stream/concepts/trust-fabric-integration.md): The appliance-to-appliance DIDComm traffic the Trust Fabric policy layer evaluates first.

- [Pipeline and stages](/products/affinidi-trust-fabric/agent-stream/concepts/pipeline-and-stages.md): Where Gateway OPA and Surface-level policy run in the inbound stage order.
