Fraqt

AI compliance and operations software for university international student offices, and the F-1 students they serve.

Two university offices engaged | Pre-revenue, pre-incorporation

Period
June 2026 to present
Role
Founder. Design, architecture, engineering, brand, positioning, sales
Stack
TypeScript, Next.js, React, Postgres, AWS (Textract, KMS, Lambda)

Visit fraqt.org

1,194

government source passages, live

715

automated tests

6

weeks to production

What it is

An international student office runs on deadlines that carry legal consequence. A date read wrong from a form becomes a status problem for the student, well after anyone could have caught it. The offices doing this work are small, and the questions arriving at them are repetitive, specific, and expensive to get wrong.

Fraqt answers those questions from a corpus of federal guidance, refuses when the corpus does not cover them, and drafts officer replies that a person edits and sends. Built by one person in six weeks from an empty repository to production.

What a student sees

They sign up. The first thing it asks for is their I-20. Upload from a laptop or photograph it with a phone.

Then a screen with the document image on one side and the extracted fields on the other. SEVIS ID, program start and end, school, country. They read across, fix anything wrong, and confirm. Nothing the system computes touches a field they have not confirmed.

Then the dashboard. Their name, their school, their status. Underneath, one to three deadline cards. Only the deadlines that apply to them, each with a why that opens the passage it came from.

They type a question. “Do I need to file Form 8843 if I had no income?” The answer streams in, plain language, with a sources list underneath showing each document, its date, and a link. If the corpus does not cover it, they get a calm card instead. This depends on details we cannot see. Your DSO can help.

That refusal is the product working, not failing.

What an officer sees

They open the queue on Monday morning. Student threads, open and unassigned. They click one. A student asking about Form 8843.

Below the message is a button. Draft a reply. They click it, and a reply appears in the box they already use. Cited, grounded, plain. They read it, fix a sentence that sounds off, and hit send. The student gets it as a normal message from their office.

The officer never sees the AI. They see a draft they can edit and send.

How it feels

Quiet. No urgency colours, no chatbot personality. Closer to a well made government form than a consumer app. That is deliberate. The people using it are already scared.

The OCR, and what it changed

Textract reads an I-20 and gives back field names that change with the scan, the angle, the school’s printer. The same date field comes back under three different labels. For a while nothing mapped cleanly and the dashboard showed garbage.

The fix was not clever. It was accepting that extraction is unreliable and putting a human confirmation step in front of every computed value. That decision came out of the failure, and it is the reason confirm-before-use is an architectural rule here rather than a preference.

The principle

No machine-read field drives a legal deadline until a person has confirmed it against the document image.

The transaction bug

Analytics events were emitted inside the database transaction that recorded an officer’s decision. A telemetry failure could therefore roll back a real approval. An officer would have clicked approve, seen it succeed, and had it silently undone because a metric could not be written.

It was found by reading code. The tests passed. They passed because they exercised the approval path and the analytics path separately, and the fault only exists where the two share a transaction boundary.

The fix was ordering. The emit now sits after the commit, and its failure is logged and swallowed. The work goes through and the number is lost.

There was a second one of the same shape. Every draft analytics event was silently dropped in production because the development tenant identifier failed a strict validator, and the tests passed because they used a hand-written value instead of the real constant.

Both are stories about tests passing while the system was wrong. Green tests do not mean the page works.

Decisions

Each of these rejected something specific. The last one did not. It came out of the bug above rather than a choice, and an invented tradeoff would be weaker than what actually happened.

Fail-closed answer grounding

A citation guard validates that every response parses to schema, carries at least one citation, cites only retrieved passages, and trips no banned-phrase or PII pattern. A separate model pass judges grounding per claim. Any failure becomes a refusal, and the guard cannot be bypassed in production.

Instead of: serving a plausible answer

Tenant isolation at the database layer

Production connects as a role that cannot bypass row-level security, so an application-code mistake cannot leak data across tenants. Validated by 93 dedicated tests inside the 715-test suite.

Instead of: trusting every future query to filter correctly

Confirm-before-use on extracted documents

No OCR field drives a computed deadline until the student confirms it against the document image. Below a confidence threshold it falls back to manual entry.

Instead of: a wrong date silently becoming a legal deadline

Change detection on federal sources

A content hash per source flags superseded guidance, and retrieval joins only current sources. Federal guidance changes without announcement, and a citation to a repealed rule is worse than no citation.

Instead of: citing repealed rules confidently

Human approval as architecture

Officer-side drafts are edited and sent by a person. Both the machine version and the human version are retained as an audit trail. The activity itself is the regulated thing, so the approval step is structural rather than advisory.

Instead of: a disclaimer, which does not cure unauthorized practice of law

Analytics fail open, deliberately

A strict allow-list drops any event carrying an unexpected property, so no free-text field exists to leak into. The emit is ordered after the commit and its failure is logged and swallowed: the work goes through and the number is lost. The principle that came out of it is that the decision must never depend on the measurement.

What it refuses to do

  • answer at all when the citation guard fails
  • trust application code to keep tenants apart
  • let an OCR read drive a deadline before a human confirms it
  • keep serving federal guidance after it has been superseded

Not published

The Fraqt repository

Not published

Private, and staying private. Compliance software holding immigration documents does not go in a public repository. The consequence is that this page and the live product are the evidence, rather than the code.

Known gaps, stated rather than hidden: a bug shows a student enrolled past their program end date, attorney sign-off on the AI-disclosure copy is outstanding, auth still runs on a development instance, several features are half-built, and the metrics dashboard emits events nothing reads.