1. Purpose

A Resource is the atom-level building block of oxFlow’s cost model — the ingredient. Every Resource has a rate and a Unit, lives in a Price Book, and carries metadata (Resource Type, Flags, Categorization) that governs how it can be used and what behaviour applies to it.

Resources flow into Items via Worksheet Resources — snapshot usages that capture the Resource’s rate and unit at a moment in time. When a Resource’s rate changes in its Price Book, Worksheet Resources that reference it don’t auto-update; divergence is flagged by Anomaly Review, and the estimator explicitly decides whether to push the new rate through.

Everything in oxFlow’s cost build-up ultimately decomposes into Resources.

Analogy (glossary cooking model): the Resource is the ingredient — the atom that gets combined into Recipes and used in Item Worksheets.


2. Attributes

AttributeTypeRequiredDefaultNotes
idUUIDgeneratedSystem-managed
descriptionstring (text)What this Resource represents; e.g., “Concrete Pump (90m boom, full day hire)“
ratenumber (decimal)The unit rate, e.g., 450.00. Stored in the Resource; Adjudications modify by replacement (BR-021)
unitUnit refOne of the managed Unit library (e.g., , hr, day, LS). Every Resource has a Unit (BR-020)
resource_typeenumLabour · Material · Plant · Subcontract · Other. Enum, not multi-select; fixed set of 5 types (BR-022)
flagsM:M to Flag Definition[]Resource-level flags picked from the admin-managed Flag Catalog (see §4). For boolean flags: presence = true. For enum flags: selected option stored.
modifiersM:M to Modifier Definition (with value)[]Resource-level numeric modifiers picked from the admin-managed Modifier Catalog (see §4b). Each modifier carries a numeric value and math operation. Values flow into Worksheet Resources as defaults.
categorization_optionsmany-to-many[]Multi-select Categorization Option references (Resources can be tagged against any Categorization whose scope includes Resource)
price_book_idPrice Book refForeign key to the Price Book this Resource lives in. Every Resource belongs to exactly one Price Book (BR-021)
noteslong textnullResource-level notes — free text, e.g., supplier source, conditions, carbon rating
created_at / updated_attimestampsystemAudit
created_by / updated_byUser refsystemAudit

Derived attributes (computed, not stored) — see §9.


3. Resource Types

Resource Type is a structural classifier (enum, not multi-select) that governs three things only (BR-022):

  1. Which Flag set is available for the Resource
  2. Whether the Resource can be an output of Subcontract Package Adjudication (Subcontract only; all others reach Estimates via Price Book or direct entry)
  3. Which type-specific Anomaly checks apply (e.g., “Plant without operator”, “Material without cartage allocation”)

All Resource Types are structurally identical — same data model, same Unit requirement, same Categorization flexibility. The Type is purely semantic/configuration.

TypePurposeAdjudication routeFlag setType-specific Anomaly checks
LabourWorkforce cost (hourly, daily, crew rates)Price Book Adjudication onlyRegion / Rate tier / Allowances / Hours per dayMissing region tag; missing rate tier
MaterialRaw goods, components, suppliesPrice Book Adjudication onlyCartage · Wastage · Supply-only vs installMissing cartage allocation; high wastage without approval
PlantEquipment hire / ownershipPrice Book Adjudication onlyWet hire / Dry hire · Daily / Weekly / Monthly · Fuel includedPlant without operator; missing hire term
SubcontractOutsourced work packages from SubcontractorsSubcontract Package Adjudication onlyFixed price / Rates-only · Insurance · Design+construct vs construct-onlySubcontract without clear scope; missing insurance clause
OtherCatch-all for items that don’t fit above (royalties, licences, permits, etc.)Price Book Adjudication onlyNone — no Flags, no type-specific checksNone

Notes on scope:

  • Subcontract Resources originate from Subcontract Package Adjudications (BR-024, BR-063) — the adjudication creates/updates a system-generated Price Book; the Subcontractor (winning Company) is the Price Book’s Supplier.
  • Subcontract Resources can also be manually created in a user-created Price Book (e.g., a standing subcontract list).
  • All other types are created either by direct entry into a Price Book or via Price Book Adjudication (BR-060, BR-062).

4. Flags (descriptive catalog)

