"""Phase 168 (task 02): the settings catalogue is complete and consistent. The Settings panel (task 05) is GENERATED from ``app/core/settings_catalog.py`` — never hand-written — so these pins are load-bearing: ``set(CATALOG) == set(Settings.model_fields)`` fails the build the moment a new ``Settings`` field lands without its metadata (it can never silently disappear from the panel), the group table is closed both directions, and the capability sets are exactly the LOCKED decisions (A3/A4). """ from __future__ import annotations from app.config import Settings from app.core.settings_catalog import ( CATALOG, GROUPS, NON_OVERRIDABLE, RESTART_REQUIRED, SECRETS, SettingMeta, env_var, ) def test_catalog_covers_exactly_model_fields() -> None: """The completeness pin (both directions, the diff in the message).""" catalog_keys = set(CATALOG) field_names = set(Settings.model_fields) missing = sorted(field_names - catalog_keys) extra = sorted(catalog_keys - field_names) assert not missing, ( f"Settings fields missing from the catalogue (invisible in the " f"panel): {missing}" ) assert not extra, ( f"Catalogue entries with no Settings field (stale): {extra}" ) assert set(CATALOG) == set(Settings.model_fields) def test_groups_closed_both_directions() -> None: catalog_groups = {meta.group for meta in CATALOG.values()} only_in_groups = sorted(set(GROUPS) - catalog_groups) only_in_catalog = sorted(catalog_groups - set(GROUPS)) assert not only_in_groups, f"GROUPS entries with no catalogue member: {only_in_groups}" assert not only_in_catalog, f"Catalogue groups missing from GROUPS: {only_in_catalog}" def test_every_meta_carries_its_own_key() -> None: for key, meta in CATALOG.items(): assert isinstance(meta, SettingMeta) assert meta.key == key def test_secrets_are_exactly_the_masked_set() -> None: # LOCKED A4: write-only, masked — the 3 named secrets + # database_url (read-only, but its URL carries credentials) + # docs_token (phase 173, C1: the docs-push remote token reuses the # write-only/masked mechanism, llm_api_key-style). assert set(SECRETS) == { "llm_api_key", "admin_password", "session_secret", "database_url", "docs_token", } def test_non_overridable_is_exactly_locked_a3() -> None: # LOCKED A3: database_url builds the engine that would read the # override (chicken-and-egg brick); embedding_dim is fixed in the # chunks table by A6 (a dim override would corrupt retrieval). assert set(NON_OVERRIDABLE) == {"database_url", "embedding_dim"} def test_restart_required_is_the_boot_wired_set() -> None: # LOCKED A4: logging, the gzip middleware (compress_min_bytes), the # static mount (static_dir), create_engine (db_pool_*), and # SessionMiddleware (session_*). assert set(RESTART_REQUIRED) == { "log_level", "compress_min_bytes", "static_dir", "db_pool_size", "db_pool_max_overflow", "db_pool_recycle", "session_secret", "session_max_age", "session_cookie", } def test_env_var_is_bare_key_upper_prefixed() -> None: assert env_var("relevance_threshold") == "BOR_RELEVANCE_THRESHOLD" for key in CATALOG: assert env_var(key).startswith("BOR_") def test_llm_thinking_levels_are_plain_live_overridable_rows() -> None: """Phase 178 (task 01): the two thinking-level rows (the phase-172 knob, renamed + the new summary level) sit in ``LLM (aipi)`` with the ``Chat thinking level`` / ``Summary thinking level`` labels and are plain — not ``secret`` (free-form text values, like ``llm_chat_model``), not ``restart_required`` (the LLM client reads the settings per request via ``get_settings()`` — live), overridable (the overlay is generic over ``str`` fields).""" for key, label in ( ("llm_chat_thinking_level", "Chat thinking level"), ("llm_summary_thinking_level", "Summary thinking level"), ): meta = CATALOG[key] assert meta.group == "LLM (aipi)" assert meta.label == label assert meta.secret is False assert key not in SECRETS assert key not in RESTART_REQUIRED assert key not in NON_OVERRIDABLE def test_docs_user_is_a_plain_live_overridable_row() -> None: """Phase 173 (task 01, C1/C5): ``docs_user`` sits in ``Docs push`` with the ``Docs user`` label and is plain — not ``secret`` (a plain username), not ``restart_required`` (the push service reads the setting per push via ``get_settings()`` — live), overridable (the overlay is generic over ``str`` fields). An empty value is a valid state (C5: the anonymous push).""" meta = CATALOG["docs_user"] assert meta.group == "Docs push" assert meta.label == "Docs user" assert meta.secret is False assert "docs_user" not in SECRETS assert "docs_user" not in RESTART_REQUIRED assert "docs_user" not in NON_OVERRIDABLE def test_docs_token_is_a_secret_live_overridable_row() -> None: """Phase 173 (task 01, C1): ``docs_token`` has the ``Docs token`` label and ``secret=True`` — write-only end-to-end via the EXISTING derived mechanism (``SECRETS`` picks it up automatically; the API reports ``is_set`` + ``value=null``, a blank PUT 422s, the panel renders it masked, zero ``settings.js`` code). Live (the push service reads it per push), overridable (generic ``str`` overlay).""" meta = CATALOG["docs_token"] assert meta.group == "Docs push" assert meta.label == "Docs token" assert meta.secret is True assert "docs_token" in SECRETS assert "docs_token" not in RESTART_REQUIRED assert "docs_token" not in NON_OVERRIDABLE def test_labels_nonempty_and_unique() -> None: labels = [meta.label for meta in CATALOG.values()] assert all(label.strip() for label in labels), "empty label in the catalogue" duplicates = sorted({label for label in labels if labels.count(label) > 1}) assert not duplicates, f"duplicate labels: {duplicates}"