---
# System prepended metadata

title: AuthZEN Authorization API 1.0 - Certification

---

# MOVED TO https://github.com/openid/authzen/issues/433

















----


# AuthZEN Authorization API 1.0 - Certification

## Status

Draft - For Working Group Discussion

## Introduction

This document defines the conformance certification profile for Policy Decision Points (PDPs) implementing the AuthZEN Authorization API 1.0 specification.

The certification verifies **protocol conformance**: that the PDP correctly accepts well-formed requests and returns correctly structured responses per the specification. The certification does **not** verify the correctness of authorization decisions -- whether a PDP permits or denies a given request is a function of the implementer's policy.

To exercise the protocol, the PDP under test must be loaded with a minimal policy and dataset so that the harness can receive real responses. This profile defines the required fixture in Section 1. The fixture is deliberately small -- it exists to give the PDP something to evaluate, not to test policy logic.

## Notational Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

## 1. Required Fixture

The PDP under test MUST be configured with the following minimal fixture so that the harness can exercise all API endpoints against known entity identifiers and receive valid responses.

### 1.1 Subjects

The PDP MUST recognise the following subjects:

| Subject ID | Subject Type | Properties |
|------------|-------------|------------|
| `alice` | `user` | |
| `bob` | `user` | `role`: `"admin"` |

### 1.2 Resources

The PDP MUST recognise the following resources:

| Resource ID | Resource Type | Properties |
|-------------|--------------|------------|
| `record-1` | `record` | `status`: `"active"` |
| `record-2` | `record` | `status`: `"archived"` |

### 1.3 Actions

The PDP MUST recognise the following action names:

| Action Name | Properties |
|-------------|------------|
| `read` | |
| `write` | |
| `delete` | `soft`: `true` or `false` |

### 1.4 Required Policy Behaviour

The PDP MUST implement a policy such that:

1. For subject `alice` performing action `read` on resource `record-1`: the decision MUST be `true`.
2. For subject `alice` performing action `write` on resource `record-1`: the decision MUST be `true`.
3. For subject `bob` performing action `read` on resource `record-1`: the decision MUST be `true`.
4. For subject `bob` performing action `write` on resource `record-1`: the decision MUST be `false`.
5. For subject `alice` performing action `write` on a resource with `properties.status` = `"archived"`: the decision MUST be `false`.
6. For a subject with `properties.role` = `"admin"` performing action `write` on a resource with `properties.status` = `"archived"`: the decision MUST be `true`.
7. For subject `alice` performing action `delete` with `properties.soft` = `true` on resource `record-1`: the decision MUST be `true`.
8. For subject `alice` performing action `delete` with `properties.soft` = `false` on resource `record-1`: the decision MUST be `false`.

Rules 1-4 use only identifier fields. Rules 5-8 require the PDP to evaluate `properties` values passed in the request.

These eight decisions are the **only** decision values the harness validates. All other requests to the PDP use fixture entity identifiers but the harness only validates response structure, not the decision value.

How the PDP implements this policy is entirely at the implementer's discretion. The fixture could be a single hard-coded rule, a full RBAC model, or anything in between.

### 1.5 Search Fixture Requirements (Search Certification Only)

For Search certification, the fixture MUST be configured such that:

1. A Subject Search for subjects of type `user` who can perform `read` on resource `record-1` MUST return a non-empty `results` array that includes at least `alice` and `bob`.
2. A Resource Search for resources of type `record` that subject `alice` can perform `read` on MUST return a non-empty `results` array that includes at least `record-1`.
3. An Action Search for subject `alice` on resource `record-1` MUST return a non-empty `results` array that includes at least `read`.

These conditions ensure the harness can validate that search responses contain structurally valid, non-empty result sets. The harness validates that the expected entities appear in the results but does not reject additional results.

### 1.6 Fixture Notes

- **Rules 1-4 use identifier fields only.** The harness sends `type`, `id`, and `name` without `properties`. The PDP may resolve attributes internally or the policy may not require them.
- **Rules 5-8 require properties.** The harness sends `properties` on subject, resource, and/or action. The PDP MUST evaluate these values to produce the correct decision.
- **The `context` field is not required for fixture decisions.** The eight required decisions in Section 1.4 MUST hold regardless of whether `context` is present or absent in the request.
- **Additional entities are permitted.** The PDP MAY have additional subjects, resources, actions, and policies beyond the fixture. The harness only sends requests using the fixture identifiers defined above.

