认证中心
← 全部文档与搜索
独立页面 ↗下载 Markdown
本文目录 · 7 节

AI 工具应用制品接口

实现基于现有 Gin、PostgreSQL、Redis、S3 分片上传和 software_releases 状态机。上传不会隐式发布,机器凭据也不是网页登录凭据。OpenAPI 与 Python CLI(仓库文件:../scripts/release-artifact.py) 可直接使用。

管理与身份

软件版本页的「AI 工具凭据」支持选择应用、授予操作范围、设置有效期、创建、吊销、轮换。需 release-tokens:write;迁移默认只授予 admin。该权限是全局管理权限,与现有 releases:write 的平台管理员模型一致,本仓库没有应用所有者/租户模型,不假定普通用户拥有某个应用。若后续引入租户,需要同时收紧两个管理权限。

凭据使用256位随机值 acr_…,数据库只存 SHA-256,创建/轮换仅返回一次原文;不存浏览器 localStorage,不写日志。轮换创建新记录并在同一事务吊销旧记录,保留范围和到期时间,最长90天。每次请求检查吊销/过期、应用启用、签发者账号有效且仍有 Token 管理权限。吊销不终止已进入执行的请求;已签发 S3 分片 URL 最长15分钟仍可使用,但不能绕过完成校验或发布授权。

机器请求使用 Authorization: Bearer $AC_RELEASE_TOKEN,仅 /api/v1/automation/applications/… 免 Cookie/CSRF,管理端仍需原 Cookie + Origin + CSRF。应用参数使用 UUID,不是公开 client_id。

Scope能力
releases:read查询该应用的机器版本、构建和上传状态
releases:create创建该应用的草稿版本
uploads:write创建/恢复上传、签发分片、上传小文件、校验完成、取消上传
publish:developmentalpha 通道发布/撤销
publish:stagingbeta 通道发布/撤销

稳定通道 stable 映射生产环境,不提供生产机器发布 scope。管理员在已有软件版本页查看 Git commit、构建元数据、安装包及摘要后,使用既有发布/定时发布确认流程完成生产发布。机器不可定时发布、删除版本或撤销生产发布。环境是现有分发通道映射,不代表私有测试环境;alpha/beta 发布后同样可通过公开更新接口下载。

契约与流程

返回沿用 {code:0,message:"success",data:…};错误为 {code:HTTP状态×100,message:…}。400 输入/文件/校验失败,401 凭据无效,403 应用或 scope/生产保护拒绝,404 记录不存在,409 幂等冲突/版本 revision 冲突,429 频率或配额超限,503 存储、数据库、Redis或并发容量不可用。不回传内部异常或凭据。

前缀 P=/api/v1/automation/applications/{application}/releases:

请求内容 / 返回
POST P必须携带 Idempotency-Key;version、version_code、platform、arch、channel、git_commit、metadata(字符串字典)、notes;返回草稿 Release
GET P/{id}release、assets、build、production_approval_required
POST P/{id}/uploadsfilename、size、sha256(小写 hex)、revision;返回 asset、part_size、uploaded_parts
POST P/{id}/uploads/{asset}/filemultipart/form-data 唯一 file 字段,≤32MiB;只上传一个分片,仍须 complete
POST P/{id}/uploads/{asset}/partpart_number、sha256(32字节 Base64);返回预签名 url、必须发送的 headers
POST P/{id}/uploads/{asset}/complete无正文;合并及同步校验,成功才将 asset 标记 ready,并递增 release.revision
DELETE P/{id}/uploads/{asset}取消未完成上传,后台重试清理
POST P/{id}/stateaction=publish/cancel、revision;受环境 scope 限制

管理员 API:GET/POST /api/v1/admin/release-tokens;DELETE /:token;POST /:token/rotate;GET /audit?application_id=…&page=1。列表也必须传 application_id。管理页面仍通过 /admin/releases/:id/state 发布/撤销,保留现有 revision 并发控制。Token 审计 API 只返回记录,不返回任何凭据。

创建幂等键为1–128位字母、数字、.、_、-;唯一范围是应用,跨 Token 和轮换有效。相同规范化 JSON 输入返回同一版本的当前状态,不同输入返回409;删除版本也保留键,不能复用它创建新版本。manifest 幂等不包含文件:上传恢复另按 filename/size/sha256 精确匹配;相同版本有不同文件的会话需先取消。完整上传重复 complete 不递增 revision。发布后先查询状态再重试,状态改变时旧 revision 返回409,避免误撤销或重复发布。

Git commit 必须是完整40或64位小写 hex;metadata 最多16KiB,仅字符串值,不得携带密钥。version_code 为1–9007199254740991,同应用/平台/架构/通道保持既有版本唯一约束。

