Skip to content

归档说明(2026-09-29):本文已由新一轮静态评估与计划接替,不再作为现行状态或执行入口。原位置:docs/temp/architecture-assessment-2026-09-28.md。历史完成标记、测试结果、发布状态和建议均只代表当时记录;本轮没有重新验证。现行入口:架构调整收尾工作计划。

架构评估(现状与问题) ​

日期:2026-09-28。基线 2d7858b(分支 dev);代码重核至 3818eab(仅文档提交)。
定位:docs/temp 唯一现行评估。只陈述当前架构现状、已定决策与仍在问题;执行细节见 plans/remaining-work-2026-09-28.md。
口径:本版全部断言按当前仓库代码重核;「已实施」不等于「可对外承诺」;产品可接受残留(R-*)只登记。
与上一版差异:修正门禁覆盖面、任务方言计数与「空转测试」机制描述;补入 CP4 门禁假阴性、页面/组件队列恢复盲区、弱密钥单实例可上线、PG 备份脚本缺失、Renderer 同网段等遗漏;删除已过期的「构建 BackgroundTasks 无租约」判断。二次补强:Backend 多副本 Run 生命周期正确性、Runtime Build 凭证隔离、仓库 branch protection 未强制、Lite 容量口径、版本兼容矩阵、System DR、多副本措辞降档。


1. 一页结论 ​

  1. 控制面 / 执行面边界成立:Backend 不跑浏览器(pyproject.toml 无 Playwright),渲染只在独立 Renderer(packages/render-contracts);凭证 fail-closed;校验有单一谓词 validation_result;SQLite 单实例有锁。这层结构值得保持。
  2. 剩余架构主轴仍是任务运行时统一。领取时序已收口到 durable_job_lease_service.claim_rows_by_cas,但实有 10 套任务模型、3 套认领方言,心跳/恢复/终态词汇仍各写各的;且 CP4 防漂移门禁存在假阴性,已有认领实现绕过检测。
  3. **有一批「假守卫」 已清理(2026-09-29 WS-B):布局脚本死副本 ×7 已删;runtime-kit 测试改为 exports 真断言;render-contracts 补 DTO↔JSON Schema 对拍。假安全感入口已关闭。
  4. 多部署能力当前不仅「未验收」,仍有已知正确性与隔离缺口:Runtime 已完成角色拆分、构建持久租约与部分多副本选址;Backend 已具备 PG / Redis / 共享签名与对象存储前提。但普通 AI Run 启动恢复是全局扫描语义,新副本启动会终态化其它副本活跃 Run;RenderCoordinator 全局/工作空间额度是 check-then-act,多副本可超限;Runtime Build 的可信 Worker 凭证与不可信构建执行仍共处同一容器。Backend / Runtime / Renderer 多副本均不得作为生产承诺。
  5. 仓库级 merge gate 未强制 已强制(2026-09-29 WS-B0):main/dev 启用 classic branch protection(require PR + 1 审 + required check quality)。
  6. 产品边界已定(见 §3):Run 承诺会丢;Lite 目标 5–10 人 / 预览并发约 3(容量验收前不是 SLA);双库方言预算从宽。
  7. 顺序建议:死物/假守卫 + merge gate 强制 + CP4 补强 (已完成 2026-09-29) → Backend 多副本 Run 语义与 Build 隔离 → 任务运行时契约冻结与恢复盲区 → 容量基线 → 多部署门槛与演练(含版本兼容)→ 契约机械化 → 巨石拆分 → System DR。多副本承诺最后。

2. 架构现状 ​

text
Editor ──HTTP──► Gateway ──┬──► Backend(控制面)
                           │     ├─ 领域服务 / AI Run(进程内)/ 工具规格(tool_specs SSOT)
                           │     ├─ 重任务队列(10 套任务模型;3 套认领方言)
                           │     ├─ render_requests → RenderCoordinator(多副本额度未原子化)
                           │     └─ SQLite(单实例锁)| PostgreSQL
                           │         + memory:// | redis://(窄命令)
                           │
                           ├──► Runtime(preview|build|check 三角色;build 编译不可信 SFC)
                           └──► Renderer(单槽 Chromium)
                                   packages/render-contracts
