diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e1c9937 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md index 5e02805..722fdbb 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,7 @@ ## 状态 需求和设计已完成,正在开发。构建、运行和部署说明在开发完成后补充。 + +## 许可证 + +专有软件,见 [LICENSE](LICENSE)。源代码和发布物公开可读,不代表授予使用许可。 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index a39d094..3aba44c 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,6 +1,6 @@ # 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 对照它们主分支的源码核对过;升级这些依赖的大版本时要重新核对。 @@ -56,6 +56,10 @@ flowchart LR | 部署 | 单文件二进制为主,同时提供 Docker 镜像(`linux/amd64`、`linux/arm64`)和 docker-compose 示例 | 第 11 节 | | 监控 | Prometheus 格式的 `/metrics` | 访问限制见第 4.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 按推荐定下的其余部分 @@ -82,12 +86,12 @@ flowchart LR 这里只列各语言 SDK 依赖的 MQTT 客户端库,SDK 的行为见第 9 节。 -| SDK | 依赖 | 说明 | -|---|---|---| -| Go | `github.com/eclipse/paho.golang/autopaho` | MQTT 5、自动重连、支持 WebSocket | -| JS/TS | MQTT.js 5.x | 浏览器和 Node 都能用 | -| Python | paho-mqtt 2.x,`CallbackAPIVersion.VERSION2` | 同步接口为主,另给 asyncio 包装 | -| Java/Android | HiveMQ MQTT Client,加上 websocket 模块 | Java 8+,Android API 24+ | +| SDK | 依赖 | 说明 | 最低支持 | +|---|---|---|---| +| Go | `github.com/eclipse/paho.golang/autopaho` | MQTT 5、自动重连、支持 WebSocket | 和服务端相同的 Go 版本 | +| JS/TS | MQTT.js 5.x | 浏览器和 Node 都能用 | Node.js 20;近两年发布的 Chrome、Edge、Firefox、Safari | +| Python | paho-mqtt 2.x,`CallbackAPIVersion.VERSION2` | 同步接口为主,另给 asyncio 包装 | Python 3.10 | +| Java/Android | HiveMQ MQTT Client,加上 websocket 模块 | 同一套 jar 给 Java 和 Android 用 | Java 8;Android API 24 | ### 2.4 后台界面 @@ -108,6 +112,7 @@ flowchart LR - 帮助图标用 `n-tooltip`;错误和关键状态用 `n-alert` 或表单校验信息直接显示。 - 弹窗用 `n-modal`(`preset="card"`),按钮放在 `footer` 插槽,正文放进 `n-scrollbar` 单独滚动。 - 表格用 `n-data-table`:`remote` 做服务端分页,设 `max-height` 让表格内部滚动,长列表开 `virtual-scroll`。 +- 所有时间按浏览器本地时区显示,格式 `YYYY-MM-DD HH:mm:ss`;接口里一律用 Unix 毫秒。 - 只用 Naive UI 一套组件库,不要混用 Element Plus 等其他库。 ## 3. 仓库 @@ -248,7 +253,7 @@ Capabilities: | 钩子 | 行为 | |---|---| | `OnConnect` | 分配连接代号,校正心跳,然后查编号、停用,按下文「登录与会话令牌」校验会话令牌或登录密码(含锁定),把结论记在这个连接上。数据库出错等内部故障时返回 error:mochi 不回 CONNACK 直接断开,客户端按网络故障重连 | -| `OnConnectAuthenticate` | 只返回 `OnConnect` 记下的结论。返回 false 时 mochi 回「用户名或密码错误」,SDK 会停止重连,所以只有编号不存在、已停用、密码错误、已锁定这几种情况能返回 false | +| `OnConnectAuthenticate` | 只返回 `OnConnect` 记下的结论。返回 false 时 mochi 回「用户名或密码错误」,SDK 会停止重连,所以只有编号不存在、已停用、密码错误、会话令牌无效或过期、已锁定这几种情况能返回 false | | `OnACLCheck` | 只允许上面这一对主题。发布检查 `write=true`;订阅和服务器下发检查 `write=false` | | `OnPublish` | 拷贝 topic 和 payload 后交给该端的串行队列。返回 `packets.CodeSuccessIgnore`,让客户端拿到 PUBACK,同时不把这条转发给任何订阅者 | | `OnPublishDropped` | 下行没写进连接的发送队列。把对应投递或回执的「已推送」标记清掉,1 秒后重推,别对慢客户端空转 | @@ -919,7 +924,7 @@ API 令牌,给接入方后台用程序调用管理接口: 所有 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 @@ -962,7 +967,7 @@ close() - 发送队列在内存,默认最多 1000 条,包括已发出但没收到 `resp` 的。连不上时 `send` 入队;重连后按原消息号、原请求内容再交。 - `sendAt` 在调用 `send` 时就换算成 `send_at_ms`,重交时不重算,否则请求指纹变了会被当成冲突。 - 同时在途(已发出、没收到 `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 | -| JS/TS | `@nixmsg/sdk` | Promise,ESM 和 CJS 都发 | -| Python | `nixmsg` | 同步为主;`asyncio` 包装放在同一包 | -| Java | `com.nixmsg:nixmsg-sdk` | `CompletableFuture`。Android 最低 API 24,长连接由应用自己放到前台服务 | +| 语言 | 包名 | 获取方式 | 接口形态 | +|---|---|---|---| +| 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 | `@nixevol/nixmsg` | Gitea npm 仓库 `https://git.asio.asia/api/packages/nixevol/npm/` | Promise,ESM 和 CJS 都发 | +| Python | `nixmsg`(导入名也是 `nixmsg`) | Gitea PyPI 仓库 `https://git.asio.asia/api/packages/nixevol/pypi/simple/` | 同步为主;`asyncio` 包装放在同一包 | +| 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 的 `` 写 `Proprietary`。每个包都带上仓库根目录的 `LICENSE`。 +- 发布只在阶段 3 由总控执行(TASKS.md Z3)。用 Gitea 个人访问令牌,只给 `package` 读写权限;令牌存进 MemRelay 密码库,只写在本机用户级配置里(用户目录下的 `.npmrc`、`.pypirc`、`.gradle/gradle.properties`),不进仓库。 接入清单(每种语言一份集成测试,对真实服务器二进制): @@ -1082,6 +1090,7 @@ data/nixmsg.db 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 之类的工具托管成服务,本期不在程序里内置服务安装。 - 服务器开启 NTP 对时。 @@ -1104,6 +1113,7 @@ data/backup/ ### 11.4 Docker - 镜像多阶段构建: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` 只读挂载。 - 首次使用先执行 `docker compose run --rm nixmsg admin init`,记下只打印一次的管理员密码,再 `docker compose up -d`。 - 容器以 uid 65532 运行:挂载的数据目录要可写,证书私钥要可读。 @@ -1112,7 +1122,7 @@ data/backup/ ```yaml services: nixmsg: - image: nixmsg:0.1.0 + image: git.asio.asia/nixevol/nixmsg:0.1.0 restart: unless-stopped command: ["serve"] environment: diff --git a/docs/PRD.md b/docs/PRD.md index c82371e..dc1e449 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -2,9 +2,9 @@ | 项 | 内容 | |---|---| -| 版本 | 0.4 | +| 版本 | 0.5 | | 日期 | 2026-09-30 | -| 状态 | 待复核后交给开发 | +| 状态 | 已确认,可交给开发 | | 读者 | 产品负责人、开发组、后续审核 | | 配套 | [DEVELOPMENT.md](./DEVELOPMENT.md) 是实现规范。两者冲突时,以本文已确认的产品行为为准,并在 `docs/DEVIATIONS.md` 记录 | | 修订 | 见第 11 节 | @@ -358,7 +358,7 @@ NixMsg 是一套自建的消息中转服务。设备、程序、App 都作为「 网页后台,界面中文。功能: -- 登录、修改管理员自己的密码、退出。 +- 登录、修改管理员自己的密码(至少 12 位)、退出。页面上的时间都按浏览器本地时区显示。 - 概览:端数量(其中自助注册的数量)、在线数、群数量、待投递数、版本。 - 端:查询(可按来源筛选:后台开通、自助注册)、开通、批量开通、编辑、启停、删除、重置登录密码、设置或清除对话密码、踢下线、解除登录锁定。列表显示是否在线、最近上下线时间、来源;支持多选后批量停用、删除,方便清理异常注册。 - 注册:开启或关闭自助注册;查看、手填或生成注册安全码。 @@ -400,6 +400,8 @@ NixMsg 是一套自建的消息中转服务。设备、程序、App 都作为「 - 修改自己的名称、默认延迟、登录密码(需要旧密码)、对话密码。 - 发送方暂时连不上服务器时,发送进入内存队列,重连后按原消息号再交;已经发出但没等到结果的也一样。进程退出则队列丢失。除发送以外的请求在离线时直接失败。 - 本机时间与服务器偏差由 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 里的同一份接入清单。清单覆盖注册、登录、收发、去重、重连、离线队列、撤回、定时、群、对话密码、改密、被踢、超限。 @@ -425,10 +427,11 @@ NixMsg 是一套自建的消息中转服务。设备、程序、App 都作为「 ### F22 部署与运维 - 一个 Go 程序,一个可执行文件,内置 MQTT 和网页。不另外部署数据库、消息队列或缓存。 -- 同时提供 Docker 镜像(amd64、arm64)和 docker-compose 示例,装有 1Panel 的服务器可以直接用它的容器编排部署。 +- 同时提供 Docker 镜像(amd64、arm64,发布在 `git.asio.asia/nixevol/nixmsg`)和 docker-compose 示例,装有 1Panel 的服务器可以直接用它的容器编排部署。 - 数据在一个目录里的 SQLite 文件。 - 首次使用先运行初始化命令生成管理员密码(只在终端显示一次,不写日志),再启动服务。 -- 提供备份命令。升级时自动迁移数据库;迁移前自动把库复制一份。 +- 提供备份命令。程序本身不做定时备份,用 1Panel 计划任务或 cron 定时调用(D32)。升级时自动迁移数据库;迁移前自动把库复制一份。 +- 源码、SDK 包和镜像都公开可读;许可证为专有,见仓库根目录的 LICENSE(D33)。 - 提供健康检查接口,以及 Prometheus 格式的监控指标(在线数、待投递数、投递耗时等,不含正文和编号明细)。指标只在后台端口上开放;后台和端共用端口时,要带配置的令牌才能访问。 验收: @@ -507,7 +510,7 @@ stateDiagram-v2 ## 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 | | D16 | 不做忘记密码自助找回和端自己注销,都由管理员处理 | 已确认 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 | | D20 | 撤回不单独发回执,结果看撤回请求的返回 | 已确认 2026-09-30 | | D21 | 停用或删除端时,它发出、还没推送的消息一并作废 | 已确认 2026-09-30 | @@ -537,9 +540,13 @@ stateDiagram-v2 | D24 | 对话密码另按被猜的端限总数:1 小时错 50 次后暂停新的验证 1 小时,已有授权不受影响 | 已确认 2026-09-30 | | D25 | 每个端未完成的发出消息最多 10000 条,排队待收的投递最多 10000 条;都可配置,设为 0 表示不设上限 | 已确认 2026-09-30 | | D26 | 开放自助注册后,目录仍对所有端可见,谁都能列出全部端 | 已确认 2026-09-30 | -| D27 | 管理 API 令牌不过期,停用或删除后立即失效;权限等同管理员,但不能改管理员密码、不能管理令牌;令牌只在创建时显示一次 | 待确认 | +| D27 | 管理 API 令牌不过期,停用或删除后立即失效;权限等同管理员,但不能改管理员密码、不能管理令牌;令牌只在创建时显示一次 | 已确认 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. 验收总表 @@ -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.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.5 | 2026-09-30 | 负责人确认 D18、D27、D29,第 9 节全部确认,状态改为可交给开发。新增 D30–D33:SDK 最低支持版本、管理员密码至少 12 位和后台时间显示、定时备份方式、源码和发布物公开可读但许可证为专有。F19 写明 SDK 包名和发布到 Gitea 包仓库;F22 写明镜像地址、备份方式和许可证 | diff --git a/docs/TASKS.md b/docs/TASKS.md index 8767961..d4e8559 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -2,9 +2,9 @@ | 项 | 内容 | |---|---| -| 版本 | 0.1 | +| 版本 | 0.2 | | 日期 | 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` | | 读者 | 总控 Agent、各开发线 Agent、负责人 | @@ -18,9 +18,9 @@ 2. PRD 第 10 节 F01–F23 每条都有验收结果:通过;或未测,写明原因并经负责人认可。 3. 四种 SDK 都通过 DEVELOPMENT 第 9 节的接入清单。 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`,并经负责人确认。 -7. 最终代码按第 7 节审核过,打上 `v0.1.0` 标签并推送。 +7. 最终代码按第 7 节审核过,打上 `v0.1.0` 和 `sdk/go/v0.1.0` 标签并推送;npm、PyPI、Maven 三个 SDK 包已发布到 Gitea 包仓库。 ## 2. 资料 @@ -39,6 +39,7 @@ - Docker 容器、网络、卷的名字带上自己的线名前缀,用完删除。 - 不改全局配置:全局 git 配置、系统环境变量、全局 npm 配置都不要动。 - 推送 git.asio.asia 用本机 Windows 凭据管理器里已存好的账号,不要把账号密码写进仓库、脚本或命令行。 +- 发布 SDK 包和推送镜像只在阶段 3 做,用 Gitea 个人访问令牌:总控用密码库条目 `git.asio.asia` 的账号在 Gitea 里创建一个只有 `package` 读写权限的令牌,立即存进 MemRelay 密码库,只写进本机用户级配置,不进仓库。 ## 4. 协作规则 @@ -77,6 +78,7 @@ 3. 不能快进(main 已经前进)时打回给开发线重新 rebase。冲突由开发线理解双方改动后解决。 4. 功能分支 rebase 后,用 `git push --force-with-lease` 更新自己的远端分支(负责人已同意,见第 9 节)。只能用在自己的 `feat/*`、`fix/*` 分支上,不许用于别人的分支;任何人都不许强推 `main`。 5. 如果仓库开了分支保护或合并请求审核,改成推分支、建合并请求,由总控合并。 +6. 本期不做 CI(负责人决定)。合并前的全量验证由总控在本机执行,开发线的自测不能代替。 ### 4.4 进度记录 @@ -148,8 +150,8 @@ flowchart LR **T0.5 集成测试启动器 `test/harness`** · 依赖:T0.1 -- 做:编译一次服务端;每个测试用随机端口、临时目录启动一个进程(配置里 `listen` 的端口写 0,服务端启动后把实际地址写进 `/listen.addr`,见 DEVELOPMENT 第 4.1 节,启动器读它),自动执行 `admin init` 拿到管理员密码;提供管理接口客户端和 MQTT 测试客户端(WebSocket 和 TCP 都支持,能收发第 6 节的帧);测试结束时清理进程和目录。 -- 验证:示例集成测试能启动服务、访问 `/healthz`,结束后进程和目录都清干净;两个测试并行跑互不干扰。 +- 做:编译一次服务端;每个测试用随机端口、临时目录启动一个进程(配置里 `listen` 的端口写 0,服务端启动后把实际地址写进 `/listen.addr`,见 DEVELOPMENT 第 4.1 节,启动器读它),自动执行 `admin init` 拿到管理员密码;提供管理接口客户端和 MQTT 测试客户端(WebSocket 和 TCP 都支持,能收发第 6 节的帧);另外提供一个命令行启动器(例如 `go run ./test/harness/cmd/testserver`),在随机端口启动服务,把连接地址和管理员密码以 JSON 打到标准输出,收到 Ctrl+C 时退出并清理,给 JS、Python、Java 的集成测试用;测试结束时清理进程和目录。 +- 验证:示例集成测试能启动服务、访问 `/healthz`,结束后进程和目录都清干净;两个测试并行跑互不干扰;命令行启动器能打出连接信息,退出后清理干净。 ### 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 | | 2 收发 | 发送队列(上限 1000、在途 100、`rate_limited` 自动重交、`send_at_ms` 不重算)、去重和再确认、串行回调、自动和手动确认、`revoked`、本地大小检查 | 任务 1 | | 3 其余接口 | 撤回、状态、回执、在线、目录、订阅、群、`self.*`、`logout`、注册 | 任务 2 | -| 4 接入清单 | 第 9 节的 15 条集成测试,对真实服务端二进制运行 | 任务 3,以及 N3、M3、I2、I4 已合进 main | -| 5 文档和示例 | 这种语言的 README 和最小示例 | 任务 4 | +| 4 接入清单 | 第 9 节的 15 条集成测试,用 T0.5 的启动器起真实服务端 | 任务 3,以及 N3、M3、I2、I4 已合进 main | +| 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 的用法。 @@ -311,7 +313,7 @@ S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语 **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 文档** · 依赖:各线完成 @@ -325,7 +327,7 @@ S1 先做 Go,再做 JS/TS;S2 先做 Python,再做 Java/Android。每种语 **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. 审核清单 @@ -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 安装;文档有疑问先问我,不要自己改产品行为。 ``` -## 9. 负责人已确认的协作授权 +## 9. 负责人已确认的协作事项 - 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`。