---

## 2. Basic Certification: Access Evaluation API

### 2.1 Endpoint

The PDP MUST expose the Access Evaluation API at:

```
POST /access/v1/evaluation
```

Or at a path discoverable via the PDP metadata endpoint (see Section 6).

### 2.2 Request Acceptance

The PDP MUST accept a valid Access Evaluation request containing `subject`, `action`, and `resource` and return an HTTP 200 response.

#### 2.2.1 Fixture request -- permit decision

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": true
}
```

This is a fixture request (Section 1.4, rule 1). The harness validates both the response structure and the decision value.

#### 2.2.2 Fixture request -- deny decision

**Request:**
```json
{
  "subject": { "type": "user", "id": "bob" },
  "action": { "name": "write" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": false
}
```

This is a fixture request (Section 1.4, rule 4). The harness validates both the response structure and the decision value.

#### 2.2.3 Request with optional context

The PDP MUST accept a request that includes the optional `context` field without error. The fixture decision MUST NOT change.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" },
  "context": {
    "time": "2025-06-27T18:03-07:00",
    "ip": "192.168.1.1"
  }
}
```

**Expected:** HTTP 200, `"decision": true`.

#### 2.2.4 Fixture request -- deny based on properties

The PDP MUST evaluate `properties` values passed in the request. This test validates rule 5 from Section 1.4.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "write" },
  "resource": {
    "type": "record",
    "id": "record-2",
    "properties": {
      "status": "archived"
    }
  }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": false
}
```

This is a fixture request (Section 1.4, rule 5). The harness validates both the response structure and the decision value. The deny is based on `properties.status` being `"archived"`, not on the resource identifier.

#### 2.2.5 Fixture request -- permit based on subject properties

The PDP MUST evaluate `properties` on the subject. This test validates rule 6 from Section 1.4.

**Request:**
```json
{
  "subject": {
    "type": "user",
    "id": "bob",
    "properties": {
      "role": "admin"
    }
  },
  "action": { "name": "write" },
  "resource": {
    "type": "record",
    "id": "record-2",
    "properties": {
      "status": "archived"
    }
  }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": true
}
```

This is a fixture request (Section 1.4, rule 6). The harness validates both the response structure and the decision value. The permit is based on `subject.properties.role` being `"admin"`, which overrides the archived resource constraint from rule 5.

#### 2.2.6 Fixture request -- permit based on action properties

The PDP MUST evaluate `properties` on the action. This test validates rule 7 from Section 1.4.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": {
    "name": "delete",
    "properties": {
      "soft": true
    }
  },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": true
}
```

This is a fixture request (Section 1.4, rule 7). Soft delete is permitted.

#### 2.2.7 Fixture request -- deny based on action properties

This test validates rule 8 from Section 1.4.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": {
    "name": "delete",
    "properties": {
      "soft": false
    }
  },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": false
}
```

This is a fixture request (Section 1.4, rule 8). Hard delete is denied.

#### 2.2.8 Request with additional properties

The PDP MUST accept a request where entities include additional `properties` beyond those required by the fixture.

**Request:**
```json
{
  "subject": {
    "type": "user",
    "id": "alice",
    "properties": {
      "department": "Sales",
      "role": "manager"
    }
  },
  "action": {
    "name": "read",
    "properties": {
      "method": "GET"
    }
  },
  "resource": {
    "type": "record",
    "id": "record-1",
    "properties": {
      "status": "active",
      "owner": "bob"
    }
  }
}
```

**Expected:** HTTP 200, `"decision": true`.

#### 2.2.9 Request with unknown fields

Per the specification's forward-compatibility requirement, the PDP MUST ignore unrecognised fields in the request body without error.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" },
  "foo": "bar",
  "futureField": { "nested": true }
}
```

**Expected:** HTTP 200, `"decision": true`.

### 2.3 Response Format

#### 2.3.1 Decision field is required

The response MUST contain a `decision` field with a boolean value.

The harness validates:
- The response body is valid JSON.
- The `decision` field is present.
- The `decision` field is a boolean (`true` or `false`).

#### 2.3.2 Response context is permitted

The PDP MAY include a `context` field in the response. If present, it MUST be a JSON object. The harness does not validate the contents of the response context.

