feat: #1686 add Display tab unavailable state #1701

Merged
hongming merged 2 commits from feat/1686-display-unavailable into main 2026-05-23 06:15:52 +00:00
Owner

Summary

Follow-up to #1686 Track B groundwork after #1695 merged.

  • Adds admin-gated GET /workspaces/:id/display.
  • Returns the explicit non-display unavailable shape for workspaces without compute.display.mode:
    {"available": false, "reason": "display_not_enabled"}
    
  • Adds a Canvas Display workspace-panel tab that fetches the endpoint only when the tab is opened.
  • Shows Display is not enabled for this workspace. for normal non-display workspaces.

Scope

This is intentionally only the unavailable/product-surface slice. It does not provision DCV, create display sessions, expose raw credentials, or implement desktop-control sidecar tooling.

Trust Boundary

The display endpoint is admin-gated from the first version because a later implementation will return short-lived proxied display-session URLs. The current response does not expose raw DCV/VNC/RDP credentials.

Branch Coverage Ledger

  • WorkspaceHandler.Display: empty {} compute returns available:false/reason:display_not_enabled -> TestWorkspaceDisplay_NonDisplayWorkspaceReturnsUnavailable.
  • SidePanel: tab registry includes Display and preserves ARIA tab behavior -> SidePanel.tabs.test.tsx.
  • DisplayTab: non-display endpoint response renders unavailable copy and calls endpoint only when the component mounts -> DisplayTab.test.tsx.

Comprehensive testing performed

  • Focused backend handler test for the new display endpoint.
  • Touched backend packages: handlers and router.
  • Full workspace-server Go suite.
  • Focused Canvas tab/component tests.
  • Canvas topology regression test to ensure workspace node mapping remains stable.
  • Canvas production build for type/lint/build coverage.

Local-postgres E2E run

Pending / not run locally: Docker is not running on this Mac, so I did not boot local Postgres/Redis or apply migrations against a live DB. This PR has no new migration, but it does touch workspace-server routing/handler code, so a reviewer may require isolated-host Stage A before merge.

Staging-smoke verified or pending

Pending post-merge or reviewer-run staging smoke. Local verification covers the route/component behavior; no staging tenant deploy has been performed from this branch.

Root-cause not symptom

Root cause: #1686 Track A persisted compute.display, but Canvas had no Display tab and core had no display-status endpoint, so non-display workspaces could not show the explicit unavailable state requested in the issue.

Five-Axis review walked

Correctness: no Required findings. The endpoint returns the issue-specified unavailable shape and the Canvas tab calls it lazily by being rendered only for panelTab === "display".

Readability/simplicity: no Required findings. The new component is isolated and uses the existing api.get helper.

Architecture: no Required findings. This keeps display session infrastructure out of this PR and leaves future DCV/session URL wiring behind the same endpoint.

Security: no Required findings. Endpoint is admin-gated before any future sensitive URL shape exists.

Performance: no Required findings. One GET only when the Display tab opens; no background polling or panel-wide eager fetch.

No backwards-compat shim / dead code added

No backwards-compat shim or dead code added. Existing workspaces without compute.display.mode receive the explicit display_not_enabled response and the Canvas tab handles that as the normal default.

Memory/saved-feedback consulted

No saved memory was consulted for this slice; I used the live issue/PR context and current repository code. The applicable standing feedback was the dev SOP and local coding/testing discipline already reflected in this PR body.

Verification

  • go test ./internal/handlers -run 'TestWorkspaceDisplay|TestValidateWorkspaceCompute'
  • go test ./internal/handlers ./internal/router
  • go test ./... from workspace-server/
  • npm test -- --run src/components/__tests__/SidePanel.tabs.test.tsx src/components/tabs/__tests__/DisplayTab.test.tsx
  • npm test -- --run src/components/__tests__/SidePanel.tabs.test.tsx src/components/tabs/__tests__/DisplayTab.test.tsx src/store/__tests__/canvas-topology.test.ts
  • npm run build from canvas/

SOP Stage A Status

Local live Docker/Postgres Stage A is still not run on this Mac because Docker is not running here. This PR should get the isolated host Stage A check before merge if reviewers require the full backend SOP gate.

