Files
jobtrackingapp/docs/cv-redesign/research/03-jobjakt-gap-analysis.md
T

93 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Jobjakt source inventory and gap analysis
## Evidence boundary
Repository inspected read-only at `b2a9fd68b081a8cc1701b1c58eaea7e1070274af` on `codex/ui-redesign-phase4`. Working tree was clean at the initial check. Statements marked **Verified — source** describe inspected code, not exercised application behavior. Jobjakt runtime usability, test results, production schema and output fidelity are **Not Tested in this investigation**.
All paths below are relative to `E:/Storage/Projects/Active/Job tracker`. No code, database, dependencies, migrations or deployment files were changed.
## Existing architecture: preserve this foundation
| Area | Verified — source | Evidence |
|---|---|---|
| Routing | CV library/editor `/career/builder` and `/career/builder/:id`; public CV `/cv/:slug` | `job-tracker-ui/src/App.tsx:436`, `:437`, `:523` |
| Editor ownership | Variant, themes and master outline loaded by existing editor; Content/Template/Customize/AI Tools/History tabs | `job-tracker-ui/src/views/CvBuilderEditor.tsx:59`, `:110`, `:605` |
| CV autosave | 800ms serialized optimistic save with expected version; blank names prevent save; revision conflict stops automatic writes | `CvBuilderEditor.tsx:187–235` |
| Recovery | Retry/status, unsaved-settings JSON download, reload saved version, route and unload protection | `CvBuilderEditor.tsx:341–389`, `:709–723` |
| Undo/redo | Settings snapshots, normal-update cap 60; new update clears redo; names outside settings history | `CvBuilderEditor.tsx:301–339` |
| Content editing | Section visibility/name/order, source overrides, custom presets/entries, hide/reorder/reset to source | `CvBuilderEditor.tsx:965–1045`, `:1243–1368`; `job-tracker-ui/src/cvBuilder.ts:3–79` |
| Reordering | Native drag/drop plus explicit up/down controls | `job-tracker-ui/src/hooks/useDragReorder.ts:3–51`; `CvBuilderEditor.tsx:1203`, `:1341` |
| Preview | 300ms API preview, stale-request suppression, last-good output retained, retry, page count/overflow notices | `CvBuilderEditor.tsx:163–185`, `:650–676` |
| Physical page contract | Font/image readiness and renderer print CSS drive browser fragmentation; fit-to-width on resize | `job-tracker-ui/src/cvPreview.ts:3–49`; `CvBuilderEditor.tsx:513–529` |
| Responsive editor | Sticky split panes on desktop, Edit/Preview one-pane mode below 900px | `CvBuilderEditor.tsx:57`, `:590–597`, `:632–676` |
| Template gallery | ATS-first filter, selected template retained, responsive cards, availability/Pro handling, keyboard selection | `job-tracker-ui/src/components/CvTemplateGallery.tsx:31–68` |
| Thumbnail limitation | Gallery uses schematic CSS illustrations, not actual rendered template output; sample-preview API already exists | `CvTemplateThumbnail.tsx:6–30`; `cvBuilder.ts:272` |
| Design controls | Capability-filtered visual settings, null-as-default semantics, confirm before resetting visual overrides | `components/cv/CvCustomizeTab.tsx:33–124`; `cvBuilder.ts:193–217` |
| CV data models | CareerProfile relational core plus JSON projection; variant is a lens over current master with stable entry keys | `JobTrackerApi/Models/CareerProfile.cs:12–33`; `Services/CareerProfileService.cs:51–101`; `Models/CvVariantSettings.cs:8–97` |
| Render/export | Unsaved preview and saved PDF share CV renderer; export saves first; safe inline text handling | `Controllers/CvVariantController.cs:210–239`; `Services/ThemedCvRenderer.cs:203–218`; `CvBuilderEditor.tsx:418–434` |
| Concurrency/history | CV expected version missing→428, conflict→409; version token; restore creates a new revision | `CvVariantController.cs:129–154`, `:191–208`; `Services/CvVariantService.cs:111–176`; `Data/JobTrackerContext.cs:483–485` |
| Variant-history meaning | Historic settings re-resolve current master facts; historical settings do not freeze historic career content | `CvVariantService.cs:179–197`, `:224–232` |
| Sharing | Owned variants/history; public slug checked explicitly; unpublish/re-publish rotates link; public PDF rate-limited | `Data/JobTrackerContext.cs:476–506`; `Controllers/PublicCvController.cs:28–56` |
| AI | Pro eligibility, consent/routing boundary, grounded proposals, revision/fingerprint-bound apply token | `Services/CvAiSuggestionService.cs:31–135`, `:218–245`; `Services/AiPrivacyPolicy.cs:23–79` |
| Cover-letter workspace | Job-owned explicit Save/Discard, dirty protection, starter text, version restore, AI compare/Apply/Reject | `components/ApplicationAssets.tsx:484–678`, `:699–817`; `views/ApplicationWorkspacePage.tsx:91–125`, `:262` |
| Current text control | Labelled MUI textarea with Markdown-marker toolbar and selection restoration; not WYSIWYG | `components/RichTextField.tsx:12–77` |
| Letter API/storage | Text, CurrentVersion, history and AI count; GET/PUT/restore; identical trimmed save avoids a new version | `JobTrackerApi/Controllers/ApplicationAssetsController.cs:17–86`; `Services/ApplicationAssetsService.cs:38–54`, `:240–316`; `job-tracker-ui/src/applicationWorkspace.ts:245–301` |
| Documents index | Letters link back to application subsection; index includes existing resources, not another editing owner | `views/DocumentsPage.tsx:39–41`; `JobTrackerApi.Tests/DocumentsControllerTests.cs:56`, `:308` |
| Frozen application evidence | Submitted package copies rendered CV HTML, letter text and attachment evidence | `JobTrackerApi/Models/SubmittedApplicationPackage.cs:3–20`; `Services/SubmittedApplicationPackageService.cs:59–104` |
| Localization/theme | English/Bokmål, legacy Norwegian normalization, fallback/interpolation, current Archivo/MUI palette and density | `src/i18n/I18nProvider.tsx:22–67`; `src/i18n/translations.ts:1`; `src/theme.ts:9`, `:113–183`, `:217–224` |
Paths in shortened rows retain the prefix from their full path earlier in the table: editor/frontend paths are under `job-tracker-ui/src`; C# controllers/models/services/data are under `JobTrackerApi`.
## Capability comparison
| FlowCV observation | Jobjakt position from source | Actual gap / recommendation | Priority |
|---|---|---|---|
| Document cards and creation | Library already lists/creates/renames/duplicates/deletes CVs | Runtime qualification, not a replacement dashboard | Preserve |
| Content outline and typed sections | Existing source-linked and custom section editor | Clarify master-source vs document-only changes; do not duplicate career CRUD | P1 UX |
| Autosave | Existing revision-aware autosave and visible states | Preserve; stronger evidence of failure handling in source than observed FlowCV feedback | Preserve |
| Undo/redo | Existing bounded settings history | Explain names/history scope; do not assume body and settings histories are interchangeable | P1 copy |
| Reordering | Existing native drag and explicit up/down | Qualify touch/keyboard; no new drag dependency justified | Preserve/verify |
| Template selection | Existing capability-aware gallery + shared preview API | Add real candidate preview before apply; schematic thumbnails can remain fast discovery aids | P1 |
| Typography/layout controls | Broad existing normalized settings | Preserve supported-setting filters and null defaults; avoid exposing unsupported knobs | Preserve |
| Preview and pagination | Existing physical renderer/fragmentation/fit-to-width | Manual zoom not found in inspected editor; add only if zoom research supports it | P2 optional |
| AI | Existing grounded proposal, Apply and consent boundary | Preserve; paid FlowCV outputs were inaccessible and are not a benchmark | Preserve |
| PDF export | Existing save-before-export and error states | Qualify newest-draft parity and long document recovery | Preserve/verify |
| Duplication/versions | Existing duplicate/history/restore, unlike inaccessible FlowCV duplication | Retain; clearly distinguish revision history from frozen application evidence | P1 copy |
| Letter content | Existing job-linked draft/history/AI | Add document preview/export around this owner, not a separate unsynchronized letter system | P1–P2 |
| Resume-data reuse for letters | Attached CV and application context exist, but no explicit sender-copy designer found | Optional core-contact snapshot with explicit copy scope; preserve master facts | P2 |
| Matching letter design | No corresponding frontend designer or generated letter PDF endpoint found in bounded searches | New letter rendering/settings contract is required | P2–P3 |
| Generic letter data export | CSV/JSON/account ZIP/backup already include letter data; attachment downloads exist | Do not describe letters as having no export at all | Preserve |
## Material implementation constraints and risks
### Letter revision coverage is incomplete
**Verified — source:** three production paths directly write `CoverLetterText` without using versioned letter persistence:
- Job create: `JobTrackerApi/Controllers/JobApplicationsController.cs:783`, saved at `:817`.
- Generic job update: `:878`, saved at `:929`; DTO at `Controllers/JobApplicationDtos.cs:113–137`.
- Application draft update: `:1558`, saved at `:1578`; DTO at `JobApplicationDtos.cs:221–226`.
The dedicated letter endpoint uses `ApplicationAssetsService.SaveCoverLetterAsync`; restore calls that service too. Its save request has no expected revision, versions use `max+1`, and the history index is non-unique (`ApplicationAssetsController.cs:22`; `ApplicationAssetsService.cs:310–316`; `JobTrackerContext.cs:570–571`).
**Inferred risk:** concurrent or legacy writes can overwrite letter text without corresponding history/version conflict protection. A race was not reproduced. Any letter autosave or persistent design phase must account for every writer and preserve their different null/clear semantics. Merely adding a revision check in a new UI would be incomplete.
### Preview, current documents and frozen records differ
- CV PDF renders saved state; preserve the existing save-before-export behavior.
- CV settings history is not a historic master-profile snapshot.
- Frozen submitted packages already preserve CV HTML and letter text. If designed letter output becomes evidence, capture its rendered artifact too; old text-only snapshots must remain readable.
- A submitted-package capture does not establish delivery to an employer. Copy must not imply it does.
### Existing exports and pipelines
**Verified — source:** `ExportController.cs:57,106,128–136` includes letter text/jobs in CSV/JSON; `AccountDataExportService.cs:189,208,213` includes versions/snapshots; encrypted backups serialize jobs (`BackupController.cs:34–42`). Downloading existing letter attachments is already supported.
**Bounded negative finding:** controller/service searches found no generated standalone cover-letter HTML/PDF/DOCX endpoint; current dedicated surface is GET/PUT/restore. DOCX references found import/attachment support, not generated CV DOCX export. This does not prove deployed functionality outside the checkout is absent.
The separate structured tailored-CV pipeline (`Models/TailoredCvDraft.cs:3–21`; `Controllers/JobApplicationsController.cs:1389–1535`) must not be silently merged into variant ownership.
### Dependencies and platform
The package declares React 19, MUI 7, Next 16, React Router 7, Axios, Jest/Testing Library, Playwright and axe (`job-tracker-ui/package.json:5–38`, `:59–72`). These are declared ranges, not a fresh dependency installation audit. No new dependency is required for the recommended initial work. Preserve current nullable C#/EF, owner scoping, safe HTML, AI policy and document rendering boundaries.