Wednesday, 16 July 2026

Session History

Brainstormed and scaffolded rokojori-tunnel — user-based local tunneling service.

What we built

rokojori-tunnel — Phase 1 (relay server)

New standalone service at C:\rokojori\projects\web-projects\tunnel, same stack as the rest of the ecosystem (Node.js, Express, ts-node, JSON file storage, shared JWT verification).

  • source/server/db.ts — JSON file storage for tunnel configs (build/data/db/tunnels.json)
  • source/server/middleware/requireAuth.ts — JWT verification, same pattern as rokojori-auth
  • source/server/relay/TunnelRegistry.ts — in-memory Map<tunnelId, WebSocket> of active agent connections
  • source/server/relay/pending.ts — pending request callbacks keyed by reqId for matching responses to waiting HTTP connections
  • source/server/routes/tunnels.ts — full CRUD plus GET /api/tunnels/available?purpose= discovery endpoint
  • source/server/routes/agent.ts — WebSocket upgrade handler; verifies JWT, confirms ownership, registers socket in registry
  • source/server/routes/proxy.tsALL /t/:tunnelId/* relay; soft auth check for access mode, raw body forwarding, 30s timeout
  • source/server/index.ts — Express + HTTP server with manual WebSocket upgrade routing; JSON middleware applied only to /api routes so proxy receives raw body streams
  • scripts/test-agent.ts — standalone Node.js agent for testing before the Electron app exists; connects via WebSocket and forwards inbound relay requests to a local port

End-to-end test — local LLM over tunnel

Registered a tunnel via POST /api/tunnels, started the test agent forwarding to port 8900 (gemma4-coding-Q4_K_M.gguf running locally), and sent an OpenAI-compatible /v1/chat/completions request through the relay. Full round-trip succeeded — request forwarded, response relayed back, streaming token count confirmed in the response.

tunneling.html outline document

New plan document at workspace/outline/tunneling.html covering: the relay mechanic (three-leg model, minimal inspection, raw byte forwarding), access modes (private / public / password-protected), tunnel metadata shape and purpose tags, all three components (relay server, Electron agent app, rokojori-auth permission), API endpoint reference, Roject LLM provider integration example, file structure, and phased implementation plan.

Key decisions

Separate service, not part of rokojori-auth. Auth stays focused on identity. tunnel.rokojori.com is its own Express process that verifies the shared JWT but owns all relay logic independently.

HTTP-only for Phase 1. Stable Diffusion (AUTOMATIC1111) and OpenAI-compatible LLMs (Ollama, LM Studio) all speak HTTP with SSE streaming — no WebSocket from the app side needed. Language servers use raw TCP and are out of scope for now.

JSON envelope protocol for Phase 1. Requests and responses are wrapped as { reqId, method, path, headers, body (base64) } JSON messages over the agent WebSocket. No raw byte framing needed at this stage; the JSON envelope is simple enough and sidesteps binary WebSocket complexity.

No express.json() on proxy routes. The JSON middleware is applied only to /api/tunnels so the proxy handler always receives a raw readable body stream, regardless of content type.