docs: 确认全部默认项并补充发布、许可证和最低版本要求

This commit is contained in:
Nixevol
2026-09-30 05:22:15 +08:00
parent 2ab09507ff
commit 6daaa95f1f
5 changed files with 74 additions and 38 deletions
+10
View File
@@ -0,0 +1,10 @@
Copyright (c) 2026 Nixevol. All rights reserved.
本仓库的源代码、文档、各语言 SDK 和构建产物(包括发布的软件包和 Docker 镜像)均为专有软件。
源代码和发布物公开可读,不代表授予任何使用许可。未经版权所有者书面许可,不得使用、复制、
修改、合并、发布、分发、再许可或出售其任何部分。
This repository, including its source code, documentation, SDKs and build artifacts (including
published packages and Docker images), is proprietary software. Public visibility does not grant
any license. No part of it may be used, copied, modified, merged, published, distributed,
sublicensed or sold without prior written permission from the copyright holder.
+4
View File
@@ -12,3 +12,7 @@
## 状态 ## 状态
需求和设计已完成,正在开发。构建、运行和部署说明在开发完成后补充。 需求和设计已完成,正在开发。构建、运行和部署说明在开发完成后补充。
## 许可证
专有软件,见 [LICENSE](LICENSE)。源代码和发布物公开可读,不代表授予使用许可。
+28 -18
View File
@@ -1,6 +1,6 @@
# NixMsg 开发说明 # NixMsg 开发说明
读者是实现本期功能的开发组。产品行为以 [PRD.md](./PRD.md) 为准,本文对应 PRD 0.4,规定怎么实现。两者冲突时改代码以 PRD 为准,并把差异写进 `docs/DEVIATIONS.md`(日期、原条款、实际做法、原因),交给后续审核。 读者是实现本期功能的开发组。产品行为以 [PRD.md](./PRD.md) 为准,本文对应 PRD 0.5,规定怎么实现。两者冲突时改代码以 PRD 为准,并把差异写进 `docs/DEVIATIONS.md`(日期、原条款、实际做法、原因),交给后续审核。
文中「必须」是验收项,「不要」是已知会做错的实现。本文对 mochi-mqtt、coder/websocket、autopaho、modernc sqlite 内部行为的说明,已在 2026-09-30 对照它们主分支的源码核对过;升级这些依赖的大版本时要重新核对。 文中「必须」是验收项,「不要」是已知会做错的实现。本文对 mochi-mqtt、coder/websocket、autopaho、modernc sqlite 内部行为的说明,已在 2026-09-30 对照它们主分支的源码核对过;升级这些依赖的大版本时要重新核对。
@@ -56,6 +56,10 @@ flowchart LR
| 部署 | 单文件二进制为主,同时提供 Docker 镜像(`linux/amd64`、`linux/arm64`)和 docker-compose 示例 | 第 11 节 | | 部署 | 单文件二进制为主,同时提供 Docker 镜像(`linux/amd64`、`linux/arm64`)和 docker-compose 示例 | 第 11 节 |
| 监控 | Prometheus 格式的 `/metrics` | 访问限制见第 4.3 节 | | 监控 | Prometheus 格式的 `/metrics` | 访问限制见第 4.3 节 |
| 证书 | 程序读取证书文件,文件变了自动重载 | 生产环境由 1Panel 申请和自动续签,推送到本地目录给程序读(第 11.3 节) | | 证书 | 程序读取证书文件,文件变了自动重载 | 生产环境由 1Panel 申请和自动续签,推送到本地目录给程序读(第 11.3 节) |
| SDK 发布 | 发布到 Gitea 包仓库(git.asio.asia,所有者 nixevol):npm `@nixevol/nixmsg`、PyPI `nixmsg`、Maven `asia.asio.nixmsg:nixmsg-sdk`;Go SDK 直接从代码仓库获取,模块 `git.asio.asia/nixevol/NixMsg/sdk/go` | 第 9 节 |
| Docker 镜像 | 推到 Gitea 容器仓库 `git.asio.asia/nixevol/nixmsg` | 第 11.4 节 |
| CI | 本期不做;总控合并前在本机跑全量验证 | TASKS.md 第 4.3 节 |
| 许可证和可见性 | 专有许可证,见仓库根目录 `LICENSE`;源码仓库、SDK 包、镜像都公开可读,公开不代表授权使用 | 各 SDK 的包信息写同样的许可证 |
### 2.2 按推荐定下的其余部分 ### 2.2 按推荐定下的其余部分
@@ -82,12 +86,12 @@ flowchart LR
这里只列各语言 SDK 依赖的 MQTT 客户端库,SDK 的行为见第 9 节。 这里只列各语言 SDK 依赖的 MQTT 客户端库,SDK 的行为见第 9 节。
| SDK | 依赖 | 说明 | | SDK | 依赖 | 说明 | 最低支持 |
|---|---|---| |---|---|---|---|
| Go | `github.com/eclipse/paho.golang/autopaho` | MQTT 5、自动重连、支持 WebSocket | | Go | `github.com/eclipse/paho.golang/autopaho` | MQTT 5、自动重连、支持 WebSocket | 和服务端相同的 Go 版本 |
| JS/TS | MQTT.js 5.x | 浏览器和 Node 都能用 | | JS/TS | MQTT.js 5.x | 浏览器和 Node 都能用 | Node.js 20;近两年发布的 Chrome、Edge、Firefox、Safari |
| Python | paho-mqtt 2.x,`CallbackAPIVersion.VERSION2` | 同步接口为主,另给 asyncio 包装 | | Python | paho-mqtt 2.x,`CallbackAPIVersion.VERSION2` | 同步接口为主,另给 asyncio 包装 | Python 3.10 |
| Java/Android | HiveMQ MQTT Client,加上 websocket 模块 | Java 8+,Android API 24+ | | Java/Android | HiveMQ MQTT Client,加上 websocket 模块 | 同一套 jar 给 Java 和 Android 用 | Java 8;Android API 24 |
### 2.4 后台界面 ### 2.4 后台界面
@@ -108,6 +112,7 @@ flowchart LR
- 帮助图标用 `n-tooltip`;错误和关键状态用 `n-alert` 或表单校验信息直接显示。 - 帮助图标用 `n-tooltip`;错误和关键状态用 `n-alert` 或表单校验信息直接显示。
- 弹窗用 `n-modal`(`preset="card"`),按钮放在 `footer` 插槽,正文放进 `n-scrollbar` 单独滚动。 - 弹窗用 `n-modal`(`preset="card"`),按钮放在 `footer` 插槽,正文放进 `n-scrollbar` 单独滚动。
- 表格用 `n-data-table`:`remote` 做服务端分页,设 `max-height` 让表格内部滚动,长列表开 `virtual-scroll`。 - 表格用 `n-data-table`:`remote` 做服务端分页,设 `max-height` 让表格内部滚动,长列表开 `virtual-scroll`。
- 所有时间按浏览器本地时区显示,格式 `YYYY-MM-DD HH:mm:ss`;接口里一律用 Unix 毫秒。
- 只用 Naive UI 一套组件库,不要混用 Element Plus 等其他库。 - 只用 Naive UI 一套组件库,不要混用 Element Plus 等其他库。
## 3. 仓库 ## 3. 仓库
@@ -248,7 +253,7 @@ Capabilities:
| 钩子 | 行为 | | 钩子 | 行为 |
|---|---| |---|---|
| `OnConnect` | 分配连接代号,校正心跳,然后查编号、停用,按下文「登录与会话令牌」校验会话令牌或登录密码(含锁定),把结论记在这个连接上。数据库出错等内部故障时返回 error:mochi 不回 CONNACK 直接断开,客户端按网络故障重连 | | `OnConnect` | 分配连接代号,校正心跳,然后查编号、停用,按下文「登录与会话令牌」校验会话令牌或登录密码(含锁定),把结论记在这个连接上。数据库出错等内部故障时返回 error:mochi 不回 CONNACK 直接断开,客户端按网络故障重连 |
| `OnConnectAuthenticate` | 只返回 `OnConnect` 记下的结论。返回 false 时 mochi 回「用户名或密码错误」,SDK 会停止重连,所以只有编号不存在、已停用、密码错误、已锁定这几种情况能返回 false | | `OnConnectAuthenticate` | 只返回 `OnConnect` 记下的结论。返回 false 时 mochi 回「用户名或密码错误」,SDK 会停止重连,所以只有编号不存在、已停用、密码错误、会话令牌无效或过期、已锁定这几种情况能返回 false |
| `OnACLCheck` | 只允许上面这一对主题。发布检查 `write=true`;订阅和服务器下发检查 `write=false` | | `OnACLCheck` | 只允许上面这一对主题。发布检查 `write=true`;订阅和服务器下发检查 `write=false` |
| `OnPublish` | 拷贝 topic 和 payload 后交给该端的串行队列。返回 `packets.CodeSuccessIgnore`,让客户端拿到 PUBACK,同时不把这条转发给任何订阅者 | | `OnPublish` | 拷贝 topic 和 payload 后交给该端的串行队列。返回 `packets.CodeSuccessIgnore`,让客户端拿到 PUBACK,同时不把这条转发给任何订阅者 |
| `OnPublishDropped` | 下行没写进连接的发送队列。把对应投递或回执的「已推送」标记清掉,1 秒后重推,别对慢客户端空转 | | `OnPublishDropped` | 下行没写进连接的发送队列。把对应投递或回执的「已推送」标记清掉,1 秒后重推,别对慢客户端空转 |
@@ -919,7 +924,7 @@ API 令牌,给接入方后台用程序调用管理接口:
所有 JSON 响应在序列化前去掉正文。测试里对管理接口的响应做一次「不含 body 字段」的检查。 所有 JSON 响应在序列化前去掉正文。测试里对管理接口的响应做一次「不含 body 字段」的检查。
`nixmsg serve` 发现库里没有管理员密码时拒绝启动,提示先运行 `nixmsg admin init`。不要自动生成密码再打到日志里。`admin init` 生成 20 位密码,只在终端打印一次,库里存哈希;已经初始化过的库拒绝执行,改用 `admin set-password`。 `nixmsg serve` 发现库里没有管理员密码时拒绝启动,提示先运行 `nixmsg admin init`。不要自动生成密码再打到日志里。`admin init` 生成 20 位密码,只在终端打印一次,库里存哈希;已经初始化过的库拒绝执行,改用 `admin set-password`。管理员密码至少 12 位,`admin set-password` 和 `/api/admin/password` 都要校验。
## 9. SDK ## 9. SDK
@@ -962,7 +967,7 @@ close()
- 发送队列在内存,默认最多 1000 条,包括已发出但没收到 `resp` 的。连不上时 `send` 入队;重连后按原消息号、原请求内容再交。 - 发送队列在内存,默认最多 1000 条,包括已发出但没收到 `resp` 的。连不上时 `send` 入队;重连后按原消息号、原请求内容再交。
- `sendAt` 在调用 `send` 时就换算成 `send_at_ms`,重交时不重算,否则请求指纹变了会被当成冲突。 - `sendAt` 在调用 `send` 时就换算成 `send_at_ms`,重交时不重算,否则请求指纹变了会被当成冲突。
- 同时在途(已发出、没收到 `resp`)的请求不超过 100 个。发送收到 `rate_limited` 时按退避自动重交,不算失败;其他请求收到 `rate_limited` 直接返回给应用。 - 同时在途(已发出、没收到 `resp`)的请求不超过 100 个。发送收到 `rate_limited` 时按退避自动重交,不算失败;其他请求收到 `rate_limited` 直接返回给应用。
- 进程退出则队列丢失。SDK 停止重连(被踢、认证失败、`close`)时,队列里的发送全部以对应错误结束。 - 进程退出则队列丢失。SDK 停止重连(被踢、认证失败、`logout`、`close`)时,队列里的发送全部以对应错误结束。
- 其他调用在未握手时返回未连接。 - 其他调用在未握手时返回未连接。
接收: 接收:
@@ -984,14 +989,17 @@ close()
各语言包装: 各语言包装:
| 语言 | 包 | 接口形态 | | 语言 | 包名 | 获取方式 | 接口形态 |
|---|---|---| |---|---|---|---|
| Go | `github.com/nixmsg/nixmsg-sdk-go` | context,方法返回 error | | Go | 模块 `git.asio.asia/nixevol/NixMsg/sdk/go`,包名 `nixmsg` | `go get git.asio.asia/nixevol/NixMsg/sdk/go@v0.1.0`(仓库打 `sdk/go/v0.1.0` 标签) | context,方法返回 error |
| JS/TS | `@nixmsg/sdk` | Promise,ESM 和 CJS 都发 | | JS/TS | `@nixevol/nixmsg` | Gitea npm 仓库 `https://git.asio.asia/api/packages/nixevol/npm/` | Promise,ESM 和 CJS 都发 |
| Python | `nixmsg` | 同步为主;`asyncio` 包装放在同一包 | | Python | `nixmsg`(导入名也是 `nixmsg`) | Gitea PyPI 仓库 `https://git.asio.asia/api/packages/nixevol/pypi/simple/` | 同步为主;`asyncio` 包装放在同一包 |
| Java | `com.nixmsg:nixmsg-sdk` | `CompletableFuture`。Android 最低 API 24,长连接由应用自己放到前台服务 | | Java | `asia.asio.nixmsg:nixmsg-sdk`(Java 包 `asia.asio.nixmsg`) | Gitea Maven 仓库 `https://git.asio.asia/api/packages/nixevol/maven` | `CompletableFuture`。长连接由 Android 应用自己放到前台服务 |
包名是占位。正式名称和发布渠道(GitHub 组织、npm scope、PyPI 名、Maven groupId)由负责人确认拥有权后再定。Go 模块路径必须和实际仓库地址一致,放在本仓库 `sdk/go` 下时就是「仓库路径/sdk/go」。 - Go SDK 放在 `sdk/go`,但 `go` 是关键字,包名用 `nixmsg`。它是仓库里单独的 Go 模块,版本标签带目录前缀(`sdk/go/v0.1.0`)。仓库公开,接入方直接 `go get`;公共代理访问不到 git.asio.asia 时,设 `GOPRIVATE=git.asio.asia` 直连。
- 接入方的配置:npm 在 `.npmrc` 里写 `@nixevol:registry=https://git.asio.asia/api/packages/nixevol/npm/`;pip 用 `--index-url` 指向上面的 PyPI 地址;Gradle 或 Maven 加上面的仓库地址。包是公开的,下载不用登录。
- 包信息里的许可证:npm 写 `"license": "SEE LICENSE IN LICENSE"`;PyPI 用 `license = { file = "LICENSE" }` 并加分类 `License :: Other/Proprietary License`;Maven 的 `<licenses>` 写 `Proprietary`。每个包都带上仓库根目录的 `LICENSE`。
- 发布只在阶段 3 由总控执行(TASKS.md Z3)。用 Gitea 个人访问令牌,只给 `package` 读写权限;令牌存进 MemRelay 密码库,只写在本机用户级配置里(用户目录下的 `.npmrc`、`.pypirc`、`.gradle/gradle.properties`),不进仓库。
接入清单(每种语言一份集成测试,对真实服务器二进制): 接入清单(每种语言一份集成测试,对真实服务器二进制):
@@ -1082,6 +1090,7 @@ data/nixmsg.db
data/backup/ data/backup/
``` ```
- 程序本身不做定时备份。用 1Panel 计划任务或 cron 定时执行 `nixmsg backup --out <路径>`;Docker 部署时执行 `docker compose exec nixmsg /nixmsg backup --out /data/backup/<文件名>.db`。旧备份按需要自己清理。
- 备份文件包含备份当时还没送完的正文,要按敏感数据保管。 - 备份文件包含备份当时还没送完的正文,要按敏感数据保管。
- systemd 示例只需要 `ExecStart`、`WorkingDirectory`、`Restart=on-failure`。Windows 上用 WinSW、NSSM 之类的工具托管成服务,本期不在程序里内置服务安装。 - systemd 示例只需要 `ExecStart`、`WorkingDirectory`、`Restart=on-failure`。Windows 上用 WinSW、NSSM 之类的工具托管成服务,本期不在程序里内置服务安装。
- 服务器开启 NTP 对时。 - 服务器开启 NTP 对时。
@@ -1104,6 +1113,7 @@ data/backup/
### 11.4 Docker ### 11.4 Docker
- 镜像多阶段构建:Node 构建前端 → Go 编译(嵌入前端)→ `gcr.io/distroless/static` 的 `nonroot` 变体。入口是 `/nixmsg`。发布 `linux/amd64`、`linux/arm64` 两个架构。 - 镜像多阶段构建:Node 构建前端 → Go 编译(嵌入前端)→ `gcr.io/distroless/static` 的 `nonroot` 变体。入口是 `/nixmsg`。发布 `linux/amd64`、`linux/arm64` 两个架构。
- 镜像名 `git.asio.asia/nixevol/nixmsg`。每次发布打版本号标签(如 `0.1.0`)和 `latest`,用 `docker buildx` 一次推送两个架构。推送前 `docker login git.asio.asia`,用和 SDK 发布同一个 Gitea 令牌。镜像是公开的,部署服务器拉取不用登录。
- 容器里的路径:配置 `/etc/nixmsg/config.yaml`(`NIXMSG_CONFIG` 指向它),数据目录 `/data`(配置里写 `data_dir: /data`),证书目录 `/certs` 只读挂载。 - 容器里的路径:配置 `/etc/nixmsg/config.yaml`(`NIXMSG_CONFIG` 指向它),数据目录 `/data`(配置里写 `data_dir: /data`),证书目录 `/certs` 只读挂载。
- 首次使用先执行 `docker compose run --rm nixmsg admin init`,记下只打印一次的管理员密码,再 `docker compose up -d`。 - 首次使用先执行 `docker compose run --rm nixmsg admin init`,记下只打印一次的管理员密码,再 `docker compose up -d`。
- 容器以 uid 65532 运行:挂载的数据目录要可写,证书私钥要可读。 - 容器以 uid 65532 运行:挂载的数据目录要可写,证书私钥要可读。
@@ -1112,7 +1122,7 @@ data/backup/
```yaml ```yaml
services: services:
nixmsg: nixmsg:
image: nixmsg:0.1.0 image: git.asio.asia/nixevol/nixmsg:0.1.0
restart: unless-stopped restart: unless-stopped
command: ["serve"] command: ["serve"]
environment: environment:
+17 -9
View File
@@ -2,9 +2,9 @@
| 项 | 内容 | | 项 | 内容 |
|---|---| |---|---|
| 版本 | 0.4 | | 版本 | 0.5 |
| 日期 | 2026-09-30 | | 日期 | 2026-09-30 |
| 状态 | 待复核后交给开发 | | 状态 | 已确认,可交给开发 |
| 读者 | 产品负责人、开发组、后续审核 | | 读者 | 产品负责人、开发组、后续审核 |
| 配套 | [DEVELOPMENT.md](./DEVELOPMENT.md) 是实现规范。两者冲突时,以本文已确认的产品行为为准,并在 `docs/DEVIATIONS.md` 记录 | | 配套 | [DEVELOPMENT.md](./DEVELOPMENT.md) 是实现规范。两者冲突时,以本文已确认的产品行为为准,并在 `docs/DEVIATIONS.md` 记录 |
| 修订 | 见第 11 节 | | 修订 | 见第 11 节 |
@@ -358,7 +358,7 @@ NixMsg 是一套自建的消息中转服务。设备、程序、App 都作为「
网页后台,界面中文。功能: 网页后台,界面中文。功能:
- 登录、修改管理员自己的密码、退出。 - 登录、修改管理员自己的密码(至少 12 位)、退出。页面上的时间都按浏览器本地时区显示。
- 概览:端数量(其中自助注册的数量)、在线数、群数量、待投递数、版本。 - 概览:端数量(其中自助注册的数量)、在线数、群数量、待投递数、版本。
- 端:查询(可按来源筛选:后台开通、自助注册)、开通、批量开通、编辑、启停、删除、重置登录密码、设置或清除对话密码、踢下线、解除登录锁定。列表显示是否在线、最近上下线时间、来源;支持多选后批量停用、删除,方便清理异常注册。 - 端:查询(可按来源筛选:后台开通、自助注册)、开通、批量开通、编辑、启停、删除、重置登录密码、设置或清除对话密码、踢下线、解除登录锁定。列表显示是否在线、最近上下线时间、来源;支持多选后批量停用、删除,方便清理异常注册。
- 注册:开启或关闭自助注册;查看、手填或生成注册安全码。 - 注册:开启或关闭自助注册;查看、手填或生成注册安全码。
@@ -400,6 +400,8 @@ NixMsg 是一套自建的消息中转服务。设备、程序、App 都作为「
- 修改自己的名称、默认延迟、登录密码(需要旧密码)、对话密码。 - 修改自己的名称、默认延迟、登录密码(需要旧密码)、对话密码。
- 发送方暂时连不上服务器时,发送进入内存队列,重连后按原消息号再交;已经发出但没等到结果的也一样。进程退出则队列丢失。除发送以外的请求在离线时直接失败。 - 发送方暂时连不上服务器时,发送进入内存队列,重连后按原消息号再交;已经发出但没等到结果的也一样。进程退出则队列丢失。除发送以外的请求在离线时直接失败。
- 本机时间与服务器偏差由 SDK 校正后再计算定时发送。 - 本机时间与服务器偏差由 SDK 校正后再计算定时发送。
- 最低支持:Node.js 20、近两年发布的主流浏览器、Python 3.10、Java 8、Android API 24(D30)。
- 发布:npm 包 `@nixevol/nixmsg`、PyPI 包 `nixmsg`、Maven 包 `asia.asio.nixmsg:nixmsg-sdk` 发布到 Gitea 包仓库(git.asio.asia);Go SDK 直接从代码仓库获取,模块 `git.asio.asia/nixevol/NixMsg/sdk/go`。
验收:每种语言都通过 DEVELOPMENT.md 里的同一份接入清单。清单覆盖注册、登录、收发、去重、重连、离线队列、撤回、定时、群、对话密码、改密、被踢、超限。 验收:每种语言都通过 DEVELOPMENT.md 里的同一份接入清单。清单覆盖注册、登录、收发、去重、重连、离线队列、撤回、定时、群、对话密码、改密、被踢、超限。
@@ -425,10 +427,11 @@ NixMsg 是一套自建的消息中转服务。设备、程序、App 都作为「
### F22 部署与运维 ### F22 部署与运维
- 一个 Go 程序,一个可执行文件,内置 MQTT 和网页。不另外部署数据库、消息队列或缓存。 - 一个 Go 程序,一个可执行文件,内置 MQTT 和网页。不另外部署数据库、消息队列或缓存。
- 同时提供 Docker 镜像(amd64、arm64)和 docker-compose 示例,装有 1Panel 的服务器可以直接用它的容器编排部署。 - 同时提供 Docker 镜像(amd64、arm64,发布在 `git.asio.asia/nixevol/nixmsg`)和 docker-compose 示例,装有 1Panel 的服务器可以直接用它的容器编排部署。
- 数据在一个目录里的 SQLite 文件。 - 数据在一个目录里的 SQLite 文件。
- 首次使用先运行初始化命令生成管理员密码(只在终端显示一次,不写日志),再启动服务。 - 首次使用先运行初始化命令生成管理员密码(只在终端显示一次,不写日志),再启动服务。
- 提供备份命令。升级时自动迁移数据库;迁移前自动把库复制一份。 - 提供备份命令。程序本身不做定时备份,用 1Panel 计划任务或 cron 定时调用(D32)。升级时自动迁移数据库;迁移前自动把库复制一份。
- 源码、SDK 包和镜像都公开可读;许可证为专有,见仓库根目录的 LICENSE(D33)。
- 提供健康检查接口,以及 Prometheus 格式的监控指标(在线数、待投递数、投递耗时等,不含正文和编号明细)。指标只在后台端口上开放;后台和端共用端口时,要带配置的令牌才能访问。 - 提供健康检查接口,以及 Prometheus 格式的监控指标(在线数、待投递数、投递耗时等,不含正文和编号明细)。指标只在后台端口上开放;后台和端共用端口时,要带配置的令牌才能访问。
验收: 验收:
@@ -507,7 +510,7 @@ stateDiagram-v2
## 9. 写进本文的默认 ## 9. 写进本文的默认
下面是写文档时定下的默认规则。「已确认」是负责人已经认可的;「待确认」的在交给开发前还可以改,改的话同步改本文和 DEVELOPMENT.md 对应小节。D14 起是 0.2 新增,D26 起是 0.3 新增,D28 起是 0.4 新增。 下面是写文档时定下的默认规则,已全部由负责人确认。以后要改,同步改本文和 DEVELOPMENT.md 对应小节,并在第 11 节记录。D14 起是 0.2 新增,D26 起是 0.3 新增,D28 起是 0.4 新增,D30 起是 0.5 新增。
| 编号 | 默认 | 状态 | | 编号 | 默认 | 状态 |
|---|---|---| |---|---|---|
@@ -528,7 +531,7 @@ stateDiagram-v2
| D15 | 注册时编号可以自选也可以留空生成;登录密码留空则服务器生成并只返回一次;注册不需要审核 | 已确认 2026-09-30 | | D15 | 注册时编号可以自选也可以留空生成;登录密码留空则服务器生成并只返回一次;注册不需要审核 | 已确认 2026-09-30 |
| D16 | 不做忘记密码自助找回和端自己注销,都由管理员处理 | 已确认 2026-09-30 | | D16 | 不做忘记密码自助找回和端自己注销,都由管理员处理 | 已确认 2026-09-30 |
| D17 | 端编号和群编号只允许小写字母、数字、`_`、`.`、`-`;消息号区分大小写 | 已确认 2026-09-30 | | D17 | 端编号和群编号只允许小写字母、数字、`_`、`.`、`-`;消息号区分大小写 | 已确认 2026-09-30 |
| D18 | 登录密码失败按「编号 + 来源 IP」锁定(5 分钟 10 次),另按编号计总数暂停密码登录(1 小时 50 次);会话令牌重连不受锁定影响;注册安全码按来源 IP 锁定 | 按 2026-09-30 反馈修改,待确认 | | D18 | 登录密码失败按「编号 + 来源 IP」锁定(5 分钟 10 次),另按编号计总数暂停密码登录(1 小时 50 次);会话令牌重连不受锁定影响;注册安全码按来源 IP 锁定 | 已确认 2026-09-30 |
| D19 | 不保留的消息推给在线端后,确认超时(5 分钟)仍未确认就按已丢弃结束,不再重推;保留的消息在保留期内继续重推 | 已确认 2026-09-30 | | D19 | 不保留的消息推给在线端后,确认超时(5 分钟)仍未确认就按已丢弃结束,不再重推;保留的消息在保留期内继续重推 | 已确认 2026-09-30 |
| D20 | 撤回不单独发回执,结果看撤回请求的返回 | 已确认 2026-09-30 | | D20 | 撤回不单独发回执,结果看撤回请求的返回 | 已确认 2026-09-30 |
| D21 | 停用或删除端时,它发出、还没推送的消息一并作废 | 已确认 2026-09-30 | | D21 | 停用或删除端时,它发出、还没推送的消息一并作废 | 已确认 2026-09-30 |
@@ -537,9 +540,13 @@ stateDiagram-v2
| D24 | 对话密码另按被猜的端限总数:1 小时错 50 次后暂停新的验证 1 小时,已有授权不受影响 | 已确认 2026-09-30 | | D24 | 对话密码另按被猜的端限总数:1 小时错 50 次后暂停新的验证 1 小时,已有授权不受影响 | 已确认 2026-09-30 |
| D25 | 每个端未完成的发出消息最多 10000 条,排队待收的投递最多 10000 条;都可配置,设为 0 表示不设上限 | 已确认 2026-09-30 | | D25 | 每个端未完成的发出消息最多 10000 条,排队待收的投递最多 10000 条;都可配置,设为 0 表示不设上限 | 已确认 2026-09-30 |
| D26 | 开放自助注册后,目录仍对所有端可见,谁都能列出全部端 | 已确认 2026-09-30 | | D26 | 开放自助注册后,目录仍对所有端可见,谁都能列出全部端 | 已确认 2026-09-30 |
| D27 | 管理 API 令牌不过期,停用或删除后立即失效;权限等同管理员,但不能改管理员密码、不能管理令牌;令牌只在创建时显示一次 | 待确认 | | D27 | 管理 API 令牌不过期,停用或删除后立即失效;权限等同管理员,但不能改管理员密码、不能管理令牌;令牌只在创建时显示一次 | 已确认 2026-09-30 |
| D28 | 每次用密码登录都换新的会话令牌,旧令牌立即作废,旧设备自动退出 | 已确认 2026-09-30(负责人提出) | | D28 | 每次用密码登录都换新的会话令牌,旧令牌立即作废,旧设备自动退出 | 已确认 2026-09-30(负责人提出) |
| D29 | 用令牌重连不换令牌;令牌 30 天没用自动失效(可配置,0 表示不失效);登录密码不能以 `nst_` 开头;端可以主动退出登录、作废令牌 | 待确认 | | D29 | 用令牌重连不换令牌;令牌 30 天没用自动失效(可配置,0 表示不失效);登录密码不能以 `nst_` 开头;端可以主动退出登录、作废令牌 | 已确认 2026-09-30 |
| D30 | SDK 最低支持 Node.js 20、近两年发布的主流浏览器、Python 3.10、Java 8、Android API 24;Go SDK 和服务端的 Go 版本要求相同 | 已确认 2026-09-30 |
| D31 | 管理员密码至少 12 位;后台所有时间按浏览器本地时区显示 | 已确认 2026-09-30 |
| D32 | 程序本身不做定时备份,用 1Panel 计划任务或 cron 定时调用备份命令 | 已确认 2026-09-30 |
| D33 | 源码仓库、SDK 包、Docker 镜像都公开可读;许可证为专有,公开不代表授权使用 | 已确认 2026-09-30 |
## 10. 验收总表 ## 10. 验收总表
@@ -579,3 +586,4 @@ stateDiagram-v2
| 0.2 | 2026-09-30 | 端口改为「端只用一个固定端口,后台可用单独端口」(F21)。新增端自助注册(F23),从「本期不做」中移除。按审查补充和修正:编号只允许小写(F01、F16);批量开通整批校验(F01);停用或删除端时作废它发出的消息,删除后编号可复用(F01);登录锁定按编号加 IP,并区分服务器故障(F02);消息号按请求内容判冲突,防重标记与记录并存(F05、F18);请求频率上限写入需求(F05);接收上限按整条数据计算(F07);不保留消息的确认超时(F08、F09);服务器重启后的宽限和补发(F10、F11);撤回结果的判定和不发回执(F13、F14);解散群时作废定时消息(F16);后台批量停用、删除和注册设置(F17);首次启动先初始化(F22);单位统一为 KiB;重试先认防重再校验(F05);每个端未完成消息和排队投递的上限(F05);对话密码另按被猜的端限总数(F15);后台端列表显示在线状态(F17);注册安全码和明文传输的提醒(F23);手机 App 在后台收不到提醒的说明(5.2);新增默认 D14–D25 | | 0.2 | 2026-09-30 | 端口改为「端只用一个固定端口,后台可用单独端口」(F21)。新增端自助注册(F23),从「本期不做」中移除。按审查补充和修正:编号只允许小写(F01、F16);批量开通整批校验(F01);停用或删除端时作废它发出的消息,删除后编号可复用(F01);登录锁定按编号加 IP,并区分服务器故障(F02);消息号按请求内容判冲突,防重标记与记录并存(F05、F18);请求频率上限写入需求(F05);接收上限按整条数据计算(F07);不保留消息的确认超时(F08、F09);服务器重启后的宽限和补发(F10、F11);撤回结果的判定和不发回执(F13、F14);解散群时作废定时消息(F16);后台批量停用、删除和注册设置(F17);首次启动先初始化(F22);单位统一为 KiB;重试先认防重再校验(F05);每个端未完成消息和排队投递的上限(F05);对话密码另按被猜的端限总数(F15);后台端列表显示在线状态(F17);注册安全码和明文传输的提醒(F23);手机 App 在后台收不到提醒的说明(5.2);新增默认 D14–D25 |
| 0.3 | 2026-09-30 | 负责人确认第 9 节 D1–D26(D27 待确认):开放注册后目录仍对所有端可见(D26),配额可设为 0 表示不设上限(D25)。新增管理 API 令牌和管理操作日志(F17)。F22 增加 Docker 镜像和 Prometheus 监控指标。F21 写明证书文件自动重载、生产环境用 1Panel 申请和续签。技术栈写入 DEVELOPMENT.md 第 2 节:Go + 标准库 net/http、SQLite + 手写 SQL、不用 Redis、Vue 3 + TypeScript + Naive UI 打包嵌入程序 | | 0.3 | 2026-09-30 | 负责人确认第 9 节 D1–D26(D27 待确认):开放注册后目录仍对所有端可见(D26),配额可设为 0 表示不设上限(D25)。新增管理 API 令牌和管理操作日志(F17)。F22 增加 Docker 镜像和 Prometheus 监控指标。F21 写明证书文件自动重载、生产环境用 1Panel 申请和续签。技术栈写入 DEVELOPMENT.md 第 2 节:Go + 标准库 net/http、SQLite + 手写 SQL、不用 Redis、Vue 3 + TypeScript + Naive UI 打包嵌入程序 |
| 0.4 | 2026-09-30 | 登录改为会话令牌(F02):首次用密码登录后发令牌,重连用令牌、和 IP 无关;每次用密码登录都换新令牌,旧设备自动退出(D28);令牌闲置 30 天失效,可以主动退出登录(D29)。密码锁定改为按编号加 IP、按编号总数两种,只拦密码登录,不拦令牌重连(D18);后台可以解除锁定(F01、F17);登录密码不能以 `nst_` 开头。新增 docs/TASKS.md 开发任务拆分 | | 0.4 | 2026-09-30 | 登录改为会话令牌(F02):首次用密码登录后发令牌,重连用令牌、和 IP 无关;每次用密码登录都换新令牌,旧设备自动退出(D28);令牌闲置 30 天失效,可以主动退出登录(D29)。密码锁定改为按编号加 IP、按编号总数两种,只拦密码登录,不拦令牌重连(D18);后台可以解除锁定(F01、F17);登录密码不能以 `nst_` 开头。新增 docs/TASKS.md 开发任务拆分 |
| 0.5 | 2026-09-30 | 负责人确认 D18、D27、D29,第 9 节全部确认,状态改为可交给开发。新增 D30–D33:SDK 最低支持版本、管理员密码至少 12 位和后台时间显示、定时备份方式、源码和发布物公开可读但许可证为专有。F19 写明 SDK 包名和发布到 Gitea 包仓库;F22 写明镜像地址、备份方式和许可证 |
+15 -11
View File
@@ -2,9 +2,9 @@
| 项 | 内容 | | 项 | 内容 |
|---|---| |---|---|
| 版本 | 0.1 | | 版本 | 0.2 |
| 日期 | 2026-09-30 | | 日期 | 2026-09-30 |
| 对应 | [PRD.md](./PRD.md) 0.4、[DEVELOPMENT.md](./DEVELOPMENT.md)(对应 PRD 0.4) | | 对应 | [PRD.md](./PRD.md) 0.5、[DEVELOPMENT.md](./DEVELOPMENT.md)(对应 PRD 0.5) |
| 仓库 | https://git.asio.asia/nixevol/NixMsg.git,主分支 `main` | | 仓库 | https://git.asio.asia/nixevol/NixMsg.git,主分支 `main` |
| 读者 | 总控 Agent、各开发线 Agent、负责人 | | 读者 | 总控 Agent、各开发线 Agent、负责人 |
@@ -18,9 +18,9 @@
2. PRD 第 10 节 F01–F23 每条都有验收结果:通过;或未测,写明原因并经负责人认可。 2. PRD 第 10 节 F01–F23 每条都有验收结果:通过;或未测,写明原因并经负责人认可。
3. 四种 SDK 都通过 DEVELOPMENT 第 9 节的接入清单。 3. 四种 SDK 都通过 DEVELOPMENT 第 9 节的接入清单。
4. DEVELOPMENT 第 13 节的弱网、崩溃、压测、端到端测试做完并有报告。 4. DEVELOPMENT 第 13 节的弱网、崩溃、压测、端到端测试做完并有报告。
5. 二进制(`linux/amd64`、`linux/arm64`、`windows/amd64`)和 Docker 镜像(amd64、arm64)能按文档启动。 5. 二进制(`linux/amd64`、`linux/arm64`、`windows/amd64`)和 Docker 镜像(amd64、arm64)能按文档启动;镜像已推到 `git.asio.asia/nixevol/nixmsg`。
6. 和文档不一致的实现都写进 `docs/DEVIATIONS.md`,并经负责人确认。 6. 和文档不一致的实现都写进 `docs/DEVIATIONS.md`,并经负责人确认。
7. 最终代码按第 7 节审核过,打上 `v0.1.0` 标签并推送。 7. 最终代码按第 7 节审核过,打上 `v0.1.0` 和 `sdk/go/v0.1.0` 标签并推送;npm、PyPI、Maven 三个 SDK 包已发布到 Gitea 包仓库。
## 2. 资料 ## 2. 资料
@@ -39,6 +39,7 @@
- Docker 容器、网络、卷的名字带上自己的线名前缀,用完删除。 - Docker 容器、网络、卷的名字带上自己的线名前缀,用完删除。
- 不改全局配置:全局 git 配置、系统环境变量、全局 npm 配置都不要动。 - 不改全局配置:全局 git 配置、系统环境变量、全局 npm 配置都不要动。
- 推送 git.asio.asia 用本机 Windows 凭据管理器里已存好的账号,不要把账号密码写进仓库、脚本或命令行。 - 推送 git.asio.asia 用本机 Windows 凭据管理器里已存好的账号,不要把账号密码写进仓库、脚本或命令行。
- 发布 SDK 包和推送镜像只在阶段 3 做,用 Gitea 个人访问令牌:总控用密码库条目 `git.asio.asia` 的账号在 Gitea 里创建一个只有 `package` 读写权限的令牌,立即存进 MemRelay 密码库,只写进本机用户级配置,不进仓库。
## 4. 协作规则 ## 4. 协作规则
@@ -77,6 +78,7 @@
3. 不能快进(main 已经前进)时打回给开发线重新 rebase。冲突由开发线理解双方改动后解决。 3. 不能快进(main 已经前进)时打回给开发线重新 rebase。冲突由开发线理解双方改动后解决。
4. 功能分支 rebase 后,用 `git push --force-with-lease` 更新自己的远端分支(负责人已同意,见第 9 节)。只能用在自己的 `feat/*`、`fix/*` 分支上,不许用于别人的分支;任何人都不许强推 `main`。 4. 功能分支 rebase 后,用 `git push --force-with-lease` 更新自己的远端分支(负责人已同意,见第 9 节)。只能用在自己的 `feat/*`、`fix/*` 分支上,不许用于别人的分支;任何人都不许强推 `main`。
5. 如果仓库开了分支保护或合并请求审核,改成推分支、建合并请求,由总控合并。 5. 如果仓库开了分支保护或合并请求审核,改成推分支、建合并请求,由总控合并。
6. 本期不做 CI(负责人决定)。合并前的全量验证由总控在本机执行,开发线的自测不能代替。
### 4.4 进度记录 ### 4.4 进度记录
@@ -148,8 +150,8 @@ flowchart LR
**T0.5 集成测试启动器 `test/harness`** · 依赖:T0.1 **T0.5 集成测试启动器 `test/harness`** · 依赖:T0.1
- 做:编译一次服务端;每个测试用随机端口、临时目录启动一个进程(配置里 `listen` 的端口写 0,服务端启动后把实际地址写进 `<data_dir>/listen.addr`,见 DEVELOPMENT 第 4.1 节,启动器读它),自动执行 `admin init` 拿到管理员密码;提供管理接口客户端和 MQTT 测试客户端(WebSocket 和 TCP 都支持,能收发第 6 节的帧);测试结束时清理进程和目录。 - 做:编译一次服务端;每个测试用随机端口、临时目录启动一个进程(配置里 `listen` 的端口写 0,服务端启动后把实际地址写进 `<data_dir>/listen.addr`,见 DEVELOPMENT 第 4.1 节,启动器读它),自动执行 `admin init` 拿到管理员密码;提供管理接口客户端和 MQTT 测试客户端(WebSocket 和 TCP 都支持,能收发第 6 节的帧);另外提供一个命令行启动器(例如 `go run ./test/harness/cmd/testserver`),在随机端口启动服务,把连接地址和管理员密码以 JSON 打到标准输出,收到 Ctrl+C 时退出并清理,给 JS、Python、Java 的集成测试用;测试结束时清理进程和目录。
- 验证:示例集成测试能启动服务、访问 `/healthz`,结束后进程和目录都清干净;两个测试并行跑互不干扰。 - 验证:示例集成测试能启动服务、访问 `/healthz`,结束后进程和目录都清干净;两个测试并行跑互不干扰;命令行启动器能打出连接信息,退出后清理干净。
### 6.2 平台 P ### 6.2 平台 P
@@ -287,8 +289,8 @@ S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语
| 1 连接和会话 | WebSocket(TCP 可选)、每次连接都带 Clean Start、握手、会话令牌(`onSession`、用令牌重连、`session_invalid`)、退避、停止重连的条件、连接超时 30 秒 | T0.2 | | 1 连接和会话 | WebSocket(TCP 可选)、每次连接都带 Clean Start、握手、会话令牌(`onSession`、用令牌重连、`session_invalid`)、退避、停止重连的条件、连接超时 30 秒 | T0.2 |
| 2 收发 | 发送队列(上限 1000、在途 100、`rate_limited` 自动重交、`send_at_ms` 不重算)、去重和再确认、串行回调、自动和手动确认、`revoked`、本地大小检查 | 任务 1 | | 2 收发 | 发送队列(上限 1000、在途 100、`rate_limited` 自动重交、`send_at_ms` 不重算)、去重和再确认、串行回调、自动和手动确认、`revoked`、本地大小检查 | 任务 1 |
| 3 其余接口 | 撤回、状态、回执、在线、目录、订阅、群、`self.*`、`logout`、注册 | 任务 2 | | 3 其余接口 | 撤回、状态、回执、在线、目录、订阅、群、`self.*`、`logout`、注册 | 任务 2 |
| 4 接入清单 | 第 9 节的 15 条集成测试,对真实服务端二进制运行 | 任务 3,以及 N3、M3、I2、I4 已合进 main | | 4 接入清单 | 第 9 节的 15 条集成测试,用 T0.5 的启动器起真实服务端 | 任务 3,以及 N3、M3、I2、I4 已合进 main |
| 5 文档和示例 | 这种语言的 README 和最小示例 | 任务 4 | | 5 打包和文档 | 按 DEVELOPMENT 第 9 节设置包名、许可证信息和发布配置,用各工具的试运行方式确认能打包(真正发布在 Z3);写这种语言的 README 和最小示例 | 任务 4 |
各语言的要点在 DEVELOPMENT 第 2.3 节和第 9 节:Go 用 `ConnectPacketBuilder` 每次设 Clean Start;JS 同时支持浏览器和 Node,发 ESM 和 CJS,要测跨域;Python 同步为主,另给 asyncio 包装;Java 编译成 Java 8 字节码,写清 Android API 24 的用法。 各语言的要点在 DEVELOPMENT 第 2.3 节和第 9 节:Go 用 `ConnectPacketBuilder` 每次设 Clean Start;JS 同时支持浏览器和 Node,发 ESM 和 CJS,要测跨域;Python 同步为主,另给 asyncio 包装;Java 编译成 Java 8 字节码,写清 Android API 24 的用法。
@@ -311,7 +313,7 @@ S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语
**Q4 Docker 与发布** · 依赖:T0.1,最终在阶段 2 完成 **Q4 Docker 与发布** · 依赖:T0.1,最终在阶段 2 完成
- 做:第 11.4 节的多阶段、多架构镜像;compose 示例;三个平台的二进制;镜像冒烟测试;第 11.3 节 1Panel 证书说明。 - 做:第 11.4 节的多阶段、多架构镜像;compose 示例;三个平台的二进制;镜像冒烟测试;推送镜像的 Taskfile 目标(推到 `git.asio.asia/nixevol/nixmsg`,真正推送在 Z3);第 11.3 节 1Panel 证书说明。
- 验证:两个架构的镜像都能初始化、启动、通过健康检查。 - 验证:两个架构的镜像都能初始化、启动、通过健康检查。
**Q5 文档** · 依赖:各线完成 **Q5 文档** · 依赖:各线完成
@@ -325,7 +327,7 @@ S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语
**Z2 审核**:按第 7 节清单逐项审核;做安全检查(日志和管理接口里没有正文、密码、令牌);检查依赖的许可证。 **Z2 审核**:按第 7 节清单逐项审核;做安全检查(日志和管理接口里没有正文、密码、令牌);检查依赖的许可证。
**Z3 交付**:汇总 `docs/DEVIATIONS.md` 并请负责人确认;打 `v0.1.0` 标签并推送;构建二进制和镜像;写交付说明(功能清单、验收结果、已知问题)。 **Z3 交付**:汇总 `docs/DEVIATIONS.md` 并请负责人确认;打 `v0.1.0` 和 `sdk/go/v0.1.0` 标签并推送;按第 3 节创建发布令牌,把 npm、PyPI、Maven 三个 SDK 包发布到 Gitea 包仓库,把两个架构的镜像推到 `git.asio.asia/nixevol/nixmsg`(版本号标签和 `latest`);构建三个平台的二进制;写交付说明(功能清单、验收结果、已知问题)。
## 7. 审核清单 ## 7. 审核清单
@@ -362,6 +364,8 @@ S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语
你是 NixMsg 的开发线 <线名> Agent。先按协作规则读 MemRelay 项目记忆,再阅读 docs/TASKS.md(重点第 3、4、5 节和第 6 节里 <线名> 的任务)以及 PRD、DEVELOPMENT 的相关小节。在你自己的工作树和 feat/<任务号>-<简述> 分支上工作,只改本线负责的目录,按依赖顺序完成本线任务:一功能一验证一提交,并推送自己的分支。每个任务完成后 rebase 到 origin/main、跑全部验证,通过后在 MemRelay 存标签为 ready-to-merge 的检查点,然后告诉我。缺工具用 scoop 安装;文档有疑问先问我,不要自己改产品行为。 你是 NixMsg 的开发线 <线名> Agent。先按协作规则读 MemRelay 项目记忆,再阅读 docs/TASKS.md(重点第 3、4、5 节和第 6 节里 <线名> 的任务)以及 PRD、DEVELOPMENT 的相关小节。在你自己的工作树和 feat/<任务号>-<简述> 分支上工作,只改本线负责的目录,按依赖顺序完成本线任务:一功能一验证一提交,并推送自己的分支。每个任务完成后 rebase 到 origin/main、跑全部验证,通过后在 MemRelay 存标签为 ready-to-merge 的检查点,然后告诉我。缺工具用 scoop 安装;文档有疑问先问我,不要自己改产品行为。
``` ```
## 9. 负责人已确认的协作授权 ## 9. 负责人已确认的协作事项
- 2026-09-30:允许各开发 Agent 在 rebase 后用 `git push --force-with-lease` 更新自己的 `feat/*`、`fix/*` 远端分支;`main` 任何时候都不许强推。 - 2026-09-30:允许各开发 Agent 在 rebase 后用 `git push --force-with-lease` 更新自己的 `feat/*`、`fix/*` 远端分支;`main` 任何时候都不许强推。
- 2026-09-30:SDK 发布到 Gitea 包仓库,镜像推到 `git.asio.asia/nixevol/nixmsg`;本期不做 CI;许可证为专有,源码仓库和发布物公开可读(DEVELOPMENT 第 2.1 节、第 9 节、第 11.4 节)。
- PRD 第 9 节的默认规则 D1–D33 已全部确认,开发中不再等待确认;和文档不一致的实现按第 4.2 节写进 `docs/DEVIATIONS.md`。