Flags are admin-curated, narrow descriptive attributes that identify the scope or conditions of a Resource’s rate without bloating the description field. Flags do not affect cost math — they’re informational and drive Anomaly Review checks.

Flag Catalog model

  • Admin maintains a Flag Catalog — a narrow list of available flags, each with a declared scope (applies to all Resource Types, one specific type, or multiple types).
  • When creating / editing a Resource, the estimator picks applicable flags from the catalog filtered by the Resource’s Type.
  • No flags selected is valid — most Resources won’t need many flags.
  • Each flag is either boolean (present = true) or enum (pick one of the allowed options; e.g., Wet hire / Dry hire).

Example flags (illustrative catalog entries)

FlagType (enum/bool)Scope (Resource Types)Description
Regionenum (Auckland / Wellington / Christchurch / National)Labour, PlantRegional scope of the rate
Shift typeenum (Standard 8hr / 9hr / 10hr)LabourStandard working day this rate assumes
HazmatboolMaterialResource involves hazardous material handling
Currencyenum (NZD / AUD / USD)Material, SubcontractCurrency the rate is expressed in
Wet hire / Dry hireenumPlantWhether operator and fuel are included in hire
Operator requiredboolPlantWhether separate operator resource needed
Design + construct / Construct-onlyenumSubcontractScope of subcontractor’s work
Includes insuranceboolSubcontractSubcontractor carries PLI / PI
Plug RateboolAllMarks the Resource as placeholder pricing — flagged by Anomaly Review when used in any Worksheet (see §4a)

The full flag list at launch is an 🟡 open item — Oxcon confirmation during admin catalog setup. The list is intentionally narrow — each flag should capture a meaningful scope/condition that matters to estimators.

Flag Definition — catalog entry attributes

Each entry in the Flag Catalog is a Flag Definition with the following structure:

AttributeTypeRequiredDefaultNotes
idUUIDgeneratedSystem-managed
namestring (short text)Human-readable name (e.g., “Wet hire”, “Plug Rate”). Unique within the active (non-archived) set
descriptionlong textnullAdmin guidance — when to apply, what it means
scopemulti-select enumResource Types this Flag applies to: any combination of All / Labour / Material / Plant / Subcontract / Other
value_typeenumbooleanboolean (presence = true) OR enum (pick one of allowed_options)
allowed_optionsarray of stringsconditionalnullRequired if value_type = enum (≥2 entries); null/empty if value_type = boolean
default_valuestringnullOptional default for new Resources of in-scope Type
is_built_inbooleanfalseTrue for catalog entries seeded at launch (e.g., “Plug Rate”). Built-in entries cannot be deleted, archived, or have their name / value_type / allowed_options changed
archived_attimestampnullSoft-delete marker. Archived entries remain visible on historical Resources but are not selectable for new Resources. Un-archive supported
created_at / updated_at / created_by / updated_bysystemAudit

Lifecycle: Flag Definitions support soft-delete (archive) only — never hard-delete. Existing flag instances on Resources retain their values through archive. Built-in entries are protected (cannot be archived or deleted; description and scope are editable). Catalog management is Admin + Lead Estimator per roles-permissions.md §3.

§4a. Plug Rate flag (special)

Plug Rate is a single flag in the Flag Catalog, but worth calling out because of the naming overlap with Plugged (Item Status). They’re distinct concepts:

  • Plug Rate (Resource flag) — marks a Resource as placeholder pricing in the Price Book. When used in any Worksheet, Anomaly Review flags it.
  • Plugged (Item Status) — the Item’s rate was entered directly at Item level, no Worksheet build-up (BR-019d).

A Priced Item can contain Plug Rate Resources in its Worksheet — the Item stays Priced, but the Plug Rate Resources show in Anomaly Review separately. See Item entity spec and BR-019d.


4b. Modifiers (numeric rate / quantity adjusters)

Modifiers are admin-curated numeric attributes that adjust the cost math when a Resource is used. Unlike flags, modifiers carry a value and apply a defined math operation to the Worksheet Resource’s contribution.

