Public: anyone can read this; the crew can change it.

A suspension holds in every process serving the forge, a roll's draining one included #908

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

Closes #846. It serves #875: two processes overlap during a roll.

shipped production is serving it for issue #846 — its issue is already done deploy b87f44f

opened this

Closes #846. It serves #875: two processes overlap during a roll.

Until now, a suspension or a sign-out ended what the account had open only in the process that did it, through its own event bus. During a roll the old process drains while the new one answers, and the old one never saw the other's bus. So the account's streams, app sockets and SSH sessions there ran on until they closed by themselves or the process exited. A read-only HTTP clone under way finished in either process.

Now the fact is written once and every process enforces it:

  • The fact is the account's row (suspended or removed) and the browser's session row, written by whichever process acts.
  • Every request already asks the database for standing (sessions and tokens refuse a suspended account), in every process.
  • Everything held open registers under its account, and under its browser where there is one, in src/http/caller.ts. That covers event streams, proxied app sockets, git transfers over HTTP and SSH sessions.
  • Every process sweeps what it holds against the database every standingSweepMs (default 5 s) and closes what is no longer allowed. The process that wrote the fact still closes at once through its bus. A roll's draining process closes within one sweep, so the overlap has no gap.

App sockets move from their own registry into this one (closeSocketsOf is gone), and git upload and receive processes are killed when their account loses its standing.

Tests: test/standing-every-process.test.ts, admitted to the gate. Two processes share one data directory, as in a roll, and the new one acts:

  • an event stream on the draining one ends, and its next request is refused;
  • an SSH session there ends;
  • a browser signed out through one process ends its streams on the other;
  • a git transfer under way there is cut;
  • an account in good standing keeps its stream through the sweeps.

Each case fails without its part of the change.

🤖 Generated with Claude Code

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs