# S02 Research — Trust & Credibility Cleanup

## Summary

Three independent cleanup items, all low-risk, well-understood work using existing patterns. No new technology, no risky integration.

**Success criteria from roadmap:**
1. Creators page has no TestCreator
2. Footer shows clean version info
3. Search results have no yellow jargon banner

## Recommendation

Light research — each item is a small, independent change. No external dependencies or unfamiliar APIs. Straightforward code/config edits.

## Implementation Landscape

### Item 1: Remove TestCreator from Creators page

**Problem:** A test creator record exists in the production PostgreSQL database. The creators list endpoint (`GET /api/v1/creators`) returns all rows from the `creators` table with no filtering — so TestCreator appears on the public Creators page.

**Current code:**
- `backend/routers/creators.py` — `list_creators()` does `select(Creator, ...)` with no visibility filter
- `backend/models.py` — `Creator` model has no `hidden`, `is_test`, or `visible` field
- `frontend/src/pages/CreatorsBrowse.tsx` — renders whatever the API returns

**Approach options:**
1. **Add `hidden` boolean column to Creator model** + Alembic migration + filter in `list_creators()`. Most robust — supports hiding any creator in the future. Small migration.
2. **Admin DELETE endpoint** — add `DELETE /api/v1/creators/{slug}` to remove the test record. Solves the immediate problem but doesn't prevent future test data.
3. **Combine both** — add the `hidden` flag for soft-delete semantics AND provide an admin delete endpoint for hard cleanup.

**Recommended: Option 1 (hidden flag).** A boolean column with `default=False` is a zero-risk migration. The query filter is one `.where(Creator.hidden != True)` clause. This also supports future use cases (temporarily hiding a creator during content review). The admin DELETE can be deferred — the hidden flag is sufficient.

**Files to change:**
- `backend/models.py` — add `hidden: Mapped[bool]` column
- `alembic/versions/` — new migration adding `hidden` column with `server_default='false'`
- `backend/routers/creators.py` — add `.where(Creator.hidden != True)` to both `list_creators()` and the count query
- Mark TestCreator as hidden via a data migration or SQL statement in the migration itself (if the record name is known)

### Item 2: Footer shows clean version info

**Problem:** The footer (`frontend/src/components/AppFooter.tsx`) shows version, build date, and git commit via Vite build-time constants. In Docker builds, `VITE_GIT_COMMIT` defaults to `"dev"` if `GIT_COMMIT_SHA` env var isn't set during `docker compose build`. The version comes from `frontend/package.json` (`"0.1.0"`).

**Current state:**
- `frontend/vite.config.ts` — defines `__APP_VERSION__`, `__BUILD_DATE__`, `__GIT_COMMIT__` via `define:{}`
- `docker/Dockerfile.web` — accepts `ARG VITE_GIT_COMMIT=dev`, passes to env
- `docker-compose.yml` — `args: VITE_GIT_COMMIT: ${GIT_COMMIT_SHA:-dev}`
- `frontend/src/components/AppFooter.tsx` — renders `v{version} · Built {date} · {commit} · GitHub`

**What "clean" means:** The footer should show a real commit hash (not "dev") and the version should be meaningful. The build date is fine as-is.

**Approach:**
1. Update `docker-compose.yml` build args to compute `GIT_COMMIT_SHA` at build time: replace `${GIT_COMMIT_SHA:-dev}` with a shell command that runs `git rev-parse --short HEAD` (or make the build script set it).
2. In `Dockerfile.web`, the fallback already handles local dev ("dev" is fine there).
3. Optionally — if the commit is "dev", hide the commit section in the footer rather than showing the literal word "dev".
4. Bump `frontend/package.json` version to reflect the current milestone (e.g., `0.8.0` for M008).

**Files to change:**
- `frontend/src/components/AppFooter.tsx` — conditionally hide commit when "dev"
- `frontend/package.json` — bump version
- `docker-compose.yml` — improve GIT_COMMIT_SHA default (optional, could also be done in a deploy script)

### Item 3: Remove yellow jargon banner from search results

**Problem:** When Qdrant semantic search fails and the keyword fallback is used, a yellow/amber banner appears: "Showing keyword results — semantic search unavailable". This is developer-facing diagnostic text, not user-appropriate messaging.

**Current code:**
- `backend/routers/search.py` — returns `fallback_used: bool` in `SearchResponse`
- `backend/search_service.py` — sets `fallback_used = True` when Qdrant/embedding fails (line 292)
- `backend/schemas.py` — `SearchResponse.fallback_used: bool = False`
- `frontend/src/pages/SearchResults.tsx` — renders `.search-fallback-banner` when `fallbackUsed && results.length > 0`
- `frontend/src/App.css` line 1119 — styles using `--color-banner-amber-bg/border/text`

**Approach options:**
1. **Remove the banner entirely** — simplest. Users don't need to know which search backend served results. The results still appear either way.
2. **Reword to user-friendly text** — e.g., "Showing approximate matches" or nothing at all.
3. **Move to admin-only visibility** — show the banner only if an admin flag/cookie is set.

**Recommended: Option 1 (remove entirely).** The banner provides no actionable information to end users. If semantic search is down, keyword results still work. Admin can check system health via the pipeline dashboard or health endpoint. Keep `fallback_used` in the API response (it's useful for monitoring) but don't render it in the UI.

**Files to change:**
- `frontend/src/pages/SearchResults.tsx` — remove the fallback banner JSX block (lines ~99-103)
- `frontend/src/App.css` — remove `.search-fallback-banner` styles (lines 1119-1127) — optional cleanup

## Seams / Task Decomposition

All three items are fully independent — they can be done in any order or in parallel. Natural task split:

1. **T01: Hidden flag + migration + filter** — backend model change, migration, query filter update
2. **T02: Footer cleanup** — frontend-only, version bump + conditional commit display
3. **T03: Remove fallback banner** — frontend-only, remove JSX and CSS

T01 is the only one touching the backend/database. T02 and T03 are purely frontend. All three are small (15-30 min each).

## Verification

- **T01:** `curl` the creators endpoint and confirm no TestCreator in results. Alternatively, check the live site at http://ub01:8096/creators.
- **T02:** Build frontend, check footer renders version without "dev" commit. In Docker: `docker compose build chrysopedia-web` then verify footer.
- **T03:** Build frontend, trigger a search. The banner should not appear even if `fallback_used` is true in the API response. Can verify with browser dev tools by mocking the API response.
- **Full slice:** `npm run build` in frontend with zero errors. Backend tests pass. Docker compose builds cleanly.
