Skip to content

The ERP World View — Why Construction Is Manufacturing

Read this first. Before any spec, any code, any schema. This is the lens through which every design decision in this project makes sense.

A building is a manufactured product with coordinates. ERP already knows how to explode a BOM, track orders, and validate rules. This project applies that 30-year-old pattern to construction — same tables, same logic, spatial output instead of shop-floor output.


The Three Concerns

iDempiere separates documents into header (C_Order) and lines (C_OrderLine), with its BOM spatiality validated against Validation Rules. We inherit the same separation:

Concern iDempiere BIM Compiler Table
WHAT to build Orders, Categories, Products Which products, classified by M_Product_Category + AD_Org c_orderline
HOW to validate BOMs, AttributeSets, Validation Spatial rules propose, regulatory rules gate — by discipline and jurisdiction ad_val_rule
WHERE it lands Output.db for 4D–8D Compiled placements + ASIs — the single source of truth downstream output.db

These three concerns are never merged. A change to WHAT (swap a product) does not require changes to HOW (rules are independent — swap jurisdiction without touching products) or WHERE (compiled output recalculates automatically). This is the architectural invariant that makes exception-based ordering possible: override one concern, inherit the others.

The downstream payoff: output.db with its ASIs (per-instance attributes) is what every downstream dimension reads — 4D scheduling, 5D cost, 6D carbon, 7D facility management, and 8D ERP integration. One compiled output, seven queries.

WHAT: M_Product_Category (Classification) + AD_Org (Discipline)

The WHAT concern has two orthogonal axes — what kind of thing and who is responsible.

M_Product_Category — Product classification (WHAT kind of thing). The same entity iDempiere uses to group products into swap pools. Categories form a BOM cascade — a Bill of Materials is a recipe: one parent product, N child products, each with a quantity. The magic is that each child can itself be a BOM — a building contains floors, a floor contains rooms, a room contains furniture, recursively. Each level is atomic and self-contained:

Level       M_Product_Category    Examples
─────       ──────────────────    ────────
Building    RE (Residential)      SH, DX, DM, FK
  Floor     GF, L1, RF            ground, first, roof
    Room    LIVING, KITCHEN        swap pool — replace one LIVING layout for another
      Leaf  IFC_WALL, IFC_DOOR     element classification (→ component library geometry)

The category at each level defines the swap pool — you can replace one LIVING room layout with another LIVING layout, but you can't swap a LIVING room for a KITCHEN. This is iDempiere's Configure-to-Order constraint applied to spatial BOMs.

AD_Org — Discipline (WHO is responsible). In iDempiere, AD_Org partitions data by business unit. Here, 16 engineering disciplines partition the BOM validation space — from architecture to rail infrastructure. Each has its own rules, its own AD_Val_Rule set, its own validation pass — but sharing the same product catalog. See the full AD_Org table below for all 16 disciplines with IFC class mappings and Terminal element counts.

The distinction matters. Disciplines cut ACROSS the category tree — they don't appear AS levels within it. Three products in the same room (same category path) can have three different AD_Orgs:

Category cascade:     RE → GF → LIVING → SOFA_001       ← AD_Org = ARC
Category cascade:     RE → GF → LIVING → SPRINKLER_001  ← AD_Org = FP
Category cascade:     RE → GF → LIVING → LIGHT_001      ← AD_Org = ELEC

M_Product_Category answers "what kind of thing?" AD_Org answers "who installs it?"

The Category Cascade — One Pattern, Three Domains

The cascade is universal. The same parent→child→grandchild pattern governs residential, infrastructure, and commercial buildings. Only the category names change:

Residential:

RE (Residential)
  └─ M_Product: SH (IsBOM=Y)              ← the building IS a product
       └─ GF (Ground Floor, IsBOM=Y)       ← floor is a product
            └─ LIVING (Room, IsBOM=Y)       ← room is a product
                 ├─ SOFA_001 (IsBOM=N)      ← leaf — geometry from component library
                 └─ TABLE_001 (IsBOM=N)     ← leaf — geometry from component library

Infrastructure:

IN (Infrastructure)
  └─ M_Product: BR (Bridge, IsBOM=Y)
       └─ SUP (Support, IsBOM=Y)           ← segment is a product
            └─ PILE_001 (IsBOM=N)           ← leaf — geometry from component library

Commercial:

