Approval system for financial requests
A personal project, not in production: a system that routes financial requests to the right approvers by rules kept as data, with encrypted attachments and an append-only audit log enforced at the database level.
§01 The case in detail
- Task
- Route a financial request to the right people depending on category, project, author and amount, and leave a trail nobody can rewrite.
- Approach
- Flexible approval rules kept as data, not code: who may submit a request and who approves it are set per category, project, author and amount range, and can be changed without a release
- Envelope encryption AES-256-GCM, a key per request, crypto-shredding
- Delegation of approval rights for a date range, and automatic escalation when a request waits too long
- A queue on Postgres without Redis
- Sign-in with local accounts
- Audit
- Append-only audit log, enforced at the database level.
- Stack
- FastAPI · server-rendered pages + HTMX · PostgreSQL 16 · job queue in Postgres, one worker (no Redis) · receipts encrypted per subject
- Status
- Personal project, not in production.
| Commits | 644 |
|---|---|
| Days | 56 |
| First commit | 10.07.2026 |
| Python | ~49,900 lines |
| pytest tests | 1,415 |
| Playwright specs | 67 |
Architecture
Architecture as text: who passes what to whom
Submit
- Staff browser ↔ FastAPI app: form, files
- FastAPI app ↔ PostgreSQL: request, audit
- FastAPI app → Attachments: receipts
- FastAPI app → Job queue: job
- Job queue → Worker: claim
- Worker → Telegram: message + buttons
- Worker → Mail server: e-mail
- Telegram → Approver: notice
Decide
- Approver → Telegram: tap
- Telegram → Telegram bot: poll updates
- Telegram bot ↔ PostgreSQL: decision
- Telegram bot → Telegram: confirm, edit
FX rates
- FX feed → Worker: rates, 90 days
- Worker → PostgreSQL: fx cache
Errors
- FastAPI app → Error tracker: exceptions
- Worker → Error tracker: failures
§02 Payment approval workflow system: problem, approach, outcome
- Problem
- Route a financial request to the right people depending on category, project, author and amount, and leave a trail nobody can rewrite.
- Approach
- Flexible approval rules kept as data: who submits and who approves is configured per category, project, author and amount. Delegation, automatic escalation, envelope encryption of receipts and an append-only audit log.
- Outcome
- A personal project, not in production. The configurable routing rules, delegation, escalation and audit log are implemented and covered by 1,415 pytest tests and 67 Playwright specs.
Short answers
- How does an approval workflow choose who approves a payment?
- Approval rules are data, not code. Who may submit a request and who approves it are configured flexibly per category, project, author and amount, and can be changed without a release.
- What happens when an approver does not respond?
- Requests escalate automatically when they wait too long, and approval rights can be delegated for a date range to cover planned absences.
- How is the audit trail protected?
- The audit log is append-only, enforced at the database level.
- How are receipts protected?
- Envelope encryption with AES-256-GCM, a key per request, and crypto-shredding.
- Does it need Redis or a separate queue service?
- No. The job queue lives in PostgreSQL and runs with one worker.
- Is it used in production?
- No. It is a personal project, not in production.
See also: Process and quality audit Person dossier aggregator.
§03 Related
- CRM for a network of martial-arts clubsWhatsApp funnels, reports, trainer pay
- Team forecasting systemDeterministic Monte Carlo, no LLM on the numbers
- Person dossier aggregator from official sourcesMany sources, one reviewed dossier
- LLM integration into working systemsWire a model into the POS, booking, CRM, messengers
- Process and quality auditA written list of fixes ordered by cost
Have a task like this? Write to me.
Send me a message
It goes straight to my Telegram. I reply to the address you leave.