Description
Summary
FR-024 §7 "view behavior on the entity" is doctrine-complete and loader-validated — an object.entity may carry a non-primary read-only 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 the design promises the view DDL is emitted ("one emitter, two hosts"). The loader even licenses it (ERR_DERIVED_FIELD_NO_READ_SOURCE). But the schema pipeline never implements it, in two places:
1. Derived fields leak into the write table. migrate-ts/src/expected-schema.ts:377 builds a column for every entity.fields() — it never excludes origin-bearing (derived) fields:
for (const field of entity.fields()) {
// … flattenObjectField / buildColumn — no check for an origin child
}So a field whose data comes from a join (origin.passthrough @from:"Other.col" @via:"…") gets a spurious column on the write table. Worse: when that column name matches the read-view's own SELECT alias (SELECT E.*, O.col AS col …), the generated CREATE VIEW collides on a duplicate column.
2. The read-view is never emitted. isWriteThrough() (codegen-ts/src/projection/projection-detector.ts:24) is defined, exported (index.ts:83), and tested — but has no call site. buildProjectionViews only walks isProjection objects, so a write-through entity's replica-view DDL is never emitted or owned, despite FR-024 §7.
Impact
An adopter following the FR-024 §7 / entity-read-view on-ramp (model the join extras as derived fields on the entity, the intended clean modeling) gets a wrong table — derived join columns leak in, and can collide with the view — and no view is created. That is a silent-corruption class, more severe than a docs gap. It's the exact reason a downstream migration currently has to quarantine the view-only columns out of the entity's field set as a workaround instead of modeling them properly.
Proposal
- Exclude origin-bearing fields from the column loop in
expected-schema.ts(a field with anorigin.*child is derived → read-only → not a write-table column). - Wire
isWriteThroughentities intobuildProjectionViewsso a write-through entity's replica-view DDL is emitted and owned exactly like a projection's view — reuse the one canonical emitter ("one emitter, two hosts"). The dead-but-testedisWriteThroughis presumably the intended hook.
Not covered by the open issues
This is the schema-pipeline half of FR-024 §7. The entity-read-view docs issue is on-ramp docs only; the view-level-filter and join-type issues extend the view emitter but don't wire the write-through host. So without this, the whole "add the read source and the derived fields" story produces incorrect schema.
Activity
docs(#206): mark the entity-read-view schema pipeline as pending #213 …
fix(#213): exclude derived fields from the entity write table + write…
fix(#213): emit the entity read-view's replica view (isWriteThrough →…
test(#213): real-PG round-trip gate for the write-through entity read…
docs(#213): entity-read-view status — schema half shipped, read half is
feat(#214): entity read-view codegen READ half (TS reference)
dmealing commentedon Jul 18, 2026
Shipped in the coordinated 0.17.0 (npm / PyPI / NuGet) · 7.9.0 (Maven Central) release — live on all four registries (PR #215, tag
v0.17.0). Cross-port, conformance-gated. See CHANGELOG [0.17.0].fix(runtime-ts,codegen-ts): write-through REST routes read through th…
docs(agent-context): teach entity read-view first for derived read co…
fix(codegen-ts): a projection's view name selects by role, not declar…