CO (Commercial)
  └─ M_Product: WA (Warehouse A, IsBOM=Y)
       └─ L1 (Level 1, IsBOM=Y)            ← floor is a product
            └─ OFFICE (Space, IsBOM=Y)      ← space type — same swap-pool logic
                 └─ DOOR_001 (IsBOM=N)      ← leaf — geometry from component library

Category Population — Current State

M_Product_Category Buildings Sub-Categories
RE (Residential) SH, DM, DX, FK, AC LIVING, KITCHEN, BEDROOM, BATHROOM, DINING, MASTER, CORRIDOR, OFFICE + floor-level (GF, RF, L1, L2)
RE (Residential, floor-only) BA, BH, BS, CA, CE, CH, CL, CP, CS, ES, GH, HI, JE, JS, MO, NI, RA, RM, RS, SC, WB, WI Floor-level categories only (GF, L1, L2, ROOF, FDN, MISC) — no room categories yet
IN (Infrastructure) BR, RD, RL SUP, DCK, ABT, TRK, ROAD, RAIL, GEO — segment types
CO (Commercial) WA, WL, WT, TE LOBBY, OFFICE, PLANT_ROOM, LOADING + floor-level (L1–L5) + discipline-driven (ARC, STR, FP, ACMV, ELEC, CW, SP, LPG)
IP (Industrial Plant) IP PROCESS, UTILITY, CONTROL, MISC + floor-level

Gaps: 22 residential buildings have only floor-level categories (GF, L1, L2) but no room-level categories (LIVING, KITCHEN, BEDROOM). These buildings were extracted before room-level classification was implemented. Re-extraction with the current pipeline would populate room categories automatically.

Self-describing BOM tree: The hierarchy is whatever the products make it (BBC.md §1 — no fixed UNIT/FLOOR/ROOM/SET/ITEM vocabulary). Root = getParentBOM() returns null. Leaf = getChildren() returns empty. M_Product_Category determines the grouping at each level.


The Insight

In 2006, we built ADempiere's manufacturing BOM module. In 2010, we rebuilt it for iDempiere. After two decades of watching M_Product, M_BOM, and C_Order handle everything from circuit boards to patio furniture sets, the realisation was unavoidable:

A building is just a very large manufactured product with spatial coordinates.

Every wall panel is an M_Product. Every floor plan is an M_BOM (assembly recipe). Every construction project is a C_Order. The only thing manufacturing MRP lacks is the where — the (x, y, z) coordinates that turn a flat bill of materials into a three-dimensional building.

Manufacturing solved procurement, scheduling, cost control, and quality decades ago. Construction never had a Bill of Materials. This project provides one. The rest follows from that foundation.


The Pattern: A Product IS a BOM

In iDempiere/Libero Manufacturing, there is one universal entity: M_Product.

A Patio Furniture Set is an M_Product. Set IsBOM=Y and it has children: 4 chairs, 1 table, 1 optional shade — each an M_Product in its own right. The chairs are leaf products (IsBOM=N): they have no children, they reference inventory directly. The set is a BOM product: it has a recipe (M_BOM) with lines (M_BOM_Line) that point to its children.

This is the entire model. Products all the way down. BOMs are not a separate entity — they are a property of a product. A building is a product. A floor is a product. A room is a product. A door is a product. A bridge span is a product. A road segment is a product. The tree is universal.

The root product has no parent. Every other product is a child of something. M_Product_Category determines what kind of thing it is — not a hardcoded type string, but the category cascade. The tree structure tells you nesting. The category tells you domain meaning. The compiler doesn't need to know if it's walking a building or a bridge — it walks products.

Residential:
  SH (M_Product, IsBOM=Y, M_Product_Category=RE)       ← root (no parent)
    └─ GF (M_Product, IsBOM=Y, M_Product_Category=GF)   ← child of root
         └─ LIVING (M_Product, IsBOM=Y, M_Product_Category=LIVING)
              ├─ WALL_PANEL (M_Product, IsBOM=N → geometry from component library)
              ├─ DOOR (M_Product, IsBOM=N → geometry from component library)
              └─ FURNITURE_SET (M_Product, IsBOM=Y, M_Product_Category=FR)
                   ├─ TABLE (M_Product, IsBOM=N → leaf)
                   └─ CHAIR × 4 (M_Product, IsBOM=N → leaf)