能力面现状可对外承诺?
浏览器截图/渲染只在 Renderer,凭证 fail-closed,每 attempt 新建 Context是
页面校验通过判定唯一谓词 validation_result.is_validation_passed是
SQLite Lite单进程/单容器,memory:// 运行态是(目标规模,见 §3;D2 未过不是 SLA)
重任务恢复页面/图片/截图/构建/回填/外部 Batch 走 DB 租约是(页面/组件 L1 循环内恢复已补,2026-09-29)
普通 AI Run进程内,重启即 AI_RUN_PROCESS_STOPPED是:承诺会丢(文档已披露,UI 弱)
Runtime 多副本固定副本、静态注册形态(手工复制 service + nginx upstream);动态发现/扩缩容/摘流与跨副本演练未做否
Backend 多副本共享前提(RSA/密钥/对象存储/Redis)已校验;Run 启动恢复全局扫描会杀其它副本活跃 Run否(已知不正确)
Renderer 多协调器单 Worker 占用有 active_occupancy 唯一索引保护;全局/工作空间额度 check-then-act 可超限否
双库(SQLite / PG)迁移与认领双方言,有门禁(含 PG 认领必跑)是(成本见 §3 D1)
工具目录tool_specs.py 单一事实源,派生链完整是(防漂移主测不在 PR,见 P0-Gates)
仓库 merge gatePR workflow 存在;branch protection / ruleset 为空否

3. 已定决策 ​

决策结论成本与边界
Lite 地位长期一等公民(SQLite)双库永久税;Lite 禁止多副本共用 DB 卷
Lite 目标规模目标 5–10 人小团队,预览并发约 3产品目标,容量验收(D2)前不得作为 SLA/硬承诺;常规演示文稿工作区,非海量资产库
Run 持久性承诺「会丢」不做可恢复 Run;用户文档已披露重启不续跑;UI 仅显示「运行已停止」
双库方言预算从宽正常双方言成本 = 固定税。正常 ≤ 8 人周/季。重开 D1 仅当:单季计入 > 12 人周,或连续两季 > 8 人周/季,或方言阻塞发版 ≥ 3 次/季,或放弃 Lite 一等公民
写路径基线(D2)作为节奏参数来源尚未采集;不阻塞任务运行时设计,但阻塞 Lite 规模升格为承诺
截图环境身份现状可接受升级后可复用旧图;不强制环境指纹(R-Screenshot)
CDP / 浏览器池不做渲染只走远程 Renderer
多副本承诺门槛已知正确性缺口关闭 + 跨副本故障演练通过 后才开放不是「有 compose 模板」即可宣称

4. 仍在问题 ​

4.1 优先(P0 / P1) ​

