Repository navigation
feat: the phone approves requests and answers questions (spec 28) - #222
Merged
Merged
Conversation
Design for the phone: sealed end-to-end relay through the cloud server, QR pairing, restricted phone token, approval/question bridge rules, Web Push without content, milestones CE1-CE7. Stays local until the implementation lands (no docs-only PRs).
devices get a kind (computer/phone) and a peer; a phone token reaches only the relay, /v1/me and logout. Pairings (open, join, accept, collect once), a WebSocket relay that routes sealed bodies without opening them, a queue per phone acknowledged by the computer, presence, revocation that closes sockets, and rate limits. Spec 28 updated to match.
…(spec 28, CE3) The daemon opens one relay connection while a phone is connected or being connected. P-256/HKDF/AES-GCM sealing (vectors in docs/test-vectors, checked against WebCrypto), QR pairing with a code to compare, keys in secrets/mobile.json, cards for approvals and questions, and the phone's answers through the same code as the app's, allowed only for plain tools shown whole. mobile.* methods and notifications, bindings, FakeBotloft handlers. The server sends a paired frame so the computer learns the phone's id.
…nnect (spec 28, CE4) Settings > Backup gets a Phone block under the account: connect a phone by showing a QR drawn in the app, compare the six-digit code the phone shows, accept or refuse, list the connected phones and disconnect one. Texts in English, Portuguese and Spanish.
… CE5) A PWA in app/src/phone: WebCrypto sealing checked against the computer's test vectors, the relay client (counters saved first, replay and tampering refused, reconnection, revocation), QR joining with a code to compare, an inbox of requests and questions with Allow/Deny only for what is shown whole, three languages, manifest and service worker. botloft-cloud serves it from phone_dir at /m under a strict policy; the Docker image builds it. Checked by hand with a real browser against a real daemon and server (cargo test -p botloftd --test mobile_live -- --ignored).
….8, CE6) The computer's wake frame makes the server send each subscribed phone of that computer an empty VAPID-signed push (nothing for a push service to read), merged when they come close together, to the browsers' push services only. Phones subscribe from their page (one tap), the service worker writes the notice in the phone's language, and the page keeps its address fresh. botloft-cloud vapid-key makes the key; [push] in cloud.toml turns it on.
…8, 19) Records what was seen with the full Docker image and a real browser, the finding that the app's browser pane cannot register service workers, and the step-by-step for the VPS and the two phones.
On macOS the status still said connected for a moment after the server cut the relay, so the question opened while the relay was down and the phone never heard of it. A phone that sees its computer come back asks again, so the test does too.
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.
What
The phone (spec section 28): a PWA that approves requests and answers questions from the owner's bots, from anywhere. It is a remote control only: no chat, no files, no messages to bots. The bots keep running on the computer and the daemon still listens only on
127.0.0.1.How it works:
docs/test-vectors/mobile.jsonis written by the daemon's tests and read by the page's tests, and was also checked against Node's WebCrypto.#p=<id>&s=<secret>&d=<computer key>after the#, which the browser never sends. The phone proves it read the secret, both screens show the same six digits, the owner accepts at the computer, and the phone collects its token once./v1/meand logout. Never the backups.Bash,PowerShell,WebFetch,WebSearch, file tools, the plan), shown whole (<= 8 KiB), once only. Everything else, and anything cut, can only be denied there. The daemon checks again when the answer arrives.Slices, one commit each (spec CE1–CE7):
botloft-cloud: pairings, WebSocket relay, queue, restricted phone tokenbotloftd: relay client, sealing, pairing, approval/question bridge,mobile.*methodsapp/src/phone), served by the account server at/m; Docker stage builds it[push],botloft-cloud vapid-key)How it was checked
cargo fmt,cargo clippy -D warnings,cargo test --workspace: pass.pnpm check(types, lint, 510 tests): passes.cargo test -p botloftd --test mobile_live -- --ignored --nocapture./mis served under its policy,..%2fstays inside the folder.Not checked yet (needs the VPS updated and two phones)
The runbook is in spec 28.10 and the results table in section 19 says "em parte":
#of the QR on iOS and Android;wssand the 25 s ping behind Cloudflare for hours.For whoever deploys
The deployed server (
botloft.comitium.com.br) is the old version. It needs this image,phone_dir = "/srv/phone"and, for notices,[push]with a key frombotloft-cloud vapid-key(docs/cloud-deploy.md). Without[push]everything else works and the phone shows only what is there when it is opened.Known: the page's JavaScript is 711 KB (223 KB gzipped) because it carries the app's strings; it can be slimmed later.