Infrastructure (same model, different categories):
  BR (M_Product, IsBOM=Y, M_Product_Category=IN)        ← root (no parent)
    └─ SPAN_01 (M_Product, IsBOM=Y, M_Product_Category=SPAN)
         └─ PILE_001 (M_Product, IsBOM=N → leaf)

When the compiler encounters a BOM product, it explodes (recurses into children). When it encounters a leaf product, it resolves (looks up geometry in the component library). This is the same operation an ERP system performs when it explodes a manufacturing BOM into work orders. The walker doesn't branch on domain vocabulary — it follows the tree.


The Order — Configure-to-Order

In iDempiere, there is one C_DocType per document purpose: SOO (Sales Order), POO (Purchase Order), MOP (Manufacturing Order). Product classification lives on M_Product → M_Product_Category — never on the document type.

This project has exactly one document purpose: "Construction Order." That is the C_DocType. Classification lives where it belongs — on the product's M_Product_Category, not on the order.

The BOM cascade gives you the FULL product tree (SH → floors → rooms → furniture → thousands of leaves). But the C_Order does NOT repeat that tree. This is iDempiere's Configure-to-Order pattern: the order carries only the EXCEPTIONS.

M_Product SH (BOM template):     1099 elements (full cascade)
C_Order "Build me SH":           0 lines (no exceptions — use template as-is)
C_Order "SH but no sofa":        1 line  (qty=0 at locator_ref RE.GF.LI.SOFA_001)
C_Order "SH Solar Premium":      6 lines (inherits from SH Solar, adds overrides)
C_Order "200 houses, 6 variants": 200 × ~3 lines = 600 lines (not 200 × 1099)

The BOM template is the PRODUCT (M_Product + M_BOM + M_BOM_Line cascade). The Order is just the delta — Remove (qty=0), Compress (reference class × N), Replace (swap product at locator_ref), Add (new line). Inheritance chains (Ref_Order_ID) let you stack deltas: SH_BASE → SH_SOLAR → SH_SOLAR_PREMIUM.

The category at each level constrains what the thin order can override. You can Replace a LIVING room layout with another LIVING layout, but you can't swap it for a KITCHEN. M_Product_Category is the swap-pool guard.


The Entity-Relationship Model

Every table in this project maps to a proven iDempiere entity. No invented abstractions. No BIM-specific data models.

The ERD

M_Product_Category (RE, IN, CO)          ← WHAT kind of thing (cascade level)
  └─ M_Product (SH, DX, BR)             ← the thing itself (IsBOM=Y or N)
       ├─ M_BOM + M_BOM_Line            ← children (cascade down, dx/dy/dz tack offsets)
       ├─ M_AttributeSet                ← WHICH attributes vary (BIM_Pipe, BIM_Component)
       │    └─ M_AttributeSetInstance   ← per-instance values (length=3200mm)
       └─ AD_Org                        ← WHO installs it (ARC, FP, ELEC) — tag, not level

C_DocType ("Construction Order")         ← ONE document type, always
  └─ C_Order ("Build me SH")            ← references M_Product
       ├─ C_OrderLine                   ← exceptions only (thin order)
       │    ├─ locator_ref              ← WHERE in the tree
       │    └─ M_Product_Category       ← swap pool constraint
       ├─ Ref_Order_ID                  ← inheritance chain
       └─ C_Campaign                    ← design theme (orthogonal)

AD_Val_Rule                              ← jurisdiction rules (MY/UBBL, US/IBC)
AD_ChangeLog                             ← full provenance (undo/redo stack)

The Mapping: iDempiere → BIM

iDempiere Manufacturing BIM Compiler What It Does
M_Product Building element or assembly The universal entity. Everything is a product
M_Product_Category RE, IN, CO, GF, LIVING, IFC_WALL... Classifies products at every cascade level. WHAT kind of thing
AD_Org ARC, STR, FP, ELEC, ACMV... Discipline = organisational unit. WHO is responsible
M_BOM + M_BOM_Line Assembly recipe + children BOM explosion. Each line has dx/dy/dz tack offset
C_Order Construction project One order = one building. Carries exceptions only
C_OrderLine Exception line Deviation from BOM template (swap, remove, compress, add)
C_DocType "Construction Order" ONE document type. Classification lives on M_Product_Category
DocAction lifecycle DR → IP → CO → AP Draft → In Progress → Complete → Approved
AD_Val_Rule Validation by jurisdiction Same rule engine, construction codes instead of tax codes
C_Campaign Design theme Bali, Scandinavian, Industrial — marketing drives variant
AD_PrintFormat Output selection Which elements to render, which to hide
M_AttributeSet Instance variation Per-element customization (pipe length, colour, finish)
C_Project Site development 200 houses under one project. Groups C_Orders

