Repository navigation
iPhone: security notices from FTW Cloud, and the car class in CloudView - #77
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4aaed2491d
ℹ️ 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".
| cloudView = view | ||
| switch env.t { | ||
| case CloudWire.msgLP: takeCloudCars(at) | ||
| case CloudWire.msgLP, CloudWire.msgCar: takeCloudCars(at) |
There was a problem hiding this comment.
Use the car timestamp for car-triggered updates
When a car envelope arrives after the current lp, this calls takeCloudCars, but that function stamps the joined result using view.sentMs(lp.header, ...). LoadpointsModel.takeCloud rejects a non-cache result whose asOfMs is no newer than the displayed stamp, so after the LP has been consumed, a car-only SoC or goal update receives the same old LP timestamp and is discarded. Stamp car-triggered projections with the car header, or the newest relevant class send time.
Useful? React with 👍 / 👎.
| /// whenever the box is linked, since security notices go to every owner | ||
| /// with the readable copy on or off; another phone only while the copy | ||
| /// carries its events. | ||
| private var takesAlerts: Bool { cloudOn || canConfigure } |
There was a problem hiding this comment.
Wait for confirmed ownership before prompting
Before the box answers hello, SessionState.role defaults to owner, so takesAlerts is true and startCloud installs the push sink even for a viewer, removed phone, or other unconfirmed connection. PushTokens.install immediately requests notification authorization; a later hello can uninstall the sink but cannot retract that one-time system prompt, and the asynchronous install can race with the uninstall. Require heardFromBox for the owner-only branch while retaining cloudOn for a known readable copy.
Useful? React with 👍 / 👎.
The notification extension reads a box-signed notice in an alert as an event of its kind, for a day, since a notice states a lasting fact. It checks the notice as Go's ReadNotice does: a 16-byte boot, and on agent.added a client's name of at most the consent page's 64 characters and its "…", with no control or format character. A notice kind sent as an event still reads as generic (#78). agent.added names the client when the box sent one: "Claude was given access to your box". An owner's phone registers for FTW Cloud's alerts whenever the box is linked, so notices reach it with the readable copy off. PushSeen keeps the numbers it showed per boot, the newest 64 above a floor, so a notice that arrives after a later event is shown, not quieted as a repeat. A file from before keeps its highest as the floor. CloudView holds the car class and joins a charger to its session's car by carId, the car winning where the two disagree. socReadAtMs dates the level from the car class's own send. The push vectors and the cloud vectors are srcfl/ftw's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4aaed24 to
9353292
Compare
The catalogue from srcfl/ftw-webapp#94, and the same in Swedish. The named line stays the phone's own, from the notice's client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
The phone half of two things FTW Cloud now carries. The box halves are srcfl/ftw#1661 (notices) and srcfl/ftw#1662 (the car class); the service half is srcfl/ftw-cloud#23.
Security notices
A box tells every owner when someone gains access, asks for a change, is about to lose access, can now approve access, or pairs as an owner. FTW Cloud sends the box's signed
noticein an alert to the owners' phones, with the readable copy on or off.PushAlertreads a signednoticein the alert'seventmember as an event of its kind, for a day, as Go'sReadAlertdoes. It refuses a notice with any field beyond the header, a boot that is not 16 bytes, a kind outside the five, or a client's name on another kind or longer than the consent page's 64 characters and "…" or with a control or format character. A notice kind in aneventenvelope still reads as generic, as push: copy the agents' kinds from srcfl/ftw's catalogue #78 made it.PushText: the kinds, the catalogue and the Swedish came with push: copy the agents' kinds from srcfl/ftw's catalogue #78.agent.addednames the client when the box sent a name that will do: "Claude was given access to your box. See who has access in the app." / "Claude har fått åtkomst till din box. Se vem som har åtkomst i appen." The box sends it only while the readable copy carries events. Otherwise the catalogue's sentence shows. That named sentence is the phone's own, so the catalogue test does not hold it. Notices get no buttons and the usual interruption level.PushSeenkeeps the numbers it showed per home and boot, the newest 64 above a floor, so a notice that arrives after a later event is shown once, not quieted as a repeat. A file from before keeps its highest number as the floor.SiteModel.takesAlerts: an owner's phone registers for FTW Cloud's alerts whenever the box is linked, not only with the copy on. Without that, no owner hears a notice with the copy off. A viewer still registers only with the copy. Two lines; it sits outside the Carrier and push files on purpose.The car class
CloudWire.Cars,Car,CarGoalandcarID; a charger'scarId,carIdentifiedBy,carCorrected,carCorrectedFromandchoose;caris a phone class.CloudViewholdscarsandjoined(_:): a charger's level and goal read from its session's car, the car winning where the two disagree, as the protocol says.socReadAtMsdates the level from the car class's own send time, so an old class cannot say "read a minute ago".takeCloudCarsuses both and runs oncartoo.carsyet; that belongs to the car view.Copies from srcfl/ftw
push-vectors.json(srcfl/ftw#1661's, ten notice cases) andcloud-vectors.json(master's, with the car messages and ids). The catalogue came with #78;agent.addednow reads "An assistant or Sourceful was given access to your box. See who has access in the app." from srcfl/ftw-webapp#94 (review S6), and the Swedish says the same.Tests
PushAlertTestsreplays all 28 push vectors and 27 cloud messages.PushTextTests.aNoticeNamesTheClientWhenItCan; the catalogue tests now cover the five kinds.CloudWireTestsdecodes the car class and the asking and tapped chargers, and cuts car ids as Go does.CloudViewCarTests.aChargerReadsItsCarAndTheCarWins, with the read time from the car class's send.PushStoreTests.anEventIsShownOnce(a late, lower number is shown once) andtheNumbersKeptAreBounded(the floor, and a file from before).swift testinappleApp/FTWKit: 461 + 257 tests pass.Not done: a look at the notification in the simulator. The words come from
PushText, which the tests above hold.Not here: a tap on a notice opening the Access screen. It follows once #76 lands.
Deploy order
Cloud first (srcfl/ftw-cloud#23), then boxes (srcfl/ftw#1661, #1662), then phones (this).
Keeps clear of
FTW/Access/*andFTW/Car/*. #74 and #76 touchCloudView,CloudWireandSiteModel, in other hunks.🤖 Generated with Claude Code