Structural map of every entity in oxFlow and how they relate.

oxFlow concept map — entities, layers, and relationships

The diagram above is the canonical structural map. Source in docs/oxflow-concept-map.d2 — edit that, re-render to SVG, and commit both. The previous Figma embed was dropped because the board’s embed permissions kept drifting.

How to read this doc:

  • Definitions live in glossary.md — this doc assumes you’ve read it
  • Relationships are expressed in standard cardinality (1:M, M:M, etc.)
  • “Optional” relationships written as 1:0..1 or M:0..1

1. Conceptual layers

oxFlow’s domain sits in five layers. Every entity belongs to exactly one.

LayerPurposeEntities
1. Work hierarchyThe tree the estimator navigates — from opportunity down to line-level methodologyTender, Estimate, Heading, Item, Worksheet
2. Building blocksThe atoms and reusable compositions that populate WorksheetsResource, Recipe, Input Parameter, Variable, Content Block, Calculation Block
3. Pricing & procurementWhere rates come from, and how competing prices are resolvedPrice Book, Price Book Adjudication, Subcontract Package, Subcontract Package Adjudication
4. Commercials & submissionTurning cost into revenue, then shipping it to the clientRule, Submission Value, Publisher output
5. Reference dataShared lookups referenced everywhereCompany, User, Unit, Categorization, Categorization Option, Code, Code Option, Reference Rate, Tender Program, Program Task, Flag Definition, Modifier Definition

2. Entity catalogue

For each entity: one-line purpose, key attributes, inbound/outbound relationships. Definitions in glossary.

Layer 1 — Work hierarchy

Tender 🟢

Outermost container; one per pricing opportunity.

  • Key attributes: name, number, client, client reference, location, contract start date, tender due date, status, win probability, categorization
  • Relationships:
    • Tender M:1 Company (Client role) — who issued the opportunity
    • Tender 1:M Estimate
    • Tender 1:0..1 Tender Program — optional MS Project upload

Estimate 🟢

A priced build-up inside a Tender. A Tender can have multiple (base, alternative, strategy variants).

  • Key attributes: name, estimate number (rev a, alt, 1, etc.), status, notes
  • Relationships:
    • Estimate M:1 Tender
    • Estimate M:1 User (Lead Estimator)
    • Estimate 1:M Heading (top-level headings)
    • Estimate 1:M Rule (commercials rules for this estimate)

Heading 🟡

Structural grouping inside an Estimate. Self-nests up to 5 levels.

  • Key attributes: title, display order
  • Relationships:
    • Heading M:1 Estimate (root-level headings only) OR Heading (parent) — one of the two
    • Heading 1:M Heading (children)
    • Heading 1:M Item
  • Constraint: total depth including parent chain ≤ 5
  • Formatting: working view uses depth-based default styling (non-editable). Heading appearance in the Publisher output is driven by the Publisher branding config (admin-level).

Item 🟢

What the client buys — the heart of the build-up. Self-nests up to 5 levels.

  • Key attributes: description, schedule code (or code if its not a schedule item - optional), Unit, quantity, status (Unpriced / Plugged / Priced / Reviewed / Locked), item type, item flags (e.g., Indirect Cost, Inactive), plug_rate (nullable; used when status = Plugged), assigned Estimator (optional)
  • Relationships:
    • Item M:1 Heading OR Item (parent) — one of the two
    • Item 1:M Item (sub-items)
    • Item 1:1 Worksheet — every Item has a Worksheet; simple Items have sparse content (UI adapts to minimal cases)
    • Item M:1 Unit
    • Item M:0..1 User (assigned Estimator)
    • Item M:M Categorization Option
    • Item M:M Program Task — via Tender Program linking; each linked task exposes its duration as a Variable on the Item
    • Item M:M Subcontract Package — an Item can be in a package
  • Constraint: a Schedule Item must be at the top of its branch (no Schedule Item nested under Schedule Item)

Worksheet 🟢