The extension: Manufacturing MRP has product + quantity + sequence. We add three columns to M_BOM_Line: dx, dy, dz — parent-relative tack offsets in millimetres. That is the entire difference between a flat BOM and a spatial BOM. Three integers turn procurement into construction.

Orthogonal Dimensions

Seven dimensions cut ACROSS the product category cascade. None of them appear AS levels within the tree:

Dimension iDempiere Entity What It Controls Orthogonal To
Classification M_Product_Category What kind of thing (swap pool) — (this IS the cascade)
Discipline AD_Org Who installs it Category
Design theme C_Campaign Bali, Scandinavian, Industrial Category, Discipline
Jurisdiction AD_Val_Rule MY/UBBL, US/IBC rules Category, Discipline, Theme
Costing M_PriceList Unit cost by region/contract All above
Instance variation M_AttributeSetInstance Pipe length, colour, finish All above
Site grouping C_Project 200 houses under one project Everything

M_AttributeSet — Why Product Count Stays Small

Without AttributeSets, TE (Terminal) with 48,428 elements would need 48,428 separate M_Products. That's wrong. In iDempiere, a shirt comes in S/M/L/XL — that's ONE M_Product with an M_AttributeSet (size) and 4 M_AttributeSetInstances. Not 4 products.

Same pattern for construction. An FP (Fire Protection) route has: - START (pipe segment) - MID (pipe segment — different length) - JOINT (elbow, tee, reducer — fixed geometry) - DEVICE (sprinkler head, valve — fixed geometry) - END (cap, terminal)

These are ~5 abstract M_Products, not thousands. The VARIABLE part (pipe length) lives on M_AttributeSetInstance. The FIXED part (elbow geometry) has no instance attributes — it's the same product everywhere.

M_Product: PIPE_CW_50MM (IsBOM=N, M_AttributeSet = BIM_Pipe)
  └─ Instance 1: {length_mm: 3200}    ← segment in corridor
  └─ Instance 2: {length_mm: 4800}    ← segment in main run
  └─ Instance 3: {length_mm: 1200}    ← branch to sprinkler

M_Product: ELBOW_90_50MM (IsBOM=N, M_AttributeSet = BIM_Component)
  └─ No instances — fixed geometry, same everywhere

M_Product: SPRINKLER_UPRIGHT_K80 (IsBOM=N, M_AttributeSet = BIM_Component)
  └─ No instances — placement varies, product doesn't

The ROUTE verb assembles these into a BOM tree with per-segment instance attributes. TE's 9,345 FP/CW/SP/LPG pipe elements → ~20 abstract products × many instances. Without this, the product table explodes.


The Application Dictionary Heritage

Compiere introduced the Application Dictionary (AD) in 2000 — metadata that defines the system itself. ADempiere inherited it. iDempiere perfected it. This project leans on it heavily. If you've administered an iDempiere instance, every pattern below will feel familiar.

iDempiere references: wiki.idempiere.org · Application Dictionary · Manufacturing · Validation Rules · DocAction

AD_Val_Rule — Validation rules as data, not code. In iDempiere, AD_Val_Rule restricts field values (e.g., "only active Business Partners"). Here, the same table enforces building codes: sprinkler spacing

= 3000mm, emergency light within 6m of exit, fire door on every corridor. Jurisdiction-scoped — MY/UBBL rules fire for Malaysian buildings, US/IBC for American ones. Exactly like tax rules scoped by C_Country. → DocValidate.md · DocAction_SRS.md §5

Column Callout — Reactive field logic. In iDempiere, a Callout fires when a user changes a field value (e.g., selecting a Business Partner auto-fills the address). Here, DiffVerb + Callout means: drag a wall in the viewport → cascading consequences fire (room AABB recalculates, furniture re-validates, MEP re-routes). Same pattern, spatial domain. → ProjectOrderBlueprint.md §9

ModelValidator — Event-driven hooks. iDempiere's ModelValidator fires before/after save, before/after delete. Our processIt() orchestration follows the identical lifecycle: prepareIt()completeIt()approveIt(). Each discipline routes through DocEvent — the validation engine discovers applicable rules and fires them. No hardcoded logic. → DocAction_SRS.md §1

C_Project — Multi-order grouping. Any ERP person recognises C_Project instantly: project accounting, milestone tracking, cross-order budgets. Here, a housing development IS a C_Project. 200 houses = 200 C_Orders under one C_Project. Site layout = C_ProjectLine per plot. The same entity that manages a manufacturing program manages a construction site. → ProjectOrderBlueprint.md §2

AD_Org — Discipline as organisational unit. In iDempiere, AD_Org partitions data by business unit. Here, engineering disciplines partition the BOM validation space. Each discipline is an organisational concern with its own rules, its own AD_Val_Rule set, its own validation pass — but sharing the same product catalog.

The Terminal building (TE, 48,428 elements) exercises all active disciplines and proves the partitioning scales to commercial-institutional complexity:

AD_Org_ID Code Name IFC Classes TE Elements Role
0 * Shared Shared infrastructure visible to all trades
1 ARC Architecture IfcWall, IfcDoor, IfcWindow, IfcSlab, IfcPlate, IfcRoof, IfcStair, IfcFurniture, IfcRailing, IfcCovering 34,724 Building envelope, internal fit-out, finishes
2 STR Structural IfcColumn, IfcBeam, IfcMember, IfcFooting, IfcElementAssembly 1,429 Load-bearing frame, foundations
3 FP Fire Protection IfcFireSuppressionTerminal, IfcAlarm, IfcSensor, IfcController + pipe network 6,863 Sprinklers, alarms, risers (NFPA 13)
4 ELEC Electrical IfcLightFixture, IfcElectricAppliance 1,172 Lighting, outlets, switches, cable trays
5 ACMV HVAC IfcAirTerminal, IfcDuctSegment, IfcDuctFitting 1,621 Ducts, diffusers, AHUs
6 CW Cold Water IfcPipeSegment, IfcPipeFitting, IfcValve, IfcFlowTerminal 1,431 Water supply piping
7 SP Sanitary/Plumbing IfcSanitaryTerminal, IfcPipeSegment, IfcPipeFitting 979 Waste pipes, fixtures, drainage
8 LPG Gas Piping IfcPipeSegment, IfcPipeFitting, IfcValve 209 Gas supply piping, meters
9 REB Reinforcement IfcReinforcingBar (removed) Rebar, mesh — generated by Bonsai addon, not construction BOM
10 MEP MEP (Generic) IfcFlowTerminal, IfcFlowSegment, IfcFlowFitting Resolves to FP/ELEC/ACMV/CW/SP/LPG at placement
11 ROAD Road IfcCourse, IfcSurfaceFeature IFC4X3 road infrastructure
12 GEO Geotechnical IfcEarthworksFill Earthworks, cut-and-fill
13 RAIL Rail IfcTrackElement, IfcRail IFC4X3 rail infrastructure
14 LAND Landscape IfcGeographicElement Geographic, landscape elements
15 SIGN Signage IfcSign Signs and signals

Key design principles:

  • Disciplines cut ACROSS the category tree — they don't appear AS levels. Three products in the same room can have three different AD_Orgs (ARC sofa, FP sprinkler, ELEC light).
  • MEP (ID 10) is a routing placeholder — the BOM assigns MEP to pipe elements generically; BomDropper.resolveDiscipline() resolves to the specific trade (FP/CW/SP/LPG) based on system_type at placement.
  • REB (ID 9) was removed from the TE pipeline — rebar is generated dynamically by the Bonsai Python addon, not extracted from the IFC construction BOM.
  • IDs 11-15 (ROAD, GEO, RAIL, LAND, SIGN) are IFC4X3 infrastructure disciplines — proven on 3 Rosetta Stones (BR, RD, RL).

DISC_VALIDATION_DB_SRS.md · TerminalAnalysis.md

AD_ChangeLog — Full provenance and UNDO/REDO.

iDempiere's AD_ChangeLog records every field change on every record: who changed it, when, old value, new value, which transaction. This is Configure-to-Order's audit trail — the record that proves a BOM recipe was built correctly.

Our ChangelogDAO applies the identical pattern to spatial operations. Every PLACE, DELETE, MOVE, and RESIZE is logged with full before/after state. The schema (bim_changelog table, migration V011) stores:

