fix(display): allow browser sessions to take control #1832

Merged
agent-dev-b merged 1 commits from fix/display-control-browser-session into main 2026-05-25 04:24:38 +00:00
Owner

Summary

  • set a stable hashed controller actor when AdminAuth accepts a verified control-plane browser session
  • allow display control acquisition for that verified browser session actor
  • let the Display tab reacquire a session URL for existing user locks after reload

Root-cause not symptom

The display takeover endpoint trusted AdminAuth for the browser request but displayControlActor had no stable actor for verified control-plane browser sessions, so the handler rejected real Canvas clicks with 403 even though viewing the Display tab was authenticated.

Comprehensive testing performed

  • Added middleware regression coverage that a verified CP browser session sets a hashed cp_session_actor and does not expose the raw cookie.
  • Added display-control handler regression coverage that the session actor can acquire a user control lock and receives a signed session URL.
  • Re-ran existing DisplayTab tests to cover take/release button behavior after the user-session actor change.

Local-postgres E2E run

N/A: this change does not add or migrate schema. The DB-facing code path is covered with sqlmock handler tests for the exact workspace_display_control_locks upsert behavior.

Staging-smoke verified or pending

Pending post-merge deploy verification. PR CI already includes E2E Staging SaaS and Canvas/staging checks for the head SHA; production canary /buildinfo plus a manual browser retry of Take control are the final release checks.

Five-Axis review walked

  • Correctness: browser session auth now produces an actor before display-control acquisition; regression tests cover middleware and handler boundaries.
  • Readability: actor derivation is a small helper and follows the existing session cache hashing pattern.
  • Architecture: keeps AdminAuth as the single CP session verification point and lets display control consume only a context value.
  • Security: actor id is tenant-scoped and hashed from the cookie only after CP membership verification; raw cookie is not stored or returned.
  • Performance: adds only one SHA-256 hash on the already-verified session path; CP verification caching remains unchanged.

No backwards-compat shim / dead code added

No compatibility shim or dead code added. The change completes the existing intended browser-session auth path for Display control.

Memory/saved-feedback consulted

Used current repo evidence and prior workspace-compute context from session continuity; no additional saved-memory file lookup was needed for this narrow production bug.

Tests

  • go test ./internal/handlers -run 'TestWorkspaceDisplayControl'
  • go test ./internal/middleware -run 'TestVerifiedCPSession|TestAdminAuth'
  • npx eslint src/components/tabs/DisplayTab.tsx --quiet
  • npm test -- --run src/components/tabs/__tests__/DisplayTab.test.tsx
  • git diff --check
## Summary - set a stable hashed controller actor when AdminAuth accepts a verified control-plane browser session - allow display control acquisition for that verified browser session actor - let the Display tab reacquire a session URL for existing user locks after reload ## Root-cause not symptom The display takeover endpoint trusted AdminAuth for the browser request but `displayControlActor` had no stable actor for verified control-plane browser sessions, so the handler rejected real Canvas clicks with 403 even though viewing the Display tab was authenticated. ## Comprehensive testing performed - Added middleware regression coverage that a verified CP browser session sets a hashed `cp_session_actor` and does not expose the raw cookie. - Added display-control handler regression coverage that the session actor can acquire a user control lock and receives a signed session URL. - Re-ran existing DisplayTab tests to cover take/release button behavior after the user-session actor change. ## Local-postgres E2E run N/A: this change does not add or migrate schema. The DB-facing code path is covered with sqlmock handler tests for the exact `workspace_display_control_locks` upsert behavior. ## Staging-smoke verified or pending Pending post-merge deploy verification. PR CI already includes E2E Staging SaaS and Canvas/staging checks for the head SHA; production canary `/buildinfo` plus a manual browser retry of Take control are the final release checks. ## Five-Axis review walked - Correctness: browser session auth now produces an actor before display-control acquisition; regression tests cover middleware and handler boundaries. - Readability: actor derivation is a small helper and follows the existing session cache hashing pattern. - Architecture: keeps AdminAuth as the single CP session verification point and lets display control consume only a context value. - Security: actor id is tenant-scoped and hashed from the cookie only after CP membership verification; raw cookie is not stored or returned. - Performance: adds only one SHA-256 hash on the already-verified session path; CP verification caching remains unchanged. ## No backwards-compat shim / dead code added No compatibility shim or dead code added. The change completes the existing intended browser-session auth path for Display control. ## Memory/saved-feedback consulted Used current repo evidence and prior workspace-compute context from session continuity; no additional saved-memory file lookup was needed for this narrow production bug. ## Tests - `go test ./internal/handlers -run 'TestWorkspaceDisplayControl'` - `go test ./internal/middleware -run 'TestVerifiedCPSession|TestAdminAuth'` - `npx eslint src/components/tabs/DisplayTab.tsx --quiet` - `npm test -- --run src/components/tabs/__tests__/DisplayTab.test.tsx` - `git diff --check`
hongming added 1 commit 2026-05-25 03:31:55 +00:00
fix(display): allow browser sessions to take control
ci-arm64-advisory / fast-checks (pull_request) Waiting to run
CI / Canvas Deploy Reminder (pull_request) Blocked by required conditions
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Successful in 15s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 27s
CI / Python Lint & Test (pull_request) Successful in 12s
CI / Detect changes (pull_request) Successful in 26s
E2E API Smoke Test / detect-changes (pull_request) Successful in 24s
E2E Chat / detect-changes (pull_request) Successful in 25s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 17s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 24s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Successful in 1m36s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 1m6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 9s
Harness Replays / detect-changes (pull_request) Successful in 7s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 10s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 10s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 12s
qa-review / approved (pull_request) Successful in 7s
security-review / approved (pull_request) Successful in 28s
sop-checklist / na-declarations (pull_request) N/A: (none)
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m5s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Successful in 5m37s
gate-check-v3 / gate-check (pull_request) Waiting to run
sop-checklist / all-items-acked (pull_request) Waiting to run
sop-checklist / review-refire (pull_request) Waiting to run
sop-tier-check / tier-check (pull_request) Waiting to run
CI / Shellcheck (E2E scripts) (pull_request) Successful in 18s
E2E Chat / E2E Chat (pull_request) Successful in 10s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 5s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 1m58s
Harness Replays / Harness Replays (pull_request) Successful in 6s
CI / Platform (Go) (pull_request) Successful in 5m57s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 4m30s
CI / Canvas (Next.js) (pull_request) Successful in 9m8s
CI / all-required (pull_request) Successful in 30m28s
audit-force-merge / audit (pull_request) Successful in 7s
9eefa5c474
core-qa approved these changes 2026-05-25 03:34:05 +00:00
core-qa left a comment
Member

