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

# OPA Policies

> Write fine-grained authorization policies that control which agent processes can access which services.

## How OPA Works in Hexr

Every outbound request from an agent container passes through Envoy, which calls **OPA (Open Policy Agent)** before forwarding:

```
Agent → Envoy → OPA (allow/deny?) → Service
```

OPA receives the agent's SPIFFE ID and the requested service, and evaluates your Rego policies.

***

## Policy Input

OPA receives this input for every request:

```json theme={null}
{
  "spiffe_id": "spiffe://hexr.cloud/agent/acme-corp/content-crew/researcher",
  "tenant": "acme-corp",
  "agent": "content-crew",
  "role": "researcher",
  "service": "gcp_bigquery",
  "action": "query",
  "timestamp": "2026-01-15T10:30:00Z"
}
```

***

## Example Policies

### Service Access by Role

```rego theme={null}
package hexr.authz

default allow = false

# Researchers can access BigQuery and S3 (read-only)
allow {
    input.role == "researcher"
    input.service in {"gcp_bigquery", "aws_s3"}
}

# Writers can only write to S3
allow {
    input.role == "writer"
    input.service == "aws_s3"
    input.action == "PutObject"
}

# Editors have no cloud access
# (implicitly denied by default allow = false)
```

### Time-Based Access

```rego theme={null}
# Only allow access during business hours (UTC)
allow {
    input.role == "researcher"
    time.clock(time.now_ns())[0] >= 8    # After 8 AM
    time.clock(time.now_ns())[0] < 18    # Before 6 PM
}
```

### Rate Limiting

```rego theme={null}
# Allow max 100 tool calls per minute per agent
allow {
    count(recent_calls) < 100
}

recent_calls[call] {
    call := data.audit_log[_]
    call.agent == input.agent
    call.timestamp > time.now_ns() - 60000000000  # 1 minute
}
```

***

## Deploying Policies

Policies are deployed as Kubernetes ConfigMaps:

```yaml theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: opa-policy
  namespace: hexr-system
data:
  policy.rego: |
    package hexr.authz
    default allow = false
    allow {
      input.role == "researcher"
      input.service in {"gcp_bigquery", "aws_s3"}
    }
```

***

## Testing Policies

Use OPA's built-in test framework:

```rego theme={null}
test_researcher_bigquery_allowed {
    allow with input as {
        "role": "researcher",
        "service": "gcp_bigquery",
        "action": "query"
    }
}

test_writer_bigquery_denied {
    not allow with input as {
        "role": "writer",
        "service": "gcp_bigquery",
        "action": "query"
    }
}
```

```bash theme={null}
opa test ./policies/ -v
```
