# DOM: Approval & Permission Dialogs > **Box is the main surface.** All operator work goes through Box (box.muse-dev.online). The web UI, `box` CLI, and agents share the same API endpoints. No UI-only powers. Companion to `DOM-APPROVALS-SPEC.md` (behavioral contract: detection → classification → handling → exit codes). This doc is the **DOM surface reference**: what the dialogs look like in the tree, which selectors find them, how `check_approvals` works today, and what's fragile. Related: `DOM-EDGE-STATES.md` §5.2, `DOM-PAGE-STRUCTURE.md` §3, `DOM-INDEX.md` §4f. ## 1. Observed specimen (real, from `docs/pip-approval-dialog.png`) Captured on pip's node during onboarding. This is a **Muse platform dialog rendered inside the chat DOM** (bottom-anchored card over the message stream) — not a browser-chrome permission bubble. ``` ┌─────────────────────────────────────────────────────────────┐ │ 🌐 Allow pip to share information with 34.139.37.135? │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ pip wants to connect to a remote server to complete │ │ (expandable detail, chevron) │ │ onboarding. ⌄ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ [ Allow once ] [ Always allow this site ] [ Deny ] │ └─────────────────────────────────────────────────────────────┘ ``` | Field | Observed value | |---|---| | Title text | `Allow pip to share information with 34.139.37.135?` | | Title pattern | `Allow to share information with ?` | | Detail text | `pip wants to connect to a remote server to complete onboarding.` | | Detail pattern | ` wants to to .` (collapsible) | | Buttons (left→right) | `Allow once` (primary/blue), `Always allow this site`, `Deny` | | Icon | globe/network glyph preceding the title | Trigger class: the agent attempted an outbound network action (connecting to a remote server). Other trigger classes are **unobserved** — geolocation, camera/mic, notifications, clipboard, and download prompts have not been captured on fleet nodes yet (see §8 induction recipe). ## 2. Dialog DOM structure (as known) No `[role="dialog"]` or `[role="alertdialog"]` elements have been observed in settled-state probes (`DOM-PAGE-STRUCTURE.md` §3.2). The dialog is found **by text, not by structure** — this is the central fragility of the current implementation. Known structural facts (Verified 2026-10-06 live capture on fleet): - The dialog is in-DOM (React-rendered), so `Runtime.evaluate` sees it; no shadow-DOM piercing needed. - Container: `div[data-testid="hatch-inline-approval-card"]` with `data-hatch-approval-surface="panel"`. - Header: `div[data-testid="approval-panel-header"]`. - Primary Allow action: `button[data-hatch-approval-primary-action="true"]` ("Allow once"). - Dropdown options: `button[data-slot="dropdown-menu-trigger"]` (contains "Always allow"). - Deny action: ``. ### Confirmed Live Selectors (2026-10-06): ```javascript // Active approval panel container 'div[data-testid="hatch-inline-approval-card"]' // Panel header '[data-testid="approval-panel-header"]' // Primary action button ("Allow once") 'button[data-hatch-approval-primary-action="true"]' // Background review surface ("N tasks need review" / "A task needs review") '[data-hatch-background-approval-surface="true"]' // Background review button trigger '[data-pel-click="chat_background_approval_review"]' ``` ### Queued Background Task Reviews ("N tasks need review") When multiple scheduled tasks or background operations trigger approval prompts concurrently (e.g. `opm` with scheduled Fleet Health Monitor runs): 1. Muse renders the first approval card inline over chat. 2. Below it, Muse docks a background approval banner: `
` stating `"N tasks need review"` with a `"Review"` button (`data-pel-click="chat_background_approval_review"`). 3. Allowing or denying the active approval immediately advances the queue: the next queued task pops into the active inline panel, decrementing the background count (e.g. from 2 down to "A task needs review" to clear). 4. Automated approval engines must inspect both the active card and `[data-hatch-background-approval-surface="true"]` to confirm whether agents remain blocked. ### Troubleshooting Blocked Agents - **In `muse-tui`**: Type `/blocked` (or press `[a]` / `F2`) from any view to open the Approvals & Blocked Tasks Drawer. Use `j`/`k` or arrow keys to navigate between blocked nodes; press `[1]` to Allow, `[2]` Always, `[3]` Deny, `[R]` Proceed, `[X]` Dismiss. Actions target the highlighted agent. - **In CLI**: Run `box blocked` or `box approvals` to view fleet approval status; use `box approvals allow ` to approve. ## 3. How `check_approvals` works today Location: `bin/muse-chat-api.py`, `check_approvals(ws)` (~line 70). Returns `[(dialog_text, is_trusted, action_taken)]`. **Detection** (two passes, JS evaluated via CDP `Runtime.evaluate`): 1. If `document.body.innerText` contains both `Allow` and `to share`: collect elements whose `innerText` contains both and is < 500 chars (first 3, text sliced to 200 chars). 2. Fallback: if no dialog found yet and ≥ 2 `