QA review approved. Verified the changed DisplayTab flow and backend regression coverage for browser-session display control acquisition. Local evidence from author branch: DisplayTab vitest passed, eslint passed, handler display-control tests passed, middleware AdminAuth/session tests passed.

QA review approved. Verified the changed DisplayTab flow and backend regression coverage for browser-session display control acquisition. Local evidence from author branch: DisplayTab vitest passed, eslint passed, handler display-control tests passed, middleware AdminAuth/session tests passed.
core-qa approved these changes 2026-05-25 03:34:43 +00:00
core-qa left a comment
Member

QA review approved. Verified the changed DisplayTab flow and backend regression coverage for browser-session display control acquisition. Local evidence from author branch: DisplayTab vitest passed, eslint passed, handler display-control tests passed, middleware AdminAuth/session tests passed.

QA review approved. Verified the changed DisplayTab flow and backend regression coverage for browser-session display control acquisition. Local evidence from author branch: DisplayTab vitest passed, eslint passed, handler display-control tests passed, middleware AdminAuth/session tests passed.
core-security approved these changes 2026-05-25 03:35:07 +00:00
core-security left a comment
Member

Security review approved. Static review: no new dependencies, no secret-shaped literals in changed files, CP session actor is derived only after VerifiedCPSession succeeds, and the stored controller id is a tenant-scoped hash rather than the raw cookie.

Security review approved. Static review: no new dependencies, no secret-shaped literals in changed files, CP session actor is derived only after VerifiedCPSession succeeds, and the stored controller id is a tenant-scoped hash rather than the raw cookie.
agent-dev-b approved these changes 2026-05-25 03:47:05 +00:00
Dismissed
agent-dev-b left a comment
Member

LGTM

LGTM
agent-dev-b approved these changes 2026-05-25 04:03:21 +00:00
agent-dev-b left a comment
Member

5-axis review on (fix(display): allow browser sessions to take control):

Correctness: APPROVED. Stable hashed controller actor set on AdminAuth for verified browser sessions; Display tab reacquires session URLs for user locks on reload. Logic is sound.
Robustness: APPROVED. Stable hash prevents actor reuse attacks; session reacquisition is conditional on existing user locks.
Performance: APPROVED. No additional DB writes or queries introduced.
Security: APPROVED. Verification gated behind AdminAuth; controller actor is deterministically derived, not arbitrary. Browser session control surface is limited.
Compatibility: APPROVED. New behavior additive; existing sessions unaffected.

5-axis review on (fix(display): allow browser sessions to take control): Correctness: APPROVED. Stable hashed controller actor set on AdminAuth for verified browser sessions; Display tab reacquires session URLs for user locks on reload. Logic is sound. Robustness: APPROVED. Stable hash prevents actor reuse attacks; session reacquisition is conditional on existing user locks. Performance: APPROVED. No additional DB writes or queries introduced. Security: APPROVED. Verification gated behind AdminAuth; controller actor is deterministically derived, not arbitrary. Browser session control surface is limited. Compatibility: APPROVED. New behavior additive; existing sessions unaffected.
Member

/sop-ack local-postgres-e2e
/sop-ack staging-smoke
/sop-ack root-cause
/sop-ack five-axis-review
/sop-ack no-backwards-compat
/sop-ack memory-consulted

Engineering ack: DB write path is covered by sqlmock because this PR has no schema change; staging validation is represented by PR E2E plus post-merge canary; root cause is the missing browser-session actor at the display-control boundary; no compatibility shim or dead code was added.

/sop-ack local-postgres-e2e /sop-ack staging-smoke /sop-ack root-cause /sop-ack five-axis-review /sop-ack no-backwards-compat /sop-ack memory-consulted Engineering ack: DB write path is covered by sqlmock because this PR has no schema change; staging validation is represented by PR E2E plus post-merge canary; root cause is the missing browser-session actor at the display-control boundary; no compatibility shim or dead code was added.
Member

/sop-ack comprehensive-testing

QA ack: regression coverage covers the browser-session Display takeover failure, handler lock acquisition, and DisplayTab take/release state.

/sop-ack comprehensive-testing QA ack: regression coverage covers the browser-session Display takeover failure, handler lock acquisition, and DisplayTab take/release state.
hongming added the tier:low label 2026-05-25 04:09:42 +00:00
agent-dev-b reviewed 2026-05-25 04:16:26 +00:00
agent-dev-b left a comment
Member

Please review

Please review
agent-dev-b reviewed 2026-05-25 04:16:27 +00:00
agent-dev-b left a comment
Member

Please review

Please review
agent-dev-b merged commit 4c86f047c7 into main 2026-05-25 04:24:38 +00:00
Sign in to join this conversation.
5 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#1832