# Candidate Verification Copilot

An interactive case study by **Sellina Xie**, inspired by a Bluevine recruiter conversation about fraudulent applications and false positives in an existing Gemini prototype.

## Try it in three minutes

1. Open the hosted workbench, or download the standalone HTML from its **Download demo** button and open it in a browser.
2. Select **AI-polished, legitimate** and run the fixture checks. Change the wording and rerun: writing style does not change verification priority.
3. Select **An unavailable source**. Missing evidence stays unknown; it does not become a fraud finding.
4. Select **Corroborated claim conflicts**. Open the cited source excerpts. Withhold one source and rerun: a remaining independently supported material conflict retains High priority while coverage becomes Partial.
5. Select **A mistyped profile link**, apply the sample correction, and rerun. Inspect the before/after history.
6. Record a local reviewer note or export an evidence packet. Review actions do not contact a candidate or update an ATS.

## The business problem

Recruiters need to investigate whether application claims belong to the person applying, without confusing polished writing, inaccessible pages, or same-name records with deception. The first useful output is a cited evidence packet and a clear next action.

## What actually runs

| Capability | This prototype | Production design |
| --- | --- | --- |
| Application data | Six synthetic cases | Authorized application ingestion |
| Source checks | Local, predefined evidence fixtures | Permitted ATS, employer and credential verification adapters |
| Entity matching | Explicit scenario assumptions; no forced name/school merge | Identifier association with documented provenance and human review |
| Priority | Real JavaScript policy over fixture check states | Stakeholder-calibrated, versioned policy |
| GenAI | Not connected; no model-generated analysis | Structured extraction, semantic comparison and cited summaries |
| Agent planning | Explanatory workflow view | Bounded planner choosing approved read-only checks |
| Review | In-memory notes and event history | Authenticated reviewer queue with durable audit storage |
| Export | Local Markdown / JSON downloads | Access-controlled case export |

The prototype makes **no external network requests, model calls or identity checks**. All source excerpts are synthetic. Changing a variation changes fixture availability or interpretation, not real-world evidence. A complete replay only means the defined fixture checks completed.

No real resumes are uploaded. State is held in memory and resets on reload. Downloaded exports persist wherever the user saves them. The standalone HTML needs no installation or API keys.

## Data and provenance

An internal `candidate_id` identifies a case. Names, schools, emails and phone numbers are matching attributes, not globally unique identity keys. Contacts use example.com and reserved fictional phone numbers.

Each source has an ID, type, excerpt and synthetic provenance. Each check references a source. Conflict findings reference both the submitted claim and the comparison source. Candidate-controlled profiles are not independent proof merely because they agree with the resume.

Proposed production evidence metadata additionally includes owner/access scope, source timestamp and version, retrieval result, document hash, assertion span, verification method and independent-source status. A 403, login wall, missing record or stale source is an evidence condition, not an identity-fraud determination.

## Priority policy v0.1

These are **illustrative verification priorities**, not probabilities of fraud or hiring recommendations.

1. A processing validation issue produces **Unknown** pending recovery.
2. A material conflict with supported identity association and independent evidence produces **High** review priority.
3. An unresolved discrepancy or uncertain entity association produces **Medium**.
4. Required missing checks or an unbound identity produce **Unknown**.
5. Otherwise the completed fixture checks produce **Low**.

`coverage` is separate: **Complete**, **Partial**, or **Interrupted**. Known High findings remain High when another source is missing. Low does not guarantee authenticity. No priority triggers automatic rejection.

## Proposed agent architecture

Authorized ingestion → claims with source spans → bounded planner → allowlisted read-only checks → evidence validation → versioned policy → cited case summary → human review.

The planner can branch according to evidence: a malformed link prompts clarification; an inaccessible source creates an evidence gap; a possible company alias requires semantic comparison before calling it a conflict. The model proposes an interpretation. Code enforces tool permissions, output schemas, citation references and workflow transitions.

Suggested implementation: Python/FastAPI/Pydantic, LangGraph, an approved LLM (including the existing Gemini setup), a relational evidence store and a reviewer UI. Exact identifier lookups precede fuzzy matching. Retrieval or graph infrastructure is added only for a measured need.

## Security and human oversight

- Treat resumes and source pages as untrusted data. The injection case illustrates expected handling; it does not validate a live model defense.
- Keep nationality, ethnicity, accent, political statements and AI-writing heuristics out of the policy.
- Enforce authorization outside prompts. Use approved read-only adapters with bounded calls, timeouts and retries.
- For URL adapters, restrict allowed destinations, block private-network targets, validate redirects and do not execute candidate content.
- Minimize PII and raw-content telemetry. Define access, retention and deletion before using real application data.
- Resolve identity association before treating a cross-record difference as an applicant contradiction.
- Keep HR / InfoSec accountable for actual investigations. Review actions in this prototype are local simulations.

## Evaluation plan

Start with 30–50 synthetic cases for behavior, including paraphrase pairs, stale/missing sources, namesakes, shared contacts, candidate corrections and conflicting evidence. Freeze a holdout split by identity and template family.

Compare manual review, rules-only, and rules + GenAI under the same permitted evidence. Include the existing Gemini workflow when authorized. Measure legitimate-case escalation rate, citation support, correct abstention, reviewer disagreement, total review/correction time, latency and model/tool cost. Fraud recall requires independently confirmed fraud labels. Unknown cases must not be labeled legitimate just to calculate accuracy.

The automated checks in `tests/core.test.cjs` verify prototype policy invariants, not detection accuracy. No precision, recall or time savings are claimed.

## Run or modify locally

The downloadable HTML is self-contained. No server is needed to try it. To rebuild it from the source repository:

```bash
python3 build.py
node --test tests/core.test.cjs
```

Sources: `src/core.js` (fixtures and policy), `src/ui.js` (workbench), `src/styles.css`, `src/shell.html`, and `README.md`. `build.py` emits `dist/index.html` with all styles, data and scripts embedded. Browser downloads are generated from local state, and the original standalone document is retained for clean offline export.

## References

- FBI / IC3, 13 Oct 2026: https://www.ic3.gov/PSA/2026/PSA261013
- FBI / IC3, 23 Jan 2025: https://www.ic3.gov/PSA/2025/PSA250123
- OWASP LLM01 prompt injection: https://genai.owasp.org/llmrisk/llm01-prompt-injection/

Independent interview case study. Not affiliated with or endorsed by Bluevine. Architecture and policy are design choices to validate with stakeholders.
