Summary
FR-024 §7 "view behavior on the entity" is shipped — an object.entity may carry a non-primary source.rdb @kind:view plus derived (origin.*) fields; writes route to the table, reads to the view, derived fields are read-only + excluded from write codecs, and meta migrate emits the view DDL (2026-06-12-fr-024-entity-surfaces-projections-design.md:251,386; loader ERR_DERIVED_FIELD_NO_READ_SOURCE, validation-passes.ts:1355). But docs/features/source-kinds.md reads as "read-only @kind ⇒ projection, full stop," so an adopter migrating a legacy SQL-view-heavy schema reaches for object.projection and immediately hits "enumerate every column" (the wildcard was removed at B4b, extract-view-spec.ts:598).
The result is that the single most common legacy view shape is modeled the hard way (or not at all).
The pattern that needs an on-ramp
CREATE VIEW order_with_customer AS
SELECT o.*, c.name AS customer_name -- the entity's own columns + a joined extra
FROM orders o, customers c
WHERE o.customer_id = c.id;
This is not a projection — it is the Order entity with a read route. The entity's own field set is the o.*; only the extra (customerName via the customer_id reference) needs declaring, as a derived origin.passthrough field. One node, one generated class, writes→table, reads→view.
Ask (docs + adoption; no metamodel change)
- Surface entity read-views prominently in
source-kinds.md / the adoption docs as the first answer for SELECT A.*, extras FROM A … legacy views — today the docs point straight at projection.
- Add an entity-vs-projection decision table:
| Use an entity read-view when |
Use a projection when |
| extras sit over the entity's own table |
it is an independent exposure contract |
| same read trust-domain (a new entity field appearing in the view is correct, not a leak) |
subset / renamed columns / versioned / external consumers |
| you can still INSERT the base and it's the record of truth |
keyless, multi-base, or proc-backed; all-derived, borrowed/no identity |
- State the honest boundary that still pushes to a projection (or other FRs): renamed base columns (a field carries one
@column per paradigm — a rename-in-view is the projection's whole point), and row-filtered views (no view-level WHERE yet — separate filter FR).
Why it matters
The entity-read-view path is the cleanest home for the largest class of legacy views and is already implemented — it just isn't discoverable. A short docs pass + a decision table turns "re-enumerate 40 columns as a projection, or hand-write the view" into "add the read source and the extra derived fields."
Summary
FR-024 §7 "view behavior on the entity" is shipped — an
object.entitymay carry a non-primarysource.rdb @kind:viewplus derived (origin.*) fields; writes route to the table, reads to the view, derived fields are read-only + excluded from write codecs, andmeta migrateemits the view DDL (2026-06-12-fr-024-entity-surfaces-projections-design.md:251,386; loaderERR_DERIVED_FIELD_NO_READ_SOURCE,validation-passes.ts:1355). Butdocs/features/source-kinds.mdreads as "read-only@kind⇒ projection, full stop," so an adopter migrating a legacy SQL-view-heavy schema reaches forobject.projectionand immediately hits "enumerate every column" (the wildcard was removed at B4b,extract-view-spec.ts:598).The result is that the single most common legacy view shape is modeled the hard way (or not at all).
The pattern that needs an on-ramp
This is not a projection — it is the
Orderentity with a read route. The entity's own field set is theo.*; only the extra (customerNamevia thecustomer_idreference) needs declaring, as a derivedorigin.passthroughfield. One node, one generated class, writes→table, reads→view.Ask (docs + adoption; no metamodel change)
source-kinds.md/ the adoption docs as the first answer forSELECT A.*, extras FROM A …legacy views — today the docs point straight at projection.@columnper paradigm — a rename-in-view is the projection's whole point), and row-filtered views (no view-level WHERE yet — separate filter FR).Why it matters
The entity-read-view path is the cleanest home for the largest class of legacy views and is already implemented — it just isn't discoverable. A short docs pass + a decision table turns "re-enumerate 40 columns as a projection, or hand-write the view" into "add the read source and the extra derived fields."