Skip to content

fix(store): differentiate os / on-prem enterprise / hosted deployments#814

Open
claude[bot] wants to merge 2 commits into
mainfrom
fix-hosted-detection-enterprise-probe
Open

fix(store): differentiate os / on-prem enterprise / hosted deployments#814
claude[bot] wants to merge 2 commits into
mainfrom
fix-hosted-detection-enterprise-probe

Conversation

@claude

@claude claude Bot commented Jul 2, 2026

Copy link
Copy Markdown

Requested by Manuel Zedel · Slack thread

What changed

  • Preview/PR deployments are no longer treated as hosted. Before, the hosted check was a substring match on hosted.mender.io, so every PR preview under *.staging.hosted.mender.io (e.g. os-pr-2012.staging.hosted.mender.io) counted as a hosted instance. After, the real hosted hosts — hosted.mender.io, eu.hosted.mender.io, hosted.mender.cn, and staging hosts like staging.hosted.mender.io — are recognized, while per-PR preview deployments (a leading -pr-<number> subdomain label) are excluded.
  • Enterprise environments are now detected on non-hosted (on-prem) installs. Before, getUserOrganization was only fetched when a multitenancy/hosted/enterprise flag was already set, so an on-prem enterprise install could not be distinguished from OS. After, core init always probes the organization endpoint and writes the result to the store: a non-hosted install where the org endpoint is reachable is classified as on-prem enterprise; if the probe fails it is treated as OS; hosted is unchanged. Combined with the hosted flag, this separates OS / on-prem enterprise / hosted.

How

  • packages/store/src/storehooks.ts: parseEnvironmentInfo builds the hosted-domain list from the locations constant and uses isHostedHostname() (a domain match minus a -pr-<n> preview check) instead of the substring test. A new probeOrganizationCapabilities thunk runs after parseEnvironmentInfo, reads the resolved isHosted, dispatches getUserOrganization().unwrap(), and on success (non-hosted) sets { hasMultitenancy: true, isEnterprise: true } via setFeatures, and on failure sets them false. retrieveCoreData sequences the probe and no longer gates on pre-set flags.
  • Tests added in packages/store/src/storehooks.test.tsx for the hostname cases and the three probe outcomes; packages/store/setupTests.ts exports the msw server for handler overrides.

Testing

  • npx turbo run test-ci lint format:check --filter=@northern.tech/store → 267 tests pass, lint + format clean.

Notes / follow-ups

  • The -pr-<number> preview-host pattern is inferred — no authoritative naming convention was found in the repo or CI config. If preview deployments use a different subdomain shape, the isHostedHostname() preview check will need adjusting.

claude added 2 commits July 2, 2026 19:25
Previously isHosted was derived from a substring check against
'hosted.mender.io', which also matched per-PR preview deployments such as
os-pr-2012.staging.hosted.mender.io, wrongly flagging them as a hosted
production environment.

Derive the hosted domains from the locations constant and treat a host as
hosted when it equals or is a subdomain of one of them (so regular staging
hosts like staging.hosted.mender.io stay hosted), while excluding per-PR
preview deployments identified by a leading <component>-pr-<number> label.
The explicit isHosted feature flag still forces hosted mode.

Signed-off-by: Claude <noreply@anthropic.com>
…point

Core init previously only fetched the organization when hasMultitenancy,
isHosted or isEnterprise was already true, so a non-hosted deployment that
never pre-set those flags could not be recognised as enterprise even when
it exposed the organization endpoint.

Always probe getUserOrganization after parseEnvironmentInfo (so the final
isHosted value is available) and classify the deployment from the outcome:
a reachable endpoint on a non-hosted deployment marks it multitenant
enterprise (setFeatures hasMultitenancy/isEnterprise true), an unreachable
one marks it a single-tenant OS install (both false). Hosted deployments
are left untouched so their enterprise status stays plan-derived via
getIsEnterprise. The rejection is caught so core init still resolves.

The store setupTests server is exported so tests can override the
organization handler to exercise the failure path.

Signed-off-by: Claude <noreply@anthropic.com>
@mzedel mzedel marked this pull request as ready for review July 3, 2026 16:54
@mzedel mzedel requested a review from a team as a code owner July 3, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant