🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

多租户网关 dusbin/dsh-multi-tenant

DeepSeek Harnessv0.9.0-alpha.1
dusbin66 天前有提交已提供中文文档扫描:含敏感能力

为 DSH 加上登录、租户隔离与用量配额管控

28.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/18 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查有告警:npm 同名包「dsh-multi-tenant」归属 guomonth/dsh-multi-tenant,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dusbin/dsh-multi-tenant
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/09/25·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 66 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查⚠ 装前注意

npm 同名包「dsh-multi-tenant」归属 guomonth/dsh-multi-tenant,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-multi-tenant @ 0.9.0-alpha.1
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/24 11:31:01

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 6 处,展示前 6 条)
  • 发起网络请求
    lib/client.js:199
    return fetch(path, Object.assign({ credentials: 'include' }, options || {}));
  • 写入本地文件
    lib/host/db.js:139
    mkdirSync(path.dirname(dbPath), { recursive: true, mode: 0o700 });
  • 发起网络请求
    lib/host/gateway.js:289
    const upstream = http.request(options, (upRes) => {
  • 发起网络请求
    lib/host/gateway.js:315
    const upstream = http.request(options, (upRes) => {
  • 发起网络请求
    lib/host/gateway.js:374
    const upstream = http.request(options, (upRes) => {
  • 发起网络请求
    lib/host/gateway.js:450
    const upstream = http.request(options);
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 登录鉴权
  • 租户隔离
  • 用量配额管控

dsh 支持多租户插件

README

由 DeepSeek 最新模型翻译生成
dsh-multi-tenant DeepSeek Harness 多租户插件:把 DSH 从“本地单用户开发工具”扩展为多租户、多角色、可登录、可计量、可审计的服务形态。 状态:M7 完成(全部里程碑)——M1-M6 已交付,M7 硬化/部署文档/打包验证完成方案文档:docs/方案.md(v2.0 定稿,含用户决策 D1–D6);调研报告:docs/research/01/02/03 功能路线 | 里程碑 | 内容 | 状态 | | M1 | 工程骨架 + 认证反代网关(HTTP/WS 代理、cookie 会话)+ bootstrap 平台管理员 + DB 层 | ✅ 完成 | | M2 | 多租户 + RBAC:/mt 管理通道、租户/用户/角色管理 API、会话归属前缀强制、管理控制台 UI | ✅ 完成 | | M3 | 用量统计(token 四桶)+ 配额(同步检查 + 周期累计)+ 用量/配额 UI | ✅ 完成 | | M4 | 审计日志(查询/CSV 导出/登录失败留痕)+ 审计员视图 + 强制下线 | ✅ 完成 | | M5 | LDAP 登录(ldapts,目录绑定验证 + 自动建号) | ✅ 完成 | | M6 | SSO/OIDC 登录(openid-client,Authorization Code + PKCE) | ✅ 完成 |
展开完整文档(README 剩余 1 节)
dsh-multi-tenant

DeepSeek Harness 多租户插件:把 DSH 从“本地单用户开发工具”扩展为多租户、多角色、可登录、可计量、可审计的服务形态。

状态:M7 完成(全部里程碑)——M1-M6 已交付,M7 硬化/部署文档/打包验证完成方案文档:docs/方案.md(v2.0 定稿,含用户决策 D1–D6);调研报告:docs/research/01/02/03

功能路线

| 里程碑 | 内容 | 状态 |
| M1 | 工程骨架 + 认证反代网关(HTTP/WS 代理、cookie 会话)+ bootstrap 平台管理员 + DB 层 | ✅ 完成 |
| M2 | 多租户 + RBAC:/mt 管理通道、租户/用户/角色管理 API、会话归属前缀强制、管理控制台 UI | ✅ 完成 |
| M3 | 用量统计(token 四桶)+ 配额(同步检查 + 周期累计)+ 用量/配额 UI | ✅ 完成 |
| M4 | 审计日志(查询/CSV 导出/登录失败留痕)+ 审计员视图 + 强制下线 | ✅ 完成 |
| M5 | LDAP 登录(ldapts,目录绑定验证 + 自动建号) | ✅ 完成 |
| M6 | SSO/OIDC 登录(openid-client,Authorization Code + PKCE) | ✅ 完成 |
| M7 | 硬化 + 交付:账号自动锁定、安全响应头、部署文档、真实 dsh plugin add 安装验证 | ✅ 完成 |

架构一句话

认证反代网关:DSH 本体保持 loopback 绑定,插件内嵌网关监听对外端口,做登录/会话校验后把 HTTP 与 WebSocket 全量代理到 DSH——/api 信任栅栏天然放行 loopback Host,DSH 零改源码。

浏览器 → 网关(:3090) [登录/RBAC/配额/归属强制] → 127.0.0.1:(原样运行)

安装

方式 A:dsh plugin(发布包/本地目录)

dsh plugin --profile web add dsh-multi-tenant # 已发布包
dsh plugin --profile web add /path/to/dsh-multi-tenant # 本地目录(开发验证)

包声明了 dsh.bundle,dsh plugin 会自动把它加入 profile 的 bundles 并应用 cordis.patch.yml(默认网关 0.0.0.0:3090),零手动配置即可启动。
已实测:dsh plugin add → bundles 自动接入 → 启动后网关按默认配置生效。

方式 B:源码开发(本仓库)

1. 软链到 profile node_modules
ln -sfn /Users/robinddu/Desktop/workspace/robinddu/dsh-multi-tenant \
~/.dsh/profiles/web/node_modules/dsh-multi-tenant

2. 在 profile 的 cordis.patch.yml 里插入一行

~/.dsh/profiles/web/cordis.patch.yml
- insert:
- id: multi-tenant
name: 'dsh-multi-tenant'
config:
gateway:
enabled: true
host: '0.0.0.0'
port: 3090

源码改动后重启 profile 即可(或把 name 里的包名换成 ...dsh-multi-tenant/lib/index.js?v=N 用 ?v= 破除 ESM 缓存)。

配置项

| 键 | 默认 | 说明 |
| gateway.enabled | true | 是否启动认证网关 |
| gateway.host / gateway.port | 0.0.0.0 / 3090 | 网关监听地址(对外入口) |
| cookie.name | mt_session | 会话 Cookie 名 |
| cookie.maxAgeDays | 14 | 会话有效期 |
| cookie.secure | false | 公网 HTTPS 部署置 true(Cookie 加 Secure) |
| db.path | $DSH_HOME/multi-tenant/mt.db | SQLite 数据文件(node:sqlite) |
| auth.local.enabled | true | 邮箱密码登录 |
| auth.local.maxFailedAttempts | 5 | 防爆破:窗口内失败上限 |
| auth.local.lockWindowMs | 900000 | 防爆破窗口(15 分钟) |
| auth.bootstrap.enabled | true | 首启 bootstrap 平台管理员 |

认证 API(网关直答)

| 端点 | 说明 |
| GET /api/auth/me | 当前用户;未初始化返回 {ok:true,user:null,bootstrapRequired:true} |
| POST /api/auth/login | {username, password} → 200 + Set-Cookie;401/423/429 |
| POST /api/auth/logout | 登出(幂等) |
| POST /api/auth/bootstrap | 首次使用创建平台管理员(201;已初始化 409) |

访问策略(v1)

- 除公开路径外一切请求(任意方法,含 /api、/mt)必须登录,否则 401
- 公开路径:/api/auth/(认证端点)、GET/HEAD 静态资源(/、/assets/、/plugins/、favicon)
- /api/events.mux、/api/events.host 的 WebSocket upgrade:必须登录,否则拒绝握手
- 会话归属强制:session.create 的 sessionId 被网关改写为归属前缀 u--t--s-(伪造他人前缀无效);其他会话作用域请求校验前缀,越权返回 403 并记审计
- 直连 DSH 端口(127.0.0.1:)保持开发者模式开放;生产请只暴露网关端口

角色与权限(M2)

| 角色 | 权限 |
| 平台管理员(system) | 租户生命周期(建/停/列)、任意租户用户管理、全局审计(不占租户配额) |
| 租户管理员(admin) | 本租户用户管理(建/启停/改角色/重置密码/删除)、配额设置、审计查看(自动含审计权限,D4) |
| 审计员(auditor) | 本租户只读统计 + 审计日志 |
| 使用者(user) | 登录、使用会话、查看个人用量 |

租户间完全隔离:会话、用户、用量、审计、配额互不可见(网关 + 服务层双重强制)。

管理 API(/mt 通道)

客户端经 ctx.connection.rpc.call('/mt', endpoint, payload) 调用(响应为 RPC 信封)。

| 端点 | 说明 | 权限 |
| me | 当前用户 + 租户信息 | 任意已登录 |
| auth.changePassword | 修改本人密码 | 任意已登录 |
| tenant.list / tenant.create / tenant.setStatus | 租户管理 | system |
| user.list | 用户列表(本租户) | admin+ |
| user.create / user.setStatus / user.setRole / user.setPassword / user.delete | 用户管理 | admin+(租户内) |
| usage.summary / usage.sessions | 用量统计(汇总/按用户/会话明细,period: day/month/all) | auditor+(租户内),user 仅本人 |
| quota.view | 配额视图(本人/指定用户/指定租户) | 任意已登录(他人需 admin+) |
| quota.set / quota.clear | 设置/清除配额(scope: platform/tenant/user,period: daily/monthly/total) | admin+(platform 需 system) |
| audit.list / audit.export | 审计日志查询/CSV 导出(可按 action/result 过滤) | auditor+(租户内只读),system 全局 |
| user.revokeSessions | 强制下线(吊销该用户全部会话) | admin+(租户内),本人亦可 |

管理控制台 UI(浏览器):设置面板新增页签 个人中心 / 用户管理 / 租户管理 / 用量统计 / 配额 / 审计日志(按角色可见);侧边栏设置按钮上方常驻当前用户芯片(用户名 + 角色/租户 + 退出登录,收起态为圆形退出图标)。

用量统计与配额(M3)

- 计量:tokenUsage 会话投影(web profile 已组合 dsh-token-meter)四桶 {uncachedInput, output, cacheRead, cacheWrite};插件按会话前缀归属,差分记账到 usage_records(首见只建基线,恢复的旧会话不重复计费;压缩/失败请求由投影正确处理)
- 配额:平台/租户/用户 三级 × 日/月/累计 周期,任一适用限额达到即拒绝新的 session.prompt/subagent.prompt(网关前置检查,返回 quota-exhausted 业务错误);周期窗口自动滚动
- 视图:用量仪表盘(今日/本月/累计 + 按用户 + 会话明细)、个人配额剩余、配额管理

审计日志(M4)

- 留痕:登录(成功/失败原因)、登出、bootstrap、改密、租户/用户/配额全部管理操作、会话越权(session.denied)、配额拒绝(quota.denied)——audit_logs 只追加不可改删
- 查询:audit.list(action/result/用户/时间过滤 + 分页);导出:audit.export(CSV,UTF-8 BOM)
- 审计员角色:租户内只读查询与导出;使用者无审计权限;平台管理员全局可查
- 强制下线:user.revokeSessions 吊销指定用户全部会话(启停账号时同样即时失效会话)

LDAP 登录(M5)

/api/auth/login 支持 method: 'local' | 'ldap'(省略时自动:有本地账号走本地,否则尝试 LDAP);登录页按 me 返回的 methods 渲染按钮。

| 配置键(auth.ldap.) | 默认 | 说明 |
| enabled | false | 启用 LDAP |
| url | — | ldap://host:389 或 ldaps://host:636 |
| bindDn / bindPassword | 空 | 服务账号(空 = 匿名搜索) |
| baseDn | — | 用户搜索基 |
| userFilter | (uid={{username}}) | 搜索过滤器,{{username}} 自动转义 |
| attributes | {username: 'uid', email: 'mail', displayName: 'cn'} | LDAP 属性 → 本地字段映射 |
| autoProvision | true | 首次登录自动建号(按 ldap_dn 关联) |
| defaultTenantId | null | 自动建号归属租户(null = 平台域) |
| defaultRole | user | 自动建号默认角色 |
| timeoutMs | 5000 | 目录操作超时 |

- 认证流程:服务账号 bind → 按过滤器搜索用户 → 以用户 DN + 密码绑定(标准 LDAP 密码校验)
- 目录凭据错误 → invalid-credentials;目录不可达 → ldap-unavailable(不泄漏目录细节)
- LDAP 登录同样受防爆破与审计;禁用/锁定账号即时生效

SSO / OIDC 登录(M6)登录页按 me 返回的 methods 渲染 SSO 登录 按钮(含 oidc 时):点击 → /api/auth/oidc/start 返回 IdP 授权 URL → IdP 登录 → 302 回 /api/auth/oidc/callback → 网关换令牌(PKCE)并校验 ID token(签名/iss/aud/exp)→ Set-Cookie + 302 回原目标。

| 配置键(auth.oidc.) | 默认 | 说明 |
| enabled | false | 启用 OIDC |
| issuerUrl | — | OIDC 发现端点(自动获取 JWKS/端点) |
| clientId / clientSecret | — | 客户端凭据 |
| publicBaseUrl | 空 | 对外基址(redirect_uri 用;空 = 取请求 Host / X-Forwarded-Proto) |
| redirectPath | /api/auth/oidc/callback | 回调路径 |
| scopes | openid profile email | 请求的 scope |
| claimsMapping | {subject:'sub', username:'preferred_username', email:'email'} | ID token 声明 → 本地字段 |
| autoProvision | true | 首次登录自动建号(按 oidc_sub 关联) |
| defaultTenantId / defaultRole | null / user | 自动建号归属 |

- 认证流程:Authorization Code + PKCE(state 内存 TTL);openid-client 校验 ID token 签名与 issuer/audience
- state 失效/换令牌失败/无 subject → 明确错误码,302 回 /?mt_error= 并记审计
- SSO 登录同样受禁用/锁定账号即时校验

管理员逃生通道 / 系统重置 / 数据备份(逃生与运维)

主机侧维护 CLI(逃生通道,免登录)

node scripts/maintenance.mjs status # 系统概览
node scripts/maintenance.mjs reset-admin-password --username --password # 重置密码(免登录)
node scripts/maintenance.mjs create-system-admin --username --password # 无可用管理员时创建
node scripts/maintenance.mjs unlock-user --username # 解锁账号
node scripts/maintenance.mjs reset-system [--keep-usage] # 重置多租户系统
node scripts/maintenance.mjs export --out backup.json # 导出全量数据
node scripts/maintenance.mjs import --in backup.json --replace # 导入恢复(覆盖)

- 需要本机文件系统访问(与 DSH 同信任级);--db 缺省 $DSH_HOME/multi-tenant/mt.db
- 导出为版本化 JSON(含密码哈希——视为敏感凭据),覆盖 tenants/users/quotas/用量/审计

UI 逃生通道(环回受限)

- 当无任何可用平台管理员(全部禁用/锁定/删除)时,登录页显示"管理员恢复"表单
- POST /api/auth/recovery 仅允许环回来源(本机/网关本地)——远程无法触发
- 恢复 = 新建平台管理员(复用会话机制)

控制台导出

- /mt data.export(仅平台管理员):全量备份下载(与 CLI export 同格式)
- 导入仅 CLI(覆盖式恢复,防止误操作)

入口与隔离边界(重要)

- 多租户隔离只在网关入口生效:登录/配额/会话归属/工作区与会话列表过滤/WS 帧过滤均由网关(默认 http://:3090)强制执行
- 租户用户(使用者/审计员/租户管理员)一律从网关访问;直连 DSH 端口(127.0.0.1:3080)是无隔离的开发者通道(仅建议平台管理员本机使用),从 3080 进入会看到全部工作区/会话(因为不经过任何过滤)
- 插件安装前的遗留会话/工作区(session- 无归属前缀)只对平台管理员可见;租户用户看不到,直到他们经网关创建自己的会话
- 生产部署请只暴露网关端口(见 docs/部署.md)

租户可见性(工作区 / 会话)

- 平台管理员:查看所有工作区与会话/任务
- 租户管理员 / 审计员:仅本租户(t- 前缀归属)
- 使用者:仅本人(u--t--s- 精确前缀)
- 无归属前缀的遗留会话:仅平台管理员可见

实现:
- 列表端点(session.list / session.search / workspace.list)响应按会话前缀过滤(工作区按可见会话裁剪,无可视会话则隐藏)
- WS 下行帧级过滤(events.mux / events.host):host/workspace-changed、 host/session-、archived-sessions-changed 与带 sessionId 的 mux 帧按可见性裁剪/丢弃(含与 101 同段到达的 upHead 帧),杜绝推送帧泄漏

开发

npm test # node:test 单元 + 集成测试(13 个用例,含 HTTP/WS 代理)
node --check lib/client.js # client bundle 语法校验

M1 冒烟验证(真实 DSH profile)

export DSH_HOME=bash
dsh plugin --profile web-mt install # 初始化测试 profile
补 dsh.profile.bundles 为 [@deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app] 软链插件 + cordis.patch.yml 插入行(网关 127.0.0.1:3990)
dsh --profile web-mt --port 3980 --no-open # 启动
curl http://127.0.0.1:3990/api/auth/me # bootstrapRequired → bootstrap → login → 代理 host.describe

安全边界(明示)

- v1 为逻辑隔离:会话/权限/配额/数据按用户与租户隔离,网关强制;DSH 单进程内无进程级隔离(模型与工具同 UID)。生产强隔离建议每租户独立容器/独立 DSH_HOME
- 登录会话为 HttpOnly + SameSite=Lax Cookie;公网部署务必 cookie.secure: true + 反代 TLS
- 防爆破:每账号+每 IP 窗口内失败计数,连续失败达阈值自动锁定账号(管理员解锁清计数);网关统一安全响应头(nosniff/DENY/CSP)
- 部署形态(内网直连 + 公网反代 TLS)与备份/升级见 docs/部署.md
- DSH 特权方法经网关:网关做浏览器信任头规范化(Origin→回环源)后,配置/凭据面(settings./credentials.*/llm.discoverModels)仅平台管理员可调;host.pickDirectory /host.openPath(工作区创建流程)对所有已登录用户放行;3080 直连仍为 loopback 语义

License

MIT
预览分享卡片长什么样 ↓dusbin/dsh-multi-tenant
分享 · DeepSeek Harness Hub
dusbin/dsh-multi-tenant

为 DSH 加上登录、租户隔离与用量配额管控

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部