Add display control lock endpoints #1718
Reference in New Issue
Block a user
Delete Branch "feat/1686-display-control-lock"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the next backend-only slice for #1686: a volatile display control lock contract for future native display takeover.
What changed
workspace_display_control_lockswith TTL-backed per-workspace ownership state.GET /workspaces/:id/display/controlPOST /workspaces/:id/display/control/acquirePOST /workspaces/:id/display/control/release409with the current holder.ADMIN_TOKENbearer or org-token actor; force release requiresADMIN_TOKEN.structure_eventsaudit rows for acquire/release started/completed/failed.Comprehensive testing performed
go test ./internal/handlers -run 'TestWorkspaceDisplayControl'go test ./internal/handlers ./internal/router ./internal/dbgo test ./...go build ./cmd/serverLocal-postgres E2E run
Ran Stage A with isolated temp services:
initdb/pg_ctlon port55432redis-serveron port56379DATABASE_URL=postgres://dev@localhost:55432/molecule?sslmode=disable REDIS_URL=redis://localhost:56379 PORT=18086 BIND_ADDR=127.0.0.1 ADMIN_TOKEN=stage-a-admin-token MOLECULE_ENV=development go run ./cmd/serverEvidence:
20260523120000_workspace_display_control_locks.up.sqlwith all repo migrations.\d workspace_display_control_locksconfirmed PK, FK cascade, controller check, controlled_by length check, and expires index.GET /display/control->{"controller":"none"}POST /display/control/acquire->{"controller":"user","controlled_by":"admin-token","expires_at":"..."}active = truePOST /display/control/release->{"controller":"none"}0structure_eventsshoweddisplay.control.acquire.started,display.control.acquire.completed,display.control.release.started, anddisplay.control.release.completedfor the workspace.Docker was not running locally. The server attempted Docker provisioner auto-detection and orphan-sweeper checks returned Docker connection errors without stopping any containers.
Staging-smoke verified or pending
Pending merge/deploy. This PR adds backend coordination endpoints only; no Canvas takeover UI is wired in this slice.
Root-cause not symptom
The display roadmap needs native computer-level takeover coordination before exposing a live screen/control UI. This adds the coordination primitive without leaking DCV/session details or changing
GET /workspaces/:id/displayavailability semantics.Five-Axis review walked
RowsAffectedon release, validating display-enabled workspace before acquire, and using a separatenoneDTO so zero timestamps are not serialized.workspaces.compute; existing display status remains backward-compatible.AdminAuth; SQL is parameterized; browser sessions cannot mutate until stable identity exists; force release requires actualADMIN_TOKENbearer.No backwards-compat shim / dead code added
No compatibility shim. Existing display status endpoint behavior is unchanged. No dead code added.
Memory/saved-feedback consulted
Used the repo SOP from
internal/runbooks/dev-sop.mdand followed the Stage A / review checklist. No prior saved rollout memory was needed for this narrow backend slice.Refs #1686
QA review: approved. Local handler/router/db tests and full workspace-server suite are green; Stage A endpoint probe against temp Postgres/Redis verified acquire/release and audit rows.
Security review: approved. New control mutation endpoints stay under AdminAuth; SQL is parameterized; browser sessions are observe-only until stable identity exists; force release requires ADMIN_TOKEN.