# UniDesk Deployment Reference 主 server 使用根目录 `docker-compose.yml` 统一编排 database、backend-core、frontend、dev-frontend-proxy、provider-gateway 以及必须留在主 server 的用户服务。当前环境本身就是主 server,因此 provider-gateway 也在同一台机器上启动,用与普通计算节点相同的 WebSocket 方式接入 core。Code Queue 按“master 低资源低抖动控制面、D601 高资源高抖动执行面”拆分:队列 CRUD、任务提交、历史摘要和轻量 Trace 读取由主 server Compose 中的 `code-queue-mgr` 直管 PostgreSQL;Codex/OpenCode scheduler、runner、dev-container、active run steer/interrupt 和执行态写回仍由 D601 原生 k3s/k8s Code Queue 执行面承担。 Production runtime and CI/CD control-plane versioning follow `docs/reference/release-governance.md` and [GitHub issue #6](https://github.com/pikasTech/unidesk/issues/6): server-side runtime is commit-pinned through `deploy.json`, while a newer `master` CLI may operate it only through compatible APIs and server-reported capabilities. ## Services - `database` 使用 `postgres:16-alpine`,数据保存到 named volume `unidesk_pgdata_10gb`,当前容量预算为 15 GB,初始化 SQL 位于 `src/components/database/init/`。 - `backend-core` 是无状态核心服务,提供 Docker 内网 REST API、provider ingress WebSocket、任务调度入口、provider data TCP pool 入口和数据库访问层。当前 backend-core 是 Rust 服务;Rust 默认迭代编译边界和主 server 上线受控例外见 `docs/reference/dev-environment.md`。源码模块结构见 `docs/reference/repo-tree.md`。 - `frontend` 是 production 公开 Web 控制台,提供登录、从 TSX 转译出的 React 应用资产和到 backend-core 的同源代理。 - `dev-frontend-proxy` 是主 server 上的 18083 dev UI 薄入口,代理到 D601 `unidesk-dev/frontend-dev`,详细边界见 `docs/reference/dev-environment.md`。 - `provider-gateway` 是当前主 server 的本机计算节点代理,通过 WebSocket 主动连到 provider ingress,挂载 `/var/run/docker.sock` 作为自动任务执行主路径,使用 `pid: "host"` 读取节点级进程资源,并周期性上报系统资源指标、进程占用与 Docker daemon 状态;计算节点 provider-gateway 还必须把 egress proxy 仅发布到宿主 loopback `127.0.0.1:18789` 供本节点执行环境出网,维护用 Host SSH / WSL SSH 私钥目录只读挂载到 `/run/host-ssh`,不得作为自动任务调度主路径。 - `todo-note` 是主 server 承载的 Todo Note 纯后端用户服务,容器名 `todo-note-backend`,只在 Compose 内网暴露 `4211/tcp`,使用主 PostgreSQL 存储迁移后的 Todo Note 数据。 - `code-queue-mgr` 是主 server 承载的轻量 Code Queue 控制面用户服务,容器名 `code-queue-mgr-backend`,只在 Compose 内网暴露 `4278/tcp`,只连接主 PostgreSQL,负责 `code-queue` 稳定代理路径下的队列管理、任务提交、历史摘要、已读状态和轻量 Trace 读取;不得引入 Codex/OpenCode/Playwright/Chromium/Docker socket/runner 依赖。生产镜像是 Rust slim runtime,Compose healthcheck 必须调用镜像内 `code-queue-mgr --healthcheck` 或等价 Rust 探针,不得依赖 Bun runtime。 - `k3sctl-adapter` 是 D601 上由 UniDesk 直管的 k3s 控制面适配微服务,容器名 `k3sctl-adapter`,只绑定 `127.0.0.1:4266`,由 UniDesk frontend/backend-core 通过用户服务代理访问并提供 `/api/control-plane` 可见性。 - `code-queue` 是稳定对外用户服务 ID。backend-core 对 `/api/microservices/code-queue/proxy/...` 做内部职责分流:控制/读取路径默认转到主 server `code-queue-mgr`,D601 k3s `code-queue-read`/`code-queue-write`/`code-queue-scheduler` 只承担执行面兼容、scheduler/runner、dev-container、judge 和 running task control。D601 执行面通过 `src/components/microservices/k3sctl-adapter/k3s/code-queue.k3s.json` 声明,运行对象通过 `code-queue.k8s.yaml` 创建 Kubernetes Deployment/ClusterIP Service;任务、queue、未读状态、控制状态和通知 outbox 一律写入主 PostgreSQL,不保留本地状态文件 fallback。 - `project-manager` 是主 server 承载的项目管理用户服务,容器名 `project-manager-backend`,仅在 Compose 内网暴露 `4233/tcp`,项目清单写入主 PostgreSQL,浏览器只能通过 UniDesk frontend 同源代理执行增删改查、Excel 导入和 Excel 导出。 - `baidu-netdisk` 是主 server 承载的百度网盘存储用户服务,容器名 `baidu-netdisk-backend`,仅在 Compose 内网暴露 `4244/tcp`,OAuth/token/transfer 状态写入主 PostgreSQL,浏览器只能通过 UniDesk frontend 同源代理执行设备码登录、文件浏览和 staging 传输任务控制。 ## Public Exposure Boundary Docker Compose 对最终用户只公开 production frontend host port、dev frontend proxy host port 和 provider ingress host port。provider data TCP port 只服务 provider 主动连入的 SSH data channel pool,不是浏览器或任意公网客户端 API。backend-core REST API 仍不得映射公网;PostgreSQL 和 OA Event Flow 只允许为了受控 Code Queue active/standby 节点使用受限端口映射,并必须由 `network.restrictedHostAccess.allowedSourceCidrs` 生成的 `DOCKER-USER` 规则限制到 D601 出口地址,不能作为浏览器或任意公网客户端入口。浏览器访问 core API 必须通过 frontend 的同源代理完成;dev UI 访问路径见 `docs/reference/dev-environment.md`。 计算节点上的用户服务后端也遵守同一边界:业务容器端口只绑定节点本机地址,并由 provider-gateway 主动连出 WebSocket 后接受 backend-core 的 `microservice.http` 调度访问。主 server 不为用户服务新增面向浏览器的公网反向代理端口;最终用户只通过 UniDesk frontend 的 React 页面访问结构化业务控件。 ## Docker Compose Runtime CLI 会优先使用 `docker compose` v2 plugin;当 v2 plugin 不存在时才回退到 `docker-compose` v1。主 server 可以通过安装系统包形式的 Compose v2 plugin 完成无中断升级,因为该动作只增加 Docker CLI plugin,不要求重启 Docker daemon,也不要求重建或停止已有容器。若 Compose v2 build 提示 buildx plugin 不存在,应同样以系统包安装 buildx CLI plugin,而不是重启 Docker 或重建业务容器。 Compose v2 安装后仍然必须遵守 UniDesk 的服务控制入口:全栈生命周期用 `server start` / `server stop`,单服务重建用 `server rebuild `。不要因为 v2 可用就直接在生产栈上手工执行未纳入 CLI 的 `up --build`、`down -v` 或跨项目清理命令;所有会影响容器的动作都应保持 job 可观测、Compose project 固定、database named volume 保留。主 server Compose 命令必须从 `providerGateway.upgrade.hostProjectRoot` 指定的 canonical UniDesk 根目录运行,临时 worktree、Code Queue 导出目录或实验分支不得复用生产 `-p unidesk` 和固定 `container_name` 去替换生产容器。 版本化用户服务部署优先使用 `bun scripts/cli.ts deploy apply` 已支持的受控路径;D601 persistent dev apply 当前支持 `backend-core`/`frontend`/`baidu-netdisk`/`decision-center`/`mdtodo`/`claudeqq` artifact consumer、dev-only `code-queue` artifact consumer,以及 `project-manager`、`oa-event-flow`、`code-queue-mgr`、`todo-note`、`findjob`、`pipeline` 和 `met-nonlinear` 的 artifact consumer validation,dev desired-state smoke 使用 `ci run-dev-e2e`。`deploy.json` 只声明服务 `id`、`repo` 和 `commitId`;目标节点、Dockerfile、Compose、Kubernetes manifest、健康检查和代理路径继续来自 `config.json` 与现有 manifest。主 server 直管微服务和内部 sidecar,例如 `code-queue-mgr`,也必须支持这一路径:`deploy apply --service code-queue-mgr` 从 `deploy.json` 指定 commit 导出源码、构建镜像、替换固定 Compose service 并验证运行中镜像/健康信息的 commit,但 prod live apply 仍需 supervisor 确认。部署默认遵循 target-side build:服务部署到哪台 target,就在哪台 target 从 remote commit 导出源码、一次性代理构建镜像并部署;不得把中心构建镜像作为默认分发路径,也不得用 `docker commit` 或脏 worktree 作为部署输入。backend-core 是明确例外;`frontend` 是用户服务 UI / 前端镜像化样板,`baidu-netdisk` 是主 server 直管微服务的镜像化样板,`decision-center`、`mdtodo` 和 `claudeqq` 是 k3s-managed artifact consumer 样板,`findjob` 和 `pipeline` 是 D601 direct Docker/Compose pull-only 样板:D601 CI 构建并推送 commit-pinned 镜像到 D601 artifact registry,CD 只拉取、retag 或导入、recreate/rollout 和验证,不在 master server 或 runtime target 执行 Compose build。Dev backend-core consumes `127.0.0.1:5000/unidesk/backend-core:` into `unidesk-dev/backend-core-dev` and must not compile Rust during CD. `met-nonlinear` 当前只允许 dry-run/plan,`k3sctl-adapter` 只允许 plan/dry-run 且真实 prod 部署需要 supervisor 确认。`code-queue` 只允许 dev artifact consumer,prod artifact deploy/rollout/manifest mutation 必须 unsupported。完整规则见 `docs/reference/deploy.md`,D601 dev/Rust 边界见 `docs/reference/dev-environment.md`,artifact registry 见 `docs/reference/artifact-registry.md`。 ## Host Codex Profiles 主 server 上的 `codex`、`mycx`、`mxcx` 和 `acx` 都是人工/Codex 运维入口,不属于 UniDesk Compose 服务、Code Queue runner、AgentRun runtime 或发布流水线。`mxcx` 只用于快速以 MiniMax-M3 provider 启动同一套 Codex CLI;`acx` 是主 server 统一多模型 Codex profile 入口,默认使用 `gpt-5.5-only`,并允许通过 `/model` 或 `-m` 切换到 OpenCode Zen Go 与 Sub2API GPT aliases。它们必须复用系统 `codex` 二进制,不安装第二套 Codex,不替换 `/usr/bin/codex`,也不改变 `mycx` 指向的默认 Codex 启动方式。主机 Codex profile 的长期运维细节以 `docs/reference/master-server-ops.md` 为准;UniDesk 仓库文档只记录部署边界和与服务运行面相关的约束。 MiniMax-M3 配置必须保持 profile/provider 级隔离。当前 `mxcx` 的稳定形态是 `CODEX_HOME=/root/.codex-minimax-m3`、`model=MiniMax-M3`、`model_provider=minimax`、`wire_api=responses`,通过本机 Moon Bridge loopback endpoint 转换到 MiniMax 上游;profile config 中的 Codex `base_url` 应指向本机 bridge,Moon Bridge runtime config 再持有 MiniMax upstream `https://api.minimaxi.com`。密钥通过 profile `auth.json` 或环境中的 `OPENAI_API_KEY`/`MINIMAX_API_KEY` 注入,文件只能由 root 读取,权限应为 `0600` 或更严;不得提交到 Git、写入 `AGENTS.md`/`docs/reference`、进入 Docker image、Compose env、GitOps manifest、issue/PR 评论、CLI 输出或任务 trace。 `mxcx` 的验收以真实 Codex CLI 行为为准:`mxcx --version` 必须显示与 `codex --version` 相同的 binary 版本;`mxcx doctor` 或等价命令必须显示 `model=MiniMax-M3`、Responses wire API、profile-local Moon Bridge endpoint 和 bridge reachable;最小真实调用可使用 `mxcx exec 'Reply exactly: MXCX_OK'`,但该调用会消耗 MiniMax token,不应放入默认健康检查、CI/CD 或循环监控。MiniMax `/v1/models` 或 Moon Bridge `/models` 探测只能作为网络/凭据诊断,不能替代 Codex CLI profile 验收。 如果 `mxcx` 需要本机转发服务,必须优先复用 AgentRun 已采用的 provider/profile 方案或同款转发组件;不得在 UniDesk master server 上临时自造一套长期维护的 MiniMax 协议转换服务。确需部署转发时只允许作为本机轻量运维组件,固定绑定 loopback、固定端口、日志可见、密钥不进镜像,并记录启动/停止/健康检查入口;不得接入 UniDesk CI/CD、GitOps、provider-gateway 自动升级或生产 Compose 主服务生命周期,除非后续专门把它产品化为受控服务。 `mxcx session-clean` 只属于主机 profile 的会话恢复工具,范围限定为修复非法 TOOLJSON / schema-invalid tool arguments 和匹配的 stale parse-failure output。它不得 compact、summarize、truncate、删除、重排或改写非工具历史;pre-sampling compact 或 token-window 问题必须走 Codex 上游 compaction 或 Codex/Moon Bridge 配置,不得在 wrapper 里新增手工压缩。修改 `mxcx` 后的最小验收包括 `bash -n /root/.local/bin/mxcx`、`mxcx doctor`、`session-clean` 双跑幂等和一个 bounded `mxcx exec` smoke。 ## Main Server Swap 主 server 可能运行在约 2 GiB 内存的小规格机器上,短时 Docker build、Codex/control-plane 调查和日志读取会触发 global OOM。主 server 必须通过 `bun scripts/cli.ts server swap status` 暴露当前 memory/swap 状态,并在 `server status` 的 `swap` 字段中给出同一摘要。 缺少 active swap 时,正式修复入口是 `bun scripts/cli.ts server swap ensure [--path /swapfile] [--size 2GiB]`。该命令必须幂等:已有任何 active swap 时只返回 no-op 状态;无 swap 时创建固定 swapfile、设置 `0600`、执行 `mkswap` 与 `swapon`,并尽量把 ` none swap sw 0 0` 写入 `/etc/fstab`。如果当前环境允许 `swapon` 但不允许写 `/etc/fstab`,命令返回 `status=degraded`,并在 JSON 的 `errors`/`actions` 中说明下一步;不得静默假装持久化完成。 swap 管理不能被强塞进所有热路径。`server start/status` 可以暴露 warning 或摘要,但不会自动创建 swap;需要变更主机 swap 时必须显式运行 `server swap ensure`,并用返回的 `before`/`after` 和 `fstab.persisted` 作为验收记录。 根分区 Docker 镜像高水位治理必须先走 `bun scripts/cli.ts server cleanup plan` 的 dry-run,再用 `bun scripts/cli.ts server cleanup run --confirm` 执行同一 classifier 选出的 stale image 删除。该入口只针对 Docker image inventory:默认只把创建时间超过 24 小时且不在保护集里的镜像列为 stale,输出 active containers/images、protected images、candidate stale images、风险、估算释放空间、人工复核命令和执行结果;高风险候选必须额外显式 `--include-high-risk` 才会执行。候选必须从白名单保护集中排除:running container image ID、stopped container 引用 image ID、Compose stable image、`deploy.json`/`CI.json` 当前 commit artifact、上游 digest pin 和 provider-gateway runner image。计划还必须显式保护 PostgreSQL named volume、Baidu Netdisk `.state`/staging、D601 registry storage 和所有 Docker volume/host data 目录。该入口不得用 `docker system prune`、`docker image prune`、`docker builder prune`、volume 清理或数据库清理替代 dry-run 审批;数据库清理前必须先确认可用备份。 ## Start And Stop `bun scripts/cli.ts server start` 与 `bun scripts/cli.ts server stop` 都是异步 job。启动 job 只执行固定 Compose project 的 `up -d --build --remove-orphans`,不得先 `down`,避免在 provider-gateway 旧容器或网络冲突时把长驻控制面容器先删掉又启动失败;停止 job 才允许执行 `down --remove-orphans`。启动和停止流程都禁止删除 Docker named volume。所有会改变主 server Compose 状态的 job 必须通过 `.state/locks/server-compose.lock` 串行化;连续 `server rebuild` 命令只代表连续创建异步 job,不能代表第一个 job 已结束,实际容器变更仍必须由 Compose lock 串行执行。 ## Single Service Rebuild 前端、本机 provider-gateway、dev-frontend-proxy 或主 server 承载的 Todo Note/Code Queue Manager/Project Manager/Baidu Netdisk/OA Event Flow 用户服务需要非版本化本地重建时,统一使用 `bun scripts/cli.ts server rebuild `,其中 `` 只能是 `backend-core`、`frontend`、`dev-frontend-proxy`、`provider-gateway`、`todo-note`、`code-queue-mgr`、`project-manager`、`baidu-netdisk` 或 `oa-event-flow`。对 `database`、`filebrowser`、`filebrowser-d601`、`code-queue`、`k3sctl-adapter` 或未知对象,CLI 必须返回结构化 `unsupported-server-rebuild`,不得创建 job、不得执行 Compose mutation,也不得把对象强行转成源码构建服务。需要按 commit 上线或恢复到 desired-state 时必须改用 `bun scripts/cli.ts deploy apply --service `、backend-core artifact CD、`deploy apply --env dev|prod --service frontend|baidu-netdisk|decision-center|mdtodo|claudeqq` artifact consumer,或 dev-only `deploy apply --env dev --service code-queue` artifact consumer;直管微服务也不能把脏工作树或手工重建作为部署真相。`server rebuild frontend`、`server rebuild baidu-netdisk`、`server rebuild project-manager`、`server rebuild oa-event-flow`、`server rebuild todo-note` 和 `server rebuild code-queue-mgr` 都只作为维护/非标准路径保留,不得作为标准发布完成证据。Rust backend-core 常规迭代和 dev artifact CD 不得在 master server 用 `server rebuild backend-core` 替代 D601 CI;唯一例外是已提交的 backend-core 修复需要上线到主 server Compose runtime 时,可以用 `server rebuild backend-core` 受控编译并替换该服务,要求限流并发、异步 job/status 轮询、容器 health 验证和 issue 证据回写。D601 Code Queue 执行面、File Browser、FindJob、Pipeline、MET Nonlinear 和 ClaudeQQ 部署在计算节点,不属于主 server Compose 可重建服务;其中 D601 Code Queue 执行面不得再通过 `codex deploy` 或维护通道直连 D601 部署,且本阶段 prod artifact deploy/rollout/manifest mutation 仍 unsupported。特例冻结清单和下一阶段删除判断见 `docs/reference/cicd-standardization.md`。 backend-core 的 Dockerfile 必须把 Rust 依赖构建和业务源码构建拆开:先只复制 `Cargo.toml` / `Cargo.lock`,用临时 `src/main.rs` 填充 release 依赖层;再复制真实 `src/` 并编译最终 `backend-core` 二进制。这样同一 builder 上只改业务源码时可以复用依赖层,避免每次重新编译全部 crate。该缓存策略只改善后续源码迭代;全新 builder 的第一次冷编译仍然需要下载和编译依赖,若要把第一次也做快,长期方案应是预构建依赖 builder image、BuildKit registry cache 或由 CI 发布 commit-pinned runtime image 后让部署侧只 pull 成品镜像。 临时 dummy `main.rs` 会生成同名 `target/release/backend-core`,这是 backend-core Dockerfile 的固定坑。源码层在编译真实代码前必须删除旧 `target/release/backend-core`、对应 `.d` 文件和 `unidesk-backend-core-*` fingerprint;只执行 `cargo clean -p` 不一定会清到 dummy binary。若忘记清理,最终镜像可能复制 dummy binary,表现为容器启动后立刻 exit 0、日志为空、health 一直失败。重建 backend-core 后必须以容器 health 和真实 `/health` 或等价 core 入口确认,不得只看 Docker build `Built`。 frontend 改动必须明确上线到公网:修改 `src/components/frontend/src/`、`src/components/frontend/public/style.css`、frontend 使用的共享 TSX/TS 模块或 WebUI 导航后,标准发布顺序是先把 pushed commit 交给 `bun scripts/cli.ts ci publish-user-service --service frontend --commit `,再用 `bun scripts/cli.ts deploy apply --env dev --service frontend` 和 `bun scripts/cli.ts deploy apply --env prod --service frontend` 消费同一个 commit-pinned artifact。公网 WebUI 的 `/app.js` 是 `unidesk-frontend` 镜像内运行时 bundle;只改工作区文件、只跑 `bun run check`、只跑 `Bun.build`、只刷新浏览器或只 `server rebuild frontend` 都不能作为标准版本发布证据。 frontend 的 artifact 上线顺序为:先运行必要的轻量本地校验或 D601 CI;然后发布 `127.0.0.1:5000/unidesk/frontend:`;再用 dev/prod `deploy apply` 消费该 artifact;最后验证 dev `frontend-dev` 和 prod `frontend` 的 `/health.deploy.commit`、image label、`UNIDESK_DEPLOY_*` metadata 都等于 requested commit。若必须手工复现维护路径,等价 Docker Compose 命令只能是固定 project/env 的 `docker compose --env-file .state/docker-compose.env -f docker-compose.yml -p unidesk build frontend`,随后 `docker compose --env-file .state/docker-compose.env -f docker-compose.yml -p unidesk up -d --no-deps --force-recreate frontend`;手工路径仍必须做同样的健康检查,不得改用全栈 `up --build`、`down`、删除容器或重启 database/backend-core 来“顺手上线”前端。 单服务重建必须由 CLI 解析出的 Compose 命令执行,且只能影响目标 service,不得连带重启 database、backend-core 或其他未指定服务。重建后 job 必须按 Docker Compose label 校验目标容器:`com.docker.compose.project` 等于 `config.json` 中的固定 project name,`com.docker.compose.service` 等于目标服务名,并等待容器进入 `healthy`;没有 healthcheck 的服务至少要进入 `running`。如果验证失败,job 必须失败并输出目标容器状态,禁止把“无输出”或“只完成 build”当作成功。`code-queue-mgr` 的 post-up validation 依赖 Docker health 状态,因此其 healthcheck 必须在 Rust runtime 镜像内自洽可执行,不能引用不存在的 `bun`。 紧急灾备或数据迁移期间如需手工启动单个 Compose service,也必须保持与 CLI 相同的隔离语义:使用固定 `--env-file .state/docker-compose.env` 和 `up -d --no-deps `,只启动目标容器;如果需要刷新 backend-core 的服务目录或环境变量,应把 `backend-core` 作为显式目标单独重建/替换,不能依赖 `up` 的依赖解析顺手重建 database、backend-core 或其他服务。 正式流程不得依赖人工 `docker rm` 兜底;手工删除旧容器后若 job、Docker client 或 daemon 在 `up` 前中断,会直接造成用户服务代理失败。`server rebuild `、`deploy apply` 和未来 D601 CD run 都必须是可观测流程:build-first、受控替换、post-up validation、保留命名卷或 `.state` 运行态目录。Code Queue 等计算节点长任务服务即使被重建也必须依赖服务自身 restart-recovery 恢复任务,不能用“避免重建”掩盖恢复缺陷。 ## User Service Restart Recovery 主 server 用户服务和计算节点用户服务都必须按 `docs/reference/microservices.md` 的 Runtime Configuration And Persistence Contract 设计。主 server Compose 内的用户服务通过固定 project、`restart` policy、健康检查、PostgreSQL 权威状态和 `server rebuild ` 的 no-deps force-recreate 恢复;计算节点用户服务通过节点本地 Compose/docker run、host bind mount 或业务数据库持久化、Docker restart policy、节点级 autorecover 脚本和 provider-gateway 私有代理验收恢复。上线说明不能只写“容器已启动”,必须说明 Docker daemon 或机器重启后如何重新进入 ready 状态,以及哪些路径/表保存了登录、队列、token、订阅和业务数据。 ## Health Criteria 服务跑通的最低标准是:backend-core 内网 `/health` 返回 ok,frontend 公网 `/health` 返回 ok,dev frontend proxy 公网 `/health` 在 D601 dev frontend 已部署后返回 ok,provider ingress 公网 `/health` 返回 ok,database 在容器内 `pg_isready` 可用,Todo Note 后端 `/api/health` 返回 `storage=postgres`,`code-queue-mgr` `/health` 返回 `role=master-control-plane`、`schemaReady=true` 和资源预算字段,`bun scripts/cli.ts microservice health code-queue` 与 `/api/tasks/overview` 默认经主 server `code-queue-mgr` 返回 PostgreSQL 队列总览,`k3sctl-adapter` `/api/control-plane` 可见 `unidesk-k3s` Kubernetes API service proxy 状态、D601 scheduler serving healthy、D601 read/write Service healthy、`presentNodeIds` 包含 `D601`、`missingNodeIds=[]` 和 no-fallback 路径,D601 Code Queue scheduler `/health` 返回轻量 readiness、默认模型、`queue.storage` 和 `egressProxy.connected=true`,提交类入口经 `code-queue-mgr` 入库后由 D601 `code-queue-scheduler` 轮询并执行,Project Manager `/health` 返回 `storage.primary=postgres` 和项目数量,backend-core `/api/performance` 返回性能指标,`/api/nodes` 中出现 `main-server`、`D601` 和 `D518` provider 且状态为 `online`,`/api/nodes/system-status` 中出现对应 CPU/内存/硬盘采样,`/api/nodes/docker-status` 中能看到主 server、D601 与 D518 Docker 快照。D601/D518 上不得存在 active `rancher/k3s` 容器;D518 只有在原生 k3s-agent 与稳定 Kubernetes 网络完成验证后才可加入 Code Queue expected nodes。交付前还必须运行 `bun scripts/cli.ts e2e run`,并以 `docs/reference/e2e.md` 的门禁作为最终判定。 ## Code Queue Control/Execution Resource Budget 主 server `code-queue-mgr` 是低资源控制面,目标常驻内存不超过 100 MB,只允许 PostgreSQL 小连接池、日志和基础 CRUD/摘要逻辑;不得安装或运行 Playwright、Chromium、Codex/OpenCode、Docker socket、dev-container 或执行器。它的 `/health` 必须暴露 `resourceBudget.targetMemoryMb=100`、`noRunnerDependencies=true`、连接池上限和 `role=master-control-plane`,便于在主 server 低内存环境中识别是否越界。 D601 Code Queue 执行面仍必须保持明确的 memory/swap 硬上限;production scheduler 当前预算是 k3s `request.memory=15Gi`、`limit.memory=15Gi`,legacy D601 Compose fallback 是 `mem_limit=15g`、`memswap_limit=16g`。默认 `CODE_QUEUE_MAX_ACTIVE_QUEUES=0` 以恢复 queue 间并行,语义是不按 queue 数量设置全局 active run slot 上限,不是“常规 5、burst 10”的策略开关;当前能同时推进约 10 个 GPT-5.5 run 只应视为 15Gi cgroup 与 memory watchdog 下的实测运行边界。如需把常规 5 / burst 10 产品化,必须另行设计显式容量策略或把正数上限作为固定硬 cap 并补预算说明。执行面仍保持 `CODE_QUEUE_IN_MEMORY_OUTPUT_RECORDS=10`、`CODE_QUEUE_IN_MEMORY_EVENT_RECORDS=10` 这类小热窗口;任务历史、队列统计和 Trace/output 读取必须优先从 PostgreSQL 直读或聚合,执行面 `/health` 只做轻量 readiness,不能为了性能便利在 Bun 进程内缓存全量历史。任何提高 Code Queue 热窗口、日志缓冲、Playwright/Codex 子进程常驻规模或容器上限的变更,或把 `CODE_QUEUE_MAX_ACTIVE_QUEUES` 显式改成正数,都必须在同一任务里说明 D601 资源预算来源,并通过 D601 `KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n unidesk get deploy,svc,pod`、`kubectl -n unidesk top pod` 或等价 Docker stats、D601 scheduler health 和对应 E2E 证明未重新引入内存爆炸风险。D601 上的默认 `kubectl` context 可能不是 UniDesk 原生 k3s,不能替代该 kubeconfig 验证。 ## Database Connection Budget 主 PostgreSQL 的内存预算按“少量长驻服务连接池 + 短查询按需连接”设计,不允许每个 Bun 服务沿用默认 8 到 10 个连接。`backend-core` 默认 `DATABASE_POOL_MAX=4`,主 server 上的 `oa-event-flow`、`baidu-netdisk` 默认 `DATABASE_POOL_MAX=2`,`project-manager` 默认 `DATABASE_POOL_MAX=1`,`code-queue-mgr` 默认 `CODE_QUEUE_MGR_DATABASE_POOL_MAX=2` 与 `CODE_QUEUE_TRACE_DATABASE_POOL_MAX=1`,D601 `code-queue` 默认 `CODE_QUEUE_DATABASE_POOL_MAX=2`;如需提高任一连接池上限,必须同时说明并发 SQL 需求、验证 `pg_stat_activity` 中该服务没有长期 idle 堆积,并确认 `max_connections` 仍有足够余量。PostgreSQL 基础配置固定保守值:`shared_buffers=128MB`、`work_mem=4MB`、`maintenance_work_mem=64MB`、`max_connections=50`,避免主 server 低内存环境被空闲 backend 和过大的 per-query 内存预算挤占。 排查 PostgreSQL 内存时以 `docker stats unidesk-database`、`pg_stat_activity` 分组和 `pg_settings` 为准;主机 `ps` 中每个 `postgres` 进程的 RSS 会重复计入共享内存,不能把所有 backend RSS 简单相加当作真实容器占用。所有 UniDesk PostgreSQL 客户端都必须设置可识别的 `application_name`,便于按服务统计连接数、状态和慢查询归属。 ## Database Volume 架构要求数据库使用 15 GB 容量预算的 named volume;当前实现仍将 volume 命名为 `unidesk_pgdata_10gb` 以固定生命周期并避免创建空新卷。Docker named volume 默认不强制容量上限;如需硬配额,应在主机存储层或 Docker volume driver 层配置。CLI server 控制只能使用不删除 volume 的 `down` / `up` 流程,禁止使用 `down -v`、`docker volume rm` 或删除 `unidesk_pgdata_10gb`。 `/api/overview` 会返回 `pgdata` 字段,frontend `态势总览 / 核心指标` 必须展示当前 PostgreSQL 数据库占用、命名卷名称和配置容量。Docker 状态页中 `unidesk_pgdata_10gb` 的命名卷检测只对 `main-server` Provider 生效,其他计算节点不需要也不应被要求存在该数据库卷。