### 2.4 Error Handling

#### 2.4.1 Missing required fields

The PDP MUST return HTTP 400 when a required field is missing from the request.

**Request (missing `subject`):**
```json
{
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (missing `action`):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (missing `resource`):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" }
}
```

**Expected:** HTTP 400.

#### 2.4.2 Missing required sub-fields

The PDP MUST return HTTP 400 when a required sub-field is missing.

**Request (subject missing `type`):**
```json
{
  "subject": { "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (subject missing `id`):**
```json
{
  "subject": { "type": "user" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (action missing `name`):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": {},
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (resource missing `type`):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (resource missing `id`):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record" }
}
```

**Expected:** HTTP 400.

#### 2.4.3 Invalid content type

The PDP MUST return HTTP 400 when the request `Content-Type` is not `application/json`.

#### 2.4.4 Malformed JSON

The PDP MUST return HTTP 400 when the request body is not valid JSON.

#### 2.4.5 Empty request body

The PDP MUST return HTTP 400 when the request body is empty.

#### 2.4.6 Invalid field types

The PDP MUST return HTTP 400 when a field has an invalid type.

**Request (subject is string instead of object):**
```json
{
  "subject": "alice",
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Request (action.name is number instead of string):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": 123 },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

### 2.5 Header Handling

#### 2.5.1 X-Request-ID echo

If the request includes an `X-Request-ID` header, the PDP MUST include the same `X-Request-ID` value in the response headers.

#### 2.5.2 X-Request-ID absent

If the request does not include an `X-Request-ID` header, the PDP MUST NOT fail. The PDP MAY generate its own `X-Request-ID` in the response.

### 2.6 Idempotency

The harness sends the same fixture request multiple times consecutively. The PDP MUST return the same `decision` value each time.

---

## 3. Batch Certification: Access Evaluations API

Batch certification requires Basic certification as a prerequisite.

### 3.1 Endpoint

The PDP MUST expose the Access Evaluations API at:

```
POST /access/v1/evaluations
```

Or at a path discoverable via the PDP metadata endpoint.

### 3.2 Request Acceptance

#### 3.2.1 Batch request with evaluations array

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "evaluations": [
    {
      "resource": { "type": "record", "id": "record-1" }
    },
    {
      "resource": { "type": "record", "id": "record-2" }
    }
  ]
}
```

**Expected:** HTTP 200 with a response body containing an `evaluations` array of two decision objects. Each object MUST contain a `decision` boolean.

```json
{
  "evaluations": [
    { "decision": <boolean> },
    { "decision": <boolean> }
  ]
}
```

#### 3.2.2 Batch with fixture decisions validated

**Request:**
```json
{
  "subject": { "type": "user", "id": "bob" },
  "resource": { "type": "record", "id": "record-1" },
  "evaluations": [
    {
      "action": { "name": "read" }
    },
    {
      "action": { "name": "write" }
    }
  ]
}
```

**Expected:** HTTP 200.
```json
{
  "evaluations": [
    { "decision": true },
    { "decision": false }
  ]
}
```

The harness validates both structure and decision values because both requests correspond to fixture rules (Section 1.4, rules 3 and 4). This also validates response ordering -- `read` (permit) must be first, `write` (deny) must be second.

#### 3.2.3 Batch with properties validated

This test validates that the PDP evaluates `properties` values in batch requests (Section 1.4, rules 2 and 5).

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "write" },
  "evaluations": [
    {
      "resource": {
        "type": "record",
        "id": "record-1",
        "properties": { "status": "active" }
      }
    },
    {
      "resource": {
        "type": "record",
        "id": "record-2",
        "properties": { "status": "archived" }
      }
    }
  ]
}
```

**Expected:** HTTP 200.
```json
{
  "evaluations": [
    { "decision": true },
    { "decision": false }
  ]
}
```

The first evaluation permits (alice can write to active records). The second evaluation denies (rule 5: archived status blocks write). This validates that properties are evaluated per-item in the batch.

#### 3.2.4 Batch with subject properties validated

This test validates that the PDP evaluates subject `properties` in batch requests (Section 1.4, rules 5 and 6).

**Request:**
```json
{
  "action": { "name": "write" },
  "resource": {
    "type": "record",
    "id": "record-2",
    "properties": { "status": "archived" }
  },
  "evaluations": [
    {
      "subject": { "type": "user", "id": "alice" }
    },
    {
      "subject": {
        "type": "user",
        "id": "bob",
        "properties": { "role": "admin" }
      }
    }
  ]
}
```

**Expected:** HTTP 200.
```json
{
  "evaluations": [
    { "decision": false },
    { "decision": true }
  ]
}
```

The first evaluation denies (rule 5: alice cannot write to archived). The second evaluation permits (rule 6: admin role overrides archived constraint). This validates that subject properties are evaluated per-item in the batch.

#### 3.2.5 Batch with fully specified evaluations (no defaults)

**Request:**
```json
{
  "evaluations": [
    {
      "subject": { "type": "user", "id": "alice" },
      "action": { "name": "read" },
      "resource": { "type": "record", "id": "record-1" }
    },
    {
      "subject": { "type": "user", "id": "bob" },
      "action": { "name": "write" },
      "resource": { "type": "record", "id": "record-1" }
    }
  ]
}
```

**Expected:** HTTP 200. Evaluations array of two elements with decisions `true` and `false` respectively.

#### 3.2.6 Batch with context inheritance

Top-level `context` applies to all evaluations unless overridden per-evaluation.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "context": {
    "time": "2025-06-27T18:03-07:00"
  },
  "evaluations": [
    {
      "resource": { "type": "record", "id": "record-1" }
    },
    {
      "resource": { "type": "record", "id": "record-2" },
      "context": {
        "time": "2025-06-27T19:00-07:00",
        "source": "batch-override"
      }
    }
  ]
}
```

**Expected:** HTTP 200 with two evaluations. The harness validates that the request is accepted; the decision values are not validated (not fixture rules).

### 3.3 Response Format

#### 3.3.1 Response array length matches request

The `evaluations` array in the response MUST have the same number of elements as the `evaluations` array in the request.

#### 3.3.2 Response ordering

The `evaluations` array in the response MUST be in the same order as the `evaluations` array in the request.

#### 3.3.3 Each evaluation contains a decision

Each element in the response `evaluations` array MUST contain a `decision` field with a boolean value. Each element MAY contain a `context` field.

#### 3.3.4 Top-level decision field

When the response contains an `evaluations` array, the top-level `decision` field SHOULD be omitted. If present, the harness ignores it.

### 3.4 Error Handling

#### 3.4.1 Evaluation-level errors

If a single evaluation within a batch fails (e.g. due to missing required fields in that evaluation), the PDP MAY return `"decision": false` with error details in the `context` field for that evaluation, or MAY fail the entire request. The harness validates that the request returns HTTP 200 with the correct number of evaluations.

**Request (second evaluation missing resource):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "evaluations": [
    {
      "resource": { "type": "record", "id": "record-1" }
    },
    {}
  ]
}
```

