Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ jobs:
run: bun install --frozen --ignore-scripts

- name: Sherif
# Deliberate version split: web's RemoteTerminal viewer uses the
# stable @xterm/xterm@5.x track; desktop uses the beta 6.x track
# for kittyKeyboard / scrollbar options that aren't on stable yet.
# See the comment in apps/web/.../RemoteTerminal/RemoteTerminal.tsx.
run: bunx sherif -i @xterm/addon-fit -i @xterm/xterm
run: bunx sherif

lint:
name: Lint
Expand Down
1 change: 0 additions & 1 deletion apps/desktop/src/main/host-service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ async function main(): Promise<void> {
`http://localhost:${env.DESKTOP_VITE_PORT}`,
`http://127.0.0.1:${env.DESKTOP_VITE_PORT}`,
],
hostServiceSecret: env.HOST_SERVICE_SECRET,
},
providers: {
auth: authProvider,
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import { DiffPaneHeaderExtras } from "./components/DiffPane/components/DiffPaneH
import { FilePane } from "./components/FilePane";
import { FilePaneHeaderExtras } from "./components/FilePane/components/FilePaneHeaderExtras";
import { TerminalPane } from "./components/TerminalPane";
import { TerminalHeaderExtras } from "./components/TerminalPane/components/TerminalHeaderExtras";
import { TerminalPaneIcon } from "./components/TerminalPane/components/TerminalPaneIcon";
import { TerminalSessionDropdown } from "./components/TerminalPane/components/TerminalSessionDropdown";

Expand Down Expand Up @@ -348,9 +347,6 @@ export function usePaneRegistry({
/>
</div>
),
renderHeaderExtras: (ctx: RendererContext<PaneViewerData>) => (
<TerminalHeaderExtras context={ctx} workspaceId={workspaceId} />
),
renderPane: (ctx: RendererContext<PaneViewerData>) => (
<TerminalPane
ctx={ctx}
Expand Down
41 changes: 7 additions & 34 deletions apps/relay/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import { startSyntheticCheck } from "./synthetic";
import { isTrpcPath, trpcErrorResponse } from "./trpc-error";
import { TunnelManager } from "./tunnel";

// Bearer tokens we never want in stdout. The remote-control viewer must
// put its token on the WS upgrade URL because browser WebSockets can't
// send custom headers, and Hono's default `logger()` echoes the full
// query string. Mask the values before they reach the log sink so the
// raw token doesn't end up in Fly logs / Sentry breadcrumbs.
const SENSITIVE_QUERY_RE = /([?&])(remoteControlToken|token)=[^&\s]+/g;
// Bearer tokens we never want in stdout. Hosts put their JWT on the WS
// upgrade URL because browser WebSockets can't send custom headers, and
// Hono's default `logger()` echoes the full query string. Mask the values
// before they reach the log sink so the raw token doesn't end up in Fly
// logs / Sentry breadcrumbs.
const SENSITIVE_QUERY_RE = /([?&])(token)=[^&\s]+/g;
const redactingLogger = logger((message, ...rest) => {
const redacted =
typeof message === "string"
Expand Down Expand Up @@ -271,35 +271,8 @@ app.get("/hosts/:hostId/_whoowns", async (c) => {
});

// ── Host proxy (auth required) ──────────────────────────────────────
//
// Remote-control viewer WebSockets (`/hosts/:hostId/remote-control/*`)
// authenticate via a per-session HMAC `remoteControlToken` query param
// that is verified by the host-service, not by us. Skip the user-JWT
// gate for those paths only — the HMAC is the credential the cloud
// hands to viewers, who may not have a Superset user JWT in the URL.
//
// We must still run the tunnel-presence + maybeReplay logic that
// `authMiddleware` does, otherwise viewer links break in multi-region
// Fly deployments whenever the load balancer lands a request on a
// relay instance that doesn't own the destination tunnel.

app.use("/hosts/:hostId/*", async (c, next) => {
const path = new URL(c.req.url).pathname;
const hostId = c.req.param("hostId") ?? "";
if (!hostId) return c.json({ error: "Missing hostId" }, 400);
const prefix = `/hosts/${hostId}`;
const rest = path.slice(prefix.length);
if (rest.startsWith("/remote-control/")) {
if (!tunnelManager.hasTunnel(hostId)) {
const replay = await maybeReplay(hostId);
if (replay) return c.body(null, 200, replay.header);
return c.json({ error: "Host not connected" }, 503);
}
c.set("hostId", hostId);
return next();
}
return authMiddleware(c, next);
});
app.use("/hosts/:hostId/*", authMiddleware);

app.all("/hosts/:hostId/trpc/*", async (c) => {
const hostId = c.get("hostId");
Expand Down
Loading
Loading