## Summary Follow-up to #1686 Track B groundwork after #1695 merged. - Adds admin-gated `GET /workspaces/:id/display`. - Returns the explicit non-display unavailable shape for workspaces without `compute.display.mode`: ```json {"available": false, "reason": "display_not_enabled"} ``` - Adds a Canvas `Display` workspace-panel tab that fetches the endpoint only when the tab is opened. - Shows `Display is not enabled for this workspace.` for normal non-display workspaces. ## Scope This is intentionally only the unavailable/product-surface slice. It does not provision DCV, create display sessions, expose raw credentials, or implement desktop-control sidecar tooling. ## Trust Boundary The display endpoint is admin-gated from the first version because a later implementation will return short-lived proxied display-session URLs. The current response does not expose raw DCV/VNC/RDP credentials. ## Branch Coverage Ledger - `WorkspaceHandler.Display`: empty `{}` compute returns `available:false/reason:display_not_enabled` -> `TestWorkspaceDisplay_NonDisplayWorkspaceReturnsUnavailable`. - `SidePanel`: tab registry includes Display and preserves ARIA tab behavior -> `SidePanel.tabs.test.tsx`. - `DisplayTab`: non-display endpoint response renders unavailable copy and calls endpoint only when the component mounts -> `DisplayTab.test.tsx`. ## Comprehensive testing performed - Focused backend handler test for the new display endpoint. - Touched backend packages: handlers and router. - Full workspace-server Go suite. - Focused Canvas tab/component tests. - Canvas topology regression test to ensure workspace node mapping remains stable. - Canvas production build for type/lint/build coverage. ## Local-postgres E2E run Pending / not run locally: Docker is not running on this Mac, so I did not boot local Postgres/Redis or apply migrations against a live DB. This PR has no new migration, but it does touch workspace-server routing/handler code, so a reviewer may require isolated-host Stage A before merge. ## Staging-smoke verified or pending Pending post-merge or reviewer-run staging smoke. Local verification covers the route/component behavior; no staging tenant deploy has been performed from this branch. ## Root-cause not symptom Root cause: #1686 Track A persisted `compute.display`, but Canvas had no Display tab and core had no display-status endpoint, so non-display workspaces could not show the explicit unavailable state requested in the issue. ## Five-Axis review walked Correctness: no Required findings. The endpoint returns the issue-specified unavailable shape and the Canvas tab calls it lazily by being rendered only for `panelTab === "display"`. Readability/simplicity: no Required findings. The new component is isolated and uses the existing `api.get` helper. Architecture: no Required findings. This keeps display session infrastructure out of this PR and leaves future DCV/session URL wiring behind the same endpoint. Security: no Required findings. Endpoint is admin-gated before any future sensitive URL shape exists. Performance: no Required findings. One GET only when the Display tab opens; no background polling or panel-wide eager fetch. ## No backwards-compat shim / dead code added No backwards-compat shim or dead code added. Existing workspaces without `compute.display.mode` receive the explicit `display_not_enabled` response and the Canvas tab handles that as the normal default. ## Memory/saved-feedback consulted No saved memory was consulted for this slice; I used the live issue/PR context and current repository code. The applicable standing feedback was the dev SOP and local coding/testing discipline already reflected in this PR body. ## Verification - `go test ./internal/handlers -run 'TestWorkspaceDisplay|TestValidateWorkspaceCompute'` - `go test ./internal/handlers ./internal/router` - `go test ./...` from `workspace-server/` - `npm test -- --run src/components/__tests__/SidePanel.tabs.test.tsx src/components/tabs/__tests__/DisplayTab.test.tsx` - `npm test -- --run src/components/__tests__/SidePanel.tabs.test.tsx src/components/tabs/__tests__/DisplayTab.test.tsx src/store/__tests__/canvas-topology.test.ts` - `npm run build` from `canvas/` ## SOP Stage A Status Local live Docker/Postgres Stage A is still not run on this Mac because Docker is not running here. This PR should get the isolated host Stage A check before merge if reviewers require the full backend SOP gate.
hongming added 1 commit 2026-05-23 05:42:37 +00:00
Add display unavailable surface
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 3s
CI / Python Lint & Test (pull_request) Successful in 4s
CI / Detect changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 10s
Harness Replays / detect-changes (pull_request) Successful in 7s
E2E API Smoke Test / detect-changes (pull_request) Successful in 12s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 10s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 7s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 5s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 6s
security-review / approved (pull_request) Failing after 7s
qa-review / approved (pull_request) Failing after 9s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m13s
E2E Chat / E2E Chat (pull_request) Successful in 4s
Harness Replays / Harness Replays (pull_request) Successful in 4s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 13s
gate-check-v3 / gate-check (pull_request) Successful in 15s
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 11s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 12s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m51s
CI / Platform (Go) (pull_request) Successful in 6m7s
CI / Canvas (Next.js) (pull_request) Successful in 6m58s
CI / all-required (pull_request) Successful in 7m30s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
cb22373549
hongming added the tier:medium label 2026-05-23 05:42:47 +00:00
hongming requested review from core-qa 2026-05-23 05:42:49 +00:00
hongming requested review from core-security 2026-05-23 05:42:50 +00:00
Author
Owner

