MemberJunction / MemberJunction/MJ
[Explorer] Per-application / per-role shell chrome + application-scoped search — wiring the shell to configuration surfaces MJ already has
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
# [Explorer] Per-application / per-role shell chrome + application-scoped search — wiring the shell to configuration surfaces MJ already has
## Context
We (Blue Cypress / Sidecar) are building an LXP product on MJ Explorer: multiple MJ
Applications in one instance — a learner-facing portal, an LMS admin console, and a content
studio — with very different chrome needs per app and per audience. This was discussed with
Amith on our Jun-30 demo call; his guidance was that granular / role-level shell control should
be bubbled up as an MJ-level capability rather than solved with app-side hacks — this issue is
that bubble-up, after verifying exactly what exists on `next` (v5.46 baseline, commit
`23d86ed45c`) so we're only asking for what's genuinely missing.
**What we do today (works, but brittle by design):** our app component toggles route-based
classes on `` and we CSS-hide shell chrome under them (search bar, notifications bell,
activity button, nav app strips, chat overlay) — display:none over MJ's DOM, re-verified on
every MJ upgrade. Single-app confinement for learner-only sessions is a similar class +
CSS hide of the app switcher.
## What we verified already exists (deliberately NOT asking for these)
- **Single-app confinement mechanics**: `SessionScope.restrictedToApplicationId` +
`appSwitchingLocked` + `AppLockGuardService` (auth-types.ts:281-296,
shell.component.ts:1469-1471 / :373-388, app-lock-guard.service.ts) — works end-to-end today
when set by the magic-link provider's JWT claim.
- **Per-role app access**: `MJ: Application Roles` CanAccess/CanAdmin
(application-manager.ts:99-105).
- **Per-app nav config**: `DefaultNavItems`, `NavigationStyle`, `TopNavLocation`, etc.
- **Instance-wide search-bar toggle**: `Shell.SearchBar.Enabled` instance configuration
(shell.component.ts:133).
- **Search scopes with per-role permissions**: `MJ: Search Scopes` + `MJ: Search Scope
Permissions` (RoleID/UserID × None|Read|Search|Manage), enforced server-side
(SearchKnowledgeResolver.ts:222-240).
- **A per-app settings store with fallback semantics**: `MJ: Application Settings` /
`ApplicationSettingEngine` — `ApplicationID NULL` = global, app row wins over global.
## The three gaps (each is "wire the shell to an existing surface", not a new subsystem)
**1. Shell chrome is not resolvable per application (or role).**
`Shell.SearchBar.Enabled` lives in `InstanceConfiguration`, which has no
ApplicationID/RoleID/UserID columns — strictly instance-wide (so hiding search for the learner
app would kill it for the admin apps too). The notifications bell, activity button, and nav app
strips have **no configuration key at all** — unconditional in shell.component.html:67-130.
Meanwhile `ApplicationSettingEngine` already implements exactly the right resolution shape
(app-scoped row → global fallback), but the shell never reads chrome keys through it.
*Ask:* shell chrome getters (search bar + new keys for bell / activity / app strips / chat
overlay — the seeded `Shell.ChatOverlay.*` keys currently have no consumer) resolved per active
Application via Application Settings, falling back to the instance configuration. Role-level
resolution would be welcome but per-app alone covers most of our need.
**2. Search cannot be scoped to the active application.**
Search Scopes are powerful but selection is purely user-driven
(search-composite.component.ts:115/:242); no selection ⇒ unconstrained global search
(search-types.ts:110-115); `SearchScope.IsDefault` exists in schema/DTO but nothing preselects
it; and scopes have no relationship to Applications. For a learner-facing app we need "search
inside this app searches this app's content" — today the shell search surfaces raw global
providers.
*Ask:* an Application↔SearchScope association (column or junction) that the shell auto-applies
when the app is active; honoring `IsDefault` in the selector; optionally a way to say "this
role/app may not run unscoped search."
**3. Session confinement can't be driven by role/application metadata.**
`restrictedToApplicationId` is only settable today via the magic-link provider's JWT claim
(mjexplorer-magic-link-provider.service.ts:174-180) — a normal SSO user (Auth0/Entra) can't be
confined without a custom auth provider. Our learner sessions are standard SSO.
*Ask:* a metadata-driven path to session scope — e.g. a flag on `MJ: Application Roles` or the
Role ("confine sessions to this app when it's the user's only granted app", or explicit) — and,
when locked, an option for the confined mode to also quiet the remaining chrome (search/bell/
activity), which it currently leaves visible.
## Why it matters beyond us
Any MJ deployment that ships an end-user-facing Application next to admin Applications (portals,
customer consoles, kiosk-style apps) hits the same wall: the shell is one-size-fits-all per
instance. The three asks reuse MJ's own precedents (Application Settings fallback semantics,
scope permissions, SessionScope contract), so they'd read as completions of existing designs
rather than new machinery.
Happy to share our CSS-interim implementation, test any branch against a real multi-app
deployment, or contribute — whichever is useful.
Contributor guide
Research direction
Start with shell.component.ts and shell.component.html, then trace ApplicationSettingEngine and the existing Shell.SearchBar.Enabled configuration. Read search-composite.component.ts, search-types.ts, SearchKnowledgeResolver.ts, and mjexplorer-magic-link-provider.service.ts to compare current search and session-scope behavior. Done requires a maintainer-approved design covering per-app chrome, application-scoped search, and metadata-driven confinement, with tests for each path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql, typescript
- Domain
- authentication, backend, databases, frontend, search
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100