Commit Graph

47 Commits

Author SHA1 Message Date
Nexus Deploy b866e944ab fix: Code Review P0/P1 batches 1-3 and single-operator risk acceptance
Apply sync/install/auth/schedule/retry/agent/settings fixes from full
code review; document accepted WS and Agent legacy risks for solo ops.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:57:49 +08:00
Your Name 4b5602a719 feat(files): fix editor freeze, EOL gates, server form and session UX
- FilesPage storeToRefs + remotePath coercion; Monaco preload; list action buttons
- text_io for UTF-8/LF; install/sync EOL; check_shell_eol + check_text_eol gates
- ServerFormDialog, hash login redirect, AppAuth keep-session; design docs and audits

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 00:42:55 +08:00
Your Name 78798e3630 feat(push): refactor B0-B6, /ws/sync channel, staging cleanup
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 08:14:09 +08:00
Your Name c6f1d73ff5 feat(files): P4 GET browse with ETag and P5 zero-flicker loading
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 05:59:55 +08:00
Your Name 8935081ac5 feat: full-site acceptance automation and health/detail fix
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 15:22:42 +08:00
Your Name 8311821590 fix: 全量修复批量选择、JWT 60min、script-callback 认证与心跳数据流
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 12:17:47 +08:00
Your Name facc1e8ae4 feat: TerminalPage全面迭代 + 快捷命令MySQL持久化
P0: Ctrl+L清屏、命令历史恢复、重连per-session、onopen不忽略、ping per-session
P1: 空catch处理、termRefs用session.id、错误透传、剪贴板权限、webssh-token错误
P2: 全选菜单、指数退避重连、快捷命令编辑、uptime per-session
新功能: quick_commands MySQL表 + CRUD API、Shell语法高亮输入栏
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 23:12:18 +08:00
Your Name d0308aaef6 fix: allow /app/wallpapers/ through AppAuthMiddleware
- Added /app/wallpapers/ to _APP_PUBLIC_PREFIXES so cached wallpaper images
  are served without requiring login auth
- Wallpaper files are now saved to web/app/wallpapers/ by bing_wallpaper() endpoint

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 20:30:46 +08:00
Your Name 7a6479dbfa fix: remove stale login.html from public paths, clean up prefixes
Old Tailwind HTML pages removed from server — Vuetify SPA is now
the sole entry at /app/. Only install.html remains for setup wizard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:44:56 +08:00
Your Name 0fdae981cf fix: add ttf/eot/otf to static asset whitelist in AppAuthMiddleware
Vuetify/Monaco fonts return 404 without these extensions whitelisted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:42:43 +08:00
Your Name f745714530 fix: allow Vuetify SPA index.html through AppAuthMiddleware
The new Vuetify SPA uses hash routing — all pages served from single
index.html. The old middleware only whitelisted individual HTML page
paths (login.html etc.), blocking the SPA entry point with 404.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 13:13:13 +08:00
Your Name de8d860244 fix: handle legacy agent heartbeat without server_id + migrate on_event to lifespan
- AgentHeartbeat.server_id changed to Optional[int] — missing server_id
  now returns 200 (discarded) instead of 422, stopping retry loops
- web/agent/agent.py: on_event("startup") → FastAPI lifespan pattern
- Added exponential backoff on consecutive heartbeat failures (cap 5min)
- Agent stops heartbeat loop on "discarded" response from central
- main.py: promoted temporary debug 422 handler to production-grade
- uninstall.sh: added legacy agent cleanup (pkill patterns, crontab,
  /opt/multisync-agent path)
