from pathlib import Path
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import FileResponse, HTMLResponse, Response
from src.frontend_bundle import build_frontend
from src.compression import _quality
router = APIRouter()
DASHBOARD_FILE = Path(__file__).resolve().parent.parent / "frontend" / "index.html"
MANIFEST_FILE = DASHBOARD_FILE.parent / "manifest.webmanifest"
FRONTEND_BUILD = build_frontend(DASHBOARD_FILE.parent)
LOGIN_HTML = """
Sign in ยท Stackchain Dashboard
Operator sign in
Use an enrolled passkey, or enter the dashboard access token for bootstrap and recovery. The token is exchanged for a private, short-lived session and is never stored on this device.
"""
class RevalidatingHTMLResponse(HTMLResponse):
def __init__(self, content, status_code=200, headers=None, media_type=None, background=None):
response_headers = dict(headers or {})
response_headers["Cache-Control"] = "no-cache"
super().__init__(content, status_code, response_headers, media_type, background)
@router.get("/", response_class=RevalidatingHTMLResponse)
async def dashboard() -> str:
return FRONTEND_BUILD.dashboard_html
@router.get("/login", response_class=RevalidatingHTMLResponse)
async def login() -> str:
return LOGIN_HTML
@router.get("/manifest.webmanifest", response_class=FileResponse)
async def web_app_manifest() -> FileResponse:
return FileResponse(MANIFEST_FILE, media_type="application/manifest+json")
@router.get("/service-worker.js")
async def service_worker() -> Response:
return Response(
FRONTEND_BUILD.service_worker_source,
media_type="application/javascript",
headers={"Service-Worker-Allowed": "/", "Cache-Control": "no-cache"},
)
@router.get("/runtime-{digest}.js")
async def runtime_bundle(digest: str, request: Request) -> Response:
if digest != FRONTEND_BUILD.runtime_digest:
raise HTTPException(status_code=404, detail="Runtime revision not found")
accepts_gzip = _quality(request.headers.get("Accept-Encoding", ""), "gzip") > 0
return Response(
(
FRONTEND_BUILD.runtime_gzip_bytes
if accepts_gzip
else FRONTEND_BUILD.runtime_bytes
),
media_type="application/javascript",
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"Vary": "Accept-Encoding",
**({"Content-Encoding": "gzip"} if accepts_gzip else {}),
},
)
@router.get("/feature-{name}-{digest}.js")
async def feature_bundle(name: str, digest: str, request: Request) -> Response:
bundle = FRONTEND_BUILD.feature_bundles.get(name)
if bundle is None or digest != bundle.runtime_digest:
raise HTTPException(status_code=404, detail="Feature revision not found")
accepts_gzip = _quality(request.headers.get("Accept-Encoding", ""), "gzip") > 0
return Response(
bundle.runtime_gzip_bytes if accepts_gzip else bundle.runtime_bytes,
media_type="application/javascript",
headers={
"Cache-Control": "public, max-age=31536000, immutable",
"Vary": "Accept-Encoding",
**({"Content-Encoding": "gzip"} if accepts_gzip else {}),
},
)