Source code for exlab_wizard.tray.storage_secret

"""Per-installation NiceGUI ``storage_secret`` token. Backend Spec §15.3.

NiceGUI's ``ui.run_with`` requires a non-empty secret to sign the
Starlette ``SessionMiddleware`` that backs ``app.storage.user`` /
``app.storage.browser``. The codebase doesn't read ``app.storage.*``
today, so the secret is functionally vestigial -- but mounting NiceGUI
demands one. We generate a 32-byte hex token on first boot, write it
to ``<state_dir>/storage_secret`` (mode 0600) atomically, and reuse it
on subsequent boots so a future feature using ``app.storage`` doesn't
silently lose state across restarts.
"""

from __future__ import annotations

import contextlib
import os
import secrets
from pathlib import Path

from exlab_wizard.io import atomic_write_bytes
from exlab_wizard.logging import get_logger

__all__ = ["STORAGE_SECRET_FILE", "load_or_create_storage_secret"]

_log = get_logger(__name__)

STORAGE_SECRET_FILE = "storage_secret"
_SECRET_BYTES = 32


[docs] def load_or_create_storage_secret(state_dir: Path) -> str: """Return the per-installation storage secret, generating it if absent. The file is created with mode 0600 so other local users cannot read it. On a corrupted / empty file the secret is regenerated and the event is logged WARN -- losing the secret only resets browser storage scopes, which we don't currently use. """ path = Path(state_dir) / STORAGE_SECRET_FILE if path.exists(): try: value = path.read_text(encoding="utf-8").strip() except OSError as exc: _log.warning("storage_secret unreadable; regenerating [path=%s] %s", path, exc) value = "" if value: return value _log.warning("storage_secret file empty; regenerating [path=%s]", path) secret = secrets.token_hex(_SECRET_BYTES) path.parent.mkdir(parents=True, exist_ok=True) atomic_write_bytes(path, secret.encode("utf-8")) with contextlib.suppress(OSError): os.chmod(path, 0o600) return secret