# Migration / Remaster Plan — Job Tracker **Companion to:** [REMASTER_PROPOSAL.md](REMASTER_PROPOSAL.md) · **Decision:** [REBUILD_DECISION.md](REBUILD_DECISION.md) Strategy: **incremental, test-guarded, feature-branch per unit** (matches `.gsd` D017 slice discipline and the project's no-direct-main / conventional-commit rule). The 135 backend integration tests + 23 frontend suites are the safety net that makes internal change low-risk. **No big-bang.** ## Guardrails per slice 1. Branch off `main`; conventional commit; no direct main pushes; no auto-merge. 2. `dotnet build -c Release` + `dotnet test JobTrackerApi.Tests` green **before** commit. 3. Frontend: full Jest suite green. 4. One PR per slice → one CI run on the Pi (single-capacity runner). 5. Behaviour preserved; add a targeted test if a slice exposes a coverage gap. ## Wave 1 — Performance (lowest risk, highest ROI) — *this was the paused Phase 7 work* - **P1. Hot-path indexes** (`Data/JobTrackerContext.cs` + one migration): `IsDeleted`, `(IsDeleted,Status)`, `FollowUpAt`, `Correspondence.JobApplicationId`, `JobEvent.JobApplicationId`. SQLite+MySQL safe. - **P2. Server-side aggregation** for `GetStats`/`GetAnalyticsOverview` (no full-table `ToListAsync`). - **P3. Gmail N+1 batch fixes** (:646, :701, :893) + `FirstOrDefaultAsync` for review decisions. - **P4. `RuleSettings` cache** in `IMemoryCache` (short TTL, per user). - **AI provider router** in `app.py` (`AI_PROVIDER={ollama|gemini|groq}`) + `/health` reports provider; default stays `ollama` (keyless). Prod `.env` sets `AI_PROVIDER=gemini` + rotated key → offloads the 1060. ## Wave 2 — Safe refactors (behaviour-preserving) - **R1. Extract services** from `JobApplicationsController`: `AnalyticsService`, `JobStatsService`, `CvContextBuilder`. Controller shrinks to a thin adapter. - **R2. Extract** `GmailImportService` + `GmailThreadRefresher` from `GmailController`. - **R3. DTO extraction** for `JobApplicationsController`/`ProfileCvController`/`GmailController`. - New files under `Controllers/`/`Services/` so the `JobTrackerBackend` glob picks them up; no `Program.cs` DI churn beyond registering the new services. ## Wave 3 — Data-model evolution (additive migrations + backfill) - **D1. Attachment booleans → computed.** Migration + backfill verification test; then drop stored columns. - **D2. Single tailored-CV source.** Migrate `TailoredCvText` → `TailoredCvDraft`; deprecate the string. - **D3. Split `JobImportContent`** 1:1 off `JobApplication`. - **D4. `CvVersion` + `CoverLetter`** first-class tables (enables real versioning promised by the product). Each is a reversible EF migration; run against a SQLite dev DB and a MariaDB staging copy before prod. ## Wave 4 — AI hardening + UX - **A1.** Prompt-injection delimiters + input normalisation; factuality diff vs `StructuredCvProfile`. - **A2.** Match-score synonym map + relabel; matched/missing breakdown in the UI. - **U1.** Import partial-parse state; dedicated application-answer field; AI-fabrication confirm UI. ## Wave 5 — Frontend platform (decide first) Resolve the `.gsd` "use next.js" override deliberately: - **Least churn:** CRA → **Vite** (drops most transitive-vuln debt, keeps React/MUI, fast). - **If public/SEO product:** **Next.js** (honours the override; SSR/routing/metadata) — larger effort. Do this as its own milestone, not coupled to backend work. ## Risk assessment | Risk | Likelihood | Mitigation | |---|---|---| | Migration data loss (Wave 3) | Low | additive + backfill + staging dry-run on MariaDB copy + backups (already automated) | | Behaviour regression in extraction | Low | 135 integration tests lock the API contract | | Single-runner CI bottleneck | Medium | one PR per slice; keep slices small | | Provider-router auth leak | Low | key from env only; never logged/committed; rotate the pasted key | | Frontend migration churn | Medium | isolate as its own milestone; feature-flag if needed | ## Preserve vs discard - **Preserve unchanged:** auth (cookie+CSRF), SSRF ingestion guard, global query filters, deterministic services, AI HTTP boundary, background-service model (single-node), test suites, deploy pipeline. - **Refactor before reuse:** the three god controllers, `JobApplication` entity, prompt construction. - **Discard:** attachment boolean columns (after backfill), inline `TailoredCvText`/`CoverLetterText` strings (after migration), scraper reliance as a *guarantee* (keep as best-effort). - **`.gsd` logic:** treat as historical design intent (already mostly realised); resolve the two open items (next.js override, notes-block workaround). The `.gsd` folder is **git-ignored** and stays out of the repo.