The methodology surface attached to an Item or Recipe. Every Item has exactly one Worksheet (simple Items just have sparse content).

  • Key attributes: title (derived from parent Item or Recipe name). The Worksheet itself has no layout-order attribute — each child entity carries its own ordering.
  • Relationships:
    • Worksheet 1:1 Item OR Recipe — exactly one parent of exactly one type
    • Worksheet 1:M Variable
    • Worksheet 1:M Calculation Block
    • Worksheet 1:M Content Block (instance)
    • Worksheet 1:M Worksheet Resource — snapshot usages of Resources (see below)
    • Worksheet 1:M Worksheet Recipe — snapshot usages of Recipes (see below)

Layer 2 — Building blocks

Resource 🟢

The atom. Has a rate and a Unit. Lives in a Price Book.

  • Key attributes: description, rate, Unit, Resource Type, flag instances (from Flag Definitions), modifier instances (from Modifier Definitions), Categorization
  • Relationships:
    • Resource M:1 Price Book
    • Resource M:1 Unit
    • Resource M:1 Resource Type (enum: Labour / Material / Plant / Subcontract / Other)
    • Resource M:M Categorization Option
    • Resource M:M Flag Definition — via flag instance (boolean presence or enum value)
    • Resource M:M Modifier Definition — via modifier instance (carries numeric value at Resource level)
    • Resource M:M Price Book Adjudication (as scope-item)

Lineage note: Resources have a single origin — their Price Book. For Subcontract Resources, the Price Book’s source type (see Price Book) tells you whether the rate was manually entered or produced by a Subcontract Package Adjudication.

Recipe 🟢

A reusable, named combination of Resources with its own Worksheet and input parameters.

  • Key attributes: name, description, notes, Categorization
  • Relationships:
    • Recipe 1:1 Worksheet (required — every Recipe has a Worksheet)
    • Recipe 1:M Input Parameter — must have ≥1
    • Recipe 1:M Worksheet Recipe — inverse view of all usages of this Recipe across Item Worksheets (useful for impact analysis: “which Items will be affected if I edit this Recipe?“)

Input Parameter 🟢

A named variable required at the top of a Recipe.

  • Key attributes: name, unit, default value (optional)
  • Relationships:
    • Input Parameter M:1 Recipe

Variable 🟡

A named value inside a Worksheet, usable in calculations. Origin is internal metadata.

  • Key attributes: name, value / expression, unit, origin (internal: manual / input-parameter / program-task / calculation)
  • Relationships:
    • Variable M:1 Worksheet
  • Notable pattern — Production Rate: Variables commonly represent Production Rates (e.g., pour_rate = 25 m³/hr), bridging quantity and duration. When an Item is linked to a Program Task, the task’s duration combined with the Item’s quantity implies a Production Rate — the Worksheet can cross-check against any manually declared Production Rate Variable.

Calculation Block 🟡

A computation inside a Worksheet that produces a value.

  • Key attributes: expression, resulting value, ordering
  • Relationships:
    • Calculation Block M:1 Worksheet

Content Block (instance) 🟢

An instance of a Content Block definition, carrying estimator-entered text for one Worksheet.

  • Key attributes: text content
  • Relationships:
    • Content Block instance M:1 Worksheet
    • Content Block instance M:1 Content Block Definition

Content Block Definition 🟢

The admin-managed definition of a block available across the system.

  • Key attributes: name, explainer, built-in vs custom
  • Seed values: Inclusions, Exclusions, Task Breakdown, Risks

Worksheet Resource (snapshot-usage join) 🟡

A usage record linking a Resource into a Worksheet. Think: Resource = menu item, Worksheet Resource = a line on your order.

  • Key attributes:
    • quantity (value or expression referencing Variables)
    • snapshot rate — the rate at time of drag-in, stored locally
    • snapshot Unit
    • snapshot flag instances — flag values at time of drag-in (from parent Resource)
    • snapshot modifier defaults — modifier default values at time of drag-in (from parent Resource)
    • modifier overrides (optional per-instance overrides, if set; else inherit Resource default)
    • wastage factor (optional)
    • notes
    • ordering within the Worksheet
  • Relationships: M:1 Worksheet, M:1 Resource, M:M Modifier Definition (via override instance, optional)
  • Snapshot semantics (important): Worksheet Resources do not auto-sync with the underlying Resource. If the Price Book rate, flags, or modifiers for the source Resource change later, the Worksheet Resource keeps its snapshot value. Divergence is surfaced by the Anomaly Review; the estimator explicitly chooses whether to push the updated rate/flags/modifiers through. This is deliberate — silent changes would compromise estimate stability. Per-instance modifier overrides allow fine-tuning at the line level.

