Skip to content

FR: backend-agnostic projection materialization — one derivation spec, N lowerings (first non-RDB slice + capability matrix) #211

Description

@dmealing

Summary

ADR-0007 defines a paradigm-subtyped source catalog (rdb / document / search / … with per-paradigm @kind/@role); #195 rules that origin.* declares semantic intent and the SQL view is just one lowering ("anything that only makes sense for an RDB is a defect"). Both halves are accepted; the composition is missing. Today derivation is welded to source.rdbSelectSpec → a SQL view only. This FR generalizes projection materialization from RDB-only to one derivation spec, N lowerings.

Unifying model

A projection = a declared field set (fail-closed exposure) + a semantic derivation graph (extends for shape, origin.* for data — pure, deterministic, backend-free per #195) + zero-or-more materializations (source.<paradigm> @kind @role). Materialization is a property, never the essence: the same node materializes as a SQL view, an Elasticsearch index, a Mongo view, or nothing (a wire-only DTO). FR-024 already says this for surfaces ("one projection serves multiple surfaces"); extend it to backends.

What maps cleanly

  • origin.passthrough = field mapping / denormalized copy. Universal.
  • origin.computed = per-row expression. Mongo $project 1:1 (meta migrate: aggregate/monitoring read-model views can't be modeled as projections — 4 missing origin/field capabilities #195 already calls it the most portable construct).
  • origin.aggregate / origin.first = same semantic contract (deterministic reduction/argmax along @via, pinned empty-set/tie-break/null behavior); only the evaluation time differs — query-time (RDB view), refresh-time (matview), write/maintenance-time (search index). Generalize source-kinds.md's matview note into doctrine: evaluation/refresh discipline is a property of the materialization (@kind/@role), never of the derivation. A search index is, semantically, a materializedView in a different paradigm — the taxonomy already contains its hardest case.
  • origin.collection (nested view-objects) — never lowers to RDB view DDL (a payload-assembly concept today), but lowers natively to document/search (nested docs, ES nested mappings). The document paradigm completes the origin vocabulary rather than straining it.

What is legitimately per-backend (and what is NOT)

Per-backend: physical attrs (@index/@analyzer/@mappingsRef, exactly where @column/@schema live for rdb), lowerings, and an origin × (paradigm, @kind) capability matrix with load-time errors (e.g. origin.first on a paradigm that can't express argmax → a clear error, not silent omission — the lesson of extract-view-spec.ts:226-231). Not per-backend origin vocabularies or projection subtypes (a defect per #195). Search scoring/analyzers are physical/query-time, not derivation — they never touch the taxonomy.

Proposed first slice

  1. Generalize SelectSpec → "one derivation spec, N lowerings."
  2. Implement the first non-RDB materialization (source.document or source.search from the ADR-0007 catalog).
  3. Ship the capability matrix with load-time errors.
  4. Give origin.collection its first persisted lowering (document/search nested).

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:metamodelMetamodel vocabulary / loaderenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions