admin
|
09ce76f3af
|
feat(overlay): 内容块级寻址 + 实例逐步拉起 + 骨干选路 + 组密钥加密(序24–㉛ 累积同步)
代码
- 内容分发块级寻址:新增 src/net/relay/content/{chunker,store,runtime,source,peer,crypto}.ts
- 组密钥(C 档)确定性加密:AES-256-GCM,块 id β′ = sha256(密文) 前 32 hex;双 epoch 过渡窗口
- 实例生命周期:三处 teardown() 不再杀实例(local/remote/leased-spawner);启动认领 + TCP 探活判孤儿
- 骨干选路:jitter 选路 + endpoint-target;relay client/server/wire/identity/directory/rendezvous/switcher 调整
- 工作台 src/web/server.ts、src/worker/relay-tunnel.ts 装配与候选链观测
脚本与测试
- scripts/overlay-{probe,keyring,jitter}.cjs 更新
- 探针新增 OBS-21(每连接候选数)/ OBS-22(teardown 静态守卫 + 认领面)/ OBS-23(组密钥加密)
- 新增 test/{orchestrator-teardown,orchestrator-rehydrate,overlay-content,overlay-jitter}.test.mjs;relay 两例更新
文档
- 新增交接单:覆盖网络-序24-内容分发块级寻址 / 序25-实例逐步拉起 / 序26-骨干稳定选路与加密
- INDEX.md、交接单/README.md、skills/dsh-auto-handoff-chain/SKILL.md 同步
验收(零回归,2026-09-18 08:0x 复核)
- npm test 201 tests / 200 pass / 0 fail / 1 skipped
- overlay-failover-drill --scene all --table 12 PASS / 0 SKIP / 0 FAIL
- overlay-probe --table 23 PASS / 0 SKIP / 0 FAIL (rc=0)
|
2026-09-18 08:08:51 +08:00 |
|
admin
|
146c3d25ef
|
feat(overlay): 覆盖网络线序①–⑮ 代码与测试产物入库
覆盖网络线累积产物(此前只在工作区、未入版本库):
- 新增 relay 子系统 src/net/relay/**(wire/duplex/server/client/dialer/switcher/directory/identity/keys/placement/network/addr-override/main/index)
- 新增 src/worker/relay-tunnel.ts、src/web/routes/overlay.ts
- 新增观测/演练脚本 overlay-probe、overlay-failover-drill、overlay-keyring、overlay-holepunch、overlay-jitter、overlay-wan、overlay-relaykey-add、relay-mem-calibrate
- 新增测试 12 个(relay / relay-failover / remote-spawner / instance-port / overlay-{network,auth,bootstrap,identity} / remote-user-fs 等)
验收基线:npm test = 162 pass / 0 fail / 1 skip;--scene all = 12 PASS / 0 SKIP / 0 FAIL;overlay-probe = 12/12
|
2026-09-17 17:03:27 +08:00 |
|
admin
|
640813e84e
|
覆盖网络线 S0+S1 落地:可达性单一入口 + 会合地址出 env
S0(本机):新增 src/net/reachability.ts(Reachability 描述 + agentBaseUrlOf 唯一取值入口)、src/net/rendezvous.ts、docs/architecture.md(四层划分 + 依赖方向 + R1-R4 判据)、scripts/check-layering.mjs + layering-baseline.json、test/reachability.test.mjs;src/supervisor/remote-spawner.ts 与 src/web/server.ts 改为统一走 agentBaseUrlOf(),agentUrl 降级为可选旧字段(向后兼容)。
S1(本机 + 106):新增 DSHS_RENDEZVOUS_URL 出 env(src/config.ts 解析 clusterRendezvousUrl,优先级 overrides > 新变量 > DSHS_TUNNEL_TARGET 兜底 > 空),src/worker/tunnel.ts 新增 normalizeTunnelTarget()、src/worker/agent.ts 改读新配置 ⇒ 双路径并存、可零代码回滚(删掉新 env 即走旧路径)。106 已上线,健康检查 tunnel.ready=true。
package.json 增加 check:layering 脚本并接入 verify;README 登记分层文档。
验收:npm run build 通过;npm test 44/44;check:layering 无新增违规(基线 5 条)。
|
2026-09-16 15:02:52 +08:00 |
|
admin
|
3efd68517f
|
chore: 并入已删除会话的在途成果(防丢失;原会话已删,未做功能验收)
**背景**:这些改动原属本工作区另外几个会话(T01/T02 等),**那些会话已被用户删除** ⇒
工作树里的成果处于"无主"状态,一次错误 checkout / 覆盖即**永久丢失** ⇒ 代入库保全。
口径遵循本项目**先例**(`39a1f2e` / `b617cdb`:**别人的活,代入库并在提交信息里注明**)。
**内容**:档案 101「能力管理」改名 + 页内 tab 分页|档案 102 语言切换搬入「用户设置」|
`07-实例UI分区登记表.md`|`scripts/find-ui*.mjs`(UI 元素定位工具)|`poc/portal-entry/`(0.5.3)|
`src/web/locale-pref.ts` + `home-files.ts`(语言偏好持久化)|`test/locale-pref.test.mjs`|
`package.json`|`BRIEF.md` / `INDEX.md` / `docs-manifest.json` / `03-路线图与待办.md` / 档案 100 增量。
**已做最小健全性检查**(⚠️ **未跑完整构建 / 单测** —— 那是原会话的验收职责,本次只求"不丢"):
- JSON 合法:`package.json` / `poc/business-plugins/package.json` / `docs-manifest.json` ✓
- 4 个 TS 文件 `{}`/`()` 配平 ✓;新增文件均非空 ✓
- 规模:13 文件改动 +340/−210,新增 12 条
**未 push**(按 §4 提交边界:用户说"提交",未说"推送")。
|
2026-09-15 21:17:12 +08:00 |
|
admin
|
c70d5d860e
|
feat(cluster): 集群化落地 —— Manager/Worker 拆分 + 归属租约 + 跨机验证(T08)
背景:把平台从「单机单进程」改造成「1 组 Manager + N 台 Worker + 共享归属状态」,
硬约束 = 全程兼容单例模式(deployMode 默认 local;生产切换前 47 一行未动)。
主要改动
1) 数据模型 v7(SQLite 与 PG 两方言同步):新增 dsh_hosts 注册表 +
dsh_instances.{host_id,epoch,heartbeat_at,lease_until};claimInstance 原子抢占
(UPDATE … WHERE host_id IS NULL OR lease_until < now)+ pinInstanceHost 钉住归属。
2) 租约与 fencing:src/supervisor/lease.ts(acquire/renew/release + stillHolder 判据 +
ttl > 2×renew 硬校验);心跳里续租,失权即向 worker 下发更高 epoch(self-fencing)。
⚠️ release 只清租约(lease_until),**保留 host_id** —— host_id 是「用户数据在哪台」的锚点。
3) Worker agent(src/worker/agent.ts,子命令 dshs worker):实例生命周期 + 文件面 /fs/*
+ 幂等键(operationId)+ 鉴权(timingSafeEqual);Worker 不写控制面数据
(apiKey/uid 由 Manager 随 launch 投递,R5 收窄)。
4) 远端 Spawner + LeasedSpawner:按 host 路由(**粘性优先**:有历史归属且那台 up 就留在原地,
否则按容量选最空的)+ 容量准入 + deployMode=cluster 装配(systemd drop-in,可回滚)。
5) bwrap 修正:**所有挂载点的中间目录统一前置 + 去重 + 由外到内**(「就近创建」会在嵌套前缀下
遮掉已绑挂载点 ⇒ bwrap: Can't chdir);且**只能用 --tmpfs**,用 --perms 会让 47 的
bwrap 0.4.0 直接拒启动(沙箱全挂)。
6) 跨机隧道 src/worker/tunnel.ts:SSH ControlMaster + 动态 -R 转发;**自愈由 agent 本地
20s 定时器驱动**(不能只放 /healthz —— 心跳本身经隧道进来,断了就没人触发它)。
7) 文件面按归属路由(RemoteUserFs):实例与文件必须落在同一台机器,否则实例看不到自己的文件。
8) 观测面:dshs doctor / dshs cluster status。
验证(本次均已实跑)
- test/lease.test.mjs:SQLite 10/10 == PG 10/10
- 组件级端到端 5 个:verify-cluster-{agent,lease,fs,migrate,live}.mjs
- 真跨机(47 Manager / 106 Worker,跨云 + 反向隧道)verify-cluster-cross.mjs 九步全绿
- 域名形态访问 verify-cluster-domain.mjs(<user>.域名 → Manager → 远端实例;越权 403)
- 冒烟 scripts/smoke-*:6/8,失败项与改动前基线完全相同(无回归)
- 生产切换与回滚剧本见 dsh-server-docs/交接单/T08-集群化落地-兼容单例模式.md §16
|
2026-09-15 18:47:02 +08:00 |
|
admin
|
cf8b7b1f5c
|
chore(k8s): 下线 K8s 后端形态,移除依赖 @kubernetes/client-node
生产形态是单机 local(DEFAULT_DEPLOY_MODE=local,env 未覆盖)⇒ K8s 分支
在 local 下本来不可达;且该形态与官方 dsh 基座、插件体系均无关
=> 整体下线,并移除该形态唯一的第三方依赖。
移除(备份在 D:/github/_dsh_shenxian_K8s后端备份_20260915/,含还原命令与
「集群化方案要复用的模板清单」):
src/supervisor/{k8s-spawner,leader,reconcile}.ts
src/fs/k8s-user-fs.ts · src/tcp-bridge.ts · src/web/file-service.ts
test/{k8s-spawner,leader}.test.mjs · scripts/smoke-file-service.mjs
改写调用方:cli.ts(5 条 import / 选主块 / file-service 与 tcp-bridge 两个
子命令 / dispatch / HELP)、web/server.ts(改为 fail-loud 守卫 + 恒用
LocalSpawner)、fs/provider.ts(只留 LocalUserFs)、package.json(测试与
smoke 入口),外加 3 处指向已删类型的悬空 JSDoc。
保留(集群化方案列为未来可选):deploy/ · poc/01-04 · Dockerfile.dsh ·
docs/k8s*.md(已加「代码已下线」状态横幅)· config.ts 的 K8s 配置字段与
DeployMode 联合类型。
验证:tsc --noEmit exit 0;npm test 36 测试 / 35 通过 / 0 失败 / 1 跳过;
npm run verify exit 0;依赖与被删符号全仓 0 命中。
|
2026-09-15 06:36:20 +08:00 |
|
admin
|
022b1f770c
|
feat(models): 「模型设置」接官方厂家目录 + 按官方页结构重做界面(档案 87 补做)
用户实测反馈:新增条目看不懂、厂家选择太少且国内一家都没有。根因是**第一版只做了手填表单**,没接官方 pi-ai 自带目录(实测 38 家,国内 11 家:蚂蚁 / 通义千问 / 小米 / 月之暗面 / 智谱 / MiniMax)。
- 新文件 src/web/model-catalog.ts:只读官方 data/*.json(10 分钟缓存,不导入 pi-ai 运行时);中文名走显示用静态表,选取范围以目录为准
- 新增 GET /api/me/model-providers(38 家 + cn 分组 + modelCount + 模型名;排除 deepseek —— 平台已有内置入口)
- POST /api/me/keys 新增 provider 参数:**目录厂家只需 API 密钥**(端点/协议/模型全由官方目录兜底 —— 官方 config.d.ts 明示 route 命中即继承默认)
- refForEntry 判据由「baseUrl 为空」改为「**没有 route**」:否则目录厂家的 key 会被写进 DEEPSEEK_API_KEY
- SettingsEntry 的 baseURL/api/models 改为可选:目录厂家只写 apiKeyEnv(写得越少越不容易漂)
- 前端按官方页结构重写:提供方行(厂家/说明/状态/操作)+ 新增**先选厂家**(中国大陆 / 国际分组 / 自定义)+ 保留并强化 admin 的「平台共享模型」区块
- 真环境验收:目录端点 38 家 / 国内 11 家;加 moonshotai-cn 只给 key → settings.yaml 仅 apiKeyEnv;删后整块消失
|
2026-09-14 00:15:17 +08:00 |
|
admin
|
918f1d3a51
|
feat(models): 平台自建「模型设置」—— 用户自配厂家 / 条目各自开关 / 共享模型开关(档案 87)
- 官方「设置 → 模型」页在平台环境**必然报错**(判据在**浏览器页面**的 loopback 判定;官方 README 原文 Non-loopback pages get no durable settings)⇒ 该分区对全角色(含 admin)隐藏,用户自配改走平台自建页(插件 0.3.11)
- DB 迁移 V6:credential_vault.route/base_url/api/models + users.shared_model_enabled;并**重定义 getEnabledCredentialKeyRef**(互斥删除后原实现无 ORDER BY ⇒ 「任取一条」)
- 新落地层 src/web/model-landing.ts:spawn 时把「已启用条目」写进实例 .credentials.yaml 与 settings.yaml 的 llm-pi-ai.providers.<route>;字段名与官方包实测对齐(apiKeyEnv / baseURL / api,**不是** protocol);只碰自己写过的 + 一次性交接
- 接口 /api/me/keys、/api/me/keys/:id/toggle、/api/me/models/shared;前端新增「设置 → 模型设置」分区(settings.section id=model-settings / order 100 / 全角色)
- 顺手修两处:ensure-role-profile-patch.cjs 的 --force 整文件覆盖会抹掉 admin 的 disable-hmr 与 workspace-scoped-picker 两个平台块(改为 stripManagedBlock 只替换自己那段);verify-mem-model.mjs 因档案 86 重构而长期失败的陈旧断言
⚠️ 本提交同时包含**档案 86(admin 跨用户实例管理 + 两处改名)**的代码改动 —— 该部分已上线并端到端验证;其 import/register 与本次改动同处 src/web/server.ts、poc/business-plugins/lib/client.js 等文件,按**文件粒度无法拆分**,且不带它会让仓库 tsc 直接失败(缺 src/web/routes/admin-user-ops.ts)。
|
2026-09-14 00:00:15 +08:00 |
|
admin
|
eb50ca2d5b
|
feat(keys): 模型密钥开放给用户自配 —— 放开官方「模型」页 + 平台改预置凭据
用户要求「把配置模型密钥开放给用户自己配」且「界面交互和官方一模一样」⇒ 不仿制,直接放开官方 ui-settings-models 页(可选厂家:DeepSeek 内置 + 自定义 OpenAI 兼容网关含 baseURL/模型)。
- ensure-role-profile-patch.cjs:不再对普通用户禁用 ui-settings-models(保留 plugins/inventory/cordis 禁用);--force 时能把「还禁着 models」的旧块升级。
- src/web/server.ts:resolveApiKey 不再注入 DEEPSEEK_API_KEY env,改为把「平台共享密钥」预置进 $DSH_HOME/.credentials.yaml 的 refs 段(新增 ensureRefInCredentials:只在无该 ref 时写 / 只在 version:1 上插入 / 备份落平台目录 / 写完 chown 给实例 uid / 失败退回 env)。真因:dsh 凭据解析里 env 优先级最高,且 dsh-credentials-local.write() 的 assertUnshadowed() 会让用户在模型页保存直接报错 ⇒ 注入 env 等于锁死用户自配。
- src/web/routes/auth.ts:/api/me/keys 由 requireAdmin 放开为 requireAuth(平台侧密钥 API 保留,UI 不再暴露)。
- poc/business-plugins 0.3.4→0.3.8:「系统管理」对齐门户 6 个功能页(同名同构,PA_PAGES 逐函数移植 portal)/ 官方插件列表高度改为「离弹窗底部约 100px」/ 撤掉自造的「我的密钥」分区(改由官方模型页承担)。
- web/portal.html:keys 页语义改名「平台共享密钥(未自配密钥的用户默认使用;仅管理员可改)」。scripts/verify-platform-admin-section.mjs:断言同步升级(含 zh/en 词典键集一致性、内联 HTML class 扫描)。
|
2026-09-13 22:27:49 +08:00 |
|
admin
|
43976fea6a
|
初始提交:DSH 多租户平台(dshs)
|
2026-09-13 16:18:10 +08:00 |
|