6.6 KiB
SDK 平台 V2 实施与接手说明
更新时间:2026-07-26。本文记录当前源码事实与尚未执行的部署动作;不得把本文当作生产环境已发布证明。
当前边界
- Config 文件唯一格式为
XUQM-CONFIG-V2,V1 不再接受。 - Config 文件由租户服务生成;客户端只验证签名、有效期和包名,不在线检查吊销状态。
- BugCollect 运行时上报失败不得影响宿主业务;服务关闭时固定返回 HTTP 403,消息码为
BUGCOLLECT_DISABLED。 - 构建产物上传唯一入口为
POST /bugcollect/v1/artifacts/upload。 - 已废弃的 App 离线激活 license 服务已从聚合构建、租户服务、网关和 Web 入口删除;它与签名 SDK 无关。
Config 文件契约
格式:
XUQM-CONFIG-V2.<keyId>.<salt>.<iv>.<ciphertext>.<signature>
- 内容加密:AES-256-GCM。
- 密钥派生:PBKDF2-HMAC-SHA256,120000 次。
- 完整性与发布方身份:Ed25519 对前五段的 ASCII 原文签名。
- 时间统一使用 UTC
Instant。 - 重新生成会产生新的
configId和递增revision;旧文件只在后续构建时被拦截,不影响已安装客户端运行。 - 构建校验接口:
POST /api/sdk/build/config/validate
Content-Type: application/json
{"content":"...","packageName":"com.example.app"}
签名密钥只能由运行环境注入:
SDK_CONFIG_SIGNING_KEY_IDSDK_CONFIG_SIGNING_PRIVATE_KEY_BASE64(PKCS#8 DER Base64)SDK_CONFIG_SIGNING_PUBLIC_KEY_BASE64(X.509 DER Base64)
公共互操作向量位于 common/src/test/resources/xuqm-config-v2-vector.json。私钥不得进入仓库、日志或普通文档。
SDK 动态配置
GET /api/sdk/config 的功能开关按 appKey + platform + serviceType 精确读取。版本更新登录要求来自 update-service 的权威字段 allowAnonymousUpdateCheck,对外返回 updateRequiresLogin。
租户服务访问 update-service 使用 500ms 连接超时、800ms 读取超时和 15s 小 TTL 缓存。依赖不可用时安全返回 updateRequiresLogin=true。
BugCollect 产物契约
构建工具必须携带:
Authorization: Bearer <XUQM_API_TOKEN>
Token 复用租户平台 API Key 权威校验,不存在 BugCollect 私有密钥。认证得到的 appKey 必须和上传表单中的 appKey 相同。
该产物端点只接受 Bearer 形式,单独传 X-API-Key 必须返回 401;通用业务接口原有的
X-API-Key 过滤行为不变。微服务向租户服务校验 Token 时使用受内部令牌保护的
POST /api/internal/sdk/validate-api-key JSON 请求体,严禁把 Token 放入 URL、查询参数或日志。
共同字段:
artifactTypeappKeyplatformappVersionbuildIdfile
RN_SOURCEMAP 额外要求 moduleId、moduleVersion、bundleHash,以完整七元组精确匹配,不允许“取最新”回退。source map 不允许内嵌 sourcesContent,sources 不允许绝对路径、Windows 盘符或 .. 穿越。
R8_MAPPING 仅支持 Android,文件名必须为 mapping.txt,并要求 artifactHash 与文件 SHA-256 一致。R8 与 RN 产物独立保存和查询。
运行时 /issues/batch、/events/batch 不使用 CI API Token;它们继续遵循客户端签名与服务开关策略。
数据库迁移
- tenant-service:V3 Config V2 元数据、V4 平台专属 App 包名、V5 移除离线 license 服务数据和枚举值。
- xuqm-bugcollect-service:V9 引入精确 bundle 身份和独立产物字段。
执行迁移前必须备份对应数据库。不得修改已在目标环境执行过的历史迁移文件。
Web 与 Jenkins
- 应用详情页展示 Config 签发元数据,并支持“长期有效”或选择 UTC 到期时间后重新生成。
- 符号化产物页同时展示 RN sourcemap 和 R8 mapping。
- Web 依赖管理统一使用仓库声明的 Yarn 1;不再保留不同步的
package-lock.json。 - Server 与 tenant-web Jenkins 默认
DEPLOY_ENV=development,development 只验证,不推送、不部署、不提交版本号。 - production 必须经过人工确认,并从 Jenkins Credentials 读取 Git 与 Config 签名凭据。
已执行验证
mvn -Dmaven.repo.local=/private/tmp/xuqm-m2 \
-pl tenant-service,xuqm-bugcollect-service -am test
2026-07-26 结果:BUILD SUCCESS。common 共 3 项测试通过,tenant-service 共 3 项测试通过, xuqm-bugcollect-service 共 7 项测试通过;覆盖 Config 向量、通用 X-API-Key 行为、 受保护的内部 POST 请求体、更新配置失败安全缓存、BugCollect 固定错误、路径校验、 R8 校验,以及产物 API Token 的无 Bearer、仅 X-API-Key、无效 Bearer、有效归属场景。
Server 全聚合 mvn -DskipTests compile 结果:BUILD SUCCESS,聚合构建中已不包含 license-service。
Web 验证命令:
yarn install --frozen-lockfile
yarn build:tenant
yarn build:ops
yarn workspace @xuqm/docs-site build
2026-07-26 三项 Web 构建均通过。最终结果以当前任务交接记录为准。
尚未执行
- 未提交、未推送。
- 未触发 Jenkins,未部署任何环境。
- 未运行真实 MySQL 迁移。
- Jenkins 中的 Git、Config 签名凭据以及生产主机运行环境变量必须由有权限的维护者配置后,才能进行生产发布。
2026-07-27 Jenkins SCM 凭据收口
- Server 流水线的显式 checkout 已改用 Gitea SSH URL 和 Jenkins
jenkins-ssh-key,不再引用未配置的XUQM_GIT_CREDENTIALS,也不允许在 URL 中嵌入用户名、密码或访问令牌。生产版本回写的 pull/push 同样放入sshagent(jenkins-ssh-key),不依赖 checkout 步骤的临时认证环境。 - 该修改尚未通过下一次 Server Jenkins 构建验证;触发部署前应先执行一次只构建不 部署的流水线或确认 checkout 阶段成功。
- 首次仓库流水线验证
xuqmgroup-tenant-service #95已证明 SSH checkout 成功, 但 Windows 节点没有全局mvn。仓库已引入 Apache Maven Wrapper 3.3.4only-script,固定 Maven 3.9.16 及官方发行包 SHA-256;Jenkins 统一调用mvnw.cmd -B test,不再依赖节点手工安装 Maven。 - 本地已使用 Wrapper 完成全部 10 个 Maven 模块的
./mvnw -B test,构建成功。 同时修正UpdatePublishConfigClientContextTest:测试上下文显式使用 Spring Boot 转换服务和RestTemplateBuilder的正式构造参数,避免把测试容器缺失的默认 Bean/类型转换能力误判为生产构造器故障。该提交推送后需再次运行xuqmgroup-tenant-service的非生产流水线,确认 Windows Wrapper 路径。