diff --git a/docs/architecture/career-profile-model.md b/docs/architecture/career-profile-model.md index 961faaa..317506a 100644 --- a/docs/architecture/career-profile-model.md +++ b/docs/architecture/career-profile-model.md @@ -7,6 +7,27 @@ > Companion to `docs/architecture/current.md` §4a (profile/career separation) and > `docs/decisions/ADR-002-job-application-model.md`. Verified against code on 2026-07-18. +> ## Implementation status (2026-07-18) — SHIPPED +> +> The model below is implemented on `main` and verified against the live database: +> - **Entities** (`Models/CareerEntities.cs`): `CareerExperience`, `CareerEducation`, `CareerSkill`, +> `CareerProject`, `CareerCertification`, `CareerLanguage` — relational children of `CareerProfile`; +> long tail in `CareerProfile.LongTailJson`. Migration `AddCareerProfileRelationalChildren` +> (applied cleanly on the real dev DB and the running container). +> - **Projection** (`CareerProfileService` + `CareerProfileMapper`): relational is the source of +> truth; `SaveVersionAsync` syncs children + long tail; `LoadStructuredAsync` reads relationally +> with lazy backfill from the blob; the `ProfileCvStructureJson` blob is kept as the derived +> projection. +> - **API** (`CareerProfileController`, `/api/career/profile`): GET/PUT profile, GET completeness, +> GET versions, POST version restore. Validation via `CareerProfileValidator` (abuse limits). +> - **Frontend** (`/career`): reads/writes the relational API, profile-completeness overview, +> version-history restore. +> - **Tests**: 23 career-focused backend tests (round-trip, item-key stability, replace-all, +> backfill, completeness, validation, versioning/restore) + frontend save/completeness tests. +> +> Not yet done (later): promote the long tail to relational if needed; a full section-by-section UX +> redesign of the editor; the eventual removal of the derived blob once every reader flips. + --- ## 1. Where we start (F1, on `main`) diff --git a/docs/implementation-roadmap.md b/docs/implementation-roadmap.md index 56c3379..eba4e1c 100644 --- a/docs/implementation-roadmap.md +++ b/docs/implementation-roadmap.md @@ -72,9 +72,17 @@ Goal: the guide's "users should always understand where they are, what they can Goal: one professional source of truth that can actually feed outputs. +> **Foundation SHIPPED 2026-07-18** (commits `9c8644e`…`a1dd447`). The relational master career +> profile is built, tested (23 backend + frontend tests), migrated (verified on the live DB), wired +> to `/career`, with completeness overview + version-history restore. See +> `docs/architecture/career-profile-model.md` (Implementation status). Tasks 3.1, 3.3, 3.4 and the +> versioning/validation goals are delivered. Remaining below: 3.2 (long-tail-as-relational, deferred +> — currently JSON), 3.5 (CV variants — Phase 4), 3.6 (retention), plus a full section-by-section UX +> redesign of the editor (polish; the functional workspace exists). + | # | Task | Priority | Difficulty | Dependencies | Expected value | |---|---|---|---|---|---| -| 3.1 | **Model Experience/Education/Skills/Projects relationally**; keep the long tail (awards, publications, organisations, references, custom sections) as a JSON blob. **Decided 2026-07-17** — no longer an open question. | **P1** | **L** | 1.9 | Buys queryable skills (needed for real matching + keyword gaps), section-level history, and concurrent-edit safety. Hybrid avoids a full rewrite of `StructuredCvProfile`. **Check task 1.9 first** — orphan `CareerProfiles`/`CvVersions` tables suggest this was attempted before. | +| 3.1 | ✅ **DONE** — Experience/Education/Skills/Projects/Certifications/Languages are relational children of `CareerProfile`; long tail is JSON. Projection service keeps the blob as a derived read-model; lazy backfill from existing data. | **P1** | **L** | 1.9 | Delivered. Queryable structured career data is now the source of truth; the blob is derived. | | 3.2 | **Add the missing profile sections** — Awards, Publications, Organisations, References | **P1** | **S** | 3.1 | The guide names them; `StructuredCvProfile` has no home for them beyond generic `OtherSections`. These are the blob half of 3.1. | | 3.3 | **Real Career Workspace page** — replace the 36-line tab facade | **P1** | **M** | 2.1, 2.2 | Currently a wrapper around `ProfilePage`. | | 3.4 | **Separate Career Profile from Master CV** | **P1** | **M** | 3.1 | The glossary is explicit — "The career profile is NOT a CV"; Master CV is a *generated representation*. Code has one blob. Getting this wrong makes Phase 4 impossible. |