# D601 Dev Environment This document is the authoritative source for the persistent `unidesk-dev` environment, the public dev frontend port, `deploy apply --env dev`, and the Rust backend-core build boundary. If the same dev-environment rule would need edits in `AGENTS.md`, `docs/reference/cli.md`, `docs/reference/deploy.md`, `docs/reference/ci.md`, `docs/reference/deployment.md`, `docs/reference/e2e.md` or `TEST.md`, keep the detailed rule here and leave only a short cross-reference elsewhere. ## Goal The dev environment lets users experience the next UniDesk version without interrupting production: - Production stays on the normal public frontend at `http://74.48.78.17:18081/`. - Dev is exposed through a separate main-server public port at `http://74.48.78.17:18083/`. - Dev backend/frontend workloads run in D601 native k3s namespace `unidesk-dev`, not in the main-server Compose stack. - Dev backend/frontend build and rollout use pushed Git commits from `origin/master:deploy.json#environments.dev`, not dirty local worktrees. - Rust backend-core check/build must run on D601 through CI or dev deploy; the master server must not compile Rust for this iteration path. ## Public Dev Frontend Port The main server owns one extra public entrypoint for dev UI: ```text browser -> main-server:18083 -> dev-frontend-proxy -> prod backend-core microservice proxy -> k3sctl-adapter -> D601 k3s Service frontend-dev -> frontend-dev -> backend-core-dev ``` `dev-frontend-proxy` is an nginx sidecar in the main-server Compose project. It proxies requests to `backend-core:8080/api/microservices/k3sctl-adapter/proxy/api/services/frontend-dev/proxy...`, so D601 does not expose a new public port and the dev UI still crosses the existing UniDesk/k3sctl-adapter control boundary. The proxy is intentionally thin: it does not build frontend assets, does not talk to D601 directly, and does not contain DevOps logic. `frontend-dev` and `backend-core-dev` are registered with `k3sctl-adapter` through the managed-service catalog `src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k3s.json`. The public dev port must use that cataloged Kubernetes API service-proxy path; it must not add a direct D601 public port, NodePort, or backend-core catalog entry for arbitrary k3s services. The dev public port is configured in `config.json` as `network.devFrontend.port=18083`, surfaced by `server status` as `urls.devFrontend`, and managed by `server rebuild dev-frontend-proxy`. The proxy health depends on `frontend-dev`; it can be unhealthy until the D601 dev frontend has been deployed. The unrestricted public network entries are therefore production frontend, dev frontend, and provider ingress. backend-core REST, PostgreSQL, user-service backend ports, k3s Services, NodePorts and D601 host ports remain private or explicitly restricted. ## Desired State `deploy.json` remains the only version intent file. Dev entries live under `environments.dev` and are read from `origin/master:deploy.json`, never from a dirty local file, when using `--env dev` or `ci run-dev-e2e`. The persistent dev rollout currently supports only: - `backend-core` - `frontend` `code-queue` is present in `environments.dev.services` only so `ci run-dev-e2e` can build a Git-pinned Code Queue image and run a temporary namespace smoke. It is not part of persistent dev apply: `deploy apply --env dev --service code-queue` must still be rejected. Decision Center, k3sctl-adapter and other D601 services are not part of persistent dev apply yet. Their smoke validation stays under `ci run-dev-e2e` or service-specific future designs. The `environments.dev.ci` declaration and short launcher runner are owned by `docs/reference/dev-ci-runner.md`. ## Rust Backend-Core Boundary backend-core is implemented as a Rust service for the dev path. The master server may inspect files, run TypeScript CLI checks, render Compose config, dispatch jobs and proxy traffic, but it must not run Rust compilation for backend-core iteration. Allowed on the master server: - `bun scripts/cli.ts check --files --scripts-typecheck --compose --logs` - `bun scripts/cli.ts check --help` - `bun scripts/cli.ts deploy plan --env dev --service backend-core` - `bun scripts/cli.ts deploy apply --env dev --service backend-core` - `bun scripts/cli.ts ci run --revision ` - `bun scripts/cli.ts ci run-dev-e2e --wait-ms ` Not allowed on the master server for this path: - `cargo check`, `cargo build`, `cargo test` or `rustfmt` against backend-core. - `bun scripts/cli.ts check --rust` without the D601 CI guard. - `bun scripts/cli.ts server rebuild backend-core` as a way to iterate Rust backend-core, because it would build the Rust image in the main-server Docker daemon. - Ad-hoc `docker build` of `src/components/backend-core/Dockerfile` on the master server. Rust checking is enabled only when the process is already running inside the D601 CI/dev execution boundary: `UNIDESK_D601_RUST_CHECK=1 bun scripts/cli.ts check --full --rust`. `check --rust` deliberately fails outside that guard with an explicit explanation instead of silently compiling on the wrong host. ## Dev Deploy Path `deploy apply --env dev --service backend-core|frontend` is the controlled persistent dev rollout path. The controller runs on the master server, but the heavy work runs on D601: 1. Fetch `origin/master:deploy.json#environments.dev` and resolve the requested service commit to a full SHA. 2. Dispatch to D601 through the existing provider-gateway/Host SSH maintenance capability. 3. On D601, fetch/export the requested Git commit through the node-local provider-gateway egress proxy `http://127.0.0.1:18789`. 4. Use the target-side commit as the source for Dockerfile, build context and dev k3s manifest. 5. Build the service image on D601 Docker, importing any required base images through the same egress boundary. 6. Import the image into native k3s containerd at `/run/k3s/containerd/containerd.sock`. 7. Apply only the selected `unidesk-dev` Service/Deployment objects from the dev manifest. 8. Stamp the Deployment with `UNIDESK_DEPLOY_*` env and `unidesk.ai/deploy-*` annotations. 9. Verify health through the Kubernetes API service proxy and require the live commit to match the requested commit. The dev path is not a fallback system. If GitHub fetch, provider-gateway egress, Docker build, native k3s, containerd import, kubectl apply or live health verification fails, the job fails with logs. It must not fall back to building on the master server, using a dirty worktree, direct D601 public ports, NodePort, or another deployment command. ## DevOps Hygiene The persistent dev environment follows the shared Git-backed deployment hygiene rules in `docs/reference/devops-hygiene.md`. In particular, D601 runtime edits, dirty-worktree builds, copied scripts/images/source, direct D601 ports, NodePorts and manual smoke checks without live commit agreement must not become deployment truth. ## Standard Workflow Use this sequence for backend-core Rust and frontend dev work: 1. Develop in the current `master` worktree and keep unrelated parallel changes separated with `git status`/`git diff`. 2. Run local non-Rust checks on the master server, for example `bun scripts/cli.ts check --files --scripts-typecheck --compose --logs`. 3. Commit and push the code to `origin master`; `deploy apply --env dev` cannot deploy unpushed local changes. 4. Update `deploy.json` `environments.dev.services` so `backend-core` and `frontend` point at the pushed commit, then commit and push that manifest update. 5. Run `bun scripts/cli.ts deploy apply --env dev --service backend-core` and observe the returned job with `bun scripts/cli.ts job status --tail-bytes 30000`. 6. Run `bun scripts/cli.ts deploy apply --env dev --service frontend` and observe the job the same way. 7. If the dev service catalog changes, deploy the pushed `k3sctl-adapter` commit through the controlled local manifest exception, then verify `/api/control-plane` lists `k3s/dev/unidesk-dev-core.k3s.json`. 8. Rebuild or verify `dev-frontend-proxy` on the main server with `bun scripts/cli.ts server rebuild dev-frontend-proxy` when the proxy config or port changes. 9. Manually test `http://74.48.78.17:18083/` and the dev health endpoints. 10. Run D601 CI for the commit and the dev smoke runner: `bun scripts/cli.ts ci run --revision --wait-ms ` and `bun scripts/cli.ts ci run-dev-e2e --wait-ms `. When Code Queue behavior changes, update the `code-queue` entry in `environments.dev.services` to the pushed commit before running the dev smoke; do not use `deploy apply --env dev --service code-queue`. ## Validation Commands Useful read-only or bounded validation commands: ```bash bun scripts/cli.ts server status bun scripts/cli.ts deploy plan --env dev bun scripts/cli.ts deploy plan --env dev --service backend-core bun scripts/cli.ts dev-env validate --manifest src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-core.k8s.yaml bun scripts/cli.ts dev-env validate --manifest src/components/microservices/k3sctl-adapter/k3s/dev/unidesk-dev-code-queue.k8s.yaml bun scripts/cli.ts ci run-dev-e2e --wait-ms 600000 bun scripts/cli.ts microservice proxy k3sctl-adapter /api/services/backend-core-dev/proxy/health --raw --full bun scripts/cli.ts microservice proxy k3sctl-adapter /api/services/frontend-dev/proxy/health --raw --full curl -fsS http://127.0.0.1:18083/health ``` When validating on D601 directly, always use the native kubeconfig explicitly: `KUBECONFIG=/etc/rancher/k3s/k3s.yaml`. The default `kubectl` context may point at Docker Desktop and is not valid for UniDesk native k3s verification.