# D601 k3s 开发环境建设计划

> 状态：本过程计划的环境分支方案已废弃。长期权威规则以 `docs/reference/deploy.md` 和 `docs/reference/ci.md` 为准：dev/prod 期望状态统一写在 `master` 分支的根目录 `deploy.json`，通过 `environments.dev` 和 `environments.prod` 区分，不再以 `deploy/dev` 或 `deploy/prod` 分支作为环境事实源。本文件保留为阶段性历史计划，不作为新实现依据。

## 目标

在现有 D601 原生 k3s 集群内建设一套与生产隔离的 UniDesk 开发环境，让以 LLM 为主力的开发流程可以部署、破坏、重建和验证 backend-core、frontend、Code Queue 及其数据库依赖，而不打断生产主 server。

第一版必须支持通过 GitHub commit id 部署。长期控制点是 GitHub 托管的 `deploy.json`：部署某个环境时，自动读取对应 GitHub 环境分支里的 `deploy.json`，并应用其中声明的 commit id。

初始环境分支：

- `deploy/dev`：D601 k3s 开发环境的期望状态。
- `deploy/prod`：生产环境的期望状态。分支保护可以后续补上；第一版仍必须把 prod 部署命令和凭据与 dev 隔离。

## 非目标

- 第一版不创建第二套物理 k3s 控制平面。先复用现有 D601 原生 k3s 集群，通过 namespace 做隔离。
- 第一版不把生产主 server 的 backend-core/frontend 迁入 k3s。
- dev 环境不得共享生产 PostgreSQL 表、Provider 身份、Provider token、Code Queue 任务状态或部署 worktree 路径。
- `deploy/dev` 和 `deploy/prod` 不是普通源码开发分支的别名，只是环境期望状态分支。

## 目标开发拓扑

第一版 dev 环境运行在 D601 的 `unidesk-dev` namespace：

- `postgres-dev`：dev 独立 PostgreSQL StatefulSet，或等价的持久化数据库。
- `backend-core-dev`：从 `deploy/dev:deploy.json` 声明的 commit id 构建。
- `frontend-dev`：从 `deploy/dev:deploy.json` 声明的 commit id 构建，并且只代理到 `backend-core-dev`。
- `code-queue-mgr-dev`：轻量 Code Queue 控制面，使用 dev 数据库。
- `code-queue-read-dev`、`code-queue-write-dev`、`code-queue-scheduler-dev`：Code Queue k3s 执行组件，使用 dev 数据库、dev 日志、dev state 路径和 dev Code Queue 配置。
- 第一阶段访问方式可选：SSH port-forward 或 D601 私有 ingress。阶段 1 不要求公网暴露。

所有 dev 服务的 `/health` 必须输出环境身份：

- `environment=dev`
- namespace 名称
- 数据库名称
- service id
- GitHub repo 和 commit id
- 部署 ref，预期为 `origin/deploy/dev`

## 核心隔离规则

1. dev 服务只能使用 `unidesk-dev` namespace。
2. dev 服务必须使用 dev PostgreSQL 实例或 dev 数据库，不能连接生产 PostgreSQL。
3. dev Provider 身份必须独立，例如 `D601-dev`，不能复用生产 `D601` 的 provider id 或 provider token。
4. dev Code Queue 的 task、queue、attempt、notification 和 trace state 不能写入生产表；除非表名已经显式 namespace 化并经过安全验证。第一版优先使用独立 dev 数据库。
5. dev manifest 不得挂载生产部署根目录，例如主 server 的 `/root/unidesk` 或 D601 生产部署路径；除非只读挂载且确实用于诊断。
6. dev Code Queue 必须使用 dev workdir、dev log dir 和 dev state dir。
7. 生产部署不能读取本地 dirty `deploy.json`；必须从配置好的 GitHub 生产环境 ref 读取生产期望状态。
8. LLM/Code Queue 开发任务默认只获得 dev 部署凭据。

## 部署清单模型

环境 manifest 使用同一套 schema：

```json
{
  "schemaVersion": 1,
  "environment": "dev",
  "services": [
    {
      "id": "backend-core",
      "repo": "https://github.com/pikasTech/unidesk",
      "commitId": "<commit>"
    },
    {
      "id": "frontend",
      "repo": "https://github.com/pikasTech/unidesk",
      "commitId": "<commit>"
    },
    {
      "id": "code-queue",
      "repo": "https://github.com/pikasTech/unidesk",
      "commitId": "<commit>"
    },
    {
      "id": "code-queue-mgr",
      "repo": "https://github.com/pikasTech/unidesk",
      "commitId": "<commit>"
    }
  ]
}
```

