Why it exists
I am the sole compliance officer of a Singapore licensed fund management company. Sole means the whole obligation stack lands on one desk, and a one-person function doesn’t fail from ignorance. It fails from cadence. Something is due quarterly, you do it well, and eleven weeks later nothing in the world reminds you it’s due again. Spreadsheets don’t remind you. Calendars remind you about the thing you remembered to put in the calendar.
So I built the register I needed. It is a local-first internal compliance operating system: Next.js 15, TypeScript, Prisma, SQLite. The modules are not tidy software abstractions. They map one-to-one onto regulatory obligations and the cadences attached to them.
What’s inside
KYC/CDD/EDD case handling with a screening engine attached. An enterprise-wide risk assessment module. A restricted list and personal-account-dealing pre-clearance flow that runs blackout-window checks automatically instead of asking me to remember which window we’re in. MAS form tracking, covering 3A, 16, and the rest of the recurring set. And a 51-check IT audit programme mapped across ten MAS TRM and Cyber Hygiene domains, which is the one place my degree and my job stop being separate careers.
The parts I’d defend in review
Passport and NRIC identifiers are encrypted at field level with AES-256-GCM. The crypto layer fails closed: if a key is missing or wrong, the write refuses rather than degrading to plaintext. There are scripts whose only job is to confirm that no identifier ever leaks into a generated report, and they run as part of the routine.
Sign-in is a passkey or Windows Hello via WebAuthn, backed by scrypt hashing, lockouts and session timeouts, and every meaningful action lands in an audit trail. There’s an LLM-assisted drafting flow for stock research, built with one hard rule in code: financial figures come only from parsed source documents. The model can write the sentences. It does not get to supply the numbers.
The whole thing runs self-hosted on a Raspberry Pi, reachable only over a private mesh VPN. No cloud, no port forwarding, no third party holding the data.
Where it stands
About 47,000 lines across roughly 288 TypeScript files, in daily use.
The screenshots here are genericized: real branding and the firm’s working data never leave the system, so what’s shown is the shape of the tool, not its contents.