Repository navigation
Ask people to agree to the terms when they sign in and again when the terms change - #82
Conversation
Neither Sign in with GitHub nor Sign in with Apple works until the box is ticked, and links open the terms and privacy policy in the app's browser. The phone tells devnull which version it showed as it signs in (terms_version), which devnull records. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Nice. Just waiting on the API PR to get merged first |
RaphaelFakhri
left a comment
There was a problem hiding this comment.
The GitHub sign-in drops terms_version whenever onboarding is the root screen. In that case AuthCallback replaces /onboarding with a fresh Onboarding, so $acceptedTerms is back to false when finishSignIn() runs from mount(), and redeemSignIn() posts {"code":"c","code_verifier":"..."} with no version. The pop-back path (onResume() on the same instance) does send "terms_version":"2026-10-23", so you only see the bug when the callback arrives as a replace. The existing test "follows the deep link back, redeems the code with the verifier and signs in" also locks this in: it still expects a body without terms_version. Since signIn() and signInWithApple() already refuse to start without the tick, you can send Client::TermsVersion unconditionally in finishSignIn() and useAppleToken(), or carry it on the SignInAttempt.
The branch also conflicts with main in resources/views/native/onboarding.blade.php after #92, and vendor/bin/pint --test flags the double blank lines this PR adds to tests/Pest.php and OnboardingTest.php. CONTRIBUTING.md asks for before and after screenshots on iOS and Android in light and dark mode for this screen.
tests/Feature/Screens/OnboardingTest.php line 209: This asserts the GitHub redeem body without terms_version, which contradicts "sends terms_version with the sign-in call for both ways in". Add 'terms_version' => Client::TermsVersion here once the replace path sends it.
The phone sent a hard-coded terms version and the server refuses anything but the one in force, so the 1 November terms update would have made sign-in fail with a 422, and every later update would do the same to builds already installed. The server now takes a yes (dev-null-sh/dev-null.sh#1385) and works out the version from when it hears. Both Client methods always send it. A sign-in can't start without the tick, and reading the tick when the sign-in finishes lost it whenever the browser's answer landed on a new onboarding screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # tests/Feature/Screens/OnboardingAppleTest.php
…tings When devnull says the terms in force haven't been accepted, the app now opens on a screen that asks for them, like the web's terms dialog. Launch goes straight there when the last answer said so, and any /me answer that says so sends you there from whatever screen you're on. Accepting sends the version /me named, so terms that change again while the screen is open get a 422 and are asked for again. Sign out and Delete account are the other ways out. Account settings gets a Terms and privacy section just before Delete account: links to both pages in the in-app browser, and the version in force beside the one you agreed to and when. devnull only keeps when you accepted, so an older version shows as "an older version" rather than a date. Sign out and delete account move into a LeavesDevnull concern so the new screen can share them with Settings, and the two page links into OpensLegalPages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # routes/mobile.php
The current, agreed to and accepted rows put two version names and one acceptance day side by side, all as dates, and agreed to always matched current because the terms screen takes over when they differ. One sentence says it plainly: "You accepted the terms of Nov 1, 2026 on Nov 3, 2026." Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
The sign-in screen has a checkbox, "I agree to the terms of service and privacy policy. There's no tolerance for objectionable content or abusive users.", with links to both pages (dev-null.sh/terms and /privacy, in the app's browser). Sign in with GitHub and Sign in with Apple stay disabled until it's ticked. This is what App Review's guideline 1.2 asks of an app with user-generated content.
The phone sends
terms_accepted: truewith the sign-in call for both ways in. A sign-in can't start without the tick, so it doesn't read the tick again when the sign-in finishes. devnull records the time, which says which version was in force. The phone no longer carries a version, because a built app can't keep up when the server raises it.People already signed in now get asked too. When
GET /mesaysterms_accepted: false, the app opens a new screen, like the web's terms dialog: "We updated our terms" (or "Accept our terms" for someone who never accepted any), links to both pages, and Accept the terms, Sign out or Delete account. The app opens on it at launch if the last/mesaid the terms are owed, and any/meanswer that says so sends you there from whatever screen you're on. Accepting sendsPUT /me/termswith the version/menamed. If the terms changed again while the screen was open, devnull answers 422 and the screen asks/mefor the new version.Account settings has a Terms and privacy section just before Delete account. It links to both pages in the in-app browser and says in one sentence which terms you accepted and when: "You accepted the terms of Nov 1, 2026 on Nov 3, 2026." Each version of the terms goes by the day it took effect. devnull only stores when you accepted, so if that was before the current terms, the sentence says you accepted an earlier version on that day. You'd only see that for a moment, because the new terms screen takes over as soon as
/meanswers.Sign out and Delete account moved into a
LeavesDevnullconcern so the new screen shares them with Settings, and the two page links intoOpensLegalPages.Depends on
dev-null-sh/dev-null.sh#1385, which makes the server take
terms_acceptedat sign-in. It's merged. Until it's deployed the server ignores the field, so someone who just signed in lands on the new terms screen once and accepts there. Nothing breaks, it's just an extra step.Verified
Pest passes after merging main (1791, with main's 36 Skia tests skipped). The checkbox was checked in iOS and Android builds earlier. The new screen and the Settings sentence were checked in an iOS 26.2 simulator and an Android 15 emulator against a local devnull with #1385. On both, the screen appears as soon as
/mesays the terms are owed, and Accept records the time on the server and goes back to the log. On iOS the screen also comes up on a cold launch, and Terms of service opens in the in-app browser. Sign out and Delete account on the new screen were only exercised by the tests, not on a device.Screenshots
accept-terms
onboarding
onboarding-ticked
settings
The Sign in with Apple button doesn't show in these builds, so it isn't pictured. It uses the same
disabledcondition as the other button. Theremoterow in Settings shows because these builds talk to a local devnull.🤖 Generated with Claude Code