Skip to content

fix(server): keep bb connect's account status reads available during a server move freeze - #4881

Closed
theFong wants to merge 1 commit into
get-bb:mainfrom
theFong:fix/server-move-freeze-bb-account-status
Closed

theFong wants to merge 1 commit into
get-bb:mainfrom
theFong:fix/server-move-freeze-bb-account-status

Conversation

@theFong

@theFong theFong commented Oct 5, 2026

Copy link
Copy Markdown

Human comments

What was wrong

During a bb server move, serverMoveFreezeMiddleware rejects every /api/v1/* request that isn't GET/HEAD/OPTIONS or under /api/v1/server/move with 503 server_moving (apps/server/src/services/server-move/freeze.ts). Plugin RPC is always POST /api/v1/plugins/<id>/rpc/<method>, so the connect plugin's reads of the bb-account plugin were frozen too. The move keeps both plugins running on purpose (CONNECT_HOLD_SOURCES). Connect long-polls bb-account.v1.waitForStatusChange, which returns at least every 25 s (LONG_POLL_TIMEOUT_MS), and then reads bb-account.v1.status. Its account client maps any 503 to AccountUnavailableError (plugins/connect/src/account-client.ts), and AccountLink treats that as signed out and calls onAccount(null), which closes the tunnel. Every daemon that reaches the server through bb connect loses its session, including the move target, so any connect move still frozen when the current long-poll returns fails with "Send data to : Host is not connected". This has the same root cause as #4837 (the freeze blocks a bb-account RPC the move depends on), but it hits a different call. #4838 fixes only the grant ordering. This is likely also what caused the mid-move 1001 tunnel disconnected in #4394.

What changed

  • apps/server/src/services/server-move/freeze.ts: isServerMoveFreezeExempt now also exempts three exact paths, /api/v1/plugins/bb-account/rpc/bb-account.v1.status, .../bb-account.v1.waitForStatusChange and .../bb-account.v1.connectCredential. Their handlers only read state: account.status(), a long-poll on the status revision, and returning the stored credential. Everything else on bb-account stays frozen: bb-account.v1.fetch, adoptConnectCredential, confirmRefusedCredential, login.*, redeemCode and signOut. These can write state that the export snapshot would lose. The server doesn't import plugin packages and had no constant for these method names or the bb-account plugin ID, so the paths are an exact-match set local to freeze.ts. Look-alike methods, other plugin IDs, trailing segments and prefixed paths don't match.
  • docs/server-move-plan.md: the "At the freeze" bullet now says the read-only bb account RPCs that bb connect polls stay available, so the tunnel stays up. The bb guide machines text doesn't describe what the freeze exempts, so it is unchanged.
  • No wire, CLI, SDK, or HOST_DAEMON_PROTOCOL_VERSION changes.

This implements fix 1 from the issue. Fix 2 is left as a possible follow-up hardening: connect's account client could treat 503 server_moving as transient instead of AccountUnavailableError, so AccountLink keeps the last known account and retries. This PR does not include the runStopWork grant-ordering change from #4838. The two PRs touch the same test file, but #4838's diff applies cleanly on top of this branch (git apply --3way --check).

How you verified

New tests:

  • test/server-move/freeze.test.ts
    • "exempts only the read-only bb account RPCs that bb connect polls" (unit test of isServerMoveFreezeExempt).
      • Exempt: the three status reads.
      • Not exempt: bb-account.v1.fetch, adoptConnectCredential, confirmRefusedCredential, login.start, redeemCode, signOut, bb-account.v1.statusX, bb-account.v1.status/extra, bb-account.v1.waitForStatusChange/, the same method under connect and bb-account-evil, /api/v1/plugins/bb-account/cli, a prefixed path, and POST /api/v1/threads.
    • "keeps bb connect's bb account status reads open while frozen so the tunnel stays up" (Hono app with serverMoveFreezeMiddleware and createServerErrorHandler).
      • The three status-read POSTs return 200 while frozen.
      • fetch, adoptConnectCredential and confirmRefusedCredential still return 503 server_moving.
  • test/server-move/coordinator.test.ts
    • "keeps bb connect's bb account status reads open while a bb connect move is frozen". This test runs a real connect-mode move. The export step makes plugin RPC POSTs through the real middleware, wired to coordinator.isFrozen() as in server.ts.
      • While the coordinator is frozen, waitForStatusChange, status and connectCredential return 200 and fetch returns 503.
      • The move completes.

Fail before (new tests on main at 300a08b, freeze.ts unchanged):

$ pnpm exec turbo run test --filter=@bb/server -- test/server-move/freeze.test.ts test/server-move/coordinator.test.ts
 FAIL  test/server-move/coordinator.test.ts > server move coordinator > keeps bb connect's bb account status reads open while a bb connect move is frozen
   (each of the three status reads: expected 200, received 503)
 FAIL  test/server-move/freeze.test.ts > server move freeze middleware > keeps bb connect's bb account status reads open while frozen so the tunnel stays up
   AssertionError: bb-account.v1.status: expected 503 to be 200
 FAIL  test/server-move/freeze.test.ts > server move freeze middleware > exempts only the read-only bb account RPCs that bb connect polls
   AssertionError: /api/v1/plugins/bb-account/rpc/bb-account.v1.status: expected false to be true
 Tests  3 failed | 25 passed (28)

Pass after:

$ pnpm exec turbo run test --filter=@bb/server -- test/server-move
 Test Files  16 passed (16)
      Tests  100 passed (100)

$ pnpm exec turbo run typecheck --filter=@bb/server
 Tasks:    5 successful, 5 total

pnpm exec oxfmt --check passes on the changed TypeScript files.

On my first full-suite run after the fix, one test failed: the existing "runs a direct move in step order and hands the server to the target". Its expect.poll timed out at the default 1 s. Two re-runs passed 100/100. That test never touches a bb-account path, and on unmodified main it takes about 2.5 s under the same suite load, so the failure was timing and not this change.

Manual check on a real move, done while investigating #4880: this exemption (plus #4838) was patched into the shipped bb 0.45.0 bundle. A bb server move from macOS to an Ubuntu machine enrolled over bb connect then completed in 39 s. There were no bb-account 503s, the tunnel stayed up for the whole freeze, and daemon sessions closed only at the switch. Without the exemption, the tunnel dropped 9 s into the freeze, when connect's in-flight waitForStatusChange long-poll returned into a 503, and the move failed at "Send data" (logs in #4880).

Fixes #4880

Related: #4837 and #4838 (same freeze-vs-bb-account cause, different call), #4394 (likely the same mid-move tunnel drop).

AGENT GENERATED

…a server move freeze

The server move freeze rejected every non-GET request outside
/api/v1/server/move with 503 server_moving, including plugin RPCs, which
are always POST. bb connect long-polls bb-account.v1.waitForStatusChange
(returning at least every 25 s) and reads bb-account.v1.status and
bb-account.v1.connectCredential. Its account client maps any 503 to
AccountUnavailableError, so AccountLink treated the frozen server as signed
out and closed the tunnel, dropping every daemon session that reaches the
server through bb connect, including the move target. The move then failed
at "Send data to <target>: Host is not connected".

Exempt exactly those three read-only bb-account RPC paths from the freeze.
Writable bb-account RPCs (fetch, adoptConnectCredential,
confirmRefusedCredential, login, redeem, sign-out) stay frozen.

Fixes get-bb#4880
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Thanks @theFong for the PR. This repo needs approval before a PR. Join the #contributors channel in Discord (https://discord.gg/kvBU6tJhcJ) and explain what you want to open a PR for and why. A maintainer then adds you to the allow list. This PR now closes on its own. Reopen it or open a new one after approval.

@github-actions github-actions Bot closed this Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server move (bb connect) drops the tunnel about 25 seconds into the freeze: connect reads the freeze's 503 on bb-account status as a sign-out

1 participant