feat(career): CV builder backend — data-driven theme engine + variant model
CI and Deploy / test (push) Failing after 1m51s
CI and Deploy / deploy (push) Has been skipped

Phase 4 foundation. A CvVariant is a lens over the master CareerProfile
(section order/visibility, per-item overrides keyed by ItemKey, theme +
builder settings) — it references career data, never duplicates it. One
renderer (ThemedCvRenderer) draws every theme; a theme is pure data
(CvThemeCatalog, 8 professional themes), so adding a theme needs no renderer
change. Autosave version history + non-destructive restore, public CV via
/api/public-cv/{slug} (anonymous, noindex, filter-bypassing owner load), and
an AI-assist endpoint reusing the existing provider abstraction (suggestions
only, never auto-applied).

- Models: CvVariant/CvVariantVersion, CvVariantSettings, CvTheme + catalog
- Services: CvVariantResolver (profile+lens -> render model), ThemedCvRenderer,
  CvVariantService, CareerProfileService.LoadStructuredForOwnerAsync (public)
- API: CvVariantController (/api/cv), PublicCvController (/api/public-cv)
- Migration AddCvVariants (2 self-contained tables; verified applied on the
  running container), 16 tests (resolver/renderer/service), 296 backend green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-07-18 09:52:58 +02:00
parent 707d8c59d2
commit a3e18e4b44
15 changed files with 3842 additions and 0 deletions
+2
View File
@@ -36,8 +36,10 @@ builder.Services.AddScoped<IAppEmailSender, SmtpEmailSender>();
builder.Services.AddSingleton<ICvProcessingQueue, CvProcessingQueue>();
builder.Services.AddTransient<ProfileCvController>();
builder.Services.AddSingleton<ICvTemplateRenderer, CvTemplateRenderer>();
builder.Services.AddSingleton<IThemedCvRenderer, ThemedCvRenderer>();
builder.Services.AddSingleton<ICvPdfExporter, PlaywrightCvPdfExporter>();
builder.Services.AddScoped<ICareerProfileService, CareerProfileService>();
builder.Services.AddScoped<ICvVariantService, CvVariantService>();
builder.Services.AddSingleton<AppPaths>();
builder.Services.AddSingleton<IStartupReadiness, StartupReadiness>();