The estate in ten minutes
What exists, what talks to what, and why it is shaped this way.
The shape, in one breath
Two apps — IAM and Finloop — sitting on one shared backend platform library, with the browser only ever talking to its own origin. Java/Spring on the backend and React/TypeScript on the web live in one repository and build through one Nx dependency graph. IAM issues tokens; Finloop validates them. Nothing else exists yet, and the design assumes more will.
One user, and what follows from it
There is exactly one person in this estate. That is not a stage the system will grow out of — it is the premise every other decision was made against.
- No roles, no permissions, no approval flows. The only authorisation question anywhere is which app is this token for — the audience claim, and nothing else (ADR-0008).
- No multi-tenancy. No
owner_idon any row, because every row has the same owner. - Correction over immutability. A single user who mistypes an amount wants to fix it, not to file a reversing entry against themselves (ADR-0017).
Where the design does spend complexity, it spends it on money being correct, not on organisational structure that will never exist.
Who calls whom
The browser talks only to its own origin. Each web app is a Cloudflare Worker that serves the SPA
and proxies /api to that app's backend, holding the session cookie itself — a BFF, not a
public API with a token in local storage (ADR-0007).
Browser → Worker. finloop.ringojr.cc serves the app and, on /api/*, forwards same-origin to
the backend. No access token ever reaches JavaScript.
Worker → backend. finloop-backend.ringojr.cc, a Spring Boot container on sawasoft, context
path /api.
Backend → IAM. The backend validates the token's signature against IAM's JWKS and checks the audience is its own app id. A token minted for another app is rejected — proven by a test, not assumed.
What is deliberately absent
Multi-currency, investments, charts, forecasting, bank integrations, statement import, per-category budget limits, multi-user. Each was considered and declined. A single-user money system that is right about the money it has beats one that is approximately right about ten things.
Where the truth lives
| Question | File |
|---|---|
| What are we contractually building? | docs/lifeos-finloop-spec.md |
| What is true today? | docs/architecture.md |
| Why was this decided? | docs/adr/ |
| What happened on each build run? | docs/run-log.md |
| How do I not break the house style? | AGENTS.md |