-
-
Get what the policy already promised you. One receipt and one sentence become a claim, verified in code before anything is sent.
-
Drop a receipt, describe the problem in one line, and watch six steps run: read, research, check evidence, verify, draft, prepare.
-
The Proof Ledger. Two quotes matched verbatim against the real policy page. One MISSING, because the photo the policy demands isn't there.
-
Claim strength, computed in code from the verified ledger, not asserted by the model. Every requirement grounded in the seller's policy.
-
Drafted by Nemotron 3 Nano, citing only quotes that survived verification. Anything ungrounded was downgraded and left out.
-
11 days left, recomputed in deterministic TypeScript with a one-click .ics reminder. Each fact links back to the document it came from.
-
If the merchant refuses: platform dispute, card chargeback, regulator, small claims. Switchable between Global/US/UK and India's CPA 2019.
-
Rightful fills the support form field by field, then stops at a human approval gate. Nothing is ever sent without explicit sign-off.
-
The whole case as one printable document: facts, verified policy quotes with sources, the deadline, and the letter.
Inspiration
Nineteen days after it arrived, the right earbud stopped charging. Support replied in one sentence: "All audio sales are final."
They were wrong — and the proof was in their own published warranty. But finding it means reading a policy nobody reads, working out which clause applies, calculating whether a window has closed, and then quoting it back accurately enough that a support agent cannot wave it away.
Billions in legitimate refunds, returns and warranty claims expire every year for exactly that reason. Not because people don't have rights, but because the rights are buried and the deadline is invisible.
The obvious build is "an LLM writes your complaint email." I didn't want that, because the failure mode is catastrophic: a model that invents a policy clause makes the user look like a liar to the one person who can help them. A hallucinated quote is worse than no claim at all.
So the question became the architecture question: how do you let a language model do the reasoning without letting it have the final word?

What it does
Rightful turns an order receipt and one sentence about what went wrong into an evidence-backed claim, in under a minute.

- Reads your documents.
.txt,.emlemail headers and PDF receipts, parsed into structured facts — seller, product, order ID, purchase and delivery dates, price — by NVIDIA Nemotron 3 Nano on Nebius Token Factory. - Retrieves the seller's own policy with Tavily Search & Extract, ranking official merchant domains above forums and review sites.
- Builds a Proof Ledger with NVIDIA Nemotron 3 Super (120B) — every requirement the policy sets, with the quote that satisfies it, stamped
Supported,Ambiguous,MissingorNot Met. - Then stops trusting the model. A deterministic TypeScript verifier re-checks everything and has final authority.
- Starts the deadline clock and hands you a
.icscalendar reminder. - Drafts the claim letter, citing only quotes that survived verification, and autofills a sandbox support form — which stops dead at a human approval gate.
The Proof Ledger

Each row is one requirement the policy imposes, the quote that addresses it, and a rubber stamp. The stamp is not the model's opinion. Two quotes here matched verbatim against the retrieved page; the third row is held back as MISSING, because the photo the policy demands was never attached.
Nemotron proposes. Code decides.
This is the whole project.

lib/verify.ts contains no AI. It enforces three things:
- Verbatim quote grounding. Every quote the model cites must exist in the text Tavily actually retrieved — by exact substring match, or a sliding token-window overlap of ≥ 0.90 to tolerate whitespace and smart-quote differences. Anything ungrounded is downgraded to
ambiguousautomatically, even when the model was confident. - Date arithmetic in code.
days_elapsedis recomputed from the real dates. If the model misclassified a claim as out-of-window, the code overrules it. - Citation integrity. Hallucinated source IDs are stripped. A third-party-only source cannot produce a
supportedverdict without an official-domain anchor.
The claim strength above is computed from the verified ledger, not asserted by the model.
Measured on a verified live run against the deployment:
| Step | Model | Latency |
|---|---|---|
| Fact extraction | nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B |
4.6s |
| Policy retrieval | Tavily Extract | ~0s (direct policy URL) |
| Evidence matrix | nvidia/nemotron-3-super-120b-a12b |
11.4s |
| Deterministic verifier | pure TypeScript | 0.001s |
| Claim drafting | nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B |
7.1s |
The step with final authority costs one millisecond, because it isn't a model at all.
A letter that only cites what survived

The deadline nobody tells you about

Days remaining are recomputed in deterministic TypeScript, with a one-click .ics reminder. Every extracted fact carries a D1 chip linking it back to the document it came from.
And it never sends anything without you

