Nexus Agent
ca0de7d04d
docs: Layer 3 模拟巡检告警验证报告
...
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
记录 flock 失败计数 bug 修复与 iptables 演练结果。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 20:56:21 +08:00
Nexus Agent
764703d401
fix(deploy): health_monitor flock 失败计数回传
...
flock 子 shell 递增后未回传 FAIL,导致 Layer 3 永不触发重启与 Telegram。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 20:53:14 +08:00
Nexus Agent
b8785d1d51
docs: Layer 3 巡检 Telegram 配置后生产复查
...
记录用户配置 Telegram 后 env 同步、health_monitor 就绪与 cron 状态。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 20:49:13 +08:00
Nexus Agent
5b372fb8a2
docs: Layer 3 巡检部署生产验证报告
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 20:19:31 +08:00
Nexus Agent
f9934bd4f1
feat(ops-patrol): Layer 3 巡检与 Telegram 配置打通
...
保存 Telegram 时同步至 .env,health_monitor 支持 MySQL 回退,
设置页展示巡检状态,部署时自动安装 cron。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 20:17:24 +08:00
Nexus Agent
66a4cba39b
docs: 设置页 Telegram 修复生产验证报告
...
记录 540a7fc 部署结果与浏览器终验步骤。
2026-06-07 19:46:43 +08:00
Nexus Agent
540a7fce05
fix(settings): Telegram 检测/测试闭环与 8 项告警开关恢复
...
检测与测试前自动持久化 Token/Chat ID;getUpdates 清除 Webhook 并返回具体 API 错误;恢复 NOTIFY 分项开关与免密 reveal。
2026-06-07 19:45:07 +08:00
Nexus Agent
2e911dcca7
fix(frontend): 设置页恢复 IP 白名单订阅 URL 与解析预览
...
补回代理订阅配置 UI,修正 ip-allowlist 保存 payload 为 manual_ips + subscription_url。
2026-06-07 19:34:24 +08:00
Nexus Agent
a5d5518054
fix(frontend): 设置页恢复 Telegram Chat ID 自动检测
...
Vue SPA 迁移遗漏 getUpdates 检测按钮;对接 GET /settings/telegram/chats,并修正 cron 脚本 bash 调用。
2026-06-07 19:31:13 +08:00
Nexus Agent
e3fe161ae5
fix(deploy): 健康检查 PORT 缺省 8600
...
NEXUS_PUBLISH_PORT 未写入 .env.prod 时避免空端口误打 OpenResty 导致部署脚本误报失败。
2026-06-07 18:05:27 +08:00
Nexus Agent
d0be2fdcf1
fix(deploy): SSH secrets 加载、Docker 运行时检测与外网探测脚本修复
...
使 deploy-production.sh 可读本机 secrets 并在非 docker 组用户下用 sudo 识别 1Panel 栈;修复 security_probe_external.sh 的 curl shift 误用与 WebSocket 自动 venv。
2026-06-07 17:34:27 +08:00
Nexus Agent
72d82d737b
fix(security): BL-07 WS 403 澄清与 code-review 跟进加固
...
外网无 token WebSocket 的 HTTP 403 为应用层拒绝而非反代故障;边端 agent
在中心 401 时停止心跳重试;install 锁定路由级 404 且归档失败 fail-closed。
同步安全规范与 BL-06 一致,门控 7/7 PASS。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 12:12:49 +08:00
Nexus Agent
eab35a35be
fix(security): BL-06 强制 Agent per-server key 并合并心跳单次查库
...
移除 Agent 认证与安装链路的 global API_KEY 回退,收口 risk-acceptance 接受项 2;巡检补修心跳重复 get_server 并加 assert_called_once 回归测试。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 11:17:41 +08:00
Nexus Agent
e5e2582743
fix(security): 外网攻击面加固 BL-01~05
...
收紧 PUBLIC 路径误匹配、强制 health/detail 与壁纸 sync 鉴权、默认关闭 OpenAPI;
安装锁定后 /api/install/* 统一 404;附探测脚本、测试与审计文档。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-07 01:45:10 +08:00
Nexus Agent
722917bfc9
fix(api): API 全量巡检 B1–B6 修复 server_ids 上限与 pending 审计
...
限制健康检查/推送/脚本执行的 server_ids 规模,补齐 pending 重试失败与删除审计,并附分批巡检报告。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:57:46 +08:00
Nexus Agent
ac17f91106
docs(audit): 14 页 API 契约审计与凭据轮询 SSOT 收尾
...
记录凭据轮询/pending 契约对照与生产验证,更新功能指南与附录 J,并将 pending 相关类型集中到 api.ts。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:50:05 +08:00
Nexus Agent
9ee5c8a708
docs(project): nx 上帝菜单巡检 round1–10 归档总结
...
新增 nexus-god-menu-audit-summary.md 汇总巡检交付与日常速查,并链入文档索引。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:25:44 +08:00
Nexus Agent
fb9dbcb11a
docs(deploy): 同步 1Panel 运维 SSOT(round4–8 能力)
...
README 与知识文档补全 nx cron/备份/验收;卸载脚本提示改为 1Panel 容器名。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:23:27 +08:00
Nexus Agent
72e46cef32
fix(deploy): 升级后镜像验收与 verify 脚本修复
...
验收检查容器内 round6/7 特性;修复 host.docker.internal 引号;nx verify 与升级后自动验收。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:21:44 +08:00
Nexus Agent
e5d482264d
fix(install): 向导守护 UI 与升级后 cron 交互提示
...
Docker 完成页展示 Layer 3 cron 步骤与 host_deploy_root;TTY 下 nx update 可一键安装巡检/备份 crontab。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:20:23 +08:00
Nexus Agent
c9e08799f9
fix(install): 守护配置对齐宿主机 cron 与验收检查
...
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
Docker 向导提示 nx cron/宿主机路径;裸机 cron 含 db_backup;验收脚本检查 cron 与 MySQL 备份能力。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:11:02 +08:00
Nexus Agent
89865ec690
fix(deploy): 部署脚本自动识别 Docker 与 Supervisor 运行时
...
upgrade/deploy-production 等分流到 nexus-1panel upgrade;升级完成后提示安装 nx cron。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 23:07:47 +08:00
Nexus Agent
ba69bc3355
fix(deploy): git pull 后备份脚本不依赖可执行位
...
db_backup/backup_mysql 改为检测文件存在并用 bash 调用;install_ops_cron 一并 chmod 备份脚本。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 22:39:10 +08:00
Nexus Agent
49f159a8ce
fix(deploy): install_ops_cron 自动安装 cron 包
...
生产 Azure 主机默认无 crontab,安装脚本现会 apt install cron 并启用服务。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 22:38:43 +08:00
Nexus Agent
4e1347ba45
fix(deploy): Docker 感知 MySQL 备份与 nx cron 安装
...
升级/定时备份通过 docker exec 1Panel MySQL 容器 dump,不再依赖宿主机 mysqldump;nx 菜单新增巡检与备份 crontab 安装。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 22:37:49 +08:00
Nexus Deploy
61b8d7d419
fix(deploy): health_monitor Docker 适配与巡检第三轮修补
...
Docker 生产用 docker restart;读 .env.prod 端口与容器 Telegram;已归档跳过全量热同步。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 22:25:27 +08:00
Nexus Deploy
954bdbd972
fix(deploy): 验收脚本已安装时输出正确通过文案
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 21:54:03 +08:00
Nexus Deploy
314bece418
fix(deploy): 验收脚本已安装时跳过 install API 检查
...
锁定后 /api/install/* 返回 403 属预期,不应判 FAIL。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 21:53:43 +08:00
Nexus Deploy
687e059a86
fix(deploy): 上帝菜单巡检第二轮 — 全新安装卷冲突与验收修正
...
FRESH 清除 nexus-state 旧锁;PENDING=1 时 entrypoint 不恢复旧 env;验收脚本已安装期望 404。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 21:53:03 +08:00
Nexus Deploy
baacdb0252
fix(deploy): 已归档安装向导时 sync 脚本验收期望 404
...
避免 nx update 因 install.html 已移除而误报失败。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 21:31:06 +08:00
Nexus Deploy
58bdf820dc
fix(install): 安装锁定后将 install.html 归档为 .bak
...
防止已安装环境继续提供安装向导静态页;entrypoint 与升级脚本避免容器重建后恢复。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 21:30:15 +08:00
Nexus Deploy
dd66d99f2d
fix(deploy): nx 上帝菜单巡检修补 1panel-network 与升级竞态
...
purge 阶段 compose 叠加 1panel overlay;菜单启动/重建与回滚后校验网络;install-auto 已安装改走 update。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 21:27:01 +08:00
Nexus Deploy
107b089b16
fix(1panel): 安装锁持久化与升级后 1panel-network 校验
...
防止 nx update 重建容器后丢失安装锁、未接入 1panel-network 导致 MySQL/Redis 不可达。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 20:52:13 +08:00
Nexus Deploy
1f5daebeed
fix(deploy): nx update 在 set -u 下 local root 同行展开报错
...
拆分 nexus_publish_port/set_install_complete/sync_env_prod_to_volume 的 local 声明,
避免 env_file="$root/..." 在 root 赋值前展开导致 unbound variable。
2026-06-06 20:38:11 +08:00
Nexus Deploy
4ba45abf38
feat(servers): 凭据轮询登录与连接失败列表
...
- 密码/SSH密钥预设增加用户名;快速添加(IP)轮询全部预设尝试 SSH 登录
- 成功入 servers 列表;失败写入 pending_servers 并支持重试/删除
- 新增 credential_poller、try_ssh_login 与 add-by-ip/pending API
2026-06-06 20:08:48 +08:00
Nexus Deploy
5a56e5a8cb
fix(1panel): 安装向导脱敏、配置一致性与 nx update 门控回滚
...
- /state 白名单脱敏;init-db db_port 修复;connection-check 后清空 redis_pass
- install.html sessionStorage token 与无 token 友好提示
- nx update: 镜像 import 门控、健康失败自动回滚、PENDING=0 回写、卷双写
- Redis 容器改名密码迁移;备份失败默认 WARN;update.sh 管道 ROOT 回退
2026-06-06 17:40:30 +08:00
Nexus Deploy
850038a3ec
fix(install): 安装向导 Redis 密码不被 nx update/Compose 覆盖
...
Compose 不再注入 NEXUS_REDIS_URL;nx update 保留卷内带密码 URL;步骤 4 可从 install state 修复无密码 URL。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 11:34:26 +08:00
Nexus Deploy
beb802802a
chore: 添加 scripts/git-push.sh 与本地 Gitea secrets 约定
...
push 读取 deploy/nexus-1panel.secrets.sh(gitignore),clone/pull 仍可匿名。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 11:22:07 +08:00
Nexus Deploy
476d87c678
docs: Gitea 公共仓库无需凭据
...
更新 .cursorrules 与 linux-dev-paths,明确不配置/探测 GITEA token。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 11:13:07 +08:00
Nexus Deploy
49f88a2cd8
fix(install): Docker .env 持久化与 entrypoint 覆盖 Compose 占位符
...
向导 init-db 后立即同步 nexus-state 卷;entrypoint 跳过不完整 env 并在启动前 source /app/.env,避免缺 DATABASE_URL 与无密码 REDIS_URL 导致容器崩溃。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 11:08:22 +08:00
Nexus Deploy
b11360015d
fix(install): 1Panel Redis 无账号与步骤 4 URL 自愈
...
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
确立 Redis 仅密码认证(:pass@/default),隐藏误导性用户名字段;
connection-check 自动修正错误 NEXUS_REDIS_URL,并更新运维文档与验收脚本。
2026-06-06 07:51:52 +08:00
Nexus Deploy
3b2856f388
fix(install): auto-resolve 1Panel Redis auth (:pass@ / default)
...
Stop prefilling root; probe multiple Redis URL formats on credential
check and persist the URL that works for init-db.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 07:15:57 +08:00
Nexus Deploy
9d9fbc62f5
docs: add 1Panel operations knowledge SSOT and Redis test script
...
Consolidate install wizard, networking, URL formats, and troubleshooting
into docs/project/nexus-1panel-operations-knowledge.md.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 07:08:42 +08:00
Nexus Deploy
807f4c2448
fix(install): correct Redis URL auth for 1Panel root user
...
Password must use redis://:pass@ or redis://root:pass@ host; wizard adds
redis_user field defaulting to root on 1Panel Docker installs.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 06:59:45 +08:00
Nexus Deploy
da061d35db
feat(install): require MySQL/Redis credential check at wizard step 3
...
Add test-credentials API and UI gate before init-db writes .env.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 06:47:22 +08:00
Nexus Deploy
d0544c9bd2
fix(1panel): grant nexus@% for Docker MySQL 1045 on install
...
Add fix-1panel-mysql-grant.sh and clearer install wizard errors when
1Panel MySQL only allows nexus@localhost.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 06:19:19 +08:00
Nexus Deploy
3f5eacae60
feat(deploy): add 1Panel install wizard verify script
...
Server-side checklist for 1panel-network, container host sync, and
install API defaults before completing /app/install.html.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 06:05:15 +08:00
Nexus Deploy
b25d0798f6
fix(1panel): sync MySQL/Redis container hosts on nx update
...
Upgrade was skipping 1panel-network detection; wizard now overrides stale host.docker.internal from volume/API defaults.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 05:47:43 +08:00
Nexus Deploy
6b1d23c7d7
fix(1panel): sync Redis URL to container name on 1panel-network
...
Update NEXUS_REDIS_URL when detecting 1Panel-redis-*; add Redis TCP precheck and connection errors matching MySQL.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 05:39:52 +08:00
Nexus Deploy
6951b8049f
fix(1panel): join 1panel-network and connect MySQL/Redis by container name
...
Per 1Panel App Store architecture, bridge apps must use Docker DNS on 1panel-network instead of host.docker.internal.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 05:35:04 +08:00
Nexus Deploy
da0424a268
fix(install): MySQL TCP probe and clearer host.docker.internal errors
...
Step 2 now detects whether host MySQL is listening; init-db fails fast with 1Panel setup guidance on error 2003.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 05:22:16 +08:00
Nexus Deploy
569263dddb
fix(install): remove redundant Redis/MySQL host hints in wizard step 3
...
Docker defaults already prefill host.docker.internal; drop duplicate 1Panel install reminders from the form.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 05:08:55 +08:00
Nexus Deploy
646929ddff
feat(deploy): register nx globally via install-nx-cli.sh
...
Centralize chmod and /usr/local/bin symlinks; install, upgrade, update, and every nx invocation refresh the global nx command.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 04:43:00 +08:00
Nexus Deploy
0a7c5ee617
fix(deploy): set executable bit on nx and refresh symlinks on update
...
Git tracked deploy/nx as 644 so /usr/local/bin/nx failed with Permission denied after pull; update.sh now chmods CLI scripts before upgrade.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 04:39:33 +08:00
Nexus Deploy
93400b7793
fix(install): split Redis install check (step 2) from connection test (step 4)
...
Step 2 only TCP-probes host Redis without blocking the wizard; step 4 runs /connection-check on MySQL and Redis from .env before creating the admin account.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 04:32:47 +08:00
Nexus Deploy
a5aa5f81ad
docs(deploy): merge nx god into unified menu and expand README
...
Consolidate install and ops into a single nx menu with one-click update via update.sh; document all curl install/update entry points in the root README.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 04:27:11 +08:00
Nexus Deploy
86c865e710
feat(deploy): add update.sh and always rebuild on upgrade
...
Upgrade no longer exits when Git is already up to date; it still rebuilds the Nexus image to pick up entrypoint changes. Add deploy/update.sh as the one-command entry point.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 04:16:15 +08:00
Nexus Deploy
1bd69077a2
fix(deploy): auto-remove legacy Compose MySQL containers on upgrade
...
Run uninstall-mysql-compose before install/upgrade and pass --remove-orphans so nexus-prod mysql orphans are stopped after the service is dropped from compose.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 03:32:00 +08:00
Nexus Deploy
f37ebf8621
feat(docker): remove bundled MySQL from production Compose stack
...
Production installs now run only the Nexus container; MySQL and Redis are self-hosted on the machine or 1Panel, with install wizard defaults pointing at host.docker.internal.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 03:27:57 +08:00
Nexus Deploy
e42dc77127
feat(deploy): add redis compose uninstall; require Redis in install wizard
...
Step 2 blocks until Redis connects; uninstall-redis-compose.sh removes legacy
nexus-prod-redis container without touching host/1Panel Redis.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:51:52 +08:00
Nexus Deploy
536d520744
fix(nx): resolve deploy dir when invoked via /usr/local/bin symlink
...
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
readlink -f fixes sourcing nexus-1panel.sh; register nexus-1panel global cmd.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:49:34 +08:00
Nexus Deploy
6276ea08b7
feat(docker): remove bundled Redis; use external host install
...
Compose stack is MySQL+Nexus only; wizard Redis check is non-blocking
and defaults to host.docker.internal for self-managed Redis.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:48:00 +08:00
Nexus Deploy
c81fe3183f
fix(deploy): sync install.py into container for Redis env-check hotfix
...
sync-install-wizard-to-container.sh now copies server/api/install.py and
restarts Nexus so Docker installs pick up redis:6379 without full rebuild.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:34:53 +08:00
Nexus Deploy
5e7c5beb43
fix(install): probe redis via docker service host in env-check
...
Install wizard no longer hardcodes 127.0.0.1:6379; Docker installs get
mysql/redis prefills and a passing Redis check inside the nexus container.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:31:11 +08:00
Nexus Deploy
9b7dba99ff
fix(install): drop Gitea token warning for public repo installs
...
Public anonymous clone needs no secrets file; document token as optional
for private repos only.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:20:56 +08:00
Nexus Deploy
222703d733
fix(install): allow curl-pipe bash when set -u is enabled
...
BASH_SOURCE[0] is unset for stdin scripts; call main directly in
install-1panel-docker.sh and quick-install.sh.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:11:40 +08:00
Nexus Deploy
d884ea00ca
feat(install): add full-stack install-1panel-docker.sh for fresh servers
...
Replace the nx redirect stub with a real orchestrator that chains 1Panel
setup, Docker Compose checks, and install-nexus-fresh; document UI-only
OpenResty proxy rules in README-1panel.md.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 02:00:24 +08:00
Nexus Deploy
422dcae0ff
fix(docker): bake install.html into prod image with build verify and sync script
2026-06-06 01:14:59 +08:00
Nexus Deploy
343def7e77
fix(docker): include install.html and wizard vendor assets in prod image
2026-06-06 00:36:03 +08:00
Nexus Deploy
83ce11f55c
feat(install): per-host auto-generated secrets for Docker installs
...
Each fresh 1Panel/Docker install generates unique MYSQL and NEXUS keys
via scripts/generate_nexus_secrets.py; install wizard reuses compose env.
2026-06-06 00:25:57 +08:00
Nexus Deploy
e613aecc8e
docs: clarify Gitea web URL vs git clone URL in README
2026-06-06 00:19:04 +08:00
Nexus Deploy
f71da47ccf
docs: add root README for Gitea product page and install scripts
2026-06-06 00:14:34 +08:00
Nexus Deploy
1acac6439a
feat(deploy): public repo quick-install via curl (1Panel style)
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-06 00:11:43 +08:00
Nexus Deploy
feda614c52
fix(deploy): register nx/nexus-fresh in PATH for root
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-05 23:58:37 +08:00
Nexus Deploy
6cef3d2942
fix(deploy): private Gitea raw 404 — use clone or token API download
...
Anonymous curl saved "Not found." causing "Not: command not found";
add download-install-fresh.sh, --skip-clone, and script self-check.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-05 23:52:48 +08:00
Nexus Deploy
00f44032ff
feat(deploy): add 1Panel-style fresh install script for empty DB
...
install-nexus-fresh.sh with phased checks, install wizard URL, and nx god
menu hints; wired into nx install-fresh and install menu option 6.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-05 23:44:38 +08:00
Nexus Deploy
8ddcf2ad0d
feat(deploy): add nx interactive installer and god ops menu
...
Single entry deploy/nx for install wizard, post-install restart/upgrade/logs,
and install-auto for non-interactive 2c8g setup on 1Panel Docker hosts.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-05 23:41:04 +08:00
Nexus Deploy
65e4478b4b
feat(deploy): load credentials from nexus-1panel.secrets.sh
...
Keep secrets out of tracked scripts; support git add -f secrets file,
git remote token parsing, and port/firewall checks for one-click install.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-05 23:37:37 +08:00
Nexus Deploy
2f830424a4
feat(deploy): unified 1Panel script with profiles and port checks
...
Merge install/upgrade into nexus-1panel.sh with 1c4g/2c8g/4c16g resource
profiles; preflight Gitea and firewall hints; post-install HTTPS health probe.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-05 22:59:47 +08:00
Nexus Deploy
7b33b745a0
feat(deploy): add 1Panel Docker one-click install script
...
Automates clone, docker/.env.prod, compose up, and health check for 2C8G prod stack.
2026-06-05 22:52:44 +08:00
Nexus Deploy
bfda70bbe7
chore(docker): tune production stack for 2C8G hosts
...
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
Add mysql-prod-2c8g.cnf, container mem/cpu limits, Redis maxmemory,
and default Nexus pool 30/20 for 8GiB 1Panel deployments.
2026-06-05 22:44:06 +08:00
Nexus Deploy
2f67e9e2b9
docs: add 1Panel Docker production deploy stack
...
Add Dockerfile.prod, docker-compose.prod.yml, OpenResty example,
and migration plan for Baota to 1Panel + Compose deployment.
2026-06-05 22:40:04 +08:00
Nexus Deploy
811eb97fbf
chore: Ubuntu local dev scripts, deploy gate, and audit changelogs
...
Rename WSL helpers to Linux-native scripts, expose Redis in docker-compose,
prefer .venv tools in pre_deploy_check, and record 2026-06-04 audit waves.
2026-06-04 23:02:21 +08:00
Nexus Deploy
0100ab2582
docs: consolidate archive, SSOT guide, and agent entry stubs
...
Move line-walk/delta/phase2/frontend audits and legacy memory into
docs/archive/, add functional development SSOT, thin AGENTS/CLAUDE stubs,
and regenerate changelog/audit indexes via consolidate_docs.py.
2026-06-04 23:01:03 +08:00
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
Nexus Deploy
a2ae74d582
release: BUG fixes batch 1-6, full bug scan docs, Ubuntu/Linux dev
...
- Backend: auth refresh reuse, schedule/retry/sync/agent/files fixes
- Frontend: push WS, files ETag browse, vite build assets
- Docs: audit/changelog, production deploy gate, bug scan registry B7-77
- Deploy: deploy-production.sh, prune assets, gate logs
2026-06-04 14:01:14 +08:00
Your Name
9ac6a2d27f
fix(docker): track docker/.env.example despite .env.* gitignore
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-03 00:59:00 +08:00
Your Name
3cec226b89
feat(docker): add Compose stack for MySQL, Redis and Nexus API
...
- Dockerfile with healthcheck and entrypoint for deps + .env persistence
- generate_env.py for local secrets; design docs and changelog
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-03 00:58:46 +08:00
Your Name
51948469c2
build(frontend): track Vite output in Git for Gitea deploy
...
- Stop ignoring web/app/index.html and web/app/assets/
- Bundle index-DBKIQT7H.js from current vite build (~101MB assets)
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-03 00:52:44 +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
9c9c763e9c
fix(credentials): password preset is name+password only, no username field
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 16:08:50 +08:00
Your Name
0cc1cc14a4
fix(terminal): restore app-bar top inset so tab bar and xterm are not clipped
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 16:02:17 +08:00
Your Name
f078d0e03b
feat(push): localize sync/rsync error messages to Chinese in history and progress
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 15:18:01 +08:00
Your Name
524dabcf7f
refactor(editor): P0 — per-tab model, EOL preservation, conflict detection (409)
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 14:46:49 +08:00
Your Name
0ccd1ba934
fix(files): use proxyRefs for inject context unwrapping
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 08:25:25 +08:00
Your Name
a6673157a5
fix(files): unwrap injected refs via reactive context for v-model
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 08:23:03 +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
68fdcbae0a
refactor(terminal): split TerminalPage into composables and components (T1-T6)
...
Extract session/WS/xterm logic with markRaw native store, per-session disconnect overlay, shared server picker, and cmd bar via ShellHighlightField expose.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 06:44:56 +08:00
Your Name
181560eca2
fix(ui): align servers stat cards with dashboard; improve files browse errors
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 06:08:02 +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
6cb591212d
refactor(files): P2 split UI into components with page context inject
...
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
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 05:14:13 +08:00
Your Name
7cbddf5d48
refactor(files): P1 split composables, Pinia store, directory cache
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 05:05:26 +08:00
Your Name
cb738a8e9a
fix: file manager double browse from v-select init and stale chunks
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 04:36:46 +08:00
Your Name
5393252036
fix: eliminate double browse requests in file manager
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 04:29:11 +08:00
Your Name
3bc2843642
fix: browse序号保护防止token刷新重试导致的双刷新
2026-06-02 03:48:01 +08:00
Your Name
1d6d26d612
fix: 加载中隐藏空状态提示,消除进目录时的视觉双刷新
2026-06-02 03:19:27 +08:00
Your Name
c65e3ea2a7
fix: 目录双击导致双刷新(e.detail守卫),横幅仅在实际权限错误时显示
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 03:07:51 +08:00
Your Name
67dac0168f
feat: 文件管理器复制粘贴守卫、2MB编辑限制、一键配置sudoers、编辑器外观重构
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 02:20:22 +08:00
Your Name
57d67c494b
fix: 警告横幅关闭后进子目录不再重新出现,文案简化
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 01:51:13 +08:00
Your Name
928e3c5fdb
fix: 登录白名单 IP 绕过防暴破锁定
...
白名单内 IP 跳过失败次数锁定;失败仅审计不计数;成功登录清除该用户历史失败记录。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 01:37:22 +08:00
Your Name
832e34fd98
fix: 修复 6 个 MEDIUM 级 Bug (锁定/重试/调度/分页/SSH池/token_version)
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 01:29:06 +08:00
Your Name
19cfb7caaa
fix: 系统全扫描修复 7 个 HIGH 级 Bug
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 01:22:00 +08:00
Your Name
ea3046f635
fix: unix_ls parse_ls_la_line 兼容 long-iso 8字段格式
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-02 01:09:39 +08:00
Your Name
39a8cf16cf
fix(ui): 调度与重试队列路由导航及前端资源一致性
...
侧栏可滚动与显式导航;懒加载失败提示;getList 兼容分页响应;生产 prune 清理 1065 个过期 chunk。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 22:36:08 +08:00
Your Name
b62d4f6f9f
fix(audit): 审计日志操作与目标类型全面中文化
...
补全 action/target 映射表与词段兜底;审计页筛选下拉使用中文标签。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 22:18:42 +08:00
Your Name
44c19f329a
fix(terminal): Ctrl+D 快捷键文案改为退出
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 22:13:54 +08:00
Your Name
9e924562d2
fix(terminal): 右下角快捷键与右键菜单中文化并放大
...
快捷键区改为中文大按钮;工具栏字号/回滚/全屏中文化;右键菜单加大并在命令栏拦截英文系统菜单。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 22:00:49 +08:00
Your Name
e3eb0e65a5
fix(ui): 仪表盘/审计/调度/重试修复与终端快捷命令改版
...
统一终端页与全局侧栏菜单;快捷命令仅在终端执行,增删改排序迁入系统设置;命令输入区加高与 Enter/Shift+Enter 行为;后端自定义命令优先与 reorder API。
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 21:56:07 +08:00
Your Name
fc056059f9
docs: production deploy changelog for files/POSIX release
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 20:45:14 +08:00
Your Name
bd6467dff9
docs: master plan execution progress and changelog
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 19:58:50 +08:00
Your Name
e704b01093
fix(deploy): restore pre_deploy_check.sh content
...
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
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 19:57:06 +08:00
Your Name
246070e599
fix(deploy): pre_deploy gate uses repo root and newest audit
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 19:56:36 +08:00
Your Name
d93c518a14
feat(files): POSIX paths, elevation, recursive chmod, access hints and docs
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 19:54:18 +08:00
Your Name
1cfac23c01
feat: terminal ANSI colors and enhanced shell syntax highlighting
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 15:49:27 +08:00
Your Name
799140f6c4
feat: terminal SPA layout, route sync, and WebSocket URL helper
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 15:41:59 +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
ab431028c1
fix: 服务器页批量选择绑定 Vuetify4 modelValue
...
v-model:selected 无法同步勾选状态;生产已部署 ServersPage-CGp8DUVa.js 并验证「已选择 2 台服务器」。
2026-06-01 14:54:39 +08:00
Your Name
cc2dad7f31
docs: 生产浏览器验收 — SPA/WebSSH/health_monitor
...
详见 docs/reports/2026-06-01-browser-verification.md;批量条与 Telegram/Push/kill 留维护窗口或人工确认。
2026-06-01 14:20:45 +08:00
Your Name
24b4439b2b
docs: 单负责人执行计划 — handoff 对齐、生产验收、prune 加固
...
计划见 docs/design/plans/2026-06-01-single-owner-execution.md;生产 health/app/Redis/MySQL 已通过。
2026-06-01 14:09:17 +08:00
Your Name
b8af1fc418
chore: 移除 superpowers 工作流 Skill,改为单 Agent 协作
...
停用 .cursor/skills 与虚拟部门分派,新增 no-department-agents 规则并更新文档索引与验收标准。
2026-06-01 14:04:50 +08:00
Your Name
b77a314b36
chore: remove virtual department agent docs (team/skills)
...
Delete docs/skills/, docs/team/, and TEAM_ROLES.md. Update docs/README and mem_key_files. Standards and .cursor/skills workflows unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 13:52:55 +08:00
Your Name
d519113734
fix: Gate3 health plain text, refresh empty body, prune underscore chunks
...
test_api: assert /health returns plain text ok instead of JSON parse.
auth: RefreshRequest.refresh_token optional so SPA POST {} is not 422.
prune: allow leading underscore in asset names to avoid deleting _plugin-vue_export-helper.
Add run_test_api_on_server.sh and deployment follow-up changelog.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 13:41:28 +08:00
Your Name
65c77155d8
fix: 修复前端 assets 清理脚本以支持 Rolldown 产物
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:31:55 +08:00
Your Name
2deb89b49c
deploy: 前端部署后自动清理孤儿 assets + 冒烟脚本
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:29:57 +08:00
Your Name
b76295aaec
docs: 记录 2026-06-01 生产部署验证结果
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-06-01 12:23:44 +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
73fdcafb81
docs: 完整交接文件 (15章节 + Cursor提示词 + 部署问题)
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:58:11 +08:00
Your Name
91d0d4104e
docs: 添加 .cursorrules 供 Cursor 接管
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:54:11 +08:00
Your Name
7fa4bd6dff
docs: Cursor交接文件 2026-06-01
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:49:12 +08:00
Your Name
a20cefcfbd
docs: 审计+changelog 全站bug审查修复
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:40:23 +08:00
Your Name
6183047fd6
fix: 全站 bug 审查修复 (前端9项 + 后端5项)
...
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
前端修复:
- P0: App.vue http 未导入导致全局搜索崩溃
- P1: TOTP 登录流程断裂 (TotpRequiredError 非 ApiError 子类)
- P1: ServersPage 编辑服务器 domain 被端口字符串污染
- P1: PushPage Set[0] 无效 → values().next().value
- P1: SettingsPage API 返回字符串未转数字
- P2: api/index.ts getList 重复定义移除
- P2: LoginPage 锁定倒计时 now ref + watch 更新
- P2: TerminalPage 路径验证正则放松 (允许空格/中文)
- P2: useWebSocket CONNECTING/CLOSING 状态关闭旧连接
后端修复:
- P1: websocket.py redis.keys() → scan_iter() 避免阻塞
- P1: auth_service.py TTL 仅在 key 无 TTL 时设置
- P1: servers.py 批量操作加 asyncio.Lock 避免并发 session commit
- P2: settings.py asyncio.get_event_loop() → get_running_loop()
- P2: settings.py datetime.utcfromtimestamp() → datetime.fromtimestamp(tz=utc)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-01 11:24:55 +08:00
Your Name
df2c188f5d
docs: Cursor 交接文件
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:32:10 +08:00
Your Name
2d00d6a8eb
fix: 登录页居中布局 + 删除Logo区域
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:30:12 +08:00
Your Name
080c1158d4
docs: 审计文档 + changelog (TerminalPage迭代)
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 23:24:53 +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
1ecd8e4542
fix: move wallpaper routes before /{key} catch-all to fix 404
...
Bing wallpaper endpoint (/bing-wallpapers) was returning 404 from HTTP
because FastAPI matched it against the /{key} catch-all route at position
2 before the specific route at position 13 ever got reached.
- Moved wallpaper routes (bing-wallpapers, bing-wallpaper) and helper code
before the /{key} wildcard route
- Removed dead guard code in get_setting() that was never effective —
FastAPI route matching happens before the handler body executes
- Removed duplicate wallpaper code block at end of file
Root cause: FastAPI matches routes in registration order. /{key} at
position 2 matched 'bing-wallpapers' as the key parameter, returning
'Setting not found' instead of routing to the wallpaper endpoint.
2026-05-31 22:00:33 +08:00
Your Name
c6485168b6
fix: bing-wallpapers route was being caught by /{key} catch-all
...
FastAPI matches routes in order: /{key} registered before bing-wallpapers
because routes are sorted by path. /{key} matches 'bing-wallpapers' as a
key name, returning 404 'Setting not found' instead of hitting the actual
bing_wallpapers handler.
Fixed by adding a guard in get_setting() to skip these fixed path names,
and crucially by ensuring bing-wallpaper(s) routes are registered BEFORE
the /{key} catch-all in the router.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:59:26 +08:00
Your Name
e9af02dd22
fix: add bing-wallpapers (plural) to PUBLIC_PREFIXES for JWT bypass
2026-05-31 20:53:49 +08:00
Your Name
c9baecfdfa
feat: Bing wallpaper slideshow — 12 images, hourly rotation, weekly cleanup
...
- Frontend: fullscreen wallpaper background with 1.5s crossfade transition,
login card centered with glass effect, images rotate every hour
- Backend: new /api/settings/bing-wallpapers endpoint fetches 8 recent images
from Bing HPImageArchive, caches to web/app/wallpapers/, returns all URLs
- Auto-cleanup: removes files older than 7 days, keeps max 12 newest
- Old /bing-wallpaper endpoint kept for backward compatibility
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:51:50 +08:00
Your Name
3d5870b404
fix: correct wallpaper dir to 3 levels up (server/api/settings.py -> Nexus/web/app/wallpapers)
...
Path breakdown: __file__ is server/api/settings.py
.parent → server/api/
.parent.parent → server/
.parent.parent.parent → Nexus/ (repo root)
Then append web/app/wallpapers
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:38:35 +08:00
Your Name
afd32118b2
fix: correct wallpaper directory path in settings.py
...
- Path(__file__) is server/api/settings.py, so:
.parent → api/ .parent → server/ .parent → Nexus/ (ROOT)
.parent → (above ROOT — wrong!)
- Changed from .parent.parent.parent to .parent.parent.parent.parent
to reach the project root, then into web/app/wallpapers/
- Moved _WALLPAPER_DIR.mkdir into the async function body
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:34:27 +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
04dda2c419
fix: download Bing wallpaper to server disk, auto-clean weekly
...
- Changed bing-wallpaper endpoint from URL proxy to image downloader
- Saves wallpaper to web/app/wallpapers/YYYY-MM-DD.jpg
- Auto-deletes wallpapers older than 7 days on each request
- Falls back to yesterday's cached file if download fails
- Added Path import for filesystem access
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:23:55 +08:00
Your Name
e084d90c61
fix: add Bing wallpaper proxy endpoint, make it public (no JWT required)
...
- Added GET /api/settings/bing-wallpaper — proxies cn.bing.com HPImageArchive
to avoid CORS issues, returns {url} for the daily wallpaper
- Added /api/settings/bing-wallpaper to PUBLIC_PREFIXES in auth_jwt.py
so the login page can fetch it without authentication
- Login page now fetches wallpaper via backend proxy instead of direct CORS-blocked fetch
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 20:12:09 +08:00
Your Name
24aa8494e5
security: bind uvicorn to 127.0.0.1 instead of 0.0.0.0
...
The install wizard wrote '--host 0.0.0.0' which exposed the raw uvicorn
port 8600 on the public IP, bypassing Nginx HTTPS/TLS/WAF/middleware.
Changed to 127.0.0.1 — only local Nginx can reach the backend.
Also applied to running server via supervisor config fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 17:04:28 +08:00
Your Name
5c7775c10c
chore: remove old Tailwind HTML pages from git
...
Vuetify SPA is now the sole frontend entry point at /app/.
Old pages (alerts/servers/scripts/...html) replaced by Vue router.
Keep install.html for setup wizard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:46:29 +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
3419ab8a09
chore: remove obsolete design department agent docs
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:37:57 +08:00
Your Name
d512460dc9
fix: frontend type definitions match actual backend API responses
...
- AlertsPage: template fields alert_type/value/is_recovery (was type/message/recovered)
- CommandsPage: remove non-existent is_dangerous/duration/admin_name; use admin_username
- ScriptsPage: ExecHistoryItem matches /scripts/executions response shape
- types/api.ts: CommandLogItem + SshSessionItem + ScriptExecItem aligned to backend
- Remove unused PaginatedResponse imports from CommandsPage/ScriptsPage
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-31 15:37:41 +08:00
Your Name
0f02e047cc
docs: update deployment instructions for Vuetify SPA
...
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
- Split backend/frontend deploy steps
- Add deploy-frontend.sh one-liner reference
- Document AppAuthMiddleware 404 and stale HTML troubleshooting
- Remove obsolete dist copy instructions
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 13:25:33 +08:00
Your Name
35583115ff
fix: Vite outputs directly to web/app/ — no dist copy needed
...
- vite.config.mts: outDir changed from web/app/dist to web/app
- .gitignore: ignore web/app/index.html + web/app/assets/ (build artifacts)
- deploy/deploy-frontend.sh: automated build+deploy+verify script
Deployment is now: bash deploy/deploy-frontend.sh
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 13:24:22 +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
0d056a45e9
feat: Vuetify 4 frontend — complete rebuild with audit fix
...
Vue 3 + Vuetify 4 + TypeScript + Vue Router 4 + Pinia frontend,
replacing the old Tailwind+Alpine.js static pages.
Infrastructure (8 new files):
- composables/useSnackbar.ts — centralized notifications
- composables/useServerList.ts — server dropdown data
- composables/useServerPagination.ts — paginated server table
- types/api.ts — 14 typed API response interfaces
- types/global.d.ts — Window augmentation
- utils/status.ts — server status display helpers
- utils/validation.ts — 8 form validation rules
- components/MonacoEditor.vue — fullscreen code editor
14 pages rebuilt:
- LoginPage, DashboardPage, ServersPage, TerminalPage
- FilesPage, PushPage, ScriptsPage, CredentialsPage
- SchedulesPage, RetriesPage, CommandsPage
- AlertsPage, AuditPage, SettingsPage
Critical fixes (from audit):
- Files upload JWT auth (was missing Authorization header)
- API Key reveal password verification dialog
- 6 silent catch blocks → snackbar error feedback
- 33 as any → 0 (typed interfaces + global.d.ts)
- Dashboard: alerts/summary/categories/audit data loading
- WebSocket reconnect timer cleanup + auth failure handling
- Terminal ResizeObserver leak fix
- PushPage timer cleanup on unmount
- FilesPage path double-slash fix (joinPath helper)
- Filter changes reset pagination to page 1
Features added:
- Servers: batch operations, CSV export/import, detail panel
- Push: sync modes, ZIP upload, WebSocket real-time progress, cancel
- Scripts: quick execute panel, execution status tracking
- Files: Monaco editor, context menu, batch delete, rename, chmod
- Terminal: right-click menu, server sidebar, tab persistence
- Settings: batch save, TOTP manual key, password TOTP verification
- Dashboard: category distribution, recent audit, WS refresh
Quality:
- vue-tsc --noEmit zero errors
- vite build passes (1613 modules)
- Formal 8-step security audit passed (0 FINDING)
- .gitignore: dist/ → **/dist/ to cover web/app/dist/
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 12:56:12 +08:00
Your Name
0ded4a28ec
fix: 主题系统改用CSS变量 — dark:前缀在浏览器CDN不生效
...
根因: Tailwind v4 浏览器CDN(tailwindcss-browser.js)不处理外部CSS的
@custom-variant指令, dark:前缀规则完全不生成
方案: 改用CSS变量 + :root.dark {} 选择器
- theme.css: :root 定义亮色值, :root.dark 定义暗色值
- 15个HTML页面: 恢复 bg-[var(--bg-page)] 等CSS变量class
- 移除所有 dark: 前缀class(CSS变量自动适配)
- theme-init.js: 同步读localStorage设.dark class(FOUC防护)
- layout.js: toggleTheme 切换 .dark class + localStorage + MySQL
优势: CSS变量方案不依赖Tailwind dark:变体, 100%兼容浏览器CDN
2026-05-31 04:18:55 +08:00
Your Name
5ac4a5c7cf
fix: theme.css 加 @import tailwindcss 使 dark: 变体生效
...
Tailwind v4 官方文档确认:
@import 'tailwindcss';
@custom-variant dark (&:where(.dark, .dark *));
浏览器CDN build需要 @import 来处理 @custom-variant 指令
2026-05-31 04:13:26 +08:00
Your Name
9c5ebdfdbd
feat: 全站主题完全重做 — CSS变量→Tailwind dark: 前缀
...
设计依据: HyperUI/Flowbite/daisyUI/Meraki UI 深度调研
配色方案: HyperUI 全局色值映射 (gray-* 色系)
改动:
- theme.css: 重写为 @custom-variant dark 配置
- theme-init.js: FOUC防护 — 同步读localStorage设.dark class
- layout.js: 主题系统改用 .dark class + localStorage
- 15个HTML页面: 649处CSS变量class替换为dark:前缀
bg-[var(--bg-page)] → bg-gray-50 dark:bg-gray-950
bg-[var(--bg-card)] → bg-white dark:bg-gray-900
bg-[var(--bg-surface)] → bg-gray-100 dark:bg-gray-800
border-[var(--border)] → border-gray-200 dark:border-gray-700
text-[var(--text-primary)] → text-gray-900 dark:text-white
等9种映射
- design spec: docs/design/specs/2026-05-31-ui-redesign-design.md
修复: FOUC(切换主题时闪暗色)已解决
2026-05-31 04:11:17 +08:00
Your Name
c457cb4058
feat: dark mode theme system with synchronous FOUC prevention
...
- Add vendor/theme-init.js for synchronous dark mode init in <head>
- Update all 13 frontend pages with dark: variant classes
- Dark mode as default, light mode via localStorage toggle
- Remove redundant theme.css rules in favor of Tailwind dark: classes
- Add settings-dark-theme.png reference screenshot
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 03:54:30 +08:00
Your Name
8b2263916c
feat: design department agents integrate Tailwind ecosystem knowledge (9 sites)
...
Deep-learned 9 Tailwind CSS ecosystem sites and injected into all design
department agents via knowledge graph references:
- HyperUI (350+ components, Tailwind v4, Alpine.js) ⭐ best match
- Meraki UI (198 components, Application UI, RTL)
- Flowbite (56+ components, data-attr driven, Figma)
- daisyUI (65 semantic components, 35 themes)
- UIBak (200+ components, Alpine.js native)
- Headless UI (a11y benchmark, data-* patterns)
- Tailblocks (63 landing page blocks)
- Kutty (plugin architecture reference, unmaintained)
- WindyToolbox (resource directory)
Updated 10 files: design-department, ui-designer, ux-architect,
frontend-designer, color-curator, inspiration-analyzer, trend-researcher,
moodboard-creator, design-wizard, team roles.
Knowledge graph IDs for cross-session reference:
tailwind-css-9 (overview)
tailwind-css-9/hyperui-nexus-tailwind
tailwind-css-9/meraki-ui-rtl-tailwind
tailwind-css-9/flowbite-tailwind-bootstrap
tailwind-css-9/daisyui-tailwind
tailwind-css-9/uibak-alpinejs
tailwind-css-9/headless-ui-tailwind-labs
tailwind-css-9/tailblocks-landing-page
tailwind-css-9/kutty-tailwind-plugin-alpinejs
tailwind-css-9/windytoolbox-tailwind
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-31 03:53:40 +08:00
Your Name
293a0d64fe
feat: 全站亮色/暗色主题切换
...
实现方案: CSS自定义属性 + Tailwind arbitrary values
新增文件:
- web/app/vendor/theme.css — CSS变量定义(亮色+暗色)
修改文件 (15个HTML + 2个JS + 2个Python):
- layout.js — 侧边栏🌙 主题切换按钮 + loadTheme/toggleTheme
- settings.py — MUTABLE_KEYS加theme/editor_theme
- 15个HTML页面 — bg-slate-*替换为bg-[var(--bg-*)] + 引入theme.css
替换统计:
- index.html: 48处
- servers.html: 183处
- files.html: 94处
- push.html: 157处
- scripts.html: 83处
- credentials.html: 100处
- schedules.html: 59处
- retries.html: 40处
- commands.html: 57处
- alerts.html: 47处
- audit.html: 32处
- settings.html: 125处
- terminal.html: 89处
- install.html: 72处
- login.html: 14处
总计: 1199处替换
功能:
- 侧边栏底部🌙 /☀️ 按钮切换亮色/暗色
- 主题偏好保存到MySQL(settings表)
- 页面加载时自动恢复主题
- Monaco编辑器主题独立控制(⚙️ 菜单)
2026-05-31 02:55:45 +08:00
Your Name
94fbdf7b2d
refactor: 主题切换移到 ⚙️ 设置下拉菜单
...
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
- 移除标题栏独立主题按钮(🌙 /☀️ )
- 新增⚙️ 设置按钮 → 下拉菜单
- 菜单项: 「☀️ 亮色主题」/「🌙 暗色主题」动态文字
- 点击菜单外自动关闭
- 菜单样式: bg-slate-800, rounded, shadow, 最小宽度200px
2026-05-31 02:42:24 +08:00
Your Name
e65c9993a2
feat: 编辑器亮色/暗色主题切换 + 保存到MySQL
...
- 标题栏🌙 /☀️ 按钮切换 Monaco 主题
- 'vs'(亮色) / 'vs-dark'(暗色)
- 切换后立即应用到所有打开的标签页
- 通过 PUT /api/settings/editor_theme 保存到MySQL
- 页面加载时自动读取保存的主题偏好
- settings.py MUTABLE_KEYS 白名单加 editor_theme
2026-05-31 02:39:21 +08:00
Your Name
ae47eb42de
fix: 双击标题栏最大化 + Monaco用官方默认主题
...
1. 双击编辑器标题栏空白区域 → 切换最大化/还原
2. Monaco移除theme:'vs-dark'和fontFamily覆盖, 使用官方默认配置
3. 编辑器外观与 https://microsoft.github.io/monaco-editor 一致
2026-05-31 02:35:52 +08:00
Your Name
c570801119
fix: 编辑器拖拽修复 — 扩大拖拽区域+退出最大化+边界限制
...
问题:
- 标签栏整体被排除导致可拖拽区域几乎为零
- 最大化/全屏后拖拽不工作
- 没有拖拽视觉提示
修复:
- 添加⠿拖拽把手图标(cursor-grab)
- 只排除button/input/select, 标签栏空白处可拖拽
- 拖拽时自动退出最大化/全屏模式
- 边界限制(不拖出屏幕)
- 拖拽结束触发Monaco重新layout
2026-05-31 02:31:56 +08:00
Your Name
cba8b3d8f6
feat: 浮动编辑器 — 拖拽+缩放+全屏+文件树
...
功能:
- 拖拽: 按住标题栏拖动编辑器面板
- 缩放: 右下角拖拽调整大小
- 最大化(⬜ ): 占满屏幕留边距
- 全屏(⤢): 完全覆盖页面
- 最小化(—): 收到底部标签栏
- 关闭(✕): 关闭全部标签
- 文件树(🌳 ): 左侧可折叠文件树, 点击文件打开/目录导航
- 文件树同步: 浏览新目录时自动更新
布局:
┌──────────────────────────────────┐
│ [🌳 ] [📄 a.conf×][📄 b.py×] [⬜ ][⤢][—][✕] │ ← 可拖拽
├────────┬─────────────────────────┤
│ 📂 .. │ │
│ 📁 dir │ Monaco Editor │
│ 📄 a │ │
│ 📄 b │ │
│ │ Ln1,Col1|ini|UTF-8|file │
└────────┴─────────────────────────┘ ← 右下角可缩放
2026-05-31 02:26:25 +08:00
Your Name
caef4a216b
fix: Monaco配置完全对齐官方默认值
...
对齐项目:
- cursorBlinking: smooth→blink(官方默认)
- 移除: cursorSmoothCaretAnimation, cursorWidth(非官方默认)
- 移除: lineHeight, padding(非官方默认)
- 移除: renderLineHighlight, smoothScrolling(非官方默认)
- 移除: scrollbar自定义尺寸(使用官方默认)
- scrollBeyondLastLine: false→true(官方默认)
- renderWhitespace: selection→none(官方默认)
- 添加: fontFamily(Cascadia Code/Fira Code/JetBrains Mono)
- 移除: quickSuggestions, insertSpaces, foldingHighlight, minimap side/scale
- 保留vs-dark主题(匹配Nexus暗色UI)
2026-05-31 02:20:04 +08:00
Your Name
507b957b4e
refactor: 编辑器改为浮动面板 + Monaco配置对齐官方
...
布局:
- 全屏覆盖 → 右下角浮动面板(70vw×65vh)
- 文件列表始终可见, 编辑器不遮挡
- 最大化/还原按钮(⬜ )
- 最小化到底部标签栏
- 移除文件树(文件列表已在背景可见)
Monaco配置对齐官方demo:
- fontSize 13→14, lineHeight 20
- wordWrap on→off(水平滚动)
- 新增: folding, matchBrackets, cursorBlinking smooth
- 新增: cursorSmoothCaretAnimation, smoothScrolling
- 新增: padding, renderLineHighlight all, renderWhitespace selection
- 新增: suggestOnTriggerCharacters, quickSuggestions
- 新增: links, colorDecorators
- 新增: tabSize 4
2026-05-31 02:14:56 +08:00
Your Name
c70424a224
docs: Monaco IDE编辑器 changelog + 审计报告
2026-05-31 02:08:31 +08:00
Your Name
e8c1acba9f
fix: 审计8个FINDING修复 (IDE编辑器+终端)
...
- H-01 [MEDIUM] esc() 加引号转义('"\') 防止onclick XSS
- H-02 [MEDIUM] initialPath 路径白名单校验(仅允许字母数字/.-_)
- H-03 [LOW] doNewFile 文件名白名单正则(替代简单的includes('/'))
- H-08 [LOW] Monaco CDN SRI — 已知限制, 版本锁定@0.45.0
- H-13 [MEDIUM] showModal 移除已删除的modalTextarea引用
- H-20 [LOW] initialPath仅首次连接cd, 不影响恢复的标签
- H-26 [MEDIUM] esc()跨文件一致性 — files.html对齐terminal.html
- H-30 [LOW] esc()注释更新
2026-05-31 02:06:42 +08:00
Your Name
34786737b4
fix: IDE编辑器语法错误 — 多余花括号
2026-05-31 01:56:15 +08:00
Your Name
be633f3e58
feat: IDE编辑器重构 — 多标签+文件树+最小化+状态栏
...
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
- 全屏IDE面板替代模态框编辑器
- 多文件标签页: 独立Monaco实例, 切换保持状态
- 左侧文件树: 基于当前目录, 点击文件打开, 点击目录导航
- 最小化/恢复: 底部最小化栏显示所有打开的文件标签
- 状态栏: 光标位置+语言+编码+未保存指示器
- Ctrl+S保存 + 未保存关闭确认
- 标签栏: 点击切换, ×关闭, amber色未保存标记
- 文件树同步: 浏览新目录时自动更新文件树
- 模态框保留用于非编辑操作(重命名/删除/新建等)
2026-05-31 01:50:34 +08:00
Your Name
00a3309005
feat: 服务器列表加「文件」按钮直达文件管理
...
- servers.html: renderActions 加「文件」链接(琥珀色) → /app/files.html?server_id=X
- files.html: 支持 server_id URL参数, 自动选中服务器并浏览 /www/wwwroot
2026-05-31 01:33:52 +08:00
Your Name
3d15200cfa
chore: 移除Monaco debug日志
2026-05-31 01:28:57 +08:00
Your Name
d8aca5bf18
fix: Monaco预加载移入files.html(解决api.js缓存问题)
2026-05-31 01:26:59 +08:00
Your Name
cb60af4483
debug: Monaco preload 加日志诊断
2026-05-31 01:22:45 +08:00
Your Name
5a5adafb39
feat: Monaco编辑器+右键菜单+排序筛选+chmod+压缩解压+新建文件
...
编辑器增强:
- E-2 Monaco集成: 70vh全屏编辑器, 暗色主题, bracket着色
- E-3 Ctrl+S保存快捷键 + 未保存指示器
- E-4 语言自动检测(30+扩展名映射)
- Monaco预加载: 登录后CDN后台加载, 打开编辑器秒开
- fallback: Monaco未就绪时退回textarea
文件管理增强:
- F-1 右键菜单: 预览/下载/重命名/权限/复制路径/终端/压缩/解压/删除
- F-2 新建文件按钮(📄 +)
- F-3 chmod权限修改(右键→输入权限如755)
- F-4 排序切换(名称/大小/时间)
- F-5 文件类型筛选下拉(.conf/.log/.sh/.py等)
- F-6 压缩(tar.gz)
- F-7 解压(tar.gz/zip)
2026-05-31 01:10:22 +08:00
Your Name
c0296b9d8e
fix: 预加载文件大小 30KB → 1MB
2026-05-31 01:04:44 +08:00
Your Name
ca4aceba3e
fix: 面包屑点击事件委托 — 作用域不在fileListEl内
...
面包屑(#breadcrumbPath)和文件列表(#fileList)是兄弟节点, 不是父子关系
事件委托绑在fileListEl上无法捕获面包屑点击
修复: 给#breadcrumbPath加独立click事件委托
2026-05-31 00:57:58 +08:00
Your Name
b5dfa8a870
feat: 文件管理器集成SSH终端
...
- files.html: 工具栏加「🖥 终端」按钮(绿色),点击在新标签页打开SSH终端
- files.html: openTerminal() 传递 server_id + 当前路径到 terminal.html
- terminal.html: 支持 path URL参数,连接成功后自动 cd 到指定目录
- 打开方式: /app/terminal.html?server_id=8&path=/www/wwwroot
- 右键菜单也会集成「打开终端」选项
2026-05-31 00:53:00 +08:00
Your Name
17cdc96bb0
feat: 文件预加载+缓存 — 双击秒开编辑器
...
- api.js: Monaco编辑器CDN预加载(登录后后台加载)
- files.html: 文件内容预加载(目录浏览后自动预读≤30KB文本文件)
- files.html: 文件缓存(_fileCache), 双击已缓存文件直接打开
- files.html: 切换服务器时清空缓存
- 预加载策略: 最多10个文件, 仅文本类型, ≤30KB
2026-05-31 00:46:04 +08:00
Your Name
6012af0b4d
fix: 双击编辑器冲突 — 延迟区分单击/双击
2026-05-31 00:25:02 +08:00
Your Name
9bdf7e420f
feat: 文件管理器4项改进
...
1. 切换服务器自动重置路径为 /www/wwwroot
2. 默认目录 /www/wwwroot(而非根目录 /)
3. 双击文件打开编辑器(doPreview textarea模态框)
4. 双击目录进入目录(browseDir)
2026-05-31 00:17:22 +08:00
Your Name
40d672fdbb
fix: 面包屑双斜杠bug (/tmp显示为//tmp)
2026-05-31 00:11:47 +08:00
Your Name
557c8d28c1
docs: files迭代审计报告
2026-05-30 23:46:12 +08:00
Your Name
9f7be66356
fix: 审计5个FINDING修复 (files迭代)
...
- H-15 [MEDIUM] download端点加100MB大小限制
- H-02 [LOW] Content-Disposition filename sanitize(替换特殊字符)
- H-12 [LOW] FileDownload/FileRead/FileWrite path加max_length=4096
- H-27 [LOW] doPreview保存失败解析错误详情显示detail
- H-29 [INFO] esc()函数加注释说明用途
- H-01 [HIGH] 远程路径限制 — ACCEPTED_RISK(用户明确决策)
2026-05-30 23:44:35 +08:00
Your Name
ac38442383
docs: files.html 全面迭代 changelog
2026-05-30 23:36:49 +08:00
Your Name
14131f98f0
feat: files.html 全面迭代 — 15项改进
...
安全+后端:
- P2-1 符号链接解析(l权限检测+name/target分离)
- P2-7 新增 /api/sync/download 端点(SFTP流式下载)
- P2-8 新增 /api/sync/read-file + /write-file 端点(base64编码避免shell注入)
前端全面重写:
- P1-1 目录删除二次确认(自定义模态框+输入目录名)
- P2-2/2-3 事件委托替代内联onclick(data-action+data-path)
- P2-4 上传进度条(XHR.upload.onprogress)
- P2-5 文件大小可读化(B/KB/MB/GB)
- P2-6 文件类型图标(30+扩展名映射)
- P2-7 下载按钮+逻辑
- P2-8 文件预览/编辑弹窗(读取+修改+保存)
- P2-9 自定义模态框替代prompt/confirm
- P2-10 批量选择+批量删除(checkbox+全选+底部操作栏)
- P3-1 文件名搜索框(前端实时过滤)
- P3-2 符号链接🔗 图标+target tooltip
- P3-3 空目录状态(图标+上传引导按钮)
- P3-4 服务器刷新按钮
- P3-5 操作loading状态(进度条) 2>&1
2026-05-30 23:34:24 +08:00
Your Name
64503c0260
fix: IP校验改用endpoint级HTTPException替代Pydantic validator
...
model_validator/field_validator在自定义RequestValidationError handler下
无法正确序列化为JSON,导致500。改用endpoint级_validate_ip_list()辅助函数
抛HTTPException(400),避免Pydantic→FastAPI序列化链路问题。
2026-05-30 22:48:41 +08:00
Your Name
d19f5af807
fix: IP格式校验用field_validator替代model_validator
...
model_validator(mode='after')抛出ValueError时FastAPI不能正确序列化为422
→ 导致500 TypeError: Object of type ValueError is not JSON serializable
改用field_validator(mode='before')由Pydantic正常捕获返回422
2026-05-30 22:44:26 +08:00
Your Name
463841a740
docs: settings安全加固审计报告
2026-05-30 22:35:40 +08:00
Your Name
36fde6e6ed
fix: 审计7个FINDING修复
...
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
- F-1 [MEDIUM] IpAllowlistSaveRequest 加 IP/CIDR/域名格式校验
- F-2 [MEDIUM] _is_private_host 改为 async DNS 解析 (不再阻塞事件循环)
- F-3 [LOW] hot-reload int转换失败改 logger.warning 而非静默pass
- F-4 [LOW] 提取 _verify_reauth 辅助函数,消除4处重复re-auth代码
- F-5 [LOW] ChangePasswordRequest.totp_code 加 min_length=6 约束
- F-6 [LOW] revealTelegramToken 空catch改 console.error+toast
- F-7 [LOW] toggleApiKeyVisibility 空catch改 console.error+toast
2026-05-30 22:34:45 +08:00
Your Name
1a61fae590
docs: settings 安全加固+UX迭代 changelog
2026-05-30 22:02:45 +08:00
Your Name
a50f17941d
fix: settings 安全加固 + UX 迭代 — 10项修复
...
安全修复:
- S-01 SSRF: parse-subscription 加私有IP封禁+重定向限制+响应大小限制
- S-02 值校验: PUT /{key} 加 key 白名单 + INT 范围校验(1-1000/1-100/10-600)
- S-05 重登录: 改密码成功后跳转login.html+绿色提示
- S-07 审计: add_manual_ips/remove_allowlist_ip 补全审计日志
- S-09 TOTP: 已启用TOTP时改密码需输入验证码
UX改进:
- UX-01: 密码框focus ring + 设置项input type映射(number/url/text)
- UX-02: 改密码按钮loading状态(disabled+提交中...)
- UX-03: 3处空catch块→console.error+toast
- UX-04: 保存失败时reloadSettings恢复原值
- UX-05: IP格式校验(前端正则+后端Pydantic model_validator)
2026-05-30 21:58:13 +08:00
Your Name
362b28199f
docs: settings 巡检 + Bot Token 脱敏 changelog
2026-05-30 21:18:34 +08:00
Your Name
5213def150
fix: Telegram Bot Token 脱敏 — GET 不返回明文,reveal 需密码验证
...
- 后端 SENSITIVE_KEYS 加入 telegram_bot_token,GET /settings/ 返回脱敏值
- 新增 POST /settings/telegram/reveal-token 端点(密码验证 + 审计日志)
- 前端 Telegram 区域独立渲染:Bot Token 默认脱敏,点"显示"需输入密码
- Chat ID 保持可编辑(非敏感信息)
- Bot Token 输入框默认 type=password,可切换明文/遮掩
2026-05-30 21:12:41 +08:00
Your Name
5166660f3a
fix: GET /api/settings/ip-allowlist 被 /{key} 路由拦截 → 404
...
/{key} 路由在 ip-allowlist 之前定义,FastAPI 将 ip-allowlist
当作 setting key 查找,找不到返回 404。
修复:将 GET /ip-allowlist 路由移到 /{key} 之前(FastAPI 路由优先级)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 20:42:42 +08:00
Your Name
48ef06babb
chore: gitignore 添加 MCP 工具目录 + 清理测试截图
...
- .megamemory/ (知识图谱)
- .playwright-mcp/ (浏览器状态/截图)
- tmp/ (临时文件)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 20:39:47 +08:00
Your Name
ede7fbaa64
fix: settings PUT 后热更新内存 — 无需重启即生效
...
问题:修改 Telegram 等设置后需要重启服务器才能生效,
因为 load_settings_from_db() 只在启动时运行。
修复:PUT /api/settings/{key} 写入 DB 后,
同步更新 settings 内存对象(DB_OVERRIDE_MAP 映射 + INT_SETTINGS 类型转换)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 20:28:51 +08:00
Your Name
4c4d41b8f5
docs: add changelog and audit for ruff cleanup
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 20:10:28 +08:00
Your Name
32feb1b6db
fix: 全站 ruff 清零 — 77 errors → 0
...
Fixes:
- F821: install.py site_url 未定义(NameError)、sync_v2.py os 未导入、script_jobs.py LOG f-string
- F401: 移除 22 个未使用导入(models/__init__.py、install.py、auth.py 等)
- B904: 20 个 except 块 raise 添加 from e/from None
- S110: 20 个有意的 try-except-pass 添加 noqa 注释(SSH清理/DDL幂等/WS断连)
- B007: 3 个未使用循环变量重命名(dirs→_dirs、server_id→_server_id)
- F541: 3 个无占位符 f-string 修正
- F841: auth.py 未使用 ip_address 变量移除
- S105: auth_service.py Redis key prefix 误报 noqa
- B023: script_execution_flush.py 循环变量绑定修复
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 20:07:45 +08:00
Your Name
ebe276ea29
docs: add changelog and audit for servers iteration
...
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 19:50:07 +08:00
Your Name
84282e87ae
feat: servers list iteration — server-side pagination/search/sort/status filter
...
Backend:
- server_repo.py: get_paginated() adds search/sort_by/sort_order/is_online params
with whitelist-validated sorting and DB-level pagination
- servers.py: list_servers() adds search/sort_by/sort_order/is_online Query params
with Redis post-filter for is_online accuracy
- servers.py: fix all 12 pre-existing ruff errors (unused imports, B904, S110, F541)
- servers.py: fix F821 bug — agent_port undefined in upgrade_agent()
Frontend:
- servers.html: complete rewrite with server-side pagination, debounced search,
clickable column sorting, status filter dropdown, auto-refresh toggle,
keyboard shortcuts (↑↓/jk/Esc//r), CSV export, skeleton loading,
empty state with contextual hints, pagination controls (first/prev/nums/next/last)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-05-30 19:45:53 +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
3f50a40d25
feat: Agent 安装/卸载/升级脚本全面迭代
...
install.sh:
- 新增 Step 0:停旧服务 + 杀端口占用(fuser/ss/netstat 兜底)
- 修正步骤编号 [1/5] → [0/7]
- pip 依赖版本提取为脚本顶部变量,方便统一维护
uninstall.sh:
- 加 pkill 杀残留 Agent 进程
- 加 fuser 杀端口占用
- 清理 /etc/sudoers.d/nexus-agent 残留
- root 用户跳过 sudo 前缀
_sudo_wrap:
- NOPASSWD 命令白名单替代 ALL=(ALL)(仅 systemctl/apt/yum/rm 等)
- 降低 SSH 超时后 sudoers 残留的风险
升级 API:
- restart 前加 fuser -k 杀端口占用(单台+批量)
- install_agent_remote 检查 stdout 中的 FAILED 标记
卸载后清理:
- 清空 agent_api_key(之前只清 agent_version)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 16:11:09 +08:00
Your Name
dc48f71b25
feat: 创建 Agent 卸载脚本 uninstall.sh
...
之前卸载功能调用了不存在的 uninstall.sh,导致 404 下载失败。
脚本功能:停止 systemd 服务 → 禁用并删除 unit → 删除 /opt/nexus-agent → 删除日志
支持非 root 用户(自动检测 sudo 权限)。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 14:35:33 +08:00
Your Name
913fd16bb9
fix: Agent 升级命令添加 sudo 前缀(非 root 用户)
...
systemctl restart 需要 root 权限,非 root SSH 用户必须加 sudo。
之前 _sudo_wrap 只设置了免密 sudoers 但命令本身没带 sudo,
导致升级时 "Interactive authentication required" 失败。
同时修复单台升级和批量升级的 rollback 命令。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 14:28:49 +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
64a8a18287
fix: refresh cookie path 改为 /,修复 AppAuthMiddleware 读不到 cookie
...
REFRESH_COOKIE_PATH 从 /api/auth 改为 /,这样浏览器访问 /app/ 页面时
也会发送 nexus_refresh cookie,AppAuthMiddleware 才能正确验证登录状态。
同时包含之前的 AppAuthMiddleware 定义顺序修复和 422 调试日志。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 05:08:21 +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
993a234152
docs: 审计 + changelog — health纯文本/sha256/AppAuth
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-30 02:37:15 +08:00
Your Name
e709c72f1f
docs: CLAUDE.md 新增部署流程 + Health 纯文本修复
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-30 02:30:49 +08:00
Your Name
f7c4b95dd6
fix: /health 返回纯文本 "ok" 替代 JSON,隐藏 FastAPI 后端指纹
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-30 02:30:01 +08:00
Your Name
75864fe04f
fix: md5 → sha256 替换文件校验哈希算法,消除 bandit CWE-327
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-30 02:27:18 +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
0b82a3fee7
feat: 推送取消 — 引擎 cancel flag 检查 + WS cancelled 计数器
...
sync_engine_v2: 每台服务器推送前检查 Redis sync:cancel:{batch_id},
若已取消则跳过并标记 cancelled 状态,WS 广播 cancelled 计数。
websocket: broadcast_sync_progress 新增 cancelled 参数。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-30 00:57:38 +08:00
Your Name
d785c78d6d
fix: 审计修复 — esc() 加单引号转义 + 移除死代码 editQuickCmd
...
B2: esc() 不转义 ' 可能在 onclick 中注入
B4: editQuickCmd 定义但无调用(✏按钮已移除)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-30 00:26:14 +08:00
Your Name
56906e8fe2
fix: 快速命令栏移至命令栏上方 — chip 样式替代右侧面板列表
...
自定义命令在前(brand高亮),内置命令在后(灰色)。hover 显示 × 可删除。
+ 号弹窗添加新命令。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-30 00:22:31 +08:00
Your Name
da234c4e73
fix: 终端命令栏被覆盖 — termContainer隔离终端实例
...
termminal div 用 absolute inset:0 覆盖了底部 cmdBar。
修复: termContainer(flex-1 relative) 容器隔离,cmdBar 作为 flex sibling 在下方。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-30 00:19:16 +08:00
Your Name
7193b88156
feat: 终端页面 11 项全覆盖迭代 — 多标签/快速命令/字体/历史/重连/右键等
...
11 项改进:
- 多标签会话 (切换/关闭/新建,每标签独立 xterm+WS)
- 快速命令栏 (内置5条 + 自定义,localStorage持久化)
- 字体大小调节 (A−/A+按钮 + Ctrl+/-)
- Ctrl+L 清屏
- 命令历史持久化 (200条 FIFO localStorage)
- 右键菜单 (复制/粘贴/清屏/全选)
- 断开自动重连 (指数退避 + 倒计时)
- 连接信息栏 (时长 + PING RTT)
- 终端路径显示 (OSC title + onTitleChange)
- 滚动缓冲区调节 (1K/5K/10K/50K)
- 快速搜索服务器
后端: PING/PONG + PROMPT_COMMAND 注入
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-30 00:17:22 +08:00
Your Name
ac66f5b4e7
fix: 卸载Agent后清除Redis心跳(之前只清MySQL导致在线状态残留)
...
卸载Agent后只更新MySQL is_online=False,但前端读Redis覆盖为True。
修复: uninstall_agent_remote + batch_uninstall_agent 都增加redis.delete(heartbeat:{id})
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 23:57:06 +08:00
Your Name
6dd0b487b7
fix: install.sh 和 upgrade_agent 增加 rsync 自动安装
...
推送功能依赖目标服务器安装 rsync,但 install.sh 仅安装 Python 包。
现在 install.sh 步骤2/6检测并自动安装 rsync(apt/yum/dnf)。
upgrade_agent / batch_upgrade_agent 流程中也增加 rsync 检测,
已有服务器点击"升级 Agent"即可自动补装 rsync。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 23:45:01 +08:00
Your Name
fe211619aa
fix: 审计修复 — esc() 增加双引号转义, 移除死代码 replace(/'/g,"\'")
...
B1: esc() 不转义 " 导致文件名含双引号时破坏 HTML onclick 属性
B2: esc().replace(/'/g,"\'") — esc已转义单引号为',后续replace为死代码
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 23:07:01 +08:00
Your Name
0cbda8c840
fix: 审计修复 — diagnose/file-diff 端点静默吞错改为 logger.debug/warning
...
B1: diagnose 磁盘和路径检查 except:pass 改为 logger.debug()
B2: file-diff SSH失败无日志改为 logger.warning()
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 22:11:06 +08:00
Your Name
5958c21048
feat: 推送页面 Round 4 — 服务器搜索 / Diff对比 / 排错诊断 / 源路径输入 / 批量重试
...
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
5 项新功能:
- H2: 服务器搜索过滤 — 目标服务器下拉加搜索框实时过滤
- H3: 推送对比 Diff 视图 — 预览文件列表加 diff 按钮对比本地与远程差异
- H4: 推送排错面板 — 失败行加诊断按钮检查SSH/磁盘/权限
- H5: 源路径直接输入 — 支持直接输入服务器本地路径推送
- H6: 批量重试 — 一键重试所有失败服务器
新增后端端点:
- POST /api/sync/validate-source-path (H5)
- POST /api/sync/diagnose (H4)
- POST /api/sync/file-diff (H3)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 21:29:41 +08:00
Your Name
02423cb803
docs: 推送页面 Round 2 迭代设计文档与 changelog
...
- 设计文档: 5 项迭代功能(同步说明、在线标识、失败重试、Telegram通知、文件预览)
- 技术方案: 详细实现步骤与文件清单
- Changelog: 功能变更记录
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 18:54:12 +08:00
Your Name
152852e2c3
fix: 会话时效30天 + 多设备同时登录
...
- access token 从 30 分钟延长到 30 天
- refresh token 从 7 天延长到 30 天
- refresh token 从 MySQL 单字段改为 Redis Set 存储,支持多设备同时登录
- 单设备退出不再踢掉其他设备(只删自己的 Redis hash)
- 改密码/禁用 TOTP 仍会让所有设备掉线(token_version 递增)
- 移除 reuse 误杀逻辑:版本不匹配只拒绝当前 token,不惩罚其他设备
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 18:52:14 +08:00
Your Name
3c7036babf
fix: 补回 servers.html 丢失的检测路径+卸载Agent功能
...
从 worktree 分支同步完整的 servers.html,补回:
- 批量操作栏"检测路径"按钮(搜索 workerman.bat 自动设置 target_path)
- 批量操作栏"卸载 Agent"按钮
- batchDetectPath() 和 batchUninstallAgent() 函数
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 16:56:23 +08:00
Your Name
74de9d303e
feat: 推送页面 Round 2 迭代 — 同步说明 + 在线标识 + 失败重试 + Telegram通知 + 文件预览
...
F5: 同步模式详细说明 — 每种模式下方显示说明文字,切换时动态更新
F2: 服务器在线状态标识 — 服务器列表显示🟢 /🔴 在线/离线标识
F1: 失败自动重试 — 推送失败自动创建重试任务 + 失败行"🔄 重试"按钮
F3: 推送完成 Telegram 通知 — 全成功🟢 /部分失败🟡 /全失败🔴 三种消息含详情
F4: 文件内容预览 — 文件管理器点击文件名弹出内容预览模态框
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 15:59:30 +08:00
Your Name
ad2e7667d3
Merge branch 'claude/condescending-ishizaka-3cff3a'
2026-05-28 21:02:09 +08:00
Your Name
82c297776a
feat: 推送页面 5 项迭代 — WS实时进度 + 分组选择 + 历史增强 + 文件操作 + 推送校验
...
F1: broadcast_sync_progress() + batch_id + 前端WS逐台更新
F2: get_paginated() platform_id/node_id + /categories端点 + 筛选下拉框
F4: _sync_log_to_dict() 补全字段 + diff_summary捕获 + 可展开详情面板
F7: /local-file-ops端点 + 文件管理器删除/重命名
F8: /verify端点 md5sum对比 + 推送后校验UI
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-28 21:01:27 +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
97be1fd214
完善审计日志中文化:auth_service/script_service/sync_engine 全部 detail 改中文 + 前端新增 webssh_token/refresh_token_mismatch 等映射 + MCP deploy 修复
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 02:57:51 +08:00
Your Name
366bdc18fa
fix: deploy tool git pull before gate check + use origin/main
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 02:27:32 +08:00
Your Name
280357d7d7
Merge remote-tracking branch 'origin/claude/condescending-ishizaka-3cff3a'
2026-05-27 02:19:40 +08:00
Your Name
fd9b7d85b5
fix: 批量安装按钮检测 + 审计日志中文化 + terminal断开反馈
...
1. updateBatchBar() hasAgent 判断从 agent_api_key_set 改为 agent_version
2. 所有后端 AuditLog detail 字段统一中文
3. audit.html 操作/目标类型中文映射
4. terminal.html 断开覆盖层 + 重新连接按钮
5. Agent os_release 上报 + 前端系统版本拆分
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 02:17:35 +08:00
Your Name
8b82d6bab0
Add changelog for fmtTime/venv/batchinstall fixes
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 00:59:48 +08:00
Your Name
869f64ac18
Fix install.sh venv robustness + batch install API error reporting
...
install.sh: detect incomplete venv (missing activate), auto-install
python3-venv and retry instead of silently failing.
servers.py batch install: preserve server_name on exception, detect
"Status: FAILED" in stdout, return error details when stderr is empty,
increase SSH timeout to 180s.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 00:53:00 +08:00
Your Name
69056491a7
Fix fmtTime Invalid Date for timezone-aware timestamps (+00:00)
...
fmtTime() was appending 'Z' to all timestamps, causing Invalid Date
when the timestamp already had a timezone suffix like +00:00.
Now tries new Date(t) first, falls back to new Date(t+'Z').
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 00:34:51 +08:00
Your Name
02f1fa4ef3
Add .gitattributes + changelog for Agent install fix and deploy
...
- .gitattributes: enforce LF line endings for .sh/.py to prevent CRLF issues on Linux
- Changelog: document Agent install 404 fix, curl|bash pipe fix, CRLF fix, and successful deployment to both sub-servers
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-27 00:27:05 +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
a2d392dae7
fix: WebSSH terminal echo delay — replace readline() with read()
...
asyncssh's async-for on shell.stdout internally calls readline()
which buffers until a newline is found. For interactive terminal
use, single-character echo never contains a newline, so all
typed characters were buffered until Enter was pressed.
Fix: use shell.stdout.read(4096) which returns data as soon as
any is available, and set bufsize=4096 on create_process() to
reduce the internal read buffer from 128KB to 4KB for low-latency
interactive echo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-26 21:54:40 +08:00
Your Name
8b10f9d64a
fix: WebSSH terminal disconnect after connect + stale pool retry
...
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
- Fix shell creation failure on stale pooled SSH connections:
force-close and retry with fresh connection
- Fix empty error message in logs: use {type(e).__name__}: {e!r}
- Fix double WebSocket.close() causing RuntimeError in finally block:
track ws_closed flag to avoid closing twice
- Fix Alpine undefined error in terminal.html: $d() now returns
default object when Alpine hasn't initialized yet
- All websocket.close() calls now wrapped in try/except
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-26 21:33:31 +08:00
Your Name
b1aa235726
fix: Gate3 false positive + test_api.py production compatibility
...
- Gate3: Replace loose grep (matched "0/25 failed" summary) with precise
[FAIL] marker counting + "N test(s) failed" pattern
- test_api.py: Add .env credential loading for gate check automation
- test_api.py: Fix REST status codes (POST→201, DELETE→204)
- test_api.py: Add 204 empty body handling, dynamic ID, pre-cleanup
- Add gate_log.jsonl tracking to all 7 gates
- Add knowledge graph restructure changelog
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-26 19:33:31 +08:00
Your Name
5afb18b745
feat: gate v2 — 3→7 gates with anti-bypass, lint, security, review cross-validation
...
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 10:02:14 +08:00
Your Name
a1b0b2c514
feat: Terminal sidebar+panel, SSH key fix, auth cleanup, pre-deploy gates
...
- terminal.html: left sidebar (default open), right server panel with server list
- servers.py: fix SSH key double-encryption in update_server, auth method switch cleanup
- servers.html: auth switch clears opposite credentials (key↔password)
- deploy/pre_deploy_check.sh: 3-gate pre-deploy check (changelog/audit/test)
- mcp/Nexus_server.py: deploy() runs gate check before git pull+restart
- docs/audit/: audit record template + today's audit results
- CLAUDE.md: add gate enforcement rules and progress bar discipline
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 09:16:05 +08:00
Your Name
f591033309
docs: add changelog for asset management removal
...
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 00:58:14 +08:00
Your Name
89fa517693
refactor: remove asset management page, simplify server form
...
- Delete assets.html (platform/node management had low utility)
- Remove "资产管理" sidebar entry from layout.js
- Server form: remove Platform/Node dropdowns, keep only Category
combobox (with datalist for existing categories)
- Remove loadOrgSelects() and platform_id/node_id from save logic
- Backend API and DB tables preserved for data compatibility
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 00:46:39 +08:00
Your Name
973e23e038
fix: CSV template download 401 + category combobox
...
1. CSV template download link now uses apiFetch (with JWT) instead
of direct <a> href which returned 401 Unauthorized
2. Server category field changed from plain input to combobox with
datalist — users can select existing categories or type new ones
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 00:30:46 +08:00
Your Name
ad7f4d8d62
docs: update changelog with route fix and browser verification results
...
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 00:27:25 +08:00
Your Name
fb4e51ec5a
fix: move static routes before /{id} to fix route conflict
...
/batch/install-agent, /batch/upgrade-agent, /import, and
/import/template were registered after /{id}, causing FastAPI
to match 'batch' and 'import' as the {id} parameter.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 00:25:25 +08:00
Your Name
8cd091add8
feat: CSV batch import, SFTP upload, batch Agent operations
...
Add three missing frontend management features:
1. Server CSV import (POST /api/servers/import) with injection prevention
2. SFTP file upload (POST /api/sync/upload) with path traversal protection
3. Batch Agent install/upgrade with Semaphore concurrency control
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-26 00:17:43 +08:00
Your Name
6be989c299
feat: add SSH key preset management to credentials page
...
Add third tab "SSH密钥预设" to credentials.html with full CRUD:
- List presets with public key preview and creation date
- Add/edit preset (name, private key, public key)
- Reveal private key via re-authentication modal
- Delete preset with confirmation
- Route "+ 新建" button to correct form based on active tab
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-25 23:54:11 +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
95aa8a610f
security: move refresh token to HttpOnly cookie
...
- Refresh token stored in HttpOnly + Secure + SameSite=Lax cookie
instead of localStorage (XSS can no longer steal it)
- Login sets cookie, refresh reads from cookie, logout clears cookie
- Access token remains in localStorage (short-lived, 30min)
- Clear pendingPassword from memory after TOTP success/back
- Remove "admin" from username placeholder
- Cookie path scoped to /api/auth (minimal exposure)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-25 20:22:34 +08:00
Your Name
9de6ac9904
fix: auth default to password + remove SSH tab from assets
...
servers.html: Default auth method to "密码" (password) instead of "密钥"
(key) when adding a new server. Hide key path row by default.
assets.html: Remove SSH Sessions tab — it duplicated the server list
functionality. Assets page now focuses on classification metadata:
platform templates and node groups only.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-25 19:33:39 +08:00
Your Name
cf0725b037
fix: credentials.html JS parse error + assets.html SSH session UX
...
credentials.html: Remove broken nested ternary `Alpine?Alpine.store?...`
that caused "Unexpected token ':'" which killed the entire script block,
making all functions (showAddCred, loadCreds, etc.) undefined.
assets.html: Replace SSH session history list with server list +
double-click to open terminal, matching user's requested UX.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-25 19:17:09 +08:00
Your Name
3943ff4f3a
fix: remove updated_at secondary check that invalidated fresh JWTs
...
The updated_at secondary check in _verify_token() was a "defense in
depth" mechanism, but it caused a race condition: login updates admin
(last_login, onupdate→updated_at) AFTER creating the JWT, so the JWT's
"updated" claim is immediately stale. Any DB admin update (including
innocuous ones like last_login) would invalidate all existing tokens.
The token_version primary check already covers all security scenarios
(password change, TOTP disable, token reuse detection) and is the
correct mechanism for invalidating sessions. Removed the updated_at
check from both _verify_token() and get_optional_admin().
Also reordered login/refresh flows to create JWT AFTER admin update,
so the token captures the latest updated_at (belt and suspenders).
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-25 16:23:20 +08:00
Your Name
deb3a94ee6
fix: token_version NULL handling — normalize None→0 in JWT comparison
...
Direct DB inserts (e.g. install wizard, manual MySQL) may leave
token_version as NULL. JWT payload had tv:null which failed the
strict != comparison against DB value 0. Normalize both sides
with `or 0` for defensive coding.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-25 15:37:10 +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
400dcae781
fix: 代码验证发现的两处问题
...
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
- websocket.py: asyncio.get_event_loop() → get_running_loop()
(Python 3.10+废弃,shutdown时可能RuntimeError)
- asyncssh_pool.py: 全忙等待逻辑在锁外操作有竞态条件
简化为直接raise ConnectionError,不在锁外重试
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2026-05-24 16:31:13 +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
488838c989
feat: separate subscription/manual IPs + master enable/disable toggle
...
Data model (separate storage):
- login_allowlist_enabled: 'true'/'false' master switch
- login_subscription_url: URL to fetch every 2h
- login_subscription_ips: last fetch result (replaced entirely each refresh)
- login_manual_ips: manually added (never overwritten by refresh)
- login_allowed_ips: combined (used by auth for legacy compat)
ip_allowlist_refresh.py:
- Saves to login_subscription_ips (replace) + rebuilds login_allowed_ips
auth_service.py:
- Login check: only runs when LOGIN_ALLOWLIST_ENABLED is 'true'
- Combines subscription_ips + manual_ips at auth time (no stale combined key needed)
settings.py:
- POST /ip-allowlist/toggle: quick enable/disable endpoint
- GET /ip-allowlist: returns subscription_ips, manual_ips separately
- POST /ip-allowlist: saves manual_ips + optional subscription_url + optional enabled
settings.html:
- Toggle switch: enable/disable with warning if list is empty
- Green notice when enabled (warns about self-lockout risk)
- Grey notice when disabled
- Subscription IPs section: read-only, auto-refresh badge
- Manual IPs section: deletable per-IP, clear all button
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 18:19:47 +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
5fcc1e22a6
feat: login IP allowlist with proxy subscription parser
...
server/infrastructure/subscription_parser.py (new):
- parse_subscription_content(): fetch and decode subscription, extract host/IP
- Supports SS, VMess, VLESS, Trojan, Hysteria2 formats
- Base64 decode with padding fix; IPv4/CIDR/hostname detection
server/config.py:
- LOGIN_ALLOWED_IPS setting (empty = allow all, comma-separated)
server/api/settings.py:
- POST /settings/ip-allowlist/parse-subscription: fetch URL, decode, return hosts
- POST /settings/ip-allowlist: save allowlist to settings table + reload
- GET /settings/ip-allowlist: return current list
server/application/services/auth_service.py:
- _ip_in_allowlist(): supports exact IP, CIDR (ipaddress module), hostname match
- login(): check allowlist before brute-force check; if IP blocked return
reason='ip_blocked' with clear message; audit log 'login_ip_blocked'
web/app/settings.html:
- New '登录 IP 白名单' card with:
- Subscription URL input + parse button (calls backend parser)
- Parsed IPs with checkboxes (select/deselect before adding)
- Manual IP/CIDR/hostname textarea input
- Current allowlist with per-IP remove buttons
- Clear all button (removes restriction)
- Status badge: 启用 N条 / 未启用(不限制)
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 18:11:23 +08:00
Your Name
37ceaef6d9
feat: auto-poll Agent online status after install with live badge update
...
- remoteInstallAgent(): after success, start _startAgentOnlinePoller() instead
of one-shot setTimeout(loadServers, 2000)
- _startAgentOnlinePoller(serverId): poll GET /api/servers/{id} every 5s up to
2 minutes (24 attempts); when is_online=true, update status badge live,
disable remote-install button, toast 'Agent 已上线', reload server list
- _updateAgentStatusBadge(isOnline): in-place badge update without full reload
- Install log shows: '✓ 安装成功!等待首次心跳...' then '✅ Agent 心跳已收到'
- Hint text explains: install ~30-60s, first heartbeat another ~60s
- Manual install: 'click to wait for Agent online' button triggers same poller
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:47:22 +08:00
Your Name
d414b945e1
feat: audit log time-range filter + script execution schedules
...
Audit log time-range filter:
- audit_log_repo.py: unified query() with action/admin_username/date_from/date_to
filters + total count; _build_filters() helper for date parsing
- settings.py GET /audit/: add date_from, date_to, admin_username query params
- audit.html: date range inputs (YYYY-MM-DD), admin filter input, action filter
expanded with optgroups (服务器/推送/脚本/认证/设置); clear filter button
Script execution schedules:
- domain/models: PushSchedule extended with schedule_type('push'|'script'),
script_id FK, script_content Text, exec_timeout int, long_task bool;
source_path made nullable
- migrations.py: 6 new ALTER TABLE statements (idempotent)
- schedule_runner.py: detect schedule_type; for 'script' type use ScriptService;
for 'push' type keep original SyncEngineV2 sync_files behaviour
- schemas.py: ScheduleCreate/Update add all new fields
- schedules.html: full UI rewrite
- type selector radio: 📁 文件推送 / ⚡ 脚本执行
- script fields: script library dropdown + textarea + timeout + long_task
- schedule list shows type badge + detail preview
- saveSched() validates required fields per type
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:29:16 +08:00
Your Name
4ca07fa252
feat: quick execute panel in scripts.html (no script save required)
...
Add collapsible '直接执行命令' card at top of scripts page:
- Textarea for ad-hoc command (no script_id, not saved to library)
- Multi-select server list (loaded on first expand, same batch size)
- Options: timeout, DB credential (* substitution), long_task nohup
- Ctrl+Enter shortcut to submit
- Uses same batch tracking + status panel + polling as saved scripts
- Clear button to reset command
- Batch hint shows server count and batch size
- 全选 button for quick server selection
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:23:25 +08:00
Your Name
d2832567c7
feat: push logs view in commands.html + paginated sync log API
...
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
sync_log_repo.py:
- get_all_paginated(): server_id/status/sync_mode/trigger_type filters +
server name JOIN + total count for pagination
server/api/servers.py GET /servers/logs:
- Add server_id/status/sync_mode/trigger_type/offset/limit query params
- Return {items, total, offset, limit} instead of plain list
web/app/commands.html (renamed title to '操作日志'):
- Third view: '推送日志' with paginated table
- Columns: 状态(dot badge) / 服务器 / 模式 / 触发方式 / 源路径 /
目标路径 / 文件数 / 耗时 / 操作人 / 开始时间
- Filters: 服务器 + 状态(success/failed/running) + 模式 (incremental/full/...)
- Pagination controls with prev/next page (50 per page)
- Error message in row title attribute (hover for details)
web/app/push.html:
- Update loadHistory() to handle new {items, total} response format
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:20:53 +08:00
Your Name
14dc29f241
feat: Agent install tab with copy command + one-click remote install via SSH
...
server/api/servers.py:
- POST /{id}/install-agent: SSH-execute install.sh on managed server using
stored credentials; requires API_BASE_URL + agent_api_key; 120s timeout
- GET /{id}/agent-install-cmd: return pre-filled curl command for copy-paste
web/app/servers.html:
- New 'Agent 安装' tab in server detail panel
- Shows Agent online/offline status badge
- Warns if NEXUS_API_BASE_URL or API Key is missing
- Displays ready-to-copy curl install command with port auto-filled
- '⚡ 一键远程安装' button (SSH exec): disabled if already online
- Scrollable install log output panel
- Tab uses shared showDetailTab() + loadAgentInstall() / remoteInstallAgent()
- Explains: script auto-installs Python, downloads agent.py, writes config,
sets up systemd, opens firewall port
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:16:14 +08:00
Your Name
b9e8db7a3f
feat: per-alert notification toggles with switch UI
...
config.py:
- Add NOTIFY_ALERT_CPU/MEM/DISK, NOTIFY_RECOVERY, NOTIFY_TIME_DRIFT,
NOTIFY_SYSTEM_REDIS, NOTIFY_SYSTEM_MYSQL, NOTIFY_RESTART settings
(string 'true'/'false', loaded from MySQL settings table at startup)
telegram/__init__.py:
- _notify_enabled(): check setting string ('false'/'0'/'no'/'off' = disabled)
- send_telegram_alert(): checks NOTIFY_ALERT_{CPU|MEM|DISK} per alert_type
- send_telegram_recovery(): checks NOTIFY_RECOVERY
- send_telegram_system_alert(): new notify_key param, checks matching setting
- send_telegram_restart_*(): check NOTIFY_RESTART
self_monitor.py:
- Pass notify_key='NOTIFY_SYSTEM_REDIS/MYSQL' to send_telegram_system_alert
server/api/agent.py:
- Pass notify_key='NOTIFY_TIME_DRIFT' to time-drift alert
settings.html:
- New '告警通知项目' section with 8 toggle switches (pill style)
- Grouped by category: 服务器资源 / 服务器 / 系统
- Optimistic toggle with revert on API failure
- renderNotifyToggles() reads _allSettings and toggleNotify() saves instantly
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:12:07 +08:00
Your Name
08d0baf762
feat: TOTP re-bind support + improved settings UI
...
settings.html TOTP section overhaul:
- Status cards: green (enabled) / amber (disabled) with context-aware buttons
- Enabled state: add '重新绑定' button to change Authenticator app/device
without disabling first (same API, just new QR + verify flow)
- Disabled state: prominent 'Enable TOTP' CTA with warning about security
- Bind panel: shared between first-time setup and re-bind, auto-scrolls into view
- Auto-focus verify input after QR renders; Enter key submits
- QR generation: 180px, transparent background, fallback message if QRious fails
- Re-bind label distinguishes 'rebind success' from 'first enable' toast
- Disable flow: clearer confirm dialog mentioning security implication
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:07:40 +08:00
Your Name
9c063a788f
feat: time drift detection between agent and central server
...
Agent (web/agent/agent.py):
- Heartbeat now includes system_info.agent_time (UTC ISO string)
Central (server/api/agent.py):
- On each heartbeat, compare agent_time vs central datetime.now(utc)
- Thresholds: warn >= 30s, crit >= 60s (affects TOTP/cron accuracy)
- Stores time_drift_seconds + drift_level in Redis heartbeat key
- Sends Telegram alert (5-min cooldown) when drift >= 60s critical
API (server/api/servers.py):
- List and detail endpoints expose time_drift_seconds + drift_level from Redis
Frontend (web/app/servers.html):
- driftBadge(): shows clock emoji badge next to server name
- amber badge: >=30s (warn)
- red badge: >=60s (crit)
- tooltip shows exact drift and NTP check hint
- no badge when drift < 30s or no data
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 17:04:34 +08:00
Your Name
5a42345bc0
docs: Nexus 6.0 功能说明书 HTML + roadmap stale fix
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:55:24 +08:00
Your Name
6c5e6a2daa
feat: file operations (delete/rename/mkdir) + fix roadmap Step3 status
...
Backend:
- schemas.py: FileOperation model (server_id, operation, path, new_path)
- sync_v2.py: POST /api/sync/file-ops endpoint
- delete: rm -rf with shlex.quote
- rename: mv src -> dst with shlex.quote on both paths
- mkdir: mkdir -p with shlex.quote
- all operations audit-logged, 30s timeout
Frontend (files.html):
- Header: add 📁 + button (doMkdir via prompt)
- File rows: action buttons (rename + delete) appear on hover
- rename: prompt for new name, inline mv
- delete: confirm dialog with warning for dirs (rm -rf)
- all ops refresh current directory after success
- fileOp() shared helper for POST /api/sync/file-ops
Docs:
- roadmap.md: Step 3 Web SSH updated from 70% to completed
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:46:00 +08:00
Your Name
ac0eb79707
feat: rsync dry-run preview (方案D 智能提示型)
...
Backend:
- schemas.py: SyncPreview model (server_id, source/target_path, sync_mode, verbose)
- sync_engine_v2.py: preview_sync() + _parse_rsync_stats() helpers
- runs rsync --dry-run --stats; verbose=True adds -v (capped 200 lines)
- returns stats dict: files_transferred/created/deleted + byte counts
- sync_v2.py: POST /api/sync/preview endpoint with audit log
Frontend (push.html - 方案D):
- Sync mode radio change listener: onSyncModeChange()
- full/overwrite mode: orange warning card + prominent preview button
- incremental/checksum mode: subtle "预览首台变动 →" link
- Inline preview result section (no modal): stats cards + optional file list
- files_deleted shown in red card for destructive modes
- verbose toggle: "显示详细文件列表 ▼" triggers second request with verbose=true
- fmtBytes() helper for human-readable file sizes
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:41:47 +08:00
Your Name
e37bc6cea9
docs: drop file editor (Monaco/ACE) - officially rejected
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:31:33 +08:00
Your Name
2c6f3abbd0
docs: add standards/ folder with all reusable dev & audit standards
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:23:50 +08:00
Your Name
d5c498549b
docs: system development standard v1.0 - full coding rules for Python/FastAPI/Frontend
...
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
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:22:36 +08:00
Your Name
07eab6020c
docs: extract audit core principles as standalone reference card
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:19:49 +08:00
Your Name
938e700fb3
docs: line-walk audit standard v2.0 - full spec integrating mdc rules + Phase 1-4 lessons
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:17:27 +08:00
Your Name
424c4efd64
docs: general-purpose line-walk audit standard (reusable for any project/AI)
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:09:28 +08:00
Your Name
c08e2a2242
fix: Phase 1 audit - ssh_key columns String(500) -> Text for RSA key support
...
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:07:24 +08:00
Your Name
6108d69b24
fix: Phase 4 audit fixes
...
F4a-01 script_callback_rate: INCR+EXPIRE were non-atomic; a crash between
the two could leave the rate-limit key without a TTL, permanently
blocking future callbacks for that job/IP. Fix: use Redis pipeline
so INCR+EXPIRE are sent in one roundtrip and EXPIRE always executes.
F4a-02 sync_service: add comment documenting that StrictHostKeyChecking=no
is a legacy issue in the dead-code SyncService shim; main sync path
(SyncEngineV2) honours SSH_STRICT_HOST_CHECKING from settings.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 16:00:28 +08:00
Your Name
680577fc97
docs: Phase 3 walk-closure report + index update
...
- docs/reports/audit-phase-3-walk-closure.md: closure declaration
covering 3a-3i (12 new FINDINGs, all fixed, code backlog = 0)
- docs/reports/README.md: add Phase 3 closure entry
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 15:56:11 +08:00
Your Name
86bb32f87e
fix: Phase 3h script_service + server_service
...
F3h-01 script_service._build_kill_command: shlex.quote(log_path) wraps the
path in single-quotes; embedding that inside "..." produced a filename
with literal single-quote chars that cat/kill could not find.
Fix: use the shlex-quoted string directly without extra double-quotes.
F3h-02 script_service._substitute_db_vars: non-atomic string replacement
allowed nested substitution when a credential value contained another
$DB_* pattern. Fix: replace with null-byte sentinels first, then
substitute actual values in a second pass.
server_service.push_to_servers: add comment documenting that audit_repo and
retry_repo are None (internal compat shim — not used by routes).
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 15:50:44 +08:00
Your Name
c3c3bae370
fix: Phase 3g sync_engine_v2 bugs
...
F3g-01 sync_commands line 195: server_results is a list; unpacking it
with ** raises TypeError, silently caught by gather(return_exceptions=True),
so S2 command sync and S3 config sync returned empty results for all
servers. Fixed by using a proper dict: {"server_name": ..., "results": ...}.
F3g-02 sync_config: config value containing newline chars was not stripped
before shlex.quote; echo inside single-quotes would write multiple lines
to the sysctl config file, injecting arbitrary keys. Strip \n\r\x00 from
value before quoting (requires admin auth, defense-in-depth fix).
scripts.py, settings.py: CLEAN (no changes needed).
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 15:46:52 +08:00
Your Name
33b7ed93bf
fix: Phase 3e auth_service.py bugs
...
F3e-01 auth_service.py:180 - jwt_token_expires (MySQL tz-naive) vs
datetime.now(timezone.utc) caused TypeError on token refresh;
strip tzinfo before comparison when expires is tz-naive.
F3e-02 auth_service.py:271 - TOTP provisioning URI was not URL-encoding
issuer or username; special chars (spaces etc.) broke QR scan.
Use urllib.parse.quote() on both fields.
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 15:41:50 +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
aa65f10c52
docs: Phase 2 audit records, project memory, WSL guide
...
Audit docs:
- docs/reports/audit-phase-2{a-j}-line-walk.md: per-file line walk findings
- docs/reports/audit-phase-2-findings-matrix.md: 63 findings (52 fixed, 3 partial, 7 accepted)
- docs/reports/2026-05-23-full-audit-report.md: full audit consolidation
- docs/reports/audit-full-vs-phase2-reconciliation.md: cross-reference
- docs/reports/audit-phase-2-walk-closure.md: closure sign-off
Project docs:
- docs/project/phase-2-audit-remediation.md: SSOT for all fixes
- docs/project/alert-push-policy.md: dashboard alert design decisions
- docs/project/production-verification-checklist.md: first-deploy checklist
- docs/project/script-execution.md: script platform design
- docs/project/wsl-integration-test.md: WSL code-only verification guide
- docs/project/line-walk-audit-standard.md: audit methodology
- docs/project/mysql-mcp-setup.md: MCP config guide
Changelogs: 18 entries (2026-05-22 to 2026-05-23)
Project memory: CLAUDE.md, AGENTS.md updated to reflect current state
Deploy: nginx_https.conf template updated
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 15:27:40 +08:00
Your Name
80d73d1b74
fix: WSL startup compatibility + dependency updates
...
- redis/client.py: use BlockingConnectionPool.from_url() (fixes 'url' kwarg error)
- database/engine_compat.py: patch aiomysql do_ping to satisfy pool_pre_ping
- database/session.py: apply engine_compat patch before create_async_engine
- requirements.txt: SQLAlchemy 2.0.49 (fixes aiomysql ping() reconnect signature)
- .env.example: document NEXUS_REDIS_URL format
- scripts/wsl_ensure_venv.sh: create project .venv (PEP 668 safe)
- scripts/wsl_start_dev.sh: use .venv python, validate Redis before start
- scripts/wsl_integration_smoke.sh: code-only verification mode
- scripts/wsl_check_mysql.py / bootstrap_database.py: MySQL setup helpers
- scripts/sync_frontend_vendor.py: vendor asset sync utility
Co-authored-by: Cursor <cursoragent@cursor.com >
2026-05-23 15:27:18 +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
341d16fd6d
P2迭代: 危险命令检测 + DB会话合并 + API密钥修复 + 安全审计 (6项)
...
P2-14: agent.py _verify_api_key() 重写文档并明确两步验证逻辑,
全局密钥匹配直接通过,非匹配密钥放行至handler做per-server验证
P2-15: websocket.py 删除已废弃的 connected_clients=[] 别名,
health.py 已使用 manager.client_count
P2-16: webssh.py 合并4个AsyncSessionLocal()为1个共享session(预接受操作),
命令日志保留独立session(长连接WebSocket不能持有单session)
P2-18: 新增危险命令检测 (check_dangerous_command),识别 rm -rf /、
fork bomb、dd写裸设备、mkfs等模式,scripts.py + webssh.py集成
P2-19: install.py 状态文件不再存储db_pass明文(步骤5已删除文件),
审计确认所有logger调用无敏感数据泄露
P2-17: httpOnly cookie迁移标记为延期(需前后端+WebSocket全面重构,
当前JWT+updated_at+CORS限制方案已足够安全)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 23:18:08 +08:00
Your Name
d744d7df8e
安全与质量修复: P0-4/P0-5 + P1-6~P1-13 (8项)
...
P0-4: install.py _write_env() 值加引号转义,防止含#$\等字符的密码破坏.env格式
P0-5: install.py _build_redis_url() URL编码redis密码,防止@:等字符破坏URL解析
P1-6: auth_service.py _decode_access_token() 验证exp/sub声明存在,拒绝畸形JWT
P1-7: websocket.py + webssh.py WebSocket JWT验证增加updated_at检查,密码修改后令牌失效
P1-8: auth.py 无refresh_token的logout返回更明确的提示信息
P1-9: install.py create_admin增加_is_installed()检查,防止.env存在后重复创建
P1-10: servers.py server_stats() 改用SQL聚合查询,避免加载全部服务器对象
P1-11: heartbeat_flush.py 移除get_redis()永不返回None的死代码
P1-13: sync_engine_v2.py completed/failed计数器加asyncio.Lock防止并发竞态
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 23:04:40 +08:00
Your Name
4af9acf564
项目文档与验证脚本: AGENTS.md + 交接文档 + 审计/测试脚本
...
- AGENTS.md: 项目记忆(与CLAUDE.md同步)
- PROJECT_HANDOVER.md: 项目交接文档
- TEAM_ROLES.md: 团队分工与职责
- audit_scan.py: 全量代码审计扫描
- test_p1_p2.py: P1+P2功能快速验证
- verify.py: WSL模块/路由/安全验证
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 22:29:54 +08:00
Your Name
6354d507df
修复 sync_v2.py 缺少 AuditLog import (NameError)
...
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 22:29:35 +08:00
Your Name
7e29397235
配置与文档更新: .gitignore + CLAUDE.md + API微调
...
- .gitignore: 添加.env/supervisor/日志等忽略规则
- CLAUDE.md: 更新项目记忆与完成状态
- assets.py: Platform/Node API端点
- settings.py: DB_OVERRIDE_MAP键名修复
- schemas.py: 模型schema补充
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 22:29:20 +08:00
Your Name
4969876ce8
新页面: 资产管理 + 命令日志 + 数据库备份脚本
...
- assets.html: Platform/Node资产管理页面
- commands.html: 命令/会话双视图 + 危险命令高亮
- deploy/db_backup.sh: mysqldump + 30天保留 + cron集成
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 22:29:13 +08:00
Your Name
b676e320de
前端增强: XSS防护 + 共享布局 + 移动适配 + 设置页
...
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
- index.html: WebSocket告警文本esc()转义
- files.html: escAttr()函数 + 路径拼接转义
- layout.js: 移动端侧边栏overlay + 全局搜索 + 用户信息
- servers.html: 点击展开详情面板(系统信息/同步/SSH)
- settings.html: TOTP QR码设置 + 修改密码 + API Key复制
- api.js: JWT refresh token自动刷新 + Toast通知
- terminal.html: WebSSH xterm.js集成
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 22:29:06 +08:00
Your Name
938d26927f
P1/P2: 后端安全与稳定性修复
...
- Agent per-server API Key认证 (agent.py)
- JWT updated_at校验与会话超时 (auth_jwt.py)
- 服务器凭据Fernet加密存储+密码脱敏 (servers.py)
- WebSSH服务器级授权检查 (webssh.py)
- Config同步去重+回滚机制 (sync_engine_v2.py)
- DB层分页offset/limit (server_repo.py)
- session.py logger修复 + @property死代码清理
- 心跳刷入rollback误用修复 (heartbeat_flush.py)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 22:28:57 +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
dfc37f6e90
修复设置页面键名与后端DB_OVERRIDE_MAP不匹配
...
settings.html引用pool_size/max_overflow/agent_heartbeat_interval
但config.py的DB_OVERRIDE_MAP期望db_pool_size/db_max_overflow/
heartbeat_timeout,导致这些设置无法从MySQL正确加载。
对齐前端键名与后端映射表。
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 12:02:08 +08:00
Your Name
0bcfeaa6d6
修复心跳刷入rollback误用 + API参数规范化
...
- heartbeat_flush: 移除循环内session.rollback(),防止一个服务器
刷入失败导致整个批次session状态损坏
- assets.py: 为Query参数添加Query()类型+描述+校验约束,
统一FastAPI参数风格 (server_id/session_id/limit/parent_id)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 11:58:15 +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
b36e1d8010
服务器详情: 兼容多种Agent心跳字段名(cpu_percent/cpu_usage)
...
- normalize: cpu_percent || cpu_usage, memory_percent || mem_usage, disk_percent || disk_usage
- 防止Agent使用不同字段名时显示空白
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 11:23:19 +08:00
Your Name
8a5d4159a4
文件管理: 添加缺失的路径输入框 + Enter键触发浏览
...
- 添加dirPath输入框(之前只有JS引用没有DOM元素)
- Enter键支持快速跳转到指定路径
- 输入框预填默认值'/'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 11:13:23 +08:00
Your Name
c03fe97d18
UX优化: 同步日志显示服务器名 + redis_url可编辑
...
- 同步日志API: JOIN Server表返回server_name字段
- 推送历史: 显示服务器名称替代操作人
- 仪表盘最近同步: 显示服务器名称替代server_id
- redis_url从SENSITIVE_KEYS移除(非密码,用户需可编辑)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 11:10:20 +08:00
Your Name
e9feaa6cdc
前后端一致性审计 + 批量操作 + 调度同步模式
...
- 服务器列表: 添加批量选择(checkbox)+批量推送/删除操作栏
- 推送页面: 支持从服务器列表页预选服务器跳转(sessionStorage)
- 调度页面: 添加同步模式选择(增量/全量/校验和)
- 后端: PushSchedule模型+Schema+API+ScheduleRunner添加sync_mode字段
- 仪表盘: 移除重复的函数定义和初始化调用
- 数据库迁移: 启动时自动执行schema migration(添加sync_mode列)
- 安装向导: 添加schema migration步骤
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 11:01:17 +08:00
Your Name
83547c0b2e
服务器列表分类过滤 + 搜索增强
...
- 添加分类过滤下拉框(对接/api/servers/?category=参数)
- 自动从服务器数据提取分类选项填充下拉框
- 搜索框也匹配分类字段
- 添加刷新按钮
- 切换分类时自动重新加载服务器列表
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 10:11:15 +08:00
Your Name
2ec24371c5
/api/auth/me 返回 system_name 供前端品牌定制
...
- auth.py: /me端点现在查询settings表返回system_name字段
- layout.js的loadLayoutUser()使用此字段动态更新侧边栏品牌名
- 用户在设置页修改"系统名称"后,所有页面侧边栏自动显示
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:54:19 +08:00
Your Name
8ae4bc48cd
文件管理增强 + 更新项目完成度至99%
...
- files.html: 面包屑导航、目录排序(文件夹优先)、父目录(..)链接、
文件所有者显示、toast反馈、owner列
- CLAUDE.md: 更新实现状态,新增Phase E UX增强条目(S1-S3安全,
UX1-UX10前端体验),完成度从95%提升至99%
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:49:10 +08:00
Your Name
9d34655cc1
fix: Alpine.js x-data缺失 + 登录页429锁定处理
...
- index.html/servers.html: 添加缺失的 x-data="{sidebarOpen:true}"
(Alpine.js需要初始化sidebarOpen变量)
- login.html: 正确处理429状态码(账户临时锁定),显示锁定提示
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:46:23 +08:00
Your Name
249a1aaed9
重试队列增强 + 审计分页
...
- 后端: 添加 POST /api/retries/{id}/retry (手动重试) + DELETE /api/retries/{id}
+ 审计日志分页(offset/limit/count) + PushRetryJobRepo新增get_all/get_by_id/delete
- 前端retries: 手动重试按钮、删除按钮、状态过滤、操作人显示、toast反馈
- 前端audit: 分页控件(上一页/下一页)、每页50条、新增retry_job/delete_retry过滤
- 修复index.html: 适配审计API新返回格式(data.items)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:41:33 +08:00
Your Name
120ae186ef
统一所有页面到layout.js共享布局组件
...
- 将11个业务页面(index/servers/files/scripts/credentials/settings/terminal等)
的内联侧边栏全部迁移到layout.js的initLayout()共享组件
- 移除各页面重复的loadUser()函数,统一由layout.js处理
- 统一全局搜索功能、用户信息加载、品牌名称显示
- 消除约800行重复的侧边栏HTML代码
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:29:25 +08:00
Your Name
cca410da33
P2: 推送页面增强 + 登录页安全强化
...
- push.html: 完整重写 — 逐服务器状态显示(成功/失败/等待)、进度条、
同步模式选择卡片、并发/批次配置、全选/全不选、推送历史记录、toast反馈
- login.html: 密码可见性切换(eye图标)、失败次数提示(3次/5次警告)、
登录失败时卡片shake动画、锁定警告提示区、迁移layout.js
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:23:38 +08:00
Your Name
26833f00d3
P1: Toast通知系统 + 脚本编辑/执行结果格式化
...
- api.js: 添加全局toast()通知函数,支持success/error/warning/info四种类型
- scripts.html: 完整重写 — 点击脚本名编辑、执行结果按服务器格式化显示(command/stdout/stderr/exit_code)
- servers.html/credentials.html/schedules.html/settings.html: 所有操作添加toast反馈
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 09:20:44 +08:00
Your Name
d4ea03d735
P2: 全局搜索功能 — 后端API + 前端侧边栏搜索
...
- 新增 /api/search/ 端点: 跨服务器/脚本/凭据/调度搜索
- layout.js: 侧边栏底部搜索框, 300ms防抖, 下拉结果面板
- main.py: 注册搜索路由
2026-05-22 09:08:09 +08:00
Your Name
f262876b25
P2: 共享侧边栏布局组件 + 4个页面迁移
...
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
- 新增 layout.js: initLayout() 自动生成侧边栏+高亮+用户信息
- retries/audit/schedules 已迁移到共享布局
- 减少约200行重复HTML代码
2026-05-22 09:05:49 +08:00
Your Name
bfa50337e5
P1+P2: 前端功能增强
...
- servers.html: 服务器详情面板(系统信息/同步日志/SSH会话三标签页)
- index.html: 仪表盘增强(分类分布图/最近同步日志/自动刷新30s)
- credentials.html: 密码预设标签页(对接/api/presets/ CRUD)
2026-05-22 09:03:18 +08:00
Your Name
305f8d5689
P1: 全局JWT保护 + 审计日志补全 — scripts/assets/servers
...
- scripts.py: 所有9个端点添加JWT认证 + CUD操作审计日志
- assets.py: 所有GET端点添加JWT + 写操作审计日志补全
- servers.py: GET端点JWT保护(上轮未提交)
- WSL全量验证通过: ALL CHECKS PASSED
2026-05-22 08:55:34 +08:00
Your Name
785ffe2a7e
fix: 设置页面敏感字段显示为只读锁定状态
...
脱敏值(包含***或...)显示为只读文本+🔒 标记,防止用户编辑部分遮蔽值
2026-05-22 08:47:16 +08:00
Your Name
55b7cbe904
fix: P1安全加固 — 全局JWT保护 + 审计日志补全 + 敏感字段过滤
...
Settings API:
- 所有端点添加JWT认证(get_current_admin)
- 不可改项(secret_key/api_key/encryption_key/database_url)禁止PUT修改
- 敏感字段GET响应自动脱敏(前8位+...)
- Schedules/Presets/Retry CRUD添加JWT+审计日志
Servers API:
- POST/PUT/DELETE添加JWT认证
- 服务器增删改写审计日志
Assets API:
- Platform/Node写操作添加JWT认证
- Platform创建添加审计日志
2026-05-22 08:46:09 +08:00
Your Name
b9139093f1
fix: 更新.env.example + CLAUDE.md反映D2迁移
...
- .env.example: install.php→install.html引用, 添加NEXUS_API_BASE_URL
- install.py: 移除_write_env中重复的site_url计算
- CLAUDE.md: 全面更新项目记忆, 反映6步完成+D1/D2/D3解决
2026-05-22 08:39:33 +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
8c8d2a74d5
docs: add Vercel-style documentation browser
...
Tailwind CSS + Alpine.js single-page HTML doc viewer with:
- 274 documents embedded (270 md + 4 other file types)
- Dark/light mode with localStorage persistence
- Sidebar navigation with grouped collapsible sections
- Full-text search (filename + content)
- Auto-generated TOC for each document
- Terminal-style code blocks with language labels
- Mobile responsive with slide-out sidebar
- rebuild: python docs/build_html.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 07:26:31 +08:00
Your Name
302fdcc1a1
test: update E2E test suite for v6 API + JWT auth
...
- Login first to acquire JWT token for all protected routes
- Use correct v6 API paths (/api/presets/, /api/schedules/, /api/scripts/)
- Add tests for: scripts CRUD, schedules toggle, settings, audit, sync browse
- Remove obsolete password-presets and retry-jobs paths
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 00:39:03 +08:00
Your Name
5590391779
feat: Nexus Agent rebrand + server_id + exec endpoint + trigger_type
...
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
Agent (agent.py):
- Rebrand MultiSync → Nexus throughout
- Add server_id to heartbeat payload (required by backend AgentHeartbeat schema)
- Add /exec endpoint for remote command execution via Nexus
- Update heartbeat fields to match backend: cpu_usage, mem_usage, disk_usage
- Use 60s default interval (matches CLAUDE.md spec)
Agent (agent.sh):
- Rebrand, add SERVER_ID env var, send in heartbeat payload
- Update service name to nexus-agent
Agent (install.sh):
- Rebrand, add --id parameter for server_id
- Write server_id to config.json
- Service name: nexus-agent
- Add config.example.json for reference
SyncEngineV2:
- Add trigger_type parameter to sync_files() (was hardcoded "manual")
- Schedule/retry runners can now pass "schedule"/"retry" trigger types
Nginx:
- Add /agent/ to static asset locations for agent file downloads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 00:37:39 +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
cd3c35b5e6
fix: add per-field save buttons to settings page
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 00:04:29 +08:00
Your Name
f0c586a345
feat: complete frontend interactive features + unified sidebar
...
- credentials: add credential CRUD form (type, host, port, user, password, db)
- schedules: add enable/disable toggle, edit modal, server selection
- retries: add status badges, retry progress bar, error display, refresh
- audit: add action filter dropdown, IP column, better status badges
- settings: reorganize into sections (brand/alert/infra/telegram)
- servers: add/edit modal with full form fields
- scripts: add execute modal + delete button
- All pages: unified sidebar with all nav items + hover states
- install.php: fix post-AdminLTE removal link paths
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-22 00:02:46 +08:00
Your Name
00a6491e59
chore: remove AdminLTE PHP frontend (keep only install.php)
...
All functionality now covered by web/app/*.html (Alpine.js + Tailwind).
Deleted: 29 PHP pages, ace editor, chart.min.js, app.js, style.css.
Kept: install.php (installation wizard with DB table creation + .env write).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 23:42:21 +08:00
Your Name
7caa880ebd
feat: unified api.js auth + Pydantic models + JWT security hardening
...
- All Alpine.js pages now use shared api.js for JWT auto-refresh (9 pages)
- Dashboard uses /servers/stats endpoint instead of fetching all servers
- Replaced all raw dict params with Pydantic models (agent, settings, presets)
- Added AgentHeartbeat, AgentExec, SettingUpdatePayload, DbCredentialCreate schemas
- JWT decode now requires exp+sub claims; better error logging
- ServerService.push_to_servers delegates to SyncService.batch_push
- SyncService handles None audit_repo/retry_repo gracefully
- Branding: web/app.js + web/style.css MultiSync→Nexus
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 23:38:01 +08:00
Your Name
a584792603
feat: Pydantic request models + pagination + JWT auto-refresh
...
- server/api/schemas.py: New shared Pydantic models for all API routes
(ServerCreate/Update/Push/Check, SyncFiles/Commands/Config/Sftp/Browse,
ScriptCreate/Update/Execute, ScheduleCreate/Update, PlatformCreate/Update,
NodeCreate/Update, PaginatedResponse)
- servers.py: Replace raw dict with Pydantic models, add pagination
(page/per_page params, response now includes items/total/pages)
- sync_v2.py: Replace raw dict with SyncFiles/Commands/Config/Sftp/Browse
- scripts.py: Replace raw dict with ScriptCreate/Update/Execute
- assets.py: Replace raw dict with PlatformCreate/Update, NodeCreate/Update
- web/app/api.js: Shared JS auth module with JWT auto-refresh (2min
before expiry), 401 retry with refresh token, doLogout with
sendBeacon to backend, backward-compatible ah() alias
- web/app/servers.html: Use api.js, handle paginated response format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 23:18:49 +08:00
Your Name
1a27327036
fix: PHP frontend JWT auth + API endpoints + missing tables + branding
...
- login.php: Fix JWT response format (success/access_token vs status=ok),
store JWT tokens in session, support TOTP 202 flow
- api_client.php: Dual auth (JWT Bearer + X-API-Key fallback), add
auto-refresh on 401, fix API endpoints (checkServerHealth → array,
getServerLogs, getAuditLogs, getDashboardStats field mapping)
- api_proxy.php: Fix check_all to use /api/servers/check (not per-server),
fix get_logs to support global endpoint, restart_multisync → restart_nexus
- install.php: Add 4 missing tables (platforms, nodes, ssh_sessions,
command_logs), fix table creation order for FK dependencies, add JWT
columns to admins, add new indexes, add platform_id/node_id/protocols/
extra_attrs/connectivity to servers
- logout.php: Call /api/auth/logout to invalidate JWT refresh token
- index.php: Use JWT Bearer auth for API calls
- server_service.py: Implement real check_all_servers with concurrent
httpx Agent health checks (was stub)
- servers.py: Add GET /api/servers/logs global sync logs endpoint
- Branding: MultiSync → Nexus across all PHP files (sidebar, titles,
TOTP issuer, version strings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 23:11:30 +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
73c1776e1e
fix: P0 critical runtime issues
...
1. conftest.py: add missing `from server.main import app` import
2. dependencies.py: get_db() reuses middleware session instead of
creating independent AsyncSessionLocal (fixes double-session bug)
3. auth_jwt.py: get_optional_admin uses request.state.db instead of
creating leaked AsyncSessionLocal session
4. config.py: default DATABASE_URL uses mysql+aiomysql (not pymysql)
5. sync_engine_v2.py: sanitize config keys with regex, escape values
to prevent command injection in sync_config
6. sync_v2.py: add POST /api/sync/browse endpoint for remote dir listing
7. files.html: browseDir calls real API instead of placeholder stub
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 22:54:35 +08:00
Your Name
ead4b2580f
fix: 3 code bugs + test fixes (46/46 passing)
...
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
1. infrastructure/__init__.py: remove nonexistent get_ssh_pool import,
use lazy __getattr__ to avoid triggering MySQL engine at import time
2. auth_service.py + auth_jwt.py: JWT sub field must be string
(PyJWT 2.12+ enforces RFC 7519), decode with int() conversion
3. session.py: lazy engine init — engine created on first access
instead of module import time, allows testing without MySQL
4. Tests: fix Column default assertions (SQLAlchemy defaults only
apply on DB INSERT), fix Request.url mock for Starlette
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 22:30:34 +08:00
Your Name
3ba85986ed
docs: update 194 skill files with cleaned group tags + metadata
...
All skill files group labels cleaned (no duplicates, no garbled text).
CMS developer renamed to frontend developer in AG group.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 22:12:57 +08:00
Your Name
3ecd3d75d4
docs: reports + research + team roster + tech-stack evaluation
...
Add implementation progress reports, review reports (CTO/quality/deploy),
session log, signoff table, team roster, collaboration charter,
tech-stack evaluation and inventory, research reports.
Remove obsolete multisync_server.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 22:12:29 +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
e5b0c2d4ef
ci: restore gitea workflows
2026-05-21 05:55:02 +08:00
Your Name
4cfed27bf7
docs: superpowers design specs + plans
2026-05-21 05:50:24 +08:00
Your Name
003ca96f07
tests: load_test + quick_load + test_api
2026-05-21 05:49:05 +08:00
Your Name
9e20898fd0
mcp: multisync_server + bridge + firefox
2026-05-21 05:48:19 +08:00
Your Name
cad49e6de1
docs: memory knowledge base + settings
2026-05-21 05:47:42 +08:00
Your Name
06f1e9ee07
docs: 194 team skills
2026-05-21 05:43:51 +08:00
Your Name
55e14805de
install.php: auto-detect site URL + simplified DB config + auto-configure process guardian
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-21 05:42:55 +08:00
Your Name
ae94101eb8
docs: add CLAUDE.md project memory for agent continuity
2026-05-20 17:29:02 +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
Your Name
05600232b7
feat: Nexus 6.0 Phase A+B — 心跳系统 + 3层守护 + Telegram告警 + install.php重写
...
Phase A (Python Backend):
- E1: WebSocket alert/recovery broadcast (server/api/websocket.py)
- E2: Agent heartbeat → Redis write + alert detection (server/api/agent.py)
- E3: Redis→MySQL 10min batch flush (server/background/heartbeat_flush.py)
- E4: load_settings_from_db() + threshold fields (server/config.py)
- E5: Python self-monitor 30s loop (server/background/self_monitor.py)
- E6: Telegram Bot push module (server/infrastructure/telegram/)
- E7: Server listing reads Redis for live status (server/api/servers.py)
- E8: /health endpoint for Shell health_monitor.sh (server/api/health.py)
- E9: Lifespan startup with background tasks (server/main.py)
Phase C (DevOps):
- D1: Supervisor config (deploy/nexus.conf)
- D2: Shell health_monitor.sh (deploy/health_monitor.sh)
Also:
- .gitignore: restored .env + SECRETS.md exclusion (never commit)
- Agent heartbeat: Redis buffer → frontend direct read → 10min → MySQL
- Alert detection: CPU/mem/disk > threshold → WebSocket + Telegram push
- Recovery detection: previously alerted metrics normal → auto-push recovery
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 17:02:45 +08:00
Your Name
98cb33c3d6
Add .env + SECRETS.md for test deployment (private repo)
...
Temporary: includes real credentials for deployment testing.
Will be removed from .gitignore when switching to formal repo.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 15:46:11 +08:00
Your Name
2cf7602573
Add SECRETS.md to .gitignore — prevent credential leak
...
SECRETS.md is a local-only file for storing database passwords,
API keys, and server credentials. It must never be committed to Git.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 15:37:47 +08:00
Your Name
669a62b17a
Update DEPLOY.md: production domain + clean sensitive values
...
- Domain: api.synaglobal.vip (强制 HTTPS)
- Website directory: /www/wwwroot/api.synaglobal.vip
- Supervisor config using .env (no hardcoded passwords)
- MySQL create DB command uses placeholder password
- Nginx config with 宝塔 SSL path and PHP-FPM socket
- All sensitive values removed from doc — safe for Git
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 15:36:47 +08:00
Your Name
99e23d7e78
Phase 1 complete: Repository implementations + Service layer + API routes + Deploy docs
...
- All 11 Repository Protocol interfaces (Admin, Setting, AuditLog, PushSchedule,
PushRetryJob, PasswordPreset + existing 5)
- All 11 async SQLAlchemy Repository implementations
- 4 Application Services (ServerService, ScriptService, AuthService, SyncService)
- FastAPI DI wiring in dependencies.py (repos → services)
- 6 API route modules (servers, auth, agent, scripts, settings/schedules/presets/audit/retries)
- Agent /api/exec endpoint for remote shell command execution
- Batch push engine with asyncio.Semaphore(10) concurrency control
- TOTP authentication + brute-force protection (5 failures / 15 min lockout)
- DB credential management with $DB_* variable substitution
- Ubuntu deployment guide (docs/DEPLOY.md) with dependency fix script
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 14:42:55 +08:00
Your Name
5ae8855894
Add CI/CD pipeline: Gitea Actions (test + lint + deploy)
...
CI (every push):
- pytest with coverage (>=50% gate)
- ruff lint check
- mypy type check (non-blocking)
CD (main branch only, after CI passes):
- SSH deploy to production server
- git pull + pip install + supervisorctl restart
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 14:25:31 +08:00
Your Name
b2617b4e31
Nexus v6.0.0: Initialize project structure with Clean Architecture
...
- Project brand: Nexus (configurable via settings.SYSTEM_NAME)
- Clean Architecture 4-layer directory structure:
server/domain/models/ — SQLAlchemy models
server/domain/repositories/ — Abstract interfaces (Protocol)
server/infrastructure/database/ — Async SQLAlchemy session + crypto
server/infrastructure/redis/ — Decoupled Redis client
server/infrastructure/ssh/ — Unified SSH connection pool
server/application/services/ — Business logic (TODO)
server/api/ — FastAPI routes (TODO)
- Config: Python 3.12+, PHP 8.2+, MySQL 8.4 LTS, Redis 7.0+
- Async SQLAlchemy (aiomysql) replacing sync pymysql
- Test framework: pytest + async fixtures + Playwright (conftest.py)
- MCP server address: 47.254.123.106
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-20 14:19:09 +08:00