# 实施说明 — 服务端 Playwright Chromium 远程浏览器

> 设计：`docs/design/specs/2026-06-11-server-browser-chromium-design.md`  
> **Worker 购机/装机**：[`2026-06-11-browser-worker-server-procurement.md`](./2026-06-11-browser-worker-server-procurement.md) ← **先买服务器**

## 部署形态（2026-06-11 更新）

**选定独立 Worker**，不在 Nexus 主站 `Dockerfile.prod` 安装 Chromium。

| 仓库路径 | 运行位置 |
|----------|----------|
| `browser-worker/` | Worker VPS |
| `server/.../browser_bridge.py` 等 | Nexus 主站 |

## 涉及文件（计划）

| 文件 | 动作 | 位置 |
|------|------|------|
| `browser-worker/Dockerfile` | **新建** | Worker |
| `browser-worker/docker-compose.yml` | **新建** | Worker |
| `browser-worker/main.py` | Worker FastAPI + WS + Playwright | Worker |
| `browser-worker/browser_url_safe.py` | SSRF（与主站共享逻辑或复制） | Worker |
| `server/utils/browser_url_safe.py` | SSRF（桥接层二次校验） | Nexus |
| `server/infrastructure/browser/worker_client.py` | HTTP/WS 连 Worker | Nexus |
| `server/api/browser_session.py` | REST + 管理员 WS 桥接 | Nexus |
| `server/main.py` | 注册 router；`NEXUS_BROWSER_*` | Nexus |
| `server/config.py` | `browser_enabled`, `browser_worker_url`, `worker_secret` | Nexus |
| `tests/test_browser_url_safe.py` | SSRF 单测 | Nexus |
| `tests/test_browser_worker_client.py` | mock Worker | Nexus |
| `frontend/src/composables/useRemoteBrowserSession.ts` | canvas + WS | 前端 |
| `frontend/src/components/GlobalBrowserPanel.vue` | iframe → canvas | 前端 |
| `frontend/src/composables/useGlobalBrowser.ts` | 对接 remote session | 前端 |

**不变**：~~`server/api/browser.py`~~ **已删除**（2026-06-11）；Worker 方案将新建 `browser_session` API，不复用 iframe 状态接口。  
**不修改**：`Dockerfile.prod`（主站）

## 实现步骤

### Phase W0 — 你购机（并行）

按 procurement 文档：**2C4G+、Ubuntu 22.04/24.04、防火墙 8443 仅 Nexus IP**。

### Phase W1 — Browser Worker 服务

1. `browser-worker/` 独立 FastAPI：`GET /health`、`POST /v1/sessions`、`DELETE`、`WS /v1/sessions/{id}/stream`
2. Header `X-Nexus-Worker-Key` 校验
3. Playwright Chromium + CDP screencast + 键鼠
4. SSRF 在 Worker 侧强制执行

### Phase W2 — Nexus 桥接

1. `worker_client.py`：创建/销毁会话、WS 双向转发
2. `browser_session.py`：管理员 JWT WS ↔ Worker WS
3. `NEXUS_BROWSER_ENABLED=0` → 503

### Phase W3 — 前端

1. `useRemoteBrowserSession.ts` + canvas
2. `GlobalBrowserPanel` 替换 iframe
3. 503 友好提示

### Phase W4 — 联调（需 Worker IP）

1. Worker 部署 + ufw
2. Nexus `.env` 配 `NEXUS_BROWSER_WORKER_*`
3. 验收表（procurement §5 Phase D）
4. changelog + audit → 门控 → 部署

## 测试要点

```bash
pytest tests/test_browser_url_safe.py tests/test_browser_ui_state.py -q
cd frontend && npm run type-check
# Worker 目录（实现后）
cd browser-worker && pytest -q
```

## 依赖与配置

**Nexus 主站**

```env
NEXUS_BROWSER_ENABLED=1
NEXUS_BROWSER_WORKER_URL=https://10.x.x.x:8443
NEXUS_BROWSER_WORKER_SECRET=<shared>
NEXUS_BROWSER_MAX_SESSIONS=2
NEXUS_BROWSER_IDLE_TIMEOUT_SEC=1800
```

**Worker `.env`**

```env
WORKER_SECRET=<same-as-above>
WORKER_BIND=0.0.0.0:8443
WORKER_MAX_SESSIONS=2
WORKER_IDLE_TIMEOUT_SEC=1800
```

## 回滚

1. `NEXUS_BROWSER_ENABLED=0` + 重启 Nexus
2. Worker 容器 `docker compose down`（主站不受影响）
