Skip to main content

Deployment-Mode Gating

The frontend has to run in two modes — a standalone ("manual") deployment and a DHIS2-synced one — from the same build. See the backend's DHIS2 vs. Generic Mode page for the server side; this is how the UI decides.

One file reads the raw signal

src/core/lib/deployment.ts is the only file allowed to read organization.source. Everything else asks it for a named capability.

export type DeploymentMode = "manual" | "dhis2";

export interface DeploymentCapabilities {
mode: DeploymentMode;
dhis2Data: boolean; // products / locations / users sourced from DHIS2
}

export function getDeploymentCapabilities(
organizationSource: string | null | undefined
): DeploymentCapabilities {
const mode = organizationSource === "dhis2" ? "dhis2" : "manual";
return { mode, dhis2Data: mode === "dhis2" };
}

The signal comes off the session: the logged-in user's organization.source, set by the backend at login.

Screens call the hook

const { mode, dhis2Data } = useDeploymentCapabilities();

useDeploymentCapabilities() (src/core/hooks/useDeploymentCapabilities.ts) just reads the session and calls getDeploymentCapabilities. Check a named field — never compare organization.source directly anywhere else.

What the modes actually change

Areamanualdhis2
Maintenance → Locationsfull CRUD (<TabLocations>)read-only synced org units (<TabOrganizationUnit>)
Create userplain formvalidate a DHIS2 username first, then create
Product importavailablehidden
ReportsCustom Reports tab shown (11th tab)hidden; 10 fixed tabs only
Setup wizardruns on a fresh deploymentnever runs
SettingsGeneral / TRVST / Device cardsalso Synchronization / DHIS2 / Reporting cards

The setup wizard is manual-only

src/core/hooks/useSetupCompletion.ts short-circuits to isComplete: true when dhis2Data is true (or the user lacks MANAGE_USERS), so <SetupWizard> in the dashboard layout never blocks a DHIS2 deployment — its org units and users come from sync, not from the wizard's create-branch / create-user flow.

Vaccine / donor fields are not gated here

VVM stage, freeze indicator, funder, partner name, shipment value and the like are attribute-definition-driven (activate the field under Maintenance → Attributes), not switched by a capability flag. A vaccine programme on a manual deployment turns those fields on; deployment.ts stays out of it.