* chore: unify product name display to OpenDesign repo-wide Rename the user-facing product name from "Open Design" to "OpenDesign" across documentation, web/desktop UI strings, i18n locales, prompts, plugin/skill/design-system content, changelogs, and specs, matching the landing-page rename already in flight. Deliberately excluded so installed-app identity stays untouched: - packages/release PRODUCT_NAME and everything derived from it (app bundle names, installer/registry identity, updater feeds) - tools/pack, tools/release, apps/packaged, landing page (PR #6983) - mocks/ recorded traces and LICENSE - test fixtures and comments that encode real on-disk install paths (Open Design.app, Program Files\Open Design, AppData paths) Validated with pnpm guard, pnpm typecheck, and targeted web/desktop/host test runs over the renamed strings. * fix(web): keep two-letter author monogram for CamelCase brand names authorInitials split words on whitespace only, so the renamed single-token author name "OpenDesign" produced a one-letter monogram. Treat lower-to-upper CamelCase boundaries as word breaks so the avatar fallback stays "OD". * fix(release): restore spaced Windows source artifact names in win.ps1 tools/pack still derives builder outputs from the unchanged PRODUCT_NAME ("Open Design"), so the asset script must look for the spaced filenames. Matches the mac/mac-intel/linux asset scripts, which were already kept on the original names. --------- Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com>
22 KiB
Workspace Team 上线 Runbook
本手册用于把 Workspace Team 从 Vela feature-test 推进到 test,最终再发布到 production。它同时覆盖 Vela DB/API/Link/Web/CLI 和 OpenDesign 桌面包;任何一层没有明确版本和验收证据,都不能把整体标记为已上线。
安全边界:仓库内不得记录 Stripe 密钥、Webhook secret、数据库连接串、内部域名或测试账号密码。环境 URL、Secret 名称和值以 GitHub Environment、GitOps 仓库和内部上线记录为准。本手册中的
<...>必须在受限上线记录中填写,不能直接提交真实 secret。
1. 发布角色与唯一证据单
发布前指定以下角色;一人可兼任,但每项必须有明确名字和替补。
| 角色 | 职责 |
|---|---|
| Release commander | 控制顺序、宣布 go/no-go、记录时间线、批准进入下一环境 |
| DB operator | Atlas 状态、备份/PITR 可用性、migration 与 catalog seed |
| Payments owner | Stripe 产品、Price、Coupon、Webhook 和 sandbox/production 隔离 |
| Vela owner | API、Link、Web、CLI 构建与部署 |
| OpenDesign owner | CLI pin、beta/prerelease/stable 包和 updater 元数据 |
| QA pair | Owner + Admin/Member 双账号真实浏览器验收 |
| SRE on-call | Grafana/Loki/Tempo、告警、回滚和事故响应 |
在受限上线记录中先建立一张证据表,至少包含:
environment | component | source SHA | image digest/package version
workflow run URL | deploy start/end | operator | validation evidence
rollback target | result | open issue/waiver
版本必须是不可变标识:Git SHA、ECR digest、npm 精确版本、OpenDesign release version。分支名或 latest 不能单独作为证据。
2. 当前硬门禁
2.1 Vela 分支必须先同步最新 main
Vela 的 DB Migration Gate 会阻止包含 DB 变更但没有基于最新 main 的 PR。不要继续使用旧上线记录中“重命名 30 条 migration”之类的静态数字;以远端当前拓扑和 Atlas 校验为准。
git fetch origin main feat/workspace-team
git rev-list --left-right --count origin/main...origin/feat/workspace-team
git diff --name-status origin/main...origin/feat/workspace-team -- db/schema db/migrations
左侧计数不为 0 时,先在独立 worktree 将 origin/main 合入 feat/workspace-team,解决冲突并重新运行完整 CI。禁止在有用户 WIP 的主 checkout 中操作。
2.2 OpenDesign production 目前是显式关闭状态
当前 OpenDesign 代码只允许 feature-test 和 test profile 启用 Workspace Team transport;prod 即使拿到 Vela Web URL 也会保持关闭。证据在:
apps/packaged/src/sidecars.ts的WORKSPACE_TEAM_AMR_PROFILES.github/workflows/release-beta.yml的amr_profile和OD_VELA_WEB_URLapps/packaged/tests/sidecars.test.ts的 prod fail-closed 用例
因此,以下事项完成前,production 为 NO-GO:
- 产品/维护者明确批准在 prod 开启 Workspace Team。
- 代码把 prod 纳入受控 gate,并为“缺 URL 关闭、合法 URL 开启、错误 URL 失败”补测试。
- stable/prerelease 工作流可以从 Secret 注入 prod Vela Web origin,且不会把内部地址写进源码或日志。
- production Vela API/Web 已先上线并通过兼容验收。
不要用手工环境变量绕过这个 gate,也不要把 feature-test/test 包冒充 stable 包。
3. 发布前冻结与检查
3.1 冻结版本
记录并核对以下 SHA:
gh api repos/powerformer/vela/git/ref/heads/main --jq .object.sha
gh api repos/powerformer/vela/git/ref/heads/feat/workspace-team --jq .object.sha
gh api repos/nexu-io/open-design/git/ref/heads/main --jq .object.sha
gh api repos/nexu-io/open-design/git/ref/heads/feat/workspace-team --jq .object.sha
从此刻开始只允许 release blocker 修复。任何新 commit 都使该环境之前的 CI、目验和签字失效,必须对新 SHA 重跑。
3.2 必须为绿的检查
Vela:
gh run list -R powerformer/vela --branch feat/workspace-team \
--workflow ci.yml --limit 10
gh run list -R powerformer/vela --branch feat/workspace-team \
--workflow db-migration-gate.yml --limit 10
gh run list -R powerformer/vela --branch feat/workspace-team \
--workflow smoke-lite.yml --limit 10
gh run list -R powerformer/vela --branch feat/workspace-team \
--workflow qa-browser-ci.yml --limit 10
OpenDesign:
gh run list -R nexu-io/open-design --branch feat/workspace-team \
--workflow ci.yml --limit 10
同时要求:
- 所有 blocker review comment 已核实并解决;不适用的 comment 有书面原因。
- 合入提交没有
Co-authored-by。 - Vela API 对旧 CLI 请求仍向后兼容;显式 Workspace 请求不得静默回退 Personal。
- 未登录 OpenDesign 仍能使用本地 Coding Agent 和 BYOK,不能因 AMR 不可用被余额弹窗阻断。
powerformer/apps中各环境的变量/ExternalSecret 映射已合并并同步;只确认 Secret 存在,不在日志中打印值。
Workspace billing flags 必须按 API 的启动校验保持依赖顺序:
WORKSPACE_BILLING_DEFAULT_SCOPE
-> requires WORKSPACE_BILLING_LINK_SCOPE_V2=true
-> requires WORKSPACE_BILLING_SCOPED_SETTLEMENT=true
WORKSPACE_TEAM_ENABLED=false 是服务端总开关。每个环境都要在证据表记录这四个 flag 的期望布尔值,并从 rollout 后 Pod 的受限配置视图核对;不要打印其他 env 或 Secret。
3.3 Stripe 和账单目录
每个环境独立核对:
- Stripe account/mode 正确,sandbox 与 production 的 Product、Price、Coupon、Webhook 不混用。
- Team Basic/Plus/Pro/Max 的月付和年付共 8 个 active catalog 条目。
plan_id、账期、币种、最低席位、单席价格、月额度、优惠金额与产品签字一致。- Webhook endpoint 已订阅上线代码依赖的事件;签名 secret 已通过 ExternalSecret 注入。
- 重放同一个 Stripe event 不会重复发额度、重复开票或重复执行
invoice.paid副作用。 - Personal Plus -> Team、Free -> Team、Team 升降级、手动充值和发票路径在 sandbox 真实支付通过。
production 目录只能从 production Stripe 对象生成。禁止复制内部 Wiki 中的 test Price/Coupon ID。
3.4 DB 门禁
- 确认生产数据库 PITR/备份在恢复窗口内,并记录恢复责任人。
- migration 必须 expand-first,旧 API 和新 API 都能在过渡 schema 上运行。
- 先
check,后apply;legacy credit repair 默认不执行。 repair是单独的、显式批准的数据变更,必须先导出受影响行数和只读校验结果。- migration 失败后不允许直接回滚 SQL;优先修复前滚。只有 DB operator 确认存在经过演练的逆迁移时才能执行。
4. 统一发布顺序
每个环境都使用同一顺序;上一步完成并留证后才进入下一步:
- Stripe/Secret/GitOps 配置就绪,但功能仍关闭。
- DB migration。
- Team billing catalog seed 与只读校验。
- Vela API。
- Vela Link(若请求、计费或 runtime contract 有变化)。
- Vela Web。
- Vela CLI 精确版本发布。
- OpenDesign pin 新 CLI,构建对应环境的包。
- 双账号真实浏览器与 packaged app 验收。
- 观察窗口通过后才进入下一环境。
若一次 push 同时触发 feature-test 的 DB/API/Web/Link workflow,它们可能并行。只有 expand-first schema 才允许这样做;否则把变更拆成“兼容 migration -> service -> cleanup migration”三个发布批次。
5. Feature-test
powerformer/vela 的 deploy/environments/feature-test/bound-branch.json 必须仍绑定 feat/workspace-team。Feature-test workflow 从 main 读取该绑定,再构建绑定分支的精确 SHA,并在 rollout 前校验 SHA、镜像 tag 和 digest。
相关路径有变更时 push 会自动触发;没有触发时从 main 手动 dispatch:
gh workflow run deploy-db-and-model-routing-catalog-feature-test.yml \
-R powerformer/vela --ref main -f legacy_workspace_credit_action=check
gh workflow run deploy-api-eks-feature-test.yml \
-R powerformer/vela --ref main
gh workflow run deploy-link-eks-feature-test.yml \
-R powerformer/vela --ref main
gh workflow run deploy-web-eks-feature-test.yml \
-R powerformer/vela --ref main
必须等待每个服务的 Sync and Verify Feature Test Rollout 成功;该 job 会验证所有 ready Pod 都运行预期 digest。只看到 build 绿不算部署成功。
发布 Vela CLI 的 test channel:
gh workflow run vela-cli-package.yml \
-R powerformer/vela --ref feat/workspace-team
记录 workflow 产出的精确 @powerformer/vela-cli@<version>-test.<n>,确认 macOS arm64/x64、Windows x64 和 Linux 包发布与 smoke 均成功。随后在 OpenDesign 更新 tools/pack/package.json 的精确 pin 和 lockfile;不能依赖 npm dist-tag 漂移。
构建 feature-test beta:
gh workflow run release-beta.yml -R nexu-io/open-design \
--ref feat/workspace-team \
-f ref=feat/workspace-team \
-f amr_profile=feature-test \
-f enable_mac_arm64=true \
-f enable_win_x64=true \
-f publish=true \
-f mac_arm64_sign_mode=notarize \
-f mac_arm64_smoke_mode=full \
-f win_x64_target=all \
-f win_x64_smoke_mode=full
release-beta 必须报告 release_state=complete。核对 beta metadata 的 github.commit 等于冻结的 Open Design SHA,平台 artifact 均有 checksum;应用身份必须是 Open Design Beta。
6. Test
Feature-test 观察通过后,将 Vela 变更通过 PR squash 合入 main。main push 对路径匹配的 DB/API/Link/Web 自动部署到 test;不要因某个 workflow 未触发而假设旧服务已兼容。
必要时按顺序手动 dispatch:
gh workflow run deploy-db-and-model-routing-catalog-test.yml \
-R powerformer/vela --ref main
gh workflow run deploy-api-eks-test.yml -R powerformer/vela --ref main
gh workflow run deploy-link-eks-test.yml -R powerformer/vela --ref main
gh workflow run deploy-web-eks-test.yml -R powerformer/vela --ref main
Test workflow 会写 GitOps values,但不像 feature-test workflow 一样内建 exact-digest rollout job。Release commander 必须从 workflow 记录 GitOps commit/image tag,并由 SRE 在 GitOps/集群只读视图确认 rollout healthy 后再验收。
用 amr_profile=test 重跑 OpenDesign beta;其余输入与 feature-test 相同。Feature-test 包不能作为 test 证据,因为 profile 和后端不同。
7. Production
只有第 2.2 节的 prod gate 已通过代码、review、CI 和 prerelease 验证后才能继续。
7.1 Vela production
所有 production workflow 只允许从 main 手动 dispatch,并受 GitHub prod Environment 审批保护:
gh workflow run deploy-db-migrations-prod.yml \
-R powerformer/vela --ref main
gh workflow run deploy-model-routing-catalog-prod.yml \
-R powerformer/vela --ref main
gh workflow run deploy-api-eks-prod.yml \
-R powerformer/vela --ref main
gh workflow run deploy-link-eks-prod.yml \
-R powerformer/vela --ref main
gh workflow run deploy-web-eks-prod.yml \
-R powerformer/vela --ref main
若 Workspace 变更触及 Admin,再单独运行 deploy-admin-eks-prod.yml。每次 dispatch 后先完成健康检查和观察窗口,不能把五个 workflow 一次性全点下去。
后端兼容确认后再发布 production Vela CLI:
gh workflow run vela-cli-release.yml -R powerformer/vela \
--ref main -f target_ref=main -f bump=patch
记录 GitHub release tag、npm 精确版本、各平台 checksum 和 Windows smoke。然后让 OpenDesign release branch pin 该 production CLI 精确版本。
7.2 OpenDesign prerelease 与 stable
Workspace Team 必须先存在于 main,再走仓库既有 release branch -> prerelease -> stable promotion,不从 beta 直接升 stable:
gh workflow run cut-release.yml -R nexu-io/open-design \
--ref main -f version=<x.y.z>
gh workflow run release-prerelease.yml -R nexu-io/open-design \
--ref release/v<x.y.z> \
-f ref=release/v<x.y.z> \
-f release_version=<x.y.z> \
-f win_x64_smoke_mode=full
gh workflow run release-stable.yml -R nexu-io/open-design \
--ref release/v<x.y.z> \
-f ref=release/v<x.y.z> \
-f prerelease_version=<x.y.z-prerelease.n> \
-f dry_run=prepublish \
-f win_x64_smoke_mode=full
prepublish 全绿、QA 签字和 production Vela 观察窗口通过后,使用同一 prerelease 和 release branch 把 dry_run 改为 publish。Stable 仍由 validated prerelease 推进,不能从 preview/beta metadata 拼装。
8. 兼容矩阵
每格必须实际运行,不得只靠单元测试推断。
| 客户端/身份 | Personal | Team Owner | Team Admin | Team Member | 未登录 |
|---|---|---|---|---|---|
| 上一个 stable OD + 上一个 prod CLI | Personal 账本 | 旧请求保持兼容 | 旧请求保持兼容 | 旧请求保持兼容 | Local agent/BYOK |
| 新 OD + 新 CLI | Personal scope | Team scope、管理和计费 | Team scope、权限边界 | Team scope、只读项目+评论 | Local agent/BYOK |
| 新 OD + 后端 N-1(回滚态) | 可用或明确失败 | 不能静默扣 Personal | 不能越权 | 不能越权 | 不受 AMR 影响 |
| 旧 OD/CLI + 新后端 | 旧无 scope 请求按既有兼容规则 | 默认 Workspace 行为保真 | 同左 | 同左 | 不受影响 |
重点断言:
- 显式
workspaceId请求只能使用该 Workspace;不可解析时 fail closed,不能退到 Personal。 - 真正无 Workspace scope 的旧请求保留既有兼容行为。
- Workspace 切换不能停止原项目 run,也不能把运行中计费切到新 Workspace。
- Team workspace 有余额时,模板运行不能弹 Personal
$0的升级弹窗。 - Owner/Admin/Member 权限与当前产品定义一致;Member 可分享自己的资源,但不能修改别人的共享项目产物。
9. 双账号真实验收
使用全新 Chrome profile 和两个真实账号/两个隔离客户端实例。不得用同一 daemon data root、同一 Vela profile 或同一浏览器 storage 冒充双账号。
- Owner 创建 Team、邀请 Admin 和 Member;两端角色与成员列表一致。
- Owner 创建/从模板运行/Remix/复制项目,验证项目绑定当前 Workspace。
- 个人项目分享进 Team 后只出现在 Team 列表;移出后只出现在 Personal。
- 重命名后返回“最近/全部项目”,两端无需刷新看到同名;更新时间不能因单纯 pull 被改成“刚刚”。
- 项目 owner 修改/新增/删除产物,另一账号无刷新看到;非项目 owner 的写入和 run/chat 返回明确 403。
- Owner、Admin、Member 分别发表评论;其他账号无刷新看到计数、锚点和正文。再验证编辑、删除和“发送到聊天”。评论可见性按 Team project,而不是本地 conversation ID。
- 两个账号同时打开项目,在线成员名单均显示对方;切换设计文件/预览或 Workspace 不应靠组件重挂载才恢复。
- 分享/移出 Design System、plugin、project,验证 Personal/Team tab 不重复且撤销及时同步。
- 运行中的 Team 项目切换到另一个 Workspace;原 run 继续且 usage/trace/账单仍归原 Workspace。
- 未登录状态真实启动 Codex/OpenCode/Claude 中至少一个本地 agent,并验证 BYOK;不得出现 AMR 余额弹窗。
- 真实 sandbox 支付覆盖 Free -> Team、Personal Plus -> Team、Team 升级、席位变化、手动充值、发票;Webhook 后 UI 和账本最终一致。
每项保留:时间、账号角色、Workspace/project/run ID、请求 trace ID、截图或录像、关键 HTTP 状态和预期/实际。截图不得包含 cookie、session token 或支付凭据。
10. 性能与 CDN
- 记录 project 首开、文件树、首个预览、聊天历史、评论/在线状态同步和 Workspace 切换的基线与发布后数据。
- 同一 project 的列表/预览切换不得反复出现全屏 loading;缓存命中和 stale-while-revalidate 行为必须保留。
- 新静态资产必须使用内容 hash。发布后从 HTML 提取实际 JS/CSS URL,逐个确认
200和正确content-type。 - Cloudflare/CDN 不得长时间缓存静态资产
404。若 rollout 新旧 Pod 混跑,先等 exact-digest rollout 完成,再验收新 HTML 与其引用的资产。 - 发现缓存污染时只 purge 精确受影响资产/版本前缀;不要把全站 purge 当常规发布步骤。purge 前后都保留响应 header 证据。
性能退化、无限 loading、资产 404/错误 MIME 或频繁重复请求均为 STOP,不以“刷新后可用”放行。
11. 观察、告警与停止条件
每个环境至少观察一个完整的支付 Webhook + Team run 周期。Production 初始观察窗口不得少于 60 分钟。
观察面:
- Grafana:API/Link 5xx、延迟、模型成功率、TTFT、CPU/内存、Pod restart/unavailable。
- Loki:Workspace scope、billing、Stripe webhook、catalog、collab/presence/comment、TLS 和 timeout 错误。
- Tempo:按
open_design.run_id核对 CLI -> API -> Link trace 和 Workspace 计费归属。 - Postgres/账本只读查询:重复 grant、负余额、错 Workspace、Webhook backlog、outbox/retry backlog。
- GitHub Actions/GitOps:built SHA、image digest、GitOps commit 与 ready Pod 完全一致。
任一条件触发立即停止推进:
- 显式 Team scope 静默回退 Personal,或扣错 Workspace。
- 重复扣款/额度、漏发订阅额度、Webhook 副作用被跳过。
- 权限绕过、跨 Workspace 数据泄漏、评论/产物错误同步。
- migration/seed 校验不一致或需要未审批的数据 repair。
- API/Link 5xx、错误率、延迟、Pod 重启超出发布前基线/既定阈值。
- 客户端未登录本地 agent/BYOK 回归。
- 新版本无法通过 updater 安装、冷启动或回到上一个健康版本。
12. 快速回滚
服务
- Release commander 宣布 freeze,停止后续 workflow 和新 stable 发布。
- 从证据表取上一个健康 image tag/digest;不要凭“上一次 run”猜。
- 通过
powerformer/apps/Orbit GitOps 把受影响服务的 values 恢复到该不可变镜像并等待 reconcile。 - 确认 Deployment、所有 ready Pod 和 digest 一致,再做 health/smoke。
- 若 API 与 Link contract 成套变化,按已验证兼容组合一起回滚;不要留下不兼容的混合版本。
禁止用临时 kubectl set image 作为最终回滚:它会与 GitOps 漂移并被覆盖。
DB
Atlas migration 默认不可逆。服务回滚必须能在新 schema 上运行;若不能,发布设计本身不满足 expand-first,禁止上线。数据修复只能走经 review、dry-run、影响行数确认和备份验证的独立操作。
Vela Web/CDN
回滚到上一个健康 Web image 后,先验证 HTML 引用旧 hash 资产仍为 200。只对确认污染的 asset URL 做精确 purge。
CLI/OpenDesign
- 停止发布/撤回下载通知;不要覆盖已发布的 npm 版本或 release artifact。
- Beta/prerelease 通过发布一个更高版本修复;Stable 使用仓库 release 流程发布 patch。
- updater metadata 只能指向经过 smoke 的完整 artifact 集;不能手改成半发布版本。
- 若新客户端会对旧后端产生危险写入,先在服务端关闭功能 gate,再回滚客户端。
回滚完成仍需跑第 8、9 节的关键兼容与双账号链路,并持续观察;“Pod 已回滚”不等于事故结束。
13. Go/No-Go 签字
只有以下全部为真才能宣布环境完成:
- 证据表中每个组件都有 SHA/digest/version、workflow URL 和 operator。
- CI、migration gate、rollout/smoke 全绿且对应当前 SHA。
- Stripe/DB/catalog/Secret 配置由双人复核。
- Owner/Admin/Member + 未登录兼容矩阵完成。
- sandbox 支付、Webhook、额度、账单、发票完成。
- project 首开/缓存/评论/在线状态无性能回退。
- 观察窗口内没有新增 firing alert 或未解释的错误尖峰。
- 回滚目标和执行人已确认,且没有依赖不可逆 DB downgrade。
- QA、Vela owner、OpenDesign owner、SRE、Release commander 签字。
任何 waiver 必须写明风险、有效期、owner 和回收条件;口头“先上线再看”不是有效签字。
14. 实现来源
操作命令和边界来自以下实际实现;修改 workflow 后应同步更新本手册:
- OpenDesign
.github/workflows/ci.yml - OpenDesign
.github/workflows/release-beta.yml - OpenDesign
.github/workflows/cut-release.yml - OpenDesign
.github/workflows/release-prerelease.yml - OpenDesign
.github/workflows/release-stable.yml - OpenDesign
tools/pack/AGENTS.md - Vela
.github/workflows/deploy-*-feature-test.yml - Vela
.github/workflows/deploy-*-test.yml - Vela
.github/workflows/deploy-*-prod.yml - Vela
.github/workflows/vela-cli-package.yml - Vela
.github/workflows/vela-cli-release.yml - Vela
deploy/environments/feature-test/bound-branch.json - Vela
specs/current/observability/{monitor,alert}.md