Commit Graph

56 Commits

Author SHA1 Message Date
cfe06788e2 Fix CV verification scoring and UI alignment issues
ProcessCVCheckJob:
- Recognize "contract", "contract work", "contract role" as freelance
- Add "various", "various clients" for multiple short-term contracts
- Prevents false matching of contract work to dissolved companies

Report.razor:
- Fix stat blocks centering (icon, number, label now centered)
- Fix employment table column alignment with fixed widths
- Add inline styles to header for consistent centering
- Improve GetPointsForCompany to show -10 for unverified companies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 11:20:38 +00:00
7510ef3670 Fix text cursor appearing on non-editable elements
- Add universal cursor inherit rule for consistent cursor behavior
- Add user-select: none to prevent text selection on UI elements
- Expand element coverage to include modals, tooltips, and inline elements
- Preserve text cursor and selection for form inputs with !important

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 10:53:13 +00:00
5ba787aff9 Add Linux deployment scripts
- deploy.sh: Publish and deploy from dev machine
- server-setup.sh: One-time Ubuntu server setup (Nginx, Docker, SQL Server)
- README.md: Deployment documentation and troubleshooting guide

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 09:48:59 +01:00
7ca00ca0b6 Fix cursor styling and replace hero logo with SVG illustration
- Replace hero section PNG logo with clean SVG document illustration
- Add comprehensive cursor styling to prevent text cursor on non-editable elements
- Cover all SVG elements, Bootstrap components, and custom classes
- Ensure checkboxes and interactive elements have pointer cursor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 09:23:51 +01:00
4cc0bb3132 UI redesign: improve readability and add candidate name display
- Add CandidateName property to VeracityReport and display on report page
- Simplify employment verification layout with compact row-based design
- Add UK employment history notice to Home and Check pages
- Improve hero section text readability with text shadow
- Update Login and Register page styling
- Remove Companies House references from UI text

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 09:01:01 +01:00
45ca5f6a05 Implement code review fixes and improvements
- Move admin credentials from hardcoded values to configuration
- Add rate limiting (5/min) to login endpoint for brute force protection
- Extract CleanJsonResponse to shared JsonResponseHelper class
- Add DateHelpers.MonthsBetween utility and consolidate date calculations
- Update PdfReportService to use ScoreThresholds constants
- Remove 5 unused shared components (EmploymentTable, FlagsList, etc.)
- Clean up unused CSS from MainLayout.razor.css
- Create IPdfReportService interface for better testability
- Add authentication requirement to Hangfire dashboard in development
- Seal EducationVerifierService class

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 02:09:26 +01:00
3a33119bea Add bulk deletion with checkboxes to Dashboard
- Add checkbox column with Select All in header
- Show selection count badge and Delete Selected button
- Enhanced confirmation modal for bulk operations
- Row highlighting for selected items
- Fixed button spacing (gap between View and Delete)
- Scrollable list in modal for many selected items

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 01:51:15 +01:00
7d5964174f Recognise community partnerships as charitable organisations
Add "partnership" detection to charity/voluntary check (excluding LLPs).
Most UK "X Partnership" organisations are registered charities or CICs,
e.g., North Halifax Partnership Limited (charity 1169746).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 01:42:06 +01:00
28a61552cc Fix ProcessCVCheckJob tests for current behaviour
- Update flag assertions to filter by specific flag types
  (job now creates additional informational flags)
- Update overlap tests: now "Concurrent Employment" with Info severity
- Update overlap score tests: no penalty for overlaps
  (legitimate for part-time, consulting, job transitions)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 01:36:25 +01:00