Modifier Catalog model

  • Admin maintains a Modifier Catalog — a narrow list of available modifiers, each with a declared scope (which Resource Types it applies to), a math operation, and a value unit.
  • When creating / editing a Resource, the estimator picks applicable modifiers and enters a default value for each.
  • No modifiers selected is valid — simple Resources with no adjustments just carry a raw rate.
  • Modifier default values flow into Worksheet Resources as initial values and can be overridden per-use (per-instance override — see §6 and Worksheet spec).

Math operations (closed list for v1)

Four operations cover all expected use cases. Application order when multiple modifiers apply: quantity → rate → (qty × rate) → lump-sum-add → total-multiplier.

OperationFormulaValue meaningExample
quantity_multiplierfinal_qty = qty × valueMultiplier applied to quantity (e.g., 1.05 for 5% wastage)Wastage on materials
rate_adderfinal_rate = rate + valueFlat addition to unit rate (same unit as rate)Cartage +$2/m³
lump_sum_addfinal_cost += valueFixed addition to total costMobilisation fee $500
total_multiplierfinal_cost = total × valueMultiplier applied to total costWeekend penalty 1.5×

Example modifiers (illustrative catalog entries)

ModifierOperationValue unitScopeExample default
Wastagequantity_multiplier% (stored as 1.0X)Material1.05 (5% wastage)
Cartage per unitrate_adder$ per resource unitMaterial$2.00 / m³
Supplier minimum chargelump_sum_add$Material$250
Weekend penaltytotal_multiplier×Labour1.5
Public holiday penaltytotal_multiplier×Labour2.0
Travel allowance per dayrate_adder$ per dayLabour$50
Tools allowancelump_sum_add$Labour$120
Fuel raterate_adder$ per hrPlant$8.50
Mobilisation feelump_sum_add$Plant, Subcontract$1,800
Bondtotal_multiplier% (as 1.0X)Subcontract1.05
Insurance levytotal_multiplier% (as 1.0X)Subcontract1.02

Full list and default values are admin-defined at catalog setup. The catalog is intended to be narrow and closed — each modifier should have a clear, defensible math operation.

Per-instance overrides

When an estimator drags a Resource into a Worksheet, the resulting Worksheet Resource inherits the Resource’s modifier list with its default values (snapshotted per BR-040 extension). The estimator can then override the value per-use — e.g., “wastage is usually 5% but this confined-access install is 10%.”

Overrides are local to the Worksheet Resource; they don’t propagate back to the Resource catalog.

Modifier Definition — catalog entry attributes

Each entry in the Modifier Catalog is a Modifier Definition with the following structure:

AttributeTypeRequiredDefaultNotes
idUUIDgeneratedSystem-managed
namestring (short text)Human-readable name (e.g., “Wastage”, “Cartage per unit”). Unique within the active (non-archived) set
descriptionlong textnullAdmin guidance — when to apply, what it means
scopemulti-select enumResource Types this Modifier applies to: any combination of All / Labour / Material / Plant / Subcontract / Other
math_operationenumOne of: quantity_multiplier · rate_adder · lump_sum_add · total_multiplier (see operations table above)
value_unitstringDisplay unit for the Modifier value (e.g., %, $, $/m³, × (multiplier)); drives UI input formatting
default_valuenumber (decimal)nullOptional default numeric value seeded into Resources that pick this Modifier
is_built_inbooleanfalseTrue for catalog entries seeded at launch. Built-in entries cannot be deleted, archived, or have their name / math_operation / value_unit changed
archived_attimestampnullSoft-delete marker. Archived entries remain visible on historical Resources but are not selectable for new Resources. Un-archive supported
created_at / updated_at / created_by / updated_bysystemAudit

Lifecycle: Modifier Definitions support soft-delete (archive) only — never hard-delete. Existing modifier instances on Resources and per-instance overrides on Worksheet Resources retain their values through archive. Built-in entries are protected (cannot be archived or deleted; description, scope, and default_value are editable). Catalog management is Admin + Lead Estimator per roles-permissions.md §3.

Stacking same-operation Modifiers: when two Modifiers of the same operation apply to the same Worksheet Resource (e.g., two total_multipliers like Bond × Insurance levy), they apply multiplicatively in catalog-defined order (e.g., 1.05 × 1.02 = 1.071). Mutual-exclusion enforcement (e.g., Weekend penalty vs Public holiday penalty — only one realistically applies) is admin-configurable per Modifier — see §11 Open items.