- Confirmed servers.html batch buttons work correctly (disabled state
  is correct when no agents installed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 18:20:14 +08:00
Your Name deffa8a8f4 fix: AppAuthMiddleware 验证 refresh token 格式而非 JWT 解码
refresh token 是 opaque 格式 (token:admin_id:token_version),不是 JWT。
之前用 pyjwt.decode() 验证必然失败,导致所有登录用户访问 /app/ 都返回 404。
改为验证格式合法性(3段、admin_id>0、token_version>=0)。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 05:10:39 +08:00
Your Name cc0ca47d61 debug: 422 handler 简化 — 只记录 errors 和 content_type,不读 body
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:09:30 +08:00
Your Name 449373f24f debug: 添加 422 验证错误日志 — 记录请求体和验证错误详情
诊断 Agent 心跳 422 问题,临时捕获请求体内容。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:05:30 +08:00
Your Name 730b665306 fix: AppAuthMiddleware 类定义移到 add_middleware 调用之前
Nexus CI/CD / test (push) Waiting to run
Nexus CI/CD / deploy (push) Blocked by required conditions
Nexus Pre-commit Checks / quick-check (push) Waiting to run
Python 模块级代码顺序执行,类必须先定义再引用。
之前 add_middleware(AppAuthMiddleware) 在第404行但类定义在第495行,
导致 NameError 服务启动失败。同时修复 _is_install_mode → is_install_mode。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:01:08 +08:00
Your Name f5bea6f0d2 fix: AppAuthMiddleware add_middleware 重新加回 2026-05-30 02:46:11 +08:00
Your Name c808c28edf fix: 移除错误的 AppAuthMiddleware add_middleware(类定义在后面)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 02:45:19 +08:00
Your Name d53309e37e fix: AppAuthMiddleware 类定义移到 add_middleware 之前
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 02:43:29 +08:00
Your Name a8fe7fed0a fix: 添加 REFRESH_COOKIE_NAME import,修复 AppAuthMiddleware NameError
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 02:41:12 +08:00
Your Name f91cd847a9 feat: AppAuth 中间件 — 未登录时 /app/ 页面返回空白 HTML 404
通过 nexus_refresh cookie 验证身份,无有效 token 返回空白 HTML,
不暴露系统存在。白名单路径: login/install/vendor/static assets。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 02:39:48 +08:00
Your Name ae22db4b3e fix: Nginx 重定向 + 自定义 404 — 隐藏 FastAPI 后端信息
Nexus CI/CD / test (push) Waiting to run
Nexus CI/CD / deploy (push) Blocked by required conditions
Nexus Pre-commit Checks / quick-check (push) Waiting to run
nginx_https.conf 新增注释化重定向规则,将裸页面路径 301 到 /app/ 前缀;
main.py 添加 StarletteHTTPExceptionHandler,404 返回空白 HTML 而非 JSON,
避免泄露后端框架标识。

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-30 02:03:57 +08:00
Your Name ad2e7667d3 Merge branch 'claude/condescending-ishizaka-3cff3a' 2026-05-28 21:02:09 +08:00
Your Name 77b332c037 fix: 远程安装按钮修复 + install.sh sudo/venv兼容 + api_base_url管理
- 修复详情面板"远程安装"按钮始终禁用:s._base_url 改为从新API获取全局API_BASE_URL
- 新增 GET /api/servers/meta/api_base_url 端点
- api_base_url 加入 DB_OVERRIDE_MAP + 启动迁移逻辑
- install.sh 非 root 用户自动 sudo 检测 + NOPASSWD 配置
- 后端 _sudo_wrap 辅助函数应用于 4 个 Agent 操作端点
- install.sh venv 创建加 || true 兼容 set -e(缺 python3-venv 不再直接退出)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 14:33:19 +08:00
Your Name eadf7254a1 Merge remote-tracking branch 'origin/claude/condescending-ishizaka-3cff3a' 2026-05-26 22:59:14 +08:00
Your Name 1c70e597a3 Fix Agent install 404 + add command input bar + fix install pipe error hiding
1. Mount /agent/ static files for install.sh/agent.py (was 404)
2. Replace curl|bash pipe with temp-file download to catch curl errors
3. Add command input bar to terminal.html bottom
4. Fix terminal CSS layout for flex with command bar

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 22:57:32 +08:00
Your Name 867e2aa552 Merge branch 'claude/condescending-ishizaka-3cff3a'
# Conflicts:
#	server/infrastructure/database/setting_repo.py
2026-05-26 21:58:38 +08:00
Your Name ccb78ed980 feat: SSH key preset system — dropdown + backend auto-resolve
- Add SshKeyPreset model + repo (encrypted_private_key, public_key)
- Add ssh_key_preset_id to Server model + schemas
- Add CRUD + reveal API routes (/api/ssh-key-presets/)
- servers.py: auto-resolve ssh_key_preset_id → decrypt → set ssh_key_private
- servers.html: key preset dropdown in key auth section, hides path/textarea on select
- Mirror password preset pattern: zero frontend credential exposure

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-25 22:49:57 +08:00
Your Name 99201f48fd fix: MissingGreenlet error — convert all middleware to pure ASGI
Root cause: BaseHTTPMiddleware.call_next() runs the endpoint in a
separate async task, which breaks SQLAlchemy's greenlet context.
After session.commit(), the connection is released to the pool.
When session.refresh() tries to acquire a new connection for a
SELECT, it fails with MissingGreenlet because the greenlet spawn
context is not available in the call_next() task.

Fix (two-part):
1. Convert all 4 middleware classes from BaseHTTPMiddleware to pure
   ASGI middleware — eliminates call_next() entirely so the entire
   request chain runs in the same async context.
2. Set expire_on_commit=False on the session factory — after commit,
   objects retain their in-memory values instead of being expired.
   This removes the need for session.refresh() entirely.

All session.refresh() calls removed from 11 repository files.
With expire_on_commit=False, post-commit attribute access no longer
triggers lazy loads that would also fail with MissingGreenlet.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-25 15:24:15 +08:00
Your Name c72631a293 merge: 安装脚本+PHP移除+宝塔适配 合并到main
合并 claude/condescending-ishizaka-3cff3a 分支:
- deploy/install.sh: 一键安装脚本(宝塔/标准模式自适应)
- deploy/upgrade.sh + uninstall.sh
- docs/install-guide.md: 完整中文安装教程
- PHP完全移除: install.php删除, config.php→config.json
- crypto.py: 移除PHP AES-CBC兼容, 纯Fernet
- install.py: 宝塔Supervisor路径自适应, Fernet密钥生成
- install.html: Step 5宝塔/标准模式条件渲染
- 44个冲突文件使用worktree分支版本(全部最新代码)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-25 08:25:29 +08:00
Your Name a1276f38ad feat: 一键安装脚本 + PHP完全移除 + config.php→config.json
新增文件:
- deploy/install.sh: 7步一键安装(自动检测宝塔/标准模式)
- deploy/upgrade.sh: git pull + pip install + restart + 健康检查
- deploy/uninstall.sh: 停服务+删配置, 可选--purge删部署目录
- docs/install-guide.md: 完整中文安装教程(宝塔+手动)

核心改动:
- install.py: 宝塔Supervisor路径自适应, init-db返回bt_panel标记,
  config.php→config.json, 移除PHP锁文件, 生成Fernet加密密钥
- install.html: Step 5根据btPanel显示不同Supervisor/Nginx/SSL指引
- crypto.py: 移除PHP AES-CBC兼容层, 纯Fernet加密
- 删除 web/install.php (1192行PHP, 功能已完全迁移到Python)

PHP清理:
- Nginx配置: config\.php→config\.json deny规则
- config.py/main.py/migrations.py: install.php注释→install wizard
- CLAUDE.md/AGENTS.md: config.php→config.json, 移除PHP引用
- firefox_server.py: login.php→login.html默认URL

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-25 08:23:37 +08:00
Your Name cdd0be328a fix: 六轮深度扫描 — 47项Bug修复、安全加固、死代码清理
Critical runtime bugs:
- terminal.html WebSSH完全不可用(URL前缀/JSON解析/Content-Type三处错误)
- servers.py路由遮蔽:/logs被/{id}拦截,3个前端页面同步日志查询失败
- scripts.html startExecPoll()→startExecPolling(),长任务快速执行崩溃
- agent.py {value!r!s:.50}格式串非法,agent发非数值时ValueError
- alerts.html d.daily.reduce()无null检查,API返回空数据时TypeError

Resource leak / stability:
- websocket.py僵尸连接未关闭TCP,文件描述符泄漏
- websocket.py _last_alert_time字典无限增长(加1小时过期清理)
- asyncssh_pool.py全忙时超过MAX_CONNECTIONS无限增长
- self_monitor.py Telegram告警无冷却,宕机时每30秒刷屏
- schedule_runner.py一次性调度执行超60秒会重复触发
- 限速脚本EXPIRE每次重置窗口可绕过(改用Lua原子脚本)

Security:
- JWT access token加token_version声明,改密码后旧token立失效(零宽限)
- INSTALL_MODE导入时常量→动态函数,安装后JWT认证不再残留禁用
- install.py /lock端点加管理员存在性验证,防止阻断安装
- ServerUpdate schema移除connectivity只读字段,防止伪造连接状态

Frontend fixes:
- doExec()缺r.ok检查、commands.html null检查
- _server_to_dict()补last_checked_at+ssh_key_public
- _field_match()逗号cron表达式修复
- alerts类型显示、SSH会话名称、搜索高亮定位
- 一次性/循环定时任务(run_mode+fire_at+自动禁用)

Dead code removed (400+ lines):
- SyncService batch_push/_push_single等5个方法(零调用者)
- 5个未使用schema(SyncCommands/SyncConfig/SyncSftp/FileDeploy/PaginatedResponse)
- 6个零调用service方法、3个无前端API端点
- 4个未使用import

Schema migrations:
- push_schedules: run_mode + fire_at列,cron_expr改NULL
- servers: 7个新列 + ssh_key_private/public VARCHAR(500)→TEXT

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-24 16:26:40 +08:00
Your Name fbf5eadcf2 fix(security): R2+R3 全面代码审计修复 — 3 CRITICAL / 9 HIGH / 15 MEDIUM / 10 LOW
CRITICAL:
- C-1: sync_service.py rsync命令shlex.quote防Shell注入回归
- C-2: agent.py exec端点危险命令正则拦截+compare_digest+僵尸进程修复
- C-3: WebSSH JWT token绑定server_id防IDOR

HIGH:
- H-1: 所有PUT/POST端点setattr改为字段白名单防任意字段注入
- H-2: settings/assets/scripts端点添加JWT认证
- H-3: refresh_token invalidate-then-generate防并发重放
- H-4: servers.py Redis pipeline解决N+1查询
- H-7: settings API Key/Secret掩码+禁止修改
- H-8: TOTP暴力破解速率限制(5次/5分钟)
- H-9: get_optional_admin改用request-scoped session

MEDIUM:
- M-2: X-Real-IP优先+X-Forwarded-For取末值防IP伪造
- M-4: asyncssh异常信息脱敏(只含server_id)
- M-5: 分页limit上限(500/200/500/500)
- M-9: API层Redis依赖抽象至dependencies.py
- M-10: WebSocket ConnectionManager多worker Redis聚合
- M-13: login_attempts复合索引
- M-14: ServerRepository.get_by_ids批量查询
- M-15: API错误消息统一中文

R3追加:
- sysctl命令注入防护+regex验证
- $DB_PASS明文存储→masked_command双命令方案
- MYSQL_PWD环境变量替代-p flag
- health端点拆分(公开/需认证)
- repo层**kwargs→字段白名单
- 全局str(e)信息泄露修复(API/Telegram/WebSocket)
- SSRF私有IP拦截
- Nginx HTTPS配置+DB备份脚本
- 前端CDN SRI哈希+XSS修复
- __import__替换为正常import

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 10:58:33 +08:00
Your Name 9bba58a529 feat: Telegram test+ChatID, Agent IP allowlist/upgrade, alert history page
Telegram:
- POST /api/settings/telegram/test: send test message (checks token+chat_id)
- GET /api/settings/telegram/chats: call getUpdates, return up to 5 chats
- settings.html: test button + detect chat IDs with click-to-fill

Agent IP allowlist (web/agent/agent.py):
- allowed_ips config: list of trusted IPs/CIDRs from config.json
- _ip_allowed(): checks exact IP, CIDR (ipaddress module), hostname
- verify_api_key(): now checks IP allowlist before API key
- /health: also checks IP allowlist
- install.sh: auto-extracts central server IP from --url, adds to allowed_ips

Agent auto-upgrade (server/api/servers.py):
- POST /api/servers/{id}/upgrade-agent: SSH → curl new agent.py → systemctl restart
- servers.html: 升级 Agent button in Agent tab (only when online)

Alert history (new page):
- domain/models: AlertLog table (server_id, type, value, is_recovery, created_at)
- migrations.py: CREATE TABLE IF NOT EXISTS alert_logs
- websocket.py: _save_alert_log() called from broadcast_alert/recovery
- settings.py: GET /api/alert-history/ (paginated, filters), GET /stats
- main.py: register alert_history_router
- alerts.html: new page with stats cards, top-servers bar chart, alert list
- layout.js: 🔔 告警中心 added to sidebar nav

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 18:27:12 +08:00
Your Name da43960f38 feat: subscription URL stored in settings, auto-refresh allowlist every 2h
config.py:
- LOGIN_SUBSCRIPTION_URL: stored in DB, configurable from UI
- LOGIN_MANUAL_IPS: manually added IPs (preserved across auto-refresh)

background/ip_allowlist_refresh.py (new):
- ip_allowlist_refresh_loop(): primary-worker task, every 2h
- _do_refresh(): fetch subscription, parse IPs, merge with manual IPs,
  write combined to LOGIN_ALLOWED_IPS + DB setting; runs once at startup (5s delay)
- get_last_refresh_time(): returns last successful refresh timestamp

main.py:
- Register ip_allowlist_refresh_loop as background task

settings.py:
- GET /ip-allowlist: now returns subscription_url, manual_ips, last_refresh
- POST /ip-allowlist: saves manual_ips + subscription_url, triggers refresh
- POST /ip-allowlist/manual: append to manual list only, trigger rebuild
- DELETE /ip-allowlist/ip: remove single manual IP, trigger rebuild

settings.html:
- Subscription URL field with 保存 + 🔄 instant-refresh button
- Last refresh timestamp display
- Status badge shows '订阅自动刷新' when URL configured
- IP badges: blue=manual (deletable), grey=from subscription (auto)
- 预览 button to inspect subscription IPs without saving

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 18:15:29 +08:00
Your Name 61b891db73 fix: Phase 3 line-walk fixes (3a-3d)
F3a-01 agent.py: _safe_float() prevents ValueError from non-numeric metric values
F3b-01 schedule_runner.py: fix tz-aware minus naive DateTime TypeError
F3b-02 schedule_runner.py: cron field divided by 0 returns False instead of crash
F3c-01 redis/client.py: mask credentials in REDIS_URL log output
F3d-01 main.py: cancel background tasks when primary worker lock is lost
F3d-02 main.py: strip whitespace from CORS origins after split

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 15:37:15 +08:00
Your Name 752a24497c feat: Phase 2 security audit fixes + script execution platform
Security (P0/P1/P2):
- WebSSH: dedicated short-lived token, server_id binding, 4003 close code
- Remove /api/agent/exec from control plane (RCE surface eliminated)
- Global JWT middleware (JwtAuthMiddleware) with install-mode bypass
- decrypt_value: failure returns None, never leaks ciphertext
- Telegram: sanitize_external_message strips sensitive fields
- Agent auth: startup enforces non-empty API key, compare_digest
- Credentials: password_set bool flag, no plaintext in API responses
- audit_log: writes admin_username + ip_address on all CUD ops
- Install lock: all /api/install/* except GET /status return 403 post-install
- WebSocket dedup: publish once, subscribers deliver locally

Script execution platform:
- script_jobs.py / script_job_callback.py: async batching and callback
- script_execution_store.py / script_callback_rate.py: Redis-backed state
- script_execution_flush.py: background flusher to MySQL
- scripts.html / script-executions.html: full execution UI
- agent_url.py: centralised URL builder

Frontend:
- All 13 pages migrated from CDN to /app/vendor/ (no external deps)
- vendor/: alpinejs, tailwindcss-browser, xterm, xterm-addon-*, qrious
- Dashboard WebSocket real-time alerts; 8h JWT session timeout

Tests:
- test_security_unit.py: 15 unit tests (JWT, sanitize, vendor, install 403)
- test_api.py: env-configurable admin credentials

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 15:26:56 +08:00
Your Name 8530f0e0d5 安全补强: 6项P0/P1漏洞修复
P0-1: PHP配置注入防护 — install.py添加_escape_php_string()转义单引号和反斜杠
P0-2: WebSocket JWT校验 — _verify_ws_token()要求exp+sub字段
P1-1: 删除SHA256密码fallback — auth_service.py和auth.py直接import bcrypt
P1-3: LIKE通配符转义 — search.py添加_escape_like()并对所有ilike()加escape参数
P1-2: 安全响应头中间件 — main.py添加SecurityHeadersMiddleware注入4个安全头
P0-3: Refresh Token重用检测 — Admin模型添加token_version字段,token格式改为token:admin_id:version

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 22:16:50 +08:00
Your Name cea5730804 P0: Add StaticFiles mount + root redirect to install wizard
Critical fix: FastAPI was not serving any static files, causing all
frontend pages (install.html, login.html, etc.) to return 404.

Changes:
- Add StaticFiles mount at /app/ for web/app/ directory (html=True)
- Redirect root path / to /app/install.html in install mode
- Remove redundant "/" path bypass in InstallModeMiddleware
- Production Nginx still serves static files directly (no conflict)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 12:24:32 +08:00
Your Name cb5b4c42de 多Worker守护 + 告警服务器名 + 清理PHP残留
- main.py: Redis主Worker选举,防止多Worker重复执行后台任务
- agent.py: 告警/恢复广播使用真实服务器名(查MySQL)替代"server-{id}"
- sync_v2.py: 修复browse目录解析死代码,正确取parts[8]
- install.html: 移除过时install.php引用,更新为"删除.env重装"
- nginx配置: 移除PHP-FPM路由(install.html纯静态无需PHP)
- schedule_runner: 清理未使用的get_redis_sync导入

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 11:54:11 +08:00
Your Name d4ea03d735 P2: 全局搜索功能 — 后端API + 前端侧边栏搜索
- 新增 /api/search/ 端点: 跨服务器/脚本/凭据/调度搜索
- layout.js: 侧边栏底部搜索框, 300ms防抖, 下拉结果面板
- main.py: 注册搜索路由
2026-05-22 09:08:09 +08:00
Your Name f796ddf0a5 feat: D2 install.php→install.html迁移 + D3 WebSSH终端完善
D2: install.php → install.html + FastAPI API
- 新增 server/api/install.py: 6个安装向导API端点(无JWT)
- 新增 web/app/install.html: Alpine.js五步安装向导
- main.py: 条件启动模式(无.env=安装模式,仅/api/install/可用)
- InstallModeMiddleware: 安装模式下非安装路由返回503
- DbSessionMiddleware: 跳过安装API(自管理临时引擎连接)
- 三写一致性: .env + config.php + MySQL settings表同步

D3: WebSSH terminal.html 完善
- 全功能xterm.js终端 + Koko协议 + 自动resize
- Alpine.js + Tailwind CSS v4 统一风格
- 全屏/断开连接/连接状态指示器

文档更新:
- status.md: 第五步→, 完成度~95%
- roadmap.md: D2技术债务已解决
2026-05-22 08:37:01 +08:00
Your Name c9a99f4fb3 fix: 全项目文档对齐 + 代码清理
代码修复:
- web/agent/agent.py: datetime.utcnow() → datetime.now(timezone.utc)
- requirements.txt: 移除 paramiko==3.5.0 (已无活跃引用)
- 删除 server/infrastructure/ssh/pool.py (DEPRECATED, 无引用)

连接池三层对齐 (config.py/.env.example/session.py):
- DB_POOL_SIZE 100→160, DB_MAX_OVERFLOW 100→120
- 基于 MySQL max_connections=400, install.php 公式

文档修复 (21项):
- P0: 硬编码域名/IP替换为配置变量占位符
- P1: 10个过时设计文档加归档标注 (引用旧文件结构)
- P2: step-3-webssh报告 paramiko引用修正
- 6份审查报告连接池参数勘误 100/100→160/120
- ECC安全报告 EC5 datetime.utcnow 标记已修复
- docs/README.md 文档索引重写
- docs/memory/mem_nexus_overview.md 移除硬编码凭证
- docs/project/tech-stack-inventory.md paramiko标记已移除

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 08:19:56 +08:00
Your Name 56993e4f98 fix: auth logout, Nginx configs, missing dependency, CORS
- auth: logout endpoint now accepts refresh_token (was admin_id which
  frontend can't know) — added logout_by_token() to AuthService
- api.js: sendBeacon uses Blob with application/json content-type
  (was sending text/plain which FastAPI couldn't parse)
- Nginx: fixed SPA fallback to 404 (not SPA), added install.php
  PHP-FPM handler, added production HTTPS config for api.synaglobal.vip
- requirements: added cryptography==44.0.0 (used by crypto.py but
  was missing from requirements.txt)
- models: removed unused Fernet import from domain models
- CORS: added http://api.synaglobal.vip origin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 00:30:28 +08:00
Your Name 814e11588e feat: P1 background tasks + server stats endpoint
1. schedule_runner.py: cron-based schedule execution every 60s
   - Parses 5-field cron expressions (*, */N, ranges, lists)
   - Triggers SyncEngineV2.sync_files for due schedules
   - Prevents re-trigger within same minute
