Repository navigation
Conversation
Taken as they stand from claude/native-swift-ftw-app-d7j9w4 (dbfce65): appleApp/, .github/workflows/apple.yml, .gitignore and the KMP change that removes the iOS targets. iosApp/ and shared/src/iosMain go, as in #5. protocol/registry.yaml stays as it is on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
iPhone only, iOS 26. Pairing, Now with the price card, and the demo stay. History, Plan, Box admin, escrow, spoken box codes, the macOS target and menu bar, swift-crypto, the Linux job and PlainWebSocket go. The charger sheet goes too; the car view replaces it next. - One Swift package, three modules: FTWKit (the app's logic), FTWShared (Sendable values for widgets and later a notification extension) and FTWDemo (the simulated box, out of the product module). - FTWShared holds the App Group cache: prices-<site> and car-<site>, each with carrier, srcState and when it was read, written with completeUntilFirstUserAuthentication. A reader takes any number of sources, so a cloud copy can be one more source later. The price and freshness formatters moved here, in English and Swedish. - The car record keeps soc_source and when the level was read. - Contract.swift follows main's registry: planner.prefs.set and the modes without priority and weighted. ContractTests now also checks modes, frozen field ids, the shared enums and the demo box's names. - The session closes when the app goes to the background and reopens on return without a passkey. A relay 4429 shows "FTW is busy". - A WidgetKit extension with one price widget that reads the cache. The App Group is written once, in FTW.xcconfig; both entitlements and Info.plists read it. No DEVELOPMENT_TEAM; simulator builds sign ad hoc so the entitlements travel with the app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- DEVELOPMENT_TEAM L66M368PZ6 in FTW.xcconfig, for the app and the widget, with automatic signing. Simulator builds still sign ad hoc and need no Apple account. The App IDs, App Group and Associated Domains still have to be registered for the team; the README lists the steps. - A pairing QR scanned with the iOS camera arrives as a universal link to https://app.ftw.energy/p#…. The app takes it through onOpenURL and onContinueUserActivity, the same offer path as any pairing link. - In the simulator, which has no camera, a picture of the QR from Photos pairs. PairingImage reads the link with CoreImage, with tests. - FTW Cloud is now an opt-in, readable state cache. The cache comments and CLAUDE.md say so; M1 does not depend on it. - Passkeys no longer uses the presentation anchor iOS 26 deprecated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 12, 2026
Member
Author
|
Included in #14, which lands the whole iPhone M1 app as one PR. The branch stays. |
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.
Replaces #5. This keeps #5's protocol core and cuts it down to the iPhone M1 that Fredrik approved on 2026-10-12: pairing, a lean Now, a car view and price widgets. This PR is the foundation. Two follow-up branches start from it: price widgets, and the car view with Now. #5 stays open.
What changed
Taken from #5:
appleApp/, the Apple workflow and the KMP change that drops the iOS targets.iosApp/andshared/src/iosMaingo. Android andshared/still build and test.Scope: iPhone only, iOS 26. Gone: History, Plan, PlanText, HistoryGeometry, BoxModels, BoxView, BoxCode, escrow (Escrow, RecoveryBlob, the sealed-copy switch, passkey recovery), GlanceView, LiveSheet, EVSheet, PlainWebSocket, the macOS target, swift-crypto and the Linux job. Session and Messages keep prices, the API passthrough and commands, without history or plan.
Modules: one Swift package,
appleApp/FTWKit, with three targets.FTWKit: the app's logic. The app alone links it.FTWShared: plainSendablevalues for widgets and a later notification extension. It holds the App Group cache,PriceStrip,Freshness,PowerFormatandPriceUnits, with English and Swedish words for the band.FTWDemo: the simulated box, out of the product module. The app injects it intoAppModel.App Group cache: the app writes
prices-<site>andcar-<site>after each read. Each record carriescarrier,srcStateand when it was read, and always reads back ascache. The car record keepssoc_sourceand when the level was read (the car's report time forvehicle). Files usecompleteFileProtectionUntilFirstUserAuthentication.CacheReadertakes any number ofCacheSources, so a copy from FTW Cloud (opt-in and readable, designed separately) can be one more source with the same records. Signing out clears it. The demo writes nothing.Contract:
protocol/registry.yamlis main's, unchanged.Contract.swiftgainsplanner.prefs.setand the mode list withoutpriorityandweighted.ContractTestsnow also checks modes and tiers, the frozen field ids, theCarrierKind/SourceStateenums and the names the demo box uses.Session: it closes when the app goes to the background and opens again on return without a passkey. Inactive (Control Center, the app switcher) only slows the stream. A relay close with 4429 sets
busy, and the band says "FTW is busy" / "FTW är upptaget" with no countdown.Pairing: a pairing QR scanned with the iOS camera arrives as a universal link to
https://app.ftw.energy/p#…and takes the same offer path as any pairing link. In the simulator, which has no camera, a picture of the QR from Photos pairs too (PairingImage, with tests).Targets:
FTWWidgets, a WidgetKit extension with one small price widget that reads the cache. It holds no key and opens no stream. The App Groupgroup.energy.ftw.appis written once, inappleApp/FTW.xcconfig. Both entitlements files and both Info.plists read it, and Swift reads it from Info.plist.DEVELOPMENT_TEAM = L66M368PZ6is set there too, for both targets, with automatic signing. Simulator builds still sign ad hoc and need no Apple account, so the entitlements travel with the app; CI no longer builds withCODE_SIGNING_ALLOWED=NO. No certificate, profile or key is committed.For the next two branches
The project uses folders that Xcode keeps in step with the disk, so a new file needs no change to
project.pbxproj.appleApp/FTWWidgets/**,appleApp/FTWKit/Sources/FTWShared/**,Tests/FTWSharedTests/**.appleApp/FTW/UI/**,appleApp/FTW/Car/**(new), and on the model sideState/LoadpointsModel.swiftandFormat/EV.swift.Checks
swift testinappleApp/FTWKit(Xcode 27, Swift 6.4)./gradlew :shared:jvmTest --rerun./gradlew :androidApp:assembleDebugxcodebuildFTW scheme,generic/platform=iOS SimulatorOpen
Signed-off-by. CONTRIBUTING asks for it, and an agent should not sign in Fredrik's name.energy.ftw.appandenergy.ftw.app.widgetsfor team L66M368PZ6, the App Groupgroup.energy.ftw.appon both, and Associated Domains on the app. Signing in to Xcode with the team and building for a phone does it through automatic signing; the developer portal works too.apple-app-site-associationfile onapp.ftw.energycomes from a separate ftw-webapp PR. Passkeys and the camera QR link need it.🤖 Generated with Claude Code