Files
jobtrackingapp/docs/remaster/REMASTER_PROPOSAL.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

89 lines
5.5 KiB
Markdown

# Remaster Proposal — Job Tracker
**Companion to:** [SYSTEM_AUDIT_REPORT.md](SYSTEM_AUDIT_REPORT.md) · **Decision:** [REBUILD_DECISION.md](REBUILD_DECISION.md)
This is an **evolution proposal**, delivered as an incremental remaster of the existing system (the audit
found no justification for a from-scratch rebuild). It reshapes internals and data model while preserving
the working boundaries that already earn their keep.
## 1. The one decision that gates everything: product identity
Answer this first — it changes the roadmap:
- **(A) Personal power-tool** (matches `.gsd` D003). Optimise for one serious job seeker: depth, automation,
no billing/onboarding overhead. Multi-tenant stays a nicety.
- **(B) Multi-tenant SaaS.** Then onboarding, plans/billing, quotas, per-tenant AI cost control, and
abuse-resistance become first-class — and the polling background services need an outbox/queue.
Everything below is written to be true for both, with SaaS-only items flagged **[SaaS]**.
## 2. Architecture redesign (target)
Keep the topology; move logic out of controllers into services.
```
Frontend (Vite+React or Next.js — resolve the override) API (thin controllers → services)
feature-sliced modules JobApplicationService / AnalyticsService
│ CvContextBuilder / GmailImportService
▼ JobPipeline / StageAnalytics (keep)
typed API client (generated from OpenAPI) │
EF Core (SQLite dev / MySQL prod, +indexes)
AI gateway (unchanged HTTP boundary) ──▶ FastAPI: provider router {ollama|gemini|groq}
/summarize local · /cv/* cloud
[SaaS] outbox + queue for reminders/enrichment; per-tenant AI budget guard
```
**Modules/services to extract** (behaviour-preserving, test-guarded):
`JobApplicationService`, `AnalyticsService` (server-side aggregation), `CvContextBuilder`,
`GmailImportService` + `GmailThreadRefresher`, `RuleSettingsCache`. Controllers become thin HTTP adapters.
## 3. Data model redesign
Per [DATA_MODEL_REVIEW.md](DATA_MODEL_REVIEW.md):
- **Jobs:** split `JobApplication` (core+workflow) from a 1:1 `JobImportContent` (description/translation/
summary/tags) so hot list queries don't drag import blobs.
- **CVs (versioned):** introduce `CvVersion(id, ownerUserId, sourceProfileId, jobApplicationId?, label,
content, structuredJson, createdAt)` — immutable snapshots. Deprecate inline `TailoredCvText`; keep
`StructuredCvProfile` as the source of truth for factuality checks.
- **Cover letters:** promote to first-class `CoverLetter(id, jobApplicationId, source{manual|upload|ai},
content, createdAt)` instead of the inline `CoverLetterText` string, enabling versions/history.
- **Timeline events:** keep `JobEvent`; ensure it and `Correspondence` render as one interleaved timeline.
- **AI outputs:** persist as versioned artifacts with provenance (provider, model, prompt hash) for audit
and regeneration — supports the factuality-check feature.
- **Attachments:** drop the drift-prone booleans; compute from the collection.
- **Indexes:** add the five hot-path indexes **first** (highest ROI, lowest risk).
## 4. UX redesign
- **Import:** explicit partial-parse state ("we read X, confirm/fill the rest"); never a silent dead end.
- **Match score:** show matched vs missing keywords; relabel as "keyword coverage".
- **CV flow:** dedicated application-answer field (retire the notes-block workaround); version picker per job.
- **CV review:** surface "AI added: <claims not in your profile> — confirm" (factuality guardrail).
- **Dashboard/timeline:** one chronological story (events + emails); keep time-in-stage + funnel.
## 5. AI strategy
- Keep **deterministic** scoring; add synonym normalisation + honest labelling.
- Keep **generative** work behind the HTTP gateway; add a **provider router** (`AI_PROVIDER`) so prod
offloads the GTX 1060 to Gemini/Groq while dev uses local Ollama on the 3080.
- Harden prompts: delimit untrusted inputs, add a post-gen factuality diff against `StructuredCvProfile`.
- Strict separation: deterministic = anything the user trusts as a fact/number; generative = drafts only.
## 6. Email + automation redesign
- Reminders: keep, but make **event-driven** where possible (status change → schedule follow-up) instead of
pure polling; **[SaaS]** move to an outbox + worker.
- Gmail: keep the job-scoped linked-thread refresh (D007/D008 works); add health/telemetry.
- Optional inbound parsing stays opt-in and deterministic (`EmailStatusClassifier`) — no auto-send (D002).
## 7. Optional features
**Must-have**
- Hot-path indexes; god-controller extraction; attachment-boolean fix; tailored-CV single source.
- Provider router for AI (unblocks prod on the 1060).
- Import partial-parse UX; match-score gap breakdown.
**Nice-to-have**
- Real `CvVersion` + `CoverLetter` history; factuality guardrail; funnel drill-downs; scraper health board.
- Frontend migration off CRA (Vite easiest; Next.js if SEO/SSR for a public product).
**Experimental**
- Embedding-based advisory match second-opinion; auto-suggested follow-up timing from response-rate data;
**[SaaS]** per-tenant AI budget + BYO-key.
## 8. Sequencing
See [MIGRATION_PLAN.md](MIGRATION_PLAN.md). Order: indexes → controller extraction → data-model splits →
AI provider router + hardening → UX polish → (decide) frontend migration.