mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-07-09 16:00:45 +00:00
## Problem
Admin config was a single responsibility hub with manually duplicated
provider metadata. Provider labels, fields, template loading,
validation, persistence, and status lived in one place.
## Changes
| Before | After |
| --- | --- |
| Admin config lived in one large `api/admin_config.py` module. | Admin
config lives in package modules for manifest, sources, values,
validation, persistence, and status. |
| Provider admin fields and UI labels were manually duplicated. |
Provider admin fields and display names derive from `PROVIDER_CATALOG`
with admin-only help overrides. |
| `fcc-init` and Admin UI loaded `.env.example` separately. | `fcc-init`
and Admin UI use shared `config.env_template` loading. |
| Architecture docs pointed to the old admin config module. |
Architecture docs describe the package owners and catalog-driven
provider manifest. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR refactors admin configuration into a catalog-driven package. The
main changes are:
- Split the former monolithic `api/admin_config.py` into manifest,
source loading, value presentation, validation, persistence, and
provider status modules.
- Generate provider admin fields and display names from
`PROVIDER_CATALOG` with admin-specific help overrides.
- Share `.env.example` loading between `fcc-init` and Admin UI defaults
through `config.env_template`.
- Update admin routes, Admin UI provider labels, architecture docs,
version metadata, and contract/API tests for the new module layout.
</details>
<h3>Confidence Score: 5/5</h3>
The refactor appears merge-safe with no code issues identified in the
reviewed changes.
The package split, catalog-driven provider metadata, shared environment
template loading, route updates, and tests/docs changes are cohesive and
covered by corresponding contract/API/CLI test updates.
<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>
**What T-Rex did**
- T-Rex ran manifest validation for catalog provider before and after
routes, capturing base and head responses and catalog-alignment checks,
and confirmed the validation completed successfully.
- T-Rex evaluated the shared-env-template scenarios, observing the
before run with no config.env\_template module and the after run with
the module present, with patched loader values and all consistency
checks passing, and the run exited with code 0.
- T-Rex executed the package-admin-workflow validation, verifying the
base and after import paths, the load/validate/write workflow produced
matching outputs, and the run completed with exit code 0.
<a
href="https://app.greptile.com/trex/runs/12529845/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=1"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=1"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=1"
height="32"></picture></a>
<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>
<sub>Reviews (1): Last reviewed commit: ["Refactor admin config into
catalog-drive..."](d6239d7953)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=40315222)</sub>
<!-- /greptile_comment -->
81 lines
2.1 KiB
Python
81 lines
2.1 KiB
Python
"""Admin config source loading and source precedence."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from io import StringIO
|
|
from pathlib import Path
|
|
from typing import Literal
|
|
|
|
from dotenv import dotenv_values
|
|
|
|
from config.env_template import load_env_template_or_empty
|
|
from config.paths import managed_env_path
|
|
|
|
from .manifest import FIELDS
|
|
|
|
SourceType = Literal[
|
|
"default",
|
|
"template",
|
|
"repo_env",
|
|
"managed_env",
|
|
"explicit_env_file",
|
|
"process",
|
|
]
|
|
|
|
|
|
def repo_env_path() -> Path:
|
|
"""Return the repo-local env path."""
|
|
|
|
return Path(".env")
|
|
|
|
|
|
def explicit_env_path() -> Path | None:
|
|
"""Return the explicit FCC_ENV_FILE path, when configured."""
|
|
|
|
if explicit := os.environ.get("FCC_ENV_FILE"):
|
|
return Path(explicit)
|
|
return None
|
|
|
|
|
|
def configured_env_files() -> tuple[tuple[SourceType, Path], ...]:
|
|
"""Return dotenv files in low-to-high precedence order."""
|
|
|
|
files: list[tuple[SourceType, Path]] = [
|
|
("repo_env", repo_env_path()),
|
|
("managed_env", managed_env_path()),
|
|
]
|
|
if explicit := explicit_env_path():
|
|
files.append(("explicit_env_file", explicit))
|
|
return tuple(files)
|
|
|
|
|
|
def dotenv_values_from_text(text: str) -> dict[str, str]:
|
|
"""Parse dotenv text into string values."""
|
|
|
|
values = dotenv_values(stream=StringIO(text))
|
|
return {key: "" if value is None else value for key, value in values.items()}
|
|
|
|
|
|
def template_values() -> dict[str, str]:
|
|
"""Return .env.example values plus manifest defaults for newer fields."""
|
|
|
|
values = dotenv_values_from_text(load_env_template_or_empty())
|
|
for field in FIELDS:
|
|
values.setdefault(field.key, field.default)
|
|
return values
|
|
|
|
|
|
def dotenv_values_from_file(path: Path) -> dict[str, str]:
|
|
"""Return dotenv values from a file, or an empty mapping when absent."""
|
|
|
|
if not path.is_file():
|
|
return {}
|
|
values = dotenv_values(path)
|
|
return {key: "" if value is None else value for key, value in values.items()}
|
|
|
|
|
|
def is_locked_source(source: SourceType) -> bool:
|
|
"""Return whether an admin value source must not be overwritten."""
|
|
|
|
return source in {"process", "explicit_env_file"}
|