What is ASAB?
Start here
Imagine a giant LEGO building where lots of different shops all live inside, one on each floor. There is a bakery on one floor and a toy store on another. Each shop gets its own locked floor — the bakery can never wander into the toy store's stockroom, and the toy store can never peek at the bakery's money. But the whole building shares the same strong walls, the same front door, and the same security guard, so nobody has to build a whole new building just to open a shop.
ASAB is that building. It is one big software system where many separate companies each get their own private, locked-off "floor," but they all share the same well-built structure underneath. We rent out floors instead of selling each company a whole building.
There are also four different doors into the building, for four different kinds of people:
- A front door with a sign-up desk for new shops that want to move in.
- A building manager's office where the people who run the building can see every floor's health and turn services on or off.
- The floors themselves, where each shop does its daily work.
- A penthouse view for an owner who happens to own several shops at once and wants to see all of them on one screen.
Now let's say all of that again, precisely, the way an engineer needs it.
ASAB in one paragraph (the engineer version)
ASAB is a multi-tenant SaaS ERP. Every word there matters, so let's unpack each one:
- ERP (Enterprise Resource Planning) — one connected system that runs the back office of a company: its money (accounting, invoices, payments), its stock (inventory, warehouses), its buying (procurement), its selling (CRM and sales), its making (manufacturing), and its paperwork (documents, approvals). Instead of ten disconnected apps that don't talk to each other, an ERP is the single place where a sale automatically updates stock, and stock automatically updates the ledger.
- SaaS (Software as a Service) — customers don't install or own the software. They subscribe to it and use it over the internet; we run, update, and operate it for them.
- Multi-tenant — a tenant is one customer company living inside the shared system. "Multi-tenant" means many tenants share the same running application and database without ever being able to see each other's data. That isolation is enforced at the deepest level (PostgreSQL row-level security), not merely hoped for in application code.
- Platform — ASAB is not a single app. It is a four-layer platform (L1–L4, explained below) where a public sign-up gate, an operator control plane, the customer ERP, and an executive portal are distinct products that fit together.
Without an ERP, a growing company keeps its sales in one spreadsheet, its stock in another, and its accounting in a third — and they constantly disagree. An ERP makes one number the truth: when sales records an order, stock and the general ledger update from that same event. ASAB's job is to be that single source of truth, for many companies at once, safely.
The four-layer platform (L1–L4)
ASAB's vision is built as four layers. Each layer is a different audience and a different "door" into the platform. Here is what each one is for — and, honestly, how built-out it is today. This handbook always describes the code as it is, not the dream.
L1 — Public Gate
What it is for. The public marketing and sign-up front door: a prospect visits a website, picks a plan, chooses their industry (Factory vs Insurance), pays, and a new tenant is created and provisioned automatically — no human operator in the loop.
L1 is greenfield today. There is no public marketing site, no subscription or
pricing model, no platform billing, and no self-serve sign-up wired into a live
public flow. The Angular app's root path redirects to a hardcoded default tenant
workspace, and the only public routes are two narrow token-scoped pages
(public/quotations/:quotationId/review and public/documents/portal). A
prospect cannot create a company, pick a plan, or pay without a human operator
running the admin APIs. What does exist — and is genuinely strong — is the back
half of the funnel L1 must eventually feed into: the durable provisioning
machinery in L2 (see below). See the Platform & Control Plane section for
detail.
L2 — Operator / Control Plane
What it is for. The internal platform the ASAB team uses to run the building: see every tenant's status and health, provision new tenants, and turn module entitlements (a tenant's permission to use a given module) on and off.
This layer is realized as a separate deployable microservice,
4EOrganizationsManager, with its own four_e PostgreSQL schema. It owns the
authoritative tenant registry (Organization then Tenant then Cell), a
durable lease-based provisioning saga (a long-running, resumable workflow that
survives crashes), module entitlements, API keys, and append-only monitoring
tables. Code lives under backend/Applications/4EOrganizationsManager.
The write/provisioning engine is production-grade, but the operator-facing
surface is thin. OrganizationsController and CellsController expose only
POST (no list/get/update/suspend). There is no live entitlement feed to the
runtime by default (the legacy worker reader uses static appsettings), no
health aggregation or SLA rollups, and historically a single all-or-nothing
FourEOrganizationsAdmin policy rather than role-graded RBAC. The operator UI
(platform-admin) has run inside the tenant shell at :tenantSlug/platform.
L3 — Customer ERP + Verticals
What it is for. The actual ERP each tenant uses every day. It is a generic ERP core plus exactly one vertical (industry-specific) pack. Today the two verticals are Factory (Manufacturing / Alfawood, a furniture-cutting workflow) and Insurance Broker. A tenant subscribes to one vertical, and its users live under that vertical.
This is by far the most complete layer. The backend (11+ .NET 10 modules under
backend/Modules) is Odoo-competitive per tenant, and the Angular frontend
(frontend/angular/erp-saas-angular) mirrors that breadth across ~14 workspaces.
The defining L3 requirement — vertical gating so a Factory tenant cannot see
or reach Insurance Broker (and vice versa) — was historically not enforced on
the path that matters. As mapped, app.routes.ts had zero route guards, the
sidebar was built from a fully static navigation map, and TenantRuntimeContext
carried only { tenantSlug } with no vertical or enabledModules. On the
backend, RuntimeApiPolicy was only RequireAuthenticatedUser() — no
RequireModuleEntitlement requirement — so a Factory-only tenant's valid token
could still call /api/insurance-broker/**. The data needed to gate
(enabledModules[]) was already fetched by the client but never consumed. The
frontend was also evidence-grade, not enterprise-grade (skeletal design system,
no chart library, no i18n/RTL, several 3000+ line mega-components). Confirm the
current state of gating, design tokens, and i18n against the code before relying
on any of these as still-open.
L4 — Executive Portal
What it is for. A separate portal for an owner of multiple companies (say, one factory plus one insurance brokerage). They get one consolidated dashboard, one dashboard per company, and clean buttons to jump into each company's ERP. An owner of a single company simply sees that one dashboard plus one button.
L4 was greenfield at platform-mapping time. There was no owner identity that
spans multiple tenants, no cross-company aggregation, no consolidated dashboard,
and no "navigate into each company" shell. The 4E model is flat
(Organization then N Tenant) with no owner field; Auth's company context is
strictly single-tenant; Analytics is hard-scoped per tenant; and Finance
cross-company consolidation is setup-metadata only (execution parked per
ADR_0002). Note: in this codebase the in-product owner persona is called the
Executive Portal / Owner — not "CEO" (that term is reserved for the human
delivery-review stakeholder, to avoid a naming collision).
What makes ASAB special
- Real tenant isolation, defense-in-depth. Every module uses PostgreSQL
FORCE ROW LEVEL SECURITYwith a fail-closedtenant_isolationpolicy, bound transaction-scoped, plus tenant-leading composite keys and indexes — proven by per-module Postgres persistence tests. One customer literally cannot read another's rows even if application code has a bug. - A genuine control plane, not just a login screen.
4EOrganizationsManagerprovides durable, resumable, evidence-logged tenant provisioning that most ERP-as-a-SaaS products simply do not have. (Odoo, our business-concept reference, has no comparable operator control plane.) - Generic core plus pluggable verticals. The reusable ERP capabilities live
in the core; industry packs (
ERP.Alfawood,ERP.InsuranceBroker) extend it and must not duplicate or own core behavior. A missing reusable capability is a core backlog item, never a vertical workaround. - Disciplined engineering contract. Every module follows the same six-project
shape (
Entity/Common/Utility/Api/Workers/Tests), CQRS is mandatory (Command/Query plus Handler plus Validator), controllers are HTTP boundaries only, and architecture tests enforce the dependency direction so no module reaches into another module'sEntityproject. The full protocol lives inAGENTS.md. - Built to beat Odoo on the platform, not just the features. The differentiation is airtight multi-tenancy, an operator control plane, and a polished, vertical-gated, multi-company experience as the L1/L3/L4 gaps close.
How to read this handbook
This site is organized so you can move from the big picture down to specific code. New hires should read top to bottom; experienced engineers can jump straight to a section.
| Section | What you'll learn | Read it when |
|---|---|---|
| Getting Started | Orientation, environment, and your first steps in the repo. | You just joined. |
| Architecture & How It Fits Together | The four layers in depth, the module shape, CQRS, tenancy, messaging, and how a request flows end to end. | You want the mental model before touching code. |
| Core Modules | The reusable ERP capabilities — Finance, Inventory, Procurement, CRM/Sales, Documents, Workflow, Auth, Master Data, Analytics, Collaboration, and Manufacturing. | You're about to work in (or call) a specific module. |
| Vertical Products | The industry packs on top of the core: Factory / Alfawood and Insurance Broker. | You're working on vertical-specific behavior. |
| Platform & Control Plane | The 4E control plane (L2) that owns the tenant fleet, module entitlements, and durable provisioning. | You're working on tenancy, provisioning, or entitlements. |
| BRD Fulfillment | Requirements traceability — which business requirements are met, partial, or open. | You need to know what's promised vs. built. |
| Database | Schema and data-model notes, tenant keys, RLS, and indexing conventions. | You're designing a migration or a query. |
| Glossary & Reference | Every term defined — tenant, entitlement, vertical, saga, cell, and more. | You hit a word you don't know. |
Throughout these pages, an "As-built gap" warning (like the ones above) marks any place where the running code differs from the design, the BRD, or the four-layer vision. When you see one, trust the code description over the aspiration — and treat the gap as real backlog, not a typo.
Welcome to ASAB. Start with Getting Started, then build the mental model in Architecture.