Tracker for issues found in the build-custom-agent end-to-end flow. Backend:
api/http/controller/admin/custom_build.go,api/service/custom_build.go,api/service/github_build_config.go. Frontend:admin-ui/src/views/custom-client/index.vue,admin-ui/src/views/server/github-build.vue. Workflow:github-build/rustqs-windows-min-test.yml.Status legend:
[ ]open ·[x]fixed ·[~]partial ·[skip]won't fix (owner decision).Last audit: 2026-06-23 (fixed items removed; tracker lists only open work).
PLAN.md declares the standalone / Docker build agents frozen as fallback (§8.3, §8.4).
Reality: custom_build.go::submitBuild still routes every non-Windows platform — and even
windows-x86 and Windows when GitHub config is absent — into the file queue
(/rdgen-data/jobs/{id}.json). Owner decision (2026-06-20):
- Treat Docker
build-linuxandbuild-wincontainers as frozen manual fallback, not the default route. They stay on disk but should not be started bydocker compose up. - Remove
windows-x86(32-bit) as a build target everywhere — UI option, form defaults, any router branches. 2026; not worth maintaining. - Build a GitHub Actions workflow for Linux + Android mirroring the windows-min-test
pipeline, and re-route
submitBuildaccordingly. Until those workflows ship, non-Windows platforms should be hidden in the UI to stop users from creating phantom builds.
The bugs below are grouped by where they leak into user-visible breakage.
Deferred on branch fix/build-custom-agent (2026-06-20): UI now restricts platforms to
Windows-via-GitHub (B-013), so the file-queue path is unreachable from the default flow
even though submitBuild still has the branch. docker/docker-compose.yml moved
build-linux and build-win services behind a fallback profile so they don't start by
default. Full fix (status mirror) only matters once Linux/Android workflows land (B-012),
at which point we'd rather route them through GitHub too.
Where: api/http/controller/admin/custom_build.go:172-201 (writes job),
docker/entrypoint-linux.sh:37,49,76,... and docker/entrypoint-win.sh:33,45,210 (write output_dir/status).
Symptom: Linux/Android (and Windows when GitHub config is missing) builds sit at
Status=pending forever. DownloadByKey returns HTTP 409. The Download button never appears
in the UI (v-if="row.status === 'done'", custom-client/index.vue:306).
Root cause: no Go-side watcher reads /rdgen-data/output/{id}/status. The build agent's
status file is dead-letter.
Fix path (per owner direction):
- Short term: hide all non-Windows-via-GitHub options in the UI (B-002, B-013).
- Long term: replace the file queue for the supported platforms with GitHub Actions dispatch (linux/android workflows, B-012).
Partially fixed on branch fix/build-custom-agent (2026-06-20):
- Deleted
CustomBuildForm.FromCustomBuild(api/http/request/admin/custom_build.go). - Deleted
CustomPresetForm.FromCustomPreset(api/http/request/admin/custom_preset.go). - Deleted
detail()export fromadmin-ui/src/api/custom_client.js. - Removed unused
detailPresetimport inadmin-ui/src/views/custom-client/index.vue. - Un-routed
GET /custom_build/detail/:idinapi/http/router/admin.go(handler kept on the controller for symmetry; can be deleted later if no internal caller appears).
Still open: /custom_build/public/detailByKey/:key exists but has no caller in the UI.
Left in place because it's a documented capability URL and may have third-party consumers.
Where:
api/http/request/admin/custom_build.go:14—CustomBuildForm.FromCustomBuild(no callers).api/http/request/admin/custom_preset.go:24—CustomPresetForm.FromCustomPreset(no callers).admin-ui/src/api/custom_client.js:10—detail()exported, no importer.admin-ui/src/views/custom-client/index.vue:323—detailPresetimported, never used insetup().GET /custom_build/detail/:idandGET /custom_build/public/detailByKey/:key— already noted as unused inaudit-report.md:879-881. Fix: delete in a single janitorial PR after the higher-priority work lands.
Backend: merged (PR #44 backend routing: submitBuild dispatches platform=linux/android
by workflow constant; tryGithubDispatch picks rustqs-linux.yml/rustqs-android.yml;
pollAndDownload selects artifact by platform).
Workflow files: deployed to bashrusakh/rustdesk on both master (API discovery)
and rustqs/min-test (execution) — all three are indexed (HTTP 200):
rustqs-windows-min-test.yml, rustqs-linux.yml, rustqs-android.yml.
Filenames in Go constants match fork filenames exactly.
Critical dependency: bridge.yml must also exist on both branches — all three
rustqs-*.yml reference it as a reusable workflow. Without it, dispatch succeeds
but the run fails with a parse error (422).
Still open:
- validate
rustqs-linux.ymlandrustqs-android.ymlon real Actions runs (build steps: vcpkg/flutter/build.py/packaging/artifact paths — need CI iteration like windows-min-test did) - Android
custom_.txtembedding is best-effort, needs verification - re-expose Linux/Android in the UI (B-013) behind a feature flag once runs are green
Where: github-build/rustqs-linux.yml, github-build/rustqs-android.yml. Reference templates:
rdgen/.github/workflows/generator-linux.yml, rdgen/.github/workflows/generator-android.yml.
Symptoms (historical): before the push, dispatch returned HTTP 404 because workflow files
were not on master (default branch); submit went to the deprecated file queue (B-001).
Resolved by pushing workflow files to both master and rustqs/min-test.
The functional admin-UI audit (PR #19) had 65 findings; 58 were fixed in PR #20–#22. The full report file was removed during doc consolidation (2026-06-21). The findings still open are preserved here:
Where: api/http/router/api.go — routes registered before frg.Use(RustAuth()) (line 76).
Symptom: POST /api/sysinfo (creates/updates Peer rows by caller-supplied id),
/api/heartbeat, /api/audit/conn, /api/audit/file are unauthenticated; an anonymous caller
can create/alter peers and inject audit entries. /api/shared-peer also does an unchecked
(*j)["share_token"].(string) assertion (webClient.go:57) → 500 on missing token.
Fix: needs RustDesk protocol design confirmation (the PC client hits these before auth).
The custom-agent build workflow audit (Django rdgen/ + Go api/) landed all its ✅ fixes.
The flagged-but-unfixed items are preserved here:
Hardened on branch fix/rdgen-file-ttl: these endpoints are consumed by unauthenticated
callers by protocol (build runners fetch get_png/get_zip; users fetch the built exe), so a
token gate would break the flow. Instead each now refuses to serve files older than a TTL, so a
leaked UUID/filename is no longer a permanent capability: download 7 days (RDGEN_EXE_TTL),
get_png 6h (RDGEN_PNG_TTL), get_zip (encrypted secrets) 1h (RDGEN_ZIP_TTL); all env-tunable,
<=0 disables. Path-traversal + UUID validation were already in place from an earlier audit.
Still open (needs design): true per-request auth via signed/expiring URLs generated server-side and threaded through the workflows — a larger coordinated change across all URL-generation sites.
- This file is owned alongside
PLAN.md. When a bug is fixed, flip[ ]→[x]and append the PR/commit hash on the same line. - New findings: append below this section with a fresh
B-NNNid. - If something is decided as "won't fix" by the owner, mark
[skip]and add a one-line reason.