环境到 ref 的映射必须固定在代码或权威配置中：

- `dev` 映射到 `origin/deploy/dev`。
- `prod` 映射到 `origin/deploy/prod`。

部署命令应接收环境名，而不是让生产部署任意指定分支。debug 或 admin-only 命令可以查看任意 ref，但普通 prod 部署必须走固定映射。

## 阶段 0：设计与护栏

目的：在加入第二套运行环境前，把目标行为说清楚。

实现项：

- 定义环境 manifest schema 和校验规则。
- 给 deploy manifest 增加 `environment` 字段，并拒绝环境不匹配的 manifest。
- 定义固定环境映射：`dev -> deploy/dev`，`prod -> deploy/prod`。
- 记录 dev 的目标 namespace、数据库、Provider 身份和 service id。
- 增加 CLI dry-run plan 输出：
  - 选中的环境
  - GitHub ref
  - 解析到的 manifest commit
  - services 和 commit id
  - 目标 namespace
- 目标数据库指纹
  - 目标 Provider 身份

验收标准：

- `deploy plan --env dev` 可以读取并校验 dev manifest，且不修改集群。
- `deploy plan --env prod` 可以读取并校验 prod manifest，且不使用本地 worktree 的 `deploy.json`。
- `environment=prod` 的 manifest 必须被 `--env dev` 拒绝，反向也必须拒绝。

## 阶段 1：GitHub 环境分支作为部署源

目的：让 GitHub 里的环境期望状态 ref 成为部署真相源。

实现项：

- 创建或初始化 `deploy/dev`，包含有效的 `deploy.json`。
- 创建或初始化 `deploy/prod`，包含有效的 `deploy.json`。
- 增加 CLI 支持：fetch 环境 ref，并从该 ref 读取 `deploy.json`。
- 现有本地 `deploy.json` 只保留为显式本地/管理员流程的兼容模式。
- 校验 manifest 中列出的 commit id 存在于声明的 repo。
- 确保 dev/prod 部署不依赖本地 dirty working tree。

验收标准：

- `deploy plan --env dev` 读取 `origin/deploy/dev:deploy.json`。
- `deploy plan --env prod` 读取 `origin/deploy/prod:deploy.json`。
- 修改本地 `deploy.json` 不影响 `--env dev` 或 `--env prod`。
- plan 输出包含实际使用的 Git ref 和 manifest blob/commit。

## 阶段 2：D601 开发 Namespace 与数据库

目的：创建 dev backend 和 Code Queue state 的最小隔离底座。

实现项：

- 增加 `unidesk-dev` namespace 的 k8s manifest。
- 增加 dev PostgreSQL StatefulSet/Service/PVC，或等价持久化 DB。
- 增加 dev DB init 和 migration 流程，用于 backend-core 和 Code Queue 表。
- 增加 dev secrets/config：
  - 数据库凭据
  - provider token
  - auth/session secret
  - 必要时的 Code Queue model secrets
- 增加资源 requests/limits，避免 dev DB 挤占 D601 生产 k3s workload。

技术决策：

- 优先使用独立 dev PostgreSQL 实例，而不是共享生产 PostgreSQL 的不同数据库名。独立实例的故障边界最清晰。
- 如果临时使用共享 PostgreSQL server，CLI 和服务启动时必须硬校验数据库名和连接目标。

验收标准：

- `kubectl -n unidesk-dev get pods,svc,pvc` 显示 dev DB ready。
- dev DB 在 Pod 重启后数据仍存在。
- dev 服务误连生产数据库 URL 时，必须启动失败。

## 阶段 3：backend-core-dev 与 frontend-dev

目的：做出一套可用的 UniDesk dev 控制面，不依赖生产主 server Compose。

实现项：

- 增加 `backend-core-dev` 和 `frontend-dev` 的 k8s manifest。
- 从 `deploy/dev:deploy.json` 声明的 commit id 构建镜像。
- 向 backend-core 注入 dev-only config：
  - `UNIDESK_ENV=dev`
  - dev `MICROSERVICES_JSON`
  - dev database URL
  - dev provider token
  - dev log paths
- 注入 frontend 配置，使其代理到 `backend-core-dev`，不能代理生产 backend-core。
- 增加 service health 和 readiness probe。
- 通过 port-forward 或私有 dev ingress 暴露 dev frontend。

技术决策：

- 第一版可以不做公网暴露。验证隔离时使用 port-forward 即可。
- dev frontend 必须有明显 DEV 环境标记，避免操作员混淆。