**Expected:** HTTP 200 with two evaluations. The second evaluation SHOULD have `"decision": false`.

#### 3.4.2 Missing evaluations array (backwards-compatible)

Per the specification, if the `evaluations` array is not present, the Access Evaluations endpoint behaves in a backwards-compatible manner with the single Access Evaluation API. The PDP MUST accept a valid request with `subject`, `action`, and `resource` at the top level and return an Access Evaluation response.

**Request (missing evaluations):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": true
}
```

This is a fixture request (Section 1.4, rule 1). The harness validates both the response structure and the decision value.

#### 3.4.3 Empty evaluations array (backwards-compatible)

Per the specification, if the `evaluations` array is empty, the Access Evaluations endpoint behaves in a backwards-compatible manner with the single Access Evaluation API. The PDP MUST accept a valid request with `subject`, `action`, and `resource` at the top level and return an Access Evaluation response.

**Request (empty evaluations):**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" },
  "evaluations": []
}
```

**Expected:** HTTP 200. Response body:
```json
{
  "decision": true
}
```

This is a fixture request (Section 1.4, rule 1). The harness validates both the response structure and the decision value.

---

## 4. Search Certification

### 4.1 Endpoints

The PDP MUST expose the following Search APIs:

```
POST /access/v1/search/subject
POST /access/v1/search/resource
POST /access/v1/search/action
```

Or at paths discoverable via the PDP metadata endpoint.

### 4.2 Subject Search

#### 4.2.1 Valid subject search request with non-empty results

