<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Martins Chibueze</title>
    <description>The latest articles on DEV Community by Martins Chibueze (@martins808).</description>
    <link>https://dev.to/martins808</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4093973%2F19af619f-dd7b-42a4-928a-5a10db2a684d.jpeg</url>
      <title>DEV Community: Martins Chibueze</title>
      <link>https://dev.to/martins808</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/martins808"/>
    <language>en</language>
    <item>
      <title>"Fingerprint, iris, or voice: which biometric fails first, and why fusion saves you"</title>
      <dc:creator>Martins Chibueze</dc:creator>
      <pubDate>Thu, 15 Oct 2026 16:36:22 +0000</pubDate>
      <link>https://dev.to/martins808/fingerprint-iris-or-voice-which-biometric-fails-first-and-why-fusion-saves-you-dnf</link>
      <guid>https://dev.to/martins808/fingerprint-iris-or-voice-which-biometric-fails-first-and-why-fusion-saves-you-dnf</guid>
      <description>&lt;p&gt;Biometric systems feel unbeatable - until you realize every single one of them can actually fail at one point just on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fingerprint Recognition
&lt;/h2&gt;

&lt;p&gt;When a finger is placed on the sensor, the image is captured and converted to grayscale, and if there is noise (that's dust or dirt), the use of Gaussian or Median filtering (both are filtering techniques) is done which preserves ridge edges. The Contrast is then enhanced using Global Histogram Equalization and refined using CLAHE (Contrast Limited Adaptive Histogram Equalization), so the ridges become more distinct from valleys, especially in areas that were originally low-contrast, while the overall appearance remains natural.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhm86gpnr1aujjvnfcjau.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhm86gpnr1aujjvnfcjau.png" alt="Figure 1.1–2×2 deliverable grid: (a) Original fingerprint, (b) Noisy version with simulated salt-and-pepper noise, © Median-filtered result, (d) Final CLAHE-enhanced image." width="800" height="414"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1.1–2×2 deliverable grid: (a) Original fingerprint, (b) Noisy version with simulated salt-and-pepper noise, © Median-filtered result, (d) Final CLAHE-enhanced image.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fingerprint Minutiae Extraction
&lt;/h2&gt;

&lt;p&gt;These are the actual biometric features being extracted used for matching minutiae points - specifically ridge endings and bifurcations (points where a ridge splits into two). These discrete points, not the whole image, are what gets compared during fingerprint matching. Morphological thinning (cv2.ximgproc. thinning-Otsu's method) is then applied which reduces ridges to a 1 pixel-wide skeleton (finds the best threshold that separates the dark ridges from the light background.) and after that the Crossing Number (CN) algorithm is applied to every ridge pixel, where every part on the fingerprint image (Minutiae) the ridge end is identified in the CN as 1 (ridge ending) and anywhere the ridge divides into two, it is identified in the CN as 3 (bifurcation).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8m7os4zg32ghnu1287jb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8m7os4zg32ghnu1287jb.png" alt="Figure 2.2 - Corrected minutiae map, after casting neighbour pixels to signed integers. Red markers indicate ridge endings; blue markers indicate bifurcations." width="800" height="421"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2.2 - Corrected minutiae map, after casting neighbour pixels to signed integers. Red markers indicate ridge endings; blue markers indicate bifurcations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The system can have failures. Some of its failure modes are:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;· Dry/worn fingers: When the skin is very dry, cracked, or heavily worn (manual workers, elderly people), the ridges become faint or broken, the system misses real minutiae, or invents false ones from the cracks and noise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;· Spoofing: Someone makes a fake fingerprint (silicone, gelatin, 3-D printed, etc.) and places it on the sensor. If the system only looks at the ridge pattern and does not check for signs of real skin (liveness detection), it can be fooled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;· genuine/imposter inversion: Normally we are supposed to have just&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I downloaded 5 genuine and 5 imposter fingerprint images sourced from FVC2004 DB2_B, a publicly available academic fingerprint verification dataset containing 10 distinct fingers with 8 separate impressions (scans) of each finger.     &lt;/p&gt;

&lt;p&gt;This structure makes it possible to build genuine pairs (two different real scans of the same physical finger) and imposter pairs (scans from two different fingers). A batch script was written to automatically process every image in the dataset folder through a pipeline (binarize → thin → Crossing Number minutiae detection), summarize each fingerprint's minutiae into a fixed-length feature vector, and compute distances for 5 genuine pairs and 5 imposter pairs automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It seems the images weren't the best quality, which caused problems - their boundaries got mixed up. In short: the system starts trusting strangers more than the real owner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz91olmxiw64au6xlm9ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz91olmxiw64au6xlm9ys.png" alt="fingerprint images sourced from FVC2004 DB2_B" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;fingerprint images sourced from FVC2004 DB2_B&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftjw4b3po15tqhgknuer0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftjw4b3po15tqhgknuer0.png" alt="Figure A.5 - Strip plot of all 10 real distance scores. Green = genuine pairs, red = imposter pairs. The shaded orange band marks the region of direct overlap between the two&amp;nbsp;classes." width="800" height="482"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure A.5 - Strip plot of all 10 real distance scores. Green = genuine pairs, red = imposter pairs. The shaded orange band marks the region of direct overlap between the two&amp;nbsp;classes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In biometrics we talk about two kinds of comparisons:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;· Genuine = same person (should get a high match score)&lt;/li&gt;
&lt;li&gt;· Imposter = different person (should get a low match score)
Inversion means the system has the scores the wrong way round:
&amp;nbsp;an imposter ends up with a higher score than a genuine pair.
This is a catastrophic failure mode. It means the matcher is not just inaccurate - it is systematically ranking the wrong people as more similar.
It can be caused by:&lt;/li&gt;
&lt;li&gt;· very bad quality images,&lt;/li&gt;
&lt;li&gt;· incorrect normalisation of scores,&lt;/li&gt;
&lt;li&gt;· bugs in the matching algorithm,&lt;/li&gt;
&lt;li&gt;· or (as in your lab finding) something going wrong in the extraction or comparison pipeline that flips the expected behaviour.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Iris recognition
&lt;/h2&gt;

&lt;p&gt;Unlike fingerprints, the iris is a circular "doughnut" shape located between the dark pupil and the white sclera. So, we localize the iris (find the pupil and iris boundaries) and normalize it - transforming the ring-shaped region into a fixed-size rectangle using Daugman's Rubber Sheet Model, so that two captures of the same eye compare consistently regardless of pupil dilation or eye rotation. (Meaning the distance from the outer boundaries of the pupil to the outer boundaries of the iris so as a doughnut circle all iris is gotten through their, its then being cut at a side and stretch to a rectangle).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffk3f5hleb92wobybttw9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffk3f5hleb92wobybttw9.png" alt="Figure 3.5 — Correct localization on eye3.jpg: red circle tightly bounds the pupil, green circle correctly follows the iris/sclera boundary, both properly concentric." width="800" height="429"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3.5 - Correct localization on eye3.jpg: red circle tightly bounds the pupil, green circle correctly follows the iris/sclera boundary, both properly concentric.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fossa729vbrpit9bfm6ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fossa729vbrpit9bfm6ri.png" alt="Figure 3.6 - Correct normalized iris strip for eye3.jpg. The radial, fibrous iris texture is visible consistently across the width of the strip - the expected output of Daugman's Rubber Sheet&amp;nbsp;Model." width="800" height="424"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3.6 - Correct normalized iris strip for eye3.jpg. The radial, fibrous iris texture is visible consistently across the width of the strip - the expected output of Daugman's Rubber Sheet&amp;nbsp;Model.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Iris recognition has extreme uniqueness: statistically, the probability of two independently formed irises matching is virtually zero - even identical twins have completely different iris patterns. Unlike fingerprints, which wear down, or faces, which age noticeably, internal iris patterns form during the pre-fetal period and remain stable from about one year of age onward. They're also resistant to spoofing because modern systems use liveness detection (analyzing pupillary light reflexes or multi-spectral illumination) to prevent attacks using high-resolution printed photos or artificial contact lenses.&lt;/p&gt;

&lt;p&gt;It does still have weaknesses: eyelashes or eyelids can block part of the iris, and bright ambient lighting, stray reflections, or glare from eyeglasses can wash out critical detail or blind the sensor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Voice biometrics
&lt;/h2&gt;

&lt;p&gt;Voice biometrics (speaker recognition) is a behavioral and physiological biometric. Unlike a fingerprint or iris image, voice is a 1D signal that changes over time - the shape of a person's vocal tract filters air from the lungs into unique resonant frequencies. And the use of Mel-Frequency Cepstral Coefficients (MFCCs), the standard feature set representing the unique "timbre" of a human voice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07rfnpbng4qd3w3afbdb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07rfnpbng4qd3w3afbdb.png" alt="Figure 4.2 - Raw audio waveform of a spoken phrase, showing amplitude over roughly 9&amp;nbsp;seconds." width="800" height="421"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4.2 - Raw audio waveform of a spoken phrase, showing amplitude over roughly 9&amp;nbsp;seconds.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I recorded audio from my phone and converted it to a waveform using an audio converter, since it needs to be in WAV format to work. The waveform shows five distinct amplitude bursts separated by near-silent stretches, consistent with five separate spoken words in the test phrase, each showing the expected spike-and-decay pattern of natural speech.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi2y69j9zf27e3ejpccsh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi2y69j9zf27e3ejpccsh.png" alt="Generated spectrogram by STFT(Short-Time Fourier Transform)" width="800" height="389"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Generated spectrogram by STFT(Short-Time Fourier Transform)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The spectrogram (visual representation of how the frequency content of the sound changes over time.) is then generated by the STFT, the image shows frequency energy concentrated in the lower bands with harmonic structure aligned to the voiced segments, typically in the 0–4000 Hz range for human speech. After the spectrogram, the pipeline continues to MFCCs (Mel-Frequency Cepstral Coefficients) where the spectrogram is passed through a Mel filterbank (which tries to mimic how the human ear perceives frequency), which results in a compact set of numbers (13 coefficients for every audio frame). These 13 numbers per audio frame form a matrix that acts as a voice biometric template. Each row of the resulting matrix represents one MFCC coefficient, with color indicating its value across time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqnjxqo0ek3fb1shoyrj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqnjxqo0ek3fb1shoyrj0.png" alt="MFCC (Voice Biometric Template)" width="800" height="384"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;MFCC (Voice Biometric Template)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Even though voice recognition is very good, it still has weaknesses: accuracy decreases with background noise, replay attacks, and changes in voice caused by illness or fatigue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fusion
&lt;/h2&gt;

&lt;p&gt;Recall the fingerprint inversion - imposter scores landing where genuine scores should be, and vice versa. Bringing in a second modality corrects it, and because the fused score averages fingerprint and voice together, this strong, cleanly-separated voice signal pulled every fused genuine score down and every fused imposter score up - correcting the fingerprint modality's backwards ordering entirely. In other words, real captured data demonstrated, without needing to be engineered or assumed, that a strong modality can compensate for and correct a weak one when combined through score-level fusion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe5vz3nxb9pl57qykglbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe5vz3nxb9pl57qykglbs.png" alt="Strip plot comparing Fingerprint alone, Voice alone, and the Fused result. The bottom row (Fingerprint) shows visible overlap between green (genuine) and red (imposter) dots. The top row (Fused) shows the two-color groups pulled apart into distinct&amp;nbsp;clusters" width="799" height="505"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Strip plot comparing Fingerprint alone, Voice alone, and the Fused result. The bottom row (Fingerprint) shows visible overlap between green (genuine) and red (imposter) dots. The top row (Fused) shows the two-color groups pulled apart into distinct&amp;nbsp;clusters&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: no single trait is foolproof; fusion isn't about "more security", it's about one modality catching what another misses.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>biometrics</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>“How cross-border money laundering hides in graph data — a Neo4j walkthrough”</title>
      <dc:creator>Martins Chibueze</dc:creator>
      <pubDate>Mon, 31 Aug 2026 03:38:32 +0000</pubDate>
      <link>https://dev.to/martins808/how-cross-border-money-laundering-hides-in-graph-data-a-neo4j-walkthrough-235</link>
      <guid>https://dev.to/martins808/how-cross-border-money-laundering-hides-in-graph-data-a-neo4j-walkthrough-235</guid>
      <description>&lt;p&gt;Using Neo4j to track money laundering, have you ever wondered how money laundering works? And why we shouldn’t use tables in tracking them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule-Based Transaction Monitoring Systems
&lt;/h2&gt;

&lt;p&gt;The dominant approach in AML compliance today is rule-based transaction monitoring, in which compliance teams define fixed rules that are evaluated against each incoming transaction. When a transaction matches a rule, an alert is generated and routed to a human analyst for review. In the normal banking system, they mostly use a role-based system for tracking money laundering, for example like “if money sent is &amp;gt; than $10,000 - Flag an alert”, which could raise a very much number of false alerts and routed to a human analyst for review.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Graph Database Approach
&lt;/h2&gt;

&lt;p&gt;The central innovation of RegTech AML is the use of a native graph database — specifically Neo4j — as the foundation for detection, rather than a relational database or a rule engine operating on isolated transaction rows. A relational database stores data in rows and columns. Finding relationships between entities requires joining multiple tables — an operation whose computational cost grows exponentially as chain depth increases. A query asking "find all entities connected to Person X through four or more intermediate companies" requires four successive table joins, each of which multiplies the data volume to be scanned. In a database containing millions of accounts and transactions, such a query is impractical in real time. As Napier AI (2024) notes: "Unlike relational databases which store data in rows and columns, graph databases excel in representing networks of entities and the dynamic relationship between them." Neo4j's native graph storage materialises joins as edges, allowing complex relationship queries to run in milliseconds rather than minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Detection Patterns
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Shell Company Layering:&lt;/strong&gt;&lt;br&gt;
Shell Company layering is line of ownership, that ends up owning itself, for example like Company A owns Company B, Company B owns Company C, Company C owns Company D, Company D owns Company E then Company E owns back Company A, so that what makes it shell layering, A Company shouldn’t own’s its self-that’s a red flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circular Flows:&lt;/strong&gt;&lt;br&gt;
Circular Flows is similar to the shell layering rounding, but it deals mostly with transaction, when the Account A transfers to Account B, Account B transfers to Account C, Account C transfers to Account D, Account D transfers to Account E and Account E transfers back to Account A, this is where the red flags lies, it’s should go back to itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rapid Pass-Through:&lt;/strong&gt;&lt;br&gt;
Rapid pass-Through is when Account A, Account B, Account C, Account D, Account E all send money to Account X(hub account), Then Account X sends all the money to five other Account retaining  less than 5% in the it’s account and all the transaction occurs within 1 hour, and that the red flag , because a company is supposed to retain some money in their account maybe for purchasing of goods and maintenances within Company, as long as All these transaction moves fast within an hour and  still leaves less than 5%( account left empty ) that’s the problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  Graph Visualization
&lt;/h2&gt;

&lt;p&gt;Neo4j Browser provides native graph visualization of query results, rendering nodes as labelled dots and relationships as directional arrows. The following queries are optimised to produce visual graph outputs (rather than tabular results) for the purposes of demonstration:&lt;br&gt;
So, this is the step-by-step process of visualization using Neo4j(Query)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 1 — SHOW THE ENTIRE DATABASE AS A GRAPH:&lt;/strong&gt; it shows ALL nodes and relationships as a visual network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvun5fce73d8knferh86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqvun5fce73d8knferh86.png" alt="Full network view — all nodes and relationships" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 2 — SHOW THE DATABASE SCHEMA (node types + relationship types):&lt;/strong&gt; This shows the blueprint of the database — what types of nodes exist and how they are connected, without showing actual data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="k"&gt;CALL&lt;/span&gt; &lt;span class="n"&gt;db.schema.visualization&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzzldhdocmqtqdyf5kpo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzzldhdocmqtqdyf5kpo.png" alt="Database schema visualization " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 3— SHELL LAYERING: Show the circular ownership loop as a GRAPH:&lt;/strong&gt; Returns the shell company chain as a visual path — dots connected by arrows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:OWNS&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;if an entity(company) owns any other entity(Company) from two to six and still owns back it’s self.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3p7t1jkxlrgaubfiwoe4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3p7t1jkxlrgaubfiwoe4.png" alt="Shell layering circular loop — graph view" width="799" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 4 — CIRCULAR FLOW: Show the money loop as a GRAPH:&lt;/strong&gt; Returns the 5-account circular flow as a visual ring of dots and arrows.  ACC-CIRC-A → B → C → D → E → (back to A)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;a:&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:TRANSFERRED&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff1ohqwitsuxi8k6lvbob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff1ohqwitsuxi8k6lvbob.png" alt="Circular flow money loop — graph view" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 5 — RAPID PASS-THROUGH - Show the hub and its connections as a GRAPH:&lt;/strong&gt; Returns the hub account with all its inbound and outbound connections.   a star shape — many sources feeding into hub, hub feeding many destinations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;src:&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r1:&lt;/span&gt;&lt;span class="n"&gt;SENT&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;tIn:&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r2:&lt;/span&gt;&lt;span class="n"&gt;RECEIVED_BY&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;hub:&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;account_id:&lt;/span&gt;&lt;span class="s2"&gt;"ACC-HUB-001"&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tIn&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;inbound&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;sentRels&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;receivedRels&lt;/span&gt;
&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r3:&lt;/span&gt;&lt;span class="n"&gt;SENT&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;tOut:&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r4:&lt;/span&gt;&lt;span class="n"&gt;RECEIVED_BY&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;dst:&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;hub&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inbound&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tOut&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;outbound&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;sentRels&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;receivedRels&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;outSentRels&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;
       &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r4&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;outReceivedRels&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F16upsq0jaa166lh7ieri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F16upsq0jaa166lh7ieri.png" alt="RAPID PASS-THROUGH — many sources feeding into hub, hub feeding many destinations." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 6 — SHOW ONLY THE SHELL COMPANY NETWORK (Entity nodes + OWNS relationships):&lt;/strong&gt; This is the clean view of just the ownership structure, this explains Shell layer quite well, because in shell layering the Company A owns Company B, Company B owns Company C and Company C owns back Company A which hides the actual owner, but when the actual owner is then tracked, the entity is then known as UBO (Ultimate Beneficial owner) of all the Companies all together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;e:&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r:&lt;/span&gt;&lt;span class="n"&gt;OWNS&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;UBO_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;e2:&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e2&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhicx7trsmjdrejtp88zy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhicx7trsmjdrejtp88zy.png" alt="One entity's full network UBO(Ultimate Beneficial owner) — graph view" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 7 — SHOW MONEY FLOW (Accounts + Transactions only):&lt;/strong&gt; Shows only the financial movement — accounts as dots, transactions as nodes, this is still the rapid pass-through pattern and within the Transaction node the timestamp contain the actual time the money was sent or received, used to check if all the transaction all together was within one hour, that’s why by right of the screenshot, this is a line of transaction, which the time the money was sent and the time money takes more than an hour, which is normal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;src:&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;s:&lt;/span&gt;&lt;span class="n"&gt;SENT&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;t:&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;rb:&lt;/span&gt;&lt;span class="n"&gt;RECEIVED_BY&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;dst:&lt;/span&gt;&lt;span class="n"&gt;Account&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rb&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukkq4cppdtfhgsij8f97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fukkq4cppdtfhgsij8f97.png" alt="Money flowwhich reveal if it’s a rapid pass through" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIZ 8 — SHOW FULL NETWORK FOR ONE SPECIFIC CRIMINAL (Victor Osei):&lt;/strong&gt; This shows everything connected to Victor — his shell companies, accounts, transactions and  showing how the graph reveals the full picture of one criminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="py"&gt;Query:&lt;/span&gt; &lt;span class="k"&gt;MATCH&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;v:&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;name:&lt;/span&gt;&lt;span class="s2"&gt;"Victor Osei"&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="ss"&gt;;&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7g3ai9k1d7xphvar3kmv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7g3ai9k1d7xphvar3kmv.png" alt="Full Network of a specific criminal (Victor Osei) both transactions and Ownership" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Reduces False Positives
&lt;/h2&gt;

&lt;p&gt;Rule-based systems flag on single-transaction thresholds with no context, for example: if money sent &amp;gt; $10,000; flag an alert, there will be lots of alerts (false positives) but with the graph pattern, it give structural red flag for example: if there is a loop in the ownership, which is not supposed to be (which is against the rules  Abnormal) or a loop of transaction that also look abnormal too and also if there is a rapid transfer of money from different account to a single hub account which transfers the money to all other accounts just "5%" (percent is redundant with the % sign) of the money that’s very abnormal, and with the graph pattern a single node like an entity could store attribute like if KYC(know your consumer) is verified,  if the entity is a PEP(Politically Exposed Person), if the country the transaction was made, or transferred to is on the gray list or black list, all these sum up to raise a red flag. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risk Signal&lt;/th&gt;
&lt;th&gt;Points Added&lt;/th&gt;
&lt;th&gt;Rationale&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Country on FATF BlackList&lt;/td&gt;
&lt;td&gt;+50&lt;/td&gt;
&lt;td&gt;Highest-risk regulatory environment; non-cooperation with global AML standards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Country on FATF GreyList&lt;/td&gt;
&lt;td&gt;+25&lt;/td&gt;
&lt;td&gt;Under active international monitoring; limited beneficial ownership disclosure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Circular ownership loop detected&lt;/td&gt;
&lt;td&gt;+40&lt;/td&gt;
&lt;td&gt;Structurally impossible in legitimate business; definitive shell indicator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KYC status not Verified/Pending&lt;/td&gt;
&lt;td&gt;+20&lt;/td&gt;
&lt;td&gt;Identity not confirmed; basic due diligence not completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PEP flag (Politically Exposed Person)&lt;/td&gt;
&lt;td&gt;+15&lt;/td&gt;
&lt;td&gt;Elevated corruption risk by regulatory definition&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The combined score determines the disposition:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Score Range&lt;/th&gt;
&lt;th&gt;Disposition&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0–29&lt;/td&gt;
&lt;td&gt;CLEAR&lt;/td&gt;
&lt;td&gt;Transaction proceeds normally; no investigator action required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30–59&lt;/td&gt;
&lt;td&gt;MONITOR&lt;/td&gt;
&lt;td&gt;Logged automatically; analyst reviews at next scheduled triage cycle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60 and above&lt;/td&gt;
&lt;td&gt;ESCALATE&lt;/td&gt;
&lt;td&gt;Immediate manual review; Suspicious Activity Report (SAR) may be filed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The near-miss validation results demonstrate the effectiveness of this approach. For example: Hartfield Logistics Ltd — a verified UK holding company with a KYC-compliant three-tier structure — scores zero (CLEAR), despite making a USD 250,000 intercompany transfer. The shell network, by contrast, scores 85 (ESCALATE): Cayman Islands GreyList (+25), circular ownership loop (+40), KYC Pending (+20). Same structural complexity; completely different treatment. This is the mechanism behind the reported 0% false positive rate across all three near-miss validation cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ”names are from a synthetic dataset used for coursework"&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;Graph databases don't replace compliance teams, but they surface the shape of laundering that row-by-row rules miss entirely.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>datascience</category>
      <category>aml</category>
      <category>neo4j</category>
    </item>
  </channel>
</rss>
