chadtmiller.com/knotless
git that lives in your Atmosphere account
The iOS app can require an update, and says when to sign in again
MergedThis adds an iOS minimum build to describeServer, set by --ios-minimum-build/--ios-minimum-reason or the matching deploy env vars. The app shows an update-only screen when its build is below that minimum. It also reads reauth from getViewer and shows a sign-in-again note over the tabs.
I found nothing that must change. I could not build or run the iOS code, so the Swift is judged by reading only.
- The server side is consistent. The flag parsing,
Appfield, lexicon, docs and tests agree. An empty value from compose ordeploy.shbecomes "none", and the tests cover that. - The app fails open on an unanswered
describeServer, and it keeps the last answer, as the body says. Account.refreshignores a result if the token changed while it was in flight, which is the right guard.
The device-only gaps (the Update button's two URLs, and telling TestFlight from the App Store by receipt name) are already listed in the body. They are worth trying on a TestFlight build before anyone raises the minimum.
The head moved from 182c476 to 29412ca only by merging main. The pull's own diff is the one I approved before, and it still merges clean. project.yml already has CURRENT_PROJECT_VERSION: "5", as the body says. My earlier review asked for nothing, so there is nothing to check off. I still could not build or run the Swift, so I judged it by reading. The device-only gaps (the two Update URLs and the sandbox-receipt test) remain as the body lists them. Try them on a TestFlight build before anyone raises the minimum.
9 passed, 1 skipped
What changes
An update can be required.
dev.knotless.describeServergainsios, withminimumBuildandreason, set by--ios-minimum-buildand--ios-minimum-reason, orKNOTLESS_IOS_MINIMUM_BUILDandKNOTLESS_IOS_MINIMUM_REASONin deploy.yml. A build older than that shows only a screen with the reason and an Update button, which opens TestFlight in a TestFlight build and the App Store in any other. Nothing sets it yet, so nothing changes on landing.ios/README.mdsays how to use it.The app says when to sign in again. It now reads
reauthfromgetViewer, as the pages do, and shows their note over every tab, with a button that signs in again as the same account. It reads this again each time it comes to the front, so a change in scopes reaches an app left open.The build goes to 5, the first that does either.
Why
Without this, a bad build stays in people's hands for as long as they don't update, and a session that fell behind only finds out when a write fails. The minimum follows
client.minimum, which does the same for the CLI, rather than adding a second way to ask. It's a server setting so that it needs no new build, and it lands like any other prod change.The app fails open: a server that doesn't answer changes nothing, so an outage can't lock anyone out. The answer is kept, so a stopped build stays stopped offline.
How it was checked
crates/knotless-serve/tests/serve.rscovers the flags and the answer. CI runs them, andjust lex.ios/check-models.shread the recorded answers here; its step that checks writes needsharness/'s packages, so that part is left to theioscheck.just ios-look homedrew the update screen, with and without a reason, and the note, in light and dark, and the screen went away when the minimum dropped. The first drawing of the note hid the toolbar, so it now sits above the tabs. The pictures here are those.Shortcomings
Not tried on a device or through TestFlight: the Update button's two addresses, and the sandbox receipt that tells TestFlight from the App Store, have not been opened for real.
appStoreReceiptURLis deprecated as of iOS 18 and gives a build warning. Its replacement is async and can ask to sign in, which is wrong on this screen.Builds up to 4 ignore the minimum. Build 5 has to reach people before it can stop anything. Raising the minimum past what people can install leaves them with nothing else to do: the README says so, and nothing enforces it.
The app does not read
redelegate, as delegating stays on the pages.🤖 Generated with Claude Code