Custom Fields Module

Tenant-configurable custom field definitions attached to any registered entity type by stable key — no schema changes, no cross-module coupling.

The Custom Fields module lets each tenant extend the platform's records with their own typed fields — for example a 'shirt size' on a person or a 'preferred foot' on a player — without any database migration or code change. Field definitions are tenant-scoped and attach to a host entity through the cross-module Entity-Type Registry rather than a foreign key, so the module never couples to another module's schema.

What Are Custom Fields?

A custom field is a tenant-defined extension to an existing entity. Each definition carries a machine key (unique per tenant and entity type), bilingual labels, a value type, an optional required flag, an optional list of allowed options for Select fields, and a sort order. Values are stored typed rather than in an untyped JSON blob.

  • Tenant-Scoped

    Every definition is owned by a tenant and isolated by the global tenant query filter. System-level (shared) definitions are supported for platform operators.

  • Registry-Validated Attachment

    Fields attach to a host entity via its canonical entity-type key, validated against the cross-module Entity-Type Registry — never via a foreign key.

  • Typed Values

    Each field declares one of twenty-two value types — from plain text and numbers through references, an uploaded file or image, and formatted rich text — avoiding an untyped metadata blob and enabling proper validation.

  • Immutable Keys

    The entity-type key and machine key are immutable after creation so already-stored values remain addressable; only display and behaviour metadata can be edited.

Value Types

Twenty-two value types are supported end to end — see the operator documentation's Value Types page for the complete list. Select and MultiSelect fields carry a newline-separated list of allowed options; other types must not carry options. The API enforces this on both create and update.

Data Model

A CustomField carries: EntityTypeKey (registered), Key (machine key, unique per tenant + entity type), LabelEn / LabelAr, ValueType, IsRequired, Options (Select only), SortOrder, and IsActive. Uniqueness is enforced per (TenantId, EntityTypeKey, Key).

Tenant Isolation

Reads run under the module's global tenant filter, so a tenant only sees its own definitions plus shared system-level ones. Create stamps the current tenant automatically. Update and Delete enforce an ownership guard so a tenant admin can never modify or remove a shared or another tenant's definition.

Permissions

The module owns the resource custom-fields with the standard CRUD actions: custom-fields.view, custom-fields.create, custom-fields.update, and custom-fields.delete.