Every module describes its screens with metadata: Pydantic objects defined in src/cluster_erp/core/metadata.py. This page lists those classes and their main fields as the server-side contract. How the web app renders them is documented on metadata rendering; the desktop client is documented in the desktop section.
Scope and source¶
- Defined in:
src/cluster_erp/core/metadata.py - Count: 45 classes (counted with
grep -c "^class "), plus the aliasLabelDict = dict[str, str](src/cluster_erp/core/metadata.py:7). 186 calls ofEntityMeta(exist undersrc/cluster_erp(counted withgrep -rn "EntityMeta(").
LabelDict maps a language code to a text, for example {"en": "...", "tr": "..."}. Every label, placeholder, help text, and description in the metadata uses it.
How metadata is served¶
A module returns its ModuleMeta from get_metadata() (src/cluster_erp/core/module_base.py:73-74). GET /api/v1/_meta serialises every loaded module's metadata with model_dump(exclude_none=True) after the tenant-field entities are added, into one JSON document {"version": "1.0", "modules": {...}}. The document is built once per process and served with an ETag and a gzip form, and only to a signed-in caller (src/cluster_erp/server/app.py:1518-1556). A field whose value is None is therefore absent from the document.
Module and entity¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
ModuleMeta |
One module's whole description | name, version, description, label, icon, order, sidebar, entities, provides, assistant_starters, home_widgets |
src/cluster_erp/core/metadata.py:719-740 |
EntityMeta |
One entity: labels, endpoints, form, list, detail, actions, and options | label, label_plural, entity_type, endpoints, form, list_view, detail_view, actions, links, identity, facets, tree_view, lock, tenant_fields, photo, parent_entity, is_settings_entity |
src/cluster_erp/core/metadata.py:553-649 |
EndpointMeta |
One HTTP method and module-relative path | method, path |
src/cluster_erp/core/metadata.py:406-408 |
ScopeMeta |
Scopes an entity by a parent entity | entity, field, label, endpoint |
src/cluster_erp/core/metadata.py:411-415 |
EntityMeta checks at construction that the form tabs of its detail view cover every form group that is not create_only, and that they name no unknown group. A mismatch raises ValueError when the module is imported (src/cluster_erp/core/metadata.py:617-649).
Forms and fields¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
FormMeta |
A form as a list of field groups | field_groups |
src/cluster_erp/core/metadata.py:171-172 |
FieldGroupMeta |
A group of fields, optionally conditional or create-only | key, label, group_type, condition, nested_key, create_only, edit_only, description, fields |
src/cluster_erp/core/metadata.py:149-168 |
FieldMeta |
One field | key, label, field_type, required, choices, source, read_only, immutable_on_edit, permission, switch, autofill, weight, help, storage |
src/cluster_erp/core/metadata.py:79-146 |
ChoiceMeta |
One choice of an enum | value, label |
src/cluster_erp/core/metadata.py:10-12 |
ForeignKeySource |
Where a foreign-key picker loads its options | module, endpoint, value_field, display_field, params, hierarchical, create_scope, group_field |
src/cluster_erp/core/metadata.py:21-33 |
CreateScopeMeta |
Pre-fills a field when a record is created from a picker | target_field, source_field, source |
src/cluster_erp/core/metadata.py:15-18 |
ConditionalSourceMeta |
A picker source that applies only under a condition | condition, source |
src/cluster_erp/core/metadata.py:61-63 |
ConditionMeta |
A field-value condition; value may list alternatives separated by a pipe, negate inverts it |
field, value, negate |
src/cluster_erp/core/metadata.py:52-58 |
AutofillMeta |
Copies a value from the selected foreign record into another field | source_fields, target_field, resolve |
src/cluster_erp/core/metadata.py:36-44 |
AutoGenerateRule |
A template that fills a field when other fields match | when, template |
src/cluster_erp/core/metadata.py:47-49 |
DynamicFormSource |
Sub-fields fetched from a driver field's selected record | driver_field, module, endpoint, schema_field |
src/cluster_erp/core/metadata.py:66-76 |
FieldMeta.field_type takes one of 19 values: string, text, integer, float, decimal, boolean, date, datetime, enum, multi_enum, foreign_key, multi_foreign_key, json, hidden_scope_field, file_upload, suggest_combo, dynamic_form, field_list, and string_list (src/cluster_erp/core/metadata.py:82-102). FieldMeta.permission hides a field's value from callers without that permission code; the comment names core/field_access.py as the enforcing code (src/cluster_erp/core/metadata.py:115-119). FieldMeta.switch shows a field only while a tenant display switch is on (src/cluster_erp/core/metadata.py:120-125). FieldMeta.storage is column for shipped fields and extra for tenant-defined fields (src/cluster_erp/core/metadata.py:142-146).
Lists¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
ListViewMeta |
A list screen | paginated, search_enabled, columns, filters |
src/cluster_erp/core/metadata.py:238-242 |
ColumnMeta |
One column | key, data_key, label, width, stretch, align, switch, formatter, choices, display_endpoint, display_field, value_field, legend |
src/cluster_erp/core/metadata.py:175-227 |
FilterMeta |
One list filter | key, label, filter_type, choices, source |
src/cluster_erp/core/metadata.py:230-235 |
SubTableMeta |
Columns of a sub-entity table | columns |
src/cluster_erp/core/metadata.py:380-381 |
ColumnMeta.formatter takes one of boolean, active_flag, date, datetime, decimal, enum, foreign_key, entity_type, entity_record, or i18n_message (src/cluster_erp/core/metadata.py:190-212).
Detail views¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
DetailViewMeta |
A record card | title_field, tabs |
src/cluster_erp/core/metadata.py:299-301 |
DetailTabMeta |
One tab of a record card | key, label, tab_type, custom_widget, entity, entity_module, field_groups, config, condition, scope_param, read_only, completeness_endpoint |
src/cluster_erp/core/metadata.py:252-296 |
CompletenessMeta and CompletenessTierMeta |
Completeness tiers of a record | tiers; key, label, fields |
src/cluster_erp/core/metadata.py:466-473 |
RecordLockMeta |
The field values at which a record becomes read-only | field, values |
src/cluster_erp/core/metadata.py:476-492 |
AvatarMeta |
A record's profile photo | field, endpoint |
src/cluster_erp/core/metadata.py:495-503 |
EmptyStateMeta |
Text and icon of an empty list | icon, title, description, action_label |
src/cluster_erp/core/metadata.py:459-463 |
SemanticGroupMeta |
A named group of fields | key, label |
src/cluster_erp/core/metadata.py:454-456 |
DetailTabMeta.tab_type takes one of form, custom, sub_entity_table, sub_entity_tree, permission_checklist, role_checklist, access_summary, completeness, or read_model_panel (src/cluster_erp/core/metadata.py:255-270). The RecordLockMeta docstring requires values to come from the same constant that the service enforces (src/cluster_erp/core/metadata.py:486-488).
Parties, facets, and composite creation¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
IdentityMeta |
Marks an entity as a facet of a canonical record in another module | field, module, entity |
src/cluster_erp/core/metadata.py:304-313 |
FacetMeta |
A role a party can play, shown inline on the party card | module, entity, link_field, sections, multi, list_endpoint, requires_flag |
src/cluster_erp/core/metadata.py:357-377 |
FacetSectionMeta |
One section a facet contributes to the card | kind, label, form_groups, sub_entity, sub_module, party_scoped, columns, table, scope_param, scope_field |
src/cluster_erp/core/metadata.py:316-354 |
CompositeCreateMeta and CompositeRoleMeta |
Guided creation of a record with role facets in one call | endpoint, roles; key, flag_field, buckets |
src/cluster_erp/core/metadata.py:506-514 |
These classes implement the party unification rule of the project's written engineering rules. See party unification.
Actions and links¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
ActionMeta |
An action on records | key, label, endpoint, scope, icon, condition, conditions, body_fields, body_field_groups, description |
src/cluster_erp/core/metadata.py:418-434 |
ActionConditionMeta |
When an action, tab, or link is offered | field, value, negate |
src/cluster_erp/core/metadata.py:245-249 |
RecordLinkMeta |
A shortcut from a record card to an app screen | key, label, icon, module, section, params, condition |
src/cluster_erp/core/metadata.py:437-451 |
ActionMeta.scope is one of global, single_record, or parent (src/cluster_erp/core/metadata.py:422). See actions and action sheet.
Trees, sidebar, and home¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
TreeViewMeta |
A tree screen | display_key, children_key, parent_id_key, tree_endpoint, nested, scope, max_depth_warning |
src/cluster_erp/core/metadata.py:390-397 |
TreeScopeMeta |
Scope of a tree by another entity | entity, field, list_endpoint |
src/cluster_erp/core/metadata.py:384-387 |
DynamicComponentsMeta |
Levels and values loaded by a trigger field | trigger_field, levels_endpoint, values_endpoint |
src/cluster_erp/core/metadata.py:400-403 |
SidebarMeta |
The navigation of a module | groups |
src/cluster_erp/core/metadata.py:715-716 |
SidebarGroupMeta |
A navigation group | key, label, icon, sections |
src/cluster_erp/core/metadata.py:691-695 |
SidebarSectionMeta |
One screen of a module | key, label, view_type, icon, entity, list_endpoint, tabs, entity_tabs, custom_widget, hidden_from_bar, required_permission, description |
src/cluster_erp/core/metadata.py:664-688 |
EntityTabRef |
One tab of a tabbed_list section |
module, entity, label, icon, list_endpoint |
src/cluster_erp/core/metadata.py:652-661 |
HomeWidgetMeta |
A home-screen widget offered by a module | key, label, icon, size, custom_widget, open_section |
src/cluster_erp/core/metadata.py:698-712 |
SidebarSectionMeta.view_type is one of list, detail, tree, settings, custom, or tabbed_list (src/cluster_erp/core/metadata.py:667). HomeWidgetMeta.size must match the pattern NxM (src/cluster_erp/core/metadata.py:710).
Tenant fields¶
| Class | Purpose | Main fields | Source |
|---|---|---|---|
TenantFieldsMeta |
Declares that an entity accepts tenant-defined fields | buckets |
src/cluster_erp/core/metadata.py:545-550 |
TenantBucketMeta |
One storage bucket for tenant field values | key, label, nested_key, group_keys, placement_group_keys, table, entity_types |
src/cluster_erp/core/metadata.py:517-542 |
See tenant fields.
Constraints and validation¶
- Metadata objects are Pydantic models; a wrong literal value or a missing required field fails when the module builds its metadata.
- At start-up the server fails if a
sub_entity_tabletab points at an entity without columns (src/cluster_erp/server/app.py:547-589). - The project's written engineering rules make the web app fully metadata-driven: screen, form, list, and action behaviour comes from metadata.
tests/test_metadata_driven_rules.pyandtests/test_architecture_boundaries.py:75guard parts of this rule; see architecture boundaries.
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| metadata | ModuleMeta |
The declarative description of a module's screens that both clients render. | metadata | src/cluster_erp/core/metadata.py:719 |
| entity metadata | EntityMeta |
The description of one entity's endpoints, form, list, card, and actions. | varlık metadata'sı | src/cluster_erp/core/metadata.py:553 |
| facet | FacetMeta |
A role a party can play, shown as a section of the party card. | rol bölümü | src/cluster_erp/core/metadata.py:357 |
| label dictionary | LabelDict |
A mapping from language code to display text. | etiket sözlüğü | src/cluster_erp/core/metadata.py:7 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.