Column Content
building_id Which building
entity_type + entity_id What changed (M_BOM, M_BOM_Line, C_OrderLine)
action SAVE / PLACE / DELETE / MOVE / RESIZE / PROMOTE / UNDO
field_name Which field
old_value / new_value Before and after
user_id Who did it
timestamp When

This gives us a complete UNDO/REDO stack. Replay the log forward to reconstruct any past state. Replay in reverse to undo. Like Wikipedia's edit history: every BOM state that ever existed can be reconstructed from the changelog, and every change is attributed to a user.

Multi-user conflict detection follows the iDempiere pattern: AD_Session identifies the editing session, user_id identifies the author. Two users editing the same BOM line produce two changelog entries — the system detects the conflict at save time by comparing timestamps.

Current status: ChangelogDAO is fully implemented and tested (TIER1_SRS.md §3). The bim_changelog table lives in the per-building output database (output.db). Wire protocol supports changelog (query history) and undoChanges (revert N steps). Not yet integrated into BOM databases — the audit trail currently covers design edits in the viewport session. → TIER1_SRS.md §3 · ProjectOrderBlueprint.md §10

EntityType (D/U/A) — Dictionary vs User vs Application. iDempiere protects shipped dictionary records from user modification. Our X_M_BOM enforces the same: Dictionary records (shipped BOM templates) are read-only. User records (verb-created BOMs) are fully mutable. GodMode bypass for migrations only. Three-tier protection at the ORM layer. → BBC.md §1 · AUDIT Appendix O.7

AD_PrintFormat — Output selection. In iDempiere, AD_PrintFormat controls which columns appear on a printed document. Here, the same concept controls which elements render in the viewport, which disciplines show in the HTML UI, and which BOM levels expand in the tree view. Presentation is configuration, not code.

Configure-to-Order — Exception-based ordering. iDempiere's BOM Configurator lets a sales rep exclude optional components or set quantities at order time. Our exception-based ordering (qty=0 removes a subtree, reference class compresses N copies) is the identical pattern applied to buildings. 200 houses, 6 lines of exceptions each. → ProjectOrderBlueprint.md §1


Why This Matters

For construction: The industry reportedly loses billions annually to the gap between design tools (geometry) and ERP tools (data). This compiler bridges that gap deterministically. Given a building design, it answers: what do I need to buy, where does each piece go, and can I prove it?

For iDempiere: The manufacturing module, proven over two decades on discrete products, turns out to handle the world's largest product — a building — with minimal extension. This extends the iDempiere architecture to building scale — a validation of the original design that its scope never anticipated.

For the project: Every decision traces to an iDempiere pattern. When we face a design question, we ask: how does iDempiere handle this for manufacturing? The answer is almost always directly applicable:

  • Exception-based ordering is iDempiere's Configure-to-Order. 200 houses, 6 lines of exceptions each — not 200 × 1099 elements. The BOM template is the product; the order is just the delta.
  • Two kinds of rules work in symbiosis: spatial rules mined from 35 real buildings tell the compiler where things go; regulatory rules (UBBL, NFPA 13, IBC) tell it what the law requires. Spatial proposes, regulatory validates — the Three Concerns in action.
  • 4D scheduling is a topological sort of the BOM tree. No Primavera needed. Material logistics follow via M_InOut — iDempiere's goods receipt applied to construction deliveries.
  • 5D cost is inherent in the data model. Every M_Product has a price. The cost of a building is SUM(price × qty) — a query, not a feature.
  • Design themes are C_Campaign — Bali, Scandinavian, Industrial. Marketing drives variant selection, orthogonal to product category and discipline.
  • Site developments are C_Project. 200 houses under one project, each a C_Order on a plot. The same entity that manages a manufacturing program manages a construction site.

The test: 35 real buildings compiled. 48,428 elements in the largest. 6 verification gates. 19 buildings ALL GREEN. Not a prototype — a working compiler with witness verification at every step.


Reading Order

After this manifesto:

  1. BBC.md §1 — the entity mapping table and technical detail
  2. DATA_MODEL.md — schema, 4-DB architecture
  3. TestArchitecture.md — verification gates, tamper seal
  4. ProjectOrderBlueprint.md — what's next (exception ordering, inheritance, C_Project)
  5. SourceCodeGuide.md — where the code is

For the full academic treatment: BIMERPPaper.md