"""HuggingFace Space entrypoint for the sync_pilot dashboard. Wraps the multi-page Streamlit app in ``sync_pilot.dashboard`` with an ``ACCESS_KEY`` gate (matching the rehab-robotics GURMA dashboard's pattern in ``src/dashboard/app.py``). The wrapper *replicates* the navigation block from ``sync_pilot/dashboard/app.py:main`` rather than importing the module — the module calls ``main()`` at top level, which would re-fire ``st.set_page_config`` after the wrapper has already set it. Required Space secrets (set in HF UI): ACCESS_KEY — the login password HF_TOKEN — read token for the private dataset PRIVATE_DATASET_REPO — e.g. ``emresar/gurma-dashboard-private-data`` SYNC_PILOT_DATA_SOURCE — ``hf`` (default in the Dockerfile) """ from __future__ import annotations import hashlib import os import streamlit as st # ``set_page_config`` must be the first Streamlit call — set it before # any other ``st.*`` invocation (including ones that might happen inside # the auth gate's ``show_login`` form). st.set_page_config( page_title="sync_pilot — Median Müzik", page_icon="♪", layout="wide", initial_sidebar_state="expanded", ) # --------------------------------------------------------------------------- # Access control (mirrors src/dashboard/app.py for the rehab dashboard) # --------------------------------------------------------------------------- ACCESS_KEY = os.getenv("ACCESS_KEY", "") IS_HF_SPACE = bool(os.getenv("HF_SPACE")) def _auth_token(key: str, salt: str = "sync_pilot") -> str: """Short deterministic token kept in the URL so refresh survives.""" return hashlib.sha256(f"{salt}_{key}".encode()).hexdigest()[:16] def check_access() -> bool: """Authenticate via session state, URL token, or pass-through locally.""" if not ACCESS_KEY: # Local dev (no key configured) — bypass. On HF Space we refuse # rather than open the dashboard up; treat missing secret as a # misconfiguration the user can fix from the Settings panel. return not IS_HF_SPACE if st.session_state.get("authenticated"): return True if st.query_params.get("auth") == _auth_token(ACCESS_KEY): st.session_state.authenticated = True return True return False def show_login() -> None: st.markdown( """ """, unsafe_allow_html=True, ) col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.markdown( """