文件策略、存储与资源界限

采用现有私有 S3 配置、AES-GCM 密钥加密、随机对象 key、分片恢复和清理 worker。机器 API 不接收任意存储地址或对象 key,不执行、部署或解压包。文件名只接受 ASCII 字母数字及 ._-,白名单 .zip .apk .exe .msi .dmg .deb .rpm .appimage,并检查对应文件头/尾;不是病毒扫描或代码签名验证。

机器制品单个≤128MiB(同步校验界限)、小文件表单≤32MiB、每片32MiB、上传有效24小时。每个应用最多100个未发布/取消版本,机器上传按该应用所有非 deleted 制品预留大小计算2GiB配额,包括等待清理对象;应用行锁防止并发超额。既有纯管理员版本上传保持原20GiB规则,故这是机器入口配额,不是管理员全局硬上限。机器版本即使通过管理员上传也执行机器文件策略与完整摘要校验。

机器请求每 IP 每分钟240次、每 Token 每分钟120次(Redis),单进程最多8个并发请求。Redis 故障拒绝请求。同步校验流式读取 S3 对象写入操作系统临时目录,最多128MiB/请求,结束删除临时文件;部署应为临时目录提供容量和访问隔离。分片合并后由服务端重算完整 SHA-256,不能把 S3 metadata 或 multipart 组合校验和当作完整文件摘要。ZIP/APK 不解压,检查目录数量≤10000、声明展开量≤256MiB、异常压缩比例、绝对/父级/Windows路径、特殊文件/符号链接及嵌套常见压缩包。

校验失败不会 ready,也不会发布;已合并的错误对象需取消会话再重新上传,后台清理。网络中断时先 GET 状态:若已 ready 可继续,若 S3 已合并但 DB 未提交,重试 complete 通过 HEAD + GET 恢复。未校验失败对象仍计入配额,防止重试滥用。现有 worker 负责过期/取消对象清理,S3 必须设置终止过期 multipart 生命周期;对象存储版本控制/保留规则可能导致存储费用残留。

管理员配置 S3 的 IAM、Endpoint、Bucket、Region、CORS 与 DATA_KEY_FILE 沿用 安装包存储说明。新增开关 MACHINE_RELEASES_ENABLED=false 可关闭机器路由,管理吊销接口保留。当前资源阈值是源码中的固定安全上限;扩大文件限额需要异步校验队列、超时和磁盘预算设计,本次不提供无限制调大开关。生产网关必须使用 HTTPS,禁止记录 Authorization、表单内容和预签名 URL。

审计与回滚

迁移 012_machine_releases.sql 新增 release_api_tokens、release_builds、release_machine_audit,以及管理权限。迁移沿用自动排序、事务和 advisory lock,可重复执行。未修改原版本/制品状态约束。审计保留 Token ID、应用、路由模板、版本 ID、HTTP 结果;执行前先落 intent,outcome=0 表示中断/未知,需查最终状态。错误应用和 scope 尝试也被记录;无法认证的随机 Token 不持久化其原文/摘要,受 IP 限速。原 release 审计保留签发者身份,新审计补充实际 Token。审计表无公开写入入口;数据库管理员仍属于信任边界,生产应另行归档。

回滚可由相应环境管理员撤销当前版本,使尚未升级的客户端重新看到旧的最高已发布版本。已经升级的客户端不会自动降级:应将已知良好构建作为更高 version_code 的新版本上传、校验和发布。不要先执行「清除历史版本」再计划回滚;被清理制品无法恢复。生产回滚同样须人工确认。

AI 工具使用

Python≥3.11,无第三方依赖。从密钥管理器注入 AC_RELEASE_TOKEN,不要把 Token 放命令行、提交文件或 shell tracing 输出中。

python scripts/release-artifact.py --base-url https://auth.example.com \
  --application APPLICATION_UUID --file ./app.zip \
  --version 1.2.0 --version-code 102 --git-commit FULL_GIT_COMMIT \
  --platform windows --arch x64 --channel beta \
  --idempotency-key pipeline-102 --metadata '{"builder":"ai-tool","run":"102"}'

默认只创建并上传草稿,附加 --publish 发布 alpha/beta;stable 明确拒绝该参数。CLI 不跟随重定向,不把 API Token 发给 S3;可用同一键重新执行,已 ready 且摘要/文件名/大小匹配时跳过上传,否则恢复同一会话重新写入分片。不要在同一构建过程中改动文件。结果只打印版本 ID、状态、摘要及生产审批提示。

curl 小文件示例(已有 RELEASE_ID、ASSET_ID 来自上述 API,环境中已有 Token):

