Package-level declarations
Types
How a storage's presence operators see a stored null and an empty array.
How a storage aggregates. HAVING, top-N by a metric, dense date-histogram fill and the windows may be RESIDUAL; percentiles and distinct counts need the records themselves, so they are NATIVE or NONE.
The profile of an aggregate's read model, Snapshot or EventStream: every record carries an identity, a payload, an event time and every system field, the record metadata shared by both models.
The record layout of one dataset: the whole record is payload, so fields and masks live at the root; the system fields are the dataset's own columns, and one it does not declare (an aggregate id, a deletion flag) is not carried. A dataset has no default scope: what a record's lifecycle means belongs to the dataset.
The Catalog's compilation of one aggregate model (design §5.2): merges the declarations of sources into the logical model under sensitivity, asks the storage adapter for its facts about it, and compiles them into the published QueryModelSchema. The first load is shared by concurrent callers; a refresh reloads the sources and the storage's native structures and replaces the published schema only when it compiles to a different schema: when the version and the native facts are unchanged, the published instance (and the descriptors it has cached) is kept. The 9.1 declaration-file scan runs once, on the first load. A provisional schema is never published: it is answered for provisionalTtl, so a storage that is never written is not asked again on every query, and the first load after that compiles the storage again. Once the storage exists its schema is the one published, at most provisionalTtl after it does.
Aggregated domain event streams: one record per command, typed event payloads under body[].body.
Declares the fields a QueryModelSource infers from the domain types of a built-in model.
compat(wow<9.2): what a 9.1 declaration file at wow-query-schema/{context}/{aggregate}/{model}.json means when no 9.2 declaration of that model exists in any source (classpath, working directory or registration bean). 9.2 does not read the 9.1 format, so such a model is served from its inferred schema.
A logical definition is shared unchanged with every native binding snapshot.
How a storage pages. Neither mode has a residual implementation, so each is NATIVE or NONE.
A declared dataset (design 2026-10-10-clickhouse-dataset-query-design.md §4): a table-like record set, such as a BI wide table, queried as the QueryModel.DATASET model of namedAggregate.
Declares a QueryDataset in code: its scope and profile columns, its fields and their sensitivity.
One change to QueryDatasets: a dataset added, replaced by a new declaration, or removed.
Reads dataset files by name. The working directory's file (config/wow/dataset/{context}.{dataset}.json) replaces the classpath's (META-INF/wow/dataset/…), so an operator can adjust a deployed dataset without a rebuild; on the classpath a name must resolve to one file.
What follows QueryDatasets: the Catalog, the gateways. A change is first validated by every listener, in registration order, and refused, with nothing changed, when one throws; it is then applied, which must not fail.
The keys of a dataset file (META-INF/wow/dataset/{context}.{dataset}.json or config/wow/dataset/…):
The datasets this instance serves, by name. Datasets join and leave at run time (dataset platform design §4.3): declaration files at startup, a registry's published versions afterwards. Reads take no lock; changes are serialized and reach every listener before the next one starts.
The columns that bound a dataset's records to a caller: the tenant, the isolation boundary every caller scope pins, optionally the owner and space, and the tags AbacQueryPolicy restricts by.
Where a logical field is stored for one capability. physicalScope is the physical container physicalField lies in whose elements storage indexes as separate documents, such as an Elasticsearch nested mapping, so a backend addresses the field through it; null when there is none.
A native binding as a storage adapter reports it; physicalScope is QueryFieldBinding.physicalScope.
The effective capabilities of one field, compiled once from its value definition, the capabilities storage grants it, its sensitivity, its element scopes and the model's storage support (design §5.2, P2). Admission checks each reference against this record, the descriptor publishes it, and it lists each capability with the cost class its spec states, which an entry gate that refuses expensive operations also reads. The value rules of the operator, group and metric specs are decided here, once, so admission and the descriptor cannot disagree about them.
One field or nested value: its shape (kind, types, nullability, structure) and semantics (enum, time, text).
One resolved field of a QueryModelSchema with its capability facts. Facts that depend only on the field and its schema are computed once per instance; static fields are resolved once per schema.
A serialized member: its JVM type and its effective annotations, those declared on the field, getter or inherited property it serializes from. Meta-annotations are not expanded.
How the Catalog compiles one aggregate model: from its context and its storage's facts to a schema provider.
Record layout and invariants of one QueryModel: the built-in Snapshot and EventStream, and each declared dataset.
Published facts only: model values and operation-specific native locations.
Type inference for the query Catalog: reports how a JVM type serializes, as raw facts.
Schema path parts; keys are captured by logical lookup, items describe array traversal.
The Catalog (design §4, §5.2): compiles the query schema of every aggregate model this instance serves, one provider per aggregate and model, with its compiler (by default the model sources merged under the sensitivity policy, see QueryModelCompiler.of). Each storage only reports its native facts, through the storage adapter storages locates. Gateways, point reads and the capability descriptor all read their schema here.
Declares, in code, what inference cannot know about a model's fields; the same vocabulary as a declaration file (see QuerySchemaDeclarationProperties).
The keys of a declaration file (META-INF/wow/query-schema/{context}.{aggregate}.{model}.json or config/wow/query-schema/…). A file only supplements what inference cannot know, in the capability descriptor's vocabulary:
How the query subsystem treats sensitive fields beyond their declared level.
A storage's port into the Catalog (design §5.2, §5.5): it reports what its native structures (indexes, mappings, validators) prove about a logical model, and nothing else. The Catalog merges the model's sources and compiles the reported facts into a QueryModelSchema, applying every rule that does not depend on the storage.
What a storage proves about one read model, in the storage-neutral vocabulary of capabilities: for each logical path, the capabilities its native structures can execute and the physical location each binds to, with the projection and response locations; and the storage's model-wide support. Which native types, index kinds or mapping options prove a capability is the storage's knowledge; what a logical value must be for a capability to apply at all is the Catalog's (compile).
A storage-neutral family of native types a logical value may be stored as. A storage adapter maps each family to its own native types (BSON types, Elasticsearch field kinds); which families a logical value needs for a capability is the Catalog's decision (storageFamilies).
Where a storage still departs from the strict table of storageFamilies. Each rule is a known divergence between storages, kept so that every adapter reproduces today's capabilities exactly; the defaults are the strict table.
Where the QuerySchemaCatalog finds the storage of an aggregate model: the QueryStorageAdapter of the query backend that serves it, or null when no backend does. The Catalog needs a storage's facts only, never its backend; QueryBackendStorages reads them from the backend factories.
One value of a serialized type.
One immutable logical value shape, shared by backend schema snapshots. Collection inputs are snapshotted; mutable enum JSON is detached on read.
The error catalog (design §5.9): every rule a query can break, as structured facts. Each violation names its stable code, renders its message from its facts, and belongs to a Kind that decides the error it becomes (rejection): the one place a rejection is rendered. Codes are a contract (added, never renamed); texts are not.
Materialized aggregate snapshots: one record per aggregate, payload under state.
What a storage declares beyond each field's native capabilities; bound into the schema by its adapter.
How storage supports a query feature (design §5.5).
The storage adapter of an aggregate model that has no query backend: every load fails with message. QuerySchemaCatalog skips it, since there is nothing to load or revalidate.
Functions
Flattens nested unions into their non-union alternatives; any other value is its own single alternative.
The fields a query on this model can name as written: the system fields and the declarations of sources, merged under sensitivity into the logical model as DefaultQueryModelSchemaProvider merges them, before any storage facts. Fields under a map, whose keys are the caller's, are left out. The OpenAPI document lists them, so it agrees with the declarations the Catalog compiles; what the storage supports for each is the capability descriptor's.
Describes how this model can be queried on one entry, derived from the same capability table and operator specs that admission reads, so the description and admission cannot disagree.
The effective SensitivityLevel of this member, or null when it is not sensitive: the same rule the query schema applies (effectiveMaskRule), for other Wow engines (BI) that must honour @Sensitive the same way.
Whether any alternative of this value is an array, so storage may flatten it into multiple values.
Whether this value can be an element scope: every non-null alternative is an array whose non-null items are all objects, so a predicate can match one element as a whole.
Operations on primitive arrays use one member layer, without flattening the definition.
Returns the record identity of this schema's model, rejecting custom models that define none.
The native type families this scalar value needs for capability: one set per declared alternative, and storage proves the capability when its native types cover every set and fall in some set. An empty list, or a list with an empty set, means no storage can prove the capability for this value.
The logical field a system-field filter targets on this schema's model (QueryModelProfile.systemField). A model without an identity rejects an identity filter; a profile that does not carry another system field rejects its filter as naming an unknown field. A custom model without a profile shares the record metadata fields.
The query meaning of a QueryTypeFact at field: its structure as a declaration, with properties that are not valid query path segments left out, standard date formats as Temporal.Date, and member annotations applied.