device-center 0.1.0-beta.1 → 0.2.0-beta.1
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/Dockerfile +2 -2
- package/README.md +34 -130
- package/SECURITY.md +7 -15
- package/bin/device-center.mjs +6 -3
- package/docs/architecture.md +25 -57
- package/docs/connection-routing.md +1 -0
- package/docs/driver-binding.md +6 -1
- package/docs/hosted-access.md +52 -0
- package/docs/npm.md +19 -35
- package/docs/onboarding.md +5 -2
- package/docs/remote-access.md +76 -0
- package/docs/roadmap.md +8 -3
- package/docs/security-and-sync.md +9 -64
- package/login.html +1 -1
- package/npm-shrinkwrap.json +304 -0
- package/package.json +18 -4
- package/scripts/access.mjs +48 -0
- package/scripts/driver.mjs +4 -3
- package/scripts/release-check.mjs +4 -0
- package/server/cloudAccess.mjs +13 -6
- package/server/connector.mjs +11 -5
- package/server/drivers/access.mjs +84 -0
- package/server/drivers/certificates.mjs +32 -0
- package/server/drivers/cloudLink.mjs +4 -2
- package/server/drivers/cloudRegistry.mjs +62 -18
- package/server/drivers/relay.mjs +59 -0
- package/server/drivers/remote.mjs +111 -0
- package/server/index.mjs +26 -12
- package/server/mcp.mjs +5 -3
- package/server/unifiedAccess.mjs +33 -17
- package/src/api.js +2 -1
- package/src/login.js +1 -0
- package/src/main.js +79 -22
- package/src/onboarding.js +18 -0
package/Dockerfile
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Optional local-only control plane, not a host/resource Agent.
|
|
2
2
|
FROM node:24-bookworm-slim
|
|
3
3
|
WORKDIR /app
|
|
4
|
-
COPY --chown=node:node package.json index.html login.html ./
|
|
4
|
+
COPY --chown=node:node package.json npm-shrinkwrap.json index.html login.html ./
|
|
5
5
|
COPY --chown=node:node server ./server
|
|
6
6
|
COPY --chown=node:node src ./src
|
|
7
|
-
RUN mkdir -p /app/data && chown node:node /app/data
|
|
7
|
+
RUN npm ci --omit=dev --ignore-scripts --no-audit --no-fund && mkdir -p /app/data && chown node:node /app/data
|
|
8
8
|
USER node
|
|
9
9
|
ENV PORT=5173 DEVICE_CENTER_RUNTIME=container DEVICE_CENTER_DB_PATH=/app/data/device-center.sqlite
|
|
10
10
|
CMD ["node", "server/index.mjs"]
|
package/README.md
CHANGED
|
@@ -1,159 +1,63 @@
|
|
|
1
1
|
# Device Center
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
让主力电脑上的智能体,使用自己的闲置设备。MIT · Node.js 24 · macOS / Linux · beta。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
一个本机连接器,加一个可选的云端控制面。真实本机内存、磁盘分别展示;已有 SSH 配置可一键关联并执行固定只读检查;设备 Agent 可通过域名绑定账号,主动回报状态。指定日志经设备主人单独授权后,以双向 TLS 1.3 直连或密文中转读取。没有默认示例设备或虚构在线状态。
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 快速使用
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
只用本机,不注册账号:
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
|
|
13
|
-
npx --yes device-center@0.1.0-beta.1 --help
|
|
14
|
-
npx --yes device-center@0.1.0-beta.1 plan --cloud https://你的控制面域名
|
|
15
|
-
# 用户主动接入;配对码由终端产生,再单独输入面板核对批准
|
|
16
|
-
npx --yes device-center@0.1.0-beta.1 connect --cloud https://你的控制面域名 --confirm
|
|
12
|
+
npx --yes device-center@0.2.0-beta.1 start
|
|
17
13
|
```
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
打开 `http://127.0.0.1:5174`,将 `/mcp` 添加到本机智能体。侧栏“开始使用”按管理电脑 → 智能体 → 设备引导;导入 SSH 后检查一次连通性。没有可用 Agent/SSH 的设备保持未知;资源快照过期显示“待刷新”,不代表密钥过期。列表刷新不主动连接 SSH。
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
需要 Node.js 24,无第三方运行依赖、无前端构建步骤。
|
|
24
|
-
|
|
25
|
-
```sh
|
|
26
|
-
npm run dev
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
打开 [本机面板](http://127.0.0.1:5173),点“开始使用”,按 **管理电脑 → 智能体 → 设备** 完成设置。本机自动加入设备列表,已有近期接入记录可直接进入导入;复制 MCP 地址到 Codex 设置并 Restart,再一键导入已有 SSH 主机。也可稍后连接智能体、先导入,界面不会伪造接入成功。后续手动新增从“添加设备”进入。见[本机、服务器与新设备的完整流程](docs/onboarding.md)。
|
|
30
|
-
|
|
31
|
-
已配置不等于已连通。点击导入或关联后,新增设备自动排队检查一次当前 SSH 路径,最多两台并发,标记等待、检查中、连通或失败原因;失败可在卡片点“检查 SSH(只读)”重试。目标机无需安装 Node 或本项目。取得资源后在线五分钟,之后显示“待刷新”(数据较早,不代表设备断线或密钥过期)。SSH 连通性与内存、磁盘采集分别显示:认证已通过但目标不支持采集时,指标为空、设备状态仍未知。刷新列表只读取缓存,不会重连。
|
|
32
|
-
|
|
33
|
-
每台设备名称下显示访问路径摘要,点击可看跳板、目标入口、认证与密钥说明。路径来自已核验的配置,详情图区分上次成功检查与未知的后段映射;未启用自动局域网选路。参见[访问路径与局域网优先方案](docs/connection-routing.md)。
|
|
34
|
-
|
|
35
|
-
“开始使用”的设备步骤会检查运行 Driver 的电脑的本用户 SSH 配置,一键导入可用条目。筛选复用当前安全解析器,要求明确且完整的 Host / 命名 ProxyJump、可读取的本机身份文件引用;仅检查文件元数据,不读取私钥内容。缺少参数、身份文件不可用或暂不支持的配置会跳过并说明原因,不删除配置。“可导入”不等于已连通或认证通过,导入只保存别名引用,随后执行固定只读检查;检查成功前保持未知。已有同名引用不会重复创建或再次排队。服务器部署不能自动读取用户正在操作的电脑;管理 Driver 可经域名配对,默认只回报本机资源;SSH 缓存分享需要另行申请和批准,配置迁移仍待实现。Docker 不读取宿主配置,需在宿主运行原生 Driver。
|
|
36
|
-
|
|
37
|
-
在“连接方式”中,同一台 SSH 设备可同时登记局域网地址/端口和中转方案。中转有三种:用户自建服务器、Device Center 提供的服务、Cloudflare;支持保存局域网优先或仅中转的计划。保存到本机 SQLite,重新打开后恢复;入口仍待验证,中继适配器和自动选路尚未启用,不会修改已有 SSH 配置或托管私钥。
|
|
38
|
-
|
|
39
|
-
智能体通过 MCP 使用本机 Driver。已有 MCP 配置可以继续使用;首次配置时,从侧栏“智能体连接”复制地址,在 Codex 设置的 MCP servers 中添加 Streamable HTTP 服务并重新启动连接。
|
|
40
|
-
|
|
41
|
-
也可以在本机终端配置一次:
|
|
17
|
+
需要在外查看设备、使用日志中转:
|
|
42
18
|
|
|
43
19
|
```sh
|
|
44
|
-
|
|
20
|
+
npx --yes device-center@0.2.0-beta.1 plan
|
|
21
|
+
npx --yes device-center@0.2.0-beta.1 connect --confirm
|
|
22
|
+
# 自建控制面可指定 --cloud https://devices.example.com
|
|
45
23
|
```
|
|
46
24
|
|
|
47
|
-
|
|
25
|
+
默认 [官方控制面](https://devices.owenshen.top),登录自己的 App Services/个人站统一账号。在面板输入终端的五分钟配对码,核对完整公钥指纹和回报范围并批准。私钥留在设备,不放进脚本、prompt 或压缩包。默认不分享 SSH 信息、不开 LAN 端口、不安装后台服务。配对只授权资源回报。
|
|
48
26
|
|
|
49
|
-
|
|
50
|
-
flowchart LR
|
|
51
|
-
AI[本机智能体] --> MCP[MCP]
|
|
52
|
-
MCP --> Driver[本机 Driver 与真实资源读数]
|
|
53
|
-
Driver --> Ref[已关联 SSH 主机引用]
|
|
54
|
-
Ref --> Snapshot[导入后检查或手动重试 · SSH 只读快照]
|
|
55
|
-
Ref -.后续单独授权.-> Task[指定日志或受限任务]
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
SSH 发现只读取 `~/.ssh/config` 和受限范围内的无条件 Include(`~/.ssh/` 内的 `config` / `.conf`)。不会读取私钥、密码、ssh-agent 或 known_hosts,不运行 `ssh` / `ssh -G`,不执行 `Match exec`、代理或远程命令;不解析完整生效配置。条件 Include、目录外文件、动态路径和通配 Host 不作为自动发现设备,界面会说明读取限制。依据 [OpenSSH 配置语义](https://man.openbsd.org/ssh_config.5),解析配置并不等于验证可达性和身份。
|
|
59
|
-
|
|
60
|
-
**主动检查与配置发现分开。** 检查支持 macOS/Linux 原生管理 Driver,根配置中的完整明确 Host 和命名 ProxyJump;目标需要 POSIX shell 和 macOS/Linux。程序生成临时隔离配置,不完整继承通配、全局或 Include 配置,影响目标或跳板的 Match 条件或自定义命令需要人工审核;仅与它们完全无关的静态 originalhost 条件不会误伤该条目。OpenSSH 使用本机现有身份文件引用和 known_hosts 做认证,程序不读取或导入私钥内容。主机指纹严格校验,不自动接受新主机、不关闭校验。固定采集只用 `uname`、`hostname`、`sysctl`/`vm_stat` 或 `/proc/meminfo`、`df`;不读取普通文件内容、安装服务或接收任意命令。超时 25 秒、输出上限 32 KiB、最多两个并发。SQLite 保存别名、时间、配置摘要及归一化资源结果,不保存配置文件、身份路径或原始输出。见 [排查说明](docs/troubleshooting.md)。
|
|
61
|
-
|
|
62
|
-
本机“在线”表示服务进程正在本机运行;每次刷新重新采集。内存为系统总量减空闲(含缓存,区别于系统活动监视器的内存压力);Linux SSH 快照使用总量减 MemAvailable。磁盘为用户目录所在卷,不能相加所有分区或代表单个项目占用。读取失败时对应指标显示失败,不影响另一项。
|
|
63
|
-
|
|
64
|
-
原有 stdio 配置继续可用,但不会在 HTTP 面板里产生接入记录;建议将同名配置改为上面的 HTTP 地址。当前对话不会因修改配置自动加载工具,需要在客户端重启连接或重开会话。接入方法见 [OpenAI 官方 MCP 文档](https://learn.chatgpt.com/docs/extend/mcp?surface=cli)。
|
|
65
|
-
|
|
66
|
-
端口可用 `PORT=5174 npm run dev` 调整。复制命令会使用当前页面端口,不带数据库路径、密钥或令牌。数据默认为仓库 `data/device-center.sqlite`,可以用 `DEVICE_CENTER_DB_PATH` 指定已有数据库;不会自动清空数据或写入种子。旧版 `is_demo=1` 记录被排除,不自动删除。
|
|
27
|
+
[远程日志:两端授权、直连与中转](docs/remote-access.md) · [常驻与 npm](docs/npm.md) · [账号模式与自建](docs/hosted-access.md) · [故障排查](docs/troubleshooting.md)
|
|
67
28
|
|
|
68
|
-
##
|
|
29
|
+
## 能做什么
|
|
69
30
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- `plan` 只展示计划,不修改系统。
|
|
79
|
-
- `install --confirm` 是用户主动安装:登记用户级后台服务,登录后启动,失败时由系统服务管理器重启。Node 及仓库必须保留在稳定路径。
|
|
80
|
-
- macOS 数据和日志位于 `~/Library/Application Support/Device Center/`;Linux 数据位于 `~/.local/share/device-center/`,日志由用户 journal 管理。
|
|
81
|
-
- 后台服务使用独立持久数据目录,不自动复制开发数据库。请先停止自己启动的同端口前台进程;脚本不会自动结束其他进程或覆盖已有服务配置。
|
|
82
|
-
- `--port 5174` 可以加在各命令后,安装、状态和卸载应使用相同端口。
|
|
83
|
-
- `npm run service -- uninstall --confirm` 只卸载这份配置对应的用户服务,保留数据目录;修改过的配置须人工处理。
|
|
84
|
-
- Windows 原生 Driver 和后台安装尚未实现;下方 Docker 方案只表示容器资源,不能替代宿主 Driver。
|
|
85
|
-
|
|
86
|
-
本轮验证仅运行 `plan`、前台预览和接口测试,**没有安装常驻服务**。系统服务安装与 Docker 运行还需在各目标平台实际验证。当前仍是源码运行方式,不是给普通用户分发的签名安装包。
|
|
31
|
+
| 能力 | 当前实现 |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| 资源清单 | 本机真实资源;已有 SSH 主机经用户触发检查;云端只显示获准回报 |
|
|
34
|
+
| 账号与设备 | 上游核验账号、租户隔离、短期一次性批准、签名防重放、撤销 |
|
|
35
|
+
| 日志 | 指定标签/绝对文件/管理设备/有效期,最大64KiB;本机审计 |
|
|
36
|
+
| 访问路径 | Agent 精确私网入口优先,网络失败回退官方/自建 HTTPS 密文中转;证书错误停止 |
|
|
37
|
+
| 中转额度 | 每账号100MiB/UTC日、全实例1GiB/日,持久计数、并发与速率限制 |
|
|
38
|
+
| 尚未提供 | 任意远程命令、通用文件传输、Windows 原生 Agent、云端 MCP、CF 专用适配器、计费、自动迁移 |
|
|
87
39
|
|
|
88
|
-
|
|
40
|
+
日志操作通过 `device_center_read_log` 请求,不能用 MCP 授权自身。用户自己的智能体仍需在目标设备单独配置授权。已有 SSH 路径独立使用,SSH“连接计划”不会自动改成新 Agent 通道。Docker 代表容器自身,不能当作宿主机;宿主运行原生 Driver 与本机智能体交互。
|
|
89
41
|
|
|
90
|
-
|
|
42
|
+
## 从源码运行和自建
|
|
91
43
|
|
|
92
44
|
```sh
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
flowchart LR
|
|
100
|
-
AI[宿主机上的 Codex] --> URL[127.0.0.1:端口/mcp]
|
|
101
|
-
URL --> DC[容器中的 Device Center]
|
|
102
|
-
DC --> DB[容器数据卷]
|
|
45
|
+
npm ci --ignore-scripts
|
|
46
|
+
npm run dev
|
|
47
|
+
# 默认 http://127.0.0.1:5173
|
|
48
|
+
npm run check
|
|
49
|
+
npm test
|
|
50
|
+
npm run verify:package
|
|
103
51
|
```
|
|
104
52
|
|
|
105
|
-
|
|
53
|
+
无前端构建步骤;依赖由 npm-shrinkwrap 固定。仅本机模式监听回环地址,不可直接公开。可选 `docker compose up --build -d` 使用本地回环端口映射与非 root 用户,未挂载宿主 HOME/SSH/Docker socket。容器不能代替用户本机 Driver。
|
|
106
54
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
## 个人云端面板
|
|
110
|
-
|
|
111
|
-
云端模式必须同时设置 `DEVICE_CENTER_RUNTIME=cloud`、明确的 `DEVICE_CENTER_PUBLIC_ORIGIN=https://你的域名` 和 `DEVICE_CENTER_AUTH_FILE`。使用现有 App Services/个人站统一账号时,在仓库外保存权限为 `0600` 的认证配置:
|
|
55
|
+
云端部署必须设置 `DEVICE_CENTER_RUNTIME=cloud`、`DEVICE_CENTER_PUBLIC_ORIGIN=https://你的域名`、`DEVICE_CENTER_AUTH_FILE=/仓库外/private.json`。已有反向代理仅转发至服务回环端口,覆盖 Host 和 X-Forwarded-Proto,提供 HTTPS。认证配置文件0600:
|
|
112
56
|
|
|
113
57
|
```json
|
|
114
|
-
{
|
|
115
|
-
"provider": "app-services",
|
|
116
|
-
"backendOrigin": "https://appapi.example.com",
|
|
117
|
-
"accountOrigin": "https://example.com",
|
|
118
|
-
"ownerEmail": "owner@example.com"
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
这些值是配置示例。控制面、账号站和 App Services 必须使用同一受信任的父域名,账号站已经设置共享的 HttpOnly `sessionToken` cookie。服务只向配置的 App Services `/v1/me` 验证身份,并检查所有者邮箱;不接受浏览器自报的用户 ID、匿名或手机号会话,不复制账号服务的签名密钥。统一登录只支持这份个人访问限制,不是多用户托管。
|
|
123
|
-
|
|
124
|
-
用户点击“使用统一账号登录”,在个人站通过邮箱或 Google 登录,回到设备面板会自动继续;个人站已登录时直接进入。退出设备面板仅退出本面板;个人站退出或切换账号会使本面板会话失效。身份结果最多缓存10秒,账号服务不可用时拒绝受保护访问,不回退到密码。
|
|
125
|
-
|
|
126
|
-
独立部署仍可显式使用 `provider: "password"`(旧配置可省略 provider):私有文件只保存用户名、16字节盐的十六进制值及 scrypt 哈希,参数 N=32768、r=8、p=1、输出64字节。统一账号模式拒绝本地密码接口;认证配置和凭据不进入源码、部署压缩包或日志。
|
|
127
|
-
|
|
128
|
-
后端继续只监听回环地址,由 HTTPS 反向代理访问;代理必须保留配置的 Host 并覆盖 `X-Forwarded-Proto=https`,不能转发客户端伪造的值。访问者先登录,网页、设备列表、批准/撤销与下载入口受保护。机器配对申请公开但限速,轮询、回报和断开需独立身份签名。云端 MCP / SSH 操作仍不可用。登录、继续和退出要求同源 Origin;本面板会话使用 Secure、HttpOnly、SameSite=Strict cookie,8小时失效,进程重启后重建。统一登录每个会话凭据每分钟最多8次继续尝试,校验并发/缓存大小有上限。此模式只用于个人访问,没有公开注册或多用户权限管理。
|
|
129
|
-
|
|
130
|
-
**面板上线不等于设备接通。** 云端不读取服务器 SSH、不复制本机数据库,云端 MCP 与 SSH 操作仍不可用。点“连接我的电脑”,下载源码、复制命令并在自己的电脑运行,再单独输入配对码、核对指纹和范围;批准并首次回报后才显示真实资源。当前支持 Node.js 24、macOS/Linux 源码 Driver,命令不含凭据。详见[域名绑定、常驻与排查](docs/driver-binding.md)及[部署记录与恢复](docs/deployment-readiness.md)。
|
|
131
|
-
|
|
132
|
-
## 当前真实功能与边界
|
|
133
|
-
|
|
134
|
-
| 真实本地功能 | 尚未实现 |
|
|
135
|
-
| --- | --- |
|
|
136
|
-
| 内置本机 Driver、真实内存/卷磁盘、状态筛选 | 独立设备 Agent、签名安装包 |
|
|
137
|
-
| SSH 候选、显式关联、严格验钥的一次只读资源检查 | 指定日志、构建/算力任务、任意远程命令 |
|
|
138
|
-
| 同一服务上的 HTTP MCP,四个只读工具 | 任务授权与审计 |
|
|
139
|
-
| 真实 MCP 初始化记录、复制本机地址或命令 | 设备可信启动、系统钥匙串封装 |
|
|
140
|
-
| macOS/Linux 管理 Driver 本机身份、一次性配对、签名回报及撤销 | Windows Driver、独立安装器、中继、网络限速、配置迁移 |
|
|
141
|
-
| 用户服务脚本、Docker 配置、个人统一登录与 HTTPS 入口 | 跨平台实际安装验证、多用户托管 |
|
|
142
|
-
|
|
143
|
-
项目位置保留在侧栏,目前没有项目管理或示例项目。“添加设备”只关联用户选中的已配置 SSH 主机;导入后执行一次固定只读检查,后续可在卡片重试,数据库保存引用与采集结果。不复制 HostName、私钥路径或凭据,不把关联当成信任或任务授权。候选只是 SSH 配置条目,可能有多个别名指向同一物理主机。删除系统 SSH 配置后,已有引用保留并提示配置不可用。明确移除产品内引用时,同时删除其快照与连接计划,并记录本地排除项,后续读取或一键导入不会重新加入;不修改系统 SSH 配置或身份文件。排除按租户与具体别名记录,不按客户端名称全局过滤。
|
|
144
|
-
|
|
145
|
-
接入资源设备的后续设计:设备在本机生成身份私钥,服务只登记公钥;短时一次性登记码由用户单独输入,不写入 prompt、脚本、压缩包或日志。Agent 建立安全出站连接。获准的局域网端点可尝试认证直连,失败时回退用户选择的中继。连接与任务授权分开,构建、指定日志和计算各自有目标及额度限制。
|
|
146
|
-
|
|
147
|
-
## 开发与后续
|
|
148
|
-
|
|
149
|
-
```sh
|
|
150
|
-
npm run check
|
|
151
|
-
npm test
|
|
58
|
+
{"provider":"app-services","accountMode":"multi-user","backendOrigin":"https://appapi.example.com","accountOrigin":"https://example.com"}
|
|
152
59
|
```
|
|
153
60
|
|
|
154
|
-
|
|
155
|
-
- [访问路径与局域网优先](docs/connection-routing.md)
|
|
156
|
-
- [安全与配置迁移设计](docs/security-and-sync.md) · [路线图](docs/roadmap.md)
|
|
157
|
-
- [安全边界](SECURITY.md) · [贡献说明](CONTRIBUTING.md)
|
|
61
|
+
需要已有受信任 App Services 共享账号服务与同父域会话;不是通用第三方 OAuth。个人部署可选 personal + ownerEmail。旧个人数据切多用户前按[迁移与回退说明](docs/hosted-access.md)核验原所有者映射;不能只切回旧代码而保留多用户数据库。
|
|
158
62
|
|
|
159
|
-
|
|
63
|
+
当前没有密钥托管、安装时自动联网或远程 shell。安全边界与披露方式见 [SECURITY](SECURITY.md)。npm 包公开不自动改变 GitHub 仓库可见性;本次发布是可追溯工作区快照,不是 main CI 构建。
|
package/SECURITY.md
CHANGED
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
|
-
Device Center is a
|
|
3
|
+
Device Center 0.2.0-beta.1 is a beta for macOS/Linux and Node.js 24. Local HTTP/MCP is loopback-only with Host/Origin checks; do not expose it publicly. Cloud deployment requires an exact HTTPS origin, a proxy overwriting Host/scheme, and a private authentication config. App Services identities are verified against the configured upstream; tenant scope comes from verified stable issuer/subject. Authentication outages fail closed.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Device keys remain in owner-private local files. Pairing is short-lived, one-time and separately approved after a full fingerprint comparison. Binding permits telemetry, not operations. Remote log access requires local pinned peer certificates plus a target-owned file/label/expiry grant. Node/OpenSSL TLS 1.3 mutually authenticates both devices over an approved LAN endpoint or opaque HTTPS relay; certificate and hostname verification remain enabled. The control plane sees metadata and ciphertext, not log plaintext or private keys. First-use fingerprint verification requires a trusted channel.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Only bounded log tail reads are available. No arbitrary commands, generic file transfer, Windows native Agent or cloud MCP. Symlink/multiple-hardlink/non-regular log files are rejected. Cloud revocation is checked on both routes. Local audit is bounded and fails closed at capacity. OS administrators, compromised endpoints and already-authorized readers remain trust boundaries. Keys are not TPM/Keychain wrapped. See [permissions, quotas, certificate renewal and limitations](docs/remote-access.md).
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Telemetry inventory never initiates SSH. Explicit local checks use bounded fixed scripts and strict known-host verification; private-key contents and raw SSH output are not imported. Containers do not read host SSH or claim host metrics.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Multi-user rollback requires consistent database and private-config restoration; never activate an older unscoped server against multi-account data. See [migration](docs/hosted-access.md). This release has automated isolation/transport tests, not an independent security audit or SLA.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Report a vulnerability
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Active checks use `/usr/bin/ssh` with a temporary isolated configuration for explicit root Host profiles and named ProxyJump aliases. Custom command, conditional and special authentication profiles stop for review; wildcard/global/Include options are not fully inherited. OpenSSH uses existing identity references and known_hosts, strictly verifies host keys, disables new forwarding and host-trust updates, and runs only the fixed macOS/Linux POSIX resource script. No target installation, arbitrary command/path input or key-content import occurs. Checks have a 25-second timeout, 32 KiB output limit and two-operation concurrency cap. SQLite stores alias, timestamp, configuration digest and normalized resources/failure code; raw outputs, identity paths and configuration contents are not stored. Success expires after five minutes; failure or profile changes invalidate online telemetry. This is a one-time observation, not a persistent connection or task grant.
|
|
18
|
-
|
|
19
|
-
The optional Docker recipe publishes to host loopback only, uses a non-root process and its own data volume, and has no host or Docker socket mounts. Its Driver represents the container, not host telemetry or SSH access. Actual container runtime and user-level background installation have not been validated in this task. `DEVICE_CENTER_RUNTIME=container` is a deployment setting, not proof of isolation.
|
|
20
|
-
|
|
21
|
-
Management Driver identity keys are generated only when the user explicitly runs `connect --confirm`. Private keys remain in owner-only 0600 files in 0700 directories; this is not OS keychain/TPM protection. The server stores public keys and fingerprints. Ed25519 requests bind origin, path, ID, time, nonce and payload digest; persistent nonce retention and revocation checks reject replay. Owner approval consumes a five-minute request transactionally. No bearer credential is issued. See [protocol, scope and limitations](docs/driver-binding.md). Short-lived single-use enrollment credentials are entered separately, not put into prompts, scripts, archives or diagnostic logs. Remote operations need independent owner grants scoped to a device, capability, path, time and quota. Hosted service key custody and configuration migration remain design work in `docs/security-and-sync.md`.
|
|
22
|
-
|
|
23
|
-
Tests cover local observations, SSH metadata/profile parsing, fixed checks with injected subprocesses, cache expiry/failures, association, service plans and personal cloud access boundaries. Ephemeral fixture identities exercise signatures, proof boundaries, replay, approval, revocation and expiry through isolated HTTP/SQLite tests. They do not contact real hosts, establish a production identity, validate remote task authority or constitute a protocol audit. External deployment verification is separately recorded in `docs/deployment-readiness.md`. A private security-reporting channel, license and public release plan remain to be selected. Do not post credentials, host metadata or private logs in public issues.
|
|
15
|
+
Do not post private keys, enrollment codes, cookies, logs or live credentials publicly. Contact the maintainer through a private channel before sharing sensitive details. The repository may be private even while the MIT npm package is public; no public issue tracker or bounty is promised. Stop recommending an affected beta and issue a new version rather than overwriting a published artifact.
|
package/bin/device-center.mjs
CHANGED
|
@@ -10,9 +10,8 @@ export function parseCli(argv = []) {
|
|
|
10
10
|
if (argv.length > 1) throw new Error('帮助和版本命令不接受其他参数。');
|
|
11
11
|
return { command: command === '-v' ? '--version' : ['-h', '--help'].includes(command) ? 'help' : command };
|
|
12
12
|
}
|
|
13
|
-
if (!['start', 'plan', 'connect', 'run', 'status', 'disconnect', 'service'].includes(command)) throw new Error('未知命令。运行 device-center --help 查看用法。');
|
|
13
|
+
if (!['start', 'plan', 'connect', 'run', 'status', 'disconnect', 'service', 'access'].includes(command)) throw new Error('未知命令。运行 device-center --help 查看用法。');
|
|
14
14
|
const args = argv.slice(1);
|
|
15
|
-
if (command === 'connect' && !args.includes('--cloud')) throw new Error('请用 --cloud 明确指定自己的 HTTPS 控制面域名。');
|
|
16
15
|
if (command === 'start') {
|
|
17
16
|
let port = 5174;
|
|
18
17
|
if (args.length) {
|
|
@@ -44,7 +43,10 @@ device-center service plan|status|install|uninstall [--port 5174] [--confirm]
|
|
|
44
43
|
|
|
45
44
|
默认端口5174,数据位于本用户的应用数据目录。关闭网页不会停止前台进程。
|
|
46
45
|
默认回报本机名称、系统、内存和磁盘;--share-ssh 需命令申请及面板另行批准。
|
|
47
|
-
|
|
46
|
+
本机无需平台注册;connect 默认申请接入 https://devices.owenshen.top,需登录自己的账号核对批准。
|
|
47
|
+
--cloud 可使用自建域名。device-center access help 查看受限日志授权与可选局域网直连。
|
|
48
|
+
支持 TLS 1.3 双向认证的日志读取与密文中转,默认100MiB/账号/日;不会自动获得操作权限。
|
|
49
|
+
任意远程命令、通用文件传输和 Windows 原生 Driver 尚未提供。安装包不含身份或配对码。
|
|
48
50
|
使用 npx 时只运行前台;常驻请先将本包固定版本安装到长期目录,再单独 install。
|
|
49
51
|
`;
|
|
50
52
|
}
|
|
@@ -53,6 +55,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
53
55
|
if (plan.command === 'help') return helpText();
|
|
54
56
|
if (plan.command === '--version') return version();
|
|
55
57
|
if (Number(process.versions.node.split('.')[0]) < 24) throw new Error('需要 Node.js 24 或更高版本。');
|
|
58
|
+
if (plan.command === 'access') return (await import('../scripts/access.mjs')).main(plan.args);
|
|
56
59
|
if (plan.command === 'service') {
|
|
57
60
|
if (plan.args[0] === 'install' && /(?:^|[\\/])_npx[\\/]/.test(ROOT)) throw new Error('npx 缓存会被清理,不能用作常驻目录。请先 npm install -g device-center@固定版本,再运行 device-center service install --confirm。');
|
|
58
61
|
return (await import('../scripts/service.mjs')).main(plan.args);
|
package/docs/architecture.md
CHANGED
|
@@ -1,66 +1,34 @@
|
|
|
1
1
|
# 架构
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Device Center 是模块化 Node.js 单体,前端静态文件无构建步骤。Node.js 24 内置 SQLite,Node/OpenSSL 提供 TLS;@peculiar/x509 创建标准证书,依赖由 npm-shrinkwrap 固定。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 两个运行位置
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- `server/drivers/local.mjs` 用 Node OS 接口与 `statfs` 读取真实本机指标;进程运行中为在线。内存含缓存,磁盘范围为用户目录所在卷;两项独立处理失败。容器只表示容器 Driver,不报告宿主指标。
|
|
10
|
-
- `server/drivers/sshConfig.mjs` 有界读取配置、枚举明确 Host 别名;不读取密钥,不调用 OpenSSH、解析动态条件或连接目标。最多 32 个配置文件、每文件 128 KiB、总计 512 KiB、递归 5 层、200 个别名;安全范围外 Include 和条件 Include 跳过并提示。
|
|
11
|
-
- `server/drivers/inventory.mjs` 保存用户勾选的 SSH 别名及时间,按租户命名空间隔离,事务内幂等插入。检查成功五分钟内为在线,之后过期;失败、配置缺失或配置摘要改变为未知。GET 和 MCP 只读取缓存,不连接目标。别名不是物理设备唯一身份。
|
|
12
|
-
- `server/drivers/sshProbe.mjs` 对根配置中的完整明确 Host 和命名 ProxyJump 建立隔离 SSH 配置;涉及 Match、条件 Include 或自定义命令的条目停止审核。OpenSSH 复用现有身份引用、严格校验已有 known_hosts,不写主机信任。固定 POSIX 脚本读取 macOS/Linux 基础资源;25 秒超时、32 KiB 输出、最多两个并发,不接受命令或文件路径。
|
|
13
|
-
- `server/connector.mjs` 共享四个只读 MCP 工具:Driver 状态、实际库存、SSH 配置候选、能力边界说明。没有命令、任意文件、日志或设备操作工具。
|
|
14
|
-
- `server/index.mjs` 提供无状态 HTTP MCP 的 JSON 响应,通知返回 202,不创建会话令牌,不提供 SSE(GET 返回 405)。记录最近有效初始化时间;不将记录当成鉴权、持续在线或设备心跳。
|
|
15
|
-
- `server/mcp.mjs` 兼容原有 stdio 配置,只读同一实际库存。stdio 进程与 HTTP 服务不共享运行状态,所以不会出现在面板的 HTTP 初始化记录中。
|
|
16
|
-
- `scripts/service.mjs` 默认只输出计划;用户显式执行安装才登记 macOS/Linux 用户级服务。
|
|
17
|
-
- Docker 是可选的本机运行容器,MCP 仍由宿主智能体主动连接。没有宿主挂载或 Docker socket 权限。
|
|
18
|
-
|
|
19
|
-
## 请求边界
|
|
20
|
-
|
|
21
|
-
首次使用界面统一为管理电脑、智能体、设备三步,复用同一组本机状态与 API。原生本机资源可读时自动跳过管理电脑步骤;只有近期真实 MCP 初始化记录才跳过智能体步骤。允许稍后接入后直接导入引用,不生成握手或任务操作授权。点击导入会为新增设备排队执行一次固定 SSH 只读检查。独立管理 Driver 可向 HTTPS 域名申请配对,所有者单独输入码、核对指纹并批准后,按固定字段回报资源;未取得回报仍为未知。完整流程见[使用引导](onboarding.md)。
|
|
22
|
-
|
|
23
|
-
页面外框固定为视口高度,侧栏与顶部不参与设备列表滚动。设备用紧凑行展示,内存和磁盘仍为独立列;小屏内部换行,空间不足时仅列表滚动。打开/关闭弹窗、刷新和快照过期重绘保留列表位置;改变搜索或状态筛选回到列表顶部。采集口径移到数值提示和可展开状态说明,失败仍明确显示。
|
|
24
|
-
|
|
25
|
-
`server/drivers/sshRoute.mjs` 从用于只读检查的已核验配置生成非秘密路径节点,面板与 MCP 共用。每台设备显示路径摘要,可打开图示与认证说明;`lastVerifiedRoute` 只在配置摘要与经过认证的检查结果一致时提供,资源采集是否可用单独判断。内部 `expired` 在面板显示“待刷新”,只说明数据时效。当前固定按配置连接,未实现自动 LAN 选路;具体方案与验收见[访问路径与局域网优先](connection-routing.md)。
|
|
26
|
-
|
|
27
|
-
`server/drivers/connectionPlans.mjs` 校验并保存每台已关联 SSH 设备的本机计划:可同时登记 LAN 地址/端口与用户自建、项目托管或 Cloudflare 中转类型,以及 LAN 优先/仅中转策略。写接口要求明确同源 Origin;不接受凭据、任意 URL 或额外字段。新增表不清理或覆盖已有设备、配置与快照。库存与 MCP 读取 `connections`,其中 `effective: false`;未验证入口及未接入中继不会改变在线状态,现有检查仍仅使用原 SSH 配置。
|
|
28
|
-
|
|
29
|
-
原生进程固定监听 `127.0.0.1`。仅接受回环 Host 和同源 Origin,拒绝跨站请求;静态内容有 CSP,不启用 CORS。MCP JSON 请求上限 16 KiB,检查类型、Accept、协议版本和工具参数。MCP 协议按 [2025-11-25 transport](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports) 实现本机无状态只读子集。
|
|
30
|
-
|
|
31
|
-
底层仅保存引用的 `POST /api/devices/ssh`:必须明确同源 Origin、JSON、小于 16 KiB;只接收 aliases 数组,重新核对当前候选,其他字段拒绝。只写本地别名引用,不执行远端操作。MCP 没有关联写入或网络检查工具。
|
|
32
|
-
|
|
33
|
-
初始化预览 `GET /api/ssh/initialization` 在发现结果上增加本机配置检查:`sshInitialization.mjs` 复用隔离配置解析器,并用 stat/access 检查目标与跳板身份文件的引用是否可读取;不读身份内容,不执行 SSH。返回 importable / reason / routeMode,不返回身份路径或配置原文。`POST /api/ssh/initialize` 要求明确同源 Origin、严格 aliases 字段和最多 200 个别名;提交时重新核对可导入状态,再通过原有关联事务保存引用。同名导入幂等,未通过检查时整批拒绝、提示重读;不写快照、连接计划或主机配置,不自动探测、删去无效条目或授予任务权限。此处的初始化与 MCP initialize 握手是两个独立概念。
|
|
34
|
-
|
|
35
|
-
面板使用组合写接口 `POST /api/devices/ssh/associate-and-check` 与 `POST /api/ssh/initialize-and-check`,保存引用后只为新增别名启动一次固定检查。`POST /api/devices/ssh/check-batch` 接受严格的 aliases 数组,最多 200 个、必须已关联且当前仍存在;队列按别名去重,所有检查共享两个并发限制。关闭网页不取消队列,进程重启不恢复未完成检查;已完成结果持久化。GET / MCP 不排队、不重试。前端仅在队列有工作时每秒读取库存,失败三次停止读取并提示刷新。
|
|
36
|
-
|
|
37
|
-
`POST /api/devices/ssh/remove` 也要求明确同源 Origin 和严格 aliases;拒绝移除正在检查或排队的条目。事务内删除指定引用、快照和计划,再写 `ssh_exclusions`。仅排除当前租户指定别名,不改系统配置或身份文件,也不自动删无效候选。排除项跨重启保留,其他租户不受影响。
|
|
38
|
-
|
|
39
|
-
库存 `ssh.connectivity` 区分 unobserved / queued / checking / passed / failed / stale / configuration-changed,并提供检查时间和失败码。通过认证后资源脚本不支持或失败,仍可标记 SSH 连通,指标与设备状态保持未知。只在已通过验钥的 OpenSSH 检查完成或收到远端命令退出状态时作此判断;SSH 错误、超时和资源错误不混淆。成功资源快照的原有五分钟状态仍保留,检查不授予远程任务权限。
|
|
40
|
-
|
|
41
|
-
只读 SSH 解析器按独立范围处理 `Match`。明确且纯静态的 `Match originalhost alias[,alias]` 只让它命中的目标或跳板配置进入人工核验;不将这段条件错误归入紧邻的前一个 Host。条件选项不会进入隔离检查配置;动态、通配或其他复杂条件仍按原规则停止核验,不执行条件命令。
|
|
42
|
-
|
|
43
|
-
`POST /api/devices/ssh/check` 同样要求明确同源 Origin,只接受已关联且当前仍存在的 alias;由所有者主动发起。它会真实执行固定远端只读采集,不能传入任意 shell、路径或命令。仅支持非 Windows 原生管理端;容器没有宿主认证权限。结果保存在独立快照表,原始 stdout/stderr 与私钥内容不进入数据库或响应。
|
|
44
|
-
|
|
45
|
-
本机模式不实施用户鉴权。可信范围仅是同一用户管理的本机,允许读取指标、登记引用和发起固定 SSH 采集;服务使用运行用户已有 SSH 认证,其他本机程序也可能访问端点并触发该采集。租户命名空间不是认证。初始化名称不用于识别所有者。不能只把监听地址改成 `0.0.0.0`。
|
|
46
|
-
|
|
47
|
-
个人云端模式由 `cloudAccess.mjs` 提供请求边界和显式认证方式;`unifiedAccess.mjs` 负责 App Services 身份核验。私有配置指定同父域名的账号站、HTTPS `/v1/me` 服务及唯一所有者邮箱。复用共享 HttpOnly 会话,不解码 JWT 作为信任、不复制签名密钥;身份结果缓存10秒,验证超时/异常拒绝访问,不回退密码。面板会话8小时、只存凭据摘要,需匹配当前共享身份;面板退出不退出其他应用,账号站退出/切换则使面板失效。未登录静态登录页与方式接口可访问;机器配对申请公开并限速,轮询/回报/断开要求独立身份签名,其余网页、库存及所有者写入口受保护;继续/退出严格同源,缓存与验证并发有上限。独立密码方式仍需显式私有scrypt配置,未知方式启动失败。后端回环监听,Nginx覆盖Host/协议头。云端库存与本机库存分开,未绑定时返回空设备,拒绝SSH/MCP设备接口,不读取服务器SSH。管理电脑身份、配对与回报由 driverProtocol.mjs、cloudRegistry.mjs、cloudLink.mjs 独立处理;浏览器会话不能代替机器签名。默认本机指标,SSH 名称/缓存分享需双重显式批准,不上传认证配置或私钥。云端不提供远程操作或多用户权限协议。参见[协议与生命周期](driver-binding.md)。
|
|
48
|
-
|
|
49
|
-
`DEVICE_CENTER_RUNTIME=container` 只供本机 Docker recipe 在容器网络中监听,Compose 对宿主机只发布回环端口。该环境变量并不能证明进程真的位于容器,不是安全鉴权开关;不要在原生启动时设置。Host/Origin 检查仍启用。Docker 默认端口映射经明确 Host IP 限制;实际运行未验证。
|
|
50
|
-
|
|
51
|
-
## 后续角色
|
|
7
|
+
- 本机 Driver:本机真实资源、已有 SSH 别名引用和缓存、回环 HTTP 面板/MCP;原生模式可显式绑定控制面,运行资源 Publisher 与获准日志 Agent。容器只代表自身。
|
|
8
|
+
- 云端控制面:统一账号鉴权、账号隔离的设备登记/回报/撤销、密文 Relay。不会读取服务器 SSH 或把服务器伪装成管理电脑;没有云端远程 shell/MCP。
|
|
52
9
|
|
|
53
10
|
```mermaid
|
|
54
11
|
flowchart LR
|
|
55
|
-
AI[
|
|
56
|
-
MCP
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Ref -.单独授权的任务适配器.-> Task[指定日志与受限任务]
|
|
61
|
-
Driver -.设备主动连接.-> Agent[资源设备 Agent]
|
|
62
|
-
Agent -.主动安全出站.-> Cloud[控制面与中继]
|
|
63
|
-
MCP -.获准 LAN 直连或中继.-> Cloud
|
|
12
|
+
AI[本机智能体] --> MCP[回环 MCP / 管理 Driver]
|
|
13
|
+
MCP -->|获准精确 LAN 地址 · 双向 TLS| Target[目标 Driver · 日志授权]
|
|
14
|
+
MCP -->|TLS 密文 / 签名 HTTPS| Relay[官方或自建控制面]
|
|
15
|
+
Relay -->|目标主动取帧| Target
|
|
16
|
+
Target -->|签名指标回报| Relay
|
|
64
17
|
```
|
|
65
18
|
|
|
66
|
-
|
|
19
|
+
## 模块
|
|
20
|
+
|
|
21
|
+
| 模块 | 职责 |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| index / cloudAccess / unifiedAccess | 本机请求边界、HTTPS代理验证、固定上游账号核验、会话 |
|
|
24
|
+
| inventory / sshConfig / sshProbe / sshRoute | 被动解析 SSH 元数据、显式只读检查、独立指标和核验路径 |
|
|
25
|
+
| driverProtocol / cloudRegistry | Ed25519 签名上下文、持久防重放、一次性配对、租户归属与资源时效 |
|
|
26
|
+
| certificates | 同设备身份的 X509 创建、指纹与自签验证 |
|
|
27
|
+
| relay | 有界密文帧队列、成员与撤销验证、持久日额度 |
|
|
28
|
+
| access / remote | 本机指纹信任、单文件限时授权、日志尾读、审计、标准双向 TLS、直连及回退 |
|
|
29
|
+
| connector | 四个本机只读工具,另有同账号设备查询和获准日志读取,共六个工具 |
|
|
30
|
+
| scripts/driver / access / service | 显式绑定、端上授权、用户级常驻;不会在 npm 安装钩子中运行 |
|
|
31
|
+
|
|
32
|
+
两条路径使用同一证书身份和端上授权。云端登记不授予日志权限;peer目录不能替换本机核对过的指纹。只有网络不可达可回退,认证错误停止。现有 SSH 设备的“连接计划”仍只保存元数据,与 Agent 通道分离。
|
|
33
|
+
|
|
34
|
+
TLS 记录分片经签名 HTTPS 请求转发,不自行设计密码协议。会话60秒,队列有上限;连接失败后不恢复/重放操作。当前仅只读日志,没有通用任务系统。参见[完整协议边界](remote-access.md)。
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# 访问路径与局域网优先
|
|
2
2
|
|
|
3
|
+
> 0.2.0-beta.1 更新:账号隔离、TLS 1.3 双向认证密文中转、独立授权的日志尾读及获准精确 LAN 优先已实现。旧文中的“尚未实现”传输描述属于此前阶段;实际操作与边界以 [远程日志](remote-access.md) 和 README 为准。通用远程命令、文件传输、Windows 原生 Agent 与自动迁移仍未提供。
|
|
3
4
|
## 当前能做什么
|
|
4
5
|
|
|
5
6
|
面板的每台设备显示配置路径,点击路径可查看节点、地址和端口。MCP 库存读取同一份信息。原生本机由进程直接采集;SSH 设备的路径来自保守解析并用于检查的配置,读取与展示时不调用 `ssh -G`、不解析动态命令、不探测 DNS 或网络。导入后一次检查、或用户手动重试,才实际访问已配置路径。
|
package/docs/driver-binding.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# 通过域名连接管理电脑
|
|
2
2
|
|
|
3
|
+
> 0.2.0-beta.1 更新:账号隔离、TLS 1.3 双向认证密文中转、独立授权的日志尾读及获准精确 LAN 优先已实现。旧文中的“尚未实现”传输描述属于此前阶段;实际操作与边界以 [远程日志](remote-access.md) 和 README 为准。通用远程命令、文件传输、Windows 原生 Agent 与自动迁移仍未提供。
|
|
3
4
|
当前支持个人控制面与 macOS / Linux 管理 Driver 的配对、只读资源回报和撤销。它不是远程终端或隧道;Windows Driver、独立安装器、系统钥匙串封装、远程任务和自动选路仍待实现。
|
|
4
5
|
|
|
5
6
|
## 三步接入
|
|
@@ -59,6 +60,10 @@ npm run service -- install --confirm --port 5174
|
|
|
59
60
|
|
|
60
61
|
云端保存公钥和 SHA256 指纹;配对码只保存 SHA256 摘要。所有者在现有个人登录边界内一次性批准,SQLite 事务消费请求,最多 16 个有效 Driver。机器轮询和回报需本机私钥签名,不依赖浏览器 cookie 或长期 Bearer token。签名涵盖固定协议、HTTPS Origin、POST 路径、Driver / 配对 ID、时间、随机数及排序后 JSON 的 SHA256;使用 Node 内置 Ed25519。随机数在 SQLite 保存三分钟,时间窗口 90 秒,拒绝重放,包括进程重启后的重放。
|
|
61
62
|
|
|
62
|
-
请求与响应上限 16 KiB
|
|
63
|
+
请求与响应上限 16 KiB,固定字段白名单;全实例每分钟最多八个配对申请;候选版本的查找与批准各自每账号八次、全实例各六十四次,最多 32 个待处理请求;配对轮询至少约五秒,回报至少 15 秒。公共申请入口仍可能遭遇拒绝服务,不适合直接扩为公开多用户托管。过期的配对请求与防重放记录按协议时效淘汰;已登记设备和回报不会自动清理。
|
|
63
64
|
|
|
64
65
|
当前测试验证隔离环境中的协议和 HTTP 接口。实际身份生成、用户批准、目标平台常驻、真实网络下连续回报需要由使用者执行接入后验收;不能以测试数据冒充已绑定设备。远程命令、文件传输与中继任务权限没有因配对而授予。
|
|
66
|
+
|
|
67
|
+
## 账号归属与候选版本
|
|
68
|
+
|
|
69
|
+
当前源码 beta.2 增加显式多用户账号隔离,未发布或部署;npm beta.1 客户端的机器配对/签名协议保持兼容。个人模式仍为默认;多用户的面板批准需同时提交码与完整指纹,归属只取服务核验的账号,不接受客户端 tenantId。历史个人记录不自动转移;多账号数据不能交给旧的无隔离服务器读取。详见[托管接入、迁移与回退](hosted-access.md)。
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# 本机、官方与自建接入
|
|
2
|
+
|
|
3
|
+
本版本 0.2.0-beta.1 使用同一 CLI 支持官方与自建 HTTPS 控制面;每个账号独立管理自己的设备。安装不自动接入,connect --confirm 默认申请官方服务,用户登录并核对批准后才绑定。
|
|
4
|
+
|
|
5
|
+
## 用户流程
|
|
6
|
+
|
|
7
|
+
1. **本机使用**:运行 Driver → 添加本机智能体的 MCP → 导入已有 SSH。本机没有平台注册要求,只监听回环地址。
|
|
8
|
+
2. **需要云端面板**:本机侧栏点“云端面板” → 官方控制面或自建 HTTPS 域名 → 复制命令,在自己的电脑运行。
|
|
9
|
+
3. **确认归属**:登录对应面板的账号 → 输入终端上的五分钟配对码 → 核对完整公钥指纹和分享范围 → 批准 → 等待首次真实回报。
|
|
10
|
+
|
|
11
|
+
官方多用户模式复用 App Services 的已验证账号;每账号最多16台有效 Driver、100MiB/UTC日密文中转。执行命令前需 Node.js 24,支持 macOS/Linux。安装不会自动配对,复制不会执行,配对不会安装常驻服务。
|
|
12
|
+
|
|
13
|
+
同一 CLI 的 `--cloud` 指向所选控制面;默认只回报本机名称、系统、内存、磁盘。SSH 名称与缓存回报需要命令申请并在面板再次批准。私钥不托管到云端、不包含在复制命令、prompt 或下载包中。
|
|
14
|
+
|
|
15
|
+
## 部署者选择账号模式
|
|
16
|
+
|
|
17
|
+
保持现有私有配置不变或明确设置 `accountMode: "personal"`,仍只接受配置的 `ownerEmail`;密码方式仍只支持个人模式。不会因为升级源码就允许其他账号进入。
|
|
18
|
+
|
|
19
|
+
本地验证后的候选可显式配置 App Services 多用户模式,示例均为占位信息:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"provider": "app-services",
|
|
24
|
+
"accountMode": "multi-user",
|
|
25
|
+
"backendOrigin": "https://appapi.example.com",
|
|
26
|
+
"accountOrigin": "https://example.com"
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
该模式只允许上游已验证的非匿名 email/Google/Apple 账号;本项目不新增注册接口。所有参与域名必须属于同一受信任父域名,并复用既有共享 HttpOnly 会话。不是任意第三方域名的 OAuth 登录实现。
|
|
31
|
+
|
|
32
|
+
服务器从固定上游 `/v1/me` 核验身份,将发行方与稳定 `profile.id` 的摘要作为租户命名空间;不按邮箱合并用户,也不信任客户端的 userId、tenantId、HTTP 头或 JWT 自解码。每次受保护请求只解析一次身份,列表、统计、回报展示、撤销与设备上限均使用该命名空间。机器回报的归属只能来自已登记 Driver,不能由请求指定。
|
|
33
|
+
|
|
34
|
+
多用户批准要求有效码与完整指纹,事务只允许消费一次。登记请求在批准前没有账号归属;持有配对码的账号可以查找,所以只在你自己的终端和面板之间使用,核对浏览器当前登录账号。批准后其他账号的查找/再次批准不可见,撤销其他账号的设备返回与不存在相同的 404。
|
|
35
|
+
|
|
36
|
+
### 旧个人数据与回退
|
|
37
|
+
|
|
38
|
+
`cloud_drivers.tenant_id` 是增量列;历史记录保留为 `cloud-owner`,不会删除、按设备名称合并或自动移交。
|
|
39
|
+
|
|
40
|
+
已有历史记录的部署切换为多用户时,必须在仓库外的私有配置中增加 `legacyOwnerId`,值为**通过可信 `/v1/me` 核验过的原所有者稳定 profile.id**。它仅把原所有者映射回历史命名空间,其他账号使用各自摘要;没有映射时启动拒绝,避免历史设备被遗失或错误归属。不要填邮箱、浏览器自报 ID 或另一个用户 ID。该值不是私钥,也不应放进公开配置示例或日志。
|
|
41
|
+
|
|
42
|
+
上线前备份 SQLite 与私有配置并验证映射。回退至个人模式只显示历史所有者设备,其他账号行保留。较旧的不支持租户查询的服务器版本会读出所有账号,因此**有多账号数据之后不可直接回退旧代码**:应停止服务并恢复切换前的完整数据库/配置备份,保留切换后备份供恢复。不能只切换二进制或 current 链接。
|
|
43
|
+
|
|
44
|
+
## 实际能力与边界
|
|
45
|
+
|
|
46
|
+
已实现账号隔离、一次性批准、签名资源回报与撤销,以及 TLS 1.3 双向认证的指定日志读取。两端必须独立核对指纹并在目标授权;绑定本身没有操作权限。获准 LAN 精确地址优先,网络不可达时回退 HTTPS 密文中转。见[远程日志](remote-access.md)。
|
|
47
|
+
|
|
48
|
+
每天每账号100MiB、全实例1GiB持久计数;单会话60秒、每账号2/全实例8并发、每方向16KiB/s。签名 nonce 全实例4096/180秒,公共登记8/分钟/32待批准;查找/批准每账号8/分钟/全局64/分钟。内存限流会随重启重置,日流量不会。当前固定默认额度,尚无计费、付费服务或 SLA。
|
|
49
|
+
|
|
50
|
+
任意命令、通用文件传输、云端 MCP、Windows 原生 Agent、CF 专用适配器和自动配置迁移尚未提供。自建/官方使用相同中转实现;CF 仅可作为用户自行配置的 HTTPS 前置。
|
|
51
|
+
|
|
52
|
+
隔离测试使用临时身份与注入上游,验证真实 Node TLS、中转密文、权限、账号和配额。它们不是对真实用户设备的授权验收,也不构成第三方安全审计。
|
package/docs/npm.md
CHANGED
|
@@ -1,53 +1,37 @@
|
|
|
1
1
|
# npm / npx 分发
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## 使用者
|
|
6
|
-
|
|
7
|
-
只看帮助或回报范围,不产生身份、不安装后台服务:
|
|
3
|
+
MIT,Node.js 24,macOS/Linux。当前版本 `0.2.0-beta.1`,使用 npm `beta` 渠道;是否上架以公开 registry 为准。
|
|
8
4
|
|
|
9
5
|
```sh
|
|
10
|
-
npx --yes device-center@0.
|
|
11
|
-
npx --yes device-center@0.
|
|
6
|
+
npx --yes device-center@0.2.0-beta.1 --help
|
|
7
|
+
npx --yes device-center@0.2.0-beta.1 plan
|
|
8
|
+
# 主动接入默认官方服务,执行后在终端与面板之间核对配对
|
|
9
|
+
npx --yes device-center@0.2.0-beta.1 connect --confirm
|
|
10
|
+
# 自建服务
|
|
11
|
+
npx --yes device-center@0.2.0-beta.1 connect --cloud https://你的控制面域名 --confirm
|
|
12
|
+
# 仅本机,无账号要求
|
|
13
|
+
npx --yes device-center@0.2.0-beta.1 start
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
安装与无参/help/version/plan 不生成身份,不配对,不自动启动后台进程。复制命令不含凭据。只有 connect --confirm 才生成本机身份并申请绑定;默认官方地址不会自动批准,用户需登录自己的账号。SSH 缓存分享须 --share-ssh 与面板再次批准。
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
npx --yes device-center@0.1.0-beta.1 connect --cloud https://你的控制面域名 --confirm
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
只有 `connect --confirm` 才在本机生成身份并申请配对;终端显示五分钟码,用户单独输入面板、核对完整指纹和范围并批准。CLI 要求明确的 `--cloud`,不会默认把公开用户的电脑绑定到开发者的个人域名。SSH 名称/缓存分享需要 `--share-ssh` 与面板再次勾选批准。没有远程任务授权,详见[绑定说明](driver-binding.md)。
|
|
21
|
-
|
|
22
|
-
只在本机/局域网现有 SSH 配置下使用,不接云端:
|
|
18
|
+
面板和本机 MCP:`http://127.0.0.1:5174/`、`/mcp`。常驻先固定安装:
|
|
23
19
|
|
|
24
20
|
```sh
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
打开 `http://127.0.0.1:5174`;智能体 MCP 为 `http://127.0.0.1:5174/mcp`。只监听回环地址,不开放局域网端口。关闭网页不退出进程,终端 Ctrl+C 才停止。已有运行实例复用,其他端口占用会提示,不结束其他进程。
|
|
29
|
-
|
|
30
|
-
常驻需要固定安装位置,不能指向会被清理的 npx 缓存:
|
|
31
|
-
|
|
32
|
-
```sh
|
|
33
|
-
npm install -g device-center@0.1.0-beta.1
|
|
21
|
+
npm install -g device-center@0.2.0-beta.1
|
|
34
22
|
device-center service plan --port 5174
|
|
35
|
-
#
|
|
23
|
+
# 自行停止同端口前台进程,再主动安装
|
|
36
24
|
device-center service install --port 5174 --confirm
|
|
37
25
|
```
|
|
38
26
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
## 发布者
|
|
42
|
-
|
|
43
|
-
本包使用显式文件白名单:CLI、运行源码、前端静态文件、Driver/服务脚本和必要说明。数据库、SSH/身份文件、认证配置、部署记录、测试 fixture、开发目录和归档均不发布;没有 install/postinstall/prepare 自动脚本。开发依赖与运行依赖当前均为零。
|
|
27
|
+
数据在用户应用数据目录,更新包不重置身份或数据库;npx 缓存不得用作常驻目录。Windows 原生身份存储和用户服务尚未提供。
|
|
44
28
|
|
|
45
|
-
|
|
29
|
+
远程指定日志需两端各自明确授权,见[远程日志](remote-access.md)。无通用远程命令或文件传输。
|
|
46
30
|
|
|
47
|
-
|
|
31
|
+
## 发布验证
|
|
48
32
|
|
|
49
|
-
|
|
33
|
+
包采用显式白名单,没有 install/postinstall/prepare 钩子;数据库、身份、SSH、认证配置、部署记录和测试不发布。标准 TLS 使用 Node/OpenSSL,X509 创建使用固定版本 @peculiar/x509 与 reflect-metadata,`npm-shrinkwrap.json` 固定传递依赖和 integrity;不再是零依赖包。源码解压后先 `npm ci --ignore-scripts`。
|
|
50
34
|
|
|
51
|
-
|
|
35
|
+
发布前运行 check/test/verify:package;后者在独立临时 HOME 中无凭据从官方 registry 取得依赖,随后离线安装本次 tar、检查真实 bin/npx/前台 HTTP。候选归档、逐文件摘要、Git 基线、dirty 快照事实及验证结果保留在本机 npm-candidates。只清理本次测试临时目录,不清理用户数据。工作区快照不称为 main CI 构建。
|
|
52
36
|
|
|
53
|
-
|
|
37
|
+
固定新版本 `npm publish <已验证tar> --access public --tag beta`。密码、发布验证与 OTP 由用户在 npm 官方页面自行处理,不进聊天或归档。发布后匿名查询 registry、核对 SHA512 integrity 和 tar 字节,并运行帮助/计划。GitHub 仓库公开与 npm 发布是独立操作,本轮不改变 GitHub 可见性。
|