计划见 docs/design/plans/2026-06-01-single-owner-execution.md;生产 health/app/Redis/MySQL 已通过。
17 KiB
Nexus 项目交接文件 — Cursor 继续开发
生成时间: 2026-06-01(2026-06-01 晚更新:单负责人收口) 当前分支: main(与 origin/main 同步,含
b8af1fc单 Agent 规则) 协作方式: 用户 ↔ 当前 Cursor Agent(无虚拟部门/Skill 分派) 主前端: Vue 3 + Vuetify SPA(frontend/→web/app/) 生产: https://api.synaglobal.vip 已部署
零、Cursor 接管第一步
1. 已为你准备好的文件
| 文件 | 位置 | 作用 |
|---|---|---|
| Cursor Rules | .cursorrules(项目根目录) |
强制规则、部署流程、文件速查 — Cursor 自动读取 |
| MCP 配置 | C:\Users\uzuma\.cursor\mcp.json |
nexus/playwright/gitea/fetch/context7 — 已写好 |
| 项目规则 | CLAUDE.md(项目根目录) |
完整项目记忆、决策、实现状态、部署常遇问题 |
| 交接文件 | docs/handoff-2026-06-01.md |
本文件 |
2. Cursor 中使用步骤
- 用 Cursor 打开
C:\Users\uzuma\Desktop\svn\Nexus - MCP 自动加载(
~/.cursor/mcp.json已配置好) .cursorrules自动生效(Cursor 自动读取项目根目录的此文件)- 直接开始对话
3. 给 Cursor Agent 的开场提示词(复制到 Chat)
读取 docs/handoff-2026-06-01.md 了解项目全貌,然后读取 CLAUDE.md 了解强制规则。项目 ~99% 完成,当前待续事项见交接文件第八节。用中文回复。
4. 更完整的 Agent System Prompt(如需配置 Custom Agent)
你是 Nexus 6.0 项目的开发助手。这是一个 2000+ 服务器运维管理平台。
技术栈:
- 后端: FastAPI 0.115.6 + Async SQLAlchemy 2.0 + Redis 5.2 + WebSocket + Telegram
- 前端: Vue 3 + Vuetify 4 + TypeScript SPA (14个页面)
- 构建工具: Vite 8,输出到 web/app/
- 部署: Gitea → SSH git pull → supervisorctl restart (后端),Vite build → tar+scp (前端)
强制规则:
1. 所有实现必须是完美实现 — 不允许降级、妥协、留技术债
2. 安全铁律: 禁止明文密码前端、禁止静默吞错、禁止f-string拼SQL、禁止硬编码密钥
3. 文档纪律: 每次修改必须写 changelog (docs/changelog/,行数≥10),新功能必须先有设计文档
4. 修改流程: 实现 → 验证 → 审计8步 → 部署 → 健康检查 → 浏览器验证 → changelog
5. 用中文回复
6. 部署用 SSH: ssh nexus "cd /www/wwwroot/api.synaglobal.vip && git fetch --all && git reset --hard origin/main && supervisorctl restart nexus"
7. 前端部署: cd frontend && npx vite build && cd .. && tar czf /tmp/nexus-frontend.tar.gz -C web/app index.html assets/ && scp /tmp/nexus-frontend.tar.gz nexus:/tmp/nexus-frontend.tar.gz && ssh nexus "cd /www/wwwroot/api.synaglobal.vip/web/app && tar xzf /tmp/nexus-frontend.tar.gz && rm /tmp/nexus-frontend.tar.gz"
8. 健康检查: ssh nexus "sleep 3 && curl -s http://127.0.0.1:8600/health" → 预期 "ok"
生产环境:
- 域名: https://api.synaglobal.vip
- SSH 别名: ssh nexus (root@47.254.123.106)
- 管理员: admin / Nexus@2026
- 数据库: MySQL nexus/Nexus@2026!@127.0.0.1:3306/nexus
详细项目文档: 项目根目录 CLAUDE.md
交接文件: docs/handoff-2026-06-01.md
一、项目基本信息
| 项目 | 值 |
|---|---|
| 项目名 | Nexus 6.0 |
| 功能 | 2000+ 服务器运维管理平台 |
| 仓库 | http://66.154.115.8:3000/admin/Nexus.git |
| 本地路径 | C:\Users\uzuma\Desktop\svn\Nexus |
| 生产域名 | https://api.synaglobal.vip |
| 生产 IP | 47.254.123.106 |
| 后端端口 | 8600 |
| 部署路径 | /www/wwwroot/api.synaglobal.vip/ |
| 管理员凭据 | admin / Nexus@2026 |
| 数据库 | MySQL nexus/Nexus@2026!@127.0.0.1:3306/nexus |
| Gitea 部署 Token | SHA: 26fee743a9332895b55f79b2dbe2e931dc7c2fe5 |
二、技术栈
后端 (server/)
- FastAPI 0.115.6 + uvicorn 0.34.0
- SQLAlchemy 2.0.49 (Async) + aiomysql 0.2.0
- Redis 5.2.1 (心跳/缓存/告警去重)
- asyncssh 2.17.0 (WebSSH 连接池)
- PyJWT 2.10.1 + bcrypt 4.2.1 (认证)
- cryptography 44.0.0 (Fernet 凭据加密)
- Clean Architecture 4层: api/ → application/ → domain/ → infrastructure/
前端 (frontend/)
- Vue 3 ^3.5.30 + Vuetify 4 ^4.0.2 + TypeScript ~5.9.3
- Vite ^8.0.0 + Pinia ^3.0.4
- xterm.js ^6.0.0 (WebSSH 终端)
- Monaco Editor ^0.55.1 (代码编辑器)
- 14个页面组件,Hash History 路由
- 构建输出到
web/app/(后端 StaticFiles 挂载点)
旧前端 (web/app/) — 仍存在但不维护
- Tailwind CSS v4 + Alpine.js,12 个 HTML 页面
- 新 SPA 构建后覆盖 web/app/index.html 和 assets/
三、MCP 服务器配置
Cursor MCP 配置(已写入 ~/.cursor/mcp.json)
{
"mcpServers": {
"nexus": {
"command": "ssh",
"args": ["-o", "StrictHostKeyChecking=no", "-i", "C:/Users/uzuma/.ssh/id_rsa_nexus", "root@47.254.123.106", "cd /www/wwwroot/api.synaglobal.vip && NEXUS_DEPLOY_DIR=/www/wwwroot/api.synaglobal.vip python3 mcp/Nexus_server.py"]
},
"playwright": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@playwright/mcp@latest"]
},
"gitea": {
"command": "cmd",
"args": ["/c", "npx", "-y", "gitea-mcp"],
"env": {
"GITEA_ACCESS_TOKEN": "4dfc8e2edeaf86bc9c485779652e2eb67a8604dc",
"GITEA_HOST": "http://66.154.115.8:3000"
}
},
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"]
},
"context7": {
"command": "cmd",
"args": ["/c", "npx", "-y", "@upstash/context7-mcp"]
}
}
}
Claude Code MCP 配置(参考)
全局配置位置: C:\Users\uzuma\.claude.json → mcpServers
| MCP 名称 | 类型 | 命令 | 用途 |
|---|---|---|---|
| Nexus Remote MCP | SSH | ssh -o StrictHostKeyChecking=no -i /c/Users/uzuma/.ssh/id_rsa_mcp root@47.254.123.106 python3 /www/wwwroot/api.synaglobal.vip/mcp/nexus_server.py |
后端操作(API/DB/部署/日志) |
| gitea | npx | gitea-mcp |
Gitea 仓库操作 |
| github | npx | @modelcontextprotocol/server-github |
GitHub 操作 |
| playwright | npx | @playwright/mcp@latest |
浏览器自动化 |
| context7 | npx | @upstash/context7-mcp |
库文档查询 |
| megamemory | 本地 | megamemory |
项目知识图谱 |
| memory | npx | @modelcontextprotocol/server-memory |
内存存储 |
| fetch | uvx | mcp-server-fetch |
URL 获取 |
项目级 MCP (~/.claude.json → projects → Nexus → mcpServers):
{
"nexus": {
"type": "stdio",
"command": "ssh",
"args": ["-o", "StrictHostKeyChecking=no", "-i", "C:/Users/uzuma/.ssh/id_rsa_nexus", "root@47.254.123.106", "cd /www/wwwroot/api.synaglobal.vip && NEXUS_DEPLOY_DIR=/www/wwwroot/api.synaglobal.vip python3 mcp/Nexus_server.py"]
}
}
四、SSH 配置
~/.ssh/config:
Host nexus
HostName 47.254.123.106
User root
IdentityFile C:/Users/uzuma/.ssh/id_rsa_nexus
StrictHostKeyChecking no
密钥文件:
C:\Users\uzuma\.ssh\id_rsa_nexus— 生产服务器 SSHC:\Users\uzuma\.ssh\id_rsa_mcp— MCP 远程连接
五、部署流程
后端部署
# 1. Push 到 Gitea
git push origin main
# 2. 服务器拉取 + 重启
ssh nexus "cd /www/wwwroot/api.synaglobal.vip && git fetch --all && git reset --hard origin/main && supervisorctl restart nexus"
# 3. 健康检查
ssh nexus "sleep 3 && curl -s http://127.0.0.1:8600/health"
# 预期: ok
前端部署
# 一键脚本
bash deploy/deploy-frontend.sh
# 或手动:
cd frontend && npx vite build && cd ..
tar czf /tmp/nexus-frontend.tar.gz -C web/app index.html assets/
scp /tmp/nexus-frontend.tar.gz nexus:/tmp/nexus-frontend.tar.gz
ssh nexus "cd /www/wwwroot/api.synaglobal.vip/web/app && tar xzf /tmp/nexus-frontend.tar.gz && rm /tmp/nexus-frontend.tar.gz"
本地开发
cd frontend && npm run dev # http://localhost:3000/app/
Vite proxy 配置: /api → https://api.synaglobal.vip, /ws → wss://api.synaglobal.vip
部署常遇问题
| 问题 | 解决 |
|---|---|
/app/ 返回 404 |
AppAuthMiddleware 拦截 — 确认 /app/ 和 /app/index.html 在 _APP_PUBLIC_PATHS 中 |
/app/ 返回旧 HTML (Tailwind/Alpine) |
git reset --hard 恢复了旧文件 — 需要重新 tar+scp 前端构建产物 |
MCP deploy → git pull 失败 could not read Username |
服务器 remote URL 没配 token,用 git remote set-url |
| Gate 2 Audit BLOCKED | 创建 docs/audit/YYYY-MM-DD-topic.md,含 Step3+Closure+DoD |
| Gate 3 Test BLOCKED (401) | 服务器 .env 中 NEXUS_TEST_ADMIN_PASSWORD 与数据库不一致 |
| Gate 6 Security BLOCKED (bandit HIGH) | md5 → sha256 等,参看 bandit 报告修复 |
| Gate 7 Review BLOCKED | 审计文件缺少实际改动文件清单 |
六、7道门控 (deploy/pre_deploy_check.sh)
| # | 门 | 检查内容 |
|---|---|---|
| 1 | Changelog门 | 文件存在且行数≥10 |
| 2 | Audit门 | 文件存在且含 Step3+Closure+DoD |
| 3 | Test门 | test_api.py 必须存在且通过 |
| 4 | Lint门 | ruff check server/ 零错误 |
| 5 | Import门 | import server.main 成功 |
| 6 | Security门 | bandit 无 HIGH/MEDIUM |
| 7 | Review门 | 审计文件包含实际改动文件清单 |
MCP deploy 工具自动执行门控,任何一门不过返回 🚫 DEPLOY BLOCKED
七、最近完成的工作
2026-06-01: 全站 bug 审查修复 (14项)
前端修复 (9项):
| 级别 | Bug | 修复 |
|---|---|---|
| P0 | App.vue http 未导入 → 全局搜索崩溃 |
添加 import { api, http } |
| P1 | TOTP 登录流程断裂 | 导入 TotpRequiredError,catch 中优先检查 |
| P1 | ServersPage 编辑服务器 domain 被端口污染 | form.address = item.domain |
| P1 | PushPage Set[0] 无效 → preview 发 undefined |
values().next().value |
| P1 | SettingsPage API 字符串未转数字 | 正则检测 + Number() |
| P2 | api/index.ts getList 重复定义 |
删除第二个 |
| P2 | LoginPage 锁定倒计时不更新 | ref(Date.now()) + watch + 定时器 |
| P2 | TerminalPage 路径验证过严 | 白名单排除控制字符+引号 |
| P2 | useWebSocket CONNECTING 状态连接泄漏 | 关闭旧连接再建新的 |
后端修复 (5项):
| 级别 | Bug | 修复 |
|---|---|---|
| P1 | websocket.py redis.keys() O(N) 阻塞 |
scan_iter() 非阻塞迭代 |
| P1 | auth_service.py TTL 每次刷新都重置 | 仅 ttl < 0 时设置 expire |
| P1 | servers.py 批量操作并发 session commit | asyncio.Lock() 序列化 |
| P2 | settings.py asyncio.get_event_loop() 弃用 |
get_running_loop() |
| P2 | settings.py datetime.utcfromtimestamp() 弃用 |
fromtimestamp(tz=utc) |
2026-05-31: TerminalPage 全面迭代 + 登录页调整
- 登录页居中 — flexbox 居中,删除 Logo
- TerminalPage 25项修复 — Ctrl+L清屏、命令历史恢复、per-session重连/ping/uptime、指数退避等
- 快捷命令 MySQL 持久化 — quick_commands 表 + CRUD API + 内置命令 seed
- Shell 语法高亮 — 命令输入栏 sudo→红、关键字→蓝、管道→黄、字符串→绿、flag→紫
项目整体进度 — ~99% 完成
14 页面全部完成部署。所有 P0/P1/P2 功能已实现。
八、待续事项(2026-06-01 更新)
已修复(见 docs/changelog/2026-06-01-bug-remediation.md)
| 原优先级 | 问题 | 状态 |
|---|---|---|
| P1 | ServersPage 批量 Agent 操作 | ✅ normalizeServerIds + 生产 SPA 已部署 |
| P1 | script-callback 无 API Key | ✅ X-API-Key 校验 |
| P1 | Access Token 30 天 | ✅ 60min + HttpOnly refresh |
| P2 | 未知 IP 心跳 422 刷屏 | ✅ 丢弃 + debug 日志 |
| P2 | Admin 废弃 JWT 列 | ✅ 迁移 DROP |
| P3 | agent on_event 弃用 | ✅ lifespan |
仍待办 / 抽测
| 优先级 | 问题 | 文件 | 说明 |
|---|---|---|---|
| P2 | 422 调试 handler 是否保留 | server/main.py | 若日志已稳定可改为仅 4xx 结构化响应 |
| P2 | 壁纸旧端点缓存 | LoginPage.vue | 强刷 /app/ 或清站点数据 |
| UX | 终端命令栏高亮对齐 | TerminalPage.vue | 多分辨率抽测 |
| 验收 | 告警 Telegram + WS 端到端 | — | 需故意超阈值或模拟 |
| 验收 | WebSSH 长会话 + resize | terminal | 浏览器抽测 |
| 验收 | Sync 推送 2 台试跑 | push | 业务抽测 |
| 验收 | 三层守护 kill 测试 | deploy/ | 维护窗口执行 |
| 运维 | 生产 pytest | tests/test_api.py | 服务器无 pytest 模块时用 WSL/CI 25/25 为准 |
九、关键文件速查
| 用途 | 文件路径 |
|---|---|
| 后端入口 | server/main.py |
| 路由注册 | server/main.py 行525-560 |
| 数据模型 | server/domain/models/__init__.py |
| JWT 认证 | server/api/auth_jwt.py |
| 登录API | server/api/auth.py |
| WebSSH | server/api/webssh.py |
| 终端 WS | server/api/websocket.py |
| 设置 CRUD | server/api/settings.py |
| 服务器 CRUD | server/api/servers.py |
| 快捷命令 CRUD | server/api/terminal.py |
| Agent 心跳 | server/api/agent.py |
| 同步引擎 | server/application/services/sync_engine_v2.py |
| 认证服务 | server/application/services/auth_service.py |
| 前端入口 | frontend/src/main.ts |
| 路由 | frontend/src/router/index.ts |
| API 客户端 | frontend/src/api/index.ts |
| Auth Store | frontend/src/stores/auth.ts |
| 登录页 | frontend/src/pages/LoginPage.vue |
| 终端页 | frontend/src/pages/TerminalPage.vue |
| WebSocket composable | frontend/src/composables/useWebSocket.ts |
| Vite 配置 | frontend/vite.config.mts |
| 部署脚本 | deploy/deploy-frontend.sh |
| 门控脚本 | deploy/pre_deploy_check.sh |
| Supervisor | deploy/nexus.conf |
| Nginx | deploy/nginx_https.conf |
| DB 备份 | deploy/db_backup.sh |
| 健康检查 | deploy/health_monitor.sh |
| 项目规则 | CLAUDE.md (非常详尽,279行) |
| Cursor 规则 | .cursorrules (项目根目录) |
十、Megamemory 知识图谱
统计: 34 nodes, 23 edges, 11 removed
使用 megamemory:understand 查询项目上下文,megamemory:list_roots 查看所有根节点。
核心概念: nexus(总览), clean-architecture-4, db-tables-14, jwt-totp, webssh, terminal-11, sync, install-wizard, 3(3层守护), websocket, telegram, redis, security, settings, vuetify-spa, pushpage, ide, v2(文件管理器), pipeline-7(7道门控), push-cancel, reveal-with-password, nexus-theme, ruff-2026-05-30, appauthmiddleware-fix-chain, browser-tool-preference, session-2026-05-30-progress, agent, servers-list, child-server-operation-rules
十一、规则文件位置
| 文件 | 路径 | 说明 |
|---|---|---|
| Cursor 规则 | .cursorrules(项目根目录) |
已创建,Cursor 自动读取 |
| Cursor MCP | C:\Users\uzuma\.cursor\mcp.json |
已创建,Cursor 自动读取 |
| 全局规则 (Claude) | C:\Users\uzuma\.claude\CLAUDE.md |
完美实现原则、安全铁律、文档纪律、执行顺序 |
| 项目规则 (Claude) | C:\Users\uzuma\Desktop\svn\Nexus\CLAUDE.md |
项目概述、目录结构、已确认决策、实现状态、部署流程 |
| 项目 Memory (Claude) | C:\Users\uzuma\.claude\projects\C--Users-uzuma-Desktop-svn-Nexus\memory\MEMORY.md |
语言偏好(中文)、浏览器偏好(Playwright)、SSH配置、部署流程、Vuetify进度 |
十二、开发流程提醒
需求确认 → 设计文档 → 技术文档 → 实现 → 测试验证 → changelog →(必要时)更新 CLAUDE.md
强制文件修改流程(不可跳步):
实现 → WSL本地验证 → ★审计8步★ → 部署 → 健康检查 → 浏览器验证 → changelog
进度条(每次改代码必须输出):
□实现 □WSL验证 □审计8步 □部署 □健康检查 □浏览器验证 □changelog
审计8步:登记→全文Read→规则扫描H→Closure表→入口表→输入→Sink→归类→DoD
十三、数据流
Agent心跳(60s) → Redis(实时) → 前端直读 → 10min批量 → MySQL(历史)
告警: CPU/mem/disk > threshold → WebSocket推送浏览器 + Telegram推送手机
恢复: 之前告警的指标恢复正常 → 自动推送恢复通知
Redis心跳key: heartbeat:{server_id} (HSET, TTL=600s)
Redis告警key: alerts:{server_id} (SET, TTL=3600s)
十四、已确认的关键决策
| 不可改项 | 原因 |
|---|---|
| API_KEY | 加密一致性 + 子服务器认证 |
| SECRET_KEY | 加密回退密钥 |
| DATABASE_URL | 启动必需 |
| ENCRYPTION_KEY | 凭据加密 |
| 可改项 | 说明 |
|---|---|
| system_name/title | 前端显示 |
| pool_size/overflow | 安装向导自动推荐 |
| redis_url | Redis 连接 |
| 告警阈值 | 默认 80% |
| Telegram 配置 | 告警推送 |
十五、用户审查清单
验证 AI 是否偷懒:
- 看
deploy/gate_log.jsonl— 每次门控都有记录,没有记录 = 没过门控 - 看审计文件 — 必须有 Closure 表(每个H的判定+依据)、Step 3 规则扫描、DoD
- 看进度条 — ☑必须在□前面,否则跳步
- 看 changelog — 行数≥10,不能是空壳