Files
ServerKit/backend
Juan DenisandClaude Opus 5 1f92ae1c91 fix(connect): use the policy door, the privilege wrapper, and safe reads
Four things the guards and the review caught, all of them real:

- app/api/connect.py: GET /connect/status carried a bare @jwt_required(),
  which the jwt-only census forbids for a new route (609 vs a ceiling of
  608). It is an admin read of pairing state, so it takes @admin_required
  — the same door the rest of the admin surface uses, API-key capable by
  way of auth_required() like its neighbours.
- connect_policy._systemctl ran systemctl through raw subprocess, one over
  the raw-subprocess ceiling. run_privileged() adds sudo when the panel is
  not root, so the fail2ban repair now works off a packaged install
  instead of reporting a permission error nobody can act on.
- connect_client.hello_headers assumed the end-to-end key fields were
  always there. build_hello() drops them rather than fail the connection,
  so a panel that could not read its X25519 key would KeyError on the
  long-poll fallback — exactly the path taken when things are already bad.
- status() called resolve_cloud_url(), which raises on a URL with no
  scheme. A typo in SERVERKIT_CLOUD_URL should surface when you pair, not
  turn `serverkit connect status` and the Settings panel into an error.

Both connect threads are now classified in the thread-ownership registry:
the relay loop is a process loop, and a signed command is bounded delivery
whose record lives in the control plane.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018q56AfqpgKjio4n9KYubvZ
2026-09-03 00:19:27 -04:00
..