DEV Community

Cover image for Bashi: a shop credit book on FalkorDB that shows its work
Sire Adell
Sire Adell

Posted on

Bashi: a shop credit book on FalkorDB that shows its work

Bashi is a credit book for any business that sells on credit, from a corner shop to a wholesaler with hundreds of accounts. When a customer asks to buy on credit, it answers YES, NO or CANNOT TRACE, and gives a receipt that links the exact sales, payments and promises behind the answer. It runs on a FalkorDB graph, and I built it for the FalkorDB Graph Hacks.

I built it because my own shop's ledger said customers owed N388,340 that they had already paid.

On 17 July 2026 I ran a read-only audit on my own shop's records. Eight sales were marked fully paid, yet the customers' account ledger still showed debt. N388,340 in total. Nobody stole anything and nobody was careless. One payment updates two records, the sale and the ledger, and one of them can lag or fail. Each screen looked right on its own, so nobody noticed.

I fixed the cause. On 15 October I ran the same kind of check again on 494 sales and 46 credit accounts. Three accounts still had two records that disagree, N15,510 in total. Much smaller, but not zero. That is why I built Bashi, for the FalkorDB Graph Hacks.

Ten seconds at the till

A customer asks for N45,000 of goods on credit. You flip the book, try to remember whether he kept his last promise, then say yes or no and hope. Bashi answers YES, NO or CANNOT TRACE, and hands back a receipt that names the exact sales, payments and promises behind the answer.

Live site, no sign-up: https://bashi-vrfv.onrender.com
Video: https://youtu.be/m4gcgUnqMD0
Code: https://github.com/Sireadell/bashi

Why a graph and not a balance

A credit book looks like a list. The trouble starts when a question crosses the list: which payment settled which sale, and did this customer keep his promise?

A balance check adds up what a customer owes and stops there. It can't tell which sale a payment cleared, and it has no idea about a broken promise.

In a graph the connection is the data, so I used FalkorDB. A payment is linked to the sale it settles. A customer is linked to each promise they made and, if the date passed unpaid, to the one they broke. Open debt is the sales a customer made minus the payments linked to them. The answer is a walk from the customer to their sales, to the payments, to the promises, and I can show the walk.

The what-if button is where FalkorDB did something I'd have hated to build by hand. It has a command, GRAPH.COPY, that copies the whole graph in one go. Bashi copies the shop, deletes one record on the copy, asks the same question again, then deletes the copy. For my practice customer Tunde the answer flips from NO to YES the moment his broken promise is removed. So you can see which single record decided it. The real data is never touched.

If I switch FalkorDB off, Bashi answers nothing. There is no second copy of the data to fall back on.

What the receipt shows

Tunde Adeyemi is an invented customer in my practice shop. His limit is N60,000 and he owes N10,000. He asks for N45,000. On money alone he fits, since N10,000 plus N45,000 is N55,000. Bashi still says no.

Every receipt has a picture. The decision sits at the top, then the customer, then his sales, the payments that settled them and his promises. Promise PR001 is outlined in red and marked BROKEN, because its date passed with the money still owed. That one promise is the whole reason.

The yes or no comes from three fixed rules, and no AI model makes it:

  1. Say NO if open debt plus the new request is over the credit limit.
  2. Say NO if the customer has any broken promise to pay.
  3. Say NO if this account and every account linked to it through buyers, collectors and family owe more than the limit once the new request is added. Bashi follows those links up to 20 steps deep.

The third rule is where the graph earns its keep. An invented customer asks for N40,000 and owes nothing on their own account, so a balance check says yes. Bashi follows seven links through the people who buy and collect for them, finds five linked accounts owing N100,000 between them, and says no.

My own audit, run through it

This is the part I care about most. In my audit, the ledger said one customer owed N343,210. A plain balance check reads that number, sees it is large, and says NO to any new credit.

Bashi walked from each of that customer's open sales to their payments and found three payments, N224,960, N47,500 and N70,750, recorded but never linked to the sales they paid. They add up to exactly N343,210. After linking them, the customer owed N0 and the answer became YES. Across all four customers in the audit, that is 8 of 8 sales flagged, N388,340 in total.

One honest limit. The amounts and sale dates come from my audit, but in the demo the payment records are rebuilt from it and their dates are assumed. So it shows what Bashi does with records shaped like my finding. It doesn't prove those customers paid.

I also loaded my whole shop, names removed: 45 customers, 544 credit sales and 543 payments. None of the payments was tied to a sale in my books. Bashi matches them by rule, marks every match as inferred, and keeps the rule's choice visible.

Can anyone change the books quietly?

Every answer carries a fingerprint, a hash of every record it read plus the verdict and the request. Edit one record later and the check fails.

You can try it yourself on the /proof page: https://bashi-vrfv.onrender.com/proof. Pick a receipt, press "Change one digit, then check", and watch it fail. It runs on a throwaway copy of the shop, so nothing real is touched and the copy is deleted straight after. I also ran 11 different edits in a test, and all 11 were caught, and each passed again once undone.

I should be straight about the limit. Someone who can write to the database can rewrite an answer and its fingerprint together, and the check would pass. So I call it tamper-evident, not tamper-proof.

The test I couldn't fudge

I wrote 55 credit cases around the situations Bashi exists for, with the correct answers worked out by plain arithmetic. I locked the answers with a hash and pushed it before running anything.

On the first run Bashi got 51 of 55, because my matching rule refused customers who had paid a deposit before the sale. I changed that one rule. That makes the second run a fix, not a fair exam, so I built a new set of 200 cases from a fixed seed, locked its hash first, and didn't touch the rules afterwards.

Across all 255 cases, Bashi wrongly approved 0 customers. A plain balance check wrongly approved 53: 14 of the first 55 and 39 of the next 200.

I also gave an AI model, Gemini Flash Lite at temperature 0, the same 200 cases as a flat list of sales, payments and promises with the same rules, just no links. It got 152 right and wrongly approved 23, worth N3,685,003 of credit. Bashi got 200 right. In fairness, the AI spotted every broken promise. Its misses were reading and arithmetic slips. But that is the point for a shop: the same records, read without the links, give answers you can't rely on.

I then locked 30 family-network cases, with chains up to 22 links. Bashi got 30 of 30. Checking only the asking account wrongly approved 11. The same AI, given the same records without the graph, got 19 of 30.

The caveat is real. The 200 are generated from templates, so they vary amounts, dates and mixes of situations, not the kinds of situation. I wrote both the cases and Bashi. Tidy cases aren't real shops. And Bashi can't record a reversed or refunded sale yet.

Other tools can ask it too

Bashi speaks MCP, a standard way for AI tools to call other tools. The address is https://bashi-vrfv.onrender.com/mcp and it has five tools: decide credit, get a receipt, verify a decision, run a what-if, and list customers. Cursor can connect to that address directly. One call, no sign-up, returns the answer, the reason, the records used and a link to re-check it. The exact command is in the README.

What it is not

It isn't tamper-proof. It isn't a smart credit score. The plain-words box can pick which lookups to run and word one reply, but it never makes the call, and every number in its reply is checked against the records first. It isn't a full set of real data: the audit sales are real with names removed, and credit limits are assumed.

Next

I want to run it on my shop's live books. You can already load your own records from three CSV files into your own FalkorDB, without sending anything to the public demo.

Try it, break it, and tell me where the answer looks wrong.

Top comments (0)