修复切换账号后画布资源不可编辑 (#182)
Project CI / Repository checks (push) Successful in 4m24s
Project CI / Frontend tests (push) Successful in 5m10s
Project CI / Backend tests (push) Successful in 5m37s
Project CI / Native shell tests (push) Successful in 13m9s

## 变更

- 新增按服务 origin、平台 userId / Developer Key 摘要和本地 projectId 分区的 External Editor 项目绑定
- 新增按当前 principal、远端项目、本地 assetId、源 SHA-256、媒体类型和 canonical kind 分区的资源绑定
- manifest 中的 canvasProjectId / resourceId / assetObjectId 仅保留来源信息,不再作为当前账号的可编辑授权
- 切换账号后从本地正式资源重新上传、confirm、登记;图片、视频、角色动画、素材画布参考、art-spec 派生和 Direct 恢复统一使用当前账号绑定
- prepared / accepted / running 账本继续冻结原 principal;账号变化或远端结果不确定时停止补偿并保留现场等待对账
- 同步技术方案、decision log 和 pitfalls

## Review 结论

- 两路独立代码 review 均未发现剩余 P0-P2
- Review 发现并关闭了 max-pass 测试误放宽问题,恢复为绑定最大轮次的强断言
- 首轮 CI 暴露两处本 PR import 排序错误,已在独立提交 09486f142 中修复并复核

## 验证

- Rust 完整测试:2301 passed,0 failed,16 ignored
- Rust 集成与构建测试:5 + 2 + 14 passed
- repository-ci 本地同构门禁通过:lint、typecheck、139 表 SpacetimeDB schema guard、403 个 appSurface 测试、web/admin-web build
- External Editor procedure 真实 smoke 通过:精确重放、冲突、删除 fail-close、并发和孤儿检查
- Encoding check:5594 files
- git diff --check 通过
- Gitea Project CI run 1253:Repository checks、Frontend、Backend、Native shell tests 全部通过
- 当前 head a0b8415be 已合并 origin/master 44ee28c43,PR 无冲突

## 后续依赖

PR #176 暴露了这一公共账号身份缺陷。该 PR 合并后,#176 需要 rebase,并删除或接入其局部 canonical cache,不能保留第二套账号绑定系统。

Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/182
Co-authored-by: kdletters <kdletters@qq.com>
Co-committed-by: kdletters <kdletters@qq.com>
This commit was merged in pull request #182.
This commit is contained in:
2026-08-24 11:33:37 +08:00
committed by 段舒康
parent 44ee28c43f
commit 2449e77461
49 changed files with 15628 additions and 1649 deletions
@@ -418,6 +418,11 @@
"ExternalApiKey": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotentCreateKey"
}
],
"requestBody": {
"required": false,
"content": {
@@ -439,11 +444,17 @@
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"409": {
"$ref": "#/components/responses/IdempotentCreateConflict"
}
}
}
@@ -684,6 +695,9 @@
"parameters": [
{
"$ref": "#/components/parameters/ProjectId"
},
{
"$ref": "#/components/parameters/IdempotentCreateKey"
}
],
"requestBody": {
@@ -718,6 +732,9 @@
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"$ref": "#/components/responses/IdempotentCreateConflict"
}
}
}
@@ -766,6 +783,11 @@
"ExternalApiKey": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotentCreateKey"
}
],
"requestBody": {
"required": true,
"content": {
@@ -795,6 +817,9 @@
},
"403": {
"$ref": "#/components/responses/Forbidden"
},
"409": {
"$ref": "#/components/responses/IdempotentCreateConflict"
}
}
}
@@ -1557,6 +1582,18 @@
"maxLength": 128,
"pattern": "^[!-~]+$"
}
},
"IdempotentCreateKey": {
"name": "Idempotency-Key",
"in": "header",
"required": false,
"description": "可选的稳定创建幂等键。同一账号、接口与键使用相同规范化请求体重试时返回首次结果的当前记录,即使该记录后来已被修改;同键不同请求体返回 409。首次结果已删除时,同键重放同样返回 409 且不会重新创建。网络结果不确定时必须复用原值。",
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"pattern": "^[!-~]+$"
}
}
},
"responses": {
@@ -1610,6 +1647,16 @@
}
}
},
"IdempotentCreateConflict": {
"description": "稳定创建幂等冲突:同一 Idempotency-Key 携带不同规范化请求体,或首次创建结果已删除 / 缺少耐久回执;服务端不会重新创建或重复首次副作用",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"UpstreamError": {
"description": "上游生成服务失败",
"content": {