Toolchain setup #
Install mise, then from the repo root:
mise trust
mise install --locked
mise exec -- gem install bundler -v 4.0.3
mise exec -- bundle config set --local path vendor/bundle
mise exec -- bundle install
mise exec -- flutter pub get --enforce-lockfile
mise.toml pins Flutter 3.47.2 (Dart 3.13.2), Ruby 4.0.1, Maestro 2.10.0,
and Lefthook 2.1.12. Gemfile.lock pins Fastlane 2.238.0, CocoaPods 1.17.0,
and their dependencies; Minitest 5.27.0 runs the Ruby regression tests.
Maestro uses its official cli-2.10.0 release tag.
Android Gradle Plugin 8.11.1, Kotlin 2.2.20, Gradle 8.14.3, and NDK versions
live in android/. Keep this compatible AGP 8 toolchain while using stable
flutter_web_auth_2 5.x: upstream requires its 6.x line for AGP 9 support.
See the plugin's migration guide.
mise.lock records download URLs and integrity hashes for macOS (ARM64 and
x64) and Linux x64. Regenerate it with mise lock --platform macos-arm64,macos-x64,linux-x64 when changing tools.
Android Studio's JDK and the Android SDK, plus Xcode on macOS, are still required.
Maestro requires Java 17 or newer on PATH (or through JAVA_HOME). On macOS
with Android Studio installed, set it before running Maestro:
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
Activate mise in your shell as described in its installation guide, or prefix
commands with mise exec --. Mise puts this repository's bin/ first on PATH;
the fastlane and pod binstubs load the locked bundle. This also lets CocoaPods
load the correct gems after tool/fastlane_flutter.rb clears inherited Ruby
variables for a Flutter build. tool/release invokes the project Fastlane
binstub using its current Ruby and checks the bundle before store access;
the build helper explicitly selects project bin/pod even without mise's PATH.
Use mise to also select the pinned Flutter and Ruby versions:
mise exec -- tool/release 1.4.0 --dry-run
mise exec -- flutter test
mise exec -- bundle exec ruby test/tool/release_test.rb
mise exec -- bundle exec ruby test/tool/fastlane_flutter_test.rb
mise exec -- maestro --version
mise exec -- maestro test .maestro/a1_login_session.yaml
The release dry run still requires store credentials and signing configuration;
it builds but does not upload. Maestro flows require a running app, a device,
and real backend infrastructure; see the QA guide.
Install Git hooks explicitly with mise exec -- lefthook install when wanted.
Keep mise.lock, pubspec.lock, Gemfile.lock, ios/Podfile.lock, and both tracked
Package.resolved files in version control. Update stable packages deliberately;
do not use flutter pub upgrade --major-versions indiscriminately, since it can
select prereleases. Sentry remains on the stable 9.x line.
Secure-storage upgrade constraint #
Keep flutter_secure_storage on 10.x. Version 11 removes the legacy encryption
backends and cannot read data that has not already been migrated by a v10 build.
Publishing a v10 release alone does not guarantee users opened it: a user can
upgrade directly from an older installation. Establish the supported upgrade
path before raising this constraint, then verify session retention on physical
Android and iOS devices. See the upstream changelog.
Native verification for this refresh #
Before release, test on physical Android and iOS devices:
- Login success, cancellation, cold-start session retention, and token refresh.
- HTTPS and custom-scheme deep links, including an OAuth callback into a cold app.
- Avatar and banner cropping: save, cancel, locked aspect ratios, and dark theme.
- Android cropper toolbar, system bars, and controls under edge-to-edge display.
- Feed/detail navigation and back behavior after the go_router upgrade.
The Android auth migration sets empty task affinity on exported activities as recommended by flutter_web_auth_2. The existing custom cropper theme is retained; there is no v9 edge-to-edge opt-out resource to remove. iOS resolves cropper and browser-auth plugins through Swift Package Manager. The cropper's compatible native dependency resolved to TOCropViewController 3.2.0; Sentry Cocoa remains at the plugin's exact 8.58.4 pin.
Empty task affinity prevents task-affinity hijacking; it does not make the
social.coves URI scheme exclusive to this app. Browser fallback paths can
still deliver callbacks through a public intent filter. Treat callback-scheme
hijacking as a separate open security issue; this dependency upgrade does not
resolve it. A backend-issued, short-lived, single-use code bound to the initiating
client and redeemed over HTTPS would avoid putting a reusable session token in
the callback. That protocol change needs coordinated backend and mobile work.