← Work

ESF-Plus

A German state funding programme needed 718 organisations to send documents to a public authority securely. Three years, on my own, a year in production with no reported security incident, and my employer then commercialised it for €500,000.

EmployerISG Institut, for the ESF Plus programme in Baden-Württemberg
My roleSole engineer. Architecture, build, security model, operations
Not my scopeRequirements gathering from the funding bank. My employer's process, and I built against it.
BuiltThree years, on my own. Handed over 2025
StackPHP 8 · Laravel · Livewire · MySQL
OutcomeMy employer commercialised it for €500,000

The constraint that mattered most

Someone from the funding bank has to be able to ask, in 2029, who uploaded which document in 2024 and who looked at it. That arrives as a compliance review, after the software is finished and too late to retrofit.

DecisionI designed and built the audit trail first, before the upload feature that needed it.
AlternativeAdd logging later, where every other project puts it. Faster to a demo, and the normal choice.
What it costWeeks of visible progress, with nothing to demonstrate while being asked when the upload screen would work.
What it boughtThe compliance review raised no findings against the permission model or the audit trail.

How it works

718 ORGANISATIONSoutside the authorityPERMISSION CHECKwho are youwhat may you seewhat may you changeevery request, no exceptionDOCUMENT STORE22,000+ processedAUDIT RECORDappend only, written first
Fig. 01 — nothing reaches storage without passing the permission check, and the audit record is written before the file

The product

The sign-in page. A panel headed Wichtige Informationen explains where credentials come from and who issues them; the sign-in form sits to its right.
Fig. 02 — sign-in, with the access rules stated on the page itself.
The account administration table, headed 718 accounts in total, showing its first three rows. The organisation, contact-person and both e-mail columns are covered by one black redaction bar.
Fig. 03 — one account per organisation, 718 of them. Names and addresses redacted.
The contact-data entry grid, shown empty, with columns for surname, first name, street, postcode, town, telephone and e-mail, and buttons to import, validate, upload and export.
Fig. 04 — the upload grid, empty. Validation runs server-side before a row is stored.

For the technical reader

How it is built, enforced and checked

Architecture

Server-side extraction, so a malformed upload never becomes the browser's problem. Role and ownership checks live in one layer every request passes through.

Enforcement

The audit record is written before the document is stored, so an upload that fails halfway still leaves a trace. That is what makes "who saw this file" answerable at all.

Checked

PHPUnit around the permission model and the extraction path. A year in production, used daily by people outside the organisation, with no reported security incident.

What I would do differently

Livewire kept me to one language and one mental model, which is why one person could finish it. It also makes the interface chattier over the network, and on a bad connection that shows. I would keep it and measure earlier.

Happy to walk through any of these in detail, including the parts that went wrong.