Skip to content

fix(remote-control): wire control token + post-pairing identity refresh/reconnect#159

Merged
andrescera merged 1 commit into
mainfrom
fix/control-token-pairing-reconnect
Jul 18, 2026
Merged

fix(remote-control): wire control token + post-pairing identity refresh/reconnect#159
andrescera merged 1 commit into
mainfrom
fix/control-token-pairing-reconnect

Conversation

@andrescera

Copy link
Copy Markdown
Member

What

A small, sanctioned pre-release fix to the device control plane, split out from the later Phase-B PR so it ships in the baseline release:

  • Control token is now presented on the control-channel dial. The production getControlToken seam defaulted to () => undefined, so dial() always opened an unauthenticated control socket that the LAN gateway rejects. It now reads the persisted claim/control credential (config.remote_key); the existing local purpose+signature verification (verifyDeviceControlToken) is retained and still drops a non-device-control or unverifiable token, falling back to the key-less path.
  • Post-pairing reconnect without a reboot. After a successful platform claim, the pairing procedure runs an idempotent identity refresh + control-channel reconnect (initIdentity() + initControlChannel()), so a freshly claimed device dials the hub with its new token immediately instead of only after the next boot.
  • Device-side pairing authorization header. The pairing RPC schema gains an optional authorization field; when present, the backend forwards it as the x-ceralive-pairing-authorization header on both the pairing-secret registration and the claim requests. A paste field is added to the CeraLive pairing surface in CloudRemoteDialog.
  • Baseline version bump to 2026.7.1 (root package.json; federation producer-version doc updated to match).

Why

  • The control channel could never authenticate: with no token source wired, every device presented an anonymous socket the gateway drops. Boot-only identity init also meant a just-claimed device stayed offline on the control plane until it rebooted.
  • Both platform pairing routes require a tenant credential (they 401 without one); the device previously sent only content-type. This wires the device's send-half. The header literal is pre-pinned here (x-ceralive-pairing-authorization); the platform-side acceptance is a separate, later change, so this only sends the header when the operator provides one.
  • This fix must be in the baseline image so the device supports the gateway session; hence a separate small PR ahead of the Phase-B work.

How to verify

  • bun run lint — clean (Biome + backend typecheck + frontend svelte-check + workspace lints).
  • bun test (backend) — 1941 pass / 0 fail, including:
    • control dial presents the verified token to the hub socket, and drops an unverified one;
    • the default getControlToken presents the persisted remote_key;
    • the post-pairing reconnect opens the control gate (canDialControlChannel()) without a manual initIdentity();
    • the x-ceralive-pairing-authorization header reaches both HTTP calls when present, and is omitted when absent.
  • bun run --filter @ceraui/rpc test193 pass / 0 fail.
  • Frontend pairing.test.ts9 pass (PairingController forwards the optional authorization).

Risks

Low. The token wiring reuses the existing verification gate unchanged — a bad/opaque token still drops to the key-less path, so no device that works today regresses. The reconnect is idempotent and fail-soft (unprovisioned hub URL is logged, not thrown). The authorization header is send-only and conditional; the platform side is intentionally not assumed here. No change to the SRT/SRTLA media path or the BCRPT relay socket.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 51f0c301-7ec4-4b5e-82eb-cdac44dca44d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/control-token-pairing-reconnect

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@andrescera
andrescera merged commit bceb588 into main Jul 18, 2026
12 checks passed
@andrescera
andrescera deleted the fix/control-token-pairing-reconnect branch July 18, 2026 02:53
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.

1 participant