验收标准：

- dev backend-core `/health` 返回 ok，并包含 `environment=dev`。
- dev frontend `/health` 返回 ok，并且只代理到 dev backend-core。
- dev backend/frontend 重部署期间，生产 `bun scripts/cli.ts server status` 仍健康。
- 重建 dev backend/frontend 不触碰主 server Docker Compose 容器。
- 当前实施切片：`deploy apply --env dev --service backend-core|frontend` 先支持 dev core 两个服务；`deploy/dev` 只保存 `deploy.json`，不保存 k8s manifest 或源码。

## 阶段 4：code-queue-mgr-dev

目的：提供 dev 队列管理和提交路径，同时不写生产 Code Queue 表。

实现项：

- 增加 `code-queue-mgr-dev` k8s manifest。
- 配置它只使用 dev 数据库。
- 配置 dev backend-core service catalog，使 dev 稳定 `code-queue` 控制/读取路径路由到 `code-queue-mgr-dev`。
- 确保 `code-queue-mgr-dev` 可以提交、列出、汇总和更新 dev queue state。
- health 输出必须证明：
  - role 是 `master-control-plane` 或 `dev-control-plane`
  - database 是 dev
  - schema ready
  - no runner dependencies

验收标准：

- dev UI/CLI 可以向 dev DB 提交 dry-run 或 queued task。
- dev 提交不会改变生产 Code Queue task list。
- `code-queue-mgr-dev` 内存占用保持在轻量控制面预算内。

## 阶段 5：code-queue-dev 执行组件

目的：在 `unidesk-dev` 内运行 dev Code Queue 执行面，不干扰生产 Code Queue。

实现项：

- 增加 Code Queue manifest 的 dev 变体：
  - `code-queue-read-dev`
  - `code-queue-write-dev`
  - `code-queue-scheduler-dev`
- 所有 dev 组件使用 dev 数据库、dev 日志和 dev state 路径。
- 使用 dev service name 和 label，避免生产 k3s adapter 混淆 dev/prod 服务。
- 决定第一版支持真实 Codex 执行，还是只支持 smoke-only 执行。
- 如果启用真实执行：
  - 隔离 workdir 路径
  - 隔离 Codex/OpenCode XDG/state 路径
  - 隔离通知
  - 限制并发和内存
  - 默认不写生产 OA Event Flow，除非显式配置为 dev

技术决策：

- 第一版采用真实 Code Queue 进程和 dev PostgreSQL，但部署验收先以执行面可部署、`/health` 通过和 dev DB 隔离为准。
- dev scheduler 使用 `D601-dev` 作为本机 Provider 标识，默认工作目录为 `/workspace-dev`，远程工作目录为 `/home/ubuntu/unidesk-dev-workspace`。
- 默认禁用生产 ClaudeQQ 通知，不使用生产 `d601-tcp-egress-gateway` 或生产 PostgreSQL 入口。
- dev frontend/backend-core 的稳定 `code-queue` 业务路由需要等 `code-queue-mgr-dev` 和 dev service catalog 完成后再接入，本阶段不把 dev 执行面伪装成完整业务入口。

验收标准：

- dev Code Queue `/health` 返回 ok，并包含 `environment=dev`。
- `deploy apply --env dev --service code-queue` 可以根据 `origin/deploy/dev:deploy.json` 构建 `unidesk-code-queue:dev`，部署 `code-queue-scheduler-dev`、`code-queue-read-dev`、`code-queue-write-dev`，并验证 health commit。
- 后续接入 `code-queue-mgr-dev` 后，dev scheduler 可以拾取 dev queued task，并推进到终态。
- 重启 dev scheduler 不影响生产 running task。
- dev Code Queue rollout 期间，生产 `code-queue` health 仍健康。

## 阶段 6：Dev 部署执行

目的：让 `deploy/dev:deploy.json` 端到端驱动 dev 环境。

实现项：

- 增加 `deploy apply --env dev`。
- 对 dev manifest 中的每个服务：
  - fetch 声明的 repo 和 commit
  - 在 D601 上构建镜像，或复用既有 target-side build 路径
  - 用环境和 commit 给镜像打 tag
  - apply dev k8s manifest
  - 等待 rollout
  - 从 `/health` 或 Deployment annotation 验证 live commit
- 部署记录包含 environment、ref、service id、commit id、image tag、namespace 和 rollout 状态。
- 增加 `deploy status --env dev` 或等价 drift check。

验收标准：

- 更新 `deploy/dev:deploy.json` 到新 commit 后，运行 `deploy apply --env dev` 会更新 dev backend-core/frontend/code-queue 组件。
- live `/health` commit 与 manifest commit 一致。
- dev 部署不会修改任何生产 Deployment、Service、Secret、PVC、DB table 或 Docker Compose 容器。

## 阶段 7：生产部署 Ref 兼容

目的：让生产部署从 `deploy/prod` 读取期望状态，同时保持生产运行方式不变。

实现项：

- 增加 `deploy plan --env prod` 和 `deploy apply --env prod`，读取 `origin/deploy/prod:deploy.json`。
- 初期保持现有生产 executor：
  - 生产 backend-core/frontend 和 direct sidecar 继续使用主 server Compose。
  - 生产 Code Queue 执行面继续使用 D601 k3s。
- 强化生产命令护栏：
  - 只能在权威根目录执行
  - 生产凭据只存在主 server
  - manifest 必须声明 `environment=prod`
  - 目标 namespace 和 Provider 身份必须匹配生产
- 建议后续给 `deploy/prod` 增加 branch protection；第一版可暂缓。

验收标准：

- 生产部署不再依赖本地 `deploy.json`。
- 生产部署报告实际使用的 Git ref 和 manifest commit。
- 生产部署 rollout 后仍校验 live commit。

## 阶段 8：操作员与 LLM 安全

目的：降低 LLM agent 和人工操作员混淆环境的概率。

实现项：

- 每次 deploy 的 CLI 输出都清晰显示：
  - environment
  - ref
  - namespace
  - DB 指纹
  - provider id
  - services 和 commits
- dev frontend 增加明确 DEV 标记。
- 增加硬启动检查：
  - dev service 拒绝生产 DB
  - dev service 拒绝生产 provider id/token
  - prod service 拒绝 dev namespace/DB
- 确保 LLM task container 默认只拿到 dev deploy 凭据，拿不到 prod 凭据。
- 增加 smoke check：故意尝试不安全组合，并验证它们失败。

验收标准：

- dev 服务使用生产 DB 配置启动时，在监听端口前失败。
- 从非权威上下文运行 prod deploy 时失败。
- LLM/Code Queue 默认环境可以部署 dev，但没有独立生产凭据路径时不能部署 prod。

## 风险与缓解

- 风险：namespace 不能隔离节点级 CPU、内存、Docker socket、hostPath 或 containerd 压力。
  - 缓解：资源 requests/limits、独立 dev workdir、不挂载生产路径，并限制 Code Queue 并发。
- 风险：dev Code Queue 误写生产 task 表。
  - 缓解：独立 dev DB、启动时 DB 指纹检查、health 输出 DB 身份。
- 风险：dev frontend 看起来像 prod，或代理到 prod backend-core。
  - 缓解：可见 DEV 标记、`CORE_INTERNAL_URL` 固定到 dev service、proxy target health check。
- 风险：deploy 命令误读本地 manifest，而不是 GitHub 环境 ref。
  - 缓解：`--env` 模式必须只读取 remote ref，并报告实际使用的 ref/blob。
- 风险：D601 k3s 控制面故障同时影响 dev 和生产 k3s workload。
  - 缓解：Phase 1 接受该风险；只有 namespace 隔离被证明不足后，再考虑独立物理节点或节点级 dev 集群。
- 风险：`deploy/prod` 初期未开启 branch protection。
  - 缓解：即使没有 branch protection，生产部署仍必须要求权威主 server 凭据，并报告用于审计的 ref。

## 建议实现顺序

1. Phase 0 和 Phase 1：建立 GitHub 环境分支期望状态和 dry-run planning。
2. Phase 2 和 Phase 3：创建 dev namespace、dev DB、backend-core-dev 和 frontend-dev。
3. Phase 4 和 Phase 5：增加 dev Code Queue 控制面和执行组件。
4. Phase 6：让 `deploy apply --env dev` 按 commit id 部署完整第一版 dev stack。
5. Phase 7：把生产部署迁移到 `deploy/prod`。
6. Phase 8：强化操作员和 LLM 安全检查。

第一个完整里程碑完成条件：`deploy apply --env dev` 可以根据 `origin/deploy/dev:deploy.json` 声明的 commit id，把 backend-core、frontend、code-queue-mgr 以及 Code Queue read/write/scheduler 部署进 `unidesk-dev`；反复 dev redeploy 不改变生产主 server status，也不改变生产 Code Queue state。阶段 3 的阶段性里程碑先以 `--service backend-core` 和 `--service frontend` 分别部署成功为准。
