# Servers API

> 서버 목록, 등록, 상세, 수정, 삭제, 토큰 재발급의 REST 계약입니다.

## Endpoint 요약

| Method | Path | Scope |
| --- | --- | --- |
| `GET` | `/api/v1/servers?projectSlug=` | `admin:read` 또는 `servers:read` |
| `POST` | `/api/v1/servers` | `admin:write` 또는 `servers:write` |
| `GET` | `/api/v1/servers/{id}` | `admin:read` 또는 `servers:read` |
| `PATCH` | `/api/v1/servers/{id}` | `admin:write` 또는 `servers:write` |
| `DELETE` | `/api/v1/servers/{id}` | `admin:write` 또는 `servers:write` |
| `POST` | `/api/v1/servers/{id}/rotate-token` | `admin:write` 또는 `servers:write` |

## 인증과 목록

```http
Authorization: Bearer <keyId>.<secret>
```

`GET /servers?projectSlug=`는 `{ "servers": [...] }`를 반환합니다. 조직 키는 조직 전체를 보고, 프로젝트 키는 자신의 프로젝트만 봅니다.

## 생성 요청과 응답

요청 body는 다음 필드를 받을 수 있습니다.

| 필드 | 타입 | 설명 |
| --- | --- | --- |
| `projectSlug` | string? | 프로젝트 키는 생략 가능 |
| `name` | string | 서버 표시 이름 |
| `slug` | string? | 서버 식별자 |
| `intervalSec` | number? | 10에서 60초, 기본 15 |
| `watchedServices` | string\[\]? | 감시할 systemd unit |
| `nginxEnabled` | boolean? | nginx 수집 여부 |

`201` 응답은 `{ server, token, agentEndpoint, install: { ubuntu, macos, nvm } }`입니다. `token`은 1회만 표시됩니다.

```json
{ "server": { "state": "unknown" }, "token": "<one-time-token>", "agentEndpoint": "wss://<agent-endpoint>", "install": { "ubuntu": "...", "macos": "...", "nvm": "..." } }
```

상태 행은 에이전트의 첫 heartbeat에서 생성되므로 등록 직후 `state`는 `unknown`입니다.

## 상세와 변경

상세 `server`는 `state`(`unknown`, `online`, `offline`), `lastSeenAt`, `agentVersion`, 최신 metrics를 포함합니다.
PATCH는 `name`, `intervalSec`, `watchedServices`, `nginxEnabled`를 부분 수정합니다.

## 오류

`401 UNAUTHORIZED`, `403 FORBIDDEN_SCOPE`, `403 project_forbidden`, `403 reserved_project_forbidden`, `403 ip_not_allowed`, `404 SERVER_NOT_FOUND`, `404 PROJECT_NOT_FOUND`, `400 VALIDATION_ERROR`, `409 SLUG_TAKEN`을 반환할 수 있습니다.

## Token rotation과 제한

`POST /servers/{id}/rotate-token`은 이전 토큰을 무효화하고 새 `token`, `agentEndpoint`, `install`을 반환합니다.
회전 응답의 `server.state`는 현재 상태를 반영하며, 상태 행이 없으면 `unknown`입니다.

```json
{ "server": { "state": "online" }, "token": "<new-one-time-token>", "agentEndpoint": "wss://<agent-endpoint>", "install": { "ubuntu": "...", "macos": "...", "nvm": "..." } }
```

서버 API 전체는 keyId마다 60초 60회로 제한되며 초과 시 `429 RATE_LIMITED`와 `Retry-After`를 반환합니다.
