Files
scadalink-design/docs/requirements/Component-TemplateEngine.md
Joseph Doherty d91aa83665 refactor(docs): move requirements and test infra docs into docs/ subdirectories
Organize documentation by moving requirements (HighLevelReqs, Component-*,
lmxproxy_protocol) to docs/requirements/ and test infrastructure docs to
docs/test_infra/. Updates all cross-references in README, CLAUDE.md,
infra/README, component docs, and 23 plan files.
2026-03-21 01:11:35 -04:00

166 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Component: Template Engine
## Purpose
The Template Engine is the core modeling component that lives on the central cluster. It manages the definition, inheritance, composition, and resolution of machine templates — the blueprints from which all machine instances are created. It handles flattening templates into deployable configurations, calculating diffs between deployed and current states, and performing comprehensive pre-deployment validation.
## Location
Central cluster only. Sites receive flattened output and have no awareness of templates.
## Responsibilities
- Store and manage template definitions (attributes, alarms, scripts) in the configuration database.
- Enforce inheritance (is-a) relationships between templates.
- Enforce composition (has-a) relationships, including recursive nesting of feature modules.
- Detect and reject naming collisions when composing feature modules (design-time error).
- Resolve the attribute chain: Instance → Child Template → Parent Template → Composing Template → Composed Module.
- Enforce locking rules — locked members cannot be overridden downstream, intermediate levels can lock previously unlocked members, and nothing can unlock what's locked above.
- Support adding new attributes, alarms, and scripts in child templates.
- Prevent removal of inherited members.
- Flatten a fully resolved template + instance overrides into a deployable configuration (no template structure, just concrete attribute values with resolved data connection bindings).
- Calculate diffs between deployed and template-derived configurations.
- Perform comprehensive pre-deployment validation (see Validation section).
- Provide on-demand validation for Design users during template authoring.
- Enforce template deletion constraints — templates cannot be deleted if any instances or child templates reference them.
## Key Entities
### Template
- Has a unique name/ID.
- Optionally extends a parent template (inheritance).
- Contains zero or more composed feature modules (composition).
- Defines attributes, alarms, and scripts as first-class members.
- Cannot be deleted if referenced by instances or child templates.
- Concurrent editing uses **last-write-wins** — no pessimistic locking or conflict detection.
### Attribute
- Name, Value, Data Type (Boolean, Integer, Float, String), Lock Flag, Description.
- Optional Data Source Reference — a **relative path** within a data connection (e.g., `/Motor/Speed`). The template defines *what* to read but not *where* to read it from. The connection binding is an instance-level concern.
- Value may be empty if intended to be set at instance level or via data connection binding.
### Alarm
- Name, Description, Priority Level (01000), Lock Flag.
- Trigger Definition: Value Match, Range Violation, or Rate of Change.
- Optional On-Trigger Script reference.
### Script (Template-Level)
- Name, Lock Flag, C# source code.
- Trigger configuration: Interval, Value Change, Conditional, or invoked by alarm/other script.
- Optional minimum time between runs.
- **Parameter Definition** *(optional)*: Defines input parameters (name and data type per parameter). Scripts without parameters accept no arguments.
- **Return Value Definition** *(optional)*: Defines the structure of the script's return value (field names and data types). Supports single objects and lists of objects. Scripts without a return definition return void.
### Instance
- Associated with a specific template and a specific site.
- Assigned to an area within the site.
- Can override non-locked attribute values (no adding/removing attributes).
- Bound to data connections at instance creation — **per-attribute binding** where each attribute with a data source reference individually selects its data connection.
- Can be in **enabled** or **disabled** state.
- Can be **deleted** — deletion is blocked if the site is unreachable.
### Area
- Hierarchical groupings per site (parent-child).
- Stored in the configuration database.
- Used for filtering/organizing instances in the UI.
## Composed Member Addressing
When a template composes a feature module, members from that module are addressed using a **path-qualified canonical name**: `[ModuleInstanceName].[MemberName]`. For nested compositions, the path extends: `[OuterModule].[InnerModule].[MemberName]`.
- All internal references (triggers, scripts, diffs, stream topics, UI display) use canonical names.
- The composing template's own members (not from a module) have no prefix — they are top-level names.
- Naming collision detection operates on canonical names, so two modules can define the same member name as long as their module instance names differ.
## Override Granularity
Override and lock rules apply per entity type at the following granularity:
- **Attributes**: Value and Description are overridable. Data Type and Data Source Reference are fixed by the defining level. Lock applies to the entire attribute (when locked, no fields can be overridden).
- **Alarms**: Priority Level, Trigger Definition (thresholds/ranges/rates), Description, and On-Trigger Script reference are overridable. Name and Trigger Type (Value Match vs. Range vs. Rate of Change) are fixed. Lock applies to the entire alarm.
- **Scripts**: C# source code, Trigger configuration, minimum time between runs, and parameter/return definitions are overridable. Name is fixed. Lock applies to the entire script.
- **Composed module members**: A composing template or child template can override non-locked members inside a composed module using the canonical path-qualified name.
## Naming Collision Detection
When a template composes two or more feature modules, the system must check for naming collisions across:
- Attribute names
- Alarm names
- Script names
If any composed module introduces a name that already exists (from another composed module or from the composing template itself), this is a **design-time error**. The template cannot be saved until the conflict is resolved. Collision detection is performed recursively for nested module compositions.
## Flattening Process
When an instance is deployed, the Template Engine resolves the full configuration:
1. Start with the base template's attributes, alarms, and scripts.
2. Walk the inheritance chain, applying overrides at each level (respecting locks).
3. Resolve composed feature modules, applying overrides from composing templates (respecting locks).
4. Apply instance-level overrides (respecting locks).
5. Resolve data connection bindings — replace connection name references with concrete connection details from the site.
6. Output a flat structure: list of attributes with resolved values and data source addresses, list of alarms with resolved trigger definitions, list of scripts with resolved code and triggers.
## Diff Calculation
The Template Engine can compare:
- The **currently deployed** flat configuration of an instance.
- The **current template-derived** flat configuration (what the instance would look like if redeployed now).
The diff output identifies added, removed, and changed attributes/alarms/scripts.
## Pre-Deployment Validation
Before a deployment is sent to a site, the Template Engine performs comprehensive validation:
- **Flattening**: The full template hierarchy resolves and flattens without errors.
- **Naming collision detection**: No duplicate attribute, alarm, or script names in the flattened configuration.
- **Script compilation**: All instance scripts and alarm on-trigger scripts are test-compiled and must compile without errors.
- **Alarm trigger references**: Alarm trigger definitions reference attributes that exist in the flattened configuration.
- **Script trigger references**: Script triggers (value change, conditional) reference attributes that exist in the flattened configuration.
- **Data connection binding completeness**: Every attribute with a data source reference has a data connection binding assigned on the instance, and the bound data connection name exists as a defined connection at the instance's site.
- **Exception**: Validation does **not** verify that data source relative paths resolve to real tags on physical devices — that is a runtime concern.
### Semantic Validation
Beyond compilation, the Template Engine performs static semantic checks:
- **Script call targets**: `Instance.CallScript()` and `Scripts.CallShared()` targets must reference scripts that exist in the flattened configuration or shared script library.
- **Argument compatibility**: Parameter count and data types at call sites must match the target script's parameter definitions.
- **Return type compatibility**: If a script call's return value is used, the return type definition must match the caller's expectations.
- **Trigger operand types**: Alarm triggers and script conditional triggers must reference attributes with compatible data types (e.g., Range Violation requires numeric attributes).
### Graph Acyclicity
The Template Engine enforces that inheritance and composition graphs are **acyclic**:
- A template cannot inherit from itself or from any descendant in its inheritance chain.
- A template cannot compose itself or any ancestor/descendant that would create a circular composition.
- These checks are performed on save.
### Flattened Configuration Revision
Each flattened configuration output includes a **revision hash** (computed from the resolved content). This hash is used for:
- Staleness detection: comparing the deployed revision to the current template-derived revision without a full diff.
- Diff correlation: ensuring diffs are computed against a consistent baseline.
### On-Demand Validation
The same validation logic is available to Design users in the Central UI without triggering a deployment. This allows template authors to check their work for errors during authoring.
### Shared Script Validation
For shared scripts, pre-compilation validation is performed before deployment. Since shared scripts have no instance context, validation is limited to C# syntax and structural correctness.
## Dependencies
- **Configuration Database (MS SQL)**: Stores all templates, instances, areas, and their relationships.
- **Security & Auth**: Enforces Design role for template authoring, Deployment role for instance management.
- **Configuration Database (via IAuditService)**: All template and instance changes are audit logged.
## Interactions
- **Deployment Manager**: Requests flattened configurations, diffs, and validation results from the Template Engine.
- **Central UI**: Provides the data model for template authoring, instance management, and on-demand validation.