Problem Statement
ConnectSupervisor is authenticated when the bidirectional stream is created. The supervisor process already refreshes its gateway sandbox JWT in the background, and new outbound RPCs pick up the refreshed token through the shared AuthInterceptor token slot. An already-open ConnectSupervisor stream does not get re-authenticated when that token slot changes.
For the initial session-control migration in #1731, this is acceptable: the accepted stream remains valid until disconnect, supersede, sandbox deletion, or gateway restart. This follow-up tracks making session lifetime explicitly align with token lifetime.
Proposed Design
Add expiry-enforced supervisor sessions with proactive reconnect:
- Record the accepted token/session expiry when the gateway accepts
ConnectSupervisor.
- Extend
SessionAccepted with both:
session_expires_at_unix_ms
reconnect_before_unix_ms
- Have the supervisor open a fresh
ConnectSupervisor before reconnect_before_unix_ms, using the already-refreshed process-wide token.
- Let the gateway supersede the old session through the existing
SupervisorSessionRegistry reconnect behavior.
- Keep bearer tokens out of supervisor session payloads.
- Add a short gateway grace period so clock skew or scheduler delay does not cause avoidable sandbox disconnects.
Alternatives Considered
Agent Investigation
Relevant current behavior:
crates/openshell-core/src/grpc_client.rs stores the bearer token in a process-wide slot.
refresh_token_loop renews the gateway sandbox JWT around 80 percent of remaining lifetime.
AuthInterceptor injects the current token into new outbound gRPC requests.
crates/openshell-server/src/supervisor_session.rs validates the ConnectSupervisor request once at stream creation and does not re-check token expiry in the session loop.
Definition of Done
Related
Problem Statement
ConnectSupervisoris authenticated when the bidirectional stream is created. The supervisor process already refreshes its gateway sandbox JWT in the background, and new outbound RPCs pick up the refreshed token through the sharedAuthInterceptortoken slot. An already-openConnectSupervisorstream does not get re-authenticated when that token slot changes.For the initial session-control migration in #1731, this is acceptable: the accepted stream remains valid until disconnect, supersede, sandbox deletion, or gateway restart. This follow-up tracks making session lifetime explicitly align with token lifetime.
Proposed Design
Add expiry-enforced supervisor sessions with proactive reconnect:
ConnectSupervisor.SessionAcceptedwith both:session_expires_at_unix_msreconnect_before_unix_msConnectSupervisorbeforereconnect_before_unix_ms, using the already-refreshed process-wide token.SupervisorSessionRegistryreconnect behavior.Alternatives Considered
Agent Investigation
Relevant current behavior:
crates/openshell-core/src/grpc_client.rsstores the bearer token in a process-wide slot.refresh_token_looprenews the gateway sandbox JWT around 80 percent of remaining lifetime.AuthInterceptorinjects the current token into new outbound gRPC requests.crates/openshell-server/src/supervisor_session.rsvalidates theConnectSupervisorrequest once at stream creation and does not re-check token expiry in the session loop.Definition of Done
SessionAcceptedcarries explicit expiry and reconnect deadline fields.Related