Skip to content
GUILHERME

Fraud intelligence

Aegis

A fraud investigation platform I designed, built, and shipped alone — from the detection rules to the WebGL that renders them.

A Brazilian betting operator needed its analysts to stop reconstructing player histories by hand. I built them the whole thing, with AI assistance: the investigation workflows, the detection engine, the API, the data pipelines, the security model, the deployment, and the WebGL view that renders 25,000 players at once. Aegis takes an analyst from a signal to the evidence behind it without leaving the screen.

Role
Software Developer
Period
April 2026–present
State
Deployed to production
Source
Private

The Aegis entry sequence — 9 seconds, silent

The film opens almost black. A small blue iris, ringed by concentric dashed segments, glows at the centre of a dark shield-shaped dome while faint aurora curtains drift behind it. The iris brightens and its rings pull into focus. The Aegis wordmark rises in brushed metal, the words "fraud intelligence" set smaller beneath it, reflected in the floor. The wordmark dissolves as the camera settles on the emblem, wreathed in light and drifting dust, and the aurora fades to black. There is no sound.

Every investigation started from scratch

An analyst who wanted to understand one suspicious account had to assemble it by hand. Identity and account data lived in the operational database. Deposits, withdrawals, bets, balances, and gameplay events accumulated in the analytical lakehouse. The story of a player existed, but only in pieces, across two systems that were never meant to be read together.

I also wanted the answer to survive scrutiny. A score on its own is useless to someone who has to justify freezing an account, so every finding Aegis produces names the rule that fired and shows the evidence that triggered it.

The path a request takes

Aegis is a static React application talking to a read-focused FastAPI service, and that service reads a curated PostgreSQL schema I designed for investigation. The lakehouse stays out of the request path entirely. That boundary buys a predictable read path and keeps access to sensitive evidence in one place I control.

Scheduled jobs move profiles, wallets, transactions, hourly balances, and visualization data from Databricks into PostgreSQL, then chain straight into detection scans every hour. Redis serves selected first reads: the jobs write it, the interface only reads it.

What a request touches

  1. Investigator UIReact single-page app, served as a static bundle
  2. FastAPI serviceRead-focused JSON API, and the only authorization authority
    1. Curated PostgreSQL schemaWhat the product reads for profiles, findings, and history
    2. Databricks lakehouseAnalytical source, read on a cache miss
    3. Redis cacheOptional, fronts the busiest reads

What keeps that data current

  1. Databricks lakehouseProfiles, wallets, transactions, and hourly balances
  2. Scheduled sync and detection jobsSync, then detection scans, chained hourly
  3. PostgreSQL and cache refreshJobs write; the interface only reads
The Aegis overview screen: a dark console with a Portuguese sidebar, a risk summary counting 25,000 analysed players and 97 with a signal, and a field of faint points with an amber cluster.
The overview, running on 25,000 synthetic profiles. The interface ships in Portuguese.

01 — I made it a separate product

I could have bolted fraud screens onto a system that already existed, and nobody would have argued with me. I built Aegis as its own product instead: its own schema, its own API, its own deployment, its own release cycle.

Two things drove that. Fraud workflows change every time a new pattern shows up, and I wanted to ship those changes without touching anything else. And the evidence behind a finding — documents, transaction history — needs a tighter authorization model than the average internal user should ever inherit.

That decision handed me the entire security surface to own: sessions, CSRF protection, multi-factor authentication, Argon2 hashing, permissions, scoped job credentials, security auditing. I took it. The API is the single authorization authority.

02 — I stopped querying the lakehouse on every click

The event data lives in the lakehouse, and pointing the interface straight at it would have been the fastest route to a working dashboard. It would also have chained every step through a player timeline to warehouse latency and a billing meter.

So the data path splits. Scheduled jobs copy what the product needs into the curated schema, an hourly pipeline runs sync and then scan, and Redis absorbs the reads that repeat.

