wu981526092 commited on
Commit
032c9f9
Β·
1 Parent(s): 8e9b60e

πŸ”’ Implement User Privacy Protection for HF Spaces

Browse files

βœ… Problem solved:
β€’ Fixed multi-user data sharing issue in HF Spaces environment
β€’ All users were seeing each other's uploaded traces and data
β€’ SQLite database was globally shared across all sessions

🎯 Root cause analysis:
β€’ HF Spaces containers share the same persistent database file
β€’ All users access the same datasets/db/agent_monitoring.db instance
β€’ No user session isolation or data privacy protection

⚑ Privacy solutions implemented:
β€’ HF Spaces detection: Check SPACE_ID environment variable
β€’ In-memory database: Use sqlite:///:memory: for HF Spaces
β€’ Session isolation: Each container restart gets fresh database
β€’ Local development: Still uses persistent file database

πŸš€ User experience improvements:
β€’ Added privacy notice banner for HF Spaces users
β€’ Clear messaging about data temporariness
β€’ Backend logging shows database type on startup
β€’ Frontend detects HF environment automatically

πŸ”’ Security impact:
β€’ Eliminates cross-user data visibility
β€’ Prevents sensitive trace information leakage
β€’ Ensures session-based data isolation
β€’ Maintains full functionality while protecting privacy

backend/app.py CHANGED
@@ -77,6 +77,14 @@ async def startup_event():
77
  try:
78
  from backend.database.init_db import init_database
79
  init_database(reset=False, force=False)
 
 
 
 
 
 
 
 
80
  logger.info("πŸ—„οΈ Database initialized successfully")
81
  except Exception as e:
82
  logger.error(f"❌ Database initialization failed: {e}")
 
77
  try:
78
  from backend.database.init_db import init_database
79
  init_database(reset=False, force=False)
80
+
81
+ # Show database type info
82
+ if os.getenv("SPACE_ID"):
83
+ logger.info("πŸ”’ HF Spaces: Using in-memory database for user privacy")
84
+ logger.info("πŸ“ Note: Data will be cleared when container restarts")
85
+ else:
86
+ logger.info("πŸ’Ύ Local development: Using persistent database")
87
+
88
  logger.info("πŸ—„οΈ Database initialized successfully")
89
  except Exception as e:
90
  logger.error(f"❌ Database initialization failed: {e}")
backend/database/__init__.py CHANGED
@@ -11,8 +11,19 @@ from sqlalchemy.orm import sessionmaker, scoped_session
11
  # Get the absolute path to the project root directory
12
  ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13
 
14
- # Database URL with absolute path
15
- DATABASE_URL = f"sqlite:///{os.path.join(ROOT_DIR, 'datasets/db/agent_monitoring.db')}"
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  # Create engine
18
  engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
 
11
  # Get the absolute path to the project root directory
12
  ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
13
 
14
+ # Database URL - Use in-memory SQLite for HF Spaces to avoid data sharing between users
15
+ # This ensures each container restart gets a fresh database
16
+ import uuid
17
+ session_id = str(uuid.uuid4())[:8]
18
+
19
+ # For HF Spaces: Use in-memory database to prevent user data sharing
20
+ # For local development: Use file database
21
+ if os.getenv("SPACE_ID"): # HF Spaces environment
22
+ DATABASE_URL = "sqlite:///:memory:"
23
+ print(f"πŸ”’ HF Spaces: Using in-memory database (session: {session_id})")
24
+ else:
25
+ DATABASE_URL = f"sqlite:///{os.path.join(ROOT_DIR, 'datasets/db/agent_monitoring.db')}"
26
+ print(f"πŸ’Ύ Local: Using persistent database")
27
 
28
  # Create engine
29
  engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
frontend/src/components/layout/MainWorkspace.tsx CHANGED
@@ -16,6 +16,7 @@ import { ConnectionsView } from "../features/connections/ConnectionsView";
16
  import { UploadView } from "../features/upload/UploadView";
17
  import { Button } from "@/components/ui/button";
18
  import { ArrowLeft } from "lucide-react";
 
19
 
20
  interface MainWorkspaceProps {
21
  isSidebarCollapsed: boolean;
@@ -391,6 +392,18 @@ export function MainWorkspace({
391
  </div>
392
  )}
393
 
 
 
 
 
 
 
 
 
 
 
 
 
394
  {/* Main Content */}
395
  <div className="flex-1 flex flex-col min-h-0">{renderView()}</div>
396
  </div>
 
16
  import { UploadView } from "../features/upload/UploadView";
17
  import { Button } from "@/components/ui/button";
18
  import { ArrowLeft } from "lucide-react";
19
+ import { IS_HF_SPACES } from "@/lib/config";
20
 
21
  interface MainWorkspaceProps {
22
  isSidebarCollapsed: boolean;
 
392
  </div>
393
  )}
394
 
395
+ {/* HF Spaces Privacy Notice */}
396
+ {IS_HF_SPACES && (
397
+ <div className="bg-amber-50 border-b border-amber-200 px-6 py-3 text-sm text-amber-800 flex items-center gap-2">
398
+ <span className="text-amber-600">πŸ”’</span>
399
+ <span>
400
+ <strong>Privacy Notice:</strong> You're using AgentGraph on Hugging Face Spaces.
401
+ Your data is stored in a temporary session and will be cleared when the container restarts.
402
+ Data is not shared between users or sessions.
403
+ </span>
404
+ </div>
405
+ )}
406
+
407
  {/* Main Content */}
408
  <div className="flex-1 flex flex-col min-h-0">{renderView()}</div>
409
  </div>
frontend/src/lib/config.ts CHANGED
@@ -24,3 +24,14 @@ export const getApiBase = () => {
24
  };
25
 
26
  export const API_BASE = getApiBase();
 
 
 
 
 
 
 
 
 
 
 
 
24
  };
25
 
26
  export const API_BASE = getApiBase();
27
+
28
+ // Check if running on Hugging Face Spaces
29
+ export const isHuggingFaceSpaces = () => {
30
+ if (typeof window === "undefined") return false;
31
+
32
+ return window.location.hostname.includes("huggingface.co") ||
33
+ window.location.hostname.includes("hf.space") ||
34
+ window.location.hostname.endsWith(".hf.space");
35
+ };
36
+
37
+ export const IS_HF_SPACES = isHuggingFaceSpaces();