Skip to content

iPhone: a consent link or QR code goes straight to review, no code to type - #84

Merged
frahlg merged 2 commits into
mainfrom
claude/offer-link-straight
Oct 17, 2026
Merged

frahlg merged 2 commits into
mainfrom
claude/offer-link-straight

Conversation

@frahlg

@frahlg frahlg commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Problem

On 17 October 2026 Fredrik connected Cursor by scanning the consent page's QR code with the iPhone. It worked, but the app then asked him to type the code from the same page. He decided: scan or open the link and go straight to approval; type the code only when you have neither. He accepted that a link someone else sends also reaches the review, where the host, the verified flag, Face ID and the offer's 10 minutes still stand.

What changes

  • OfferFlow: a link (https://app.ftw.energy/a#<request>.<offer>, tapped or opened by the Camera from the QR code) is checked against the pinned offer keys at once and goes straight to review. The code step is gone from this path.
  • The checks stay. Unsigned, expired, wrong home, support from anyone but Sourceful, and a build with no pinned key are refused before anything shows. Approving checks the signed offer again, behind Face ID. An unverified client still needs "I started this myself and trust …" before Approve works.
  • The review shows Code on the page (K7QF-2MXD) for an owner who wants to compare. Nothing asks them to.
  • No link: type the code, fetch, review, as before. A typed code is not shown again.
  • The pairing scanner reads a consent QR as its link: the home this phone opens (sites.current()) shows the offer. With no home it says "That is an assistant's QR code. Connect your box first, then scan it with the iPhone Camera." When the home is paired but cannot open yet, the offer waits for it, as a tapped link does, and the scanner says "The assistant's request opens once your home does." There is no scanner on the Access page and I added none; the Camera covers it.
  • submit asks FTW Cloud once: a second press while the first is out does nothing, since the code works once. present does nothing once an offer is shown, so nothing swaps the signed offer under a review or an approval.
  • A second link replaces an open offer page rather than stacking a second one. The page takes the link as its identity (.id(link)): without it, the simulator showed that SwiftUI kept the first flow's state at that place and showed the old offer.
  • Debug only: -FTWOfferKeys now also pins in the demo, beside the demo's own key, so a link signed elsewhere opens in the simulator.
  • AccessE2E no longer types a code after the link; FTW_E2E_CODE is gone. LiveOfferTests checks the review's code when FTW_LIVE_OFFER_CODE is set.

No settings, no change to the offer, its keys or signatures.

Tests

swift test in appleApp/FTWKit: 503 tests in 78 suites pass, the new ones among them. New or changed:

  • aLinkGoesStraightToReview: a link reaches review with nothing typed, never asks FTW Cloud, shows the page's code.
  • aBadLinkIsStillRefused: unsigned, expired, malformed, support from a stranger, no pinned key.
  • aCodeFetchesItsOffer: no link starts at the code and fetches.
  • approvingChecksAgain: another home or a lapsed clock at approve is refused.
  • aLinkIsApprovedWithNoCode (AccessFlowTests): link → review → approve against the simulated box, one Face ID, row in the roster.
  • aConsentQRInThePairingScannerOpensTheOffer (ShellTests), with a second home listed first.
  • aTypedCodeIsAskedOnceAndMustMatch: a fetched offer whose code differs is refused with .wrongCode after one fetch; Return plus Continue fetch once. Without the new guard this test fails.
  • startingAgainChangesNothing: start again after the owner set control, trust and length changes nothing, and present cannot swap the offer.

App and UI tests build for the iOS 27 simulator (xcodebuild build-for-testing, -jobs 4). LiveOfferTests passes against a link signed outside the app with a fresh P-256 key, so the signing matches.

In the simulator

iPhone 17 Pro, iOS 27.0, demo with -FTWOfferKeys <test key>, then xcrun simctl openurl <udid> 'https://app.ftw.energy/a#…'. The universal link opened the app straight on the review.

Link → review Approved Unverified, sv, dark
Expired link Signed by another key Largest text
No link: the code No link: review

Two links in a row, each opened from the home screen as the Camera would: the second replaces the first, and Back goes to Now.

First link Second link replaces it

Not tried: a real phone, the real FTW Cloud, the Camera on a printed QR code.

Paired

#82 touches OfferFlow.swift, OfferFlowView.swift and OfferTests.swift in other places (lengths, grant). Whichever lands second has a small rebase; the one shared line is a test comment.

🤖 Generated with Claude Code

… type

A link from FTW Cloud's consent page, tapped or opened by the iPhone Camera
from the page's QR code, now goes straight to the review screen. The owner
types the code only when they have neither. Fredrik chose this on
17 October 2026 over keeping the code for links.

The checks stay: the offer is opened against the pinned keys at once and
refused when unsigned, expired, for another home or support from anyone
but Sourceful. Approving checks the signed offer again, behind Face ID,
and an unknown client still needs the owner's "I started this" first.
The review shows the page's code for an owner who wants to compare.

The pairing scanner reads a consent QR as its link: the saved home opens
with the offer, or, with no home, it says to connect the box first.
A debug build's -FTWOfferKeys now also pins in the demo, so a link signed
elsewhere opens in the simulator.

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

chatgpt-codex-connector Bot commented Oct 17, 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-17T08:30:08.578980Z 803e19b 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.

@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: 803e19b92d

ℹ️ 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".

return
}
app.offer(raw)
return openKnown()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep consent scans on the currently open home

When the phone has multiple saved homes and the user scans a consent QR while viewing any home other than the first stored row, openKnown() switches to sites.all().first because that is how known is initialized. An offer naming the home that was actually open is then immediately rejected as .unknownHome, while an unbound offer is presented against the wrong home. Preserve the current app.site when leaving the pairing scanner rather than reopening the first saved site.

Useful? React with 👍 / 👎.

…he open home

Review fixes for the consent link flow:
- submit asks FTW Cloud once: Return plus Continue no longer fetch twice
  and spend the code. present does nothing once an offer is shown.
- A second link replaces an open offer page instead of stacking another.
  The page takes the link as its identity; without it SwiftUI kept the
  first flow's state at that place and showed the old offer.
- The pairing scanner opens the home this phone opens (sites.current()),
  keeps the offer for a home that cannot open yet, and with no home says
  to scan with the iPhone Camera once the box is connected.
- Tests: a wrong code is refused after one fetch, a double submit fetches
  once, start again changes nothing the owner chose.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@frahlg
frahlg merged commit eecf504 into main Oct 17, 2026
1 check 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