Skip to content

docs: the watch exchange, an Apple Watch that works without the phone - #83

Merged
frahlg merged 2 commits into
mainfrom
claude/watch-direct-exchange
Oct 14, 2026
Merged

frahlg merged 2 commits into
mainfrom
claude/watch-direct-exchange

Conversation

@frahlg

@frahlg frahlg commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Accepted design, no code. Paired with srcfl/ftw#1621 (ADR 0009), which holds Core's and FTW Cloud's side, the decisions and the order of work; neither works without the other.

Decision

Fredrik answered "ja på alla" on 14 October 2026 and asked that the watch work fully on its own, for example on LTE with the phone away. docs/watch-exchange.md is now marked accepted.

watchOS allows HTTPS and no WebSocket (TN3135). So a watch on its own uses two doors:

  • Commands through the relay's exchange. The box opens /r/<epoch>/<handle>/exchange; the watch posts one Noise message to /x/<epoch>/<handle>; the relay draws a random id, hands the body to that socket and returns the reply. It reads only the id it wrote. Exchanges never take a stream place.
  • Reads through FTW Cloud's one-shot read (ADR 0009, decision 7), which never wakes the box. With FTW Cloud off, now on the exchange answers in one lane 0 frame.

What the doc covers

  • The exchange steps and their fixed lengths. A read and a command have the same request and answer lengths, so the relay cannot tell them apart.
  • IK with its own prologue, opened when the confirm screen appears, so a tap waits for one request. Why not KK and why not 0-RTT.
  • The receipt line: one answer carries cmd.ack and cmd.result; the watch shows observed; a retry with the same cmdId acts once.
  • Adding a watch through an owner phone with step-up; role watch with ftw.live.read, ftw.plan.read, ftw.events.read and ftw.dispatch.write, never more than its phone; the key under kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly; one identity removed in one place, the box.
  • What the relay must never learn and what it still knows; Caddy skips the access log on /x/.
  • Limits, latency and battery bars, client changes, nine alternatives, and relay and device tests.

Order of work in this repository

ADR 0009's milestones hold the full order. Here: the registry (role watch, capability cmd.exchange, copied to ftw and ftw-app in a pair) is step 2, and the relay exchange with its tests is step 4. Both can start now.

What I checked

Read against relay/src/server.ts, relay/src/limits.ts, relay/deploy/Caddyfile, docs/protocol.md, Core's session, handler, command and transport code, FTW Cloud's protocol and app session, and the W1 plan. Nothing was run; this is a document.

🤖 Generated with Claude Code

watchOS allows HTTPS and no WebSocket, so the relay gains a request and
answer route that hands opaque Noise messages to a second socket from the
box. The relay reads only the id it writes. The doc covers the wire, the
Noise use, the receipt line, adding and removing a watch, what the relay
still knows, limits, latency, client changes and the tests.

Proposed only. Paired with srcfl/ftw ADR 0009.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T06:41:52.413069Z 3902d71 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ftw-webapp cffa2fe Commit Preview URL

Branch Preview URL
Oct 14 2026, 07:43 AM

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3902d7147a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/watch-exchange.md Outdated
Comment on lines +158 to +160
**Role `watch`.** Scopes `ftw.live.read` and `ftw.dispatch.write`: Charge
now, Pause, Back to the plan and the car's level. Not `ftw.mode.write`, no
members scopes, no passthrough, no history. Each check takes the role's scopes

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict the watch role to the commands listed

Granting ftw.dispatch.write authorizes every operation mapped to that scope, not just Charge now, Pause, Back to the plan, and car-level updates. In the current registry, this also includes battery.hold, loadpoint.boost, and loadpoint.surplus_only.set (contract/registry.yaml lines 139–143), and the box deliberately authorizes named operations by scope. Consequently, a modified watch client could control the house battery or enable battery boost even if the watch UI never exposes those actions; define a narrower scope or an explicit server-side operation allow-list for the watch role.

Useful? React with 👍 / 👎.

Fredrik said yes to the design on 14 October 2026 and asked that the watch
work fully on its own. The doc now splits two doors: commands through the
relay's exchange, reads through FTW Cloud's one-shot read (ADR 0009). The
exchange gains `now` for homes with FTW Cloud off, at the same lengths as a
command, and `hello_ok` carries what the watch needs to read FTW Cloud. The
watch role gains the plan and alert scopes, and one identity covers both
doors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@frahlg frahlg changed the title docs: propose the watch exchange, commands from an Apple Watch docs: the watch exchange, an Apple Watch that works without the phone Oct 14, 2026
@frahlg
frahlg merged commit 040bdb5 into main Oct 14, 2026
3 checks passed
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