Keys and References
Indexes allow validators to enforce uniqueness and to create references between different parts of a configuration document.
Indexes are defined using the reserved section list vr_key and can appear
either at the document root or inside a section definition.
Once defined, the values collected by an index can be referenced using the
key constraint (see Key).
This mechanism enables referential integrity within a configuration, for example by ensuring that a reference in one section points to an identifier defined elsewhere.
*[vr_key]*
name: "filter"
key: "filter.identifier"
[filter]
type: "SectionList"
[filter.vr_entry.identifier]
type: "text"
[app.start_filter]
type: "text"
key: "filter"
*[filter]*
identifier: "first"
*[filter]*
identifier: "second"
[app]
start_filter: "first"
Rules for Indexes
Index Creation: An index is created by defining a section list named
vr_key.*[vr_key]* name: "filter" key: "filter.identifier"
Uniqueness: All key values collected in an index must be unique. Validators must report an error if a duplicate key is encountered.
*[filter]* identifier: "one" *[filter]* identifier: "one" # ERROR: Identifier must be unique
Placement: A
vr_keysection list may appear either:at the document root, or
inside a node-rules definition for a section.
[app.server] type: "SectionList" *[app.server.vr_entry.vr_key]* name: "connection_id" key: "connection.id"
Scope and Visibility: An index is visible only within the subtree in which it is defined. References outside this scope are invalid.
*[app.server.vr_entry.vr_key]* name: "connection_id" key: "connection.id" [app.connection] type: "text" key: "connection_id" # ERROR: No such index in this scope
Key Field: Each
vr_keyentry must contain akeyfield that specifies one or more values to be indexed.*[vr_key]* key: "filter.identifier"
Optional Name: A
vr_keyentry may define anamefield, which assigns an identifier to the index for use inkeyconstraints.*[vr_key]* name: "filter" key: "filter.identifier"
Design Rationale
Indexes are intentionally scoped to the subtree in which they are defined. This prevents name collisions between unrelated parts of a configuration and keeps validation rules modular and predictable.
A global index space would introduce two problems:
Accidental collisions between unrelated rules using the same index name.
Unnecessary coupling between distant parts of the configuration.
If global or cross-document references are required, they should be modeled
explicitly at a higher level instead of overloading vr_key.
Rules for Keys
Text Name-Path Required: Each
keyvalue must be a text string containing a valid name-path.*[vr_key]* name: "filter" key: "filter.identifier"
Allowed Value Types: A referenced key must point to either a text or an integer value.
*[vr_key]* key: "blog.created" # ERROR: Must reference text or integer [blog] type: "SectionList" [blog.vr_entry.created] type: "DateTime"
Section List + Value Requirement: Each name-path must resolve to:
a section list, and
a value inside each entry of that section list.
*[vr_key]* name: "filter" key: "app.filter.meta.id" [app.filter] type: "SectionList" [app.filter.vr_entry.meta.id] type: "text"
In this example:
app.filteridentifies the section listmeta.ididentifies the value within each entry
Composite Keys: If multiple keys are specified, their combination must be unique across all entries.
*[vr_key]* key: "server.service", "server.protocol" [server] type: "SectionList" [server.vr_entry.service] type: "text" in: "api", "management" [server.vr_entry.protocol] type: "text" in: "https", "json"
Rules for Index Names
Optional Name: An index may define a
nameentry, which is used bykeyconstraints to reference the index.Naming Rules: Index names must follow the ELCL name rules.
*[vr_key]* name: "%my-name%" # ERROR: Invalid ELCL name
Normalization and Comparison: Index names are normalized and compared according to the ELCL name rules.
Underscores and spaces are equivalent, and comparisons are case-insensitive.
*[vr_key]* name: "filter_index" key: "filter.identifier" [app.start_filter] type: "text" key: "Filter Index" # VALID after normalization
Rules for Multi-Key Indexes
Key Combination Representation: Multi-key indexes combine their key values into a single entry, separated by commas (
,).*[vr_key]* key: "server.service", "server.protocol"
[server] # Creates the composite key "api,https" service: "api" protocol: "https"
Design Rationale
While commas could theoretically appear in key values, such cases can be avoided by disallowing commas in fields used as keys. This keeps index representation simple and efficient.
Referencing Parts of a Multi-Key: A multi-key index can be referenced either as a whole or by individual parts using the
key[index]syntax, where the index is zero-based.*[vr_key]* name: "server" key: "server.service", "server.protocol" [server.ports] type: "SectionList" [server.ports.vr_entry.protocol] type: "text" key: "server[1]" # References only the protocol part key_error: "No server with this protocol was configured"