原生后端详细架构图册:G1–G8
基线日期:2026-10-06,Asia/Shanghai。按本轮已经交付的原生后端与指定 Actions 证据编写。本次只更新架构文档 / 网页图,没有重新测试、发布或操作云资源。
阅读顺序:系统拓扑 → 环境与事实存储 → 实体与业务流 → 任务 / 清理 → 身份与拒绝 → 构建 / 发布 → 恢复 / 回滚 → 退役 → 证据与待测。图形中的箭头区分请求、数据写入、控制和恢复;不凭位置推断事务性、授权或物理隔离。
0. 图例、范围与关键结论
| 表达 | 意义 | 不代表什么 |
|---|---|---|
| 实线箭头 | 已接线的请求、读写、控制或验收路径;以标签为准 | 不自动等于内网、同步请求或跨服务事务 |
| 虚线箭头 | 验收后的管理关系、非日常路径或人工待测路径;标签说明具体含义 | 不能把未测终端体验写成真实用户已通过 |
| 环境子图 | staging / production 的业务与权限边界 | 不一定是独立物理实例、独立 VPC 或独立故障域 |
| 已退役组件 | 软件停止、自动启动关闭、无业务调用 | 不表示删卷、删原数据库、释放 ECS 或删除备份 |
| 验收数字 | 指定 run 中的检查与测量快照 | 不等于全规模 SLA、永远最新版本或测试上限 |
本轮 G1–G8 的主线是:独立资源领域 + MySQL 全域业务接线 + 私有 TOS 持久文件 + 同镜像自动发布 + 恢复 / 回滚 + 实际 RomM 退役。开发阶段不保留旧账号 / API / RomM 映射兼容,不承担旧业务记录无损迁移;文件资产没有被默认删除。原 Goal 已取消的 legacy、前端全量视觉和强制全量加密备份要求不能重新当门槛。
1. 系统请求面与控制面
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart TB
subgraph CLIENT[用户请求面]
WEB[浏览器\n首页 / 账号 / 云库 / 收藏 / 社区 / 游戏库]
ADMIN[运营台\n站内用户 + 服务端 Admin 角色]
LAUNCH[本地桥接器\n一次性票据 / 真实终端体验待测]
end
subgraph EDGE[环境网络入口]
STG_EDGE[staging DNS / HTTPS / Nginx]
PROD_EDGE[production DNS / HTTPS / Nginx]
end
subgraph APP[无状态原生应用]
WEB_STG[staging 网站 / API 容器]
WEB_PROD[production 网站 / API 容器]
ROUTES[server.mjs\n原生路由 / 页面 worker]
DOMAIN[身份 / 目录 / 社区 / 文件 / 运营 / 票据]
end
subgraph FACTS[外部持久事实]
STG_DB[staging MySQL 业务库]
PROD_DB[production MySQL 业务库]
STG_TOS[staging 私有 TOS]
PROD_TOS[production 私有 TOS]
MODELS[公开内容哈希模型\nLFS / 不可变 manifest / CDN]
end
subgraph CONTROL[独立控制面]
STG_WORKER[staging 存储 worker]
PROD_WORKER[production 存储 worker]
RELEASE[Actions / 独立 Runner / 部署控制器]
RECOVERY[托管备份 / 连续日志 / 隔离恢复]
end
WEB --> STG_EDGE
WEB --> PROD_EDGE
ADMIN --> PROD_EDGE
STG_EDGE --> WEB_STG
PROD_EDGE --> WEB_PROD
WEB_STG --> ROUTES
WEB_PROD --> ROUTES
ROUTES --> DOMAIN
WEB_STG --> STG_DB
WEB_PROD --> PROD_DB
WEB_STG --> STG_TOS
WEB_PROD --> PROD_TOS
WEB --> MODELS
LAUNCH -. 用户交付票据后兑换 .-> DOMAIN
STG_WORKER --> STG_DB
STG_WORKER --> STG_TOS
PROD_WORKER --> PROD_DB
PROD_WORKER --> PROD_TOS
RELEASE -. 拉取 / 验收 / 切换代码 .-> WEB_STG
RELEASE -. 同 digest 晋升 .-> WEB_PROD
RECOVERY -. 备份与隔离恢复 .-> STG_DB
RECOVERY -. 备份与隔离恢复 .-> PROD_DB这里的 ROUTES / DOMAIN 是两个网站镜像中的逻辑层,不是额外购买的中心服务。实现入口是 server.mjs、lib/server/native-web-runtime.mjs 和 lib/server/native-api.mjs;app/api/ 只覆盖部分接口。图中没有 RomM 的在线调用箭头,也没有“所有请求必须经过 Redis”的路径。
2. 环境部署、物理边界与事实存储
2.1 物理部署与权限隔离
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart LR
subgraph BUILDER[独立北京构建 ECS]
RUNNER[可信 self-hosted Runner]
CACHE[BuildKit / LFS / npm 缓存]
LOOPBACK[回环代理入口]
RUNNER --> CACHE
RUNNER --> LOOPBACK
end
subgraph STG[staging 网站 ECS]
STGNG[Nginx]
STGA[网站槽位 18787 / 18788]
STGC[main 隔离槽位 18887 / 18888]
STGW[独立 worker / UID 10002]
STGNG --> STGA
STGNG -. 受控候选选择 .-> STGC
end
subgraph PROD[production 网站 ECS]
PRODNG[Nginx]
PRODA[网站槽位 18887 / 18888]
PRODW[独立 worker / UID 10002]
PRODNG --> PRODA
end
subgraph RDS[一个托管 MySQL 8.4 物理实例]
SQLSTG[rewind_native_staging\n独立应用 / 初始化身份]
SQLPROD[rewind_native_production\n独立应用 / 初始化身份]
end
STGA --> SQLSTG
STGC --> SQLSTG
STGW --> SQLSTG
PRODA --> SQLPROD
PRODW --> SQLPROD
STGA --> BUCKETSTG[独立 staging 私有桶]
STGW --> BUCKETSTG
PRODA --> BUCKETPROD[独立 production 私有桶]
PRODW --> BUCKETPROD
RUNNER -. 受控部署,网站机不构建 .-> STG
RUNNER -. 受控部署,网站机不构建 .-> PROD当前两个业务库共享一个托管 MySQL 实例,因此存在共同故障 / 维护域。独立数据库名、SQL 账号、私有桶与 IAM 边界已实际验证;这不能冒称两个独立数据库实例或跨机房高可用。未来需要独立物理实例、读副本或高可用时,应基于容量和可用性另行决策。
2.2 有日期的资源清单
以下是本次完成基线的定位信息,不是以后部署必须照抄的永久前提;密钥值不记录。
| 角色 | 定位 | 当前职责 / 限制 |
|---|---|---|
| 独立北京 Runner | 115.190.54.32,rewind-build-runner-beijing | 信任检查、测试、Dockerfile 构建、私有 CR、部署;不和网站共机 |
| staging ECS | 115.190.119.205 / 私网 172.31.28.237 | staging.rewindcloud.fun、原生网站、独立 worker |
| production ECS | 115.191.71.187 / 私网 172.31.28.236 | rewindcloud.fun、原生网站、独立 worker |
| 托管 MySQL | mysql-2d56c9bebec4,MySQL 8.4.7-7 | 一个物理实例;环境业务库独立 |
| MySQL 私网目标 | 172.31.28.238:3306 | 已接受固定私网非 TLS 例外;不扩大到其他连接 |
| 业务库 | rewind_native_staging / rewind_native_production | 应用表级权限、初始化与应用身份分离 |
| 私有文件桶 | rewind-private-staging-littsk / rewind-private-production-littsk | 玩家文件、分片、版本与环境私有备份域 |
| 私有对象域 | private/rewind-native/{env}/ | 业务文件,不只靠前缀做环境隔离 |
| 备份域 | backups/rewind-native/{env}/ | 应用不能删除;独立保留 / 恢复 |
| 公开模型资产 | retro-cloud-play-iso-littsk 的公开模型资产路径 | 不承载私有玩家 ROM 或私有备份 |
| 模型内容路径 | roms/assets/models/{sha256}/{path} | 内容寻址复用;哈希与真实字节核对 |
| manifest 路径 | roms/manifests/digibitplay/{env}/{40sha}.json | 环境 / 完整提交绑定,不可变发布 |
| 模型 CDN | https://cdn.rewindcloud.fun | 公开模型,不授予玩家私有文件权利 |
| 北京私有 CR | rewind-images-cn-beijing.cr.volces.com/rewind/app | 推拉身份分离,原始 digest 部署 |
| 认证代理 | Runner 回环 127.0.0.1:17891 → RFCHost 出口 | 按需 GitHub / LFS / 海外依赖;不是公共开放代理 |
资源清单是脱敏拓扑,不要在其旁边补入真实密码、Access Key、签名 URL、Cookie、历史 .env 或 Config.Env。日常访问和发布具体步骤由 SOP 管理,架构图不构成资源购买或删除授权。
2.3 每类状态的事实存储
| 状态 | 权威存储 | 为什么 | 本机 / 缓存作用 |
|---|---|---|---|
| 用户、身份、设备、会话、挑战、角色 | MySQL 实体表 | 稳定身份、过期撤销、一次性、跨实例一致 | 请求上下文可临时缓存,不能绕过撤销 |
| 游戏目录、发行版本、地区语言、媒介、文件组 | MySQL 实体关系 | 目录身份与字节身份分离、多文件 / 多光盘 | 页面展示和公开 DTO 可重建 |
| 社区、收藏、运营、个性化记录 | MySQL 实体表 | 事务、关联、审计、分页、多写者 | 页面 / 查询缓存不是唯一主数据 |
| 上传会话、分片索引、outbox、租约 | MySQL | 换实例 / 中断 / 重试后恢复控制状态 | 不依赖 ECS pending 文件 |
| ROM / ISO、用户上传、存档、持久分片字节 | 私有 TOS 精确对象版本 | 独立于应用 ECS、可信摘要与授权 | 临时流缓冲可重建,本地 ROM 缓存是副本 |
| 玩家持有、共享引用、对象摘要 / VersionId | MySQL | 授权与物理清理约束、共享引用事务 | 不再使用 content-index.json |
| 模型原始源文件 | Git LFS + Git 中的指针身份 | 大文件版本与代码绑定 | Runner LFS 缓存减少重复传输 |
| 公开模型发布文件 | 内容哈希 TOS / CDN + 不可变 manifest | 分环境 / 分提交追溯、缓存和回退 | 镜像只保存可信模型索引;无GLB/ECS回退 |
| 自动备份 / 连续日志 / 恢复证据 | 托管备份 + 私有独立对象域 | 不依赖网站系统盘、应用不可删 | ECS 快照只补充系统恢复 |
| 启动器下载副本 / LRU 索引 | 用户设备 | 不影响云端事实,可重新下载 | 真实终端行为仍需人工待测 |
| Redis / 内存 / 临时磁盘 | 仅可重建或生命周期明确短态 | 不作为不可重建业务唯一存储 | 当前原生业务图不假定已有必需 Redis 服务 |
3. 关系模型与领域边界(G2 / G4)
下面是领域关系图,不将概念实体名冒充数据库中每张表的精确 SQL 名。精确表、列、迁移版本和约束以 lib/persistence/native-schema.mjs 为准。G6 恢复证据核对 schema 6、59 张表、100 个外键及无孤儿关系。
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
erDiagram
USER ||--o{ IDENTITY : binds
USER ||--o{ DEVICE : registers
USER ||--o{ SESSION : owns
USER ||--o{ ROLE_ASSIGNMENT : has
USER ||--o{ CHALLENGE : verifies
USER ||--o{ PLAYER_REFERENCE : owns
USER ||--o{ FAVORITE : selects
USER ||--o{ POST : writes
USER ||--o{ UPLOAD_SESSION : starts
USER ||--o{ LAUNCH_TICKET : requests
PLATFORM ||--o{ GAME : classifies
GAME ||--o{ RELEASE : editions
RELEASE ||--o{ RELEASE_LANGUAGE : languages
RELEASE ||--o{ RELEASE_REGION : regions
RELEASE ||--o{ FILE_GROUP : contains
MEDIA ||--o{ FILE_GROUP : represents
FILE_GROUP ||--o{ FILE_MEMBER : ordered_files
OBJECT_VERSION ||--o{ FILE_MEMBER : resolves
OBJECT_VERSION ||--o{ PLAYER_REFERENCE : authorized_refs
PLAYER_REFERENCE ||--o{ LAUNCH_TICKET : authorizes
UPLOAD_SESSION ||--o{ UPLOAD_PART : checkpoints
UPLOAD_SESSION ||--o{ STORAGE_EVENT : schedules
STORAGE_EVENT ||--o{ TASK_LEASE : claimed
CIRCLE ||--o{ MEMBERSHIP : members
USER ||--o{ MEMBERSHIP : joins
CIRCLE ||--o{ POST : organizes
POST ||--o{ REPLY : replies
USER ||--o{ PERSONAL_SETTING : configures3.1 身份领域
用户、供应商身份、设备、会话、撤销、角色、挑战、限流和审计是持久业务事实。外部供应商只证明身份,后端负责绑定、会话和每个资源边界。provider + subject 不是简单“邮箱一样就猜同一个人”。挑战需要受限生命周期和一次性消费;验证码明文不长期保存在普通收件箱。
3.2 目录领域
平台 → 游戏 → 发行版本 → 文件组是不同身份层级。地区、语言、媒介、多光盘和多文件有显式关联。SHA-256 表示整文件内容身份,不决定游戏 / 地区 / 授权;扩展名不能独立判断平台。人工元数据导入 / 校验 / 修订接管旧依赖,不恢复不稳定自动抓取。
3.3 玩家与社区领域
持有关系与收藏分开:收藏公开目录并不自动持有私有文件。圈子、成员、帖子、回复、点赞、关注、举报、提案、审核和个性化记录在实体仓储中维护,查询有完整分页,写入有事务 / 约束 / 审计。公开内容不能通过搜索、错误响应或详情泄露私有对象。
3.4 文件与任务领域
对象版本包含可信摘要、大小、格式、精确 VersionId 和就绪状态;玩家引用表达所有权 / 可访问关系。上传会话与分片索引描述恢复位置,分片字节在 TOS。outbox / 任务 / 租约记录异步处理,不依赖进程内队列作为唯一状态。启动票据绑定已授权文件快照,跨实例一次消费。
必要的小型结构化元数据不等于“把整个业务库塞一行 JSON”。禁止的是全库 JSON 覆盖、JSON 事实存储回退和新旧双写,而不是禁止一切 JSON 请求或元数据字段。
4. 身份、鉴权与运营(G2 / G4 / G5 / G8)
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
sequenceDiagram
participant U as 浏览器 / 管理台
participant P as Google / 配置的供应商
participant A as 原生认证 API
participant D as MySQL 身份 / 会话 / 挑战
participant B as 业务 / 管理 API
U->>A: 发起登录或挑战
A->>D: 建立受限 state / nonce / 挑战状态
A-->>U: 授权入口或受限挑战结果
U->>P: 用户完成供应商交互(真人流程待测)
P-->>A: 回调或可验证身份结果
A->>D: 核对挑战 / 过期 / 一次性消费
A->>P: 校验供应商身份 / JWKS 等必要验证
A->>D: 绑定稳定身份并建立站内会话
A-->>U: 站内会话结果
U->>B: 站内会话 + 业务请求
B->>D: 校验会话、撤销、角色与资源引用
alt 已授权
B-->>U: 限定业务结果
else 无会话 / 无角色 / 无持有关系
B-->>U: 明确 401 / 403 / 隐私安全的拒绝
else 存储或必要配置故障
B-->>U: 明确失败,不造用户或伪造空库
end管理台的 Admin 是应用授权角色,不是 MySQL 管理账号。数据库初始化 / 管理身份不注入网站容器。自动集成检查覆盖正常站内登录、服务端权限和普通用户拒绝;真人 Google 页面、刷新切页退出再登录和管理表格交互仍记录在人工待测清单,不用合成会话绕过正式鉴权宣称真人通过。
可配置短信交付不等于本轮所有供应商已端到端完成;Android 和其他登录供应商继续延期。存储故障不能退回内存授权,缓存不能继续授予已撤销资源。
5. 上传、对象就绪与跨介质一致性(G3)
5.1 可恢复上传时序
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
sequenceDiagram
participant U as 已认证用户
participant A as 文件 API / 应用实例 A
participant D as MySQL 会话 / 分片 / outbox
participant T as 私有 TOS
participant W as 独立存储 worker
participant B as 应用实例 B
U->>A: init(平台 / 文件组 / 资源约束)
A->>D: 持久化 owner、幂等键与上传状态
A->>T: 建立受限分片上传
A->>D: 记录云端上传身份 / checkpoint
A-->>U: 受限上传会话
loop 各分片
U->>A: part(会话 / 分片身份 / 字节)
A->>D: 校验 owner / 状态 / 期限
A->>T: 持久化分片字节
A->>D: 记录分片结果 / 可恢复 checkpoint
end
Note over A,B: 进程中断或更换完整应用实例
U->>B: 查询 / 续传上传会话
B->>D: 恢复持久会话与完整分片索引
B->>T: 核对必要云端分片状态
B-->>U: 可恢复进度(不依赖旧 ECS 目录)
U->>B: complete 请求
B->>D: 事务写入完成状态与稳定 outbox 事件
W->>D: 带租约领取提交任务
W->>T: 幂等完成 / 获取精确版本 / 读取验证字节
W->>D: 记录可信整文件摘要 / VersionId / ready / 引用
B->>D: 查询完成结果
B-->>U: ready 或明确 pending / 失败 / unknownMySQL 和 TOS 没有跨服务原子事务。API 顺序调用成功不能代表关联天然一致;服务端通过事务 outbox、稳定事件身份、租约、幂等云操作、就绪门禁和对账处理崩溃 / 重试 / 提交未知。细节以上传与对象仓储实现为准,图中的状态名表达领域合同而非承诺精确某个函数名。
5.2 状态机和异常分支
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
stateDiagram-v2
[*] --> Initialized
Initialized --> Uploading: 分片字节外置 / 持久 checkpoint
Uploading --> Uploading: 续传 / 分页核对 / 幂等重试
Uploading --> CompletionRequested: complete + 稳定 outbox
CompletionRequested --> Committing: worker 租约领取
Committing --> Verifying: 云端提交 / 精确 VersionId
Verifying --> Ready: 整文件摘要可信 / 引用事务成立
Committing --> OutcomeUnknown: 网络中断 / 提交结果未知
OutcomeUnknown --> Reconciling: 查询精确版本与事件身份
Reconciling --> Verifying: 确认正确对象
Reconciling --> Blocked: 冲突 / 权限拒绝 / 无法确认
Uploading --> CancelRequested: 用户取消
Uploading --> Expired: 到期任务
CancelRequested --> AbortPending: 持久取消任务
Expired --> AbortPending: 清理未完成分片
AbortPending --> Aborted: 独立 worker 幂等终止
Verifying --> Blocked: 摘要 / 版本 / 关联不匹配必须完整分页列出对象 / 分片,不在第一页就猜上传完整。ETag 可用于条件与缓存,但不等于服务端可信整文件 SHA-256。文件名、扩展名、客户端声称的哈希与已有签名 URL 都不是所有权证明。
5.3 独立 worker 与六类任务
| 持久任务 | 职责 | 为什么不放在普通页面请求里 |
|---|---|---|
expire_uploads | 找到到期会话并形成受控处理状态 | 生命周期跨进程,不能靠内存定时器唯一维护 |
scan_cancelled | 处理已取消状态、形成后续任务 | 用户请求可能中断,需要持久重试 |
commit_objects | 幂等提交对象、记录可信摘要 / 版本 / 就绪 | 云端调用与 DB 更新非原子,需要恢复未知结果 |
abort_uploads | 幂等终止未完成分片上传 | 必须避免迟到提交和清理竞态 |
reconcile_versions | 核对对象版本 / 关系,处理失败和孤儿 | 不能吞权限错误或猜成功 |
delete_versions | 零引用、恢复窗口与精确版本核对后清理 | 网站不持有直接物理删除 / 备份删除权 |
网站 UID 10001 和存储 worker UID 10002 是不同执行边界。worker 不拿初始化身份;独立清理身份不进网站容器。普通网站发布验证 worker 程序、依赖与运行身份后保持其启动时间 / 重启次数,不为了更新网页重启文件任务。
worker 代码身份绑定实际入口、递归本地 .mjs 源码、Node 版本,以及静态导入所能到达的完整运行依赖锁定闭包(含嵌套、传递、peer 和实际存在的可选依赖)。锁文件中的版本、integrity、resolved 和依赖关系仍受校验;缺失、link 或无法确认的依赖失败关闭。与 worker 无关的 Mermaid / Markdown / 前端包或 npm 安装分类字段不作为重启理由,不能再用整个全局锁文件哈希误判网站改动。真实 worker 源码、Node 或可达依赖变化仍要求单独发布,不跳过保留检查。
6. 共享引用、安全删除与下载(G3 / G4)
6.1 引用与物理清理
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart TB
UPLOAD[可信完整字节] --> HASH[服务端 SHA-256\n精确对象 VersionId]
HASH --> OBJECT[环境内共享对象版本]
USERA[玩家 A] --> REFA[玩家 A 的授权引用]
USERB[玩家 B] --> REFB[玩家 B 的授权引用]
REFA --> OBJECT
REFB --> OBJECT
REMOVE[玩家 A 请求移除] --> AUTH[会话 / 引用权限检查]
AUTH --> TX[事务移除 A 引用\n锁 / 约束 / 事件]
TX --> COUNT{仍有有效引用?}
COUNT -->|是| KEEP[保留物理对象\nB 下载不受影响]
COUNT -->|否| DELAY[创建延迟清理事件\n等待恢复保留窗口]
DELAY --> CHECK[再次核对零引用\nVersionId / 摘要 / 保留期限]
CHECK -->|一致且允许| CLEANER[独立清理身份删除精确版本]
CHECK -->|迟到引用 / 冲突 / 拒绝| BLOCK[保留 / 重试 / 明确异常]正常物理清理保留窗口为 30 天。演练可使用自己拥有的已过期测试命名空间,但不能降低正常窗口让验收更快。共享内容不跨环境共享业务身份,不用“全局哈希一样”越过不同环境 / 玩家权限。
6.2 私有下载与启动票据
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
sequenceDiagram
participant U as 网页用户
participant A as 文件 / 票据 API
participant D as MySQL 会话 / 引用 / 票据
participant L as 本地桥接器
participant T as 私有 TOS
U->>A: 文件请求或启动请求
A->>D: 校验会话 / 角色 / 持有 / 平台 / 文件组
alt 普通下载
A-->>U: 短期受限签名结果(已鉴权)
U->>T: 有效期内访问授权对象
else 本地启动
A->>D: 签发绑定完整文件快照的一次性票据
A-->>U: ticket / 受限兑换信息
U->>L: 用户主动交付票据
L->>A: redeem
A->>D: 原子核对 / 过期 / 一次性消费
A-->>L: 授权文件 / 可信摘要 / 受限地址
L->>T: 流式下载 / 校验
Note over L: LRU 副本 / 本地白名单模拟器\n真实设备流程待测
end票据不以客户端 userId、文件名或现成 URL 授权;平台 / profile 白名单和完整文件快照绑定在服务端。跨实例重复兑换只能有一次成功;后端票据功能自动验证不等于真人设备和模拟器进程已实际拉起。浏览器不执行云端传来的任意系统命令,不运行 WASM 模拟器,不调用 RomM 模拟器。
7. 身份与权限矩阵(G1–G5 / G8)
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart LR
PUSH[CI 推送身份] --> CR[本项目私有 CR 仓库]
PULL[ECS 拉取身份] --> CR
APPSTG[staging 网站应用身份] --> DBSTG[staging 业务库]
APPSTG --> TOSSTG[staging 私有文件域]
APPPROD[production 网站应用身份] --> DBPROD[production 业务库]
APPPROD --> TOSPROD[production 私有文件域]
INIT[受控初始化 / 管理身份] -. schema / 限定授权 .-> DBSTG
INIT -. schema / 限定授权 .-> DBPROD
CLEANSTG[staging 清理身份] --> TOSSTG
CLEANPROD[production 清理身份] --> TOSPROD
BACKUP[独立备份 / 恢复身份] --> RETAIN[私有备份与保留控制]
DENIAL[真实拒绝测试] -. 应用不能跨库 / 跨桶写删 .-> DBSTG
DENIAL -. 应用不能创建用户 / DDL / 删备份 .-> RETAIN| 身份 | 允许 | 必须拒绝 / 不注入 |
|---|---|---|
| 浏览器 / 本地桥接器 | 站内会话 API、短期授权文件、一次性票据 | 云长期密钥、MySQL 直连、任意系统命令、客户端 ID 越权 |
| 网站应用 | 当前环境限定业务表读写、事务、文件授权、上传 / outbox | 自动 DDL、创建用户 / 权限、跨环境写删、备份删除、直接物理清理 |
| 初始化 / 管理 | 受控 schema、初始化与精确应用授权 | 注入网站、作为运行故障 fallback、授宽权限让检查绕过 |
| 存储 worker | 租约领取、幂等提交、版本对账、条件清理 | 忽略引用 / 保留期限、跨环境清理、备份删除、初始化 schema |
| CI 推送 | 发布本项目构建镜像 / 必要资产 | 应用业务访问密钥写镜像、让不可信 PR 获取发布秘密 |
| ECS 拉取 | 拉取已确认原始 digest | 构建源代码、凭可变标签判断版本、使用网站业务身份登录仓库 |
| 备份 / 恢复控制面 | 备份、日志、隔离恢复、演练自有资源 | 普通应用代用、覆盖在线库、删除非本次演练资源 |
| 部署控制器 | 候选、健康门禁、受控流量切换、回退与退役 | 将控制权暴露给普通用户请求、任意旧容器 / 卷清理 |
必须通过真实 SQL / 云端拒绝验证,不只核对配置文本或前缀。最终 production 证据包含 12 项 SQL 拒绝和 12 项隔离 / 备份拒绝。权限缩减不能靠扩大另一身份偷用其权利。
固定已有 MySQL 私网非 TLS 例外只适用实际已接受目标,不能扩展到公网 / 新数据库。G6 新临时实例实际验证 CA、主机名与受支持 TLS;“全量备份不强制加密”也不等于可以关闭已启用的对象加密、身份校验或 HTTPS。
8. 可信构建、网络与资产(G1 / G5 / G7)
8.1 可信任务先于代码执行
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart TB
EVENT[GitHub 事件 / 提交 / PR] --> TRUST[来源 / owner / 仓库 / 固定分支检查]
TRUST -->|不可信 / fork| BLOCKED[拒绝或不调度\n无托管回退 / 不作为验收通过]
TRUST -->|可信发布输入| CHECKOUT[独立 Runner\n认证 checkout / 真实 LFS]
CHECKOUT --> PROOF{当前完整质量证明可信且匹配?}
PROOF -->|无证明| FULL[完整 Node / MySQL / API 门禁]
PROOF -->|全部身份匹配| REUSE[受控复用完整成功质量结果]
PROOF -->|证明可疑| FAIL[关闭发布]
FULL --> INPUTS[锁文件 / 工具链 / 完整模型字节]
REUSE --> INPUTS
INPUTS --> BUILD[根 Dockerfile\n网站 / API / 模型资源层]
BUILD --> PUSH[私有 CR 原始 digest + provenance]
BUILD --> ASSETS[内容哈希对象 / 不可变 manifest]所有已授权任务固定使用现有北京Runner,无托管分配或回退。它是独立持久可信构建机,不是强隔离且每任务销毁的恶意代码执行平台;Docker组权限是主机高权限。陌生分支、fork和外部actor不获得执行权限,PR仍不取得发布秘密,队列/缓存/依赖边界保持原合同。
可信功能分支在代码guard和作业条件中精确登记,仅在所有者发起/触发、同仓库来源、指定dev目标和有效PR范围同时成立时进入北京Runner;dev到main保留原受控路径。不使用 feat/* 或所有同仓库PR的通配授权,不把付款限制当扩大权限、跳过门禁或修改发布身份的理由。
8.2 网络流量方向
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart LR
RUNNER[北京 Runner] --> LOOP[本机回环代理]
LOOP --> RFC[认证 RFCHost 出口]
RFC --> GH[GitHub / Actions / LFS]
RFC --> DEPS[必要海外依赖 / 工具]
RUNNER --> CR[北京 CR\n按实际区域入口直连]
RUNNER --> TOS[北京 TOS\n资产发布 / 完整校验]
WEBSITE[网站 ECS] --> CR
WEBSITE --> DB[固定托管 DB 私网目标]
WEBSITE --> FILES[环境私有 TOS 实际入口]跨境的是 GitHub / LFS / 必要海外依赖和其控制连接,不是要求把北京 CR / TOS 推拉全部绕境外。小文件连通、LFS 大文件、依赖下载和真实镜像发布各有不同阶段证据,不能只测一条 URL 就断言“网络全部没问题”。代理不承担测试 / 构建 / 发布任务,Runner 才承担。
8.3 模型版本与镜像身份
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart LR
SOURCE[Git / LFS真实GLB] --> ASSET[同SHA资产任务 / 完整摘要]
ASSET --> TOS[不可变内容哈希对象 / TOS]
ASSET --> MANIFEST[同环境同SHA manifest / 受保护artifact]
MANIFEST --> INDEX[网站镜像 / 小型可信索引 / 无GLB]
INDEX --> META[网站API / 元数据与同版本跳转]
META --> BROWSER[浏览器]
BROWSER --> CDN[不可变CDN URL]
CDN --> TOS真实LFS字节和完整摘要仍是资产门禁,不能用指针、文件头或假清单提速。网站镜像不再携带GLB,API不读ECS模型副本或流式代理;CDN故障有界重试和明确错误。候选核对当前manifest完整库存、SHA/GLB/CORS,视觉尺寸、镜头和动画单独待测。详见CDN操作和资产主题。
9. dev、main 与同镜像晋升(G5 / G8)
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
sequenceDiagram
participant G as GitHub 当前分支 / 可信门禁
participant R as 独立 Runner
participant C as 北京私有 CR
participant S as staging 部署控制器
participant P as production 部署控制器
participant E as 公开入口 / 收据
G->>R: dev 当前提交通过门禁
R->>C: 构建并推送 dev 镜像 / 原始 digest
R->>S: digest + SHA + manifest
S->>C: 独立回读 / 拉取同 digest
S->>S: 非 root 候选 / 真实业务 / 权限 / 无状态
S->>G: 发布锁 / 最新 dev 检查
S->>E: 切换 staging / 外部健康 / 公开身份
Note over G,R: 后续最终 main 有自己的完整提交身份
G->>R: 最终 main 门禁通过
R->>C: 构建 main 的唯一候选镜像
R->>S: main 原始 digest / SHA / manifest
S->>C: 拉取同镜像至隔离 main 槽位
S->>S: 当前候选业务 / 完整模型门禁
S->>P: 已验收同一 digest(不重建)
P->>C: 拉取完全相同原始 digest
P->>P: 独立生产配置 / SQL 与对象拒绝 / 真实业务
P->>E: 切换官网 / 外部健康 / 身份收据
P->>P: 保持独立 worker 与持久依赖不变同镜像不等于同配置:staging / production 分别使用自己的业务库、私有桶、账号和 auth 配置。最终构建身份、运行时 release、provenance 和 manifest 一致,不靠修改 runtime 文件假装另一个提交。当前普通 dev staging 和 final main candidate 是不同用途的槽位。
9.1 容器隔离配置
| 项目 | 当前合同 |
|---|---|
| 网站用户 | UID 10001,非 root |
| 独立 worker | UID 10002,受限任务与清理身份 |
| rootfs | 只读;capabilities 收敛;no-new-privileges;临时目录可重建 |
| 业务磁盘 | 无旧 JSON 持久化挂载,无唯一 pending 目录 |
| 四个网站挂载 | /run/native-application-mysql.json、/run/native-application-tos.json、/run/native-auth.json、/run/rewind/release.json,只读 |
| 不注入网站 | 初始化 / 管理 DB 身份、对象清理身份、备份身份 |
| 身份核对 | 镜像内 build 身份与运行 release 交叉校验 |
| 依赖保持 | 数据库、存储 worker 与其他独立服务按 ID / 启动时间 / 重启次数核对 |
| 普通更新 | 不清库、不搬业务数据、不重启全部依赖、不手改服务器源码 |
9.2 候选失败与旧任务
候选启动、schema、配置、模型、鉴权、私有下载或拒绝测试失败时不切换正常站。发布控制器持锁并检查最新目标分支,过时工作不能覆盖新版本。切换后外部身份 / 健康失败,受控恢复上一兼容槽位;不能只看内部探针 200 就记成功。
候选清理限于实际收据确认归本次拥有、非活动、只读且无业务卷的容器;当前 / 上一版本保留供兼容回退。自动删除探针的缺席只有在确认归属 / 已停止删除证据时才接受,不把任意未知容器缺失都判成功。
9.3 无状态验收的含义
实际检查网站容器重建、完整应用实例替换与两个完整实例并发后,关键会话、社区、资源引用与文件状态保留。应用并发是单关卡内的安全检查,不是并行推进 G1–G8。当前证据不冒称购买并替换了一台全新物理 ECS;目标是事实状态不依赖网站业务目录,而不是“没有任何配置或缓存文件”。
10. 数据恢复、代码回滚与故障保护(G6)
10.1 三种机制不能混淆
| 机制 | 触发条件 | 操作对象 | 数据处理 |
|---|---|---|---|
| 候选失败保护 | 新版本上线前未通过门禁 | 当前候选 / Nginx 路由 | 保留旧站,事实数据不倒退 |
| 兼容代码回滚 | 已切换代码需要退回上一兼容版本 | 镜像 digest / 代码槽位 | 使用最新 MySQL / TOS,不恢复旧 JSON |
| 数据时间点恢复 | 演练或真实数据故障需回到恢复点 | 独立 DB 目标 + 对象版本关联 | 隔离恢复并核对,不直接覆盖在线新数据 |
10.2 备份与 PITR 拓扑
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart TB
ONLINE[在线原生应用] --> SQL[托管业务库]
ONLINE --> PRIVATE[私有 TOS 对象与版本]
SQL --> FULL[自动全量备份]
SQL --> LOGS[持续日志 / 可恢复时间点]
PRIVATE --> RETAIN[对象版本 / 30 天正常保留窗口]
FULL --> TARGET[独立隔离托管恢复目标]
LOGS --> TARGET
POINT[指定恢复点 / 事件时间] --> TARGET
TARGET --> RELATIONS[59 表 / 100 外键\n计数 / 孤儿 / 角色 / 引用核对]
RETAIN --> BYTES[精确版本 / 私有文件字节核对]
RELATIONS --> APPTEST[普通原生应用鉴权 / 关键业务]
BYTES --> APPTEST
APPTEST --> MEASURE[RPO / RTO / 脱敏收据]
OWNED[演练自有源实例回收] -. 保留备份后重建验证 .-> TARGET用户已将 G6 调整为“备份即可,不强制全量备份加密”。因此现有托管全量快照不被错误描述成全部加密。保持已有私有对象加密、身份限制和应用不可删除备份,不关闭既有安全设置。备份独立于应用 ECS;释放后行为用本次自有临时数据库演练,不释放共享正式实例来证明。
10.3 实测恢复指标
| 指标 / 项目 | 本次实际记录 | 范围说明 |
|---|---|---|
| RPO | 3305 ms,即 3.305 s | 目标 ≤ 5 分钟;按本次事件 / 恢复点测量 |
| RTO | 184703 ms,即 184.703 s | 目标 ≤ 30 分钟;按本次恢复到业务可用测量 |
| schema / 关系 | schema 6、59 表、100 外键、关联 / 孤儿检查 | 不仅确认备份文件存在 |
| 私有对象 | 恢复关联的精确版本与 131072 字节文件校验 | DB 恢复不能遗失对应 TOS 文件版本 |
| 释放后恢复 | 自有临时源实例实际回收后由保留备份恢复到独立目标 | 不覆盖在线库,不误释放共享实例 |
| 代码回滚 | 两个原生兼容版本之间受控回退再恢复 | 使用最新 MySQL / TOS,非旧 JSON / RomM 回退 |
| 临时资源收尾 | 本次拥有的 DB / 身份 / 白名单 / 原始演练材料受控清理 | 不扩大到旧备份、证书或其他项目数据 |
这些数字是本次规模实测,不承诺任意数据量、任意云平台事故都在同样时间内恢复。持续能力由工作流、SOP 和定期 / 按需演练维护;不要求每次普通前端发布都回收一个临时数据库。
10.4 代码与 schema 兼容
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
sequenceDiagram
participant D as 部署控制器
participant V2 as 当前原生版本
participant DB as 最新 MySQL / TOS 状态
participant V1 as 上一兼容原生版本
D->>V2: 记录当前 SHA / digest 与依赖身份
V2->>DB: 写入新的测试业务状态
D->>V1: 启动上一兼容镜像(同最新外部状态)
V1->>DB: 读取 / 写入最新数据
V1-->>D: 健康 / 身份 / 业务通过
D->>D: 受控切换到兼容代码
D->>V2: 恢复新版镜像
V2->>DB: 最新状态继续存在
V2-->>D: 恢复后的完整业务收据
Note over D,DB: 不清库 / 不执行破坏性 down / 不以旧备份覆盖新写入11. 热缓存发布与容量(G7)
G7 的原始要求是连续三次普通热缓存发布每次 ≤ 300 秒。实际完整样本为 393284 ms,用户明确接受该速度并要求视为 G7 通过。原性能断言失败保留,不重写为“五分钟连续三次全部通过”。
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart LR
Q[质量门禁\n35 秒] --> A[资产处理\n109 秒]
A --> B[构建与推送\n116 秒]
B --> D[拉取 / 候选 / 切换 / 健康\n103.284 秒]
D --> T[计入排队与衔接 30 秒\n总计 393.284 秒]| 阶段 | 实测耗时 |
|---|---|
| 质量门禁 | 35000 ms |
| 资产 | 109000 ms |
| 构建 / 推送 | 116000 ms |
| 部署 / 外部健康 | 103284 ms |
| 排队 / 衔接 | 30000 ms |
| 端到端 | 393284 ms,约 6 分 33 秒 |
缓存已建立不代表所有后续 run 都同样快:完整质量门禁 fallback、冷启动、新工具链、新大模型、网络和排队分别记录。不能删必要检查、真实源资产、完整摘要或扣掉不利阶段制造漂亮数字;去除运行镜像GLB由已验证CDN合同接管,不是删除模型资产。容量清理只处理项目拥有的构建资源,保护实际线上与近期可回退镜像;数据库 / 文件卷不属于构建垃圾。
证据:原始 run 37320625401、G7 收据、热发布 SOP。
12. RomM 退役、授权清理与普通发布核验
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart TB
NATIVE[原生 MySQL / TOS 全域接管] --> BUSINESS[无 RomM 配置的真实业务验收]
BUSINESS --> SCOPE[确认项目归属 / 依赖 / 原挂载]
SCOPE --> STOP[两环境停止 RomM\nrestart policy = no]
STOP --> OLDWEB[旧网站 systemd masked / inactive\nstaging 旧 Compose 网站停止]
OLDWEB --> PORT[历史 8787 入口关闭]
PORT --> RETEST[两环境各 58 项退役后业务检查]
SCOPE --> KEEP[原卷 / ROM / 模型 / 凭据 / 证书 / 备份保留]
SCOPE --> OLDDB[原 RomM 数据库容器保留\n非原生网站依赖]
RETEST --> RECEIPT[实际停用与依赖不变收据]
RECEIPT --> AUTH[后续明确授权完全清理]
AUTH --> PURGE[旧容器 / 专属卷 / 旧业务记录移除\n原始 ROM 独立保留 / 凭据私有归档]
PURGE --> PROOF[root 保护的清理控制记录]
PROOF --> VERIFY[普通发布只读核验\n原始 ROM / 归档存在\n旧运行时 / 卷 / 启动 / 端口未恢复]
VERIFY --> CURRENT[两环境当前公开业务复验\n当前依赖与卷保持不变]| 项目 | 状态与核验边界 | 保留 / 不做的事 |
|---|---|---|
| 首次软件退役 | 两环境 running=false、restartPolicy=no | 当次保留原挂载,停用与删除是不同操作 |
| 后续明确授权完全清理 | 旧 RomM、专属数据库 / 卷和旧业务记录移除 | 原始 ROM 移到独立目录;凭据、证书与当前原生依赖不作为清理目标 |
| 普通发布核验 | 校验 root 保护的清理记录与当前负向状态 | 不要求已经移除的旧容器继续存在,不再次执行清理 |
| 旧网站自动启动 | 已移除或 masked / inactive;旧 Compose 不运行 | 不用旧服务作为兼容 fallback |
| 旧端口 | 8787 关闭 | 不恢复到旧 JSON 事实存储 |
| 退役后业务 | 两环境各 58 项检查 | 不只检查进程停止 / HTTP 200 |
| 独立依赖 | ID / 启动时间 / 重启次数保持 | 不误停共享数据库 / worker |
| 原数据库与专属卷 | 删除只属于后续明确授权的清理范围 | 普通发布不操作历史数据库与卷,当前业务事实仍在 MySQL / TOS |
| 可复用文件 / 配置 | 当前模型、原始 ROM、证书、凭据与备份按边界保留 | 清理核验检查保留目录,不读取凭据内容或恢复旧事实存储 |
去掉 RomM 是必要条件,但不是充分条件。只有独立目录 / 文件管理、可靠 MySQL / TOS、权限、自动发布和恢复都接管,并且停用后业务正常,才构成完成;不能只搜索替换名字或提交“待退役计划”。旧数据保留物不参与在线双写、授权或 fallback。
只读核验由 deploy/native-legacy-purge-proof.mjs 验证历史清理凭据及当前状态;缺少可信记录、陌生旧组件、保留目录丢失、旧端口开放或独立依赖变化均阻断。历史记录的发布身份与本次发布身份分别记录,不能把过去删除的卷说成本次发布再次删除。
13. G1–G8 验收与实现地图
| 关卡 | 主要实现 / 合同 | 指定证据 | 完成 / 未覆盖 |
|---|---|---|---|
| G1 后端边界 | Goal 实施计划、部署合同 | G1 收据、run 37226195802 | 边界 / 重置 / 保留明确,可信基础复用;不是历史无损导入 |
| G2 关系模型 | lib/persistence/native-schema.mjs、实体仓储 | G2 收据、run 37226582781 | 真实 MySQL、事务 / 约束 / 权限拒绝;不把 schema 存在当全域接线 |
| G3 私有文件 | 文件 / 上传 / 引用 / scheduler 仓储;独立 object worker | G3 收据、run 37228764289 | 16 阶段 / 97 检查 / 23 拒绝;字节与权限真实,不用假 TOS |
| G4 业务接线 | server.mjs、原生 API / runtime、账号与社区仓储 | G4 收据、run 37229617663 | 无 RomM / JSON fallback;必要网页 API 联调,不是视觉全量验收 |
| G5 staging | deploy/native-staging.mjs、deploy/native-stateless-acceptance.mjs、native-g5 workflow | G5 收据、run 37246477925 | 实际自动切换与完整实例并发;不冒称换物理 ECS |
| G6 恢复回滚 | 恢复 SOP、native-g6 workflow | G6 收据、run 37300875057 | RPO / RTO 实测;全量加密非强制;普通 CI 不每次回收 DB |
| G7 热发布 | 质量证明、容量控制、latency 工具、热发布 SOP | G7 收据、run 37320625401 | 用户接受 393.284 秒;原五分钟 / 三次未达标,仅一完整样本 |
| G8 官网退役 | deploy/native-g8.mjs、deploy/native-romm-retire.mjs、官网 SOP | 最终 run 37375166062、PR #101 最终证据 | final main 同 digest、真实新后端、两环境实际停用;原件与共享依赖保留 |
历史 G8 实施收据可能保存第一轮 main 的已验收快照以及当时“文档待收尾”字段,它是有日期的历史证据。最终完成判断使用最终 run / PR 交付记录,不把早期字段当作当前仍未完成,也不覆盖旧证据使历史失真。
13.1 最终交付身份
| 项目 | 完成时身份 |
|---|---|
| main | 87839e2361e496280788ae87dfade20c57c80a6f |
| dev | 197a0cf441a8bbc0f73cfdad8457b9cf29bcbe3e |
| 原始镜像 digest | sha256:e41de36502bf62ec3f0d555f2a8a4358086f522792f8c58dd68307e85497f4ec |
| main manifest | roms/manifests/digibitplay/production/87839e2361e496280788ae87dfade20c57c80a6f.json |
| 最终候选 | 58 项业务、36 完整模型,与官网同 SHA / digest |
| production | 58 项业务、12 项 SQL 拒绝、12 项隔离检查;独立 worker 保留 |
| 两环境退役后 | 各 58 项业务、旧入口关闭、RomM restart=no、原卷保留 |
| 最终 Actions | 37375166062 |
| dev 自动部署 | 37373352004 |
本轮架构图更新没有新的上线身份,也不把此表 SHA 写成之后每个提交必须永远相等的值。
14. 当前状态、目标态与人工待测
已实现且已自动 / 云端验收
- 网站 / API、独立资源领域、MySQL 实体业务事实、私有 TOS、上传 / 引用 / outbox / 租约 / 延迟清理。
- 可信独立 Runner、按需代理、真实 LFS、根 Dockerfile、私有 CR、不可变身份、候选门禁和两环境自动容器发布。
- 应用 / 初始化 / 清理 / 备份身份分离、环境跨写拒绝、真实 Admin 权限与普通用户拒绝。
- 容器重建、完整应用实例替换、两个实例并发、备份 / PITR、私有文件关联与原生兼容版本回滚。
- 最终 main 同镜像官网交付、RomM / 旧网站实际退役、依赖不变、原资产保留。
明确待测 / 延期
- 真人 Google 登录、刷新 / 切页 / 退出 / 再登录和个人页面展示。
- 多模态视觉、响应式、键盘、动画连贯、模型尺寸 / 朝向 / 遮挡 / 镜头、贴纸和前端视觉统一。
- 实际电脑上的桥接器、系统协议、断点下载、LRU、已安装模拟器进程与错误提示端到端体验。
- Android 与未纳入的其他登录供应商。
人工待测入口:tests/manual-acceptance-checklist.md。本次架构图也没有做浏览器复核,不能因完成文档把上述项目改为通过。
不是当前已部署承诺
- 两个物理独立 MySQL 实例、多可用区高可用、无限水平扩容、跨地域数据库容灾。
- 每个发布都 ≤ 五分钟,连续三次原性能断言通过,或所有事故都达到同样 RPO / RTO。
- 模型全部从镜像移除、所有云端请求全部内网、可信 Runner 能安全执行任意恶意 PR。
- 旧 RomM 全部数据 / 数据库 / 卷 / 收费资源已经删除或释放。
- 必需 Redis 原生业务服务、浏览器内 ROM 运行、RomM 模拟器或旧 JSON / API 兼容 fallback。
15. 文档、UI 与后续维护规则
交互图的数据入口为 app/components/architecture-model.ts;渲染入口为 app/components/architecture-diagram.tsx 和 release-architecture.tsx。五个视图沿用统一节点,避免“发布图说 MySQL、运行图仍说 JSON”的内容分叉。节点详情展示输入 / 输出 / 边界 / 实现路径和有向关系,图形之外提供完整文字关系及窄屏列表。
网站主导航的“项目架构”指向 /architecture,页面在构建时直接导入本 Markdown。正文与 GFM 表格由 React Markdown 展示,Mermaid 图按可视区域加载、严格模式渲染,提供缩放、源码查看和失败重试;不从运行中的 ECS 文件系统读取另一份文档。目录按源文档行号生成章内锚点,相对资料链接指向仓库。
仓库原文与相对资料链接优先绑定公开 /api/release 中经过完整 SHA 校验的运行提交;公开身份暂不可用时回退到 dev 文档入口。这样 staging 尚未合入 main 时不会因默认指向 main 而找不到新图册,也不把移动分支内容冒充已经运行的文档版本。
Docker 构建上下文仅放行页面所需的 arch/native-backend.md,其他 arch 文件、docs、sop 和秘密目录继续排除。构建时 raw import 不等于运行时开放服务器文件读取;依赖的文档必须和应用一起进入可信构建,不通过生产机器临时复制补齐。
维护时先确认当前实现与真实收据,再更新日期、状态和证据入口。任何前端或后端架构变更必须在同一变更中同步更新 arch,要求见根 AGENTS.md。新增组件注明是否在线、只验收工具、人工待测或退役;不能为了箭头好看连接一个不存在的业务依赖。具体操作步骤放 SOP,不在多个架构文件重复完整执行脚本。历史计划保留历史标识,当前事实来源保持清晰。
本图不包含密钥值,不要求读回历史凭据。更新图不授权购买、清库、权限扩大、停共享服务或释放资源;既有 Goal 的完成证据也不自动成为后续新操作的无限授权。
公开模型脱离网站镜像:staging 反馈修复(2026-10-06)
本节是本次代码实现及待发布架构,尚未执行本轮 CI、候选或流量切换。此前运行基线中的 ECS 本地模型分发不代表本节已上线;以之后成功的 run、完整 SHA、digest 和公开模型清单为准。
进入可视区域后加载架构图。
查看 Mermaid 源码与文字关系
flowchart TB
Git[Git commit / LFS 完整模型] --> Asset[资产任务:完整字节 / SHA-256 / 增量上传]
Asset --> TOS[公开模型 TOS 内容哈希对象]
Asset --> Manifest[不可变 environment / commit manifest]
Manifest --> Small[同次 Actions artifact:只有小型清单]
Small --> Build[根 Dockerfile:代码与清单身份核对]
Build --> CR[私有 CR 不可变网站镜像 digest]
CR --> Web[非 root 网站容器:代码与 public-models.json]
Web --> Index[清单 API:与 sealed build / release 同 SHA 同 key]
Index --> Browser[浏览器:解析模型身份与状态]
Browser --> CDN[不可变 CDN URL:下载公开 GLB]
CDN -->|缓存未命中回源| TOS
CDN --> Bytes[长度 / GLB 结构 / 完整 SHA 校验]
Bytes --> Scene[独立 THREE 场景:解析 / 镜头 / 交互]
Candidate[发布候选门禁] --> Index
Candidate --> CDN
Candidate --> Gate[完整模型字节 / 摘要 / 格式 / 两站 CORS]
Gate -->|成功才切换| Live[staging / production 公开流量]
Gate -->|失败| Old[保留原运行版本]发布面
- 资产仍由 Git LFS 管版本,构建机校验真实文件后上传 TOS;内容未变则复用内容哈希对象。
- TOS commit manifest 不要求公开读取。资产 job 将已验证清单上传到本次 Actions artifact,名称绑定环境、完整 SHA 和 run attempt。
- 镜像 job 核对仓库、环境、完整 SHA、实际 manifest key、公开路径、库存及 assembly 摘要。镜像只保留小型公开模型索引,
dist/client/digibitplay/models不进入最终运行镜像。 - sealed
build.json保留同版本 manifest 身份;运行 release 和索引不一致时拒绝服务,不切到 latest 或猜另一版本。 - 后续普通前端发布仍跑质量与候选门禁,但网站 ECS 不再拉取模型镜像层。新增资产的上传成本属于资产发布,不隐瞒这部分耗时。
请求面与故障边界
/api/digibitplay-assets是同源小型公开索引,使用no-store;不是模型下载中转。- 浏览器从批准的 CDN origin 和不可变内容哈希路径下载模型;无 Cookie / Bearer,不接受任意外部 URL。
- 旧
/api/digibitplay-model路径仅做清单内 URL 查找和 CDN 重定向;生产不读本地 GLB,也不作为 CDN 故障的 ECS fallback。 - CDN 缓存未命中由 CDN 向 TOS 回源。真正的网络故障、403、404、损坏文件或解析超时由前端明确呈现,并提供有限重试。
- 下载、校验、解析、缓存命中分阶段反馈;旧加载会取消,晚到场景会释放。字节缓存有容量上限,不缓存共享可变 THREE 场景。
- 镜头按实际 assembly 可见边界计算,不改变资产内部坐标、比例、机械枢轴或动画路径。CDN 不能代替镜头和解析问题的修复。
- 候选门禁不再用 ECS 本地模型作对照,而以镜像中已绑定的清单核对 CDN 的完整响应字节及两站 CORS。失败不得省略失败模型后继续切流量。
- 本地开发可使用仓库源文件,不代表生产镜像保留模型。ROM、存档、用户上传继续走私有 TOS 与业务授权,绝不写进公开模型索引。
同轮认证与玩家档案修复
Google 公钥的请求目标固定为官方 HTTPS JWKS。新增回环 CONNECT 代理配置入口只承载公开密钥 GET,TLS 验证及 JWT 签名、nonce、issuer、audience、有效期检查不变;不将用户 token 发送到代理处理接口。运行配置接入与真实 Google 登录仍需后续部署验收。
玩家主页统计和游戏记录采用同一公开游戏可见性:MySQL rw_play_status 关联公开 rw_games,不再返回硬编码空数组。游戏记录与帖子分页使用不同游标,公开 DTO 不含私有 ROM 下载权限或签名地址。没有记录与读取失败分别展示,不能通过删 QA 数据使统计和空列表看似一致。
实施与排障:公开模型 CDN SOP。自动与人工验收状态以实际后续证据为准。
媒介陈列选择状态的回归修复
载体货架切换 SNES CART / N64 CART 等条目时,使用共享 reducer 的 shelf.change -> games,保留所选游戏和已插入媒介姿态;不能复用主机货架的 platform.focus -> platform,否则会隐藏卡带并丢失游戏条目层。主机货架仍按原流程聚焦闭合主机,所有切换继续递增 nonce、拒绝旧动画回调。纯选择事件由 digibitplay-shelf-selection.mjs 提供,自动回归覆盖两条路径。此段实现随正常 CI 和 staging 发布验收,不据文字宣称已上线。
文档维护边界
当前主题、模块与操作的职责由登记表定位,文档治理约束新增和重复正文。轻量CI检查结构,不替代图册事实、实际API/存储/恢复或画面验证。
本图册仍是 /architecture 的构建时唯一正文。主题、模块与SOP的唯一位置见文档索引,历史阶段和授权已独立归档。本文更新不代表重新运行既有CI、恢复或真人验收,当前公开身份按当次release和Actions核对。