One system, five maps. Each answers a different question about how Avali is put together — pick whichever one matches what you were trying to ask.
Drawn from the uploaded api/ and assets/js/ sources plus the live DEMO and IKO tenants. Where a file wasn't in the upload it is named as inferred rather than shown as fact.
A single-page front end talking to flat PHP endpoints over one database. No framework, no build step, no application server — the browser holds all the state and the server holds all the truth.
The tenant boundary is a WHERE clause. Every layer above is shared by all companies; isolation lives entirely in company_id being present on each statement — 44 of 45 by the team's own audit. That is what ADR-001 proposes to move into the connection itself.
Worth knowing
There is no $_SESSION anywhere. Auth is a token signed with APP_SECRET, held in the browser and re-verified per request by requireAuth(). That makes the PHP layer stateless — which is why it could scale horizontally, and why containerising it is even plausible.
Map two
Product surface
What a user can actually open, and how it nests. Three sidebar groups, a Payroll Composition tab strip, and an HR hub with its own five-group rail — plus a second front door for employees.
Two coordinates, always. Nothing in Avali means anything without a company and a period. Most of the defensive code in the codebase — the settle-window check, the period banner, the historical-period pill — exists to stop an action landing on the wrong one.
Map three · the important one
Path of the money
If you only look at one map, this is it. Everything distinctive about Avali — the reconciliation tooling, the period-health checks, the push-and-recall vocabulary — follows from a single structural fact visible here.
The muster roll has two writers. Registers push into payroll_records, and Pay Entry edits the same columns by hand. Nothing in the schema stops them disagreeing, so the disagreement is detected instead of prevented — which is why Avali carries three independent reconciliation mechanisms that most payroll systems don't have. Read that as a scar, not an ornament: each one exists because a real client's numbers drifted.
The same shape, repeatedly
Almost every defect found across this codebase is a variant of one pattern: a rule enforced on the read path but not the write path. A checklist item that can't be hand-ticked in the UI but can be through the endpoint. A contract that can't be signed as a draft in the portal but could be by id. A client figure that's ignored for overtime and absence, but trusted for per diem. The registers-versus-muster split is the original of that pattern, and the reconciliation tooling is what containing it looks like.
Map four
The month's lifecycle
A pay period is a small state machine with real teeth. Each transition has a different role behind it, and locking is the one that converts provisional figures into facts.
Locking is the commit. Until it happens, advance recoveries exist only as a schedule — the deductions appear on payslips while the register still shows them provisional. A past month left unlocked is money charged on paper but never collected, which is exactly what the period-health sweep's "unlocked charges" warning is looking for.
Map five
Data model core
Roughly thirty tables, but only a handful are load-bearing. What matters structurally is which of them carry company_id — because that column is currently the only thing holding one client's payroll apart from another's.
An audit result, not a schema guarantee. The difference matters: a WHERE clause can be forgotten in a new query and nothing will fail loudly. Moving the boundary into the connection — one database per tenant, resolved before any query runs — is what turns a convention that has to be maintained into a structure that holds by itself.
The five maps, and what each one is for
Map
Use it when
Its single claim
Runtime layers
Talking about hosting, scaling, or deployment
Stateless PHP over one shared database
Product surface
Onboarding someone, or scoping a feature's home
Everything is scoped by company and period
Path of the money
Debugging a wrong figure, or explaining the product
The muster roll has two writers
Month's lifecycle
Anything touching approval, payment or immutability