← The Workshop Floor

StokvelOS

Rotating savings, made legible

A stokvel is not a bank. It is a trust community with written rules — so the software's job is transparency, and most fraud dissolves before it becomes fraud.

12 commits
2026-03-01 → 2026-03-18
TypeScript 90.1%
stokvelos.co.za
The problem

South Africa's stokvels — rotating savings groups — are run on WhatsApp threads, paper ledgers and shared spreadsheets. The chairperson tracks who paid, calculates penalties from a handwritten constitution, chases fifteen to thirty people individually, and settles disputes with no record to point at.

The build was triggered by a specific failure: a teachers' stokvel lost money because two members paid into a closed account, nobody reconciled, and three months passed before the gap was found. There was no audit trail, so there was no way to tell error from theft.

That framing set the product. The problem was never missing money. It was missing transparency — and those need different software.

5 decisions

What the constraint forced.

Each of these is a choice with a reason attached. The reason is the part worth reading — a stack list tells you what was used, and nothing at all about the judgment that put it there.

  1. 01

    Read the constitution once with a model. Enforce it forever without one.

    Each group uploads its own written constitution. A model reads it a single time and extracts the rules — contribution amounts, due dates, penalty schedules, payout order — into structured data. From then on enforcement is ordinary TypeScript running against those rules, with no model in the loop. The cost per transaction goes to effectively zero and, more importantly, enforcement becomes deterministic: the same input produces the same penalty every time, which is the only version a group will trust.

  2. 02

    The members are not on the web app, and were never going to be.

    The dashboard is used by the chairperson. Everyone else interacts entirely through WhatsApp — payments, loan requests, balance checks, disputes, proof-of-payment photographs — inside the application already on their phone. Building the web app first and discovering this is a common and expensive route to the same conclusion.

  3. 03

    Cache the constitution in the prompt, not just in the database.

    The parts of the context that never change turn-to-turn — the constitution, the extracted rules, the member roster — sit in the prompt cache. The first message from a group in a window pays full price; everyone after that pays a fraction. In a thirty-member group that is the difference between a daily AI cost that kills the pricing and one that disappears into it.

  4. 04

    Never trust the balance field.

    The stored total is a cached number and cached numbers go wrong. Fraud detection ignores it completely and derives the balance from first principles — sum every confirmed contribution, subtract every paid payout — then compares. A divergence past both a relative and an absolute floor is a critical alert. Deriving the check from source truth rather than from the summary is the whole technique; it is also how a discrepancy gets caught in a day instead of a quarter.

  5. 05

    Give the mediating agent a position, not a personality.

    The dispute agent's instruction is not "be helpful". It is that it takes nobody's side and protects the group's trust — warm, respectful, ubuntu-centred. And before it says anything, an automated investigation compares the claim against the financial record. Most disputes are "I already paid", and most are settled by the records alone; the model's job is to explain what the ledger shows, not to adjudicate.

What generalises

The part that survives the build.

Use a model to convert, not to operate.

The pattern that made this build affordable — parse the ambiguous human artefact once into structured rules, then run deterministic code against the structure — generalises to almost every "AI-powered" product with recurring per-user cost. Ask what is genuinely novel per transaction. Usually it is much less than the architecture assumes.

An audit trail is a social feature.

The technical description is an append-only log. The actual function is that a group can disagree about a payment without anyone having to be called a liar. The design goal was not fraud prevention; it was making disputes boring.

A cached aggregate is a claim, and something has to check claims.

Any denormalised total will eventually diverge from the rows it summarises — a failed transaction, a partial rollback, a migration. Software that treats the summary as truth cannot detect this at all. The reconciliation job is not an optional extra; it is the thing that makes the summary safe to use.

The record

Built with

  • Next.js
  • TypeScript
  • Supabase / Postgres
  • Claude API (prompt caching)
  • WhatsApp Business API
  • PayFast

Measured

commits
12
last commit
2026-03-18
journal sections
32

Written from StokvelOS build journal — dossier, 56 sections. The dossier is composed from the journal rather than quoted out of it — the raw sections stay behind the review gate described in docs/THE_FORGE.md §4, and every figure above is read from the GitHub API at build time.