# 04 - 云同步（基础可用）：服务端基础能力

## 目标（PRD 约束）

- 支持用户级任务数据同步/读取（用户隔离）
- 提供基于角色/权限的访问控制（RBAC）
- 对高风险操作支持二次认证（能力以服务端实现为准）
- 下发“可控落盘”配置（服务端配置驱动）

## 范围（建议最小闭环）

- 认证（登录/会话）
- 任务数据 API（按用户隔离）
- 配置下发 API（是否允许落盘、终端可信度/会话策略等）
- RBAC 最小落地（至少能区分“允许同步/禁止同步”或“只读/读写”）
- 二次认证最小落地（至少覆盖“启用/关闭同步、切换账号、调整落盘策略”等高风险操作的接口）

## 依赖

- 与 `05-*`（客户端）可并行推进，但需要尽早冻结 API 契约（字段名/响应结构/错误码）

## 接口契约（需要在实现前先写清楚）

v1.2.0 已实现一套最小可用契约（用于 05/06 客户端对接时冻结字段名/错误码）。

### 通用约定

- Base URL：由客户端配置（例如 `https://{host}:{port}`）
- 认证：`Authorization: Bearer {accessToken}`
- 错误响应（统一结构）：

```json
{ "code": "ERROR_CODE", "message": "Human readable message." }
```

### 错误码

- `UNAUTHORIZED`：未登录或会话失效
- `FORBIDDEN`：权限不足（RBAC / 策略拒绝）
- `SECOND_FACTOR_REQUIRED`：需要二次认证（step-up）
- `BAD_REQUEST`：请求参数不合法
- `NOT_FOUND`：资源不存在

### Auth

- 初始化管理员（仅当系统尚无云用户时允许一次）：
  - `POST /auth/bootstrap`
  - Body：`{ "userName": "admin", "password": "..." }`
  - 200：成功；403：已初始化或不允许

- 登录：
  - `POST /auth/login`
  - Body：`{ "userName": "admin", "password": "..." }`
  - 200：`{ accessToken, expiresAtUtc, userId, role, permissions[] }`

- 二次认证（step-up，v1.2.0 最小实现为“复用登录口令进行再认证”）：
  - `POST /auth/step-up`
  - Header：`Authorization: Bearer ...`
  - Body：`{ "password": "..." }`
  - 200：`{ stepUpExpiresAtUtc }`

### Tasks

- 获取当前用户任务全量：
  - `GET /tasks`
  - Header：`Authorization: Bearer ...`
  - 权限：`tasks:read`
  - 200：`CloudTaskItem[]`

### Sync

- 上传/同步（增删改后返回最新全量）：
  - `POST /sync`
  - Header：`Authorization: Bearer ...`
  - 权限：`sync:write`
  - 二次认证：必需（否则返回 `SECOND_FACTOR_REQUIRED`）
  - Body：

```json
{
  "upserts": [
    { "id": 1, "title": "A", "priority": 1, "isCompleted": false, "parentTaskId": null },
    { "id": null, "title": "New", "priority": 1, "isCompleted": false, "parentTaskId": null }
  ],
  "deletes": [2, 3]
}
```

  - 200：

```json
{
  "serverTimeUtc": "2026-04-06T17:39:30.0281279Z",
  "tasks": [ /* CloudTaskItem[] */ ]
}
```

### Security Policy

- 获取安全策略（服务端下发）：
  - `GET /security/policy`
  - Header：`Authorization: Bearer ...`
  - 权限：`policy:read`
  - 200：

```json
{
  "allowPersist": true,
  "allowSync": true,
  "requireSecondFactorFor": ["sync:write", "policy:write"]
}
```

- 更新安全策略（高风险操作）：
  - `PUT /security/policy`
  - Header：`Authorization: Bearer ...`
  - 权限：`policy:write`
  - 二次认证：必需（否则返回 `SECOND_FACTOR_REQUIRED`）
  - Body：`{ "allowPersist": false, "allowSync": false }`

## 关键实现点（建议）

1. 用户隔离
   - 服务端所有读写必须绑定当前登录用户上下文
2. 权限模型（RBAC）
   - 定义最小角色：例如 `user`、`admin`
   - 定义最小权限：例如 `tasks:read`、`tasks:write`、`sync:enable`
3. 二次认证
   - 选择实现方式（示例）：二次口令/一次性验证码（TOTP）/短信（若无能力则先实现“二次口令”）
   - 能力不足时必须返回明确错误，使客户端可提示用户
4. 落盘策略下发
   - 支持按用户或按会话/终端下发
   - 默认策略建议为“允许落盘”，便于可用性；但需支持“禁止落盘”

## 验收标准

- 使用不同用户登录后获取任务，数据严格隔离
- 未授权角色/权限访问受限接口会被拒绝（错误响应可被客户端识别）
- 能返回安全策略配置（至少包含 `allowPersist`），并可通过配置切换行为

## 当前实现说明（v1.2.0）

- 数据隔离：`Tasks` 表新增 `UserId` 外键，云端 API 的所有读写按当前会话用户隔离；本地模式使用固定的 `local` 用户 ID（不影响既有 Dynamic API）。
- RBAC：内置 `admin / user / readonly / nosync` 角色与权限映射；并叠加 `SecurityPolicies.AllowSync` 作为“是否允许同步写入”的策略开关。
- 二次认证：通过 `POST /auth/step-up` 将会话提升到 step-up 状态；`POST /sync` 与 `PUT /security/policy` 会强制要求 step-up。
