Files
pikasTech-unidesk/docs/reference/cicd-standardization.md
T
2026-05-21 10:02:45 +00:00

49 KiB

CI/CD Standardization

This document defines the stable split between CI artifact producers, artifact catalog data, legacy guardrails and CD consumers. Detailed Tekton rules remain in docs/reference/ci.md; registry runtime and consumers remain in docs/reference/artifact-registry.md; user-service delivery order remains in docs/reference/user-service-delivery.md.

Target Shape

The standard release shape is:

  1. CI builds or locks the artifact from a pushed commit or verified upstream digest.
  2. The artifact is published to the D601 artifact registry or a controlled mirror.
  3. Dev validation consumes that same artifact.
  4. Production CD is pull-only and verifies live commit or upstream digest.
  5. Runtime metadata can be traced back to a live Git commit or upstream image digest.

backend-core and D601 code-queue may be validated only in dev in this phase. This document must not be used to introduce production deploy validation for either service.

Artifact Catalog

Root CI.json is the CI producer catalog. It is not a deployment manifest.

Allowed catalog data:

  • stable serviceId;
  • artifact kind: source-build or upstream-image;
  • producer command: ci publish-backend-core or ci publish-user-service;
  • source repository URL, optional repo root and repo-relative Dockerfile path;
  • image repository naming and commit tag policy;
  • upstream image digest, upstream source revision and D601 mirror intent for image-only services;
  • the required success summary contract.

Forbidden catalog data:

  • provider IDs;
  • runtime namespace, Compose service, Kubernetes Service or health path;
  • ports, environment variables, replicas or volumes;
  • desired deployment commits or rollout targets.

Runtime topology belongs to config.json, deploy.json, existing Kubernetes manifests and the artifact-registry executor.

Producer Contract

bun scripts/cli.ts ci publish-user-service --service <id> --commit <full-sha> reads source.repo, source.dockerfile and image repository naming from CI.json. It rejects command-line repo overrides. Successful source-build producers must label the image with:

  • unidesk.ai/service-id;
  • unidesk.ai/source-commit;
  • unidesk.ai/source-repo;
  • unidesk.ai/dockerfile.

The successful artifactSummary must contain serviceId, sourceCommit, sourceRepo, dockerfile, imageRef, tag, digest and digestRef.

blocked catalog entries must return a structured blocked result. They must not silently skip, build from a dirty worktree, fall back to target-side maintenance deployment, or mutate production.

Current Coverage

Supported source-build artifact producers:

  • backend-core through ci publish-backend-core;
  • frontend, baidu-netdisk, decision-center, project-manager, oa-event-flow, todo-note, code-queue-mgr, findjob, pipeline, met-nonlinear, k3sctl-adapter, mdtodo, claudeqq through ci publish-user-service;
  • code-queue through ci publish-user-service for dev image validation only.

Cataloged but blocked:

  • filebrowser and filebrowser-d601: upstream image-only services pinned to docker.io/filebrowser/filebrowser@sha256:289c5dd677c56662440f26eeb44266ed9746fe563d2e9100f546bff558534d70; they need a future upstream mirror producer before CI can publish them.

code-queue-mgr is a supported CI producer because the source-build input is known and the remote consumer commit already added a reviewed artifact consumer shape. Its production live apply remains supervisor-gated by deploy/artifact-registry and is not authorized by CI.json.

Main-Server Compose User Services

Main-server Compose user services are normal source-build artifacts even though their runtime lives on the master server. CI builds them on D601, publishes a commit-pinned image to the D601 registry, and CD streams that artifact back to the master-server Compose project. The runtime target must not build source, use a dirty worktree, expose the service port publicly, or use server rebuild <service> as release truth.

Service Producer Artifact Consumer Dev validation Prod validation Blocker
baidu-netdisk ci publish-user-service --service baidu-netdisk from src/components/microservices/baidu-netdisk/Dockerfile 127.0.0.1:5000/unidesk/baidu-netdisk:<commit> master-server Compose service baidu-netdisk, container baidu-netdisk-backend deploy plan/apply --env dev --service baidu-netdisk consumes the registry artifact and verifies labels plus health; dry-run is acceptable while the artifact or registry is absent deploy plan/apply --env prod --service baidu-netdisk recreates only baidu-netdisk with --no-build --no-deps --force-recreate, then verifies image labels, /health.deploy.commit, requested commit and auth health D601 registry artifact must exist; live apply also requires non-empty Baidu client id, client secret and token key plus logged-in auth health
project-manager ci publish-user-service --service project-manager from src/components/microservices/project-manager/Dockerfile 127.0.0.1:5000/unidesk/project-manager:<commit> master-server Compose service project-manager, container project-manager-backend deploy plan/apply --env dev --service project-manager consumes the registry artifact and verifies labels plus health; dry-run is acceptable while the artifact or registry is absent deploy plan/apply --env prod --service project-manager recreates only project-manager with --no-build --no-deps --force-recreate, then verifies image labels, /health.deploy.commit and requested commit D601 registry artifact must exist before live dev or prod apply

Focused smoke for this class is intentionally narrow: health, running image labels/digest, live deploy.commit / deploy.requestedCommit, and one private proxy API check such as baidu-netdisk /api/transfers?limit=20 or project-manager /api/projects. Full e2e, Playwright, broad check, public-port probing and unrelated service restarts are outside this lane.

