@shgroup/dsh-serenity-hooks 1.24.5 → 1.24.7

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/lib/index.js CHANGED
@@ -6831,9 +6831,10 @@ function applyWirePatch(wire) {
6831
6831
  const pass = a.pass;
6832
6832
  const totp = a.totpSecret;
6833
6833
  const totpReset = a.totpReset === true;
6834
- const totpConfirm = a.totpConfirm;
6835
- if (typeof totp === "string" && totp !== "") {
6836
- if (typeof totpConfirm !== "string" || verifyTotpCode(totp, totpConfirm) === null) throw new Error(`Account "${a.user}" TOTP confirmation code invalid — enter the 6-digit code currently shown by the authenticator`);
6834
+ if (typeof totp === "string" && totp !== "") try {
6835
+ base32Decode(totp);
6836
+ } catch {
6837
+ throw new Error(`Account "${a.user}" TOTP secret is not valid base32`);
6837
6838
  }
6838
6839
  const nextTotp = totpReset ? void 0 : typeof totp === "string" && totp !== "" ? totp : existing?.totpSecret;
6839
6840
  const withTotp = {
@@ -7944,23 +7945,6 @@ function registerOpencodeSkills(ctx) {
7944
7945
  };
7945
7946
  ctx.skills.registerProvider(() => provider);
7946
7947
  }
7947
- //#endregion
7948
- //#region src/gateway-auth.ts
7949
- /**
7950
- * gateway-auth.ts — F1 双端口网关:认证域纯逻辑(v1.22.4 安全加固)
7951
- *
7952
- * 从 gateway.ts 拆分(S142 熵点治理,v1.22.8):认证纯逻辑独立成模块——
7953
- * 登录验证(scrypt)/ 会话 token(滑动 TTL + 吊销)/ 失败锁定(账号维度指数退避)/
7954
- * CSRF(双提交 + Origin 校验)/ cookie 解析 / 登录页 HTML。
7955
- * gateway.ts 保留 HTTP 装配(startGateway/registerGateway)并从本模块 import。
7956
- *
7957
- * 纯函数设计(可单测):无 socket/无 HTTP 依赖,全部导出可注入测试。
7958
- */
7959
- function verifyGatewayLogin(accounts, user, password) {
7960
- const account = accounts.find((a) => a.user === user);
7961
- if (!account) return false;
7962
- return verifyPassword(password, account.passHash);
7963
- }
7964
7948
  /** 内存会话表(重启即清空——用户决策) */
7965
7949
  const sessions = /* @__PURE__ */ new Map();
7966
7950
  /** 颁发会话 token(Hex 32 字节) */
@@ -8127,13 +8111,13 @@ button:active{background:#2563eb}
8127
8111
  ${csrf ? `<input type="hidden" name="csrf" value="${csrf}">` : ""}
8128
8112
  <label for="f-user">用户名</label>
8129
8113
  <input id="f-user" type="text" name="user" placeholder="用户名" autocomplete="username" autocapitalize="none" autocorrect="off" required autofocus enterkeyhint="next">
8130
- <label for="f-pass">密码</label>
8131
- <input id="f-pass" type="password" name="password" placeholder="密码" autocomplete="current-password" required enterkeyhint="next">
8114
+ <label for="f-pass">密码(或下方验证码,二选一)</label>
8115
+ <input id="f-pass" type="password" name="password" placeholder="密码" autocomplete="current-password" enterkeyhint="next">
8132
8116
  <label for="f-code">验证码(已绑定 Authenticator 时填写)</label>
8133
8117
  <input id="f-code" type="text" name="code" placeholder="6 位验证码" inputmode="numeric" pattern="[0-9]{6}" maxlength="6" autocomplete="one-time-code" enterkeyhint="go">
8134
8118
  <button type="submit">登录</button>
8135
8119
  <div class="error">${extra}</div>
8136
- <p class="hint">未绑定验证器的账号只需用户名 + 密码</p>
8120
+ <p class="hint">已绑定验证器的账号:密码 或 6 位验证码任一即可登录(二选一)</p>
8137
8121
  </form>
8138
8122
  <p class="foot">Serenity ACC · dsh-serenity-hooks</p>
8139
8123
  </div></body></html>`;
@@ -8488,17 +8472,16 @@ function startGateway(config, getAccounts) {
8488
8472
  res.end(loginPageHtml(`账号已锁定,请 ${Math.ceil(lockedRemaining / 6e4)} 分钟后再试`));
8489
8473
  return;
8490
8474
  }
8491
- const accounts = getAccounts();
8492
- const account = accounts.find((a) => a.user === user);
8493
- const passOk = account !== void 0 && verifyGatewayLogin(accounts, user, password);
8494
- let totpOk = true;
8495
- if (totpEnabled && passOk && account !== void 0 && typeof account.totpSecret === "string" && account.totpSecret !== "") {
8475
+ const account = getAccounts().find((a) => a.user === user);
8476
+ const passOk = account !== void 0 && password !== "" && verifyPassword(password, account.passHash);
8477
+ let totpOk = false;
8478
+ if (totpEnabled && account !== void 0 && typeof account.totpSecret === "string" && account.totpSecret !== "") {
8496
8479
  const hit = verifyTotpCode(account.totpSecret, code);
8497
8480
  totpOk = hit !== null;
8498
8481
  if (totpOk && hit !== null && lastTotpCounter.get(account.id) === hit) totpOk = false;
8499
8482
  if (totpOk && hit !== null) lastTotpCounter.set(account.id, hit);
8500
8483
  }
8501
- if (passOk && totpOk) {
8484
+ if (passOk || totpOk) {
8502
8485
  resetFailState(user);
8503
8486
  const token = issueToken(user);
8504
8487
  res.writeHead(302, {
@@ -8506,12 +8489,12 @@ function startGateway(config, getAccounts) {
8506
8489
  "set-cookie": `${cookieName}=${token}; HttpOnly; SameSite=Strict; Path=/${cookieSecure ? "; Secure" : ""}`
8507
8490
  });
8508
8491
  res.end();
8509
- console.log(`[serenity-hooks] 登录成功: user=${user} ip=${remote}`);
8492
+ console.log(`[serenity-hooks] 登录成功: user=${user} ip=${remote} via=${passOk ? "password" : "totp"}`);
8510
8493
  return;
8511
8494
  }
8512
8495
  const lockMs = recordLoginFailure(user);
8513
- console.warn(`[serenity-hooks] 登录失败: user=${user} ip=${remote} reason=${!passOk ? "bad-password" : "bad-totp"}${lockMs > 0 ? ` 锁定=${Math.ceil(lockMs / 6e4)}min` : ""}`);
8514
- const msg = lockMs > 0 ? `尝试过多,账号已锁定 ${Math.ceil(lockMs / 6e4)} 分钟` : passOk ? "验证码错误" : "用户名或密码错误";
8496
+ console.warn(`[serenity-hooks] 登录失败: user=${user} ip=${remote}${lockMs > 0 ? ` 锁定=${Math.ceil(lockMs / 6e4)}min` : ""}`);
8497
+ const msg = lockMs > 0 ? `尝试过多,账号已锁定 ${Math.ceil(lockMs / 6e4)} 分钟` : "用户名、密码或验证码错误";
8515
8498
  res.writeHead(401, { "content-type": "text/html; charset=utf-8" });
8516
8499
  res.end(loginPageHtml(msg));
8517
8500
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.24.5",
3
+ "version": "1.24.7",
4
4
  "description": "宁静号 ACC harness — Native Cordis 插件(DeepSeek Harness 运行时)。真实 DSH 工具注册(cc_fs/session/acc_msm 等 9 工具)+ 拦截缝机械约束(safe-mode/路径守卫/会话落盘)+ 系统提示词注入(ACC/CCE/Constraints/SKILL/Session 五块)。适配 DSH 公开版(deepseek-ai/deepseek-harness 0.1.0-rc)。",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -55,9 +55,9 @@
55
55
  "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.5",
56
56
  "@deepseek-ai/dsh-llm": "^0.1.0-rc.5",
57
57
  "@deepseek-ai/dsh-session": "^0.1.0-rc.5",
58
+ "@deepseek-ai/dsh-session-title": "^0.1.0-rc.5",
58
59
  "@deepseek-ai/dsh-shell": "^0.1.0-rc.5",
59
60
  "@deepseek-ai/dsh-shell-env": "^0.1.0-rc.5",
60
- "@deepseek-ai/dsh-session-title": "^0.1.0-rc.5",
61
61
  "@deepseek-ai/dsh-skill": "^0.1.0-rc.5",
62
62
  "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.5",
63
63
  "@deepseek-ai/dsh-tools": "^0.1.0-rc.5",
@@ -86,11 +86,18 @@
86
86
  },
87
87
  "devDependencies": {
88
88
  "@types/node": "^20.0.0",
89
+ "@types/qrcode-generator": "^1.0.6",
89
90
  "@types/react": "^18.2.0",
91
+ "qrcode-generator": "^2.0.4",
90
92
  "react": "^18.2.0",
91
93
  "tsdown": "^0.22.14",
92
94
  "typescript": "^5.4.0",
93
95
  "unrun": "^0.3.1",
94
96
  "vitest": "^1.6.0"
97
+ },
98
+ "pnpm": {
99
+ "onlyBuiltDependencies": [
100
+ "esbuild"
101
+ ]
95
102
  }
96
103
  }