User menus
User menus define the left-hand navigation each person sees in the Moltaro web app. An administrator configures one or more menus; at sign-in the runtime picks the menu that matches the user’s roles and renders its tree.
Menus, priority, and role resolution
Section titled “Menus, priority, and role resolution”Each menu has a name, an optional description, a priority, and an optional role scope. Resolution is per user: from the menus whose role scope matches the user (an empty scope matches everyone), candidates are considered from highest to lowest priority. A role-scoped menu is considered before a global menu when priorities are equal. The runtime removes nodes the user cannot access and selects the first candidate that still contains at least one visible node; if a candidate becomes empty, resolution continues with the next one. This lets one workspace serve different navigation to dispatchers, technicians, and managers without per-user configuration.
Menu structure
Section titled “Menu structure”A menu is a tree of nodes, one nesting level deep:
- Sections and submenus group leaf items under a label and icon.
- Leaf items open a concrete target. The leaf type decides which extra field applies:
| Leaf type | Target field | Opens |
|---|---|---|
| Data Explorer | EntityDefinitionId | The record list of one entity definition |
| Module page | PageCode | A registered built-in module page of the web app |
| External link | Href | An absolute HTTP(S) URL or an app-relative SPA path beginning with / |
| File system | — | The workspace file browser |
| Workspace UI page | WorkspaceUiPageKey | A workspace-authored UI page |
| Catalog | CatalogDefinitionId | One concrete Classifier or Resource Tree Catalog |
Every node carries a label, an icon, a sort order among its siblings, and an
optional RoleIds scope. An empty node scope adds no restriction. A non-empty
scope requires the signed-in user to hold at least one listed role. Restrictions
compose through the tree: a node is visible only when the menu, every ancestor,
and the node itself match the user. A hidden section hides its entire subtree,
and a section with no remaining visible children is omitted.
Node visibility only shapes navigation. It does not grant access to the leaf target or its data. Data Explorer, Catalog, module page, and other target authorization is evaluated independently, and a leaf is still removed when the user cannot access its target. Hidden nodes are filtered before target lookup so their labels and target identifiers are not returned by runtime resolution.
Managing menus
Section titled “Managing menus”In the web app, menus are managed under Administration > User menus. The
same operations are available to integrations and AI agents through the
Configuration API: list, read,
create, replace, and delete menus (admin-runtime-menus-* operations). The
menu a signed-in user actually receives is served by the runtime menu resolve
endpoint of the Runtime API. Workspace UI
page keys come from the pages published by the workspace’s
Workspace UI Project.
The Configuration API exposes the authoritative built-in page registry at
GET /api/workspace/admin/runtime-menus/module-pages. Use it for pickers and
automation instead of maintaining a separate PageCode list. Each entry
includes its localized display name, icon, module, backend route name,
required permissions, availability, and deprecation metadata. A known page
of a disabled module may still be saved or imported, but it is unavailable
and omitted from resolved navigation until the module is enabled. An unknown
code is rejected. Stable codes are not reused: a replacement is introduced
only after the old entry is marked deprecated.
Use these target shapes deliberately:
ModulePagewithPageCode: MoltaroBoards.Boardsopens the root Board selector.ExternalLinkwithHref: /boards/supportopens one Board by its stable key through the Moltaro SPA.WorkspaceUiPageis preferred for a registered workspace-authored page.ExternalLinkwithHref: https://example.comleaves the application.
App-relative links must begin with one /. Moltaro rejects protocol-relative
//... values, backslashes, control or whitespace characters, and leading or
trailing whitespace; it does not trim an unsafe value before validation.
Updates replace the whole menu, take the current RowVersion, and fail with a
localized moltaro.runtimeMenus.* error code when a value is missing or the
menu changed concurrently — see the
error code reference.
The menu editor provides a role picker for every section and leaf. Installation
package YAML uses the same optional RoleIds property on every node; omitting it
or exporting an empty list preserves unrestricted node visibility.
A Catalog leaf targets one concrete Classifier or Resource Tree Catalog.
Entity Hierarchy is unavailable until its runtime is implemented. Menu
resolution hides the leaf unless the signed-in user is a Catalog reader,
Catalog administrator, workspace Owner, or Admin. Adding the leaf does not
grant access to the Catalog or to any record shown inside it. Installation
packages identify this target by the portable CatalogKey; the workspace
resolves it to the local Catalog Definition. Moltaro does not add a generic
Catalogs item to the fixed sidebar: each user-facing Catalog must be placed in
a Runtime Menu explicitly.