Attribute Reference
Attributes define how each field is stored, validated, and rendered.
Attribute Shape
{
name: 'status',
label: 'Status',
scope: 'global',
dataType: 'string',
inputType: 'select',
defaultValue: 'active',
options: {
list: [
{ label: 'Active', value: 'active' },
{ label: 'Inactive', value: 'inactive' }
],
comment: 'Operational lifecycle status',
placeholder: 'Select a status',
size: 160,
},
searchable: true,
validation: (z) => z.enum(['active', 'inactive']),
}Required Keys
name: stringlabel: stringscope: 'local' | 'global' | 'relationship'dataType: DataTypeinputType: InputType
Optional Keys
defaultValue?: DefaultValueByDataType[dataType]previewType?: PreviewTypehidden?: booleanreadOnly?: booleanunique?: booleanisRequired?: booleansearchable?: booleangroup?: string | string[]spaces?: string[]options?: AttributeOptions[inputType]relationship?: { entity: string; mode: 'single' | 'multiple'; field: string }validation?: (z) => zodSchema
defaultValue must match dataType: use a number for int and float, a boolean for boolean, and a
string for textual and temporal types. An empty string is accepted as the legacy “no default” value; omitting
defaultValue is preferred when no default is needed.
Scope
global: shared across all scopes.local: scope-specific value.relationship: relationship field/connection semantics.
Validation
validation receives the Zod namespace and returns a schema. flexkit deploy compiles it to JSON Schema and the Studio form enforces it; the messages editors see are generated from label, so write the rule, not the message.
validation: (z) => z.number().int().min(0).max(5);Only rules JSON Schema can express survive the deploy: .min(), .max(), .regex(), z.email(), z.enum() and the like work, .refine() and .transform() fail the deploy. Hidden and read-only fields are not validated. The supported rules, the generated messages and the current enforcement boundary are on the Validation page.
Flags
unique: marks uniqueness intention. Enforced at deploy for global non-asset attributes.isRequired: requires a value at the API level. The generated GraphQL field is non-null, so API clients, imports and agents cannot write a record without it. Applies to global scalar attributes. For a form-level “required” message, addvalidation: (z) => z.string().min(1).searchable: includes the field in search indexing and the global search UI.hidden: a static boolean.truehides the field in the form and the list column.readOnly: a static boolean.truerenders the field as read-only; read-only attributes are omitted from the create/update mutations the Studio sends and skipped during form validation.
hidden and readOnly accept booleans only. Callbacks such as hidden: ({ record }) => … are no longer supported and fail the deploy; see Hidden and read-only fields for what to use instead. These flags are not the same as entity.menu.hidden, which hides the entity from the sidebar menu.
Field Groups
group assigns the attribute to one or more form tabs defined on entity.groups. This is not entity.menu.group (sidebar section). See Field Groups.
Hidden and read-only fields
hidden: true removes the field from the form and the list; readOnly: true shows it but blocks edits. Both are static for the whole entity. Rules that depend on the record or the user belong in permission spaces, field groups or the agent and automation layer — see Hidden and read-only fields.
Relationship Attributes
When inputType: 'relationship', add:
relationship: {
entity: 'company',
mode: 'single',
field: 'name',
}entity: target entity name.mode:singleormultiple.field: target attribute used for display/labeling.
Permission spaces
Use spaces: ['catalog'] to restrict a supported entity or global/local attribute to members of a deployed space. Membership in any listed space is sufficient. The effective display attribute cannot be space-bound, and relationship-scoped attributes cannot declare spaces. See permission spaces for deployment and assignment.