Files
jobtrackingapp/docs/remaster/REBUILD_DECISION.md
T
cesnimda f0f178d77e docs(remaster): full-system audit + rebuild-vs-refactor decision
Deep, code-grounded audit of Job Tracker producing the mission deliverables
under docs/remaster/: system audit, bug report, architecture/data-model/AI/UX
reviews, remaster proposal, migration plan, competitor research, and the gated
REBUILD_DECISION.

Verdict: Incremental Refactor (no full rebuild). Evidence: no Critical defects;
hardened cookie/CSRF auth (token never in JS storage), real SSRF defence,
enforced multi-tenancy via global query filters, decoupled provider-swappable
AI service, 135 backend tests. Debt is localised (god controllers/entity,
missing hot-path indexes, prompt-injection hardening, CRA build debt) and
reachable by in-place, test-guarded refactors.

Also harden .gitignore: exclude agent tooling (.claude/, .bg-shell/, .agent.md)
and restore/broaden the runtime-secrets block (**/keys/, **/backups/, exports,
CV artifacts) so nested DataProtection keys can't be committed accidentally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:04:03 +02:00

6.0 KiB
Raw Blame History

Rebuild Decision — Job Tracker

Companion to: SYSTEM_AUDIT_REPORT.md This is the gate. Per the mission, because the recommendation is Incremental Refactor, work STOPS here pending your approval — no JobTrackerV2 is created.

Executive summary

The audit examined product logic, architecture, data model, AI, security, UX, testing, and deployment against the actual code. The system is a mature, working, production-deployed brownfield with correct architectural bones (hardened cookie/CSRF auth, real SSRF defence, enforced multi-tenancy, a cleanly decoupled AI service, deterministic scoring, 135 backend integration tests + 23 frontend suites, live at jobs.cesnimda.uk). Its problems are concentrated and fixable — god controllers, a god entity, missing indexes, prompt-injection hardening, and CRA build debt — none of which are load-bearing architectural failures. A rebuild would discard substantial correct, tested work to re-solve problems that are already solved, while re-introducing risk. The evidence points clearly to incremental refactor.

Recommendation

Continue with Incremental Refactor

(A full rebuild is not justified.)

Evidence

Against rebuild / for refactor:

  1. No Critical defects. No auth bypass, tenant-isolation break, or SSRF hole in audited paths. Rebuilds are justified when the foundation is unsafe; this foundation is sound.
  2. The hard, easy-to-get-wrong things are already right: SSRF blocklist (post-DNS, all private/CGNAT/ link-local/IPv6-ULA ranges), HttpOnly-cookie + CSRF auth (token never in JS storage — test-asserted), global query-filter tenancy, and a provider-swappable AI boundary that needs zero app changes to move off the weak prod GPU.
  3. Strong test harness. 135 integration tests exercise controllers against a real in-memory DB — they lock behaviour so internals can move safely. A rebuild throws this safety net away.
  4. Debt is localised. 3 god controllers (~6.7k of ~9k controller lines) and 1 god entity account for most of the maintainability pain. Both are reachable by in-place extraction.
  5. Live in production with a working CI/CD pipeline. Discarding a deployed, observable system for a greenfield reset trades known, bounded debt for unknown, unbounded schedule risk.

Acknowledged weaknesses (all refactorable): god classes; JobApplication god entity + denormalised attachment booleans + dual CV source; missing hot-path indexes + load-all analytics + Gmail N+1; prompt injection (capped by human-review); CRA transitive-vuln debt; the unexecuted "use next.js" override.

Estimated effort

Incremental Refactor Full Rebuild
Perf wave (indexes, aggregation, N+1, AI router) ~1 focused pass included, re-derived
Safe refactors (extract services/DTOs) ~12 passes rebuilt from scratch
Data-model evolution (versioning, splits) ~12 passes, additive migrations rebuilt + data migration anyway
Frontend platform (Vite/Next) 1 isolated milestone rebuilt
Re-earning current parity (auth, SSRF, tenancy, 135 tests, deploy) £0 — already have it large, high-risk, re-tested
Total Weeks of bounded, shippable slices Months, mostly to get back to today

Long-term maintenance: after the refactor waves, maintenance cost is lower than a rebuild's because the domain knowledge, tests, and ops are retained and improved rather than reconstructed.

Risks

  • Continuing (current architecture): god classes slow features and invite merge conflicts; unindexed hot paths degrade as data grows; prompt injection can mislead drafts; CRA debt ages. All mitigated by the planned waves.
  • Rebuilding: re-introducing already-solved security bugs; long no-value-delivery window; data migration is required either way; loss of the test harness during transition; opportunity cost.
  • Migration (refactor path): additive migrations with backfill checks + staging dry-run on a MariaDB copy + already-automated backups keep data-loss risk low.
  • User impact: refactor path keeps the app live throughout; rebuild path risks a freeze or a parallel system to maintain.
  • Operational: single-capacity CI runner → keep slices small, one PR at a time (already the practice).

Reuse analysis

Verdict Items
Reuse unchanged Cookie/CSRF auth, SSRF ingestion guard, global query filters, JobCvMatchService/JobPipeline/StageAnalytics/EmailStatusClassifier, AI HTTP boundary, background-service model (single-node), test suites, deploy pipeline, docs from prior phases
Refactor before reuse JobApplicationsController, ProfileCvController, GmailController, JobApplication entity, tools/summarizer prompt construction, CRA build setup
Rewrite attachment-boolean logic → computed; tailored-CV/cover-letter storage → versioned tables; analytics read paths → server-side aggregation
Remove denormalised attachment columns (post-backfill), inline TailoredCvText/CoverLetterText (post-migration), dead Controller/ folder, scratch files (temp_job.json, temp_post_job.py)
Keep out of repo .gsd/, .claude/, keys, backups, exports (all git-ignored — verify .claude is added)

Long-term recommendation

Incrementally remaster. It delivers the best balance of maintainability (retain tests + knowledge), scalability (indexes + service extraction + optional queue), engineering velocity (shippable slices, no freeze), reliability (behaviour-locked by tests, app stays live), and product quality (UX/AI fixes land continuously). Reserve "rebuild" language for the frontend platform only, and only if you choose Next.js for a public SEO product — that is a scoped migration, not a system rebuild.

Gate

➡️ Awaiting your approval. On approval, I proceed with MIGRATION_PLAN.md Wave 1 (the paused Phase 7 performance work) as the first slice. No JobTrackerV2 will be created.