**Request:**
```json
{
  "subject": { "type": "user" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200 with a `results` array. Per the fixture (Section 1.5), the results MUST include at least:
```json
{
  "results": [
    { "type": "user", "id": "alice" },
    { "type": "user", "id": "bob" }
  ]
}
```

The harness validates:
- HTTP 200 response.
- `results` is an array.
- Each element contains `type` and `id`.
- Each element's `type` matches the requested type (`user`).
- `alice` and `bob` appear in the results.
- Additional results beyond `alice` and `bob` are permitted.

#### 4.2.2 Subject search with context

The PDP MUST accept a Subject Search request that includes the optional `context` field.

#### 4.2.3 Subject search with subject id present

Per the specification, `subject.id` should be omitted from Subject Search requests. The harness does not send `subject.id` in Subject Search requests.

### 4.3 Resource Search

#### 4.3.1 Valid resource search request with non-empty results

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "action": { "name": "read" },
  "resource": { "type": "record" }
}
```

**Expected:** HTTP 200 with a `results` array. Per the fixture (Section 1.5), the results MUST include at least:
```json
{
  "results": [
    { "type": "record", "id": "record-1" }
  ]
}
```

The harness validates:
- HTTP 200 response.
- `results` is an array.
- Each element contains `type` and `id`.
- Each element's `type` matches the requested type (`record`).
- `record-1` appears in the results.
- Additional results are permitted.

#### 4.3.2 Resource search with resource id present

Per the specification, `resource.id` should be omitted from Resource Search requests. The harness does not send `resource.id` in Resource Search requests.

### 4.4 Action Search

#### 4.4.1 Valid action search request with non-empty results

Note: the `action` field is omitted entirely from Action Search requests.

