Adds the full bedroom-developer-docs OpenSpec change implementation: - docs/developers/README.md — index page - docs/developers/quick-start.md — bootstrap to working token in 7 steps - docs/developers/concepts.md — AgentIdP, AGNTCY, lifecycle, OAuth 2.0, free tier - docs/developers/guides/README.md — guide index - docs/developers/guides/register-an-agent.md — all fields, validation, common errors - docs/developers/guides/manage-credentials.md — generate, list, rotate, revoke - docs/developers/guides/issue-and-revoke-tokens.md — OAuth 2.0 flow, introspect, revoke - docs/developers/guides/query-audit-logs.md — filters, pagination, 90-day retention - docs/developers/api-reference.md — all 14 endpoints, all error codes, curl examples Also commits deferred OpenSpec housekeeping from previous session: - Archives phase-1-mvp-implementation change to openspec/changes/archive/ - Adds bedroom-developer-docs change artifacts (30/30 tasks complete) - Syncs 4 delta specs to openspec/specs/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
87 lines
5.7 KiB
Markdown
87 lines
5.7 KiB
Markdown
## 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
|