What it declares
Apps — the top-bar dropdown that collects the front doors of the packages installed on this mesh. Each entry is shipped by the package it opens, as a UiContribution node in that package's own partition.
Why a declaration is needed at all
A UiContribution names the menu it joins. The entries are decentral — they live with the package that owns them — but the menu they join has to exist, or the aggregator has nowhere to put them.
That is not a theoretical gap. Six entries (Courses, Tours, Providers & Models, Set up AI providers, Approval Desk, Feedback Inbox) shipped against an undeclared context and rendered nowhere at all: no error, no warning, no missing-area placeholder. scripts/check-menu-contexts.py now fails a PR that adds a seventh.
Who enforces visibility
The compiled aggregator, never the data. A contribution is checked against the viewer's live permissions and a closed gate vocabulary, and can only ever NARROW its own visibility — it cannot widen anything. A menu with no visible entries renders nothing.