Inspiration

Recruiters reviewing high-volume applicant pools (some postings crack 10,000+ submissions) are stuck asking one question at a time: "does this individual résumé look fake?" Meanwhile résumé fraud is getting harder to catch by eye — AI-generated résumés, prompt-injection attacks hidden in PDF metadata, and coordinated groups submitting near-identical applications. We wanted to flip the framing: instead of judging applicants one by one, analyze the whole applicant population as a network, and only escalate to a human when there's real evidence something is off — not a black-box "fraud score."

What it does

Applicant Trust Intelligence (ATI) ingests a corpus of résumés and produces two separate signals for every candidate instead of one opaque number:

$$ \text{Qualification} \in [0, 100], \qquad \text{Trust Evidence} \in [0, 100] $$

  • Population Intelligence — embeds every résumé, reduces dimensionality with UMAP, and clusters with HDBSCAN to surface unusually similar or coordinated groups of applications.
  • Claim Provenance — extracts discrete claims from each résumé (employer, degree, GitHub, project work) and checks them against external evidence like GitHub history and account age.
  • Anomaly Detection — feeds engineered features (similarity scores, timeline gaps, submission velocity, etc.) into an Isolation Forest to flag statistically unusual applicants.
  • Adaptive Verification — instead of auto-rejecting, the system asks for the minimum verification needed to resolve a specific uncertainty (e.g. GitHub OAuth to confirm repo ownership).

The output is a recruiter dashboard that turns 10,000 applications into a prioritized shortlist, with full explainability for every flag.

How we built it

  • Backend: Java 21 + Spring Boot 3 (Maven) serving the core API, orchestrating the trust pipeline, and persisting to PostgreSQL.
  • Frontend: React + Vite + TypeScript for the recruiter dashboard (cluster visualizations, applicant landscape, claim provenance views).
  • ML service: a separate Python FastAPI microservice handling embeddings, UMAP, HDBSCAN, and Isolation Forest, called by the Spring Boot backend.
  • We built the pipeline in phases — application integrity checks first, then population-level clustering, then claim provenance — validating each stage before layering on the next.

Challenges we ran into

  • We started on a MERN/Mongoose/Prisma stack and hit friction with schema rigidity and typing across the fraud/trust data model, so we made the call mid-hackathon to restart on Spring Boot + PostgreSQL — a real cost in hours, but it paid off in reliability.
  • Splitting responsibilities between the Java backend and the Python ML service meant getting the service boundary and API contract right early, so embeddings/clustering results could flow back into the trust graph without duplicating logic.
  • Keeping "qualification" and "trust" as genuinely separate scores (rather than collapsing them into one fraud probability) took discipline — it's tempting to just output a single number, but that's exactly the black-box behavior we were trying to avoid.

What we learned

  • Fraud detection in hiring is as much a product and policy problem as a technical one — a hard reject on weak evidence is a legal and ethical liability (NYC's AEDT law was front of mind), so "flag for human review" is almost always the right default over automation.
  • Population-level signals (clustering, embedding similarity) catch categories of fraud that per-candidate checks structurally can't — coordinated résumé rings only become visible in aggregate.
  • Splitting a monolith into a dedicated ML microservice earlier rather than later made iteration on the clustering/anomaly pipeline much faster, since we could redeploy it independently of the Spring Boot API.
  • "Unverified" and "false" are not the same thing, and building that distinction into the UI (rather than just the backend logic) was as important as the modeling itself.

Built With

Share this project:

Updates

Submission history