Stable ids
The id written beside every named element in Meridian configuration, who writes it, why a rename keeps all stored data, how renames and aliases work, and how to fix a missing, copied or wrong id.
Every named element in a project’s configuration carries an id: beside its handle. The handle (a key, name or code) is a label you can change at any time; the id is the element’s identity. The database stores everything by id, so renaming a field, a type, a site or a route keeps every value stored under it.
fields:
- { name: lengthKm, aliases: [distance], id: fld_qvbnm6shzg, type: number } Here the field was called distance and is now lengthKm. Its id did not change, so every document’s value is still there, and the old handle still answers as an alias.
The rules
- Never type an id and never copy one. The tooling writes ids. An element you add by hand gets one from
engine-dmo check --fix,engine-dmo dev up, or theengine-dmo devverb that adds it. - Never edit an id. A changed id is a different element: the plan replaces the stored one.
- Change the handle freely. A changed handle beside an unchanged id is a rename.
- Ids are per project.
engine-dmo init --fromgives a copied project new ids so the two can never be confused.
check cannot tell a typed id from a written one: any well-formed id passes, so rule 1 is yours to keep.
schema plan compares each element in the files with the stored one by id first, then by handle:
flowchart TD
el["An element in the files"] --> hasid{"Has an id?"}
hasid -- no --> fix["check refuses it:<br/>run check --fix"]
hasid -- yes --> stored{"Id stored?"}
stored -- yes --> samehandle{"Same handle?"}
samehandle -- yes --> same["No change, or ~ change"]
samehandle -- no --> rename["> rename: values kept"]
stored -- no --> oldhandle{"Handle stored?"}
oldhandle -- no --> add["+ add"]
oldhandle -- "yes, with no id" --> bind["= bind"]
oldhandle -- "yes, under another id" --> replace["! replace: refused<br/>without --replace"]What an id looks like
A prefix naming the kind of element, an underscore, and ten characters from a lower-case base32 alphabet without i, l, o or u: fld_qvbnm6shzg. The prefix makes an id of the wrong kind an obvious error.
| Prefix | Element | Where |
|---|---|---|
site_ | A site | site.id in sites/<key>/site.yaml |
net_ | A network | networks.yaml |
loc_ | A locale | locales.yaml |
grp_ | A locale group, or a group of fields in a type’s editor | locales.yaml, schema files |
typ_ | A content type | Schema files |
fld_ | A field, including custom CRM and staff user fields | Schema files, crm/, access/users.yaml, portal/enquiries.yaml |
blk_ | A block | blocks/_index.yaml, schema files |
opt_ | A select option, or a link style | Schema files: { value: mid, id: opt_... } |
var_ | An entry variant | Schema files |
rte_ | A route | routes.yaml |
lnd_ | A landing page pairing | routes.yaml |
nav_ | A navigation slot | site.yaml |
end_ | A declared endpoint | endpoints.yaml |
src_, imp_, whk_ | A source, an importer, a webhook | sources.yaml, importers.yaml, webhooks.yaml |
role_ | A staff role or a partner role | access/roles.yaml, portal/roles.yaml |
rep_ | A report | analytics/reports.yaml |
met_ | An entered metric | analytics/dashboards.yaml |
tier_ | A membership tier | memberships.yaml |
scr_, act_ | A portal screen, a portal action | A site’s portal.yaml |
slot_ | A promotion slot | A site’s promotions.yaml |
A role that replaces a built-in role (same key) needs no id: it keeps the built-in role’s.
Writing ids
check refuses an element without an id:
config/sites/main/routes.yaml:2:11: route "page" has no id
2 | - type: page
| ^^^^
= run engine-dmo check --fix to write one; ids are written by the tooling, never by hand
= error code MRD-1006 check --fix writes every missing id, keeping your comments and layout, then checks:
engine-dmo check --no-db --fix wrote 1 id in 1 file routes:
- type: page
id: rte_4rvbbqzx1m
uri: "/{slug}" engine-dmo dev up does the same on every save, and every engine-dmo dev verb writes the id of the element it adds. An element written as an empty map, such as a navigation slot main: {}, cannot take an id (check --fix says nav.main is an empty mapping); give it at least one setting first, such as main: { depth: 1 }.
Renaming
Rename with a verb where there is one: it changes the handle, keeps the id, and rewrites every reference to the handle in your configuration.
engine-dmo dev field rename walk distance lengthKm wrote config/schema/walk.yaml
field.walk.lengthKm: fld_qvbnm6shzg
walk.distance answers as an alias until engine-dmo schema alias retire walk.distance | Rename | Command | What else happens |
|---|---|---|
| A field | dev field rename <type> <old> <new> | The old handle is kept in aliases: so templates using it keep working. --no-alias drops it |
| A site | dev site rename <old> <new> | The site’s directory moves; old admin and public URLs redirect |
| A source, importer or webhook | dev source rename, dev importer rename, dev webhook rename | Every endpoint step naming it is rewritten |
| Anything else | Edit the handle in the file, leave the id | schema plan shows it as a rename |
schema plan marks a rename with >, and applying it changes only the stored handle. describe type shows a field’s old handle (number [translate none, was distance]).
Field aliases
An alias keeps an old field handle working in templates (and, on engine-dmo, the member API). List and retire them when nothing uses the old handle:
engine-dmo schema alias list
engine-dmo schema alias retire walk.distance retire refuses while a template still uses the alias. engine-dmo dev status lists the live aliases dev up found.
Mistakes and how to fix them
| Problem | What check or the plan says | Fix |
|---|---|---|
| An element has no id | route "page" has no id | engine-dmo check --fix |
| The same id on two elements (usually a copied block) | id fld_... is written on two elements: field "title" here and field "summary" at ... | Delete the copy’s id and run check --fix |
| An id of the wrong kind | typ_... is a type id; a field id starts fld_ | Delete it and run check --fix |
| A malformed id | "fld_abc" is not an id: after fld_ come 10 characters, not 3 | Delete it and run check --fix |
| An existing handle with a new id | The plan marks it ! (replace) and schema apply refuses it | Put the stored id back (your version control history has it), or apply with --replace <type>.<field> when you mean a new element |
A replace drops the stored element and creates a new one, so the values stored under the old id are no longer read by the field. Treat every ! in a plan as a mistake until you are sure.
Databases made before ids
A database whose schema was applied from files that had no ids can take the ids the files now carry without changing anything else:
engine-dmo schema adopt-ids It writes any missing ids (as check --fix does), then applies a plan that may contain only binds (=): each stored element takes the id its file gives it. A plan with any other change is refused; apply that first with schema apply.
Ids in the rest of the engine
engine-dmo describe projectanddescribe type <key>print every element with its id, as text or--json.engine-dmo guidelists each site, type and field with its id, so an agent working on the project can refer to them.- Documents have UUIDs, not configuration ids. They are stored in the database and never appear in configuration or seed files.
- A seed file may hold a configuration id where a field’s value is one: a
formfield stores its endpoint’s id, so a seed writescontactForm: end_srhmvkf6j3, copied fromendpoints.yamlordescribe project. Copying an id that the tooling wrote into the value that refers to it is not inventing one.
Modules and bundles
What the core platform provides, what each Meridian module adds and requires, which modules the engine-cms and engine-dmo bundles compile, and what happens when a project uses a module its binary lacks.
Users, roles and permissions
How staff users, groups, built-in and custom roles, and scoped grants control what each person may do in Meridian; how to create users and explain a decision; and how members of the public realm differ from staff.