curl --fail-with-body "$BASE/api/v1/automation/applications/$APP/releases/$RELEASE/uploads/$ASSET/file" \
  -H "Authorization: Bearer $AC_RELEASE_TOKEN" -F 'file=@app.zip'
curl --fail-with-body -X POST "$BASE/api/v1/automation/applications/$APP/releases/$RELEASE/uploads/$ASSET/complete" \
  -H "Authorization: Bearer $AC_RELEASE_TOKEN"

共享主机的 curl 命令参数可能被本机进程查看,推荐使用上面的 Python CLI;不得启用 curl -v 或命令跟踪输出密钥。

本地启动与验证

应用直接在本机运行。先检查 docker ps 与 docker port Postgres18 5432/tcp、docker port RedisPwd 6379/tcp;不得运行 compose 或创建/重建数据库容器。连接密码仅保存在被 Git 忽略的 .local/database-connections.md。从该文件在当前进程注入 DATABASE_URL(postgres 用户)和 REDIS_URL,使用检查到的 loopback 端口。

# 设置当前进程的 DATABASE_URL、REDIS_URL,以及本机密钥路径后:
$env:APP_ENV='development'
$env:APP_ORIGIN='http://localhost:13140'
$env:LISTEN_ADDR='127.0.0.1:13141'
$env:JWT_PRIVATE_KEY_FILE='<本机JWT私钥路径>'
$env:DATA_KEY_FILE='<本机32字节数据密钥路径>'
cd server
go run ./cmd/server keygen  # 仅新环境,已有密钥不会覆盖;两个父目录须已存在
go run ./cmd/server migrate
go run ./cmd/server
# 另一个本机终端:cd web; npm ci; npm run dev

迁移生产/已有业务库前按惯例备份;本次仅在测试专用随机 schema 应用迁移,没有修改用户业务表。

# 脚本读取忽略目录的凭据表,检查既有容器状态和端口,不打印连接密码。
./scripts/test-machine-releases.ps1 -Go '<go.exe路径>'
./scripts/test-machine-releases.ps1 -Go '<go.exe路径>' -Run '.'
cd server; go vet ./...
cd ../web; npm run typecheck
python ../scripts/release-artifact.py --help

实际结果(2026-09-10):Postgres18 / RedisPwd 均健康,loopback 5432 / 6379;MySQL 未使用。Go 全套执行通过(包含新增机器流程和现有数据库集成测试),只读页面测试因未配置 TEST_READONLY_DATABASE_URL 跳过。新流程覆盖成功 multipart/预签名上传、生产人工发布、状态/撤销、摘要错误、非法文件、应用/操作越权、重复与并发幂等、Token 失效及轮换、速率与草稿配额。Python CLI 通过实际本机 HTTP API 端到端上传、发布并重复执行,确认恢复同一版本。go vet ./...、Go 可执行文件构建、npm run typecheck、npm run build -- --webpack、Python 编译和帮助命令、git diff --check 均通过;OpenAPI YAML 成功解析,12个路径、61个本地引用均可解析。

S3 为本机 httptest 协议服务,不是实际云 Bucket;真实服务的 IAM、SigV4、CORS、跨网超时、大文件吞吐和对象生命周期尚未实测。浏览器人工/自动 UI 交互验收未执行,前端验证范围为类型检查和生产构建。可在配置现有 S3 后通过 CLI 复现完整流程,不需要新增数据库容器。npm 对当前本机 Node 预发布版本给出兼容性提示,但类型检查和 webpack 生产构建均成功;部署建议使用项目支持的稳定 Node 版本。

修改文件索引

文件修改
server/internal/app/machine_releases.goToken、scope、幂等创建、归属、状态、审计与路由
server/internal/app/machine_artifacts.go表单上传、文件策略、完整摘要和 ZIP 检查
server/internal/app/app.go机器路由注册、CSRF边界和请求大小
server/internal/app/release_uploads.go复用上传流程,加入机器配额和完成校验
server/internal/app/releases.go管理列表返回构建来源
server/cmd/server/main.go、.env.example机器 API 开关
server/internal/database/migrations/012_machine_releases.sql三张表、索引和管理权限
server/internal/app/machine_artifacts_test.go文件和 scope 边界单测
server/internal/app/machine_releases_integration_test.goPostgreSQL/Redis/S3 协议及 CLI 联调
web/components/workspace/release-tokens.tsx管理 Token 界面
web/components/workspace/releases.tsx管理入口及构建详情
scripts/release-artifact.pyAI 工具 CLI
scripts/test-machine-releases.ps1既有本地服务检测与测试启动
docs/machine-releases.md、docs/machine-releases.openapi.yaml、docs/releases.md设计、契约、操作、安全和验证文档