Worked math example

Resource: Concrete 32MPa @ $230/m³ with these modifiers:

  • Wastage: 1.05 (5%)
  • Cartage per unit: $2/m³
  • Supplier minimum charge: $250

Item uses 8 m³:

Step 1 — quantity_multiplier:      final_qty  = 8 × 1.05 = 8.4 m³
Step 2 — rate_adder:                final_rate = $230 + $2 = $232/m³
Step 3 — (qty × rate):              interim    = 8.4 × $232 = $1,948.80
Step 4 — lump_sum_add:              interim    = $1,948.80 + $250 = $2,198.80
Step 5 — total_multiplier (none):   final_cost = $2,198.80

Contribution to Item cost: $2,198.80.


5. Lifecycle States

Resources do not have a formal lifecycle state machine. Once created, a Resource persists in its Price Book with a rate that can be changed by:

  • Direct edit (in Price Book management UI) — updating rate in place
  • Price Book Adjudication — replacement of the Resource’s rate during adjudication award (BR-062)
  • Subcontract Package Adjudication — creation of new Subcontract Resources or update of existing ones (BR-063)

Snapshot semantics: when a Resource’s rate changes, any Worksheet Resources that reference it keep their snapshot rate (the rate at time of drag-in). The Worksheet Resource does not auto-update. Divergence is flagged by Anomaly Review (BR-042, BR-043).

How new Resources are created

Resources originate from three pathways:

  1. Manual creation in a user-created Price Book — Admin or Lead Estimator via Price Book Editor. Full control over all attributes (description, rate, unit, flags, modifiers, categorization).

  2. System-generated from Subcontract Package Adjudication — When a subcontract package is adjudicated, new Resources of type Subcontract are created in a system-generated Price Book (BR-063). The winning supplier’s bid becomes the Resource’s rate.

  3. Forked from a Worksheet Resource — When an estimator forks a modified Worksheet Resource via the fork action (BR-049), a new Resource is created in the Estimate’s auto-generated Project-Specific Price Book. The new Resource inherits Flags, Modifiers (with defaults), Unit, Resource Type, and Categorization from the original Worksheet Resource; the modified rate becomes the new Resource’s rate, and the estimator can rename the description.


6. Relationships

Inbound (things referring to Resource)

FromCardinalityNotes
Worksheet ResourceWR M:1 ResourceVia Worksheet (transitive: Worksheet M:M Resource)
Worksheet RecipeWRec M:1 ResourceVia Recipe’s Worksheet (transitive: Recipe Worksheet M:M Resource via Worksheet Resource)
Price Book AdjudicationPBA M:M ResourceResources being adjudicated; scope of comparison
Subcontract Package AdjudicationSPA → Price Book → ResourceProduces Resources of type Subcontract (indirect link)

Outbound (things Resource references)

ToCardinalityRequiredNotes
Price BookResource M:1 Price BookEvery Resource lives in exactly one Price Book (BR-021)
UnitResource M:1 UnitEvery Resource has a Unit (BR-020); LS is valid
Flag DefinitionResource M:M Flag DefinitionVia flag instance (boolean presence or enum value). From Flag Catalog filtered by Resource Type
Modifier DefinitionResource M:M Modifier DefinitionVia modifier instance (carries numeric default value). From Modifier Catalog filtered by Resource Type
Categorization OptionResource M:M CatOptionMulti-select tagging for reporting

7. Validation / Invariants

Rules that must hold at all times:

