---
title: SAIF.Business.Menu operations and processes
summary: Business and technical operations supported by this library.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-08-17
library: SAIF.Business.Menu
reference_type: package
---

# SAIF.Business.Menu operations and processes

This page is the operation catalog and cross-operation hub for `SAIF.Business.Menu`. The library implements ten operations: one authorization-resolution operation (the core of the menu system), three in-memory navigation lookups, application/category code loading, the shared create/update/delete lifecycle for maintenance objects, and loading a user's favorites, group memberships, and item-level security grants. Each operation's detailed, step-by-step logic lives in its own page under `operations/`.

## Operation catalog
| Operation | Intent | Trigger | Inputs | Outputs | Rules | Tables | SQL |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [Resolve a user's authorized menu items](operations/op-menu-01-resolve-authorized-menu-items.md) | Resolve the complete set of menu items a specific user may reach, combining group-granted items, unsecured items, and the user's own favorites. | `NavigationContext.New(user)` — once per web session | `IDataPortalInfo`, menu user ID | Populated `clsMenuAuthorizedItemCollection` | [BR-MENU-001](business-rules.md#br-menu-001-scoped-vs-unfiltered-retrieval), [BR-MENU-002](business-rules.md#br-menu-002-group-granted-authorization), [BR-MENU-004](business-rules.md#br-menu-004-unsecured-items-open-to-all), [BR-MENU-005](business-rules.md#br-menu-005-favorites-appear-in-the-authorized-set) | [MENU_ITEM](database-tables.md#menu_item), [MENU_SECURITY](database-tables.md#menu_security), [MENU_SECURITY_USER](database-tables.md#menu_security_user), [MENU_PAGE](database-tables.md#menu_page), [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code), [MENU_CATEGORY_CODE](database-tables.md#menu_category_code), [MENU_FAVORITE](database-tables.md#menu_favorite) | [SQL-015](sql/SQL-015-retrieve-authorized-menu-items-for-user.md), [SQL-016](sql/SQL-016-retrieve-all-authorized-menu-items.md) |
| [Check whether a page is authorized](operations/op-menu-02-check-page-authorization.md) | Answer whether a requested page is authorized for the current user by testing membership in the resolved authorized-item set. | `clsControllerBase.RedirectUnauthorizedUsers` on every web request, via `NavigationContext.IsMenuItem` | Application code, requested page link | The matching `clsMenuAuthorizedItem`, or `Nothing` (denial) | [BR-MENU-008](business-rules.md#br-menu-008-page-reachability-requires-an-authorized-entry), [BR-MENU-009](business-rules.md#br-menu-009-page-link-normalization) | — | — |
| [Locate a menu item for navigation](operations/op-menu-03-locate-menu-item-for-navigation.md) | Locate a menu item within a category for navigation rendering, trying an exact link match before a query-string-insensitive fallback. | Menu/navigation rendering (category-scoped lookup) | Category code, page link, optional visible-only flag | The matching `clsMenuAuthorizedItem`, or `Nothing` | [BR-MENU-009](business-rules.md#br-menu-009-page-link-normalization), [BR-MENU-010](business-rules.md#br-menu-010-visible-only-lookups), [BR-MENU-011](business-rules.md#br-menu-011-category-lookup-fallback) | — | — |
| [Resolve an application by virtual path](operations/op-menu-04-resolve-application-by-path.md) | Resolve the application code that owns the current request's virtual path. | `NavigationContext` resolving the current application | Requested virtual path | The matching `clsApplicationCode`, or `Nothing` | [BR-MENU-012](business-rules.md#br-menu-012-application-resolution-by-virtual-path) | [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code) | — |
| [Load application codes](operations/op-menu-05-load-application-codes.md) | Load application codes for administration or lookup, optionally restricted to active-only codes. | Caller requests `GetAllApplicationCodes` or `GetActiveApplicationCodes` | `IDataPortalInfo`, active-only flag | Populated `clsApplicationCodeCollection` | [BR-MENU-013](business-rules.md#br-menu-013-active-only-application-filtering) | [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code) | [SQL-013](sql/SQL-013-retrieve-all-application-codes.md), [SQL-014](sql/SQL-014-retrieve-active-application-codes.md) |
| [Create a menu item](operations/op-menu-06-create-menu-item.md) | Create a new menu item (representative of the create pattern shared by every maintenance object in this library). | Administration code calls `clsMenuItem.NewMenuItem(dpi)` then `Save()` | Item properties, `DataPortalInfo.UserID` | New `MENU_ITEM` row with a server-assigned sequence number | [BR-MENU-014](business-rules.md#br-menu-014-sequence-assigned-identity), [BR-MENU-016](business-rules.md#br-menu-016-audit-stamp-on-insert-and-update), [BR-MENU-017](business-rules.md#br-menu-017-dirty-tracking-on-change), [BR-MENU-018](business-rules.md#br-menu-018-save-only-when-dirty), [BR-MENU-019](business-rules.md#br-menu-019-yn-boolean-flag-storage), [BR-MENU-020](business-rules.md#br-menu-020-single-row-write-verification), [BR-MENU-021](business-rules.md#br-menu-021-cascading-child-security-group-save) | [MENU_ITEM](database-tables.md#menu_item), [MENU_SECURITY](database-tables.md#menu_security) | [SQL-002](sql/SQL-002-menu-item-next-seq.md), [SQL-008](sql/SQL-008-insert-menu-item.md), [SQL-010](sql/SQL-010-insert-menu-security.md) |
| [Update or delete a maintained object](operations/op-menu-07-update-delete-maintained-object.md) | Update or delete an existing maintenance object, verifying that exactly one row was affected. | Caller calls `Save()` on a dirty existing object, or `Delete()` | Object properties (update) or key (delete), `DataPortalInfo.UserID` | Updated/deleted row; object returned to "new" state after delete | [BR-MENU-016](business-rules.md#br-menu-016-audit-stamp-on-insert-and-update), [BR-MENU-020](business-rules.md#br-menu-020-single-row-write-verification), [BR-MENU-022](business-rules.md#br-menu-022-delete-returns-object-to-new-state) | [MENU_ITEM](database-tables.md#menu_item), [MENU_PAGE](database-tables.md#menu_page), [MENU_SECURITY](database-tables.md#menu_security), [MENU_SECURITY_USER](database-tables.md#menu_security_user), [MENU_FAVORITE](database-tables.md#menu_favorite), [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code), [MENU_CATEGORY_CODE](database-tables.md#menu_category_code) | [SQL-034](sql/SQL-034-update-menu-item.md), [SQL-041](sql/SQL-041-delete-menu-item.md) |
| [Load a user's favorites](operations/op-menu-08-load-user-favorites.md) | Load the favorite menu items recorded for one user (or all users when no user is supplied). | Caller requests `GetMenuFavoritesForUser` | `IDataPortalInfo`, user ID | Populated `clsMenuFavoriteCollection` | [BR-MENU-001](business-rules.md#br-menu-001-scoped-vs-unfiltered-retrieval) | [MENU_FAVORITE](database-tables.md#menu_favorite) | [SQL-020](sql/SQL-020-retrieve-all-menu-favorites.md), [SQL-021](sql/SQL-021-retrieve-menu-favorites-for-user.md) |
| [Load a user's group memberships](operations/op-menu-09-load-user-group-memberships.md) | Load the security-group memberships recorded for one user (or all memberships when no user is supplied). | Caller requests `GetMenuSecurityUserForUser` | `IDataPortalInfo`, menu user ID | Populated `clsMenuSecurityUserCollection` | [BR-MENU-001](business-rules.md#br-menu-001-scoped-vs-unfiltered-retrieval) | [MENU_SECURITY_USER](database-tables.md#menu_security_user) | [SQL-029](sql/SQL-029-retrieve-all-menu-security-users.md), [SQL-030](sql/SQL-030-retrieve-menu-security-users-for-user.md) |
| [Load security grants for an item](operations/op-menu-10-load-security-grants-for-item.md) | Load the security grants recorded for one menu item (or all grants when no item is supplied); this is the lazily-loaded `SecurityGroups` child of `clsMenuItem`. | First access of `clsMenuItem.SecurityGroups`, or a direct call to `GetMenuSecuritiesForItem` | `IDataPortalInfo`, menu item sequence number | Populated `clsMenuSecurityCollection` | [BR-MENU-001](business-rules.md#br-menu-001-scoped-vs-unfiltered-retrieval) | [MENU_SECURITY](database-tables.md#menu_security) | [SQL-027](sql/SQL-027-retrieve-all-menu-security.md), [SQL-028](sql/SQL-028-retrieve-menu-security-for-item.md) |

## Process flow diagram
The following diagram visualizes the primary operational flow: resolving a user's authorized menu items and using that set to gate navigation.

```mermaid
flowchart TD
    Start([Web session starts]) --> Resolve[Resolve authorized menu items<br>op-menu-01]
    Resolve --> Cache[Cache collection in web session]
    Cache --> Request([Subsequent page request])
    Request --> Check{Check page authorization<br>op-menu-02}
    Check -->|Found| Allow([Render page / menu])
    Check -->|Not found| Deny([Redirect unauthorized user])
    Request --> Locate[Locate menu item for navigation<br>op-menu-03]
    Locate --> Allow
```

## Inherited operations and processes

No inherited operations were identified for this library. `SAIF.Framework` supplies the generic BOF lifecycle (`Before*`/`After*`, data portal dispatch) that every business object and collection here overrides with its own SQL and logic; the framework contributes infrastructure, not a distinct named operation consumed unchanged by this library.

## Database interactions

The following table summarizes which operations read from or write to the database. Per-step SQL and table citations live in each operation's detail page under `operations/`.

| Operation | SQL | Tables | Type |
| --- | --- | --- | --- |
| [Resolve a user's authorized menu items](operations/op-menu-01-resolve-authorized-menu-items.md) | [SQL-015](sql/SQL-015-retrieve-authorized-menu-items-for-user.md), [SQL-016](sql/SQL-016-retrieve-all-authorized-menu-items.md) | [MENU_ITEM](database-tables.md#menu_item), [MENU_SECURITY](database-tables.md#menu_security), [MENU_SECURITY_USER](database-tables.md#menu_security_user), [MENU_PAGE](database-tables.md#menu_page), [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code), [MENU_CATEGORY_CODE](database-tables.md#menu_category_code), [MENU_FAVORITE](database-tables.md#menu_favorite) | Read |
| [Resolve an application by virtual path](operations/op-menu-04-resolve-application-by-path.md) | — | [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code) | Read (in-memory over a previously loaded collection) |
| [Load application codes](operations/op-menu-05-load-application-codes.md) | [SQL-013](sql/SQL-013-retrieve-all-application-codes.md), [SQL-014](sql/SQL-014-retrieve-active-application-codes.md) | [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code) | Read |
| [Create a menu item](operations/op-menu-06-create-menu-item.md) | [SQL-002](sql/SQL-002-menu-item-next-seq.md), [SQL-008](sql/SQL-008-insert-menu-item.md), [SQL-010](sql/SQL-010-insert-menu-security.md) | [MENU_ITEM](database-tables.md#menu_item), [MENU_SECURITY](database-tables.md#menu_security) | Write |
| [Update or delete a maintained object](operations/op-menu-07-update-delete-maintained-object.md) | [SQL-034](sql/SQL-034-update-menu-item.md), [SQL-041](sql/SQL-041-delete-menu-item.md) | [MENU_ITEM](database-tables.md#menu_item), [MENU_PAGE](database-tables.md#menu_page), [MENU_SECURITY](database-tables.md#menu_security), [MENU_SECURITY_USER](database-tables.md#menu_security_user), [MENU_FAVORITE](database-tables.md#menu_favorite), [BUSONLINE_APPS_CODE](database-tables.md#busonline_apps_code), [MENU_CATEGORY_CODE](database-tables.md#menu_category_code) | Write |
| [Load a user's favorites](operations/op-menu-08-load-user-favorites.md) | [SQL-020](sql/SQL-020-retrieve-all-menu-favorites.md), [SQL-021](sql/SQL-021-retrieve-menu-favorites-for-user.md) | [MENU_FAVORITE](database-tables.md#menu_favorite) | Read |
| [Load a user's group memberships](operations/op-menu-09-load-user-group-memberships.md) | [SQL-029](sql/SQL-029-retrieve-all-menu-security-users.md), [SQL-030](sql/SQL-030-retrieve-menu-security-users-for-user.md) | [MENU_SECURITY_USER](database-tables.md#menu_security_user) | Read |
| [Load security grants for an item](operations/op-menu-10-load-security-grants-for-item.md) | [SQL-027](sql/SQL-027-retrieve-all-menu-security.md), [SQL-028](sql/SQL-028-retrieve-menu-security-for-item.md) | [MENU_SECURITY](database-tables.md#menu_security) | Read |

## Failure and edge-case behavior
- A missing or renamed column in the authorized-item reader surfaces as a runtime error from `AfterRetrieve` (see [Resolve a user's authorized menu items](operations/op-menu-01-resolve-authorized-menu-items.md)).*
- `GetMenuSecurityUserForUser` is affected by an inverted-branch defect: the parameterized statement is issued without its bind variable while the unfiltered statement receives a superfluous one; the user-scoped path is expected to fail at execution (see [Load a user's group memberships](operations/op-menu-09-load-user-group-memberships.md)).*
- Every create/update/delete verifies exactly one row was affected and adds an error message instead of throwing when that check fails (see [Update or delete a maintained object](operations/op-menu-07-update-delete-maintained-object.md)).

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Business rules](business-rules.md)
- [Database tables](database-tables.md)
- [SQL catalog](sql/index.md)
- [Security and authorization](security-authorization.md)
- [API reference](api/index.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

## Sources
- SAIF.Business.Menu/clsMenuAuthorizedItemCollection.vb
- SAIF.Business.Menu/clsMenuItem.vb
- SAIF.Business.Menu/clsApplicationCodeCollection.vb
- SAIF.Business.Menu/clsMenuFavoriteCollection.vb
- SAIF.Business.Menu/clsMenuSecurityUserCollection.vb
- SAIF.Business.Menu/clsMenuSecurityCollection.vb
