SCR.CDocument · Reading view
PUBLISHEDRICH BODYTOC + VERSIONS
Platform / Architecture / Runtime topology
Published
∹ RFC · PLATFORM / ARCHITECTURE · DOC #0a1e

Runtime topology
& co-hosting.

The Hono trunk is the top-level server: it hosts the SPA as static assets, the JSON-RPC capability surface, auth, MCP, and an embedded collaboration server — all on one owned port. This document fixes that decision and the four production-attach blockers it leaves open.

Authors NA JK AR Nadia A., Jo K. + archivist
Agent contributor AR archivist · AI
Published2026·05·31
Versionv14 · snapshot
Read time9 min · 2,410 w

01 Decision

Adopt a single-process trunk. The HTTP server, the static SPA assets, the /auth and /mcp mounts, the event-rendered published HTML, and the embedded Hocuspocus collaboration server co-host on one http.Server instance. No second framework hosts the collaboration WebSocket, and no reverse proxy is required for the surfaces to share a principal.

Invariant. The WebSocket upgrade authenticates the principal from the same-origin cookie before any document is reachable; per-document authorization runs at onAuthenticate. A rolled-back SQL transaction must never leave a mutation resident in the live Y.Doc once clients attach.

02 Co-hosting mechanism

The trunk owns the server; raw ws in noServer mode receives the upgrade and hands the connection to Hocuspocus. Static assets are served from the SPA build directory; everything else routes through the capability surface, so one origin and one cookie carry every principal — human or agent.

server.ts · upgrade handoffTS
// one owned http.Server โ€” all surfaces co-host
server.on("upgrade", async (req, socket, head) => {
  const principal = await resolver.fromCookie(req);
  if (!principal) return socket.destroy();
  ws.handleUpgrade(req, socket, head, (conn) =>
    hocuspocus.handleConnection(conn, req, { principal })
  );
});

03 Principals on one origin

Both humans and AI agents authenticate against the same cookie session and arrive as typed principals. An agent carries its own rate limit, capability scope, and audit attribution — the upgrade path does not special-case it beyond resolving the principal kind.

  • Human — session cookie, interactive scopes, presence shown as a square ultramarine marker.
  • Agent — scoped API key bridged to a session, distinct rate limit, notched-cyan presence and audit attribution.
  • Every mutation from either principal writes exactly one audit entry; the log alone reconstructs final state.

04 Open blockers

Four production-attach blockers remain before this topology is hardened for untrusted networks:

  • Role-aware read / write at onAuthenticate, not the tenant-only floor.
  • An Origin check on the WebSocket upgrade to reject cross-site sockets.
  • Revocation freshness on the upgrade-time principal snapshot.
  • Enforce the onAuthenticate invariant by construction, not by convention.
End of document · DOC #0a1e · last edited by AR archivist on 2026·05·31