Aegis therefore reads recent data rather than live data, and I made that call deliberately. The behaviour I am detecting — structuring, velocity, repeated documents — develops over hours and days. Freshness I did not need was not worth the latency I would have paid for it.

03 — I followed the analyst's actual path

A dashboard tells you a number is high. That is where its job ends and the analyst's job starts, which is exactly the wrong place to stop. Aegis follows the path someone actually walks: a triage queue grouped by rule, opening into a player view that holds profile, balances, transactions, gameplay, open findings, and generated reports in one place.

Every finding carries its rule, category, confidence level, and the evidence that triggered it. Rules run in shadow mode by default and get promoted to live on purpose, never by accident. Findings an analyst is actively working sit in a browser-local worklist.

Then there is the Risk Constellation. I render the whole scored population as a GPU point field, with colour and brightness for risk and position to pull flagged players out of the crowd. It started as a question about whether 25,000 players could be legible at once. It turned out clusters and outliers are far easier to see than to query.

A player investigation screen showing a monitored player's balances and deposit totals, a risk score of 35 rated high confidence, tags for the rules that fired, and an expanded deposit-structuring finding listing the deposit counts and amounts that triggered it.
A finding opened to its evidence. Every value here, including the document number, is synthetic.
The Risk Constellation: a wide, dark field of thousands of faint points with a bright amber cluster, beside a panel breaking 25,000 analysed players into critical, high, medium, low, and no-signal tiers.
25,000 synthetic players placed by risk, in colour and brightness.

04 — I made an internal tool worth looking at

Internal tools look like internal tools because someone decided nobody would mind. I minded. Aegis got a shield-and-iris emblem, a dark console, and a cinematic entry sequence, and that identity holds from the first frame through to the investigation workspace.

I modelled and animated the emblem in Blender, exported it as FBX, assembled and lit the scene in Unreal Engine 5, rendered a 4K image sequence, and graded the film in DaVinci Resolve. That is not a normal thing to do for a fraud console. I wanted to find out whether I could.

None of it gets in the way of the work. The sequence plays once per session and fails open: if the media stalls, cannot play, or the user prefers reduced motion, the console is simply there.

What I built

Aegis is mine end to end. The product and interaction design. The React application, the FastAPI service, authentication, permissions. The PostgreSQL model, the lakehouse synchronization, the hourly pipeline, the detection rules, the scoring, the reports. The tests, the deployment, the WebGL Risk Constellation, and the identity film.

I work AI-native and I am not shy about it: agents accelerated scaffolding, refactoring, test generation, and review. Every architectural decision, every trade-off, and every judgment about whether something was actually good enough stayed mine.

What shipped

I shipped Aegis to production. Eight configurable rules across payment, gameplay, identity, and impact categories; shadow and live execution; scoring and explainable findings; alert triage; player investigation; a browser-local worklist; rule administration; geographic analysis; the Risk Constellation; security auditing; and reports exported as HTML, Markdown, or PDF.

The alerts triage queue, grouped by rule: duplicate document, incomplete identity checks, deposit structuring, promotional-credit volume, and two operator-impact rules, each with its rule code, category, alert count, and maximum score, next to an empty evidence panel inviting the analyst to select an alert.
The triage queue. Selecting an alert opens its evidence panel, empty in this capture.

What it is built with

React, Vite, and React Router deliver the interface. FastAPI exposes the read API. PostgreSQL owns the investigative model, Databricks stays the analytical source, and Redis backs selected cache-first reads. Opaque sessions, Argon2, TOTP, CSRF protection, and API-enforced permissions hold the security boundary.

Three.js and a Web Worker point decoder drive the Risk Constellation. deck.gl and MapLibre handle geographic analysis. WeasyPrint generates the reports. pytest and Jest cover backend and frontend paths. Blender, Unreal Engine 5, and DaVinci Resolve produced the identity film.