mslxdff 0.1.212 → 0.1.213

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mslxdff",
3
- "version": "0.1.212",
3
+ "version": "0.1.213",
4
4
  "description": "测试项目,请勿使用。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2,13 +2,13 @@
2
2
  //
3
3
  // 为什么需要它:这条链路跨 3 台机器 + 1 道鉴权,坏了只会看到一句 `502 fetch failed`,
4
4
  // 完全无法定位是哪一跳断的。本模块**按阶段**记录,把断点直接指出来:
5
- // ① 定位本机组/组长 → ② 取组长 token(调组长 forward 要**组长的** token,见下)→
5
+ // ① 定位本机组/组长 → ② 取组长 token(调组长 forward 用组长自己的 token 恒可)→
6
6
  // ③ POST 组长 /v1/groups/relay/forward → ④ 判读回包(200 拿内容 / 401 鉴权 / 404 成员不存在 / 502·504 转发失败)
7
7
  //
8
- // ⚠ 鉴权事实(2026-10-19 实测):`authorized()` 比的是**接收方自己的 token**,
9
- // 而 `/v1/groups/relay/forward` 在路由层 requiresAuth=true ⇒ 要**组长 token**。
10
- // 普通组员只有自己的 token ⇒ 调不动组长 forward(这就是"组员经组长"从没通的原因)。
11
- // 本命令调用时用组长 token;若拿不到组长 token(如你只是组员且未持有),会明确报出这一步。
8
+ // 鉴权(2026-10-19 修正):forward 路由由 `requiresAuth:true` 改为鉴权下沉到 handler——
9
+ // 接受**组长 token 或本组成员 token**。旧实现只认组长 token,导致生产里成员经组长转发一律 401、
10
+ // 组员接力从未通过(deepseek-v4.1-flash-free.log 所有 relay-fail 均 401)。本命令仍用组长 token 调
11
+ // (组长 token 恒可),若拿不到则明确报出这一步。
12
12
  import { loadPeers, loadGroupsJoined, loadToken } from "../state.js";
13
13
  import { compatFetch, timeoutSignal } from "../compat.js";
14
14
 
@@ -87,8 +87,8 @@ export async function runGroupLinkTest({
87
87
  // 按阶段归类失败 —— 这是本命令存在的意义:一眼看出断在哪一跳
88
88
  if (res.status === 401) {
89
89
  return { status: "error", stage: "auth", httpStatus: 401, target, leaderUrl: lead.leaderUrl, group: groupName, ms,
90
- error: "组长拒了鉴权(401):调 /v1/groups/relay/forward 需要**组长的** token,本机没有",
91
- hint: "这是已知缺陷:组员中继链路的鉴权断了。修复 = 组长侧 forward 应接受成员 token(见 -group test 的 PR)" };
90
+ error: "组长拒了鉴权(401):本机持有的 token 既不是组长 token、也不在该组成员表里",
91
+ hint: "检查本机是否真的已加入该组(state.peers[leader].token / groupsJoined 是否过期);用 -addtogroup 重新入组。注:0.1.213+ 组长已接受成员 token,正常入组的节点不该再 401。" };
92
92
  }
93
93
  if (res.status === 404) {
94
94
  return { status: "error", stage: "target-missing", httpStatus: 404, target, leaderUrl: lead.leaderUrl, group: groupName, ms, error: txt.slice(0, 200), hint: "该目标不在组内(名称/url 对不上);用 -group list 核对" };
@@ -1,4 +1,4 @@
1
- import { clientIp, json, readBody, parseHops, errMsg } from "./helpers.js";
1
+ import { clientIp, json, readBody, parseHops, errMsg, authorized } from "./helpers.js";
2
2
  import { DEFAULT_MAX_HOPS } from "../peers.js";
3
3
  import { enqueueRelay, dequeueRelayForPoll, resolveRelay, subscribeStream, unsubscribeStream } from "./relay-queue.js";
4
4
  import { compatFetch } from "../compat.js";
@@ -148,11 +148,20 @@ export async function streamHandler({ req, res, groups, bus, logs }) {
148
148
  await new Promise(() => {});
149
149
  }
150
150
 
151
- export async function forwardHandler({ req, res, groups, bus, logs }) {
151
+ export async function forwardHandler({ req, res, groups, bus, logs, token }) {
152
152
  let body;
153
153
  try { body = await readBody(req); } catch { return json(res, 400, { error: "Invalid JSON body" }); }
154
154
  const groupName = body?.group || body?.name;
155
155
  const target = body?.target || body?.url;
156
+ // 鉴权(对齐 heartbeat/poll/result):接受**组长自己的 token**(本机 forward 自用)**或本组的任一成员 token**
157
+ // (成员经组长转发用的就是成员 token)。路由层 authorized() 只认组长那一个 token,故本路由 requiresAuth:false,
158
+ // 校验下沉到这里——否则成员中继一律 401(现网 2026-10-19:所有 relay-fail 均 status=401)。
159
+ const bearer = (/^Bearer (.+)$/.exec(req.headers["authorization"] || "") || [])[1] || "";
160
+ const authed = Boolean(bearer) && (authorized(req, token) || Boolean(groupName && groups?.membersForToken?.(groupName, bearer)));
161
+ if (!authed) {
162
+ res.setHeader("WWW-Authenticate", "Bearer");
163
+ return json(res, 401, { error: "Unauthorized" });
164
+ }
156
165
  const hops = parseHops(req.headers["x-mslxdff-hops"] || body?.hops);
157
166
  if (!groupName || !target) return json(res, 400, { error: "group and target required" });
158
167
  if (hops >= DEFAULT_MAX_HOPS) return json(res, 429, { error: "max hops exceeded" });
@@ -110,7 +110,11 @@ const ROUTES = [
110
110
  {
111
111
  method: "POST",
112
112
  path: "/v1/groups/relay/forward",
113
- requiresAuth: true,
113
+ // 鉴权下沉到 forwardHandler:接受**组长 token 或本组成员 token**(成员经组长转发的正是成员 token)。
114
+ // 路由层 authorized(req, token) 只认组长自己那一个 token ⇒ 用 requiresAuth:true 会把成员中继一律 401
115
+ // (现网 2026-10-19 实证:deepseek-v4.1-flash-free.log 里所有 relay-fail 都是 status=401,组员接力从未通过)。
116
+ // 同族 heartbeat/poll/result 同理走 requiresAuth:false + membersForToken 自校验。
117
+ requiresAuth: false,
114
118
  handler: forwardHandler,
115
119
  },
116
120
  {