Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion versions/1.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,9 @@ A roll-up writes onto the child's own parent. For a total grouped by SEVERAL rel

The parent MAY be owned by another model. A roll-up whose `via` relation is a cross-model reference maintains a field on an entity that model owns: the child stays local (it owns the event that drives the recompute) while the parent's coordinates come from the owner's model, so a time-tracking model can keep an `actualHours` total on a project the projects model owns.

**Normative.** For a cross-model parent, the `via` relation's model MUST be declared in [`uses`](#reuse-dont-redefine--uses), and the parent field is validated against the owner's model at generation time rather than against the local document. A conforming generator MUST report a roll-up it cannot resolve (an undeclared model, or a field the owner does not have) instead of dropping it silently. The `capacity` / `balance` / `status` variants remain local-only: they read the parent's own limit and status values, which belong to the model that owns the parent.
A cross-model parent MAY also declare `capacity` and `balance`. Both are arithmetic on the parent's own numeric columns — the capacity is read, the balance is written alongside the sum — and the overdraw check they install belongs to the **child**, which is local on this direction. That is what lets both sides of an n:m allocation be guarded from the module that owns the link rows: an invoice cannot be paid past its payable, and the payment it is paid from cannot be applied past its amount.

**Normative.** For a cross-model parent, the `via` relation's model MUST be declared in [`uses`](#reuse-dont-redefine--uses), and the parent's `field`, `capacity` and `balance` are validated against the owner's model at generation time rather than against the local document. A conforming generator MUST report a roll-up it cannot resolve (an undeclared model, or a column the owner does not have) instead of dropping it silently, MUST refuse a cross-model `balance` declared without a `capacity` (the balance is defined as `capacity - sum`, so on its own it names a column nothing fills), and MUST enforce the capacity on the child's own write path with the same refusal a same-model roll-up emits. The `status` variant remains local-only: it moves the parent through the owner's own status values, which belong to the model that owns the parent.

### aggregates — keyed cross-entity totals

Expand Down