Skip to content
Merged
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
31 changes: 31 additions & 0 deletions versions/1.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,36 @@ A guard compares a keyed [aggregate](#aggregates--keyed-cross-entity-totals) aga

`immutableWhen` requires a `function: EntityStatus` relation; `immutable: true` needs none and is mutually exclusive with it. System / workflow writes stay possible — corrections to an immutable record are flow-generated reversals, never edits.

### locksWithMaster — a child collection that outlives its master's lock

An entity's immutability covers **that entity**. A composition child is a different entity, so a
master that locks says nothing about whether its child collections should:

```yaml
- name: Invoice
immutableWhen: "Status == 3" # ISSUED: the document's own content freezes
- name: InvoiceAllocation
locksWithMaster: false # ...but money keeps being recorded against it
relations:
- { name: Invoice, kind: manyToOne, to: Invoice, composition: true, required: true }
```

The canonical case is settlement: an issued invoice's lines are frozen — that is the audit trail —
while payment allocations against it go on being recorded for months. Content and settlement are
different lifecycles on the same document.

> **Normative.**
> `locksWithMaster` defaults to **true**, so a child that says nothing keeps freezing with its
> master.
> A generator MUST NOT extend a master's user-write immutability to a child collection declared
> `locksWithMaster: false` — including the affordances it renders for that collection, not merely
> the writes it accepts. A read-only rendering that the server would have permitted is the same
> defect as a refused write.
> The declaration is only meaningful on a composition child whose master actually declares
> immutability; a generator MUST reject it elsewhere rather than ignore it, since an inert
> declaration is indistinguishable from a working one until someone needs it.
> It does not apply to a document's own line items, which ARE the document's content.

### hierarchy / leafOnly — tree entities

```yaml
Expand Down Expand Up @@ -1366,6 +1396,7 @@ One line per construct, linking into the chapters above.
| [`number`](#document-numbering) | a platform-numbered, gap-free document field |
| [`checks`](#checks--declarative-validations) | cross-field / cross-line validations |
| [`immutableWhen` / `immutable`](#immutablewhen--immutable--user-write-immutability) | reject user writes in a status / append-only |
| [`locksWithMaster`](#lockswithmaster--a-child-collection-that-outlives-its-masters-lock) | a child collection that stays writable while its master is locked |
| [`hierarchy` / `leafOnly`](#hierarchy--leafonly--tree-entities) | tree entities, leaf-only references |
| [calculated fields](#calculated-fields) | server + UI-evaluated expressions, date helpers, call-outs |
| [`relations` / `composition`](#relations) | associations and master-detail compositions |
Expand Down