Upstream Image Consumers

filebrowser and filebrowser-d601 are upstream-image consumers, not source-built UniDesk services.

Service Upstream image Source revision Catalog home CI Dockerfile build Digest / mirror strategy CD validation
filebrowser docker.io/filebrowser/filebrowser:v2.63.3 ca5e249e3c0c94159c2136a0cd431a424eb18472 CI.json.artifacts[] with kind=upstream-image plus config.json.microservices[].repository.artifactSource forbidden resolve tag to docker.io/filebrowser/filebrowser@sha256:<manifest-digest>, then optionally mirror to 127.0.0.1:5000/upstream/filebrowser/filebrowser@sha256:<manifest-digest> pull by digest or mirror digest, verify OCI labels, container image id/digest, and private proxy health
filebrowser-d601 docker.io/filebrowser/filebrowser:v2.63.3 ca5e249e3c0c94159c2136a0cd431a424eb18472 CI.json.artifacts[] with kind=upstream-image plus config.json.microservices[].repository.artifactSource forbidden same as filebrowser same as filebrowser

The catalog records the resolved upstream digest for the current image. If a future tag refresh cannot resolve the registry manifest digest, rollout must remain blocked until a reachable registry path resolves the manifest digest and records the mirror digest. A local Docker image id is supporting evidence only and not a registry digest pin.

D601 Direct Services

D601 direct / host-managed services keep runtime ownership outside native k3s. Their standard path is still the artifact split: CI builds a commit-pinned image on D601, CD on D601 only checks the registry manifest, pulls or retags the artifact, recreates the existing Compose service with --no-build --no-deps --force-recreate, and verifies image labels plus service health. The provider-gateway/SSH path is a controlled maintenance bridge for those D601-local actions, not a target-side build standard and not a new public ingress.

Service Producer Consumer Dev validation Prod validation Blocker
findjob ci publish-user-service --service findjob builds Dockerfile from https://gitee.com/Lyon1998/findjob into unidesk/findjob:<commit> D601 direct Compose artifact consumer, service server, container findjob-server deploy apply --env dev --service findjob --dry-run plans pull-only CD and live apply is allowed when the artifact exists deploy apply --env prod --service findjob --dry-run plans the same path; prod live apply is allowed by policy health does not report deploy commit, so strict commit proof relies on image and container labels plus /api/health
pipeline ci publish-user-service --service pipeline builds Dockerfile from https://github.com/pikasTech/pipeline into unidesk/pipeline:<commit> D601 direct Compose artifact consumer, service pipeline-control, container pipeline-v2-control deploy apply --env dev --service pipeline --dry-run plans pull-only CD and live apply is allowed when the artifact exists deploy apply --env prod --service pipeline --dry-run plans the same path; prod live apply is allowed by policy health does not report deploy commit, so strict commit proof relies on image and container labels plus /health
met-nonlinear ci publish-user-service --service met-nonlinear builds docker/unidesk/Dockerfile.ml from https://github.com/pikasTech/met_nonlinear into unidesk/met-nonlinear:<commit> D601 direct Compose dry-run contract for service met-nonlinear-ts deploy apply --env dev --service met-nonlinear --dry-run returns runtime-verification-blocked until the runtime image contract is fixed deploy apply --env prod --service met-nonlinear --dry-run returns runtime-verification-blocked; live prod apply is unsupported catalog Dockerfile is the ML image while the long-running service is met-nonlinear-ts; publish a labeled artifact for the running TS service or separate the server Dockerfile contract
k3sctl-adapter ci publish-user-service --service k3sctl-adapter builds src/components/microservices/k3sctl-adapter/Dockerfile from UniDesk into unidesk/k3sctl-adapter:<commit> D601 direct Compose plan/dry-run for service k3sctl-adapter, container k3sctl-adapter no normal dev target; it is the control bridge for dev/prod k3s visibility deploy apply --env prod --service k3sctl-adapter --dry-run exposes the pull-only contract; live prod apply is supervisor-only must remain outside the k3s failure domain and be recoverable before any live replacement; worker automation must not replace it without explicit supervisor confirmation
filebrowser-d601 no UniDesk source-build producer; CI.json marks it upstream-image/blocked future pull-only upstream digest or D601 mirror digest consumer only not implemented not implemented must not be represented as a Dockerfile build; first implement upstream digest resolution and mirror governance for docker.io/filebrowser/filebrowser:v2.63.3

findjob, pipeline and met-nonlinear deliberately do not create NodePort, hostPort or new public business ports. Runtime traffic stays behind backend-core, provider-gateway and the configured private service proxy. k3sctl-adapter is a control bridge, not an ordinary business service; it must be versioned, dry-run verifiable and manually recoverable before live replacement.

D601 Lane C Closure Matrix

This matrix is the single review surface for the remaining D601 service lane. It separates execution-plane ownership, control-plane ownership, CI artifact production, CD consumption and acceptance scope. All commands listed here are non-mutating unless they explicitly say live apply; Code Queue live apply is limited to dev and must not be performed by a running Code Queue task.

Service Deployment / ownership CI current state CD current state DEV acceptance PROD acceptance Blockers Next task
findjob D601 unidesk-direct execution service in Docker Compose; control path is backend-core -> provider-gateway private HTTP proxy -> D601 loopback /api/health. CI.json source-build supported through ci publish-user-service --service findjob; artifact is 127.0.0.1:5000/unidesk/findjob:<commit> from the external Gitee repo Dockerfile. Reviewed D601 direct Compose artifact consumer for service server / container findjob-server; CD is pull-only, retag, docker compose up -d --no-build --no-deps --force-recreate server, then label and health verification. Allowed after deploy apply --env dev --service findjob --dry-run plus a matching registry artifact; live dev apply is permitted by policy. Allowed after deploy apply --env prod --service findjob --dry-run plus artifact/operator review; no public port or target-side build. /api/health does not report deploy commit, so strict proof depends on image/container labels plus health. Registry health and artifact existence are required before live apply. Add or upstream a deploy metadata field in health; keep label-based proof as the minimum contract until that lands.
pipeline D601 unidesk-direct execution service in Docker Compose; control path is backend-core -> provider-gateway private HTTP proxy -> D601 loopback /health and /api/ / /oa/. CI.json source-build supported through ci publish-user-service --service pipeline; artifact is 127.0.0.1:5000/unidesk/pipeline:<commit> from the external GitHub repo Dockerfile. Reviewed D601 direct Compose artifact consumer for service pipeline-control / container pipeline-v2-control; CD is pull-only, retag, docker compose up -d --no-build --no-deps --force-recreate pipeline-control, then label and health verification. Allowed after deploy apply --env dev --service pipeline --dry-run plus a matching registry artifact; live dev apply is permitted by policy. Allowed after deploy apply --env prod --service pipeline --dry-run plus artifact/operator review; no public port or target-side build. /health does not report deploy commit, so strict proof depends on image/container labels plus health. Registry health and artifact existence are required before live apply. Add health deploy metadata and keep OA Event Flow integration checks as a focused post-apply smoke.
met-nonlinear D601 unidesk-direct GPU/business execution service in Docker Compose; control path is backend-core -> provider-gateway private HTTP proxy -> D601 loopback /health and /api/. CI.json source-build supported through ci publish-user-service --service met-nonlinear; cataloged artifact uses docker/unidesk/Dockerfile.ml from https://github.com/pikasTech/met_nonlinear. D601 direct Compose consumer is plan/dry-run only for service/container met-nonlinear-ts; dry-run exposes the no-build pull-only shape but returns runtime-verification-blocked. Dry-run/read-only only. deploy apply --env dev --service met-nonlinear --dry-run must remain blocked until the running service image contract matches the published artifact. Not authorized. Prod dry-run must remain runtime-verification-blocked; live prod apply is unsupported. Published artifact is the ML image contract while the long-running service is met-nonlinear-ts, so CD cannot prove the running container image label equals the requested commit. Split the TS server artifact from the ML image or publish a labeled artifact that exactly matches met-nonlinear-ts; then add live commit proof before enabling apply.
k3sctl-adapter UniDesk-managed D601 direct Compose control bridge, outside the native k3s fault domain; it is the control path for k3s-managed services and must not be moved into k3s. CI.json source-build supported through ci publish-user-service --service k3sctl-adapter; artifact is 127.0.0.1:5000/unidesk/k3sctl-adapter:<commit> from the UniDesk Dockerfile. Artifact consumer exposes plan/dry-run only for service/container k3sctl-adapter; live replacement is supervisor-only because replacing the bridge can remove the repair path for k3s. No normal dev target. DEV acceptance is read-only bridge health, service catalog/proxy checks and dry-run contract review only. Dry-run/read-only only in this lane. Real prod replacement requires explicit supervisor confirmation, rollback proof and out-of-band recovery access. Must remain recoverable while k3s may be broken; worker automation must not self-replace or k3s-manage the bridge. Write a supervised bridge-upgrade runbook with rollback and out-of-band access checks; keep CLI dry-run as the standard preflight.
code-queue Production execution plane is D601 native k3s (unidesk namespace) behind k3sctl-adapter; dev execution plane is unidesk-dev scheduler/read/write/provider-egress-proxy. Main-server code-queue-mgr is a separate control-plane sidecar. CI.json source-build supported through ci publish-user-service --service code-queue for dev image validation only; artifact is 127.0.0.1:5000/unidesk/code-queue:<commit>. Reviewed dev-only k3s artifact consumer updates only unidesk-dev Code Queue objects. deploy plan --env prod --service code-queue and artifact-registry deploy-service --env prod --service code-queue must stay unsupported. Allowed only as dry-run/source/contract evidence here; a later human-approved dev live apply may consume the artifact into unidesk-dev outside the running Code Queue task. Not implemented and not authorized. No production artifact deploy, manifest mutation, scheduler/runner restart, interrupt or cancel is allowed. Production still has hostPath/source and active-run safety boundaries; self-deploy would couple the deployment actor to the target being replaced. Keep contract tests and dev dry-run coverage; design a separate supervisor-approved production CD consumer before any prod mutation is considered.

Minimum evidence for this lane is:

Evidence Command
Code Queue dev/prod boundary contract bun scripts/code-queue-cicd-dry-run-contract-test.ts
Code Queue dev target shape bun scripts/cli.ts deploy plan --env dev --service code-queue
Code Queue prod unsupported shape bun scripts/cli.ts deploy plan --env prod --service code-queue
D601 direct Compose dry-run for findjob / pipeline `bun scripts/cli.ts deploy apply --env dev --service <findjob
MET Nonlinear blocked dry-run bun scripts/cli.ts deploy apply --env dev --service met-nonlinear --dry-run
k3s control bridge dry-run bun scripts/cli.ts deploy apply --env prod --service k3sctl-adapter --dry-run
CI producer preflight bun scripts/cli.ts ci publish-user-service --service <service> --commit <full-sha> --dry-run

Upstream Image Evidence

The catalog expression is intentionally minimal and parseable:

Evidence command Required result shape
`jq '.artifacts[] select(.kind=="upstream-image")
bun scripts/cli.ts config show with the File Browser artifactSource projection both services parse as kind=upstream-image, digestPinRequired=true, mirrorRepository=127.0.0.1:5000/upstream/filebrowser/filebrowser, ciDockerfileBuild=false, and pullOnlyCd=true
docker manifest inspect --verbose docker.io/filebrowser/filebrowser:v2.63.3 must resolve the upstream manifest digest before rollout; if the registry request times out, rollout remains blocked
bun scripts/cli.ts ci publish-user-service --service filebrowser --commit <full-sha> --dry-run returns ok=false with status=blocked, upstream digest/mirror metadata, and no Dockerfile source build

The digest/mirror dry-run contract is:

  1. Resolve docker.io/filebrowser/filebrowser:v2.63.3 to docker.io/filebrowser/filebrowser@sha256:<manifest-digest>.
  2. Mirror only that resolved digest to 127.0.0.1:5000/upstream/filebrowser/filebrowser@sha256:<manifest-digest>.
  3. Record the digest ref used by CD; do not promote a mutable tag as release truth.
  4. Refuse pull-only CD while the digest is unknown or the mirror digest differs from the upstream digest.

Pull-only CD validation must be expressed as concrete checks:

Check Form
Pull source docker pull docker.io/filebrowser/filebrowser@sha256:<manifest-digest> or docker pull 127.0.0.1:5000/upstream/filebrowser/filebrowser@sha256:<manifest-digest>
Runtime identity docker inspect reports the expected image id/digest and OCI labels org.opencontainers.image.version=2.63.3 and org.opencontainers.image.revision=ca5e249e3c0c94159c2136a0cd431a424eb18472
Service health UniDesk private proxy health succeeds for filebrowser and filebrowser-d601; direct public exposure remains forbidden
Build absence no docker build, docker compose up --build, CI Dockerfile producer, or source checkout is used for these services

Frozen Special-Case Inventory

This table freezes the boundary between standard artifact services, upstream image consumers, bootstrap or maintenance paths, unclear manual-risk paths, and legacy paths that may be removed only after replacement evidence exists.

