feat(connections): scan-to-connect — QR channel pairing (Telegram + Discord)#9
Merged
Merged
Conversation
…+ Discord Connect a channel by scanning a QR — from Vesper World or the terminal — with the chat captured automatically (no copying ids). Dependency-free; bot tokens stay CLI/stdin -> Keychain. - core: optional Pairable capability (startPairing -> streamed PairingUpdates); portable Nayuki QR encoder + half-block terminal renderer (media/qr); pairable channel-state flag; pairing audit kinds with nonce/qr redaction - telegram: t.me/<bot>?start=<nonce> deep-link QR auto-captures chatId via the bot long-poll - discord: OAuth2 invite QR (state=<nonce>) + first `pair <nonce>` message captures the channel - daemon: PairingCoordinator multiplexes the single inbound long-poll into chat sink + pairing sessions (transient receiver for not-yet-running channels); persists params.defaultChatId on link - ui/cli: POST /api/connections/:id/pair ndjson + GET /api/qr; Vesper World "Connect" canvas QR card; `vesper connections pair <id>` terminal QR 854 tests / 0 fail; biome clean; no new dependencies. WhatsApp-Web (Baileys) + Signal deferred to a follow-up. Record per Rule 11 (issue cap): cycle-log.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Connect a messaging channel by scanning a QR — from Vesper World or the terminal — with the chat captured automatically (no copying chat ids). Dependency-free; bot tokens stay on the CLI (stdin -> Keychain), never the browser.
The flagship is the Telegram flow: a QR of
https://t.me/<bot>?start=<nonce>— scan, tap Start, and the bot's long-poll receives/start <nonce>, so Vesper captures and persists your chat id automatically. Discord is the analogue (OAuth2 invite QR + a firstpair <nonce>message captures the target channel).What's included
Pairablecapability aChannelHandlermay also implement (startPairing -> PairingSessionstreaming awaiting/linked/error/expired); a portable, dependency-free QR encoder (Nayuki port, cross-checked byte-for-byte vs upstream) + a half-block ANSI terminal renderer (media/qr); apairablechannel-state flag; pairing audit kinds withnonce/qrredaction.chatId.state=<nonce>) + firstpair <nonce>message captures the channel.PairingCoordinatorthat multiplexes the single inbound long-poll into the chat sink + active pairing sessions (a transient receiver covers not-yet-running channels), and persistsparams.defaultChatIdon link.POST /api/connections/:id/pair(ndjson stream) +GET /api/qr; a Vesper World "Connect" canvas-QR card with live status;vesper connections pair <id>rendering the QR in the terminal.Design notes
getUpdates(Telegram allows only one).Deferred (follow-up)
WhatsApp-Web via Baileys (isolated opt-in package + contract amendment), Signal (signal-cli), optional browser token entry behind the approval gate.
Test plan
bun test— 854 / 0 fail (QR encoder/renderer, pairing abstraction, Telegram + Discord pairing, coordinator, ndjson endpoint +/api/qr, CLI render).biome ciclean.tsc --noEmitadds no new errors (manual; CI skips tsc).