VpnConnection._init() started a 30 s /health poll from the constructor
with no lifecycle gating, so it ran for the life of the app process -
backgrounded, and whether or not the user ever connected. The app is
excluded from its own tunnel, so those requests left in the clear. A
periodic request that fires while the user is deliberately not connected
is an avoidable fingerprint, and rule 60 already ruled probes out:
reachability is meant to be passive.
All it bought was the status dot before the first connect, and it got
that wrong in both directions - "Offline" on a transient resolver
failure against a server that was fine.
Reachability now comes from a session sync that succeeded. serverHealthy
is isConnected && hasSyncedOnce, so a green dot means a working session
rather than a check made beforehand; while disconnected the bar reads
"Ready" and claims nothing either way.
checkHealth() goes with it. Nothing calls it, and leaving a probe helper
in place invites its reuse.
Pinned in test/session_lifecycle_regression_test.dart so it cannot come
back as a tidy-up. flutter analyze clean, 10/10 tests pass.
Co-Authored-By: Claude Opus 5 <[email protected]>
SOCKS5 Reconnect re-attached to the session the device already held. It
was the only path where a session began without an ad and without a
nonce binding it to one, and supporting it cost three parameters -
resume, release, resetSupportClaim - plus a carve-out in rule 4 that let
_fetchActiveSession accept whatever nonce the server happened to return.
It also wasn't the kindness it looked like. _handle_main calls
create_or_replace with a fresh full window, so a new session hands the
user *more* time, not less; re-attaching only preserved the remainder of
a session whose proxy had just died.
Reconnect now disconnects and connects again exactly as the button does,
ad included. All four special cases are deleted and the nonce check is
unconditional.
Costs one rewarded ad to repair an orphaned proxy once ads are enabled.
esef's call, and it buys a single way to start a session.
Also fixes the 3.3.7 regression where Reconnect released the session and
then asked for it back: there is no longer a path that does either.
Co-Authored-By: Claude Opus 5 <[email protected]>
Regression from e67f0b9, shipped in 3.3.7.
Reconnect repairs an orphaned proxy by tearing the runtime down and
re-attaching to the session the device already holds. It does that
through SessionTimer.disconnect(), which e67f0b9 taught to hand the
session back to the server - so it destroyed the very session the
following connect(resume: true) then asked for. Unawaited, so it raced:
the resume either found the session already gone or removed moments
later, surfacing as "Session not activated".
disconnect() now takes release, and the Reconnect path passes false.
Every other caller still hands the session back.
Narrow in practice: SOCKS5 mode only, only the Settings Reconnect
button, and the main-screen connect was unaffected because it mints a
new session anyway.
Co-Authored-By: Claude Opus 5 <[email protected]>
Source assertions, in the style of the existing release-verification
test. Every behaviour here was found broken on a device and fixed today;
none can be covered by an ordinary Dart test, because they live in the
vendored Android runtime or need a live tunnel. They all regress
silently, and each one looks like tidying when it does - inlining a
CountDownTimer, dropping a Handler callback, restoring a friendlier
notification string.
Checked that they fail without the fixes, not just that they pass with
them: restoring the "disconnects in 5 minutes" wording and moving
releaseSession() out of disconnect() both turn them red.
Co-Authored-By: Claude Opus 5 <[email protected]>
Removed at the maintainer's request. The four tests covered the auto->tun
and ass->proxy preference migrations, secure SOCKS session generation, and
the patched Xray SOCKS authentication schema.
Note that nothing now guards the build-time patchers against schema drift;
their fail-closed anchors are the only remaining check.
Co-Authored-By: Claude Opus 5 <[email protected]>
Cover legacy Auto and ASS preference migration, authenticated SOCKS session generation and the stock-runtime Xray SOCKS schema so future runtime changes cannot silently restore the old fixed-port/no-auth behavior.