Object Classification Current Path Target Path Cleanup Prerequisites Risk If Misclassified Next Stage / Remove Later
filebrowser upstream-digest config.json registers D518 unidesk-direct with repository.dockerfile=docker.io/filebrowser/filebrowser:v2.63.3, artifactSource.kind=upstream-image, and provider-local docker run --restart unless-stopped. CI.json marks it blocked from source-build CI. Pull-only upstream image consumer: resolve docker.io/filebrowser/filebrowser:v2.63.3 to a manifest digest, optionally mirror that digest to D601 registry, run by digest, then verify image identity and private proxy health. Implement upstream digest resolver/mirror worker, record mirror digest, add container image-id/digest validation, preserve File Browser state paths and rollback runbook. Treating it as source-build would build the wrong artifact; deleting the docker-run repair path before pull-only CD exists can break D518 file access. Do not delete in the next stage; implement digest/mirror CD first.
filebrowser-d601 upstream-digest Same upstream image and blocked CI catalog as filebrowser, but provider-local container is unidesk-filebrowser-d601 on D601. Same pull-only digest or mirror digest model as filebrowser, scoped to D601. Same digest/mirror worker and runtime verification, plus D601 path/volume audit. Same source-build confusion; premature cleanup can remove D601 file access used by operations. Do not delete in the next stage; implement with filebrowser.
database upstream-digest Main-server Compose service uses postgres:16-alpine, named volume unidesk_pgdata_10gb, init SQL, and pinned config files. It is lifecycle-managed by server start/server stop, not by server rebuild. Upstream digest pin or mirror for PostgreSQL image; Compose remains volume-preserving and pull-only for the image. Digest pin for postgres:16-alpine, database backup/restore drill, major-version upgrade policy, and no down -v or volume deletion. Data loss or unplanned PostgreSQL upgrade; a source-build model is meaningless for this service. Keep; never remove as legacy.
provider-gateway bootstrap-keep Main-server Compose server rebuild provider-gateway and provider provider.upgrade mode=schedule can repair the control bridge. Host SSH keys are mounted read-only for maintenance, while normal automation uses WebSocket/provider tasks. Standard source artifact publication for normal releases plus retained protected self-upgrade/repair path; Host SSH remains explicit maintenance only. Prove provider-gateway artifact consumer or protected upgrade can recover a broken provider without SSH session lifetime coupling; keep Docker socket scope and loopback egress checks. Removing the bridge repair path can strand providers and block CD, diagnostics, or registry relay. Keep; not removable next stage.
dev-frontend-proxy bootstrap-keep Main-server Compose service built from src/components/dev-frontend-proxy/Dockerfile, exposed on the dev frontend port, and rebuildable by server rebuild dev-frontend-proxy. Small bootstrap proxy kept as a main-server support service; optional future source artifact only after dev frontend proxy health and D601 dev UI rollout are covered. Decide whether the proxy should become a standard artifact, add CI image and pull-only consumer if yes, and preserve dev UI recovery. Deleting it breaks the public dev UI path even when production is healthy. Keep; not removable next stage.
server rebuild backend-core bootstrap-keep Local main-server Compose build/recreate, serialized by Compose lock and validated after up. Docs forbid using it for Rust iteration or standard prod CD. Recovery-only path; standard production path is D601 CI artifact plus deploy apply --env prod --service backend-core. Backend-core artifact CD rollback proven under outage conditions; recovery runbook can repair a broken core without local Rust build. Removing too early can block recovery when core or registry relay is degraded. Keep; not removable next stage.
server rebuild frontend bootstrap-keep Local main-server Compose build/recreate for production frontend; maintenance-only and not release evidence. Standard frontend release is CI unidesk/frontend:<commit> plus dev/prod artifact consumer and health/image-label verification. Equivalent pull-only repair command, registry rollback, and frontend health verification runbook. Local dirty bundle can become accidental production truth; deleting too early removes emergency UI repair. Keep for now; degrade only after pull-only repair is proven.
server rebuild baidu-netdisk bootstrap-keep Local main-server Compose build/recreate for Baidu Netdisk; maintenance-only. D601 CI source-build artifact plus dev/prod pull-only consumer. Pull-only repair and token/staging persistence validation. Dirty rebuild can hide token/staging regressions; premature deletion can block storage service repair. Keep for now; degrade after pull-only repair is proven.
server rebuild todo-note, code-queue-mgr, project-manager, oa-event-flow bootstrap-keep Local main-server Compose rebuild for internal or direct main-server services; some have artifact consumer validation, while live prod apply may remain gated. Convert each to CI artifact plus pull-only consumer and live health commit verification where supported; keep recovery entry until equivalent repair exists. Per-service artifact consumer, runtime deploy metadata, rollback, and persistence validation. Dirty local rebuilds can bypass deploy.json; deleting before rollback can break main-server service recovery. Keep; reassess service by service.
server rebuild provider-gateway bootstrap-keep Local Compose rebuild for the main-server provider gateway. Keep as bridge repair; normal upgrades should use protected provider upgrade or artifact path when available. Same provider-gateway recovery proof as above. May strand host-level observability and maintenance dispatch. Keep.
server rebuild filebrowser*, database, code-queue, k3sctl-adapter, unknown services allowed-remove-later for silent fallback only Historically the CLI threw a generic usage error; no valid main-server Compose rebuild exists for these objects. Structured unsupported-server-rebuild result; no job creation, no source build, no Compose mutation. Operators must use documented upstream digest, k3s artifact, bridge repair, or manual-risk path instead. Generic errors can lead operators to invent hand-built fallback commands. Silent/generic fallback is removed; do not delete the real upstream/bootstrap runtime paths.
deploy apply --env prod unsupported services needs-manual Environment-ref prod apply reads origin/master:deploy.json; services without reviewed prod artifact consumers return structured unsupported. Add service-specific CI producer, D601 registry artifact, prod consumer, and live commit/digest verification before enabling. Silent target-side builds would bypass registry, dirty-worktree, and live verification guardrails. Not removable as a class; enable per service only after review.
Local-manifest deploy apply --file ... for reviewed prod artifact consumers allowed-remove-later CLI blocks reviewed prod artifact consumers before source materialization and points to deploy apply --env prod --service <id>. Environment-ref deploy and artifact consumer only for standard production. Confirm no recovery runbook requires local-manifest prod apply; provide rollback via registry. Dirty local deploy.json or target-side source build can become production truth. Allow removing or further degrading after recovery runbooks move to env-ref artifacts.
D601 target-side build path for dev backend-core allowed-remove-later Replaced by deploy apply --env dev --service backend-core artifact consumer, which imports 127.0.0.1:5000/unidesk/backend-core:<commit> into unidesk-dev/backend-core-dev without compiling. Keep only structured no-build artifact consumer; remove stale target-side callers/docs. D601 CI artifact publication, dev consumer, Rust check/build parity, and rollback evidence. Any fallback rebuild could bypass the CI artifact and hide Rust build failures. Legacy path is no longer the standard dev route.
D601 maintenance-channel direct deploy for non-bridge services allowed-remove-later Direct provider host.ssh build/apply is blocked for normal D601 services; codex deploy is disabled. Only artifact consumers or reviewed native bootstrap may mutate D601 services. Confirm no supported runbook still calls the disabled path; keep structured unsupported output. A second deploy control plane can bypass registry artifacts and k3s verification. Remove stale callers/docs after no references remain.
artifact-registry deploy-backend-core allowed-remove-later Compatibility name returns a structured deprecated result; replacement is `deploy apply --env dev prod --service backend-core`. Use only deploy reconciler entry for backend-core CD. All callers and docs stop using the compatibility action. Bypasses common deploy guardrails if re-enabled casually.
k3sctl-adapter bootstrap-keep D601 direct Compose control bridge outside k3s; artifact consumer is plan/dry-run only and live prod apply needs supervisor confirmation. Keep outside the k3s fault domain; optionally publish artifact for controlled upgrade, but retain bridge repair. Supervisor-approved live upgrade path, adapter health/control-plane validation, and rollback without losing Kubernetes access. Removing or moving it into k3s can remove the bridge needed to repair k3s. Keep; not removable next stage.
Maintenance SSH / manual Docker / manual k3s commands needs-manual Available through provider-gateway Host SSH, WSL SSH, manual Docker, and native k3s commands for repair and investigation. Explicit maintenance-only runbooks with bounded commands, no silent source builds, no dirty worktree release truth, and no default CD fallback. For each manual entry, document owner, trigger, rollback, volume/scope safety, and replacement artifact path. Manual state can become undocumented production truth or destroy bootstrap access if over-cleaned. Do not delete globally; constrain and document per path.
Dirty worktree, mutable latest tag, hand-mutated container state allowed-remove-later as release truth These may exist as local operator state or Docker cache, but they are not valid deployment evidence. Standard releases use deploy.json commit, commit-tagged or digest-pinned images, image labels, and live commit/digest verification. Runtime label checks, digest pins, env-ref deploy, and runbooks that reject latest and dirty worktree inputs. Reproducibility and rollback are lost; a healthy old or hand-built container may be accepted accidentally. Remove as accepted release evidence; keep only as diagnostic observations.