Rightful fills the support form field by field and then halts. Actions are restricted to a local /portal sandbox; nothing is ever submitted to a real company.
How we built it
Next.js 15 + React 19 + TypeScript, deployed on Vercel. No database — documents are processed in memory per request and discarded; history lives only in the browser's localStorage.
Model routing across the Nemotron family on Nebius Token Factory, chosen deliberately rather than defaulting to one model:
- Nemotron 3 Nano (30B A3B) for extraction and drafting — strict JSON schema adherence at speed. Extraction is a bounded transformation, not a reasoning problem.
- Nemotron 3 Super (120B A12B) for the evidence matrix — the one genuinely hard step, cross-referencing a user's documents against every requirement a policy imposes. This is where a bigger model earns its latency.
Routing per step is only cheap because both sit behind the same OpenAI-compatible API — switching a step is a model-name string. That is also how Nemotron-3_5-Lightning was ruled out for extraction: benchmarked at a 23.8s median against Nano's 5.8s on the same prompt.
Tavily Search & Extract for policy retrieval, with domain-targeted ranking: official merchant domains score +5.0, the seller's name in the URL +3.0, policy keywords +2.5, and community/forum/review domains are penalised −4.0.
The pipeline streams to the browser as NDJSON so each step appears as it completes, and a Run Log Drawer exposes real model IDs, latencies and token counts.
Verification is enforced, not aspirational: 7 invariant unit tests cover exact-match grounding, smart-quote normalisation, the ≥0.90 sliding-window fallback, rejection of an injected hallucinated quote, domain ranking, constant-time judge-code comparison, and date-window arithmetic. A bundle audit scans all 24 client chunks for leaked keys on every build.
Challenges we ran into
1. The model was right and my prompt was wrong. Every run on the flagship sample case was collapsing to a pre-recorded fallback. Attempt-level logging finally showed why: my system prompt said "use ONLY information explicitly stated in the documents — never invent facts." The sample receipt names no merchant; the seller arrives only as a hint field. So Nemotron correctly returned null — and my validator demanded a value. I had written a contradiction and blamed the model for obeying it. Fixed in three places: the prompt now names the hint as an authoritative source for that one field, the validator no longer requires it, and the route backfills it deterministically — keeping final authority in code, which is the project's whole thesis.
2. The schema was causing a token blowout. The model mirrors the layout it's shown. A pretty-printed JSON schema was drawing ~2,400 tokens of padded output for a ~300-token object — overrunning max_tokens and tripling latency. Minifying the schema and requiring single-line output dropped it to ~1,000–1,500 tokens and took the isolated pass rate from 1/4 to 4/4.
3. Serverless timers don't fire reliably mid-stream. One deployed run hung for 130 seconds with no terminal event. The cause was almost funny: the replay fallback — the thing that runs when everything else fails — awaited a setTimeout between every event, purely for cosmetic "realistic" pacing. In Vercel's streaming context those timers stall, so the safety net could itself hang forever. The pacing meant to look good was preventing runs from finishing.
4. The 60-second wall. Identical input ranged 26s to 67s purely on provider load. No fixed per-step timeout is correct, so each step is now capped by what the downstream steps still need, with a watchdog guaranteeing a terminal event. Then I removed work instead of tuning it: when a policy URL is already supplied, the research-planning model call generates search queries nobody reads, so it's now derived in code. That one change took the deployment from 0/4 successful live runs to 4/4.
5. Research was unbounded in aggregate. Each Tavily call had a 20s timeout, but the step issues up to five sequentially — ~100s worst case, enough to blow the function limit before the evidence matrix was even reached. It now receives a budget from the pipeline clock and stops searching at 60% of it, reserving the rest for the extract that turns URLs into quotable text.
Accomplishments that we're proud of
- A model's confident verdict getting overruled by 1ms of code, visibly, on screen. A
supportedstamp flipping toambiguousbecause a quote failed verbatim grounding is the moment the architecture explains itself. - Final verification: 5/5 live runs completed on the deployment, 31–53s wall time, every run producing a terminal event, 4 of 5 drafting on Nemotron rather than the code fallback.
- Honest telemetry. The fallback used to report a hardcoded
latency_ms: 50, so a draft attempt that burned 25 seconds showed as an instant code draft. In a panel whose entire job is showing where time goes, a fabricated number is worse than none — it now reports measured elapsed time and names the reason. - Zero secrets in 24 client bundles, audited on every build. No login, no database, no document retention.
- A fictional benchmark seller (Voltline) so the demo is deterministic and infringes no real retailer's trademarks.


What we learned
Naming a model earns nothing; showing how you checked its output earns everything. Every submission this year uses an LLM. The differentiator is the verification layer, and building the verifier first changed every downstream decision.
Measure, never assume. Three times I was confident about a root cause and wrong. "Reasoning-token truncation" — disproved by a direct API test showing response_format: json_object suppresses <think> entirely. "Tavily is the bottleneck" — that was a client-side arrival gap distorted by stream buffering. Attempt-level logging found in one minute what three rounds of reasoning had missed.
Model size is a routing decision, not a quality setting. Nano at 4.6s and Super at 11.4s doing different jobs beats one model doing both badly — and it keeps the credits going further.
Graceful degradation has to be honest. Silently substituting pre-recorded data for a failed live run makes failure indistinguishable from success. That hid real breakage from me for hours, and would have misrepresented the project to anyone inspecting the stream. It now says so, in the stream and in the UI.
What's next for Rightful
- Nemotron 3 Ultra (550B) for genuinely contested matrices — multi-document disputes where a 120B model's confidence isn't enough. The routing slot already exists.
- Vision via Nemotron VL so a photo of a paper receipt works, not just a PDF or
.eml. The environment slot is wired and unset. - Nebius Serverless Jobs for nightly policy snapshots, so a claim can cite the policy as it stood on the purchase date — the single most useful thing against a merchant who quietly edits their terms. A job script is already in the repo.
- More jurisdictions. The escalation ladder currently maps India's Consumer Protection Act 2019; the same structure fits UK, EU and US state consumer authorities.
- Measured outcomes. Real claim success rates against real sellers, which is the only number that ultimately matters.
Live demo: https://rightful-nu.vercel.app · Code: https://github.com/devprashant19/Rightful (MIT)
Built for the Nebius x NVIDIA Global AI Hackathon 2026. Architectural logic, verifier algorithms and prompts developed under the entrant's direction with AI coding assistance; all code owned by the entrant.
Built With
- css-modules
- eslint
- ics-calendar
- ndjson
- nebius-token-factory
- nemotron-3-nano
- nemotron-3-super
- next.js
- node.js
- nvidia-nemotron
- python
- react
- server-side-streaming
- serverless
- tavily
- typescript
- unpdf
- vercel


Log in or sign up for Devpost to join the conversation.