Remove the blanket .agent/ gitignore so the phase roadmap, user stories, reports, and PLAN.md are versioned with the code. Only runtime artifacts (.agent/phase-sessions/, .agent/pipeline.log) remain ignored. Update AGENTS.md git protocol rule to match.
4.2 KiB
4.2 KiB
Task 01 — Three new Settings + /api/config keys (+ validator)
Phase: 62_ui_customization · Source: TODO.md:3 — "…an environment variable to call it 'Brain of ' along with custom message-input placeholder, custom footer-inner text, custom color themes…"
Story: n/a (TODO-derived)
Objective
The backend half of the customization layer: three new BOR_-prefixed settings with phase-61's neutral strings as DEFAULTS, surfaced through the existing public GET /api/config boot fetch — with the existing exact-key-set contract tests moved to the new six-key set so the suite stays green from this task on.
Work
app/config.py— in the# --- App ---block (afterstatic_dir, ~L47), add:plus a# --- UI customization (phase 62, TODO L3) --- # Defaults are the phase-61 neutral copy — UNSET => byte-identical UI. input_placeholder: str = "Ask me anything…" footer_text: str = "Powered by self-hosted models" #: Theme file NAME under frontend/assets/themes/ (e.g. "indigo.css"); #: empty = the built-in dark-tech palette. Validated: bare filename #: only — no paths, no ".." (no-CDN: served from the static dir). theme: str = ""@field_validator("theme")(pydantic v2,mode="after"): empty string passes; the value must match^[a-z0-9_-]+\.css$(ASCII, lowercase, bare filename) or the validator raisesValueErrornaming the offending value and the allowed shape (phase-56 fail-loud house style — a typo in.envmust kill startup, not silently 404).input_placeholder/footer_text: no validation beyond being strings (empty ⇒ the template default stands, handled by brand.js treating empty as "skip").
app/api/config.py— theGET /api/configresponse grows to exactly six keys:(values passed through verbatim — the frontend brand layer decides "empty = keep the template default"; NO new secrets surface: these are display strings, same public posture asreturn { "app_name": settings.app_name, "version": settings.app_version, "docs_repo_configured": settings.docs_configured, "input_placeholder": settings.input_placeholder, "footer_text": settings.footer_text, "theme": settings.theme, }app_name). Update the module + endpoint docstrings to cite phase 62.- Contract-test updates (MUST land with this task or the suite goes red):
tests/integration/test_api.pyL21–46: both exact-key-set assertions become{"app_name", "version", "docs_repo_configured", "input_placeholder", "footer_text", "theme"}; assert the DEFAULT values ("Ask me anything…","Powered by self-hosted models",""); extendtest_config_follows_overridden_app_name's pattern with atest_config_serves_ui_customization_overridestest (fresh app withSettings(input_placeholder=…, footer_text=…, theme="indigo.css")→ the three keys reflect the overrides).tests/e2e/test_configurable_brand.pyL150 + L158: the two exact-key-set assertions grow to the six-key set (values untouched — that suite's instance has no phase-62 overrides, so the new keys are their defaults).
- Unit tests —
tests/unit/test_config.py(existing file, add cases):themevalidator —""ok;"indigo.css"ok;"Indigo.css"rejected;"../evil.css"rejected;"a/b.css"rejected;"indigo"(no extension) rejected — each rejection names the value. Plus one test thatGET /api/config(integration) default response carries the three new keys with the locked defaults.
Testing & Quality
uv run pytestgreen (unit + integration);uv run ruff check . && uv run pyrightclean.- Coverage: >90% on
app/(validate.sh gate).
Completion Criteria
Settingsexposesinput_placeholder/footer_text/themewith the locked defaults;BOR_THEME=../evil.cssin the env fails app startup, naming the value (verified once via a unit/validator test — the E2E boots-check lands in task 05).GET /api/configreturns exactly the six keys (defaults + overrides) — integration tests green.tests/e2e/test_configurable_brand.py's key-set assertions updated (suite itself re-run in task 05's regression pass, DB up).- Full suite green, lint + types clean, coverage >90%.