Skip to content

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.

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.

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 typeTarget fieldOpens
Data ExplorerEntityDefinitionIdThe record list of one entity definition
Module pagePageCodeA registered built-in module page of the web app
External linkHrefAn absolute HTTP(S) URL or an app-relative SPA path beginning with /
File systemThe workspace file browser
Workspace UI pageWorkspaceUiPageKeyA workspace-authored UI page
CatalogCatalogDefinitionIdOne 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.

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:

  • ModulePage with PageCode: MoltaroBoards.Boards opens the root Board selector.
  • ExternalLink with Href: /boards/support opens one Board by its stable key through the Moltaro SPA.
  • WorkspaceUiPage is preferred for a registered workspace-authored page.
  • ExternalLink with Href: https://example.com leaves 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.