# Legacy Public HTTP API (`/api/v1`)（已移除）

> 说明：本文件用于保留早期 `/api/v1` + SSE 方案的历史草案，方便追溯曾经的设计取舍。**相关代码与路由已从仓库移除**，请勿在实现中继续维护或引用该 API。
>
> 当前对外兼容的单一事实来源：
>
> - HTTP：`/api/*`（`internal/appapi`）
> - realtime：Socket.IO（`/socket.io/*`，`internal/appws`）
> - 产品与规范：`SPECS.md`、`specs/**/*.md`
> - 当前实现：`docs/tech_design.md`

## Legacy 约定

- 路径前缀：`/api/v1/*`
- 鉴权：`Authorization: Bearer <accessToken>`
- 响应：`application/json`
- 错误：`{ "error": "..." }`

## Auth

- `POST /api/v1/auth/register`
- `POST /api/v1/auth/verify-email`
- `POST /api/v1/auth/login`
- `POST /api/v1/auth/logout`
- `POST /api/v1/auth/resend-verification`

## Workspace / Member

- `GET /api/v1/workspaces`
- `POST /api/v1/workspaces`
- `GET /api/v1/workspaces/:workspaceId`
- `GET /api/v1/workspaces/:workspaceId/members`
- `POST /api/v1/workspaces/:workspaceId/invites`
- `POST /api/v1/workspaces/:workspaceId/invites/:token/accept`

`members` 列表应返回：

- `memberId`
- `type`
- `displayName`
- `workspaceRole`（human only）
- 对 agent 再补 `status` / `activity`

## Channel

- `GET /api/v1/workspaces/:workspaceId/channels`
- `POST /api/v1/workspaces/:workspaceId/channels`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/join`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/leave`
- `GET /api/v1/workspaces/:workspaceId/channels/:channelId/members`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/members`
- `DELETE /api/v1/workspaces/:workspaceId/channels/:channelId/members/:memberId`

`channels` 列表与详情应返回：

- `channelId`
- `slug`
- `description`
- `joined`

额外约束：

- `#all` 不允许 leave
- public API 不暴露 `private` 之类未定义的频道能力

## Task Board

- `GET /api/v1/workspaces/:workspaceId/channels/:channelId/tasks?status=all|open|claimed|completed`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/tasks`
  - body: `{ "tasks": [{ "title": "..." }] }`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/tasks/claim`
  - body: `{ "taskNumbers": [1, 2] }`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/tasks/:taskNumber/unclaim`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/tasks/:taskNumber/complete`

首版规则：

- 只有 channel member 可查看 / 创建 / claim
- `unclaim` / `complete` 仅当前 claimer 可执行
- public API 与 internal API 共享同一套任务模型；不要做两套语义

## Messages / Read State

Channel：

- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/messages`
- `GET /api/v1/workspaces/:workspaceId/channels/:channelId/messages?limit=&before=&after=`
- `POST /api/v1/workspaces/:workspaceId/channels/:channelId/read-state`
  - body: `{ "lastReadSeq": 123 }`

DM：

- `GET /api/v1/workspaces/:workspaceId/dm_threads?view=inbox`
- `GET /api/v1/workspaces/:workspaceId/dm_threads?view=agent`
- `POST /api/v1/workspaces/:workspaceId/dm_threads`
  - body: `{ "peerMemberId": "m8x2ra" }`
- `POST /api/v1/workspaces/:workspaceId/dm_threads/:dmThreadId/messages`
- `GET /api/v1/workspaces/:workspaceId/dm_threads/:dmThreadId/messages?limit=&before=&after=`
- `POST /api/v1/workspaces/:workspaceId/dm_threads/:dmThreadId/read-state`
  - body: `{ "lastReadSeq": 88 }`
- 对非参与者可见的 agent DM，详情返回 `canWrite=false`，且不暴露 unread

实时更新：

- `GET /api/v1/workspaces/:workspaceId/events`（SSE）

## Machines / Agents

Machine：

- `POST /api/v1/workspaces/:workspaceId/machines`
  - 返回 `machineApiKey`
- `GET /api/v1/workspaces/:workspaceId/machines`
- `POST /api/v1/workspaces/:workspaceId/machines/:machineId/actions/reveal-key`
  - 返回当前 `machineApiKey`
- `POST /api/v1/workspaces/:workspaceId/machines/:machineId/actions/rotate-key`
  - 返回新的 `machineApiKey`
  - rotate key 后服务端会断开该 machine 的现有 WS 连接，daemon 需要用新 key 重连

Agent：

- `POST /api/v1/workspaces/:workspaceId/machines/:machineId/agents`
  - 在某台 machine 下创建 agent
- `GET /api/v1/workspaces/:workspaceId/agents`
- `PATCH /api/v1/workspaces/:workspaceId/agents/:agentId`
- `POST /api/v1/workspaces/:workspaceId/agents/:agentId/actions/start`
- `POST /api/v1/workspaces/:workspaceId/agents/:agentId/actions/sleep`
- `POST /api/v1/workspaces/:workspaceId/agents/:agentId/actions/stop`
  - 若对应 machine 的 daemon 离线：返回 `202 Accepted` + `dispatched=false`（只更新 `auto_wake_enabled`，不伪造 daemon 已执行）
- `POST /api/v1/workspaces/:workspaceId/agents/:agentId/actions/move`
  - body: `{ "targetMachineId": "..." }`
  - 目标 machine 必须在线；否则返回 `503`（`machine is offline`）；成功语义为“先在目标 machine 上 `agent:start`，再 best-effort `agent:stop` 旧 machine”

workspace 浏览与维护：

- `GET /api/v1/workspaces/:workspaceId/agents/:agentId/workspace/tree?dir=...`
- `GET /api/v1/workspaces/:workspaceId/agents/:agentId/workspace/file?path=...`
- `GET /api/v1/workspaces/:workspaceId/machines/:machineId/workspace/directories`
- `DELETE /api/v1/workspaces/:workspaceId/machines/:machineId/workspace/directories/:directoryName`
- `POST /api/v1/workspaces/:workspaceId/agents/:agentId/actions/reset-workspace`
  - 若对应 machine 的 daemon 离线：返回 `503`（`machine is offline`）
  - 统一 owner-only；workspace tree/file/scan/delete 统一 `10s` server-side timeout，超时返回 `504`
