How the 0–100 Trust Score is built, what each of the five analyzers looks for, and the small crew that runs the rules.
The short version
Make 'veridex it' the default reflex before tapping a link, replying to a message, or scanning a code — so locals don't pay the price for a global pattern of inbox scams.
Who builds Veridex
Veridex is built by a small crew — founders, engineers, and a handful of advisors who have watched an inbox scam cost a family member real money. We are local-first and we keep the team small enough that every shipped rule has a real person's name on it.
Want to reach the team? Email us — every message lands in the same inbox.
We build for the family member who pastes an SMS into the wrong field. Their input is the payload, never the product — we keep the smallest set of rows we need to surface a permalink, and nothing else.
Every chip on a result is a named rule with a fixed weight. If we miss a scam, you can see which rule didn't fire. If we call a real thing a scam, the matched signals are sitting in plain text next to the verdict.
No inbox pipe, no crawl layer, no opaque model in the loop — though a model-driven version of the screenshot explanation is on the roadmap. The pipeline is the same five deterministic rules on every input, and we say so on every result page.
What the score actually is
Veridex never auto-blocks a message. It runs a fixed set of deterministic rules — every signal is a named rule a reviewer can argue with — and returns a Trust Score plus the red flags that drove it. If we miss a scam, you can see exactly which rule didn't fire. If we call a real thing a scam, you can override the call because the matched signals are sitting in plain text next to the verdict.
Every signal is a named rule. There is no opaque model in the loop, and no "trust" verdict — only the absence of matched red flags.
URL, email, text, QR, and screenshot all share the same three-band scale and the same per-rule weight philosophy, so the habit carries across the five analyzers.
The output is the same shape every time, so the habit of reading the matched signals first — then deciding — carries across inputs.
The 0–100 scale
A higher score means fewer red flags were matched — not "verified safe". We never claim a thing is safe; we claim we did not see the usual scam signals. The scale is walked rule-by-rule on the methodology page.
| Score | Verdict | Next step |
|---|---|---|
| 0–39 | bad | Potential warning signs detected. Do not enter credentials, payment details, or one-time codes — navigate to the brand yourself in a fresh tab. |
| 40–74 | warn | Potential warning signs detected — verify the sender through a separate channel before clicking or signing in. |
| 75–100 | ok | No major warning signs detected — standard caution still advised; sign in only on sites you reached yourself. |
The five analyzers
All five analyzers share the same banded scale, the same deterministic-rule philosophy, and (where it fits) the same URL pipeline. The signals below come straight from the live src/lib/business/* modules — no claims about signals the code doesn't actually run.
The URL pipeline — host, scheme, path, query, no network calls.
The URL pipeline looks at the host, scheme, path, and query string and folds a weighted set of rules against them. There is no DNS lookup, no fetch, no redirect resolution — exactly so the checker cannot be weaponised into a phishing payload by a malicious link.
Header parsing + body lexicon + per-link fold.
Pasting an email parses From: / Reply-To: / Subject from the headers, scans the body for scam phrasing, and folds each in-message link back through the URL pipeline — so a single terrible link in an otherwise fine email still collapses the score.
Sender shape + body lexicon + per-link fold.
The SMS pipeline reads the sender shape (shortcode / ten-digit mobile / alpha-tag / unknown), keyword slices, and any link present. As with the email checker, a single bad link in the message collapses the score.
URL payload → URL pipeline. Text payload → keyword scoring.
After pngjs + jsqr have decoded the QR on the server, the payload is routed two ways and a transparent chip tells you which — so the QR target lands on the same URL pipeline the /check page already uses, and a non-URL payload gets the SMS-style keyword slices.
OCR text → URL fold + keyword fold + contact-info chip.
The screenshot pipeline is the only one that produces an aiExplanation. It first OCRs the image via the Polsia proxy, then runs the same URL / keyword / contact-info rules against the extracted text. The output includes a paragraph, a confidence number, and three action recommendations.
The AI explanation
The screenshot analyzer is the only one that produces an aiExplanation field. The paragraph is a deterministic template keyed off the score band and the worst fired signal id — so every screenshot result that lands in the same band references the same wording and the same worst-fired signal, not a paraphrase.
The trust-score route on a screenshot returns { paragraph, confidence, actions } — a short paragraph, a confidence number, and three action recommendations keyed off the verdict band.
The confidence number is computed from the distance of the score from 100, shaved for every warn or bad signal fired so a noisy result gets a proportionally lower confidence rating.
100 − |100 − score| − Σ( warn × 3 + bad × 6 ), clamped to [0, 100]The current explanation is a deterministic template, not a model call. We say so on the result itself. A model-driven version is on the roadmap; it will be swapped in once the templates are stable enough to A/B against.
Honest about what the score does not tell you.
Try a verifier
Run a check on a real input and watch the score update as each rule matches.