diff --git a/API.md b/API.md index b6e94fb..62829f2 100644 --- a/API.md +++ b/API.md @@ -379,6 +379,17 @@ QQBot 运行态包括 NapCat 容器登录、OneBot v11 反向 WebSocket、MQTT NapCat Chinese Desktop Runtime v8 使用 KT `NapCatQQ` fork 源码构建出的 `NapCat.Shell` artifact,并在 QQ `KickedOffLine` 后重置 native login service 再请求二维码;同一次踢下线事件只消费一次 reset,且只有明确二维码过期或扫码确认窗口失效的 QR session failure 才自动换码,避免扫码确认期间被 `ErrType=1/ErrCode=1` 抢刷新打断。构建前必须运行 `scripts/napcat-desktop-cn-stage-build.mjs` 生成 Docker build context;生产 `QQBOT_NAPCAT_IMAGE` 应指向验证过的 `kt-napcat-desktop-cn:desktop-cn-v8` digest。 +API 仓库不提交 `NapCat.Shell.zip`;生产镜像必须从 staged context 构建,且 `fork-artifact.json` 必须包含完整 marker metadata:upstream release tag/commit、fork commit、base image digest、Jenkins URL 和 artifact hashes。NapCat base image 在 release evidence 中必须 pin 到 digest。 + +```powershell +node scripts/napcat-desktop-cn-stage-build.mjs ` + --napcat-root D:\MyFiles\KT\GitHub\NapCatQQ ` + --upstream-release-tag v4.8.0 ` + --upstream-release-commit 0000000000000000000000000000000000000000 ` + --napcat-base-image-digest mlikiowa/napcat-docker@sha256:0000000000000000000000000000000000000000000000000000000000000000 ` + --jenkins-build-url https://jenkins.kwitsukasa.top/job/KT-NapCatQQ-Runtime-Release/1/ +``` + ### NapCat WebUI Gateway NapCat WebUI Gateway 是独立部署的内部代理服务,生产镜像由 `dockerfile.gateway` 打包 `dist/apps/napcat-webui-gateway/main.js`,K8s 服务名为 `kt-napcat-webui-gateway`,端口 `48086`。API 侧只通过内部路由 `NAPCAT_WEBUI_GATEWAY_INTERNAL_BASE_URL` 创建、续期、撤销会话和交换一次性 ticket;浏览器只访问公开前缀 `NAPCAT_WEBUI_GATEWAY_PUBLIC_BASE_URL` 下的代理页面、静态资源和 WebSocket 转发,不能直连 NapCat 容器 WebUI。 diff --git a/README.md b/README.md index 0621a2b..088e53a 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,17 @@ Admin 环境总览面板使用 `ENV_DASHBOARD_*` 只读配置聚合 local-dev、 NapCat Runtime/Protocol Profile 已完成本地 API/Admin 实施,线上发布和账号闭环按 `docs/superpowers/plans/2026-06-18-qqbot-napcat-runtime-protocol-profile-implementation-plan.md` 的 Task 10 执行。当前实现覆盖运行态/协议/会话行为/历史登录事件兼容表/风险模式表,真实物理设备风格 hostname/MAC,NapCat/OneBot 配置 hash,KT `zh_CN.UTF-8` 中国桌面派生镜像资产,只读 `/qqbot/napcat/runtime/detail` 证据接口,watchdog 离线巡检告警,以及 Admin 账号页“运行态”抽屉;不绕过 QQ/Tencent 验证码、不修改 QQ/NTQQ 签名协议、不启用 privileged/host network,也不做账号级每小时/每日累计发送预算。NapCat Chinese Desktop Runtime v8 使用 KT `NapCatQQ` fork 源码构建出的 `NapCat.Shell` artifact,并在 QQ `KickedOffLine` 后重置 native login service 再请求二维码;同一次踢下线事件只消费一次 reset,且只有明确二维码过期或扫码确认窗口失效的 QR session failure 才自动换码,避免扫码确认期间被 `ErrType=1/ErrCode=1` 抢刷新打断。镜像必须先用 `scripts/napcat-desktop-cn-stage-build.mjs` staged build context,生产 `QQBOT_NAPCAT_IMAGE` 应指向验证过的 `kt-napcat-desktop-cn:desktop-cn-v8` digest。 +运行时发布时,API 仓库不提交 `NapCat.Shell.zip`;生产镜像必须从 staged context 构建,`fork-artifact.json` 必须带完整 marker metadata,包括 upstream release tag/commit、fork commit、base image digest、Jenkins URL 和 artifact hashes。release evidence 里的 NapCat base image 必须用 digest pin。 + +```powershell +node scripts/napcat-desktop-cn-stage-build.mjs ` + --napcat-root D:\MyFiles\KT\GitHub\NapCatQQ ` + --upstream-release-tag v4.8.0 ` + --upstream-release-commit 0000000000000000000000000000000000000000 ` + --napcat-base-image-digest mlikiowa/napcat-docker@sha256:0000000000000000000000000000000000000000000000000000000000000000 ` + --jenkins-build-url https://jenkins.kwitsukasa.top/job/KT-NapCatQQ-Runtime-Release/1/ +``` + NapCat WebUI Gateway 是独立运行的 NestJS 入口,生产镜像使用 `dockerfile.gateway` 打包 `dist/apps/napcat-webui-gateway/main.js` 并监听 `48086`。API 通过内部地址 `NAPCAT_WEBUI_GATEWAY_INTERNAL_BASE_URL=http://kt-napcat-webui-gateway:48086` 创建/续期/撤销 WebUI 会话,Admin 浏览器只访问公开前缀 `NAPCAT_WEBUI_GATEWAY_PUBLIC_BASE_URL=/napcat-webui`。Gateway 运行时需要 `NAPCAT_WEBUI_GATEWAY_INTERNAL_SECRET`、`NAPCAT_WEBUI_GATEWAY_REDIS_HOST`、`NAPCAT_WEBUI_GATEWAY_REDIS_PORT`、`NAPCAT_WEBUI_GATEWAY_SESSION_TTL_MS`、`NAPCAT_WEBUI_GATEWAY_TICKET_TTL_MS`、`NAPCAT_WEBUI_GATEWAY_UPSTREAM_TIMEOUT_MS`;生产 secret 由 Jenkins 从私有 `.env.production` 重建到 `kt-template-online-api-env`,不得写入 Git。验收命令:`pnpm exec jest --runTestsByPath test/modules/qqbot/napcat-webui-gateway/gateway-deployment.spec.ts --runInBand`、`pnpm run typecheck`、`pnpm run build`、`Test-Path .\dist\apps\napcat-webui-gateway\main.js`、`git diff --check`。安全边界:浏览器不得收到 WebUI token、Credential、上游 URL/端口、Docker 拓扑、Redis 地址或内部 secret。 ## 启动 diff --git a/scripts/napcat-desktop-cn-stage-build.mjs b/scripts/napcat-desktop-cn-stage-build.mjs index ed85618..13d150e 100644 --- a/scripts/napcat-desktop-cn-stage-build.mjs +++ b/scripts/napcat-desktop-cn-stage-build.mjs @@ -136,6 +136,10 @@ const napcatRootArg = readArg('napcat-root'); const napcatRoot = resolve(napcatRootArg); const outputRoot = resolve(apiRoot, readArg('out', DEFAULT_OUTPUT)); const upstreamBaseCommit = readArg('upstream-base-commit', DEFAULT_UPSTREAM_BASE); +const upstreamReleaseTag = readArg('upstream-release-tag', 'unknown'); +const upstreamReleaseCommit = readArg('upstream-release-commit', upstreamBaseCommit); +const napcatBaseImageDigest = readArg('napcat-base-image-digest', ''); +const jenkinsBuildUrl = readArg('jenkins-build-url', ''); const shellDist = resolve(napcatRoot, 'packages/napcat-shell/dist'); const napcatMjs = resolve(shellDist, 'napcat.mjs'); @@ -163,8 +167,12 @@ const marker = { builtAt: new Date().toISOString(), distSha256: sha256Directory(shellDist), forkCommit: gitCommit(napcatRoot), + jenkinsBuildUrl, + napcatBaseImageDigest, napcatMjsSha256: sha256File(napcatMjs), upstreamBaseCommit, + upstreamReleaseCommit, + upstreamReleaseTag, }; writeFileSync( diff --git a/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts b/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts index 647d483..943ac01 100644 --- a/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts +++ b/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts @@ -50,6 +50,10 @@ describe('NapCat Chinese Desktop Runtime image assets', () => { expect(script).toContain('napcatMjsSha256'); expect(script).toContain('forkCommit'); expect(script).toContain('upstreamBaseCommit'); + expect(script).toContain('upstreamReleaseTag'); + expect(script).toContain('upstreamReleaseCommit'); + expect(script).toContain('napcatBaseImageDigest'); + expect(script).toContain('jenkinsBuildUrl'); expect(script).toContain('packages/napcat-shell/dist'); expect(script).toContain('fork-artifact.json'); expect(script).toContain('.kt-workspace/napcat-desktop-cn-build');