RFC: Global context injection for extension display expressions (GSoC 2026 — Dynamic EHR)

The Problem

The extension displayExpression system currently evaluates JavaScript expressions to control extension visibility. However, the available expression context is limited to:

  • session — user, roles, privileges, sessionLocation

  • slotState — custom state passed via ExtensionSlot props

This limitation means that location tags, visit type, and encounter context cannot be accessed directly within expressions. Instead, they must be manually passed through every <ExtensionSlot state={{...}}> mounting point across the codebase, leading to significant prop-drilling.

Examples of currently unsupported expressions

"displayExpression": "visit.visitType.display === 'Inpatient'"
"displayExpression": "isLocationTagged('ICU')"
"displayExpression": "encounter.encounterType === 'ANC'"

This limitation represents a structural blocker for the GSoC 2026 project:

“Dynamic EHR: Custom screens based on user roles, locations, and other values.”


What I Have Already Built

To address related gaps, I have implemented the following groundwork:

Proposed Solution

I propose introducing a GlobalExpressionContextStore using a lightweight Zustand store that allows applications to write shared runtime context:

setExpressionContext('visit', currentVisit);
setExpressionContext('location', sessionLocation);
setExpressionContext('encounter', currentEncounter);

The evaluator in getAssignedExtensionsFromSlotData() would automatically merge this global context with:

  • existing session

  • existing slotState

This eliminates the need for prop-drilling.

Resulting capability

Implementers could then write expressions like:

"displayExpression": "visit.visitType.display === 'Inpatient'"
"displayExpression": "isLocationTagged('ICU')"
"displayExpression": "hasRole('Nurse') && visit != null"

Questions for Mentors

  1. Architecture

    Is a global context store the right pattern, or is there a preferred approach for sharing runtime context across the extension system?

  2. Placement

    Should this implementation live in:

    • esm-extensions, or

    • esm-react-utils?

  3. Security Considerations

    Are there any security or sandboxing concerns with exposing visit/encounter data to arbitrary expressions?

  4. Existing Patterns

    Is there an existing global state pattern in the codebase that applications can write to and that I should align with?

cc: @jayasanka , @dkayiwa , @dennis , @ibacher , @bawanthathilan