Worksheet Recipe (snapshot-usage join) 🟡

A usage record linking a Recipe into a Worksheet, with snapshotted input parameter values.

  • Key attributes:
    • input parameter values (key → value map; values can be expressions referencing Worksheet Variables)
    • snapshot reference to Recipe at time of drag-in
    • notes
    • ordering within the Worksheet
  • Relationships: M:1 Worksheet, M:1 Recipe
  • Snapshot semantics: same principle as Worksheet Resource. If the underlying Recipe changes (new resources added, rates updated), existing Worksheet Recipes keep their snapshot behaviour. Anomaly Review flags divergence; estimator chooses whether to pull the Recipe update through.

Layer 3 — Pricing & procurement

Price Book 🟢

A named collection of Resources, usually supplier-scoped.

  • Key attributes: name, Price Book Type (Project-Specific / Internal / External), source_type (user-created / system-generated), scope (date range, region, project link if project-specific)
  • Auto-creation on fork (BR-049): when a Worksheet Resource is forked (“Fork to new Resource”), if the current Estimate doesn’t already have a Project-Specific Price Book, one is auto-created (named e.g., “Estimate {estimate_number} — Project Overrides”). The estimator doesn’t go through an explicit “create Price Book” flow — the fork action triggers it. These Project-Specific Price Books are user-created semantically (originating from an estimator action) but created automatically.
  • Relationships:
    • Price Book M:0..1 Company (Supplier) — required if Type = External
    • Price Book 1:M Resource
    • Price Book M:0..1 Subcontract Package Adjudication — populated for system-generated Price Books (lineage back to the adjudication that produced them)

Price Book Adjudication 🟢

Adjudication that scopes over Resources selected from an Estimate.

  • Key attributes: name, status (Draft / Adjudicated), created/updated dates
  • Relationships:
    • Price Book Adjudication M:1 Estimate
    • Price Book Adjudication M:M Resource — the scope (Resources being adjudicated)
    • Price Book Adjudication M:M Company (Suppliers) — with pricing + variances per supplier
    • Output: updates rates on the scoped Resources in the Estimate

Subcontract Package 🟢

A named bundle of Items scoped for subcontract pricing. Persistent; has no state of its own — state lives on the Adjudication(s) beneath it.

  • Key attributes: name, scope description
  • Relationships:
    • Subcontract Package M:1 Estimate
    • Subcontract Package M:M Item (the package contents)
    • Subcontract Package 1:M Subcontract Package Adjudication — one or more adjudication rounds

Subcontract Package Adjudication 🟢

A single round of adjudication for a Subcontract Package.

  • Key attributes: name, round number, status (draft / adjudicated), created/updated dates
  • Relationships:
    • Subcontract Package Adjudication M:1 Subcontract Package
    • Subcontract Package Adjudication M:M Company (Subcontractors) — with pricing + variances
    • Subcontract Package Adjudication 1:0..1 Price Book (system-generated) — the Price Book this Adjudication creates/updates on award
  • Output on award: creates or updates the system-generated Price Book (one per Subcontract Package across all its rounds); Resources of Type Subcontract are written into it (one per Item in the Package). Each Item’s Worksheet gets a Worksheet Resource referencing its corresponding Resource.

Layer 4 — Commercials & submission

Rule 🟡

A single commercial adjustment inside an Estimate’s Commercials layer.

  • Key attributes: name, rule type (Percentage / Lump Sum / Rate Adjustment), value, sequence order, scope definition
  • Relationships:
    • Rule M:1 Estimate
    • Rule M:M Scope Target — can target: All, Direct-only, Indirect-only, an Item Type, a Categorization Option, or a specific Item (polymorphic — modelled as a scope-target join)

