SPEC rev.2026.10 · 42.70°N 23.32°E · Sofia · EET/EEST · UTC+2/+3

// Machine view — the DOM of this page as a parser reads it


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.
Engineering ■ confirmed
Commits644
Days56
First commit10.07.2026
Python~49,900 lines
pytest tests1,415
Playwright specs67
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

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.

Your details are used only to reply to you.