Parameter Value
One canonical value a ParameterKey can take, optionally carrying measured quantities. Owned by bim-ontology; product-marketplace reads it. No lifecycle.
Purpose
A parameter value is one canonical value a ParameterKey can take — Brushed Nickel for Finish, 36 in for Width. It is defined once and reused everywhere: ClassParameter allowed-value sets, ModelParameter allowed values, and VariantParameter selections all point at the same row rather than restating the value.
When the value is measurable it carries QuantityValue parts, each a number plus a unit plus a role. A nominal value carries none.
Airtable tables parameter_values and quantity_values, both in the BIM Ontology base.
Ownership boundary with Product Marketplace
ParameterValue is owned here. The aggregate lives in bim-ontology/core/domain/parameter-value/; there is no product-marketplace parameter-value domain directory. Product Marketplace consumes it through an explicit cross-module import — CatalogReadUseCases.ts imports ParameterValue and ParameterValueGroup from @modules/bim-ontology and serves them over its internal catalog-read routes. The junctions that reference values (ModelParameter, ModelParameterAllowedValue, VariantParameter) stay in that domain.
No lifecycle
A parameter value has no lifecycle and emits no domain events. It has no pullDomainEvents, and nothing in the module subscribes to a value change. Update is a full replace: UpdateParameterValueUseCase reconstructs the aggregate from the request under the existing id, so the request body carries the whole value including its quantity set. Omitting quantityValues clears them.
Quantity values and roles
QuantityValue is a value object of value, unitId, and role. The role set is exactly seven, and the names are two-word tokens with a space, not separate min / max roles:
| Role | Meaning |
|---|---|
primary | The single headline reading |
primary min / primary max | The primary range endpoints |
alternate | A second reading in another unit system or convention |
alternate min / alternate max | The alternate range endpoints |
modifier | A qualifying reading that is neither headline nor alternate |
A quantity value is rejected unless its value is finite and its unitId is non-empty.
unitId points at a Unit, Airtable units. A unit belongs to neither the value nor the key: quantity values reference it, and ParameterSpec constrains which units are legitimate for the key through its own units link and unitSystem. Unit is a reference catalog with a read-only GET …/units surface and no entity page of its own — see ubiquitous language.
Invariants
Enforced by ParameterValue.rehydrate, which create delegates to, so create and replace are validated identically:
- A value belongs to exactly one parameter key.
nameis required and non-empty after trimming.- At most one
primaryquantity value. Two primaries is a domain error, not a last-write-wins. - Ranges require both endpoints.
primary minandprimary maxmust both be present or both absent; the same rule applies independently toalternate min/alternate max. A half-open range is refused. - Every quantity
valuemust be finite and everyunitIdnon-empty.
Violations surface as ParameterValueDomainError. The application layer adds two reference checks that the aggregate cannot see: the referenced key must exist (ParameterKeyNotFoundError) and, on replace, the value itself must exist (ParameterValueNotFoundError).
Note what is not enforced: nothing checks the quantity unit against the referenced key’s ParameterSpec unit list, and nothing requires a value to be in an allowed-value set before it is referenced. Both are application-level concerns today.
Domain Events
None. ParameterValue records no events and has no event file.
OpenAPI Operations
Authoring, in bim-ontology:
createParameterValue is a POST and requires an Idempotency-Key; updateParameterValue is a PUT and replaces the authored key, name, code, and quantity set.
Read, over the product-marketplace internal catalog-read surface:
ADRs
The platform series lives in docs/adr/07_Architectural_Decision_Records.md. The per-file series is separate and the numbers collide — see docs/adr/README.md.
| ADR | Decision |
|---|---|
| Platform ADR-0048 | domain_id is the public identifier; never a rec… id in a payload |
| Per-file ADR-0006 | Canonical parameter keys and values with per-level junctions, rather than value arrays on key records |
| Per-file ADR-0007 | MTO allowable values and ranges live on the model-level junction and reference canonical values |
| Per-file ADR-0009 | Parameter table base placement and cross-base sync |