feat: complete release readiness work

- consolidate API ownership and remove dead vendor code

- add Stripe billing, learning paths, and public CV hardening

- add migration, recovery, security, audit, and browser gates
This commit is contained in:
cesnimda
2026-07-31 16:54:16 +02:00
parent a23c3dfc97
commit ce76046a29
1634 changed files with 6889 additions and 135429 deletions
@@ -567,9 +567,6 @@ Canonical profile:
{
lastMsg.TryGetValue(j.Id, out var lm);
var d = RulesEngine.Evaluate(settings, j, now, lm);
// Use persisted short summary when available to avoid repeated model calls.
var shortSummary = j.ShortSummary;
var summary = shortSummary; // list endpoints return the short summary only
dtoItems.Add(BuildJobApplicationDto(j, d));
}
@@ -599,8 +596,6 @@ Canonical profile:
{
lastMsg.TryGetValue(j.Id, out var lm);
var d = RulesEngine.Evaluate(settings, j, now, lm);
var shortSummary = j.ShortSummary;
var summary = shortSummary;
dtos.Add(BuildJobApplicationDto(j, d));
}
@@ -745,7 +740,7 @@ Canonical profile:
}
[HttpPost]
public async Task<ActionResult<JobApplication>> Create([FromBody] CreateJobApplicationRequest request, CancellationToken cancellationToken)
public async Task<ActionResult<JobApplicationDto>> Create([FromBody] CreateJobApplicationRequest request, CancellationToken cancellationToken)
{
var userId = CurrentUserId;
var title = (request.JobTitle ?? "").Trim();
@@ -825,7 +820,9 @@ Canonical profile:
.Include(j => j.Company)
.FirstAsync(j => j.Id == job.Id, cancellationToken);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
var followUp = RulesEngine.Evaluate(settings, created, DateTime.Now, lastMessageAt: null);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, BuildJobApplicationDto(created, followUp));
}
[HttpPut("{id:int}")]
@@ -1432,6 +1429,8 @@ Canonical profile:
}
var result = _matchService.Evaluate(job.JobTitle, jobText, cvSections);
var learningRecommendations = await _checklist.SyncLearningRecommendationsAsync(
userId, id, result.MissingKeywords, cancellationToken);
return Ok(new MatchScoreDto(
Score: result.Score,
@@ -1441,7 +1440,8 @@ Canonical profile:
MatchedKeywords: result.MatchedKeywords.ToList(),
MissingKeywords: result.MissingKeywords.ToList(),
SectionCoverage: result.SectionCoverage.Select(s => new MatchSectionCoverageDto(s.Section, s.Matched, s.Total)).ToList(),
HasEnoughSignal: result.HasEnoughSignal));
HasEnoughSignal: result.HasEnoughSignal,
LearningRecommendations: learningRecommendations));
}
[HttpGet("{id:int}/candidate-fit")]