b2887dfe38 Improve UI styling and AI company matching
- Enhance text contrast (darker grey #2d2b27)
- Soften footer with warmer dark (#3a3833)
- Use warmer primary blue (#3d5a80)
- Add subtle background gradient for depth
- Strengthen table header styling
- Increase logo size to 95px for better visibility
- Fix AI matcher to handle acronyms in parentheses (e.g., NHP)
- Improve matching rules for CIC/LLP legal suffixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 01:27:53 +01:00
71efbcfc48 Merge feature/improved-company-matching into feature/ui-eye-friendly
Bring in AI-powered company name matching using Claude API.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 00:59:35 +01:00
4721f6d6f6 Update UI with eye-friendly colour scheme
Replace bright white backgrounds with warmer off-white tones to reduce
eye strain while maintaining good contrast and professional appearance.

Changes:
- Update CSS variables with warmer neutral palette (#f5f3f0 page bg,
  #faf9f7 surfaces, #f0ede8 muted sections)
- Soften primary blue from #2563eb to #3b6fd4
- Update navbar, cards, tables to use new surface colours
- Update upload area, file lists, and icon backgrounds
- Update flag item backgrounds with softer tints
- Update shared components (VeracityScoreCard, FlagsList)

The new colour scheme uses warm off-white/cream tones that are easier
on the eyes than pure white while maintaining professionalism.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 00:59:12 +01:00
d047de1c84 Add AI-powered company name matching using Claude API
Replace fuzzy string matching with semantic AI matching to fix false
positives where similar-sounding but different companies were matched
(e.g., "Families First CiC" incorrectly matching "FAMILIES AGAINST
CONFORMITY LTD").

Changes:
- Add ICompanyNameMatcherService interface and AICompanyNameMatcherService
  implementation using Claude Sonnet 4 for semantic company name comparison
- Add SemanticMatchResult and related models for AI match results
- Update CompanyVerifierService to use AI matching with fuzzy fallback
- Add detection for public sector employers, charities, and self-employed
  entries that cannot be verified via Companies House
- Update tests to work with new AI matcher integration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 00:51:24 +01:00
030ede9e77 Use more saturated green and yellow for score rings on blue background 2026-01-21 00:05:42 +01:00
c9ed3119cc Use more saturated red for score ring to avoid orange appearance on blue 2026-01-21 00:05:14 +01:00
911e3f99bb Make all score ring colours more visible against blue background 2026-01-21 00:04:33 +01:00
80ba03c627 Make red score ring more visible against blue background 2026-01-21 00:03:42 +01:00
150cb268bd Colour score ring background based on score level
- Red ring for low/zero scores
- Amber ring for medium scores
- Green ring for high scores
- Background ring now visible and coloured appropriately

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 00:02:06 +01:00
a15be6423a Improve score roundel CSS and fix rotation
- Add explicit circumference calculation for clarity
- Apply rotate(-90deg) to start progress from 12 o'clock
- Add transform-origin: center for consistent rotation
- Clean up duplicate CSS rules
- Fix mobile responsive styles for score-roundel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:59:13 +01:00
f840b9a55d Hide score ring progress when score is zero
Prevents red dot from appearing at top of ring when score is 0.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:56:52 +01:00
0e71097bbc Replace coloured score header with neutral blue and score roundel
- Change header background to neutral blue gradient
- Add score roundel with coloured ring based on score
- Ring colour indicates score level (green/amber/red)
- Keeps header consistent regardless of score

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:45:30 +01:00
b3d45c12d1 Skip unverified institution flag for unknown institutions
Filter out empty, "Unknown", and "Unknown Institution" values
from generating verification flags since there's nothing to verify.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:42:10 +01:00
894b539002 Replace score labels with TrueCV Score branding
- Remove score rating labels (Excellent, Good, Fair, Poor, Very Poor)
- Display "TrueCV Score" instead of rating text
- Remove Rating column from batch PDF report

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:38:54 +01:00
5bfefdfd1d Enhance UI design and update to UK English
- Add custom CSS design system with brand colours and variables
- Enhance Report page with SVG score ring and improved flag styling
- Improve Dashboard with better table design and score badges
- Enhance Check page upload area with animated icon and file styling
- Update spellings to UK English (analysing, recognised)
- Add user-select: none to prevent text cursor on clickable elements
- All date formats already use UK-friendly dd MMM yyyy format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:35:36 +01:00
14ee569617 Skip verification note for unknown institutions
When the institution name is empty, "Unknown", or "Unknown Institution",
don't show the "not found in UK database" message since it's not useful.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:14:52 +01:00
8106b86bcd Remove points display from informational flags
Informational flags are context-only and don't affect the score,
so displaying "0 pts" was redundant and confusing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:10:28 +01:00
c07254f93a Remove SIC code mismatch check from company verification
The SIC code mismatch check was flagging tech roles at companies not
registered as technology businesses. This is not a reliable measure
since many companies employ tech staff regardless of their SIC code.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:07:36 +01:00
1aeaba7fbb Add comprehensive informational flags for recruiters
New info flags (no penalty - provide context):
- Career Span: Total years of experience with label (Early Career to Extensive)
- Current Status: Currently employed at X / Available since Y
- Long Tenure: Highlight 5+ year roles positively
- Management Experience: X of Y roles with management titles
- Individual Contributor: When no management titles detected
- Company Size Pattern: Startup/SME/Corporate experience breakdown
- Career Trajectory: Upward/Lateral/Step-down progression analysis
- PLC Experience: Roles at publicly listed companies
- Director Experience: Director/officer roles without red flags

All flags have ScoreImpact = 0 (informational only)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:02:58 +01:00
f711c9725e Add frequent job changes detection (informational flag)
- Add CheckFrequentJobChanges() to detect short tenure patterns
- Flag when 3+ employers have <18 month tenure (no penalty, info only)
- Group multiple roles at same company/group together
- Calculate and display average tenure across all employers
- Add NormalizeCompanyForGrouping() to handle company name variations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 23:00:07 +01:00
a6b24d2c64 Change report download from JSON to PDF
- Add GenerateSingleReport() method to PdfReportService for individual CV reports
- PDF includes: score header, employment verification table, timeline analysis,
  gaps/overlaps sections, and color-coded flags (critical/warning/info)
- Update Report.razor to use PdfReportService instead of JSON serialization
- Add TrueCV.Web.Services to _Imports.razor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:49:22 +01:00
1a53431757 Prefer main trading companies over subsidiaries in company matching
When matching brand names like "ASDA", prefer the main employer company
(ASDA STORES LIMITED) over subsidiaries (ASDA DELIVERY LIMITED).

- Add SubsidiaryIndicators set (delivery, distribution, holdings, property, etc.)
- Add MainCompanyIndicators set (stores, retail, manufacturing, etc.)
- Add CalculateCompanyPriorityScore() method for ranking matches
- Sort matches by priority score first, then by fuzzy score
- Subsidiaries get -10 priority unless explicitly searched for
- Main trading companies get +5 priority, PLCs get +3

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:41:27 +01:00
55c0aebdaa Improve company verification filtering and fix duplicate points display
- Add NonEmploymentEntityPatterns dictionary with 10 categories of non-employer entities
  (clubs, associations, trusts, charities, investment, property, religious, sports, educational, professional)
- Expand SkipWords from ~30 to 120+ words for better core identifier extraction
- Add GetSearchEntityTypes() and IsValidEmploymentEntity() helper methods
- Refactor FindBestMatch() to use pattern-based filtering instead of hardcoded checks
- Fix UI showing duplicate points for same company appearing multiple times
  (now only shows points on first occurrence, subsequent rows show 0)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:33:16 +01:00
4bd7f1cef1 Fix incorrect company matching with stricter validation
- Require ALL core identifier words to be present in match
  (e.g., "Lloyds Bowmaker" needs both "LLOYDS" and "BOWMAKER")
- Filter out club/association/society type entities
  (prevents "BMW" -> "BMW CAR CLUB LIMITED")
- Filter out benefit/trust/pension type entities
  (prevents "BMW Group" -> "BMW GROUP BENEFIT TRUST LIMITED")
- Core word extraction now returns all significant words, not just first

Fixes false matches like:
- "BMW Group Canada" -> "CANADA LIFE GROUP" (missing BMW)
- "Bank of Scotland" -> "BANK AND CLIENTS PLC" (missing Scotland)
- "Lloyds Bowmaker" -> "LLOYDS ALARMS" (missing Bowmaker)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:13:23 +01:00
be2f738e58 Deduplicate penalties for same company appearing multiple times
When a company appears multiple times in employment history (e.g.,
multiple roles at same company), penalties are now applied only once
per unique company, not per employment entry.

- Unverified company: -10 pts once per company (not per role)
- Company flags (incorporation date, etc.): once per (company, flag type)

Description now shows "(X roles)" when multiple instances exist.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:07:23 +01:00
7f4c2362f0 Add first-word parent company extraction
For company names like "UNILEVER BESTFOOD", now also tries searching
for just the first word ("UNILEVER") as it may be the registered
parent company name. Adds PLC/Limited variations for major corps.

Skips common prefixes like "The", "UK", "British", etc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 22:04:44 +01:00
02147d1221 Clear company cache on startup
Ensures fresh API lookups each time the app starts, avoiding stale
cached results that may have been stored before matching improvements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:57:53 +01:00
5d2ec4b98e Improve company matching and move points to employment table
Company Matching:
- Extract parent company from "Brand (Parent Company)" format
- Handle slash-separated names like "ASDA/WALMART"
- Match against both original name and search query for flexibility
- Add PLC/Plc case variations

Report UI:
- Remove separate Score Breakdown section
- Add Points column to Employment Verification table
- Calculate points per company from matching flags

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:49:26 +01:00
f4890b3049 Fix company name variation search to find older companies
The previous search only tried a single query which often returned newer
companies with similar names. Now generates all combinations of name
variations (UK/U.K. + Ltd/Limited) to find the correct company.

For "Mattel UK Ltd", now searches:
- Mattel UK Ltd
- Mattel U.K. Ltd
- Mattel UK Limited
- Mattel U.K. Limited (finds MATTEL U.K. LIMITED from 1980)
- Plus core name variations

This ensures companies like "MATTEL U.K. LIMITED" (incorporated 1980)
are found instead of incorrectly matching "UK MATTEL LTD" (2025).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:39:22 +01:00
58c0e79a85 Add alternative search queries for company name variations
When searching Companies House, now generates multiple query variations
to find companies registered with different naming conventions (e.g.,
"U.K." vs "UK", "Limited" vs "Ltd"). This helps match older companies
like "MATTEL U.K. LIMITED" when CVs list "Mattel UK Ltd".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:32:02 +01:00
12da40496e Don't match wrong company when no temporal match exists
When no company in search results existed at the claimed employment
start date, return no match instead of falling back to wrong company.

This prevents matching "UK MATTEL LTD" (2025) when the CV claims
employment in 2006-2013 and the real "MATTEL U.K. LIMITED" (1980)
isn't in the search results.

Result: Company shows as "Unverified" instead of wrongly verified
with multiple "Employment Before Company Existed" flags.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:26:36 +01:00
04557dd8c4 Add debug logging to company matching for diagnosis 2026-01-20 21:21:21 +01:00
7bb68b2567 Fix cache bypassing temporal company matching
- Cache lookup now validates company existed at claimed start date
- If cached company was incorporated after employment date, search for alternatives
- Fixes matching wrong company when cached data points to newer company

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:17:11 +01:00
67a98405af Fix file upload stale reference and improve company matching
File upload fix:
- Buffer file data immediately on selection to prevent stale IBrowserFile references
- Add BufferedFile record to hold file data in memory
- Add loading indicator while files are being buffered
- Fixes "Cannot read properties of null (reading '_blazorFilesById')" error

Company matching improvement:
- Prefer companies that existed at the claimed employment start date
- Fixes matching wrong company when newer company has similar name
- Example: "UK MATTEL LTD" (2025) vs "MATTEL U.K. LIMITED" (1980)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:14:01 +01:00
3c8ee0a529 Change employment overlaps to informational only
- Rename "Employment Overlap" to "Concurrent Employment"
- Remove score penalty for overlaps (often legitimate: part-time, consulting, transitions)
- Change severity from Warning/Critical to Info
- Update scoring explanation to note overlaps are not penalised

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:06:06 +01:00
21c73ab1e2 Improve report readability and add score breakdown
- Add Score Breakdown section showing how score is calculated
- Convert variable-style flag names to readable titles (e.g. UnverifiedDirectorClaim -> Unverified Director Claim)
- Deduplicate flags in report display for existing reports
- Make verification notes more user-friendly
- Add "How Scoring Works" explanation panel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 21:04:30 +01:00
0eee5473e4 Add audit logging, processing stages, delete functionality, and bug fixes
- Add audit logging system for tracking CV uploads, processing, deletion,
  report views, and PDF exports for billing/reference purposes
- Add processing stage display on dashboard instead of generic "Processing"
- Add delete button for CV checks on dashboard
- Fix duplicate primary key error in CompanyCache (race condition)
- Fix DbContext concurrency in Dashboard (concurrent delete/load operations)
- Fix ProcessCVCheckJob to handle deleted records gracefully
- Fix duplicate flags in verification report by deduplicating on Title+Description
- Remove internal cache notes from verification results
- Add EF migrations for ProcessingStage and AuditLog table

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 20:58:12 +01:00
652aa2e612 Add comprehensive CV verification checks and dashboard auto-refresh
- Add dashboard auto-refresh polling to update when processing completes
- Skip verification for freelance employers (but not contractors)
- Add incorporation date check (flags employment before company existed)
- Add dissolution date check (flags employment at dissolved companies)
- Add dormant company check (flags non-director roles at dormant companies)
- Add company size vs role check (flags senior roles at micro-entities)
- Add SIC code mismatch check (flags tech roles at non-tech companies)
- Add director verification against Companies House officers
- Add rapid career progression detection (3+ seniority jumps in <2 years)
- Add early career senior role detection (<2 years after education)
- Extend CompanyVerificationResult with flags and company data
- Add officers endpoint to Companies House client
- Fix null reference warning in Report.razor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 20:00:24 +01:00
acf4d96fae Replace CSV export with PDF report generation
- Add QuestPDF library for professional PDF generation
- Create PdfReportService with formatted table layout
- Export includes score (color-coded), verified employers, gaps, and flags
- Report has header, footer with page numbers, and alternating row colors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 19:28:22 +01:00
7d6d5f12ea Add multi-file upload, auto-refresh reports, and CSV export
- Allow recruiters to upload multiple CVs at once with batch processing
- Add auto-refresh polling on Report page during CV processing
- Add CSV export button on Dashboard for completed check summaries
- Update logo and reset to Bootstrap default styling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 19:15:33 +01:00
4de233f56d Add TrueCV logo and update site branding
- Add logo to navbar, home hero, login and register pages
- Update color scheme to match logo blue (#2B5F9E)
- Add CSS variables for consistent brand colors
- Improve card hover transitions with shadow effects
- Add responsive content padding
- Add focus-visible states for accessibility
- Add active state styling for navigation links

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 17:19:06 +01:00