**Request:**
```json
{
  "subject": { "type": "user", "id": "alice" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 200 with a `results` array. Per the fixture (Section 1.5), the results MUST include at least:
```json
{
  "results": [
    { "name": "read" }
  ]
}
```

The harness validates:
- HTTP 200 response.
- `results` is an array.
- Each element contains a `name` field.
- `read` appears in the results.
- Additional results are permitted.

#### 4.4.2 Action search with context

The PDP MUST accept an Action Search request that includes the optional `context` field.

### 4.5 Pagination

#### 4.5.1 Request with page limit

The PDP MUST accept a search request that includes a `page` object with a `limit` field.

**Request:**
```json
{
  "subject": { "type": "user" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" },
  "page": {
    "limit": 1
  }
}
```

**Expected:** HTTP 200 with a `results` array. If the PDP supports pagination, the response MAY include a `page` object.

The harness validates:
- HTTP 200 response.
- `results` is an array.
- If `page` is present in the response, it MUST be an object.
- If `page.next_token` is present, it MUST be a string.

#### 4.5.2 Request with page token

If the PDP returned a non-empty `next_token` in a previous response, the harness sends a follow-up request with that token.

**Request:**
```json
{
  "subject": { "type": "user" },
  "action": { "name": "read" },
  "resource": { "type": "record", "id": "record-1" },
  "page": {
    "token": "<next_token from previous response>"
  }
}
```

**Expected:** HTTP 200 with a `results` array.

The harness validates:
- HTTP 200 response.
- `results` is an array.
- If more results exist, `page.next_token` is a non-empty string.
- If no more results exist, `page.next_token` is an empty string or `page` is absent.

#### 4.5.3 Pagination response format

If the PDP returns paginated results, the response `page` object:
- MUST contain `next_token` (string). Empty string signals end of results.
- MAY contain `count` (number of results in this response).
- MAY contain `total` (total number of matching results).
- MAY contain `properties` (implementation-specific metadata).

#### 4.5.4 Pagination is optional

The PDP MAY support pagination on search endpoints. If it does not support pagination, it MUST:
- Return all results in a single response.
- Accept requests containing a `page` object without error (ignoring it).
- Omit the `page` object from the response, or return `page.next_token` as an empty string.

### 4.6 Empty results

The PDP MUST return an empty `results` array (not an error) when no entities match the search criteria. The harness tests this by sending a search request with an entity identifier not in the fixture.

**Request:**
```json
{
  "subject": { "type": "user", "id": "nonexistent-user" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:**
```json
{
  "results": []
}
```

### 4.7 Search Error Handling

#### 4.7.1 Missing required fields

The PDP MUST return HTTP 400 when a required field is missing from a search request.

**Subject Search (missing `action`):**
```json
{
  "subject": { "type": "user" },
  "resource": { "type": "record", "id": "record-1" }
}
```

**Expected:** HTTP 400.

**Resource Search (missing `subject`):**
```json
{
  "action": { "name": "read" },
  "resource": { "type": "record" }
}
```

**Expected:** HTTP 400.

**Action Search (missing `resource`):**
```json
{
  "subject": { "type": "user", "id": "alice" }
}
```

**Expected:** HTTP 400.

#### 4.7.2 Missing required sub-fields

**Subject Search (resource missing `id`):**
```json
{
  "subject": { "type": "user" },
  "action": { "name": "read" },
  "resource": { "type": "record" }
}
```

**Expected:** HTTP 400.

**Resource Search (subject missing `id`):**
```json
{
  "subject": { "type": "user" },
  "action": { "name": "read" },
  "resource": { "type": "record" }
}
```

**Expected:** HTTP 400.

---

## 5. Transport Requirements

These requirements apply to all certification levels.

1. The PDP MUST accept HTTPS requests with `Content-Type: application/json`.
2. Successful evaluation and search responses MUST return HTTP 200 with `Content-Type: application/json`.
3. Missing required fields MUST return HTTP 400.
4. The PDP MUST echo the `X-Request-ID` header if present in the request.
5. The PDP MUST ignore unknown fields in the request body.

---

## 6. PDP Metadata Discovery

### 6.1 Metadata Endpoint

The PDP SHOULD expose a metadata endpoint at:

```
GET /.well-known/authzen-configuration
```

### 6.2 Metadata Response Format

If exposed, the response MUST be HTTP 200 with `Content-Type: application/json`.

**Example response:**
```json
{
  "policy_decision_point": "https://pdp.example.com",
  "access_evaluation_endpoint": "https://pdp.example.com/access/v1/evaluation",
  "access_evaluations_endpoint": "https://pdp.example.com/access/v1/evaluations",
  "search_subject_endpoint": "https://pdp.example.com/access/v1/search/subject",
  "search_resource_endpoint": "https://pdp.example.com/access/v1/search/resource",
  "search_action_endpoint": "https://pdp.example.com/access/v1/search/action",
  "capabilities": ["urn:authzen:evaluation", "urn:authzen:evaluations", "urn:authzen:search"],
  "signed_metadata": "eyJhbGciOiJSUzI1NiIs..."
}
```

### 6.3 Required Metadata Fields

The response MUST include:
- `policy_decision_point` -- Base URL of the PDP (HTTPS, no query string or fragment).
- `access_evaluation_endpoint` -- URL for the Access Evaluation API.

### 6.4 Optional Metadata Fields

The response MAY include:
- `access_evaluations_endpoint` -- URL for the Access Evaluations API.
- `search_subject_endpoint` -- URL for the Subject Search API.
- `search_resource_endpoint` -- URL for the Resource Search API.
- `search_action_endpoint` -- URL for the Action Search API.
- `capabilities` -- Array of capability URNs supported by the PDP.
- `signed_metadata` -- A JSON Web Token (JWT) containing metadata claims. If present, it MUST be digitally signed or MACed using JSON Web Signature (JWS) and MUST contain an `iss` (issuer) claim. Metadata values in the signed token take precedence over plain JSON values in the response.

### 6.5 Metadata Validation

The harness validates:
- HTTP 200 response with `Content-Type: application/json`.
- Response body is valid JSON.
- `policy_decision_point` is present and matches the base URL used for discovery.
- `access_evaluation_endpoint` is present and is a valid HTTPS URL.
- If `access_evaluations_endpoint` is present, it is a valid HTTPS URL.
- If `search_*_endpoint` fields are present, they are valid HTTPS URLs.
- If `capabilities` is present, it is an array of strings.
- If `signed_metadata` is present, it is a valid JWT string with a verifiable signature and contains an `iss` claim.

### 6.6 Metadata Endpoint Unavailable

If the metadata endpoint is not available (HTTP 404), the harness falls back to the default paths defined in the specification:
- `/access/v1/evaluation`
- `/access/v1/evaluations`
- `/access/v1/search/subject`
- `/access/v1/search/resource`
- `/access/v1/search/action`
