# OSHUN V10 Rail shell

This Tauri 2 application is the native host for the shared Rail frontend in
`apps/v10/web`. It does not maintain a second UI implementation.

- `pnpm dev` starts the web app on `http://127.0.0.1:3095` through Tauri's
  `beforeDevCommand` and opens that URL in the native webview.
- `pnpm build` creates the web static export first, embeds `apps/v10/web/out`,
  and compiles the native release binary.
- `pnpm check`, `pnpm lint`, `pnpm test`, and `pnpm format:check` run the
  targeted Rust verification gates.
- `pnpm verify:launch` builds and starts the native binary, then verifies its
  launch, persisted window state, and platform-native controls. See
  `LAUNCH_VERIFICATION.md` for the automated macOS checks and the short visual
  signoff that still needs human eyes.

Move the window within 24 logical pixels of a monitor's left or right work-area
edge to snap it flush. The native **Rail** menu exposes the same actions through
`CmdOrCtrl+Shift+ArrowLeft` and `CmdOrCtrl+Shift+ArrowRight` while the app is
focused.

Use **Keep on Top** in the native **Rail** menu or tray, or press
`CmdOrCtrl+Shift+P`, to toggle the window's always-on-top state. Both checkboxes
stay synchronized with the real window state, which is saved immediately.

The desktop shell registers two system-global accelerators, so they work while
another app has focus: `CmdOrCtrl+Shift+X` emits the discretion `panic()` event
and hides the panel immediately, while `CmdOrCtrl+Shift+L` toggles panel
visibility. A hidden discretion session remains protected when shown and still
requires the Rail's explicit restore confirmation.

On macOS 14.4 and newer, a one-second native monitor uses ScreenCaptureKit's
current-process shareable-content API to observe whether the Rail window is
actively streamed. This path does not request Screen Recording permission or
inspect other applications. Linux and Windows return an explicit
`supported: false` status; detector errors do the same and never auto-restore
protected tiles.

All webview/native IPC names and payloads are closed by the shared
`v10.shell-bridge.4` descriptor and Zod schemas in
`libs/contracts/src/v10/shell-bridge.ts`. Rust owns matching decoded types for
window operations, tray snapshots, native shortcut/menu events, and screen-share
status, and the dogfood journal; its contract audit reads the same JSON
descriptor so name or fixture drift fails the shell test suite.

The webview mirrors its versioned local dogfood journal through the typed
`save_rail_dogfood_journal` command. Rust independently decodes the closed calm
metric union, enforces event and byte bounds, rejects duplicate identifiers, and
replaces `dogfood-journal.json` through a private temporary file under the
platform app-data directory. The file and parent directory are owner-only on
Unix. Nothing uploads the journal; the native copy exists so the local
`rail dogfood-report` command can find it without a browser export.

Autostart is device-local and opt-in. The official Tauri autostart plugin is
registered with the macOS LaunchAgent backend, but setup never calls `enable`;
only the typed settings command can add or remove the operating-system login
registration, and every write is read back before success is reported.

The tray also exposes panel visibility, a discretion hide, live audio-lane
play/pause, skip, and handoff controls, plus three disabled text glance lines.
Its status includes the real holder volume and queued-offer count. Play/pause is
capability-gated, handoff is enabled only for a queued offer, and an idle lane
can accept that next offer without reopening the panel. Glances use the
frontend's effective text-only projection during privacy modes. Closing the
panel hides its live webview instead of destroying it, so the frontend kernel
and tray transports continue running headless. Use **Show Panel** to restore the
same session or **Quit The Rail** to exit it explicitly.

The shell writes `window-state.json` under the platform app-config directory on
focus loss, explicit docking, and close-to-tray. The versioned state restores
the monitor, dock edge, logical size, always-on-top value, and visibility on the
next launch.

Native packaging remains disabled at this scaffold stage. The release binary
still uses Tauri's production custom protocol and embeds the static web bundle;
installer targets can be enabled when the platform release work begins.

The packaged webview enforces an explicit CSP for the docked-player boundary:
privacy-enhanced YouTube and the Twitch player are the only frame origins, the
two official interactive-player SDK hosts are the only remote script origins,
and the Rail itself rejects all frame ancestors. The exact provider-visible
data, same-origin/SDK trust distinction, browser-host header requirements, and
custom-protocol referrer release gate are documented in the web module's “Embed
security and privacy review.”
