NAME
Concierge::Users::Meta - Field definitions, validators, and configuration utilities for Concierge::Users
VERSION
v0.7.3
SYNOPSIS
use Concierge::Users;
my $users = Concierge::Users->new('/path/to/users-config.json');
# Introspect field schema
my $fields = $users->get_user_fields(); # ordered field list
my $def = $users->get_field_definition('email');
my $hints = $users->get_field_hints('email');
# Class-level field lists
my @core = Concierge::Users::Meta::user_core_fields();
my @std = Concierge::Users::Meta::user_standard_fields();
my @sys = Concierge::Users::Meta::user_system_fields();
# Display configuration
Concierge::Users::Meta->show_default_config(); # built-in defaults
$users->show_config(); # active setup
DESCRIPTION
Concierge::Users::Meta is the parent class for Concierge::Users and all storage backends. It owns the master field definitions, the validation subsystem, the filter DSL parser, and the configuration display helpers. Application code normally interacts with Meta indirectly through a Concierge::Users instance, but the introspection methods and class-level field lists are available for direct use.
FIELD CATALOG
Every user record is composed of fields drawn from three built-in categories plus an optional application category.
Core Fields (4)
Always present in every setup.
- user_id
-
Primary authentication identifier.
type: system required: 1 max_length: 30 default: "" null_value: "" must_validate: 0 description: User login ID - Primary authentication identifier - moniker
-
User's preferred display name, nickname, or initials.
type: text validate_as: moniker required: 1 max_length: 24 default: "" null_value: "" must_validate: 1 description: User's preferred display name, nickname, or initials - user_status
-
Account status for access control.
type: enum validate_as: enum required: 1 options: *Eligible, OK, Inactive max_length: 20 default: Eligible (auto-set from * option) null_value: "" must_validate: 1This is a core field (always present), but its
optionscan be replaced viafield_overridesto match your application's workflow. See "Field Overrides" for an example. - access_level
-
Permission level for feature access.
type: enum validate_as: enum required: 1 options: *anon, visitor, member, staff, admin max_length: 20 default: anon (auto-set from * option) null_value: "" must_validate: 1Core field (always present);
optionscan be replaced viafield_overrides. See "Field Overrides".
Standard Fields (12)
Included by default when include_standard_fields is omitted or set to 'all'. Pass an arrayref of names to select specific fields, or an empty arrayref [] to exclude all standard fields.
Name fields:
- first_name -- type
text, validate_asname, max 50, must_validate 1 - middle_name -- type
text, validate_asname, max 50, must_validate 1 - last_name -- type
text, validate_asname, max 50, must_validate 1 - prefix -- type
enum, options: (none) Dr Mr Ms Mrs Mx Prof Hon Sir Madam, max 10 - suffix -- type
enum, options: (none) Jr Sr II III IV V PhD MD DDS Esq, max 10
Identity fields:
Contact fields:
- email -- type
email, validate_asemail, max 255 - phone -- type
phone, validate_asphone, max 20 - text_ok -- type
boolean, validate_asboolean, null_value 0, max 1
Temporal fields:
- last_login_date -- type
timestamp, validate_astimestamp, default0000-00-00 00:00:00, max 19 - term_ends -- type
date, validate_asdate, null_value0000-00-00, max 10
All standard fields have required => 0 by default.
System Fields (2)
Always appended to the field list. Auto-managed by the backends; cannot be set through the public API. Protected from overrides.
- last_mod_date -- type
system, timestamp updated on every write - created_date -- type
system, timestamp set once on creation,required => 1
FIELD ATTRIBUTES
Each field definition is a hashref that may contain the following keys:
field_name-- Internal name (snake_case). Used as hash key and column/file identifier.category-- One ofcore,standard,system, orapp. Set automatically; protected from overrides.type-- Data type:text,email,phone,date,timestamp,boolean,integer,enum,system.validate_as-- Validator to use if different fromtype. See "VALIDATOR TYPES".label-- Human-readable label for UI display. Auto-generated fromfield_nameif omitted.description-- Short explanatory text for documentation or UI hints.required--1if the field must have a non-null value on creation;0otherwise.must_validate--1if a validation failure should reject the entire operation;0to treat failure as a non-fatal warning.options-- Arrayref of allowed values forenumfields. Prefix one option with*to designate the default (see "Enum Default Convention").default-- Value assigned to the field on new-record creation when no value is supplied.null_value-- Sentinel that represents "no data" for this field type (e.g.""for text,0for boolean,0000-00-00for date).max_length-- Maximum character length enforced by thetextvalidator and used as a UI hint.
VALIDATOR TYPES
Ten built-in validators are available. Each is selected by the field's validate_as (or type as fallback) and receives ($user_data, $field_name, $field_def).
- text
-
Validates
max_lengthif defined. Accepts any string.null_value: "" -
Pattern:
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/null_value: "" - phone
-
Digits, spaces, hyphens, parentheses, optional leading
+; minimum 7 characters.null_value: "" - date
-
Pattern:
YYYY-MM-DD(/^\d{4}-\d{2}-\d{2}$/).null_value: "0000-00-00" - timestamp
-
Pattern:
YYYY-MM-DD HH:MM:SSorYYYY-MM-DDTHH:MM:SS.null_value: "0000-00-00 00:00:00" - boolean
-
Strictly
0or1.null_value: 0 - integer
-
Optional leading minus, digits only (
/^\-?\d+$/).null_value: 0 - enum
-
Value must appear in the field's
v_optionslist (options with*prefix stripped).null_value: "" - moniker
-
2-24 alphanumeric characters, no spaces (
/^[a-zA-Z0-9]{2,24}$/).null_value: "" - name
-
Letters (including accented), hyphens, apostrophes, and internal spaces.
null_value: ""
validate_as vs type
A field's type declares its data type and determines the default validator. validate_as overrides the validator without changing the type. For example, an application field with type => 'text' and validate_as => 'moniker' is stored as text but validated with the moniker pattern. When type is changed via a field override and validate_as is not explicitly set, validate_as is updated automatically to match the new type.
must_validate Behavior
When must_validate is 1 for a field, a validation failure causes the entire register_user or update_user call to return { success => 0 }. When must_validate is 0, the field's value is silently dropped and a warning is appended to the response.
Setting required => 1 in a field override automatically enables must_validate unless must_validate is explicitly set in the same override.
The environment variable USERS_SKIP_VALIDATION bypasses all validation when set to a true value.
FIELD CUSTOMIZATION
Application Fields
Pass app_fields to Concierge::Users->setup() as an arrayref. Each element is either a string (minimal definition) or a hashref (full definition):
app_fields => [
'nickname', # string shorthand
{ # full definition
field_name => 'department',
type => 'enum',
options => ['*Engineering', 'Sales', 'Support'],
required => 1,
label => 'Department',
},
],
String shorthand creates a field with type => 'text', validate_as => 'text', required => 0.
Reserved names (any core, standard, or system field name) are rejected with a warning.
Field Overrides
Pass field_overrides to setup() as an arrayref of hashrefs. Each must contain field_name to identify the target:
field_overrides => [
{
field_name => 'email',
required => 1,
label => 'Work Email',
},
],
Protected fields that cannot be overridden: user_id, created_date, last_mod_date.
Protected attributes that cannot be changed: field_name, category.
Auto-behaviors:
Changing
typeauto-updatesvalidate_asto match (unlessvalidate_asis also specified).Setting
required => 1auto-enablesmust_validate(unlessmust_validateis also specified).An unknown
validate_asvalue falls back totextwith a warning.
Overriding enum options: Core fields like user_status and access_level are always present, but their options are not fixed. Replace them with values that fit your domain:
# Makerspace member status instead of the default
# Eligible / OK / Inactive
field_overrides => [
{
field_name => 'user_status',
options => [qw( *Applicant Novice Skilled
Expert Mentor Steward )],
},
],
The *-prefixed option becomes the default (see "Enum Default Convention"). Validation, filtering, and all other enum behaviors apply to the new option set automatically.
Enum Default Convention
In an options arrayref, prefix exactly one value with * to mark it as the default:
options => ['*Free', 'Premium', 'Enterprise']
The * is stripped for validation (stored internally in v_options). If no explicit default is set for the field, the *-marked option becomes the default automatically. A bare * (e.g. in prefix and suffix) represents an empty default.
FILTER DSL
The list_users method accepts a filter string with five operators and two combinators.
Operators
= exact match user_status=OK
: substring (case-insensitive) last_name:smith
! not-contains (case-insensitive) email!example.org
> greater than (string) last_login_date>2025-01-01
< less than (string) term_ends<2026-01-01
Combinators
; AND -- all conditions must match
| OR -- at least one group must match
AND binds tighter than OR: a=1;b=2|c=3 means (a=1 AND b=2) OR (c=3).
Examples
# Active members
user_status=OK;access_level=member
# Staff or admin
access_level=staff|access_level=admin
# Name search with status filter
last_name:Garcia;user_status=OK
# Recent logins
last_login_date>2025-06-01
Unknown fields in a filter string produce a warning and are skipped.
METHODS
Class Methods
user_core_fields
my @fields = Concierge::Users::Meta::user_core_fields();
Returns the list of core field names: user_id, moniker, user_status, access_level.
user_standard_fields
my @fields = Concierge::Users::Meta::user_standard_fields();
Returns the list of standard field names (12 fields).
user_system_fields
my @fields = Concierge::Users::Meta::user_system_fields();
Returns the list of system field names: last_mod_date, created_date.
init_field_meta
my $meta = Concierge::Users::Meta::init_field_meta(\%config);
Processes the setup configuration and returns a hashref with fields (ordered arrayref) and field_definitions (hashref of field definitions). Called internally by Concierge::Users->setup().
show_default_config
Concierge::Users::Meta->show_default_config();
Prints the built-in default field configuration template to STDOUT.
Instance Methods
get_field_definition
my $def = $users->get_field_definition('email');
Returns the complete field definition hashref for the named field, or undef if the field is not in the current schema.
get_field_validator
my $code_ref = $users->get_field_validator('email');
Returns the validator code reference for the named field based on its validate_as or type, or undef if no validator is available.
get_field_hints
my $hints = $users->get_field_hints('email');
Returns a hashref of UI-friendly attributes: label, type, max_length, options, description, required.
get_user_fields
my $fields = $users->get_user_fields();
Returns the ordered arrayref of field names for this instance's schema.
validate_user_data
my $result = $users->validate_user_data(\%data);
Validates %data against the field schema. Returns { success => 1, valid_data => \%clean } on success (with optional warnings arrayref), or { success => 0, message => $reason } on failure.
parse_filter_string
my $filters = $users->parse_filter_string('user_status=OK;access_level=member');
Parses a filter DSL string into an internal structure suitable for backend list methods. See "FILTER DSL".
show_config
$users->show_config();
$users->show_config(output_path => '/tmp/config.yaml');
Prints the active YAML configuration file for this instance to STDOUT. Must be called on a Concierge::Users instance (not a class method).
config_to_yaml
my $yaml = Concierge::Users::Meta::config_to_yaml(\%config, $storage_dir);
Converts a configuration hashref to a human-readable YAML string with a warning header. Used internally during setup().
SEE ALSO
Concierge::Users -- main API and CRUD operations
Concierge::Users::Database, Concierge::Users::File, Concierge::Users::YAML -- storage backend implementations
AUTHOR
Bruce Van Allen <bva@cruzio.com>
LICENSE
This module is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.