Legacy Path Classification

Path Classification Current guardrail Cleanup condition
deploy apply --env prod for services without a reviewed artifact consumer Must stay disabled/degraded returns structured unsupported and refuses maintenance-channel fallback enable only after each service has a documented artifact producer, dev consumer, prod consumer and live verification
Local-manifest deploy apply for prod artifact consumers (backend-core, frontend, baidu-netdisk, decision-center) Must stay disabled/degraded as a standard prod path blocked before source build; operator is pointed to deploy apply --env prod remove only after all production deploys use env-ref artifact consumers and no recovery runbook depends on local manifests
artifact-registry deploy-backend-core Legacy compatibility entry returns structured deprecated result; replacement is `deploy apply --env dev prod --service backend-core`
server rebuild frontend and server rebuild baidu-netdisk Maintenance / non-standard docs classify as maintenance-only; standard release requires CI artifact plus dev/prod artifact consumer keep until recovery runbooks have equivalent pull-only repair commands
server rebuild backend-core Diagnostic/recovery only; not Rust iteration or prod CD docs forbid Rust iteration and prod backend-core artifact CD through this command keep for bootstrap/recovery until backend-core artifact CD and rollback are proven under outage conditions
server rebuild dev-frontend-proxy, code-queue-mgr, project-manager, oa-event-flow, todo-note, provider-gateway on main-server Compose Bootstrap / recovery / diagnostic still serialized through Compose lock and post-up validation reassess service by service after artifact consumers exist
provider.upgrade mode=schedule for provider-gateway Must be retained protected upgrade path with validation; Host SSH self-rebuild remains forbidden do not delete; it is the provider-gateway recovery path
D601 direct docker build, kubectl apply, docker compose up --build used by deploy executor for native k3s setup or approved recovery Bootstrap / recovery limited to native k3s initialization or documented recovery; dev backend-core CD is now artifact-only; Code Queue prod is not enabled convert only after artifact consumers or native bootstrap replacements exist
D601 direct Code Queue / old codex deploy Must stay disabled/degraded compatibility command throws; docs classify direct deployment as forbidden wait for controlled Code Queue dev/prod CD worker
File Browser docker run image-only path Needs later worker now cataloged as upstream-image consumer; no CI Dockerfile build allowed implement digest-resolved pull-only/mirror CD before treating it as standard deployment

Guardrails Added

  • Upstream-image services are represented in CI.json.artifacts[] with kind=upstream-image and in config.json.microservices[].repository.artifactSource; they are explicitly outside source-build producers.
  • ci publish-user-service returns a structured blocked result for registered upstream-image services instead of trying to interpret repository.dockerfile as a source Dockerfile.
  • Local-manifest production deploy for reviewed artifact consumers is blocked before source materialization/build, so prod cannot silently fall back to target-side source build or a dirty worktree.
  • artifact-registry deploy-backend-core is demoted to a structured deprecated result; backend-core production CD must enter through deploy apply --env prod.
  • server rebuild returns unsupported-server-rebuild for upstream image consumers, database, D601 execution/control-plane objects and unknown services; it does not create a job or mutate Compose for those objects.

Guardrail Evidence Matrix

Guardrail name / result key Command evidence Legacy path covered Deletion status
upstream-image CI publish rejection bun scripts/cli.ts ci publish-user-service --service filebrowser --commit <full-sha> --dry-run returns ok=false, status=blocked, and upstream metadata File Browser accidentally entering Dockerfile CI keep; deletion of docker-run repair waits for digest/mirror CD
prod-artifact-consumer-local-manifest-blocked bun scripts/cli.ts deploy apply --file deploy.json --service frontend --dry-run returns ok=false, this error key, and points to deploy apply --env prod --service <service-id> --commit <full-sha> prod source-build fallback for reviewed artifact consumers keep; local manifest mode may still be needed for non-prod/recovery until runbooks are replaced
artifact-registry deploy-backend-core deprecated result bun scripts/cli.ts artifact-registry deploy-backend-core --commit <full-sha> returns ok=false, deprecated=true, and replacement deploy apply --env prod --service backend-core --commit <full-sha> backend-core prod CD bypassing deploy reconciler guardrails keep name only as compatibility until all callers stop using it
prod unsupported result for services without artifact consumers deploy apply --env prod --service <unsupported-service> --dry-run must return unsupported instead of falling back to source build target-side source build/maintenance-channel prod deploy keep disabled until service-specific artifact consumers exist
unsupported-server-rebuild bun scripts/cli.ts server rebuild filebrowser and bun scripts/cli.ts server rebuild database return ok=false, error=unsupported-server-rebuild, classification, replacement path and allowed services accidental source-build/Compose fallback for upstream images, database, k3s/control bridges and unknown services keep; it removes only silent/generic fallback, not bootstrap or maintenance runtime paths
backend-core/code-queue prod boundary docs and deploy support matrix allow backend-core and D601 Code Queue only in dev validation for this phase accidental prod validation entrypoints for backend-core or Code Queue do not add executable prod test/deploy validation in this precheck

The guarded-but-not-deletable paths are: server rebuild backend-core, server rebuild frontend, server rebuild baidu-netdisk, provider-gateway protected upgrade, native k3s bootstrap, k3sctl-adapter bridge repair, and File Browser provider-local docker-run repair. Dev backend-core target-side rollout is no longer a standard guarded path; its replacement is the D601 registry artifact consumer, and stale target-side callers/docs should be removed once no runbook references remain.

Safety Boundary

CI may build images, push to the D601 loopback registry and report immutable digests. CI must not run production CD, call deploy apply for production, mutate production namespaces, recreate production Compose services or update deploy.json.

backend-core now has explicit dev/prod artifact consumers; CI still only produces the image and must not deploy it as a side effect. D601 code-queue remains restricted to dev image validation in this phase. Any future production rollout for Code Queue must be implemented as an explicit CD consumer change, not as a CI producer side effect.

Code Queue Dry-Run Delivery Boundary

Code Queue follows the standard artifact split only up to a dev-only consumer:

Stage Owner Allowed output Explicitly forbidden
CI producer Tekton / CI runner outside Code Queue self-deploy Build from pushed Git, publish 127.0.0.1:5000/unidesk/code-queue:<commit>, report service id, source repo, source commit, Dockerfile, tag, digest and digest ref deploy apply, kubectl apply, scheduler/read/write rollout, task interrupt or cancel
CD dry-run deploy/artifact-registry CLI Read origin/master:deploy.json, show unidesk-dev target objects, required registry image, no-runtime-build validation and forbidden actions Mutating runtime objects, using dirty worktrees, using mutable tags, falling back to codex deploy or D601 maintenance-channel source deploy
DEV live apply Human operator after dry-run evidence Pull/import the existing commit image, update only unidesk-dev Code Queue scheduler/read/write/provider-egress-proxy objects, verify health through the Kubernetes API service proxy Touching production unidesk namespace, production PostgreSQL, production scheduler/runner, running task state or Code Queue Manager prod sidecar
PROD Not implemented Structured unsupported / dry-run evidence only Any production Code Queue artifact deploy, manifest mutation, rollout restart, scheduler/runner rebuild, task interrupt/cancel, or self-deploy by the running Code Queue task

The operator review points are fixed. DEV requires an operator to compare the CI artifact summary with deploy plan --env dev --service code-queue or deploy apply --env dev --service code-queue --dry-run, then explicitly authorize a DEV apply outside the Code Queue task. PROD has no apply authorization point in this phase; even a manual request must first land a separate reviewed Code Queue production CD design. The current runner may produce plans, preflight output, docs and contract tests only.

Lightweight contract evidence for this boundary is:

bun scripts/code-queue-cicd-dry-run-contract-test.ts

The test checks that dev targets only unidesk-dev, prod exposes no runtime deploy target, production mutation is unsupported, and dry-run output forbids Code Queue self-deploy, scheduler/runner mutation, interrupt and cancel actions.

Validation Boundary

This precheck uses lightweight parsing and dry-run evidence only. It intentionally does not run full check, e2e, Playwright, or other broad browser/runtime test suites on the master server because those are outside the precheck scope and may exceed master-server resource limits. D601 code-queue production validation is out of scope. backend-core dev rollout must use the artifact consumer path, and a provider-offline result is an infrastructure blocker rather than permission to validate production.

The structured read-only preflight entrypoints are artifact-registry status|health and ci publish-user-service --dry-run. Remote runners may call them through the frontend passthrough path, and the result must classify missing backend-core, database, provider or registry channels as runnerDisposition=infra-blocked. The detailed probe list remains in missingChannels; the stable runner-facing domain list is missingControlChannels with only backend-core, database, provider and registry. Those cases are infrastructure blockers, not business failures and not a license to retry a real publish. A non-dry-run publish may be attempted only where controlledPublish points: D601 CI, namespace unidesk-ci, PipelineRun unidesk-user-service-artifact-publish.

