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
2 changes: 1 addition & 1 deletion docs/spec/surfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ entities:
- **`identity: <field>`** on the owner entity names the string field (conventionally a unique e-mail) matched against the login username. With no matching record, the scoped surface is simply empty — never an error.
- **`personal: true`** on a record-owning to-one relation generates a personal controller: reads are filtered to the caller's mapped record, the owner FK is forced server-side on writes, and a foreign record is not found. At most one `personal:` relation per entity; the target must declare `identity`; never put it on a composition parent — composition children inherit the owner's scope through their parent.
- **`partner: true`** is the exact mirror for **external** parties (customers, suppliers) on a partner surface, gated by the corresponding partner roles. An entity may carry both a `personal:` (staff) owner and a `partner:` (external) owner at once.
- **`personalReadOnly: true`** (with `personal: true`) makes the personal surface see-only: create / update / delete are refused and the scoped pages render without new / edit / delete. Use it for records an owner may see but never author — a balance, a payslip. Composition children inherit it through the parent.
- **`personalReadOnly: true`** makes a personal surface see-only: create / update / delete are refused and the scoped pages render without new / edit / delete. Declared **with `personal: true`** it closes the declaring entity's own surface — use it for records an owner may see but never author, a balance or a payslip. Declared on a **composition relation** it closes only that child's inherited surface while the parent stays writable: the scope still comes from the parent, the writes do not. That is the shape of a header the owner authors whose lines a generator writes — a leave request whose day rows an approval flow charges against an entitlement — where closing the parent would close the header the person must author. The child's scoped pages, the parent page's items panel and its child panels all render without a write affordance. It is an authoring error to declare it on a relation that is neither `personal: true` nor a composition, on a second composition of the same entity, or on a child whose master has no personal surface to inherit.
- **`sensitive: true`** on a field (never the PK, the identity field, or the owner FK) strips it from the scoped responses and ignores it on scoped writes — use it for billing rates and amounts the owner must not see. It is enforced server-side, not just hidden.

::: info Normative
Expand Down