`backend/migration.py` and `scripts/migrate_csv_to_db.py` import `School`, `SchoolResult`, `init_db` and `set_db_schema_version` — names that no longer exist. `scripts/geocode_schools.py` imports the same removed ORM model. None of the three can be imported against the current backend, so they were not dormant utilities anyone could fall back on; they were files that would fail on the first line. `backend/version.py` existed only to hand `SCHEMA_VERSION` to that importer, and the FastAPI lifespan performs no version-triggered import. Three symbols go with them, each confirmed to have no caller: the unvectorised `haversine_distance`, superseded by the inline NumPy calculation in search; `fetcher`, an SWR helper for a dependency this project does not install; and `kmToMiles`. `calculateDistance` stays — CutoffMapPanel uses it. Two comments pointed at `migrate_csv_to_db.py --drop` to explain why Payload owns its own schema. The reason survives the script: blog content must stay clear of the school marts and Airflow's metadata. Reworded rather than deleted, so the constraint keeps its justification. docs/LEGACY_CODE.md records what was removed and where to find it in history. It also records what was deliberately *not* removed, which is the more useful half: unused UI components awaiting a design decision, manual data utilities whose operators a repository search cannot see, and fallbacks that look obsolete but are load-bearing — `data_loader.py`'s older-mart branches, the generated GIAS dictionary copies, and the `legacy`-named dbt models that annual DAG selectors explicitly include. A zero-import count is evidence, not a verdict. The scripts that fetch DfE CSVs are marked historical and kept, pending confirmation that nobody runs them by hand. Checked: 190 backend tests, 429 frontend tests, `tsc --noEmit` clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016y2J6bs8gbuSJbH18w7Tan
7.3 KiB
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/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.pyolder-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.pyandpipeline/scripts/gias_codes.pyare intentionally generated copies for separate runtime images. Their parity is tested.nextjs-app/migrations/,payload-types.tsand the Payload import map are active CMS artifacts, not remnants of the removed school importer.get_available_years,get_available_local_authoritiesandget_schools_countindata_loader.pyare called throughget_data_info, which serves the backend data-info endpoint. They are not dead functions.get_supplementary_datais an intentional single-school wrapper around the batch implementation.pipeline/transformmodels namedlegacycan be active data sources: annual DAG selectors explicitly include legacy KS2/KS4 lineage. Names alone do not establish obsolescence.
Suggested next passes
- Decide the fate of the three unused UI components and remove paired assets/tests.
- Consolidate backend session usage and remove abandoned settings/constants.
- Verify external consumers, then retire static-serving API routes and old compose recipes.
- Audit manual data utilities with pipeline operators before deleting them.
- 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.