# Sessions shared by local agent clients

Browser login and explicit token login store one local user session. Login/MCP startup does not mint an extra API key. Same-account re-login retains an existing saved script key; switching accounts does not carry that key across. Server-side key records are unchanged by this local session lifecycle.

The 2.2.1 candidate resolves the session before each stdio tool call. Refresh is performed on demand under a shared process lock. Idle clients do not independently rotate stale refresh tokens. Each auth HTTP request has a 20-second timeout, and concurrent callers wait up to approximately three seconds for the refresh lock before receiving a retryable busy/unavailable error.

Credential mutations use a separate short lock and atomic file replacement. Session updates compare the expected user, login generation and token pair while holding that lock, preserving unrelated fields. An old process cannot overwrite a cooperating client's newer login/rotation or clear it after failed authentication. A pending refresh cannot recreate a logged-out session. Logout is independent of the network lock, with a bounded 1.5-second wait if another process is actively writing credentials. Errors are reported rather than claiming a successful clear.

Each running process remains bound to its original local login generation. Logout clears local credentials for clients on this host; a later login requires restarting old connections. It does not retroactively cancel an API request already submitted, revoke every server-issued JWT, or sign out other devices. Server session expiry/revocation and backend membership authorization remain separate checks. Tests with simulated auth denial are not proof of hosted token-revocation behavior.

## Upgrade and recovery

Upgrade and restart all Crowdlisten client processes together. Older versions do not participate in these locks and must not continue writing the shared credential file. Generated setups pin the package version; the matching package/API release must be available first.

After an interrupted process, retry after 60 seconds for stale-lock recovery. Do not manually remove an active lock or use different stale/update settings in another writer. Private orphan staging files are removed under the credential lock; unreadable/corrupt credentials produce an explicit error and can be replaced by an explicit successful login. Logout also reports filesystem errors.

The lock uses the pinned [proper-lockfile](https://github.com/moxystudio/node-proper-lockfile) implementation with consistent heartbeat/staleness settings. Local filesystem and competing macOS process behavior are verified here. This is cooperative, lease-based coordination, not a fencing mechanism against manually removed locks, legacy writers, or indefinitely suspended processes resuming after lease expiry. Network-filesystem and Windows behavior have not been tested in this release.

## Verification boundary

The actual package entry is exercised through mcporter against controlled local auth/API responses, including startup success/failure racing logout, a later login and environment-token startup. Separate actual OS-process checks pause a writer immediately before rename and exercise contention, conditional updates, serial network refresh, logout and killed-writer recovery. Source/comment transport and OpenClaw skill discovery remain covered.

These local checks do not complete fresh-customer hosted login, live provider/browser collection, real Supabase refresh/revocation or production cross-client evidence continuity. See the workspace release audit before describing the candidate as production self-serve.
