IDAgentsFreshTest / SESSION_ISOLATION_GUIDE.md
IDAgents Developer
Implement per-user session isolation system - Each authenticated user now has isolated workspace with separate chat histories and agent data
d952de8
|
raw
history blame
5.46 kB
# Per-User Session Isolation Implementation Guide
## Overview
This guide explains how to implement per-user session isolation in the ID Agents app so that each authenticated user has their own isolated workspace (chat histories, agents, patient data, etc.).
## Problem
Currently, all users share the same `gr.State()` objects, meaning:
- User A sees User B's chat messages
- User A's agents appear in User B's dropdown
- Everyone works in the same shared container
## Solution
Use Gradio's `gr.Request` object to identify users and store their data separately in a `UserSessionManager`.
## Files Created
1. **user_session_manager.py** - Core session storage with thread-safe operations
2. **session_helpers.py** - Helper functions for getting/setting user data
## Implementation Steps
### Step 1: Update Function Signatures
All functions that currently accept `gr.State` parameters need to accept `request: gr.Request` instead:
**Before:**
```python
def simple_chat_response(user_message, history):
# Uses history parameter
...
```
**After:**
```python
def simple_chat_response(user_message, request: gr.Request):
# Gets history from session manager
history = get_user_simple_chat_history(request)
...
# Saves history back to session manager
set_user_simple_chat_history(request, updated_history)
```
### Step 2: Update Gradio Event Bindings
When binding functions to Gradio components, remove `gr.State` from inputs/outputs and add `request`:
**Before:**
```python
simple_input.submit(
simple_chat_response,
inputs=[simple_input, simple_chat_history],
outputs=[simple_chatbot, simple_input]
)
```
**After:**
```python
simple_input.submit(
simple_chat_response,
inputs=[simple_input], # request is added automatically by Gradio
outputs=[simple_chatbot, simple_input]
)
```
### Step 3: Remove gr.State() Declarations
In `build_ui()`, remove these lines:
```python
simple_chat_history = gr.State([])
builder_chat_histories = gr.State({})
deployed_chat_histories = gr.State({})
```
These are now managed by the session manager per-user.
## Functions That Need Updates
### Critical Functions (High Priority)
1. βœ… `simple_chat_response` - Already updated
2. βœ… `chatpanel_handle` - Already updated
3. `load_history` - Needs update
4. `reset_chat` - May need update if it affects per-user state
5. `save_deployed_agent` - If it stores to chat histories
6. `populate_from_preset` - If it affects builder state
### UI Event Bindings That Need Updates
All `.click()`, `.submit()`, `.change()` handlers that currently use:
- `simple_chat_history`
- `builder_chat_histories`
- `deployed_chat_histories`
- Any other `gr.State()` objects
## Testing Checklist
After implementation, test with 2 different user accounts simultaneously:
- [ ] User1 and User2 have separate simple chat histories
- [ ] User1's agents don't appear in User2's dropdown
- [ ] User1 and User2 can build different agents without interference
- [ ] Patient data is separate between users
- [ ] Reset/clear functions only affect the current user
- [ ] Logout/re-login maintains session (or clears if desired)
## Key Benefits
1. **True Multi-Tenancy**: Each user gets isolated workspace
2. **No Data Leakage**: User A cannot see User B's data
3. **Thread-Safe**: Concurrent users don't interfere with each other
4. **Scalable**: Can handle multiple simultaneous users
5. **Auditable**: Can log per-user actions for debugging
## Important Notes
- `gr.Request` only works when authentication is enabled
- Username comes from `request.username` (set by Gradio's auth system)
- Session data is stored in memory (lost on restart - could be persisted to database if needed)
- The session manager is thread-safe for concurrent access
## Migration Strategy
### Phase 1: Core Chat Functions (DONE)
- βœ… simple_chat_response
- βœ… chatpanel_handle
### Phase 2: Agent Management
- load_history
- save_deployed_agent
- remove_selected_agent
### Phase 3: UI Bindings
- Update all .click() and .submit() bindings
- Remove gr.State declarations
### Phase 4: Testing & Verification
- Multi-user testing
- Session isolation verification
- Performance testing
## Quick Reference
```python
# Import at top of app.py (DONE)
from user_session_manager import session_manager, get_username_from_request, SessionKeys
from session_helpers import (
get_user_simple_chat_history, set_user_simple_chat_history,
get_user_builder_chat_histories, set_user_builder_chat_histories,
get_user_deployed_chat_histories, set_user_deployed_chat_histories,
get_current_username, log_user_access
)
# In any function:
def my_function(user_input, request: gr.Request):
username = get_current_username(request)
log_user_access(request, "my_function")
# Get user-specific data
data = session_manager.get_user_data(username, "my_key", default=[])
# Process...
# Save user-specific data
session_manager.set_user_data(username, "my_key", new_data)
```
## Next Steps
To complete the implementation:
1. Search for all `gr.State(` declarations and remove them
2. Search for all functions that have `histories` or `history` parameters
3. Update each function to use session helpers
4. Update all Gradio event bindings
5. Test with multiple users
6. Deploy and verify
For assistance, see:
- user_session_manager.py - Core session storage
- session_helpers.py - Helper functions and examples