Har designet et function‑first datalag i PostgreSQL — 1.275 stored functions på tværs af 34 skemaer — så hver læsning og skrivning går gennem en funktion, databasen kan tildele rettigheder til, frem for gennem en tabel.
Arbejdet udført: 2025
Situation. Forretningslogik har det med at lække. Lidt ender i API’et, lidt i noget SQL, en handler kører inline, og før længe er den samme regel skrevet på to‑tre lidt forskellige måder, og der er ingen steder, man kan pege hen og sige “det her er, hvad systemet gør med sine data.” Det er sådan, fejl og sikkerhedshuller kommer ind.
Opgave. Målet var ét hjem til det hele: hver læsning og skrivning gennem databasen, API’et en tynd adapter, der ikke kender forretningsreglerne, og det hele muligt at låse ned til.
Handling. Datalaget er function‑first. Skemaet er delt op efter domæne — identity, organization, review, message, notification og 29 mere, 34 i alt — og hver operation, appen kan udføre, er én af 1.275 PostgreSQL‑funktioner, den kalder; der er slet ingen direkte tabeladgang fra Go. Så håndhæver databasen det. Den rolle, API’et logger ind som, mariner, har EXECUTE på app‑funktionerne og USAGE på skemaerne og intet andet — ingen SELECT, ingen INSERT, ingen måde at røre en tabel direkte — hvilket løber op i cirka 4.000 eksplicitte grants frem for én generel. Funktionerne kører SECURITY DEFINER, ejet af en separat non‑login function_owner‑rolle med en pinned search_path, og superuser‑kontoen holdes reserveret til migrationer og cron, langt væk fra den kørende app.
Resultat. Logikken bor ét sted, man faktisk kan revidere, API’et forbliver tyndt og kedeligt på den gode måde, og adgangsgrænsen håndhæves af Postgres selv frem for af, at alle husker reglerne. Hvis API’et på en eller anden måde blev kompromitteret, kunne det stadig ikke gøre noget, funktionerne ikke tillader. Ved 1.275 funktioner koster disciplinen noget reelt — et nyt felt er en migration og en funktionsændring, ikke en linje i en forespørgsel — og den friktion er prisen for, at grænsen holder.