M9 #3: flush UserHomeCache on soft disconnect

Full ConnectedServerRegistry was scoped out of this phase — SwiftUI
view lifecycle already tears down transports via .onDisappear when
ScarfGoTabRoot unmounts on state transition to .serverList. Adding
a formal registry that tracks every active transport per ServerID
is complexity without proven UX payoff right now (can revisit post
pass-2 if users hit stale-connection bugs).

One real cleanup we should always do on soft disconnect: invalidate
the shared UserHomeCache entry for the server we're leaving. The
cache lives forever otherwise, and a hypothetical scenario where
the remote user's home directory changes between sessions would
surface as SFTP paths resolving to the wrong directory. Rare, but
free to fix.

`RootModel.softDisconnect()` now calls the new static
`ServerContext.invalidateCachedHome(forServerID:)` before flipping
state to `.serverList`. Static form is a convenience for callers
that have the ServerID in hand but not a full ServerContext (avoids
forcing a round-trip through config store just to rebuild the
context we're already discarding).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-04-24 13:56:57 +02:00
parent bb399e6d35
commit 9c2e9279cc
2 changed files with 19 additions and 7 deletions
@@ -219,6 +219,13 @@ extension ServerContext {
public static func invalidateCaches(for contextID: ServerID) async {
await UserHomeCache.shared.invalidate(contextID: contextID)
}
/// Static convenience for callers that have the ServerID but not
/// a full ServerContext (e.g. RootModel.softDisconnect). Mirrors
/// the instance method above.
public static func invalidateCachedHome(forServerID id: ServerID) async {
await UserHomeCache.shared.invalidate(contextID: id)
}
}
// MARK: - Convenience file I/O via the right transport