feat: wss for the realtime connection with a local CA bundle #3

Merged
troed merged 6 commits from feat/ota-wss into main 2026-10-10 17:35:30 +02:00
Owner

wss for the realtime connection, with a local CA bundle

Implements the communicator-sailfish side of the OTA design
(starfleet/crew:docs/specs/2026-09-10-ota-design.md, §8) — plan 4 of 4
(crew, computer, communicator-esp32, communicator-sailfish).

The realtime WebSocket moves from plaintext ws:// to wss://, validated
against the same local CA the other Starfleet clients pin (the crew/computer
TLS cutover, spec §10).

What this adds

  • Backend TLS (qml/py/backend.py): the backend resolves a CA bundle
    from STARFLEET_CA_BUNDLE, else a CA shipped in app resources at
    qml/py/starfleet-ca.pem; when a CA is present it connects wss:// with
    ssl.create_default_context(cafile=...) (hostname verification left on).
    When no CA is configured it stays plaintext ws:// — the dev default.
  • No silent downgrade: a CA that is configured but missing/unreadable, or
    that fails to load, surfaces a connect_error and aborts instead of
    falling back to plaintext.
  • Packaging: a guarded qmake INSTALLS rule (src/src.pro) ships
    qml/py/starfleet-ca.pem when present, so release RPMs carry the trust
    anchor while CA-less dev builds still build. The real CA is rollout
    material and is gitignored.
  • Tests: 35 passing, including real wss:// handshakes — a cert signed by
    the test CA is accepted, an untrusted cert is rejected (test keys generated
    at test time; only a public cert is committed).

Note on branch contents

feat/ota-wss was branched from main, which carried one pre-existing
unpushed commit unrelated to OTA — abf3d07 fix: keep reconnecting after server restart instead of giving up (which is why the test baseline grew
from 26 to 27). That commit is included in this PR.

Follow-ups

  • AGENTS.md still records the pre-change test count (30); the suite is now
    35.
  • The plaintext dev default relies on no CA file being staged; a test fixture
    now pins that, but a stray real qml/py/starfleet-ca.pem on a dev machine
    will still switch the singleton to wss://.
# wss for the realtime connection, with a local CA bundle Implements the communicator-sailfish side of the OTA design (`starfleet/crew:docs/specs/2026-09-10-ota-design.md`, §8) — plan 4 of 4 (crew, computer, communicator-esp32, communicator-sailfish). The realtime WebSocket moves from plaintext `ws://` to `wss://`, validated against the same local CA the other Starfleet clients pin (the crew/computer TLS cutover, spec §10). ## What this adds - **Backend TLS** (`qml/py/backend.py`): the backend resolves a CA bundle from `STARFLEET_CA_BUNDLE`, else a CA shipped in app resources at `qml/py/starfleet-ca.pem`; when a CA is present it connects `wss://` with `ssl.create_default_context(cafile=...)` (hostname verification left on). When no CA is configured it stays plaintext `ws://` — the dev default. - **No silent downgrade**: a CA that is configured but missing/unreadable, or that fails to load, surfaces a `connect_error` and aborts instead of falling back to plaintext. - **Packaging**: a guarded qmake `INSTALLS` rule (`src/src.pro`) ships `qml/py/starfleet-ca.pem` when present, so release RPMs carry the trust anchor while CA-less dev builds still build. The real CA is rollout material and is gitignored. - **Tests**: 35 passing, including real `wss://` handshakes — a cert signed by the test CA is accepted, an untrusted cert is rejected (test keys generated at test time; only a public cert is committed). ## Note on branch contents `feat/ota-wss` was branched from `main`, which carried one pre-existing unpushed commit unrelated to OTA — `abf3d07 fix: keep reconnecting after server restart instead of giving up` (which is why the test baseline grew from 26 to 27). That commit is included in this PR. ## Follow-ups - `AGENTS.md` still records the pre-change test count (30); the suite is now 35. - The plaintext dev default relies on no CA file being staged; a test fixture now pins that, but a stray real `qml/py/starfleet-ca.pem` on a dev machine will still switch the singleton to `wss://`.
A configured-but-unreadable/missing CA and an invalid CA bundle both now
surface connect_error and set disconnected instead of silently falling
back to ws:// or dying in the worker thread. Add real wss handshake tests
(CA-signed accepted, untrusted rejected) and isolate the default CA in
tests so a stray local starfleet-ca.pem cannot flip the plaintext suite.
troed merged commit 692c604a7a into main 2026-10-10 17:35:30 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
starfleet/communicator-sailfish!3
No description provided.