Submission Value 🟢

Editable final rate/amount for a Schedule Item after Commercials have applied.

  • Key attributes: computed value (from Commercials), override value (optional), final value (computed or override)
  • Relationships:
    • Submission Value 1:1 Item (Schedule Items only)

Publisher Output 🟡

The submittable artifact generated at publish time.

  • Key attributes: file type (PDF / Excel / etc.), generated date, version, cover letter, conditions, inclusions, exclusions, branding config
  • Relationships:
    • Publisher Output M:1 Estimate

Layer 5 — Reference data

Company 🟢

An external organisation. Sourced from Xero.

  • Key attributes: name, Xero ID, address, contact info
  • Relationships:
    • Company M:M Company Role (multi-select: Client / Supplier / Subcontractor)

User 🟢

A person with access. Sourced from Microsoft 365.

  • Key attributes: name, email, M365 ID
  • Relationships:
    • User M:1 Role (Admin / Lead Estimator / Estimator)

Unit 🟢

Measurement label. Admin-managed library.

  • Key attributes: symbol (m, , LS), display name, is-built-in flag

Categorization 🟢

A user-defined taxonomy. Has options and a scope.

  • Key attributes: name, scope (Items / Resources / Tenders / Estimates / combination)
  • Relationships:
    • Categorization 1:M Categorization Option

Categorization Option 🟢

An allowed value inside a Categorization.

  • Key attributes: value, display label, colour (optional)
  • Relationships:
    • Categorization Option M:1 Categorization
    • Categorization Option M:M Item / Resource / Tender / Estimate — depending on Categorization’s scope

Code 🟡

A required, admin-defined classifier on Items or Resources, distinct from Categorization in two ways: (1) required (missing values block downstream Cost Management export per BR-127), (2) integration-linked (options can be sourced/synced from external systems like Workbench). Two Codes seeded at launch from the Benchmark migration: Workcentre (on Items) and Activity Code (on Resources).

  • Key attributes: name, scope (multi-select: Items / Resources — restricted to these two only in v1, BR-125), sync_source (nullable; e.g., “workbench”), locked (boolean — system-protected when sourced externally)
  • Relationships:
    • Code 1:M Code Option

Code Option 🟡

An allowed value inside a Code (e.g., a single Workcentre value like “E-EX01 Excavation & Earthworks”).

  • Key attributes: value, display label (optional), external_id (nullable; for synced Codes), parent_option_id (nullable; reserved for future hierarchical Codes)
  • Relationships:
    • Code Option M:1 Code
    • Code Option M:M Item — when parent Code’s scope includes Items (e.g., Workcentre)
    • Code Option M:M Resource — when parent Code’s scope includes Resources (e.g., Activity Code)

Tender Program 🟡

An MS Project file attached to a Tender.

  • Key attributes: file reference, uploaded date, parsed date
  • Relationships:
    • Tender Program M:1 Tender
    • Tender Program 1:M Program Task

Program Task 🟡

A parsed task from a Tender Program.

  • Key attributes: task name, start date, end date, duration, MS Project ID
  • Relationships:
    • Program Task M:1 Tender Program
    • Program Task M:M Item — via link (creates a duration Variable on the Item)

Reference Rate 🟡

An admin-defined expected unit rate for a category of work, used by Anomaly Review as the anchor layer for rate-based outlier detection. Not used in cost build-up.

  • Key attributes:
    • name — e.g., “Reinforced concrete works”
    • rate_min, rate_max (or rate + tolerance) — the expected range
    • notes — description / context
  • Relationships:
    • Reference Rate M:1 Unit
    • Reference Rate M:0..1 Categorization Option — optional scoping
  • Used by: Anomaly Review (Layer 2, rules-first; Layer 3 AI-assisted in Release milestone)

Flag Definition 🟡

Admin-managed catalog entry. Curates available Flags across the system.

  • Key attributes: name, description, scope (All / single or multiple Resource Types), value_type (boolean | enum), allowed_options (if enum)
  • Relationships:
    • Flag Definition M:M Resource — via flag instance (boolean presence or enum value)

