Files
sentryagent-idp/openspec/specs/agent-registry/spec.md
SentryAgent.ai Developer 61ea975c79 docs: bedroom developer documentation — complete docs/developers/ set
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>
2026-03-28 14:13:03 +00:00

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