Resource-level invariants:

  1. Unit mandatory. unit cannot be null (BR-020); LS is valid for any Resource.
  2. Rate required. rate cannot be null and must be ≥ 0.
  3. Exactly one Price Book. Every Resource price_book_id points to exactly one Price Book; no orphaned Resources (BR-021).
  4. Resource Type enum. resource_type must be one of: Labour, Material, Plant, Subcontract, Other. Enforced at write time.
  5. Flag scope consistency. Each selected flag must have a scope that includes the Resource’s Type. Enforced at pick time in UI; validated server-side on save.
  6. Modifier scope consistency. Each selected modifier must have a scope that includes the Resource’s Type. Modifier value must be numeric and match the declared value unit.
  7. Modifier value required. If a modifier is selected, its value cannot be null. Default value comes from the catalog definition but can be overridden at Resource level.
  8. Subcontract origin. A Resource with resource_type = Subcontract must belong to either a user-created Price Book or a system-generated Price Book produced by a Subcontract Package Adjudication (BR-024).
  9. Activity Code tiering. activity_code (Code Option ref) is soft-required in the Estimate working view; hard-required at Cost Management export (BR-127).
  10. Subcontract lineage via Price Book. System-generated Subcontract Resources inherit their Adjudication lineage through their containing Price Book (the Price Book carries subcontract_package_adjudication_id). Resources themselves do not carry an Adjudication FK (BR-066; domain-model v0.3).

Flag Definition (catalog entry) invariants:

  1. Name unique within active set. Two active (non-archived) Flag Definitions cannot share the same name. Archived entries are exempt (allows un-archive without name collision).
  2. Scope non-empty. Flag Definition scope must contain at least one entry (All or one or more Resource Types).
  3. Enum requires options. If value_type = enum, allowed_options must contain ≥2 entries. If value_type = boolean, allowed_options must be null or empty.
  4. Default value validity. If default_value is set: for boolean, must be "true" or "false"; for enum, must be one of allowed_options.
  5. Built-in protection. Flag Definitions with is_built_in = true cannot be deleted, archived, or have their name / value_type / allowed_options changed. Description and scope are editable.
  6. Soft-delete only with references. Flag Definitions referenced by any Resource cannot be hard-deleted; archive is the only path. Existing flag instances retain their values through archive.

Modifier Definition (catalog entry) invariants:

  1. Name unique within active set. Two active (non-archived) Modifier Definitions cannot share the same name.
  2. Scope non-empty. Modifier Definition scope must contain at least one entry.
  3. Math operation enum. math_operation must be one of the four defined operations.
  4. Value unit required. value_unit cannot be null (drives UI input formatting and value validation).
  5. Built-in protection. Modifier Definitions with is_built_in = true cannot be deleted, archived, or have their name / math_operation / value_unit changed. Description, scope, and default_value are editable.
  6. Soft-delete only with references. Modifier Definitions referenced by any Resource or per-instance override on a Worksheet Resource cannot be hard-deleted; archive is the only path.

8. Derived / Computed Attributes

AttributeDerivationNotes
is_plug_rateCheck if “Plug Rate” flag is set (future: after BR-026 locks the taxonomy)Placeholder rates caught by Anomaly Review before submission
item_unit_rateNot directly on Resource; computed when Resource is used in an Item’s contextWhen a Worksheet Resource is applied to an Item with a different Unit, the item’s implicit unit rate = resource_rate × (resource_unit → item_unit conversion). Conversion is explicit in Worksheet (no auto-convert in v1). Used by Reference Rate matching (BR-144–146)
current_price_book_statusDerived from price_book.source_type”User-created” or “System-generated” (from Adjudication). Determines visibility and editability

9. Worked Examples

Example A — Simple Labour Resource

A standard carpenter day rate with regional and tool inclusions:

Resource:
  description: "Carpenter — general (Auckland, includes small tools)"
  rate: 185.50
  unit: day
  resource_type: Labour
  flags: [
    "Standard rate" (not public holiday / weekend),
    "Auckland region",
    "Includes small tools"
  ]
  price_book_id: <Price Book "In-House Labour Rates — May 2026">
  categorization_options: [
    "Auckland" (Region categorization),
    "Carpentry" (Trade categorization)
  ]
  activity_code: <Code Option "C-CARPENTRY">
  notes: "Tools limit: torch, cordless drill, level, tape. No power equipment"

Worksheet Resource (usage in Item "Timber framing"):
  resource: <Resource above>
  quantity: 8 (days)
  snapshot_rate: 185.50/day (captured at time of drag-in)
  snapshot_unit: day

Derived:
  contribution = 8 days × $185.50/day = $1,484

Example B — Material Resource with Cartage and Wastage

A bulk supply item with transport and waste handling:

