# Legacy and unused-code inventory Reviewed 2026-09-14. This inventory records source evidence, not production usage telemetry. A command with no repository caller may still be run manually or from an external scheduler. Historical specs and prototypes are not runtime imports. ## Method and scope Searched backend imports, tests, CLI scripts, Airflow DAGs, Meltano configuration, Gitea workflows, Dockerfiles and documentation. For frontend candidates, inspected TypeScript imports, re-exports, literal dynamic imports and `require` calls, resolving relative and `@/` paths while excluding tests, dependencies and build output. Checked candidates again with text searches including tests. Next.js route files, generated Payload import-map entries and plugin discovery are entry points even without ordinary imports. This is why a zero-import count alone is not sufficient grounds for deletion. Computed imports and external operators are outside this static audit. ## Removed in this cleanup These names are recorded for Git-history lookup; they are no longer file links. | Removed path or symbol | Evidence and replacement | |---|---| | `backend/migration.py` | Imported `School` and `SchoolResult`, which no longer exist in `backend/models.py`. Only the legacy CSV CLI imported it. Current tables are built by dbt. | | `backend/version.py` | Only the legacy importer consumed `SCHEMA_VERSION`. FastAPI lifespan does not perform version-triggered imports. This is unrelated to active Payload migrations. | | `scripts/migrate_csv_to_db.py` | Imported removed `init_db`/`set_db_schema_version` helpers and the obsolete models indirectly. No runtime, DAG or workflow calls it. Use the managed pipeline for current marts. | | `scripts/geocode_schools.py` | Imported the removed `School` ORM model. No pipeline/workflow calls it. Coordinates now come from GIAS/PostGIS; a separate mart-aware manual utility remains under `pipeline/scripts/`. | | `backend.data_loader.haversine_distance` | No callers. Search uses its inline vectorised NumPy calculation. | | `nextjs-app/lib/api.ts: fetcher` | No callers; SWR is not installed. Application fetches use the named API wrappers. | | `nextjs-app/lib/api.ts: kmToMiles` | No callers. `calculateDistance` remains because `CutoffMapPanel` uses it. | The removed command files could not import successfully against the current backend. This cleanup does not run replacements, migrate data or modify databases. Their previous implementations remain recoverable from Git history. ## Unused candidates retained for a separate cleanup | Candidate | Evidence | Recommended next step | |---|---|---| | `nextjs-app/components/LoadingSkeleton.tsx` and its CSS | No application or test imports found. | Remove together after confirming no planned use. | | `nextjs-app/components/Pagination.tsx` and its CSS | No application or test imports found; HomeView implements load-more behaviour. | Remove as a pair if numbered pagination will not return. | | `nextjs-app/components/SchoolCard.tsx` and its CSS | Imported by its own tests, not application code. HomeView uses SchoolRow/SecondarySchoolRow. | Decide whether to retire the card design; if removed, remove its dedicated tests as well. Passing tests do not establish runtime use. | | `backend/database.py: get_db`, `get_db_session` | No remaining callers after removing the importer. Current code creates SessionLocal directly. | Either adopt these helpers during session-lifecycle cleanup or remove them; do not rewrite active sessions in a documentation change. | | `backend/schemas.py: COLUMN_MAPPINGS`, `NULL_VALUES`, `LA_CODE_TO_NAME` | No remaining Python consumers found after importer removal. Other constants in this module are active. | Remove individual constants after checking external data utilities; retain the module. | | `backend/app.py: result_filters` keys `school_types`, `phases`, `genders`, `admissions_policies` | Since 2026-10-02 FilterBar offers these from `/api/filters`, because options scoped to the results left only the chosen value on offer. Only `local_authorities` is still read. | Stop computing the four keys in a focused API change; keep `local_authorities`. | | `backend/config.py: data_dir`, `max_page_size`, `rate_limit_burst` | No active consumers found. `default_page_size` appears only in a branch that expects None, although the route supplies a concrete default. | Reconcile settings with route validation in a focused API change. | ## Legacy/manual paths requiring operational verification | Path | Status and reason to retain for now | |---|---| | FastAPI `/`, `/compare`, `/rankings`, `/favicon.svg`, `/robots.txt`, and conditional `/static` | Old frontend-serving routes reference a `frontend/` directory absent from the checkout and backend image. Next.js owns these public surfaces. Removal changes externally callable routes, so first check proxy/operator usage and define replacement responses. | | `scripts/fetch_real_data.py`, `scripts/download_data.py` | Historical standalone CSV utilities. The fetch script targets Wandsworth/Merton; neither is wired into the managed pipeline. Marked historical, retained pending confirmation of manual use. | | `pipeline/scripts/geocode_postcodes.py` | Mart-aware postcode fallback, not called by the current DAGs. Do not confuse it with the removed legacy ORM geocoder. Verify the target schema before manual use. | | `docker-compose.yml` | Uses unpublished `:latest` release tags and lacks frontend Payload DB/secret/media configuration. Retained as an old development topology, not recommended onboarding. | | `nextjs-app/docker-compose.yml` | Standalone legacy recipe with old backend port assumptions and no CMS persistence setup. Retained until its consumers are checked. | | `MIGRATION_SUMMARY.md`, `docs/superpowers/`, `mockups/` | Historical designs and prototypes. Retain as history; do not follow as current deployment instructions. | | `scripts/sql/drop_fact_parent_view.sql` | One-off maintenance SQL. Not an application entry point; repository call-site searches cannot establish whether it is still needed operationally. | ## Active code that can look obsolete - `backend/data_loader.py` older-mart query fallbacks are covered by backend tests and support databases at different migration stages. Remove only after verifying the deployed schemas in every supported environment. - `backend/gias_codes.py` and `pipeline/scripts/gias_codes.py` are intentionally generated copies for separate runtime images. Their parity is tested. - `nextjs-app/migrations/`, `payload-types.ts` and the Payload import map are active CMS artifacts, not remnants of the removed school importer. - `get_available_years`, `get_available_local_authorities` and `get_schools_count` in `data_loader.py` are called through `get_data_info`, which serves the backend data-info endpoint. They are not dead functions. - `get_supplementary_data` is an intentional single-school wrapper around the batch implementation. - `pipeline/transform` models named `legacy` can be active data sources: annual DAG selectors explicitly include legacy KS2/KS4 lineage. Names alone do not establish obsolescence. ## Suggested next passes 1. Decide the fate of the three unused UI components and remove paired assets/tests. 2. Consolidate backend session usage and remove abandoned settings/constants. 3. Verify external consumers, then retire static-serving API routes and old compose recipes. 4. Audit manual data utilities with pipeline operators before deleting them. 5. Revisit compatibility fallbacks only after documenting supported schema versions. Validation for this cleanup should include frontend typechecking/tests, Python syntax checks, reference searches and documentation link checks. Live database, external scheduler and deployed route usage require separate integration evidence.