Codex Dashboard Browser Recipe¶
Use the projected Playwright MCP browser to explore an authenticated isolated dashboard.
Details¶
Use the playwright MCP server generated by wbuddy harness sync --target codexcli. It runs pinned @playwright/mcp with --isolated. Use browser_navigate, browser_wait_for, browser_snapshot, browser_click, browser_type, and browser_fill_form for interaction. Inspect errors with browser_console_messages and browser_network_requests, layouts with browser_resize and browser_take_screenshot.
Start npm --prefix dashboard-react run test:e2e:live:interactive -- --app cowork and name the environment isolated live harness. Read the runner's interactive-session.json for the authenticated frontend URL, backend URL, nonce, and mode. Open the complete printed /app/cowork#wb-bootstrap=... URL with browser_navigate. Wait with browser_wait_for for the Co-work workspace or launcher, then use browser_snapshot. Confirm the fragment was consumed and authenticated controls are available before writing.
The fragment is removed before redemption completes, and an enabled New control does not prove authentication. Use browser_evaluate to check the actual session before any write:
async () => {
const response = await fetch('/api/local-identity/session');
const session = await response.json();
return {authenticated: session.authenticated === true, originMatches: session.principal?.origin === location.origin};
}
Both fields must be true. A failed check is an authentication problem to resolve before the scenario, not evidence of a product mutation defect.
The printed bootstrap is single-use and expires after a short window. A page reload keeps the cookie. If the grant expired, or a fresh browser context needs authentication after it was consumed, navigate to the same isolated frontend first, then use browser_evaluate to mint another grant in page context:
async () => {
const response = await fetch('/api/_live/identity-bootstrap', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'X-WB-Live-Control': '<nonce from interactive-session.json>'},
body: JSON.stringify({origin: location.origin})
});
if (!response.ok) throw new Error(`Bootstrap refused: ${response.status}`);
return await response.json();
}
Use browser_navigate on <frontend origin>/app/cowork#wb-bootstrap=<returned token>, repeat the session check, then confirm the UI with browser_snapshot. Derive the frontend origin from new URL(frontend_url).origin; the session file's frontend_url already includes an App path and fragment. Keep nonce and grant values in disposable session artifacts, never in source or review records. The mint must run in page context so the body origin matches the browser's Origin header.
Use snapshots for text and structure. Screenshots confirm appearance. Poll for expected elements instead of fixed sleeps. Do not append probes to the serial suite or relax its assertions to reach one check.