import { sidecarPort } from '@@/sidecar-registry'; import { snapshotPlugins } from '@@/plugins/mount'; /* Where a plugin's socket actually goes. A target is an ADDRESS — a host and a port — never a URL a manifest wrote. The relay turns it into `ws://:/ws`, and `/ws` is a convention rather than a setting for the same reason the host is not configurable: every value here has to be one the platform derived, not one a plugin asserted. The target is always a SIDECAR. A fixed-port form was written and removed the same day: nothing stops a manifest naming a port it does not own, so `{ port: 5432 }` plus a grant would be a raw TCP relay onto Postgres for anyone that plugin reaches. Verifying the host is loopback is not verifying the port belongs to the plugin, and only the second question matters. A sidecar's port is different in kind, not degree: the platform watched it arrive at registration, so the association is observed rather than asserted. It is also the SAME port the sidecar serves its HTTP on — one announcement, one listener, `/ws` alongside the routes. That is what the relay's move to websocket-to-websocket bought, and why a plugin wanting a socket no longer has to choose between having one and having ordinary routes. **Host is always loopback and is not configurable.** A plugin socket that could name an arbitrary host would be a request-forgery primitive handed to every plugin author and reachable by anyone the plugin is granted to. There is no case for it that a sidecar does not already serve. */ export type PluginWsTarget = { host: string; port: number }; export async function pluginWsTargetFor(appName: string): Promise { const { states } = await snapshotPlugins(); // Installed, not merely present on disk. A plugin directory that exists but is not installed has no // routes and no permission, so it must have no socket either. const state = states.find((st) => st.plugin.appName === appName && st.install); const socket = state?.plugin.manifest.websocket; if (!socket) return null; // A sidecar that has not announced its port yet is indistinguishable from one that never will, and both // are correctly a refusal — there is nothing to relay onto. The caller says "not accepting connections", // which is true either way. const port = sidecarPort(socket.sidecar); return port ? { host: '127.0.0.1', port } : null; }