ADR 0031 — Tenant-scoped Leptos web shell + CSR/vectordb compile fixes
This ADR closes the "tenant scoping not adopted" gap in the web lens and fixes two pre-existing compile bugs in the CSR + vectordb path.
1. Tenant-scoped Leptos web shell
Context
EE's app shell (SlotShell) routes and scopes the UI by tenant. Mosaic already
had the backend machinery (realms, x-realm-{dim} headers, token-borne realms,
and a realm/tenant bar on the static admin HTML pages) but the Leptos
pages (dashboard, list/detail, projections, events, CQRS, schedules, flags,
notifications, knowledge, search) did not send the realm header. So switching
tenant on an admin page scoped that page, but the Leptos pages kept showing the
default (seeded) tenant — an inconsistent, partially-scoped shell.
Decision
When the app declares realms, the Leptos web shell is now tenant-scoped:
- Dimension selection — the shell scopes by the root realm dimension
(e.g.
tenant), else the first declared dimension, else the first aggregate's realm dimension. This mirrors how an operator thinks about "which tenant am I in?" and matches the admin realm bar's source. - Tenant bar — the shell's
nav-actionsgains arealminput +applybutton (only when a realm dimension exists). The selected tenant is persisted inlocalStorageundermosaic-realm-{dim}and restored on load. - Realm header — every client fetch helper (
api,api_put,api_post) stamps thex-realm-{dim}header from the stored tenant, so all Leptos pages are scoped to the selected tenant in every hydration mode (CSR, and the hydrated full/islands browser bundle). - Apply reloads the page so the new tenant's data is fetched fresh (the SSR branches keep reading the in-process store, which is already realm-filtered server-side).
The realm machinery is emitted only when a realm dimension exists and is
#[cfg(target_arch = "wasm32")]-gated, so non-realm and server-rendered builds
are byte-identical.
2. CSR + vectordb compile fixes
Two pre-existing bugs blocked any CSR app with a vector_db from
compiling (no example exercised that combination until now):
- The knowledge page's search closure was
let do_search = move || { … }(0-arg) but used ason:click=do_search(1-arg). Fixed tomove |_|. - The knowledge page's collection selector used
<select value=kb_sel …>, but Leptos does not support avaluebinding on a<select>. The select now relies on native display +on:changeto sync the signal that the search reads.
Both are covered by rendering a CSR + vectordb (+ realms) app and compiling its
web lens for wasm32-unknown-unknown in local validation.
Consequences
- The Leptos web shell is now consistently tenant-scoped, matching the admin pages and EE's tenant routing. This closes the "tenant scoping not adopted" item in the app-shell feature-map row.
- The six-position
SlotShellitself is still not adopted (Mosaic uses a 4-position switchable shell) — an intentional design difference, not a functional gap. - CSR apps with a knowledge base now compile and run the knowledge/search pages.
- Tenant selection is per-browser (
localStorage); a server-side session-scoped tenant would be a follow-up if multi-tenant SSO sessions need it.