Modifier Definition 🟡

Admin-managed catalog entry. Curates available Modifiers across the system.

  • Key attributes: name, description, scope (All / single or multiple Resource Types), value_unit (%, $, $/hr, etc.), math_operation (enum: quantity_multiplier / rate_adder / lump_sum_add / total_multiplier), default_value (optional numeric)
  • Relationships:
    • Modifier Definition M:M Resource — via modifier instance (carries the numeric value at Resource level)
    • Modifier Definition M:M Worksheet Resource — via modifier instance (carries the per-instance override value if set, else inherits Resource default)

3. Cardinality reference table

Quick-scan view of every relationship in the model.

FromToCardinalityNotes
CompanyTender (as Client)1:MCompany with Client role
TenderEstimate1:M
TenderTender Program1:0..1Optional upload
Tender ProgramProgram Task1:MParsed from MS Project
EstimateHeading1:MRoot headings. Inverse: Heading → Estimate M:0..1 (XOR parent — a Heading’s parent is either Estimate (if root) OR another Heading, never both)
HeadingHeading1:MNesting, ≤5 levels total. Inverse: Heading → Heading M:0..1 (XOR parent — see Estimate → Heading)
HeadingItem1:MInverse: Item → Heading M:0..1 (XOR parent — an Item’s parent is either a Heading OR another Item, never both)
ItemItem1:MNesting, ≤5 levels total. Inverse: Item → Item M:0..1 (XOR parent — see Heading → Item)
ItemWorksheet1:1Every Item has one (sparse if simple). Inverse: Worksheet → Item M:0..1 (XOR parent — a Worksheet’s parent is either an Item OR a Recipe, never both, per BR-007)
ItemProgram TaskM:MVia program-task link
ItemSubcontract PackageM:MPackage membership
RecipeWorksheet1:1Every Recipe has one. Inverse: Worksheet → Recipe M:0..1 (XOR parent — see Item → Worksheet)
RecipeInput Parameter1:M≥1 required
WorksheetVariable1:M
WorksheetCalculation Block1:M
WorksheetContent Block (instance)1:M
WorksheetWorksheet Resource1:MWorksheet Resource → Resource M:1 (transitive Worksheet↔Resource is M:M)
WorksheetWorksheet Recipe1:MWorksheet Recipe → Recipe M:1 (transitive Worksheet↔Recipe is M:M)
ResourcePrice BookM:1
ResourceUnitM:1
ResourceResource TypeM:1Enum
ResourceCategorization OptionM:M
ResourceFlag DefinitionM:MVia flag instance
ResourceModifier DefinitionM:MVia modifier instance, carries value
Worksheet ResourceModifier DefinitionM:MVia override instance, optional
Price BookSubcontract Package Adjudication1:0..1Lineage for system-generated Price Books: each system-gen PB is produced by exactly one SPA, and each SPA produces at most one PB
Price BookCompany (Supplier)M:0..1Required if External
Price BookTenderM:0..1Required if Project-Specific (BR-052); null for Internal/External
Price Book AdjudicationEstimateM:1
Price Book AdjudicationResourceM:MScope
Price Book AdjudicationCompany (Supplier)M:MCompeting suppliers
Subcontract PackageEstimateM:1
Subcontract PackageSubcontract Package Adjudication1:MRounds
Subcontract Package AdjudicationCompany (Subcontractor)M:MCompeting subs
RuleEstimateM:1
Submission ValueItem1:1Schedule Items only
Publisher OutputEstimate0..1:1Latest only (BR-075): at most one Publisher Output per Estimate
CompanyCompany RoleM:MMulti-select
UserRoleM:1
ItemUnitM:1
ItemUser (Estimator)M:0..1Optional
ItemCategorization OptionM:M
EstimateUser (Lead Estimator)M:1Required
CategorizationCategorization Option1:M
Reference RateUnitM:1Required
Reference RateCategorization OptionM:0..1Optional scoping
CodeCode Option1:MAllowed values
ItemCode OptionM:0..1Workcentre Code; tiered enforcement (BR-127)
ResourceCode OptionM:0..1Activity Code; tiered enforcement (BR-127)
RecipeRecipe1:MNesting (via Worksheet Recipe); ≤3 levels (recipe.md)
RecipeUnitM:1Output Unit (BR-030)
RecipeCategorization OptionM:MOptional multi-select tagging for library organisation
RecipeUserM:0..1Reserved for future ownership/lock
Input ParameterUnitM:1Every Input Parameter declares a Unit
VariableUnitM:0..1Optional — estimator may declare a Unit on a Variable for clarity
TenderCategorization OptionM:MIf Categorization scope includes Tender
EstimateCategorization OptionM:MIf Categorization scope includes Estimate
RuleCategorization OptionM:MCommercials Rule targeting a Categorization Option (BR-073)
RuleScope TargetM:MPolymorphic; a Rule can target Heading, Item Type, Resource Type, Categorization Option, Code, specific Item, or structural (All/Direct/Indirect)
Worksheet ResourceResourceM:1Snapshot reference to the Resource (see BR-040)
Worksheet ResourceItemM:1Via parent Worksheet (XOR Worksheet parent — Item or Recipe)
Worksheet RecipeRecipeM:1Snapshot reference to the Library Recipe (see BR-041)
Worksheet RecipeItemM:1Via parent Worksheet (XOR Worksheet parent — Item or Recipe)

