docs(v4): batch report for items 24/25 + notes entries as authored
This commit is contained in:
@@ -157,3 +157,16 @@ v2 上线后现网四台核心版本列全空。已查实根因:节点 sing-bo
|
|||||||
约束:①手动点部署(/api/nodes/:id/deploy)保持立即执行,不进合并窗口;②删除/移除流程语义不变,窗口内节点被删除时待发 apply 必须正确作废、不许复活;③面板在窗口内重启不能把节点卡在未下发状态(待发状态可落盘或启动对账补发,二选一并在报告注明);④凭据重置等其他触发 RebuildNode 的路径按同一合并口径(按节点合并即可)。
|
约束:①手动点部署(/api/nodes/:id/deploy)保持立即执行,不进合并窗口;②删除/移除流程语义不变,窗口内节点被删除时待发 apply 必须正确作废、不许复活;③面板在窗口内重启不能把节点卡在未下发状态(待发状态可落盘或启动对账补发,二选一并在报告注明);④凭据重置等其他触发 RebuildNode 的路径按同一合并口径(按节点合并即可)。
|
||||||
验收:同一节点快速连加 5 个客户,最终只执行 1 次 apply_resource 且 5 人齐全;窗口内删节点不复活;手动部署仍立即;既有测试与金标准不回归。
|
验收:同一节点快速连加 5 个客户,最终只执行 1 次 apply_resource 且 5 人齐全;窗口内删节点不复活;手动部署仍立即;既有测试与金标准不回归。
|
||||||
口径补充(同日用户问答确认):合并窗口为固定窗口(从该节点第一次待发变更起算,不滑动延长);代价=新加入用户最多晚约 10 秒 + 一次 apply 时间才能连通该节点,窗口内老配置照常服务、老用户无感。此代价用户已知悉并接受。
|
口径补充(同日用户问答确认):合并窗口为固定窗口(从该节点第一次待发变更起算,不滑动延长);代价=新加入用户最多晚约 10 秒 + 一次 apply 时间才能连通该节点,窗口内老配置照常服务、老用户无感。此代价用户已知悉并接受。
|
||||||
|
|
||||||
|
## 24. 列表页勾选是空壳:补齐批量操作(2026-10-21 20:55 用户实测指出)
|
||||||
|
现象(用户附 3x-ui 对照图):3x-ui 勾选行后顶部出现「已选 N 项 + 删除」,可一键删除全部选中;amo 三个列表页(节点管理/入站&出站/用户订阅)的行勾选框与表头全选都在,全选也能勾上,但选中后界面毫无变化、无任何批量动作可用。
|
||||||
|
已核代码(public/app.js):data-row-check 渲染在 servers/customers/nodes 三页;唯一的 data-check-all 处理只是把全选状态镜像到每行 checkbox(约 1426 行);row-check 本身无 change 处理、全站无任何代码读取勾选集合(grep 无 已选/bulk 字样)。
|
||||||
|
修法:每页维护选中集合,选中 ≥1 时在工具条区显示批量操作条「已选 N 项」+ 动作:批量删除、批量启用、批量停用(按各页既有单项语义:节点 启用=部署/停用=移除、客户与服务器走各自启停);删除一次确认弹窗说清数量与不可逆;逐项执行既有单项接口/端点,守卫规则与单项完全一致(如服务器有未删节点拒绝、节点有运行中任务拒绝),结果汇总回报成功/失败数与失败原因;操作后刷新列表并清空选择。切页/重渲染后选择状态的去留施工时定并在报告注明。
|
||||||
|
范围补充(同日用户强调):**所有页面都要改**——凡是带行勾选框/全选框的列表页全部补齐批量操作,不许只做一页;施工时以 data-row-check / data-check-all 在 public/app.js 的全部出现处逐一排查销账(当前已知:节点管理、入站&出站、用户订阅三页),报告中逐页列明。
|
||||||
|
|
||||||
|
## 25. agent 鉴权令牌化:压掉待机 CPU 的 scrypt 主项(2026-10-21 21:01 用户拍板,与第 24 条同批)
|
||||||
|
背景(v3 第 22 条归因):面板待机 CPU 的主项是 agent 每次请求都跑一次 scrypt VerifySecret 验 KeyHash(沙箱单次约 88ms、20 台模拟稳态 32.3%);二开版 3x-ui 无此问题——慢哈希只用于人类登录,agent 通信走 API 令牌比对(已查其代码证实)。
|
||||||
|
修法(用户原话口径:往令牌制靠):agent 首次(或令牌失效时)仍走指纹定位 + scrypt 验一次身份,面板随即签发一张短期令牌(随机值,面板只存其快速哈希如 SHA-256 + 过期时间,绑定该 agent 身份);agent 后续请求带令牌,面板只做快速哈希比对,不再跑 scrypt。令牌过期/不符自动回退 scrypt 路径并重签。吊销语义不降级:删除/吊销 agent、重置其密钥时令牌一并失效。
|
||||||
|
兼容:旧 agent(不支持令牌)继续走 scrypt 路径可用、只是不提速;新 agent 对旧面板自动回退。鉴权强度不许降级:令牌随机强度与现有密钥同级、比对用常时比较、传输通道沿用现状(现制下密钥本就逐请求在同一通道上传输,令牌不弱于此)。
|
||||||
|
验收:①稳态 CPU 按 v3 同法复测(20 台 agent 模拟、无界面请求)——目标个位数 %,报告给改动前后同口径数字;②功能回归:agent 注册/心跳/任务拉取/用量上报全链路冒烟、面板或 agent 单侧重启后自动恢复(重签或凭令牌续用)、吊销后令牌立即失效、旧 agent 混跑可用;③全量测试与金标准不回归。
|
||||||
|
部署提示:面板与 agent 双侧都改;面板先行兼容旧 agent,agent 逐台换新后逐台提速。
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# amo v4 批报告(第 24、25 条)
|
||||||
|
|
||||||
|
- 基线:`18074da`(开工核对一致)
|
||||||
|
- 提交:`408b03e`(第 25 条)、`1e7ccd3`(第 24 条),文档收尾提交随本报告
|
||||||
|
- 范围口径:第 0 条 Go 单一真源——只改 `panel-go/`、`agent-go/`、共用前端 `public/`,Node 零改动
|
||||||
|
- 状态:**第 25 条完成、第 24 条完成**(完成状态只在此报告标注,NEXT-ROUND-NOTES 原文未删改,随本批一并提交)
|
||||||
|
- 未部署、未推 Gitea
|
||||||
|
|
||||||
|
## 第 25 条 agent 鉴权令牌化(提交 408b03e)
|
||||||
|
|
||||||
|
### 设计
|
||||||
|
|
||||||
|
- **签发**:agent 请求先按原路径鉴权——指纹(KeyFingerprint)定位记录后 `VerifySecret` 跑 scrypt——通过后才签发会话令牌。令牌为 `RandomToken(40)`,与 agent 密钥同一强度;每次密钥路径鉴权成功都会**轮换**签发新令牌(旧令牌即刻失效)。
|
||||||
|
- **存储(面板)**:agent 记录只存令牌的 SHA-256 哈希(`SessionTokenHash`,复用 `TokenFingerprint`)与过期时间(`SessionTokenExpiresAt`),明文不落库。两字段 omitempty,旧数据文件零迁移。
|
||||||
|
- **有效期**:**24 小时**。经响应头 `X-Agent-Session-Token` / `X-Agent-Session-Token-Expires` 下发。
|
||||||
|
- **校验**:后续请求带令牌作 bearer,面板走 `agentBySessionToken()`——`store.View` 内扫描、hex 解码后 `subtle.ConstantTimeCompare` 常时比对、校验记录 active 与过期时间。不再跑 scrypt。
|
||||||
|
- **回退**:令牌过期/哈希不符/记录吊销 → 该请求自动回退密钥路径(scrypt),成功后重签新令牌。agent 侧:收到 401 且本次用的是令牌时,清掉本地令牌、以密钥重试恰好一次(防循环);面板未签发(旧面板)时不写令牌文件、逐请求带密钥,行为与旧版一致。
|
||||||
|
- **吊销语义**:`(*Agent).Revoke()` 统一收口——置 revoked 并清空令牌两字段。三处调用:重新 enroll 时吊销同服务器旧 agent、`delete_server`、`force_forget_server`。全仓 `"revoked"` 字面量只剩 Revoke 内部一处,不存在遗漏的失效路径(agent 密钥本身从不在原记录上重置,重置只经重新 enroll 建新记录 + 吊销旧记录)。
|
||||||
|
- **存储(agent)**:`session-token.json` 放在既有状态目录(默认 `/etc/nexusgate/agent`,可经 `NG_SESSION_TOKEN_FILE` 覆盖),权限 0600、临时文件 + rename 原子落盘,与 keys.json 同规格。读取时带 1 分钟过期余量,过期直接用密钥。
|
||||||
|
- **强度不降级**:签发必须在 scrypt 验证通过之后;库里始终只有哈希(密钥哈希 + 令牌哈希);令牌绑定单条 agent 记录。
|
||||||
|
- **兼容**:旧 agent 不带令牌 → 继续逐请求 scrypt,功能不受影响;新 agent 连旧面板 → 无签发头,自动回退。agent 版本号保持 `0.6.8`。线格式不变,差异已登记 `agent-go/PARITY.md` 第 0 条。
|
||||||
|
|
||||||
|
### 改动点
|
||||||
|
|
||||||
|
面板(panel-go):
|
||||||
|
- `types.go`:`Agent` 新增 `SessionTokenHash` / `SessionTokenExpiresAt`(omitempty);新增 `(*Agent).Revoke()`。
|
||||||
|
- `handlers.go`:`AgentSessionTokenTTL = 24h`;`agentBySessionToken()`、`issueAgentSessionToken()`(Transaction 落盘、记录已非 active 则不签发)、`authenticateAgent()`(令牌路径 → 密钥路径;候选记录先从 View 拷出、scrypt 在锁外执行、成功后签发);`FindAgentByBearer` 保留为兼容 wrapper;handleAgent 在签发时设置两响应头;三处吊销改走 `Revoke()`。
|
||||||
|
- 新增 `agenttoken_test.go`:7 例(签发且只存哈希、篡改 KeyHash 后令牌仍可鉴权即令牌路径不跑 scrypt、过期被拒 + 密钥重签轮换、哈希不符被拒 + 重签、吊销后令牌与密钥双拒、令牌绑定本记录、纯密钥请求逐次轮换可用)。
|
||||||
|
|
||||||
|
agent(agent-go):
|
||||||
|
- `main.go`:`SessionTokenFile` 配置(env `NG_SESSION_TOKEN_FILE`);`agentSessionToken` + 懒加载状态(mutex);`currentSessionToken()`(1 分钟余量)、`storeSessionToken()`(0600 + rename)、`clearSessionToken()`;`request()` 拆为 `requestAttempt`(bearer 优先令牌、每响应检查签发头并落盘、401 用令牌时清令牌以密钥重试一次)。
|
||||||
|
- 新增 `sessiontoken_test.go`:5 例(fakePanel:捕获/落盘 0600/冷启重载/复用、401 回退 + 重签、旧面板无头时纯密钥、客户端已过期直接用密钥、令牌与密钥双拒时报错且恰好两次尝试)。
|
||||||
|
|
||||||
|
### 验收 ①:稳态 CPU(按 v3 同一测法复测)
|
||||||
|
|
||||||
|
测法:20 服务器种子(20 台 enrolled agent、40 节点、40 客户、约 160 绑定,数据文件 196KB,与现网 225KB 同量级);令牌感知驱动按现网节奏模拟 20 台 agent(poll 8s / heartbeat 30s / usage 60s、空 samples、错峰),无界面请求;预热 15s 后取 60s 窗口,按 `/proc/<pid>/stat` 的 utime+stime 差折算(100 ticks = 1 秒 CPU),同一台架、同一脚本、面板进程为脚本直系子进程采样。
|
||||||
|
|
||||||
|
| 二进制 | 稳态 CPU(单核 %) | 驱动侧证据 |
|
||||||
|
|---|---|---|
|
||||||
|
| 旧 `18074da`(本机同台架实测) | **28.98%** | 未签发令牌;请求延迟 74–254ms |
|
||||||
|
| 新 v4(HEAD) | **1.52%** | 恰好签发 20 个令牌、20/20 agent 转令牌路径;请求延迟 5–8ms;失败 0 |
|
||||||
|
|
||||||
|
- v3 报告的旧版数字为 32.31%(其台架种子构成略有差异),本批同台架复跑为 28.98%,量级一致;新版 **1
|
||||||
|
...[truncated 6135 chars]
|
||||||
Reference in New Issue
Block a user