ID问题为何重要出口
P0-BackendMultiInstancerecover_interrupted_agent_runs_on_startup 无 owner/lease/epoch,启动时把全库 pending/running/cancelling Run 一律终态化(run_recovery.py:22-36)。Backend-B 扩容/滚动启动会杀死 Backend-A 正在执行的 Run。signing_identity 多实例校验只查共享 RSA/密钥/对象存储/Redis,不禁止该语义跨副本正确性问题,不是「未演练」;配置层误示 multi-backend 已安全并入 WS-C 前置 blocker;恢复改为按 owner/epoch 认领
P0-BuildIsolationruntime-build 编译用户 SFC(不可信),却挂载全局 build_worker_credential(compose.runtime-roles.yml:212-225);子进程只删 env(runtime-build-worker.ts:30-42),同容器同 mount、Dockerfile 无 USER(root),仍可读 /run/secrets/build_worker_credential。该凭证可 claim 任意 pending 构建并领取 build_token/service_token可信 Worker 身份与不可信构建执行共处一容器,不是弱默认密码问题并入 WS-G3 升级:sandbox 独立/降权/只拿单任务短 TTL token
P0-MergeGatemain/dev branch protection 为空「有 CI」≠「有门禁」已关闭(2026-09-29 WS-B0):main/dev 均启用 classic protection(1 审 + required check quality)
P0-DeadGoods布局脚本死副本 ×7;runtime-kit 测试断言 capabilities;render-contracts JSON Schema 零消费假安全感已关闭(2026-09-29 WS-B1–B3):死副本已删;manifest 测试改 exports 真断言;补 test_schema_roundtrip.py
P0-ClaimGateCP4 门禁假阴性:变量间接 execute(update) 与 reserve_* 命名漏检并发原语边界可被合法合入破坏已关闭(2026-09-29 WS-B ClaimGate):AST 检测补强;claim_next_pending_job 迁 claim_rows_by_cas;reserve_attempt 登记例外
P0-Gates工具目录主防漂移在 integration,PR 默认不跑漂移可合法合入 PR已关闭(2026-09-29 WS-B4):主测迁 tests/unit/test_unified_tool_specs.py(test:backend:unit 在 PR);contracts/render-contracts 本就在 PR。E2E/镜像 smoke/CLI 跨仓仍非 PR 阻塞(已知边界)
P1-Recovery页面/组件变更队列 Worker 循环内不做过期恢复 已关闭(2026-09-29):Worker 循环内补过期恢复故障后任务挂死,用户无感知已关闭(2026-09-29 WS-A3)
P1-TaskModel重任务 10 套任务模型;认领时序 3 套(共享 CAS / lease_generation CAS / render claim_generation);心跳比例、终态词汇(image "error" vs 他处 "failed")不统一正确性靠各队列自觉;扩展成本高;故障语义不可比部分关闭(2026-09-29 WS-A):契约冻结 + 统一执行器 + 队列迁移完成;render reserve_attempt 仍为登记例外
P1-RenderQuotaRenderCoordinator._dispatch_once 先 count_active_attempts() 再 reserve_attempt()(coordinator.py:254-285),非全局事务原子;多 Backend 可同时见 active=0 而突破 global/workspace limit(单 Worker 双派已有 active_occupancy 唯一索引保护) 已修(2026-09-29):dispatch 持调度状态准入锁后同事务计数+reserve多协调器下额度失守已并入 WS-C 并落地
P1-MultiDeploy多部署门槛未达成;Runtime 多副本是静态固定拓扑(手工复制 service + nginx upstream、静态 RUNTIME_CHECK_BASE_URLS);跨副本回归/故障演练未跑容易把 compose 静态复制当成真正分布式计划 WS-C
P1-VersionSkew滚动升级只约定 Runtime build_id/runtime_kit_version 指纹一致;缺 兼容矩阵:Backend↔Runtime API、Backend↔Renderer render-contracts、Backend↔DB schema、Runtime Kit↔产物。版本不一致直接拒绝会造成瞬时停机多服务独立部署后滚动升级必需并入 WS-C
P1-LiteLite 故障域合并(Backend+Runtime+Nginx);混合负载未验收;test:lite:runtime-state-drill 有脚本但不在 CI目标规模缺运行证据WS-G1 + WS-D
P1-Secrets示例弱密钥(AI_SECRET_ENCRYPTION_KEY=AAAA…、DEFAULT_ADMIN_PASSWORD=change-admin-password)可被单实例/Lite 直接采用;占位拒绝仅在多实例路径轻量部署可带弱 Fernet/弱管理员密码上线WS-G3
P1-Backupdeploy/scripts/ 仅 SQLite demo 备份/恢复;无 PG 备份脚本、全仓无 pg_dump。生产恢复实为 DB + 对象存储 + AI 加密密钥 + RSA keyring + service credentials 组合态,缺 System DR(RPO/RTO、恢复顺序、密钥备份/轮换)DB 恢复了 S3 没恢复 = 悬空引用;密钥丢了密文永久不可读WS-G4 升格为 System DR
P1-Health队列/租约积压无对外指标;code_check_result_cache.snapshot_metrics 无出口;/metrics/* 仅 db-write/runtime-state积压不可见WS-G2
P1-RunDisclosureRun「会丢」在用户文档已披露(docs/user/ai/workflow.md 等),但 Editor UI 只显示「运行已停止」,未区分「取消」与「进程停止、不续跑」与 external 任务持久承诺并存,用户不可辨WS-G7

4.2 维护性(P2) ​

ID问题出口
P2-ContractsEditor types/api.ts(约 1551 行)手写镜像 Backend schema,无 OpenAPI→TS;previewSchema 三份手写(Backend 校验器 / Editor component-preview.ts / Runtime runtime-preview.ts)无对拍WS-E
P2-GodFilesplatform_runtime.py(2082 行,store+SSE+状态机)、session_facade_pydantic.py(1802 行)、page_mutation_queue.py(849 行)等;ai↔services 双向依赖(约 25↔15 文件),懒 import 掩盖环WS-F
P2-DialectOps双库日常成本可见性(记账与复审触发器需落到治理文档)WS-G6
P2-ProdHardeningRenderer 与 Backend 同 platform-net,浏览器可触达 Backend 内网 API(仅拦 Renderer 控制面路径);compose.with-deps Redis appendonly no;各 Dockerfile 均无 USER(root)WS-G3/G5
P2-AuthZGap缺「A 用户 AI 工具调用写 B 用户实体」的跨用户工具矩阵已关闭(2026-09-29 WS-B):补 test_cross_user_ai_tool_write_should_be_denied;写路径增加 AgentWorkScopeService.require_workspace_access 操作者成员校验
P2-VocabDrift终态词汇(error/failed/skipped)、心跳/租约比例、死列 ai_page_mutation.lease_generation、死 scope COMPONENT_TOOL_DELETE_SCOPES部分关闭(2026-09-29):Job 终态已统一 succeeded/failed/cancelled;死列/死 scope 待清

4.3 产品可接受残留(登记,不进优先级) ​

ID问题处理
R-Screenshot截图指纹不含 Runtime/Chromium/字体环境版本可复用旧图;可选发布提示手动刷新
R-Profileprofile.v1 手填多副本强一致成为目标时再改
R-CP5sqlite :memory: + BACKEND_MULTI_INSTANCE 不被拓扑拒绝(sqlite_single_process.py 内存库 early-return 在拓扑校验之前)。注:memory:// Redis + 多实例已被拒非真实部署形态
R-CP6AI 事件追加进程内锁保留保护同一会话上的并发写,与方言无关

5. 尚未验证(不能当作已有能力) ​

  • D2 容量基线(锁等待、队列年龄、P50/P95、混合负载 RSS/OOM)——Lite 规模升格为承诺的前置
  • 故障注入(Renderer 全挂、构建被杀、写冲突耗尽、升级中断 Run、多副本并发启动互相杀 Run)
  • 多实例联调(共享对象存储、密钥、跨实例租约与迁移;Render 额度在多协调器下是否超限)
  • 版本 skew 兼容(Backend N ↔ Runtime/Renderer N-1、DB migration 期间旧副本存活)
  • Lite 成功构建产物下载;test:lite:runtime-state-drill 未进 CI
  • 两阶段校验耗时拆分
  • System DR 演练(脚本本身不存在;密钥备份/轮换未定义)
  • Build sandbox 逃逸面(同一容器 root + 全局 credential 的实际风险)

6. 处理方向 ​

序工作目标
0启用 branch protection / ruleset(WS-B0)已完成(2026-09-29)
1死物清理 + 假守卫修复 + CP4 门禁补强已完成(2026-09-29 WS-B)
2Backend 多副本 Run 恢复语义 + Build credential 隔离关闭跨副本正确性与信任边界缺口(多部署前置)
3任务运行时契约冻结 + 页面/组件恢复盲区统一角色模型 / 字段 / 恢复语义;循环内恢复
4D2 与 Lite 规模基线采集用数字支撑目标规模;通过前不写 SLA
5多部署门槛 + Render 额度原子化 + 版本兼容矩阵 + 跨副本演练不过则保持“单副本可用”口径
6双入口对拍、类型/schema 单源降低人肉对齐
7巨石拆分(宜在运行时迁移前)降低改动面
8Run / Lite 文档与 UI 承诺落地与 §3 决策一致
9System DR + 生产加固(弱密钥拒绝、密钥/对象存储/DB 联合恢复、网络隔离)运维与安全风险
10多副本对外承诺严格最后

编号与验收口径见 plans/remaining-work-2026-09-28.md。


7. 代码锚点 ​

text
backend/app/ai/run_recovery.py:22-36                                 全局扫描终态化(P0-BackendMultiInstance)
backend/app/services/signing_identity.py:257-310                     多实例共享前提校验(不含 Run 语义)
backend/app/services/rendering/coordinator.py:254-285                额度 check-then-act(P1-RenderQuota)
runtime/src/core/plugins/runtime-build-worker.ts:30-42                仅删 env(P0-BuildIsolation)
deploy/compose/compose.runtime-roles.yml:203-225                     runtime-build 挂全局 credential
runtime/Dockerfile                                                   无 USER(root)
backend/app/api/routes/internal_runtime.py:442+                      全局 claim → build_token/service_token
.github/workflows/{platform,reusable-quality}-.yml                   PR 测试面(merge gate 未强制)
backend/app/services/durable_job_lease_service.claim_rows_by_cas     认领时序(共享 CAS)
backend/app/services/mutation_job_service.claim_next_pending_job      自写认领(CP4 门禁漏检)
backend/app/services/rendering/repository.reserve_attempt            render 认领方言
backend/app/ai/{page_mutation,component_mutation}_queue.py            恢复仅启动时(P1-Recovery)
backend/app/services/project_build_service.py                        构建租约/attempt(已走 CAS)
backend/app/services/runtime_state/                                  运行态窄接口
backend/app/services/validation_result.py                            校验谓词
backend/app/db/{retry,tx,profile,sqlite_single_process}.py            方言边界
backend/app/ai/tool_specs.py                                         工具目录 SSOT
backend/tests/unit/test_unified_tool_specs.py                        工具防漂移主测(PR unit,2026-09-29 迁入)
backend/tests/unit/test_db_adapter_layer.py                          CP4 门禁(AST 已补强,2026-09-29)
backend/tests/integration/ai/test_ai_generic_business_tools.py       跨用户 AI 工具写入矩阵(2026-09-29)
packages/render-contracts/tests/test_schema_roundtrip.py             DTO↔JSON Schema 对拍(2026-09-29)
tests/contracts/runtime-backend/runtime-kit-manifest.test.ts         exports 真断言(2026-09-29 修复)
deploy/scripts/                                                      仅 SQLite demo 备份

8. 对上一版评估的修正与补漏 ​

上一版表述代码重核结论
「manifest.capabilities 空转测试」更严重:测试读 capabilities,manifest 真实键是 exports,后两条断言恒空转;仅 alias 有效
「约 9 套」任务方言10 套任务模型;认领时序实为 3 套;「构建 BackgroundTasks 无租约」已过期(现走 claim_rows_by_cas)
「架构测试不在 PR 阻塞层」过宽:unit/api(含 test_multi_user_access 越权矩阵)在 PR;integration(工具防漂移主测)/E2E/镜像 smoke/CLI 契约不在 PR
「PG 备份演练不足」更严重:PG 备份/恢复脚本全仓不存在;且应升格为 System DR(DB+对象存储+密钥组合态)
「示例密钥/弱默认」(P2)应为 P1:单实例/Lite 无启动拒绝,可带弱密钥上线
R-CP5「memory:// + 多实例不拒绝」不精确:memory:// Redis + 多实例已拒;未拒的是 sqlite :memory: + 多实例
「Run 会丢尚未在 UI/文档体现」部分过时:用户文档已披露;缺口在 Editor UI 文案未区分取消/进程停止
「多部署:代码具备,演练未做」不充分:不仅是未演练——Run 全局恢复会杀其它副本活跃 Run(P0)、Build 全局凭证与不可信执行同容器(P0)、Render 额度非原子(P1)
「Lite 推荐规模 5–10 人」写进「可承诺」口径冲突:D2 未过时只能是目标规模,不得作 SLA
(未记)新增 P0:Backend 多副本 Run 生命周期、Build 凭证隔离、branch protection 未强制;CP4 门禁假阴性;页面/组件恢复盲区;Renderer 同网段
(未记)新增 P1:版本兼容矩阵缺失(rolling upgrade 会瞬时停机);Render 多协调器额度竞态