minesweeper leaves the platform; plugin sockets relay ws-to-ws
Minesweeper is now plugins/minesweeper (gitea.officer.dev/plugins/minesweeper). Removes /api/minesweeper, the Dashboard screen, the officerdev panel, the permission registry entry, the App.tsx route and the hand-written websocket provider in server.tsx. Registry entries: 22 -> 21, execution 4 -> 3. The relay changed transport, and that is the part worth reading. A sidecar announces exactly one port. That single announcement is the whole provenance argument in target.ts — the platform watched the port arrive at registration, which is the only thing separating it from a number a manifest asserted. But a raw-TCP relay requires that port to BE a raw TCP listener, so the sidecar cannot also serve HTTP on it, and the plugin's ordinary routes have to fall back to the typed command vocabulary over the registration socket. That is the mechanism the fleet has spent months retiring, and Minesweeper would have been the first thing to go back to it. Relaying websocket-to-websocket dissolves the conflict. The sidecar serves HTTP and /ws on the one port it announced, exactly as the pty sidecar already does; createSidecarProxy handles the HTTP half; and the conversion from frames to whatever the plugin actually speaks happens inside the plugin, which is the only process that knows. The relay is still ignorant of the payload — the ignorance sits one layer up. Also: the caller's JWT is no longer forwarded upstream. A sidecar has no use for it and forwarding one puts a bearer token into whatever that process logs. X-Officer-User carries the only part it needs. (The terminal relay still forwards its token to the pty sidecar; not touched here.) Verified: bunx tsgo clean, bun test 1403 pass / 0 fail, bun run docs:check green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
@@ -285,10 +285,10 @@ export type PluginManifest = {
|
||||
/**
|
||||
* A websocket this plugin serves, relayed by the platform.
|
||||
*
|
||||
* Declaring this makes `/api/plugin-ws/<appName>` a byte relay onto the address below. It exists because
|
||||
* Bun's route table is fixed at `serve()`, so a plugin installed afterwards could never add a socket route
|
||||
* — which is why `/minesweeper` had to live in the platform and `plugins/desktop` could not stream a
|
||||
* display at all.
|
||||
* Declaring this makes `/api/plugin-ws/<appName>` a frame relay onto `ws://127.0.0.1:<port>/ws`, where the
|
||||
* port is the one the named sidecar announced at registration. It exists because Bun's route table is
|
||||
* fixed at `serve()`, so a plugin installed afterwards could never add a socket route — which is why
|
||||
* `/minesweeper` had to live in the platform and `plugins/desktop` could not stream a display at all.
|
||||
*
|
||||
* Authorisation is the plugin's OWN capability, asked as if the socket were a GET against its HTTP prefix.
|
||||
* There is deliberately no separate socket permission: granting the plugin grants its socket, and nothing
|
||||
@@ -308,7 +308,13 @@ export type PluginManifest = {
|
||||
* manifest asserted. Provenance, not a claim.
|
||||
*
|
||||
* The cost is that a plugin wanting a socket needs a sidecar. That is not ceremony — it is the thing
|
||||
* that makes the port mean anything.
|
||||
* that makes the port mean anything. It costs nothing else: the socket lives at `/ws` on the SAME
|
||||
* listener the sidecar already serves its routes from, so a plugin does not choose between having a
|
||||
* socket and having ordinary HTTP.
|
||||
*
|
||||
* **The sidecar serves a websocket, not a raw stream.** Whatever it is really talking to — a VNC display,
|
||||
* a line protocol, another process entirely — the conversion happens inside the plugin, because the
|
||||
* plugin is the only thing that knows. The platform moves frames it does not read.
|
||||
*
|
||||
* The host is always loopback and cannot be set. A plugin naming an arbitrary host would be a
|
||||
* request-forgery primitive reachable by anyone the plugin is granted to.
|
||||
|
||||
Reference in New Issue
Block a user