2. retry_runner.py: automatic retry of failed pushes every 5min
   - Exponential backoff (60s base, doubles per retry, max 64x)
   - Respects max_retries from PushRetryJob model
3. GET /api/servers/stats: dashboard aggregation endpoint
   - Returns total/online/offline counts + category breakdown
   - Reads real-time status from Redis, falls back to MySQL
   - Registered before /{id} to avoid path collision
4. main.py: register schedule_runner + retry_runner as background tasks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:58:17 +08:00
Your Name 539c33ef42 feat: Nexus 6.0 6-step implementation (Step 0-5)
Step 0: Infrastructure hardening — Redis BlockingConnectionPool,
WebSocket two-layer (memory+Redis Pub/Sub), JWT auth, DB session leak fix
Step 1: Data layer — 4 new tables (platforms/nodes/command_logs/ssh_sessions),
data migration (category→Node), repos + API routes
Step 2: Auth layer — JWT middleware on all routes, TOTP JWT integration
Step 3: Web SSH — asyncssh connection pool, /ws/terminal endpoint,
xterm.js frontend, Koko protocol
Step 4: Sync engine v2 — file/command/config/SFTP modes, parallel execution
Step 5: Frontend migration — 12 Tailwind CSS v4 + Alpine.js pages,
PHP-FPM removal from nginx config

21 Python backend + 12 HTML frontend + 2 deploy configs + 3 test files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:11:38 +08:00
Your Name f9045a8404 refactor: 仓库结构扁平化 + PHP前端合并到Nexus仓库
- 将 Nexus/Nexus/* 移到仓库根目录(消除双层嵌套)
- 删除旧的多层空壳目录 (server/, web/, agent/, deploy/, docs/)
- 将PHP前端 (web/) 合并进Nexus仓库 — 统一管理
- 部署时 git clone Nexus 仓库即可,不再需要两个仓库

目录结构:
  server/     ← Python FastAPI后端
  web/        ← PHP前端 (install.php, config.php, etc)
  deploy/     ← Supervisor + Shell健康检查
  docs/       ← 部署文档
  tests/      ← 测试
  .env        ← 不在git中 (install.php生成)
  .gitignore  ← 排除 .env, SECRETS.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:24:21 +08:00