Resource:
  description: "Reinforcement steel — 500MPa coil (incl. cartage, excluding wastage)"
  rate: 1.25
  unit: kg
  resource_type: Material
  flags: [
    "Includes cartage",
    "Excludes freight" (long-haul separate),
    "Supply-only",
    "Wastage to add separately" (estimator handles wastage in Worksheet as variable)
  ]
  price_book_id: <Price Book "Suppliers — Steel Ltd (May–Aug 2026)">
  categorization_options: [
    "Reinforcement" (Product type),
    "NZ-sourced" (Origin)
  ]
  activity_code: <Code Option "M-REININ">
  notes: "500 kg coils. Cartage covers metro area only; > 50km premium $0.15/kg"

Worksheet Resource (usage in Item "Rebar to perimeter"):
  resource: <Resource above>
  quantity: 12500 × 1.15 (with wastage factor applied as expression in Worksheet)
  snapshot_rate: 1.25/kg
  
  Worksheet also contains:
    Variable: wastage_factor = 0.15 (15% waste allocation)
    Calculation: effective_qty = base_qty × (1 + wastage_factor)

Derived:
  base_qty = 12,500 kg
  effective_qty = 12,500 × 1.15 = 14,375 kg
  contribution = 14,375 × $1.25/kg = $17,969

Example C — Plant Resource with Dry Hire and Term Mismatch

A mobile crane with fuel and operator separate; highlights Anomaly Review potential:

Resource:
  description: "Mobile crane 35T (dry hire, daily rate, no operator)"
  rate: 850.00
  unit: day
  resource_type: Plant
  flags: [
    "Dry hire" (no operator or fuel),
    "Daily rate",
    "Fuel separate",
    "External plant" (rental company)
  ]
  price_book_id: <Price Book "Plant Suppliers — Crane Co (Q2 2026)">
  categorization_options: [
    "Lifting" (Equipment class),
    "Capacity 35T" (Capacity)
  ]
  activity_code: <Code Option "P-CRAN35">
  notes: "Fuel @ $6.50/hr; operator typically $55/hr if needed. Min hire 3 days"

Worksheet Resource (usage in Item "Foundation lifting"):
  resource: <Resource above>
  quantity: 2.5 (days; estimator enters as decimal, unusual)
  snapshot_rate: 850.00/day
  snapshot_flags: ["Dry hire", "Daily rate", "Fuel separate"]

Anomaly Review flags:
  ⚠️ "Plant without operator declared" — Resource is "Dry hire" but Item may need operator; confirm labour is costcd separately
  ⚠️ "Plant term mismatch" — Min hire is 3 days; Worksheet uses 2.5 days
  ⚠️ "Fractional day hire may incur minimum" — typical crane terms

Estimator acts on flags → adjusts Worksheet to 3 days or accepts the note in the record.

Example D — Subcontract Resource from Adjudication

A subcontracted formwork package price after adjudication award:

Resource:
  description: "Formwork package — concrete slab (3m × 12m area)"
  rate: 45.75
  unit: m²
  resource_type: Subcontract
  flags: [
    "Fixed price" (lump, not unit rates),
    "Includes insurance",
    "Construct-only" (no design),
    "Includes temporary works" (site office, safety, etc.)
  ]
  price_book_id: <Price Book "System-generated — Subcontract Package Adjudication #42">
  // lineage to Adjudication lives on the Price Book (price_book.subcontract_package_adjudication_id), not on the Resource
  categorization_options: [
    "Formwork" (Trade),
    "In-house shortlist" (Supplier tier)
  ]
  activity_code: <Code Option "S-FORM">
  notes: "Awarded to XYZ Formwork 23 Apr 2026. Quote ref XYZ-2047. Includes site office, OH&S coord."

Lineage:
  origin: Subcontract Package Adjudication #42 (round 1)
  winning_supplier: XYZ Formwork (Company with Subcontractor role)
  original_item_qty: 36 m² (Item in Subcontract Package "Ground floor slab formwork")

Worksheet Resource (usage in Item "03.02 Formwork — ground slab"):
  resource: <Resource above>
  quantity: 36 (m²; matches Item quantity)
  snapshot_rate: 45.75/m²
  snapshot_flags: [all flags above]

Derived:
  contribution = 36 × $45.75 = $1,647
  Lineage visible: estimator can trace this cost back to the winning adjudication