Index: lan-frontend/src/App.jsx
===================================================================
--- lan-frontend/src/App.jsx	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/App.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,6 +1,6 @@
-import React from "react";
-import {useEffect, useMemo, useState} from "react";
+import React, {useEffect, useMemo, useState} from "react";
 import "./styles/theme.css";
 
+import Login from "./components/Login";
 import TopBar from "./components/TopBar";
 import ComputerCard from "./components/ComputerCard";
@@ -22,13 +22,40 @@
     const [selectedEnv, setSelectedEnv] = useState("default");
 
+    const [me, setMe] = useState(null);
+    const [meLoading, setMeLoading] = useState(true);
+
+    // const [openAI, setOpenAI] = useState(false);
+    // const [scope, setScope] = useState(null);
+
+
+    async function loadMe() {
+        setMeLoading(true);
+        try {
+            const r = await fetch("/api/me", {credentials: "include"});
+            if (r.ok) {
+                const data = await r.json();
+                setMe(data.user);
+            } else {
+                setMe(null);
+            }
+        } catch (e) {
+            console.error("loadMe error", e);
+            setMe(null);
+        } finally {
+            setMeLoading(false);
+        }
+    }
+
     async function refresh() {
         try {
             setLoading(true);
             const [s, c] = await Promise.all([
-                fetch("/api/stats").then((r) => r.json()),
+                fetch("/api/stats", {credentials: "include"}).then((r) => r.json()),
                 fetch("/api/computers", {
+                    credentials: "include",
                     headers: {"X-Env": selectedEnv},
                 }).then((r) => r.json()),
             ]);
+
             setStats(s);
             setComputers(Array.isArray(c) ? c : []);
@@ -41,7 +68,14 @@
     }
 
+    // on mount: check session
     useEffect(() => {
-        refresh();
-    }, [selectedEnv]);
+        loadMe();
+    }, []);
+
+    // when logged in OR env changed, refresh data
+    useEffect(() => {
+        if (me) refresh();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [me, selectedEnv]);
 
     const filtered = useMemo(() => {
@@ -51,8 +85,15 @@
             .filter((c) => {
                 if (!q) return true;
-                const hay = [c.name, c.user, c.ip, c.os, c.status].filter(Boolean).join(" ").toLowerCase();
+                const hay = [c.name, c.user, c.ip, c.os, c.status]
+                    .filter(Boolean)
+                    .join(" ")
+                    .toLowerCase();
                 return hay.includes(q);
             });
     }, [computers, query, status]);
+
+    // Gate UI
+    if (meLoading) return <div style={{padding: 20}}>Loading…</div>;
+    if (!me) return <Login onDone={loadMe}/>;
 
     return (
@@ -64,5 +105,8 @@
                 onEnvChange={(env) => setSelectedEnv(env)}
                 selectedEnv={selectedEnv}
+                me={me}
+                onLoggedOut={loadMe}
             />
+
 
             {/* STATS */}
@@ -104,5 +148,9 @@
                         />
 
-                        <select className="select" value={status} onChange={(e) => setStatus(e.target.value)}>
+                        <select
+                            className="select"
+                            value={status}
+                            onChange={(e) => setStatus(e.target.value)}
+                        >
                             <option value="">All status</option>
                             <option value="online">Online</option>
@@ -111,5 +159,7 @@
                         </select>
 
-                        <button className="btn primary" onClick={refresh}>Refresh</button>
+                        <button className="btn primary" onClick={refresh}>
+                            Refresh
+                        </button>
                     </div>
                 </div>
@@ -122,8 +172,12 @@
                     <div style={{display: "flex", gap: 10, alignItems: "center"}}>
                         <span className="pill">{filtered.length} computers</span>
-                        <button className="btn" onClick={() => {
-                            setQuery("");
-                            setStatus("");
-                        }}>Reset
+                        <button
+                            className="btn"
+                            onClick={() => {
+                                setQuery("");
+                                setStatus("");
+                            }}
+                        >
+                            Reset
                         </button>
                     </div>
@@ -142,5 +196,7 @@
                         ))}
                         {filtered.length === 0 && (
-                            <div style={{color: "var(--dim)"}}>No computers match filter.</div>
+                            <div style={{color: "var(--dim)"}}>
+                                No computers match filter.
+                            </div>
                         )}
                     </div>
@@ -160,4 +216,15 @@
 
             {/* AI DRAWER */}
+            {/*<button onClick={() => setOpenAI(true)}>AI</button>*/}
+
+            {/*<AIAssistantDrawer*/}
+            {/*    open={openAI}*/}
+            {/*    onClose={() => setOpenAI(false)}*/}
+            {/*    computers={computers}*/}
+            {/*    scope={scope}*/}
+            {/*    setScope={setScope}*/}
+            {/*    apiBase={import.meta.env.VITE_API_BASE}*/}
+            {/*/>*/}
+
             <AIAssistantDrawer
                 open={aiOpen}
@@ -166,5 +233,8 @@
                 scope={aiScope}
                 setScope={setAiScope}
+                apiBase={import.meta.env.VITE_API_BASE}
             />
+
+
         </div>
     );
