## ADDED Requirements

### Requirement: Register a new AI agent
The system SHALL create a new agent identity record with a system-assigned immutable UUID (`agentId`) when a valid `CreateAgentRequest` is received. The `email` field SHALL be unique across all agents. The agent SHALL be created with `status: active`. The system SHALL enforce a free-tier limit of 100 registered agents per account.

#### Scenario: Successful agent registration
- **WHEN** a POST request to `/agents` is received with a valid `CreateAgentRequest` body and a valid Bearer token
- **THEN** the system creates the agent, assigns a UUID `agentId`, sets `status` to `active`, sets `createdAt` and `updatedAt` to the current timestamp, and returns `201` with the full `Agent` object

#### Scenario: Duplicate email rejected
- **WHEN** a POST request to `/agents` is received with an `email` that is already registered
- **THEN** the system returns `409 Conflict` with `code: AGENT_ALREADY_EXISTS`

#### Scenario: Free tier limit enforced
- **WHEN** a POST request to `/agents` is received and the account already has 100 registered agents
- **THEN** the system returns `403 Forbidden` with `code: FREE_TIER_LIMIT_EXCEEDED` and `details.limit: 100`

#### Scenario: Invalid request body rejected
- **WHEN** a POST request to `/agents` is received with a missing required field or invalid field value (e.g. invalid semver, invalid email, invalid capability pattern)
- **THEN** the system returns `400 Bad Request` with `code: VALIDATION_ERROR` and `details` identifying the failing field

### Requirement: Retrieve a single agent by ID
The system SHALL return the full `Agent` record for a given `agentId`.

#### Scenario: Agent found
- **WHEN** a GET request to `/agents/{agentId}` is received with a valid Bearer token and a UUID that exists in the registry
- **THEN** the system returns `200 OK` with the full `Agent` object

#### Scenario: Agent not found
- **WHEN** a GET request to `/agents/{agentId}` is received with a UUID that does not exist
- **THEN** the system returns `404 Not Found` with `code: AGENT_NOT_FOUND`

### Requirement: List agents with pagination and filtering
The system SHALL return a paginated list of agents, orderd by `createdAt` descending, optionally filtered by `owner`, `agentType`, and/or `status`.

#### Scenario: Successful paginated list
- **WHEN** a GET request to `/agents` is received with optional `page`, `limit`, `owner`, `agentType`, `status` query parameters and a valid Bearer token
- **THEN** the system returns `200 OK` with a `PaginatedAgentsResponse` containing `data`, `total`, `page`, and `limit`

#### Scenario: Invalid pagination parameters rejected
- **WHEN** a GET request to `/agents` is received with `limit` greater than 100 or `page` less than 1
- **THEN** the system returns `400 Bad Request` with `code: VALIDATION_ERROR`

### Requirement: Update agent metadata
The system SHALL partially update a mutable agent record. `agentId`, `email`, and `createdAt` SHALL be immutable. Setting `status` to `decommissioned` SHALL be a one-way irreversible operation.

#### Scenario: Successful partial update
- **WHEN** a PATCH request to `/agents/{agentId}` is received with a valid partial `UpdateAgentRequest` body and a valid Bearer token
- **THEN** the system updates only the provided fields, sets `updatedAt` to the current timestamp, and returns `200 OK` with the full updated `Agent` object

#### Scenario: Attempt to modify immutable field rejected
- **WHEN** a PATCH request to `/agents/{agentId}` contains the `email` field
- **THEN** the system returns `400 Bad Request` with `code: IMMUTABLE_FIELD` and `details.field: email`

#### Scenario: Decommissioned agent cannot be updated
- **WHEN** a PATCH request to `/agents/{agentId}` targets an agent with `status: decommissioned`
- **THEN** the system returns `403 Forbidden` with `code: AGENT_DECOMMISSIONED`

### Requirement: Decommission (soft-delete) an agent
The system SHALL set an agent's `status` to `decommissioned` and revoke all of its active credentials. The agent record SHALL be retained for audit purposes. This operation SHALL be irreversible.

#### Scenario: Successful decommission
- **WHEN** a DELETE request to `/agents/{agentId}` is received with a valid Bearer token and the agent exists and is not already decommissioned
- **THEN** the system sets `status` to `decommissioned`, revokes all active credentials for this agent, and returns `204 No Content`

#### Scenario: Already decommissioned agent rejected
- **WHEN** a DELETE request to `/agents/{agentId}` is received for an agent that is already `decommissioned`
- **THEN** the system returns `409 Conflict` with `code: AGENT_ALREADY_DECOMMISSIONED`

### Requirement: Authentication required on all agent endpoints
All agent endpoints SHALL require a valid Bearer JWT in the `Authorization` header.

#### Scenario: Missing token rejected
- **WHEN** any request to `/agents` or `/agents/{agentId}` is received without an `Authorization: Bearer` header
- **THEN** the system returns `401 Unauthorized` with `code: UNAUTHORIZED`

#### Scenario: Invalid token rejected
- **WHEN** any request to `/agents` or `/agents/{agentId}` is received with an expired, malformed, or revoked Bearer token
- **THEN** the system returns `401 Unauthorized` with `code: UNAUTHORIZED`

### Requirement: Rate limiting on all agent endpoints
The system SHALL enforce a rate limit of 100 requests per minute per authenticated client. Rate limit state SHALL be tracked in Redis.

#### Scenario: Rate limit exceeded
- **WHEN** a client sends more than 100 requests to any agent endpoint within a 60-second window
- **THEN** the system returns `429 Too Many Requests` with `X-RateLimit-Limit`, `X-RateLimit-Remaining: 0`, and `X-RateLimit-Reset` headers
