pastilhasandClaude Opus 5 f3cc1242c4 minesweeper: extracted from the platform
Minesweeper X under wine on a headless display, as a plugin. It was
/api/minesweeper, a Dashboard screen, an officerdev panel, a permission
registry entry and a hand-written websocket provider in server.tsx.

The socket is why it had to live in the platform: Bun's route table is fixed
at serve(), so nothing installed later could add one. That ceiling is gone,
and this is the first plugin through the per-plugin relay.

Three things changed rather than moved:

The sidecar owns the session. The platform used to spawn bin/session.sh
detached, so the game outlived every restart, nothing supervised it, and a
crashed run left wine processes holding the prefix — the next start hung
rather than failed. PM2 supervises a sidecar, and stop() uses 'wineserver -k'
scoped by WINEPREFIX instead of 'pkill -f wineserver', which would have killed
every other wine prefix on the machine.

x11vnc moved from 127.0.0.1:5907 to a unix socket in a mode-0700 directory.
-nopw was only ever safe because of the machine, not the platform: any local
account could open that port and take the display. A fixed port is squattable
too. There is now no listener to authenticate against.

The wine prefix is confined to C:. This is the one that mattered. The platform
classified Minesweeper as kind:'execution' — never grantable — because a fresh
prefix maps the whole filesystem to Z: and symlinks the profile into the
owner's real home, and the game has Open and Save dialogs. A plugin permission
has no kind and is always grantable, so extracting it without this would have
converted a sealed capability into a file picker running as the owner.
Re-asserted on every start, because wine restores z: whenever it updates a
prefix.

Not solved: one display and one game, so two grantees share a board.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
2026-08-23 17:43:17 +00:00

Minesweeper

Minesweeper X, running under wine on a headless X display, streamed into an Officer panel.

It is a game. It is also the smallest honest proof that Officer can put an arbitrary X11 program in a panel — a framebuffer, a process on it, a VNC server reading it, a client in the browser — and it is the first plugin to use the platform's per-plugin websocket relay.

What it needs

Six host binaries, declared in manifest.ts and checked before install: wine, Xvfb, x11vnc, xdotool, xdpyinfo, winetricks.

The awkward one is wine. Minesweeper X is a 32-bit PE (machine 0x014c, Visual Basic 6), so the host needs i386 multiarch and a win32 prefix. A 64-bit-only wine cannot load it, and the failure is a bare Bad EXE format. On Debian or Ubuntu:

sudo dpkg --add-architecture i386
sudo apt update
sudo apt install wine wine32:i386 xvfb x11vnc x11-utils xdotool winetricks

The game

Minesweeper X — the competition build, with timing and replay extras. game/Minesweeper X.exe is committed; it is 68 KB and it is the thing being run rather than state produced by running it.

zip sha256 21089193924919ef876a5b464f06bed9cc149867c51e40c259288ebe623014f0
exe sha256 e414c207adaa14999b0464c3d0a701f20ed11282d5ed0f84b27b62d25389f661

The download needs a browser User-Agent; the site answers 403 to curl's default.

Where its state lives

DATA_PATH/minesweeper/ — never in this directory, which plugins:update will git pull over.

  • prefix/ — the wine prefix, ~600 MB, built on first POST /start. Deleting it is the standard fix for a wedged wine, and it is safe: the next start rebuilds it.
  • run/ — pid state, logs, and vnc.sock. Mode 0700, and that is load-bearing.

Two things worth knowing before you change anything

x11vnc has no password, and that is correct. It binds a unix socket inside run/, not a port. The kernel refuses every other account before x11vnc is asked anything, so a password would be a second lock on a door only one person can reach. The version this replaced bound 127.0.0.1:5907 with -nopw, which is a different claim entirely — every local account could open it and take the display.

The wine prefix is confined to C: on every start. A fresh prefix maps the whole filesystem to Z: and symlinks the profile into the real home, and Minesweeper X has Open and Save dialogs for its replays. That is why this was an ungrantable execution capability in the platform. sidecar/prefix.ts closes it instead, which is what makes the plugin's permission safe to grant. Wine restores z: whenever it updates a prefix, so the confinement is re-asserted rather than done once.

Contract

GET  /api/minesweeper/status     { installed, running, window, error? }
POST /api/minesweeper/start      idempotent; builds the prefix on a cold install (minutes)
POST /api/minesweeper/stop
     /api/plugin-ws/minesweeper  the display, as RFB
S
Description
Minesweeper X under wine on a headless display, streamed into an Officer panel
Readme
449 KiB
Languages
TypeScript 100%