LedgerLock — Devpost Project Story
Inspiration
"Running an SME in Nigeria in this economy is daunting. If overheads don't come for your jugular, your staff will try to steal from you." — P. Tommy, Nigerian entrepreneur, March 2026
This post went viral because it is not an isolated story. In two months, P. Tommy changed laundry service providers three times because staff kept diverting customer payments to personal accounts. A chartered accountant in South Africa embezzled R52 million from two supermarkets over two years. A UK government report revealed staff stole over £1.7m in benefits money. A US financial administrator stole $1.36 million by exploiting payroll systems.
The pattern is identical everywhere: businesses give humans too much access to financial credentials, and there is no system between the employee and the money. LedgerLock was built to be that system.
What It Does
LedgerLock is an AI-powered financial guardrails platform for SMEs. It protects businesses from two specific fraud scenarios that destroy small businesses:
Outgoing fraud — A staff member initiates a transfer to a personal account or fake vendor instead of a legitimate supplier.
Incoming fraud — A staff member tells a customer to pay their personal account number instead of the company's official account.
Elf, LedgerLock's AI agent (built with LangGraph and powered by Anthropic Claude Haiku), sits between every financial operation and the business bank account. It analyses every transaction in real time against the owner's defined policies, detects anomalies using AI reasoning, and makes an instant decision: auto-approve, flag for owner review via Auth0 CIBA, or block outright.
Core features:
Verified Payment Links — Every customer-facing payment link is generated by Elf and locked to the company's account via Auth0 Token Vault. Staff generate the link but cannot change the destination. The customer always pays the business, never an individual.
Transaction Guardian — Every outgoing payment request is reviewed by Elf against spending limits, vendor whitelists, and time restrictions before execution. High-risk transactions never move without owner approval.
Auth0 CIBA Step-up Authentication — When Elf flags a transaction as high-risk, it triggers an Auth0 Client-Initiated Backchannel Authentication (CIBA) push to the owner's phone. The owner sees the full transaction details — amount, vendor, staff member, risk signals — and taps Approve or Deny in one tap without logging in.
Staff Risk Scoring — Elf tracks each staff member's payment behaviour over time. Repeated flags raise their risk score so owners see early warning signals before fraud becomes financial loss.
Auth0 Token Vault — All bank and payment API credentials are stored in Auth0 Token Vault, never in LedgerLock's database or codebase. Elf operates through scoped OAuth tokens with least-privilege access. Staff never touch a raw credential.
Tamper-proof Audit Log — Every action Elf takes is logged with an Auth0 reference ID. Nothing can be quietly reversed.
How We Built It
Frontend: Next.js 14 (App Router), TypeScript, Tailwind CSS
AI Agent: LangGraph with a 6-node stateful graph — load_policies → policy_check → anomaly_detection → make_decision → trigger_ciba → persist_and_notify. Powered by Anthropic Claude Haiku for reasoning.
Auth & Identity: Auth0 for AI Agents — Token Vault for credential storage, CIBA for async human-in-the-loop approval, @auth0/nextjs-auth0 SDK
Database: Prisma ORM with PostgreSQL (Neon) for production, SQLite for local development
Payments: Paystack integration via Token Vault (Nigerian payment gateway)
Notifications: Twilio WhatsApp/SMS via Token Vault for customer payment confirmations
Deployment: Vercel
The key architectural decision was that Elf never holds credentials. Every API call to a bank, payment gateway, or notification service goes through a Token Vault-managed OAuth token. Our database stores only a non-sensitive tokenRef — a reference ID that is meaningless without Auth0's private key infrastructure.
Challenges We Ran Into
Token Vault activation — The Auth0 dashboard has evolved significantly. Token Vault is not a single toggle — it activates at the social connection level and requires the My Account API to be authorized. This took significant debugging and reading of the raw SDK source.
LangGraph type system — The newer versions of LangGraph require explicit reducer functions on every Annotation with a default value, not just a default field. This caused TypeScript compilation failures that required careful reading of the LangGraph changelog.
SQLite on Vercel — Vercel's ephemeral filesystem means SQLite databases don't persist between deployments. Switching to PostgreSQL (Neon) for production was necessary.
CIBA polling — Implementing the async CIBA loop required careful timeout handling. The owner's device receives a push notification, they approve or deny, and the server polls Auth0's token endpoint until it resolves. Getting this to work without hanging the UI required a fallback rule-based decision system.
Accomplishments We're Proud Of
The payment link architecture is the feature we are proudest of. It makes the "personal account" fraud structurally impossible rather than just detectable. When a customer pays via a LedgerLock-generated link, the destination is embedded via Token Vault at generation time and cannot be altered by any staff member. There is no social engineering attack that works against this — the system simply does not allow a different destination.
The LangGraph pipeline is also production-grade. Each node is independently testable, the state is fully typed, and new fraud detection nodes can be added without touching existing logic.
What We Learned
AI agents need identity layers as much as they need intelligence. Elf's reasoning is only trustworthy because it operates within explicit permission boundaries enforced by Auth0 Token Vault. An autonomous agent with unrestricted credential access is a liability, not an asset.
CIBA is a significantly underused pattern for financial applications. The ability to interrupt an agent's action and route it to a human for approval is exactly what makes agentic AI safe in high-stakes contexts.
What's Next for LedgerLock
- Direct Nigerian bank API integrations (GTBank, Access Bank, Zenith) for real-time deposit verification against payment links
- WhatsApp-first interface for business owners who manage via mobile
- Multi-branch and multi-staff-tier support
- ML-based fraud model trained on transaction patterns across the platform
- Expansion to other emerging markets (Ghana, Kenya, South Africa) where the same fraud patterns are endemic
## Blog Post: How Auth0 Token Vault Made Our AI Agent Actually Trustworthy
A technical deep-dive into LedgerLock's security architecture
When we set out to build LedgerLock, we faced a paradox: an AI agent that can approve and block financial transactions sounds powerful, but would a business owner trust it with their bank credentials?
The answer, before Token Vault, was no.
The Problem With Naive Agent Architecture
Our initial approach stored payment gateway keys in environment variables and passed them to Elf at runtime. This works in development but creates three critical vulnerabilities: any staff member with server access could extract credentials; prompt injection attacks against the AI could leak them; and a compromised deployment would expose every customer's financial integrations simultaneously.
Token Vault flips the model entirely.
How We Integrated Token Vault
Instead of our application holding credentials and passing them to Elf, Auth0 holds the credentials and Elf makes calls through the vault using scoped OAuth tokens. Our database stores only a tokenRef:
const vaultToken = await prisma.vaultToken.create({
data: {
tokenRef: 'vault_paystack_user123_1711234567',
scopes: JSON.stringify(['create_payment_link', 'read_charges']),
// The actual API key never appears here
}
})
For each connected service, we define exactly what Elf is permitted to do:
- Bank connection:
read_transactions,verify_deposits— Elf can verify deposits but cannot initiate transfers - Paystack:
create_payment_link,read_charges,verify_payment— Elf can generate links but cannot issue refunds - Twilio:
send_message— Elf can send confirmations, nothing else
This least-privilege model means that even if Elf's reasoning were somehow compromised, the blast radius is strictly limited to the scoped permissions. A compromised payment token cannot touch the bank. A compromised bank token cannot generate payment links.
CIBA: The Human-in-the-Loop Pattern
Token Vault handles credential security. Auth0 CIBA handles transaction authorisation. When Elf scores a transaction above our risk threshold (35/100), it calls Auth0's /bc-authorize endpoint:
const cibaResult = await fetch(`${AUTH0_DOMAIN}/bc-authorize`, {
method: 'POST',
body: new URLSearchParams({
client_id: process.env.AUTH0_CLIENT_ID,
login_hint: JSON.stringify({
format: 'iss_sub',
sub: ownerAuth0UserId
}),
binding_message: `Elf: Approve ₦85,000 to "Apex Supplies"? Risk: 65/100`,
scope: 'openid',
})
})
Auth0 pushes a notification to the owner's authenticated device. The owner sees the exact transaction details and taps Approve or Deny. Our server polls the token endpoint until it resolves. The AI does the analysis; the human retains authority on anything above threshold.
The Pattern This Establishes
Token Vault + CIBA together establish a security pattern that should be standard for any financial AI agent: credentials never leave Auth0's infrastructure, agents operate with least-privilege scoped tokens, and high-stakes decisions always route to a human before execution.
For SME owners in markets like Nigeria, where internal financial fraud is existential, this pattern is not a nice-to-have. It is the only way to make an AI agent trustworthy enough to actually deploy.
LedgerLock is live at: https://ledgerlock-git-main-estherea07s-projects.vercel.app GitHub: https://github.com/estherea07/ledgerlock Demo Video: https://youtu.be/EyBkxuteXOc
Built With
- anthropic-claude
- auth0-ciba
- auth0-token-vault
- langgraph
- next.js-14
- paystack
- prisma
- sqlite
- twilio
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.