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>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user