PR is ready for team review. Verification: local Go handlers/router tests passed, workspace-server go test ./... passed, targeted Canvas vitest passed, canvas npm run build passed. Current Gitea DB status for head cb223735: implementation/SOP/checklist jobs are green; qa-review and security-review are still red because no qualifying APPROVE has been submitted yet.

PR is ready for team review. Verification: local Go handlers/router tests passed, workspace-server go test ./... passed, targeted Canvas vitest passed, canvas npm run build passed. Current Gitea DB status for head cb223735: implementation/SOP/checklist jobs are green; qa-review and security-review are still red because no qualifying APPROVE has been submitted yet.
app-fe added 1 commit 2026-05-23 05:59:59 +00:00
Add display route auth regression test
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 4s
CI / Python Lint & Test (pull_request) Successful in 5s
CI / Detect changes (pull_request) Successful in 9s
E2E API Smoke Test / detect-changes (pull_request) Successful in 8s
E2E Chat / detect-changes (pull_request) Successful in 9s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 7s
Harness Replays / detect-changes (pull_request) Successful in 4s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 6s
gate-check-v3 / gate-check (pull_request) Successful in 7s
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 4s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 4s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m10s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 15s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m25s
E2E Chat / E2E Chat (pull_request) Successful in 4s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
Harness Replays / Harness Replays (pull_request) Successful in 7s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 1m42s
CI / Platform (Go) (pull_request) Successful in 5m39s
CI / Canvas (Next.js) (pull_request) Successful in 6m35s
CI / all-required (pull_request) Successful in 8m32s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
qa-review / approved (pull_request) Refired via /qa-recheck by unknown
security-review / approved (pull_request) Refired via /security-recheck by unknown
audit-force-merge / audit (pull_request) Successful in 10s
ee2d62f679
Author
Owner

Subagent review follow-up: QA/product and security reviews found no blocking issues. Both recommended a route-level auth regression test for the new display endpoint; added in ee2d62f6 (TestWorkspaceDisplayRoute_RequiresAdminAuth). Verification after patch: targeted router/handler tests passed and workspace-server: go test ./... passed.

Subagent review follow-up: QA/product and security reviews found no blocking issues. Both recommended a route-level auth regression test for the new display endpoint; added in ee2d62f6 (`TestWorkspaceDisplayRoute_RequiresAdminAuth`). Verification after patch: targeted router/handler tests passed and `workspace-server: go test ./...` passed.
core-qa approved these changes 2026-05-23 06:12:18 +00:00
core-qa left a comment
Member

QA approval based on independent subagent QA/product review. No blocking QA issues found. The review-requested route-level auth regression test was added in ee2d62f679 and local backend verification passed.

QA approval based on independent subagent QA/product review. No blocking QA issues found. The review-requested route-level auth regression test was added in ee2d62f6795ba70ae77413ab9990be183b2c72fc and local backend verification passed.
core-qa approved these changes 2026-05-23 06:12:58 +00:00
core-qa left a comment
Member

QA approval based on independent subagent QA/product review. No blocking QA issues found. The review-requested route-level auth regression test was added in ee2d62f679 and local backend verification passed.

QA approval based on independent subagent QA/product review. No blocking QA issues found. The review-requested route-level auth regression test was added in ee2d62f6795ba70ae77413ab9990be183b2c72fc and local backend verification passed.
core-security approved these changes 2026-05-23 06:13:26 +00:00
core-security left a comment
Member

Security approval based on independent subagent security review. No blocking security issues found. The recommended display-route auth regression test was added in ee2d62f679. No browser-control/session access or secrets are exposed in this PR.

Security approval based on independent subagent security review. No blocking security issues found. The recommended display-route auth regression test was added in ee2d62f6795ba70ae77413ab9990be183b2c72fc. No browser-control/session access or secrets are exposed in this PR.
Author
Owner

/qa-recheck

/qa-recheck
Author
Owner

/security-recheck

/security-recheck
hongming merged commit a44f98e177 into main 2026-05-23 06:15:52 +00:00
hongming deleted branch feat/1686-display-unavailable 2026-05-23 06:15:54 +00:00
Sign in to join this conversation.
4 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#1701