Next Stage Dispatch Matrix

This matrix describes the next promotion stage after dry-run coverage is in place. It favors correctness over throughput, keeps backend-core and D601 code-queue dev-only, and splits dev and prod only where the runtime policy already allows it.

Service class Target branch CI current state CD current state DEV acceptance PROD acceptance Blockers Suggested model
backend-core master source-build supported through ci publish-backend-core dev + prod artifact consumer dev artifact rollout to unidesk-dev/backend-core-dev with no CD compile prod artifact recreate with live commit proof CI resource, registry artifact, and runtime health evidence GPT-5.5
code-queue master source-build supported, dev-only dev-only k3s consumer dev artifact validation for unidesk-dev scheduler/read/write/provider-egress-proxy not implemented; must remain unsupported production boundary, hostPath/source contract, scheduler/egress dependency health GPT-5.5
frontend master source-build supported dev + prod artifact consumer commit-pinned dev rollout and /health.deploy.commit commit-pinned prod recreate and UI route verification none beyond standard artifact/CD checks GPT-5.5
baidu-netdisk master source-build supported dev + prod artifact consumer pull-only dev validation plus auth and proxy checks pull-only prod recreate plus live commit and proxy checks secret presence and /health.auth gate GPT-5.5
project-manager master source-build supported dev + prod artifact consumer dev artifact validation with /api/projects prod artifact validation with live commit proof none beyond standard artifact/CD checks MiniMax for dry-run/reporting, GPT-5.5 for release sign-off
oa-event-flow master source-build supported dev + prod artifact consumer dev artifact validation with /api/diagnostics prod artifact validation with live commit proof none beyond standard artifact/CD checks MiniMax for dry-run/reporting, GPT-5.5 for release sign-off
todo-note master external source-build supported dev + prod artifact consumer dev recreate with PostgreSQL-backed deploy metadata prod recreate with matching deploy.commit and deploy.requestedCommit external repo fetch and runtime metadata consistency DeepSeek for digesting external-source evidence, GPT-5.5 for final gate
decision-center master source-build supported dev + prod k3s consumer dev gate with record CRUD, diary lifecycle, doc-number uniqueness and frontend visibility manual prod acceptance after dev gate; verify health, records, diary editor and live commit doc-management completeness, PostgreSQL truth, no public business ports GPT-5.5
mdtodo master source-build supported dev + prod k3s consumer dev rollout with deployment metadata and /health or /live proof prod rollout with service proxy verification and live commit proof no NodePort/hostPort/public backend exposure MiniMax for prompt prep, GPT-5.5 for approval
claudeqq master source-build supported dev + prod k3s consumer dev rollout with Deployment metadata and health via Kubernetes API proxy prod rollout with same commit-pinned artifact contract NapCat/backend port exposure must stay private MiniMax for prompt prep, GPT-5.5 for approval
findjob master source-build supported dev + prod direct Compose consumer pull-only dev validation on D601 with image labels and /api/health pull-only prod recreate with live commit proof target-side compose health/labels only, no public business ports DeepSeek for dry-run matrix drafting, GPT-5.5 for final gate
pipeline master source-build supported dev + prod direct Compose consumer pull-only dev validation on D601 with image labels and /health pull-only prod recreate with live commit proof runtime contract is commit-label + compose service identity DeepSeek for dry-run matrix drafting, GPT-5.5 for final gate
met-nonlinear master source-build supported dev dry-run only runtime-verification-blocked until long-running TS service image contract is fixed not authorized image contract mismatch between ML Dockerfile and TS runtime service GPT-5.5
k3sctl-adapter master source-build supported plan/dry-run only no normal dev target; only control-bridge health and recovery evidence prod live apply requires supervisor confirmation bridge recovery, k3s fault-domain isolation, no worker self-replacement GPT-5.5
filebrowser / filebrowser-d601 master upstream-image blocked pull-only mirror target digest resolution, mirror governance and private proxy health only not in this phase upstream digest/mirror worker not yet implemented DeepSeek for evidence summarization, GPT-5.5 for blocker resolution

Frontend lane closure evidence is intentionally lightweight and non-mutating:

bun scripts/frontend-artifact-lane-contract-test.ts

The contract fixes the current sample around one artifact lane: deploy.json dev/prod both request the same frontend commit, CI.json keeps the producer as ci publish-user-service, the D601 registry manifest digest is recorded, dev and prod health expose matching deploy.commit / deploy.requestedCommit, ci publish-user-service --dry-run is ready, and both CD dry-runs are artifact consumers with no source build.

Planned parallelism for the next wave should be three lanes:

  1. Lane A: frontend, baidu-netdisk, project-manager, oa-event-flow.
  2. Lane B: decision-center, mdtodo, claudeqq, todo-note.
  3. Lane C: findjob, pipeline, met-nonlinear, k3sctl-adapter, code-queue, backend-core.

Lane C must stay split into dev-only work for backend-core and code-queue, plus read-only or dry-run work for met-nonlinear and k3sctl-adapter. backend-core and code-queue must not be promoted into prod acceptance tasks in this phase.