diff --git a/muxplex/main.py b/muxplex/main.py
index 5791bc3..ddcbbf7 100644
--- a/muxplex/main.py
+++ b/muxplex/main.py
@@ -22,6 +22,7 @@ import websockets.exceptions
from websockets.typing import Subprotocol
from fastapi import FastAPI, HTTPException, WebSocket
+from fastapi.responses import HTMLResponse, JSONResponse as FastJSONResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
@@ -465,6 +466,34 @@ async def terminal_ws_proxy(websocket: WebSocket) -> None:
pass
+# ---------------------------------------------------------------------------
+# Auth routes
+# ---------------------------------------------------------------------------
+
+
+@app.get("/login", response_class=HTMLResponse)
+async def login_page():
+ """Stub login page — replaced in Phase 2 with branded login.html."""
+ return HTMLResponse(
+ "
"
+ "muxplex login
"
+ ""
+ ""
+ )
+
+
+@app.get("/auth/mode")
+async def auth_mode_endpoint():
+ """Return the current auth mode and running username."""
+ username = ""
+ if _auth_mode == "pam":
+ username = pwd.getpwuid(os.getuid()).pw_name
+ return {"mode": _auth_mode, "user": username}
+
+
# ---------------------------------------------------------------------------
# Static file serving — MUST come after all API routes (first-match-wins)
# ---------------------------------------------------------------------------
diff --git a/muxplex/tests/test_api.py b/muxplex/tests/test_api.py
index b53850b..45cafc0 100644
--- a/muxplex/tests/test_api.py
+++ b/muxplex/tests/test_api.py
@@ -683,3 +683,25 @@ def test_non_localhost_without_auth_gets_redirected(monkeypatch):
response = c.get("/health", follow_redirects=False)
# Should be redirected to /login or get 307/401
assert response.status_code in (307, 401)
+
+
+# ---------------------------------------------------------------------------
+# Login stub and auth mode endpoint
+# ---------------------------------------------------------------------------
+
+
+def test_get_login_returns_200_html(client):
+ """GET /login returns 200 with HTML content."""
+ response = client.get("/login")
+ assert response.status_code == 200
+ assert "text/html" in response.headers["content-type"]
+ assert "