4. Self-referential relationships

Two entities self-nest:

  • Heading → Heading — up to 5 levels
  • Item → Item — up to 5 levels

Both are strict trees (one parent). No DAG-style sharing.

The total depth cap is 5 per entity type. A Heading nested 3 deep can still contain an Item nested 5 deep underneath. This is intentional: Headings are for organisation, Items are for cost build-up.


5. Derived (computed) attributes

Attributes the system calculates rather than stores:

AttributeOn entityDerivation
Total costItemSum of (Worksheet Resources: quantity × snapshot rate) + sum of sub-Items (recursive) + sum of Worksheet Recipes evaluated (each Recipe’s Worksheet is computed using its supplied input-parameter values)
Unit costItemTotal cost ÷ quantity (when quantity > 0)
Total costEstimateRoll-up of top-level Items
Direct / Indirect classificationItemStructural: an Item is indirect if (not Schedule Item AND not nested under one) OR Indirect Cost flag = true
Submission Value (final)Item (Schedule only)Commercials-computed value OR estimator override if set

Not derived — stored:

  • Resource rate is stored on the Resource; Adjudications change it by replacement (Price Book Adjudication) or by adding new Resources (Subcontract Package Adjudication), not by derivation.
  • Worksheet Resource snapshot rate is stored; divergence from the Price Book is detected by Anomaly Review, not resolved by derivation.

6. Multi-select attributes

Attributes that are genuinely many-valued and implemented as M:M joins, not enum picks:

  • Company Role — a Company can be Client + Supplier + Subcontractor simultaneously
  • Categorization Options on Items / Resources / Tenders / Estimates
  • Resource Flags — a Resource can carry any combination of its type’s flags
  • Item Flags — minimal set for v1 (Indirect Cost); extensible

7. Lifecycle states

Entities that move through states. Full state machines live in entity specs (Batch B); this is the map of which entities have them.

EntityHas status?v1 states (working)Transitions
TenderYesActive · Submitted · Won · Lost · ArchivedActive → Submitted → Won / Lost / Archived; Active → Archived
EstimateYesIn Progress · Reviewed · Submitted · ArchivedSubmit blocked if any child Item is Unpriced or Plugged
ItemYesUnpriced · Plugged · Priced · Reviewed · LockedUnpriced/Plugged/Priced are derived from Worksheet content + plug_rate; Reviewed is manual; Locked cascades from Estimate Submit
Price Book AdjudicationYesDraft · Adjudicated
Subcontract PackageNoState lives on its Adjudication(s)
Subcontract Package AdjudicationYesDraft · Adjudicated
Publisher OutputYesDraft · Published

🔴 Open: states for each entity need confirmation with Oxcon — this list is provisional.