# Bellona Control Room

Browser-first operator surface for the Bellona remote-control MVP.

The app is scaffolded behind `VITE_BELLONA_CONTROL_ROOM_ENABLED`. The default
state is disabled, including production builds. Local development and Playwright
coverage can opt in explicitly:

```bash
pnpm nx serve @bellona/control-room
VITE_BELLONA_CONTROL_ROOM_ENABLED=true pnpm nx serve @bellona/control-room
pnpm nx e2e @bellona/control-room
```

Route ownership:

- `/control-room` renders the operator shell only when the feature flag is set
  to `true`.
- `/mobile-approvals` renders the approval-only mobile PWA surface when the
  feature flag is set to `true`.
- `/` redirects to `/control-room` only when enabled; otherwise it renders the
  disabled gate.
- No gateway, host, desktop, browser, Blender, or Unreal privileges are exposed
  from this scaffold.

Operator workflow:

- Use
  [`docs/domains/bellona/extras/remote-control/operator-workflow-blender-browser-mvp.md`](../../../docs/domains/bellona/extras/remote-control/operator-workflow-blender-browser-mvp.md)
  when watching the current Blender and browser MVP CLI smokes from the Control
  Room context.
- Use the `Review` workspace to keep command progress, pending approval state,
  approve/deny controls, and screenshot-first stream status visible in one
  operator flow.

Keyboard shortcut map:

| Action           | Shortcut   | Scope                    | Browser-default conflict check                  |
| ---------------- | ---------- | ------------------------ | ----------------------------------------------- |
| Approve once     | Ctrl+Alt+A | Pending approval         | Clear; no common browser default uses it.       |
| Deny             | Ctrl+Alt+D | Pending approval         | Clear; no common browser default uses it.       |
| Pause stream     | Ctrl+Alt+P | Active screenshot stream | Clear; avoids browser print shortcuts.          |
| Resume stream    | Ctrl+Alt+R | Paused screenshot stream | Clear; avoids browser reload shortcuts.         |
| Stop stream      | Ctrl+Alt+S | Running stream           | Clear; avoids browser save shortcuts.           |
| Request takeover | Ctrl+Alt+T | Operator control         | Clear; avoids browser tab-management shortcuts. |

Shortcuts are ignored while focus is inside text fields so deny reasons and
other operator notes can be typed without triggering a global command.

Desktop notifications:

- The MVP uses the browser `Notification` API so macOS can route granted web
  notifications into Notification Center while the Control Room is open.
- The Control Room detects unsupported, pending, granted, and denied permission
  states and only constructs OS notifications after permission is granted.
- Operators can independently mute or enable approval-required, host-offline,
  long-running completion, and policy-denial event classes.
- Preferences are persisted in local browser storage. Cross-platform native,
  mobile push, and service-worker notification channels remain deferred to
  `180.C.31.06` and `180.C.34`.

Mobile approval PWA:

- `/mobile-approvals` is a focused, installable approval-only route with large
  touch targets for approve once and deny decisions.
- The route ships a web app manifest, standalone mobile metadata, and a static
  service worker at `/control-room-sw.js`.
- The service worker handles incoming push payloads, displays approval
  notifications with approve/deny actions, and returns notification actions to
  the mobile approval route through client messages or a focused/opened window.
- The current MVP registers the service worker and verifies browser
  `PushManager`/`Notification` capability, but it does not create a live gateway
  push subscription because the gateway VAPID/public push endpoint is still out
  of scope for this stage.

Command palette:

- The operator command palette is visible in the Control Room shell and is
  searchable by protocol namespace, command name, title, and description.
- The command registry is drawn from `REMOTE_COMMAND_NAMESPACE_VALUES` in
  `@bellona/remote-protocol` so every canonical namespace has a palette entry.
- Ad-hoc palette commands are approval-required by default. Queueing a command
  records an audit preview with the selected command and payload, then moves the
  operator to the approval workspace; it does not dispatch to a live host.

First-session guided tour:

- The Control Room shell includes a three-checkpoint tour for a new operator's
  first successful session path: `blender.scene.query`, `browser.navigate`, and
  the screenshot-only stream preview.
- The tour is capped at a five-minute fixture-backed path and persists completed
  checkpoints in local browser storage so a reload does not restart progress.
- The Blender and browser checkpoints reuse the command palette audit capture
  and approval-required queueing path. The screenshot checkpoint reuses the
  stream MVP `start-screenshot` state transition.

Device permission diagnostics:

- Device summaries surface host-sourced macOS TCC diagnostics for desktop
  fallback readiness. Missing Screen Recording appears as a blocked
  `desktop.observe` permission and missing Accessibility appears as a blocked
  `desktop.input` permission.
- The selected-device inspector includes the host remediation reason so an
  operator can distinguish an unapproved permission from a macOS Privacy &
  Security permission that is missing on the remote host.
