Roles, never direct grants
Permissions are granted only through roles. There is no way to attach a permission to a person directly — a special case means a custom role, so access is always inspectable.
Loading
Platform
One shared platform sits under every suite: the isolation model, the multi-entity model, the permission system, and the audit substrate. The commitments below were decided before the first line of code — written down so the system can't drift away from them.
These are not implementation details. They are choices made up front and enforced by the data model itself, so no feature can quietly undo them.
01
Every organization gets its own logical Postgres database and its own object-storage bucket. Tenant boundaries are physical, not column filters. There is no shared organization_id to leak across, no row-level policy to misconfigure, no global table where a bug in one tenant can affect another.
A shared control-plane database holds only global identity: user accounts, organization registry, tenant routing. Nothing business-domain lives there.
What this gives you
Trade-off we accept
Higher per-tenant infrastructure cost than row-level isolation. We accept it in exchange for a boundary that cannot be coded around.
02
Budget remaining, PO committed, invoice balance, master-agreement consumption: calculated at read time from underlying transactions. The ledger is always the source of truth.
Stored aggregates rot. The moment the underlying rows change — a correction, a reversal, a status transition — the cached number becomes a lie. We do not store the cache in the first place.
What this gives you
Trade-off we accept
Slightly higher read cost than pre-aggregated rollups. We mitigate with event-driven cache invalidation and never store a number we cannot invalidate the instant its inputs change.
03
Every business document — budget, requisition, RFQ, purchase order, goods receipt, invoice, payment — has a status lifecycle, an audit history, attachments, and an activity timeline. Not because those documents happened to need it, but because it is a property of every document the system understands.
When a new document type is added, these four capabilities are inherited from the platform layer. We do not decide which documents get an audit trail. They all do.
What this gives you
Multi-entity
Subsidiaries and branches are entities inside your single tenant database, not separate logins. Reads are entity-scoped, fiscal-year windows and sharing grants flow from HQ, and headquarters consolidates every branch into one report in the group's base currency.
See consolidation in BudgetGroup consolidation · FY 2026
base USD| Entity | Local | In base |
|---|---|---|
| HQ · United States | $1,200,000 | $1,200,000 |
| Kenya Branch | KES 84,000,000 | $640,000 |
| UK Subsidiary | £310,000 | $392,000 |
| Group total | $2,232,000 |
Permissions flow only through roles, roles scope to departments and entities, and every boundary is enforced at runtime — so what a person can do is always inspectable.
Permissions are granted only through roles. There is no way to attach a permission to a person directly — a special case means a custom role, so access is always inspectable.
Departments, roles, and permissions are managed together in one connected workspace. Each org is seeded a department and role set matched to its profile at signup.
A role scoped to a department only acts on that department's documents. A Finance-only approver cannot touch a document outside its scope — enforced, not advisory.
Every query is scoped to one entity. Reaching across a subsidiary boundary returns not-found, not a permission error — the data is invisible, not merely forbidden.
A suite an organization isn't entitled to returns 404, not 403 — hidden, not degraded. Cross-suite calls check entitlement at call time and never reach into another suite's tables.
Every write lands on a per-tenant audit chain with a running head, so history cannot be rewritten silently. Policy-relaxed actions record the policy state at action time.
We onboard organizations by invitation. Tell us about yours and we'll set you up with your own isolated workspace.
Request access