Keep the cache win (no base-image nuke); back to the legacy builder which the job
context supports. BuildKit needs buildx installed in the runner before it can be used.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
DOCKER_BUILDKIT=1 (explicit) so the restore layer is cached across builds; drop the
explicit 'docker builder prune' (it was wiping that cache) and rely on BuildKit's own
GC + 86GB headroom. Cleanup keeps dangling-image removal only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stop wiping the layer cache + base images after every build (the host has 86GB free).
Keep base images (prune dangling only) and ~2 weeks of build cache, so the cache-friendly
Dockerfiles (COPY *.csproj + restore before source) actually benefit -> warm rebuilds skip
restore and base-image pulls.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
main = day-to-day work (no deploy). Merge into staging -> :staging, into
production -> :production; IMAGE_TAG = branch name. Also fixes the checkout to
build the PUSHED commit (git checkout $GITHUB_SHA) instead of always cloning
the default branch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CompactJsonFormatter in both ConfigureJsonSerilog overloads; rename Service->Application,
EnvironmentName->Environment (keep AppVersion). Applies to all myAi services.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The AI prompt now instructs the LLM to derive keywords entirely from the
candidate's CV (seniority level, primary role title, core technologies they
emphasize) rather than from the job description being matched. This ensures
the job-board search keywords used by cv-search-job represent who the
candidate actually is, not a mirror of the job they happened to match against.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. Pass session.Language to MatchJobRequest in cv-search-job so the LLM
uses the correct language-specific prompt for job titles and summaries.
2. Replace hardcoded "Manual job description" with a template-driven label
(email.match.manual-job-label) seeded in English and Romanian, so the
match email subject and Job row reflect the user's language.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
[ENV_NAME] prefix is now only prepended in non-production environments
(Development, Staging, etc.). Production emails get a clean subject line.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
[ENV_NAME] prefix is now only prepended in non-production environments
(Development, Staging, etc.). Production emails get a clean subject line.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds nullable JobSearchSessionId to PageFetchEntity and FetchPageRequest.
cv-search-job passes session.Id on every fetch so all Playwright page
loads for a job search session can be traced back to their session.
Includes index on JobSearchSessionId for efficient lookup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Captures the IP when the user submits the CV match form and stores it on
the token, giving a full audit trail: token holds the match-site IP,
session holds the email link-click IP.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously always stored empty string; now stores the full page text
returned by page-fetcher-api, which is already in scope at save time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Captures client IP at job-search link-click time and threads it through to the session.
Both Email and ClientIpAddress are copied from session to each result row during processing.
Closes#47
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Threads the caller's email and client IP through the match pipeline so
every Results row records who triggered the match and from where.
Closes#45
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
page-fetcher-api always uses Playwright (networkidle by default), so the
per-provider flag that chose between headless and plain HTTP is obsolete.
- Removed from JobProviderEntity, CvSearchDbContext, JobProviderConfig, JobTokenService
- HtmlJobSearcher no longer passes WaitFor (uses page-fetcher-api default)
- EF migration drops the column from cvSearch.JobProviders
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Refit 10.1.6 signing certificate was revoked; upgraded to 11.0.1 in Directory.Packages.props
- cv-matcher-api/Dockerfile and cv-search-job/Dockerfile were missing COPY steps
for page-fetcher-api-models (added in this feature branch)
All 8 images now build cleanly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the spurious Api segment to match the pattern used by all other
models projects: CvMatcher.Models.*, Rag.Models.*, PageFetcher.Models.*.
Updated all consumers: email-api, api, cv-search-job.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes inconsistency where email-api used EmailApi.* and page-fetcher-api
used PageFetcherApi.*, while cv-matcher-api and rag-api use the generic
Api.* namespace. All four API projects now follow the same pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings classes now live in the -models project alongside DTOs and client
interfaces, eliminating the Settings/ folder from both API projects.
- SmtpSettings: email-api/Settings/ → email-api-models/Settings/ (namespace EmailApi.Models.Settings)
- PageFetcherSettings: page-fetcher-api/Settings/ → page-fetcher-api-models/Settings/ (namespace PageFetcher.Models.Settings)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Server-side-only settings (internal config not needed by callers) belong in
the API project itself, not in the models project. PageFetcherSettings
(DefaultWaitFor, TimeoutSeconds, MaxTextChars) mirrors SmtpSettings in
email-api/Settings/ — callers never reference these.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings class now lives in Apis/page-fetcher-api-models/Settings/ with
namespace PageFetcher.Models.Settings, matching how EmailApiSettings is
placed in email-api-models/Settings/.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings classes belong in Settings/ with namespace PageFetcherApi.Settings,
not Services/. Matches the SmtpSettings placement in email-api.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use http://page-fetcher-api:8080 (the Compose service key) for Docker DNS
resolution, consistent with all other internal service URLs (rag-api,
email-api, cv-matcher-api).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>