A BEHAVIORAL FRAUD LAYER FOR THE CRYPTO ON-RAMP
HOW IT WORKS

A checkout session is evidence. Most systems throw it away.

Straja computes fifteen behavioral features from the session itself, sends them for a tier decision, and — only when the pattern warrants it — asks the person four questions a scam script doesn't survive.

THE PATH A SESSION TAKES

From signal to verdict.

01 — CHECKOUT
User confirms amount and destination
02 — SIGNALS
15 behavioral features computed live
03 — MODEL
Signals + context sent for a tier decision
04 — VERDICT
PASS · SOFT · INTERVENE

The model receives only the signal vector and session context — never account identity, never anything beyond what's needed for this one decision.

THE DECISION

Three tiers, not two.

A binary allow/block forces every borderline session into one of two wrong answers. The middle tier is where most real ambiguity lives.

PASS

No additional screens. The user never knows Straja was there. Roughly 98% of checkouts resolve here.

SOFT

One context screen. The user acknowledges and proceeds. No block, no delay.

INTERVENE

A short probe, then a pattern reflected back in the user's own words. A 24-hour hold — never a hard block.

THE PROBE

Four questions that a scam script doesn't survive.

On INTERVENE, Straja asks rather than warns. Warnings don't work on someone who has been coached to expect them and told exactly how to dismiss them — a question has no script to match against.

01
How did you first hear about this opportunity?
02
Where did you get the wallet address you're sending to?
03
Have you successfully withdrawn money from this platform before?
04
Has anyone asked you to keep this private, or told you what to say if someone asks?

A legitimate buyer answers question four with confusion. A coached victim recognizes an instruction they were actually given — and that recognition is the moment the pattern becomes visible to them, not just to the system.

THE SIGNAL VECTOR

Fifteen features, computed before the model sees anything.

Every one is deterministic — derived from the session and the account, never from the model. The model's job is to read the pattern they form, not to invent the evidence.

idle_gaps_over_60s
Pauses long enough to suggest someone is being coached off-screen during checkout.
SESSION
tab_switches
Switches away from the checkout mid-flow — reading instructions somewhere else and coming back.
SESSION
address_entry_method
Pasted, typed, or scanned — a pasted address someone else supplied reads differently than a self-scanned wallet.
SESSION
minutes_to_outbound
How long the crypto sits before being sent onward. Minutes rather than days is the tell.
SESSION
deposit_escalation
The sequence of this account's deposits. A small successful withdrawal, then a large one, is the classic bait-and-scale pattern.
HISTORY
amount_vs_median
This purchase as a multiple of the account's own median. Null on a first purchase, where there is no median to compare against.
HISTORY
is_first_purchase
Whether this account has ever bought before. Changes what every history signal is worth.
HISTORY
destination_first_seen_days
How new the receiving address is to this specific relationship, not to the wider chain.
DESTINATION
destination_type
Fresh externally-owned account, known exchange, contract, or the user's own self-custody wallet.
DESTINATION
merchant_verified
Whether the named recipient is a verified merchant. Null where the destination isn't a merchant at all.
DESTINATION
account_age_days
How long the account has existed at the moment of this purchase.
ACCOUNT
kyc_retries
How many attempts identity verification took — repeated failures suggest documents someone else is supplying.
ACCOUNT
amount_eur
The value of this transaction. Read in context, never as a threshold on its own.
PAYMENT
funding_method
Card, bank transfer, or Apple Pay. Different instruments carry different reversal windows.
PAYMENT
declined_attempts
Failed payment attempts before this one cleared — often someone working through cards that aren't theirs.
PAYMENT
WHAT COMES OUT

Every verdict is already an audit record.

Not a log line written alongside the decision — the decision itself, in the structure a reviewer or a regulator would ask for.

decision recordstructured, timestamped
{
  "decision_id": "d_a619893f",
  "created_at": "2026-09-12T09:41:22.104Z",
  "tier": "INTERVENE",
  "signals": { /* the full fifteen-field vector */ },
  "key_signals": ["idle_gaps + pasted address"],
  "reasoning": "Coached-session pattern: repeated idle gaps...",
  "probe_transcript": [...],        // if any
  "pattern_summary": "...",             // what the user was shown
  "user_outcome": "held",
  "model": "claude-opus-5",
  "prompt_fingerprint": "pf_3c1e"          // which prompt version decided
}

What a compliance team does with this is its own page — see Compliance.