Lookup types and their values. Core.
references is the controlled vocabulary every form and grid reads: statuses, types, currencies, countries, industries, job titles, and every other closed set a row classifies itself by.
| Table | Holds |
|---|---|
lookup_types | A named set, optionally under a parent type for per-entity subtypes. |
lookups | The values of a set, keyed by type and code, with a sort and a parent. |
An enumeration is a table, never a check constraint. A reference column names its own type beside the code, so the foreign key discriminates: a value from another set cannot land in it. Every type seeds a not_specified entry, which is what an optional classification defaults to.
A type is closed or open. A closed type is one the code branches on: the platform owns its membership, no tenant role may write it, and its labels come from the references message namespace, which a tenant renames at /text. An open type is the tenant's own vocabulary — brands, categories, job titles — and its rows carry their own name. is_open on the type is the flag; adding a value to an open type is an insert, not a migration.
Collections and product options are not lookups: they are tenant-authored data with their own tables and cache tags.
| Route | Surface |
|---|---|
/lookup-types | The types. |
/lookups/[type] | One type's values. |
The grids are generated per type, so their settings keys cannot be enumerated ahead of time and fall back to the tenant's defaults.
references.
references.read gates the admin screens; references.manage the writes. Reads are protected-tier and cached per tenant under their own tag, and the storefront reads an allowlisted subset anonymously.
Never. Every project links it at provisioning.