From 80c536364973dd09e92ca8b1fd2aaca4328b934e Mon Sep 17 00:00:00 2001 From: "Pablo Fernandez Guerra (PFE)" <148432447+pfe-nazaries@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:09:35 +0200 Subject: [PATCH] refactor(ui): rename integration enable flags to past tense (#11917) Co-authored-by: Pablo F.G --- .env | 2 +- .../developer-guide/environment-variables.mdx | 8 ++-- ui/Dockerfile | 8 ++-- ui/app/(auth)/layout.tsx | 2 +- .../enable-flags-past-tense.changed.md | 1 + ui/instrumentation.ts | 2 +- ui/lib/env.test.ts | 22 ++++----- ui/lib/integrations.test.ts | 48 +++++++++---------- ui/lib/integrations.ts | 8 ++-- ui/lib/runtime-config.ts | 12 ++--- ui/lib/runtime-env.test.ts | 20 ++++---- ui/sentry/sentry.edge.config.test.ts | 6 +-- ui/sentry/sentry.edge.config.ts | 4 +- ui/sentry/sentry.server.config.test.ts | 6 +-- ui/sentry/sentry.server.config.ts | 4 +- ui/tests/runtime-config/runtime-config.md | 6 +-- ui/types/env.d.ts | 6 +-- 17 files changed, 83 insertions(+), 82 deletions(-) create mode 100644 ui/changelog.d/enable-flags-past-tense.changed.md diff --git a/.env b/.env index 8ee0951df1..e4a634cf71 100644 --- a/.env +++ b/.env @@ -146,7 +146,7 @@ DJANGO_SENTRY_DSN= DJANGO_THROTTLE_TOKEN_OBTAIN=50/minute # Sentry for the web app (server + browser). The UI_SENTRY_* values load only -# when UI_SENTRY_ENABLE="true"; without it they are ignored (default off, zero +# when UI_SENTRY_ENABLED="true"; without it they are ignored (default off, zero # egress). The deprecated NEXT_PUBLIC_SENTRY_DSN still activates Sentry without # the flag. SENTRY_RELEASE (unprefixed) feeds the web app's server/edge SDKs. UI_SENTRY_DSN= diff --git a/docs/developer-guide/environment-variables.mdx b/docs/developer-guide/environment-variables.mdx index ce51e06bbb..33e3567251 100644 --- a/docs/developer-guide/environment-variables.mdx +++ b/docs/developer-guide/environment-variables.mdx @@ -45,16 +45,16 @@ Prowler App gates each optional third-party integration behind an explicit enabl | Integration | Enable flag | Required configuration when enabled | |-------------|-------------|-------------------------------------| -| Sentry (error monitoring) | `UI_SENTRY_ENABLE` | `UI_SENTRY_DSN` | -| Google Tag Manager | `UI_GOOGLE_TAG_MANAGER_ENABLE` | `UI_GOOGLE_TAG_MANAGER_ID` | -| PostHog (product analytics) | `UI_POSTHOG_ENABLE` | `UI_POSTHOG_KEY` and `UI_POSTHOG_HOST` | +| Sentry (error monitoring) | `UI_SENTRY_ENABLED` | `UI_SENTRY_DSN` | +| Google Tag Manager | `UI_GOOGLE_TAG_MANAGER_ENABLED` | `UI_GOOGLE_TAG_MANAGER_ID` | +| PostHog (product analytics) | `UI_POSTHOG_ENABLED` | `UI_POSTHOG_KEY` and `UI_POSTHOG_HOST` | When an integration is enabled but its required configuration is missing, Prowler App fails fast at server startup with a clear error, so a misconfigured container never starts silently. A new `UI_*` value set while its enable flag is not `"true"` is ignored, and the server logs a one-time startup warning noting that the integration will not load. Legacy names follow the backward-compatible rule described in [Deprecated Names](#deprecated-names). PostHog support is currently limited to configuration validation: Prowler App reads and validates the PostHog variables but does not yet load a PostHog client. -Configuring an integration through the new `UI_*` variables now requires its enable flag. A deployment that adopted `UI_SENTRY_DSN` or `UI_GOOGLE_TAG_MANAGER_ID` must also set `UI_SENTRY_ENABLE=true` or `UI_GOOGLE_TAG_MANAGER_ENABLE=true` to keep the integration active. Deployments still using the legacy names (`NEXT_PUBLIC_*`, or `POSTHOG_KEY` and `POSTHOG_HOST`) keep working without the flag. +Configuring an integration through the new `UI_*` variables now requires its enable flag. A deployment that adopted `UI_SENTRY_DSN` or `UI_GOOGLE_TAG_MANAGER_ID` must also set `UI_SENTRY_ENABLED=true` or `UI_GOOGLE_TAG_MANAGER_ENABLED=true` to keep the integration active. Deployments still using the legacy names (`NEXT_PUBLIC_*`, or `POSTHOG_KEY` and `POSTHOG_HOST`) keep working without the flag. ## Upcoming Breaking Change diff --git a/ui/Dockerfile b/ui/Dockerfile index 03d50be231..6ab9752972 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -79,12 +79,12 @@ ENV HOSTNAME="0.0.0.0" # Helm/K8s): # - required: UI_API_BASE_URL, AUTH_URL, AUTH_SECRET (missing ⇒ fail fast at boot) # - optional: UI_API_DOCS_URL -# - gated integrations (load only when *_ENABLE="true"; the value is then +# - gated integrations (load only when *_ENABLED="true"; the value is then # required or boot fails). Legacy names (NEXT_PUBLIC_*, POSTHOG_KEY/HOST) # still activate without the flag: -# UI_SENTRY_ENABLE + UI_SENTRY_DSN (+ optional UI_SENTRY_ENVIRONMENT) -# UI_GOOGLE_TAG_MANAGER_ENABLE + UI_GOOGLE_TAG_MANAGER_ID -# UI_POSTHOG_ENABLE + UI_POSTHOG_KEY + UI_POSTHOG_HOST (no consumer yet) +# UI_SENTRY_ENABLED + UI_SENTRY_DSN (+ optional UI_SENTRY_ENVIRONMENT) +# UI_GOOGLE_TAG_MANAGER_ENABLED + UI_GOOGLE_TAG_MANAGER_ID +# UI_POSTHOG_ENABLED + UI_POSTHOG_KEY + UI_POSTHOG_HOST (no consumer yet) # - reserved: REO_DEV_CLIENT_ID (no consumer yet) # server.js is created by next build from the standalone output # https://nextjs.org/docs/pages/api-reference/next-config-js/output diff --git a/ui/app/(auth)/layout.tsx b/ui/app/(auth)/layout.tsx index 4513f12efb..27fff93fe5 100644 --- a/ui/app/(auth)/layout.tsx +++ b/ui/app/(auth)/layout.tsx @@ -43,7 +43,7 @@ export default async function AuthLayout({ await connection(); const gtmId = readGatedEnv( - "UI_GOOGLE_TAG_MANAGER_ENABLE", + "UI_GOOGLE_TAG_MANAGER_ENABLED", "UI_GOOGLE_TAG_MANAGER_ID", "NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID", ); diff --git a/ui/changelog.d/enable-flags-past-tense.changed.md b/ui/changelog.d/enable-flags-past-tense.changed.md new file mode 100644 index 0000000000..41451a464c --- /dev/null +++ b/ui/changelog.d/enable-flags-past-tense.changed.md @@ -0,0 +1 @@ +UI integration enable flags renamed to past tense — `UI_SENTRY_ENABLE` → `UI_SENTRY_ENABLED`, `UI_GOOGLE_TAG_MANAGER_ENABLE` → `UI_GOOGLE_TAG_MANAGER_ENABLED`, `UI_POSTHOG_ENABLE` → `UI_POSTHOG_ENABLED`; deployments that set the former names must update them diff --git a/ui/instrumentation.ts b/ui/instrumentation.ts index be157251e5..c9793bddf7 100644 --- a/ui/instrumentation.ts +++ b/ui/instrumentation.ts @@ -22,7 +22,7 @@ import * as Sentry from "@sentry/nextjs"; import { readGatedEnv } from "@/lib/integrations"; const sentryDsn = readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ); diff --git a/ui/lib/env.test.ts b/ui/lib/env.test.ts index 1b4bb8df12..3c696a8baf 100644 --- a/ui/lib/env.test.ts +++ b/ui/lib/env.test.ts @@ -49,15 +49,15 @@ describe("lib/env gated integration validation", () => { // Clear every gated flag/config so ambient shell env cannot affect assertions, // then satisfy the unconditional REQUIRED vars (they are checked first). const GATED_ENV_VARS = [ - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", "UI_SENTRY_ENVIRONMENT", "NEXT_PUBLIC_SENTRY_ENVIRONMENT", - "UI_GOOGLE_TAG_MANAGER_ENABLE", + "UI_GOOGLE_TAG_MANAGER_ENABLED", "UI_GOOGLE_TAG_MANAGER_ID", "NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID", - "UI_POSTHOG_ENABLE", + "UI_POSTHOG_ENABLED", "UI_POSTHOG_KEY", "POSTHOG_KEY", "UI_POSTHOG_HOST", @@ -80,14 +80,14 @@ describe("lib/env gated integration validation", () => { vi.restoreAllMocks(); }); - it("throws when UI_SENTRY_ENABLE is true but the DSN is unset", async () => { - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + it("throws when UI_SENTRY_ENABLED is true but the DSN is unset", async () => { + vi.stubEnv("UI_SENTRY_ENABLED", "true"); await expect(import("@/lib/env")).rejects.toThrow("UI_SENTRY_DSN"); }); - it("resolves when UI_SENTRY_ENABLE is true and the DSN is present", async () => { - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + it("resolves when UI_SENTRY_ENABLED is true and the DSN is present", async () => { + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); await expect(import("@/lib/env")).resolves.toBeDefined(); @@ -99,8 +99,8 @@ describe("lib/env gated integration validation", () => { await expect(import("@/lib/env")).resolves.toBeDefined(); }); - it("throws when UI_GOOGLE_TAG_MANAGER_ENABLE is true without an id", async () => { - vi.stubEnv("UI_GOOGLE_TAG_MANAGER_ENABLE", "true"); + it("throws when UI_GOOGLE_TAG_MANAGER_ENABLED is true without an id", async () => { + vi.stubEnv("UI_GOOGLE_TAG_MANAGER_ENABLED", "true"); await expect(import("@/lib/env")).rejects.toThrow( "UI_GOOGLE_TAG_MANAGER_ID", @@ -108,14 +108,14 @@ describe("lib/env gated integration validation", () => { }); it("throws on UI_POSTHOG_HOST when PostHog is enabled with only the key", async () => { - vi.stubEnv("UI_POSTHOG_ENABLE", "true"); + vi.stubEnv("UI_POSTHOG_ENABLED", "true"); vi.stubEnv("UI_POSTHOG_KEY", "phc_key"); await expect(import("@/lib/env")).rejects.toThrow("UI_POSTHOG_HOST"); }); it("resolves when PostHog is enabled with both key and host", async () => { - vi.stubEnv("UI_POSTHOG_ENABLE", "true"); + vi.stubEnv("UI_POSTHOG_ENABLED", "true"); vi.stubEnv("UI_POSTHOG_KEY", "phc_key"); vi.stubEnv("UI_POSTHOG_HOST", "https://eu.i.posthog.com"); diff --git a/ui/lib/integrations.test.ts b/ui/lib/integrations.test.ts index 78fd59b67f..6565cf3a46 100644 --- a/ui/lib/integrations.test.ts +++ b/ui/lib/integrations.test.ts @@ -9,15 +9,15 @@ import { // Every env var any gated integration reads. Cleared before each test so the // assertions never depend on ambient shell/CI env. const GATED_ENV_VARS = [ - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", "UI_SENTRY_ENVIRONMENT", "NEXT_PUBLIC_SENTRY_ENVIRONMENT", - "UI_GOOGLE_TAG_MANAGER_ENABLE", + "UI_GOOGLE_TAG_MANAGER_ENABLED", "UI_GOOGLE_TAG_MANAGER_ID", "NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID", - "UI_POSTHOG_ENABLE", + "UI_POSTHOG_ENABLED", "UI_POSTHOG_KEY", "POSTHOG_KEY", "UI_POSTHOG_HOST", @@ -37,13 +37,13 @@ afterEach(() => { describe("readGatedEnv", () => { it("returns the primary value when the integration is enabled", () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); // When / Then expect( readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ), @@ -52,13 +52,13 @@ describe("readGatedEnv", () => { it("falls back to the legacy value when enabled and the primary is unset", () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("NEXT_PUBLIC_SENTRY_DSN", "https://legacy.example"); // When / Then expect( readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ), @@ -67,13 +67,13 @@ describe("readGatedEnv", () => { it("ignores the primary (new) value when disabled and no legacy is set", () => { // Given - the new UI_* name only counts when the enable flag is "true" - vi.stubEnv("UI_SENTRY_ENABLE", "false"); + vi.stubEnv("UI_SENTRY_ENABLED", "false"); vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); // When / Then expect( readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ), @@ -82,13 +82,13 @@ describe("readGatedEnv", () => { it("returns the legacy value when disabled (legacy ignores the enable flag)", () => { // Given - legacy names stay backward compatible: they work without the flag - vi.stubEnv("UI_SENTRY_ENABLE", "false"); + vi.stubEnv("UI_SENTRY_ENABLED", "false"); vi.stubEnv("NEXT_PUBLIC_SENTRY_DSN", "https://legacy.example"); // When / Then expect( readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ), @@ -97,14 +97,14 @@ describe("readGatedEnv", () => { it("returns the legacy value when disabled even if the new value is also set", () => { // Given - new value is ignored without the flag; legacy still activates - vi.stubEnv("UI_SENTRY_ENABLE", "false"); + vi.stubEnv("UI_SENTRY_ENABLED", "false"); vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); vi.stubEnv("NEXT_PUBLIC_SENTRY_DSN", "https://legacy.example"); // When / Then expect( readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ), @@ -116,7 +116,7 @@ describe("readGatedEnv", () => { vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); // When / Then - expect(readGatedEnv("UI_SENTRY_ENABLE", "UI_SENTRY_DSN")).toBeNull(); + expect(readGatedEnv("UI_SENTRY_ENABLED", "UI_SENTRY_DSN")).toBeNull(); }); }); @@ -127,7 +127,7 @@ describe("assertGatedIntegrations", () => { it("throws when Sentry is enabled but the DSN is unset", () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); // When / Then expect(() => assertGatedIntegrations()).toThrow("UI_SENTRY_DSN"); @@ -135,7 +135,7 @@ describe("assertGatedIntegrations", () => { it("does not throw when Sentry is enabled and the DSN is present", () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); // When / Then @@ -144,7 +144,7 @@ describe("assertGatedIntegrations", () => { it("accepts the legacy DSN name when Sentry is enabled", () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("NEXT_PUBLIC_SENTRY_DSN", "https://legacy.example"); // When / Then @@ -153,7 +153,7 @@ describe("assertGatedIntegrations", () => { it("does not require the optional Sentry environment when enabled", () => { // Given - DSN present, UI_SENTRY_ENVIRONMENT intentionally unset - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); // When / Then @@ -162,7 +162,7 @@ describe("assertGatedIntegrations", () => { it("throws when GTM is enabled without an id", () => { // Given - vi.stubEnv("UI_GOOGLE_TAG_MANAGER_ENABLE", "true"); + vi.stubEnv("UI_GOOGLE_TAG_MANAGER_ENABLED", "true"); // When / Then expect(() => assertGatedIntegrations()).toThrow("UI_GOOGLE_TAG_MANAGER_ID"); @@ -170,7 +170,7 @@ describe("assertGatedIntegrations", () => { it("requires BOTH UI_POSTHOG_KEY and UI_POSTHOG_HOST when PostHog is enabled", () => { // Given - key set, host missing - vi.stubEnv("UI_POSTHOG_ENABLE", "true"); + vi.stubEnv("UI_POSTHOG_ENABLED", "true"); vi.stubEnv("UI_POSTHOG_KEY", "phc_key"); // When / Then @@ -179,7 +179,7 @@ describe("assertGatedIntegrations", () => { it("does not throw when PostHog is enabled with both key and host", () => { // Given - vi.stubEnv("UI_POSTHOG_ENABLE", "true"); + vi.stubEnv("UI_POSTHOG_ENABLED", "true"); vi.stubEnv("UI_POSTHOG_KEY", "phc_key"); vi.stubEnv("UI_POSTHOG_HOST", "https://eu.i.posthog.com"); @@ -196,7 +196,7 @@ describe("assertGatedIntegrations", () => { }); it("accepts the legacy PostHog names without the enable flag", () => { - // Given - both legacy names present, no UI_POSTHOG_ENABLE + // Given - both legacy names present, no UI_POSTHOG_ENABLED vi.stubEnv("POSTHOG_KEY", "phc_key"); vi.stubEnv("POSTHOG_HOST", "https://eu.i.posthog.com"); @@ -224,13 +224,13 @@ describe("warnGatedIntegrationsMisconfig", () => { // Then expect(warn).toHaveBeenCalledTimes(1); - expect(warn.mock.calls[0][0]).toContain("UI_SENTRY_ENABLE"); + expect(warn.mock.calls[0][0]).toContain("UI_SENTRY_ENABLED"); }); it("does not warn when the integration is enabled", () => { // Given const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://dsn.example"); // When diff --git a/ui/lib/integrations.ts b/ui/lib/integrations.ts index a5441a2e7b..dca756cf2e 100644 --- a/ui/lib/integrations.ts +++ b/ui/lib/integrations.ts @@ -1,7 +1,7 @@ import { readBoolEnv, readEnv } from "@/lib/runtime-env"; // Single source of truth for the third-party integrations gated behind a -// UI_*_ENABLE flag. The same map drives boot validation (lib/env.ts) and the +// UI_*_ENABLED flag. The same map drives boot validation (lib/env.ts) and the // runtime-config gating (lib/runtime-config.ts) so the two cannot drift. // // Two activation paths, applied uniformly to every integration: @@ -27,7 +27,7 @@ interface GatedIntegration { export const GATED_INTEGRATIONS: Record = { sentry: { name: "Sentry", - enableKey: "UI_SENTRY_ENABLE", + enableKey: "UI_SENTRY_ENABLED", required: [{ key: "UI_SENTRY_DSN", legacy: "NEXT_PUBLIC_SENTRY_DSN" }], optional: [ { @@ -38,7 +38,7 @@ export const GATED_INTEGRATIONS: Record = { }, googleTagManager: { name: "Google Tag Manager", - enableKey: "UI_GOOGLE_TAG_MANAGER_ENABLE", + enableKey: "UI_GOOGLE_TAG_MANAGER_ENABLED", required: [ { key: "UI_GOOGLE_TAG_MANAGER_ID", @@ -49,7 +49,7 @@ export const GATED_INTEGRATIONS: Record = { }, posthog: { name: "PostHog", - enableKey: "UI_POSTHOG_ENABLE", + enableKey: "UI_POSTHOG_ENABLED", required: [ { key: "UI_POSTHOG_KEY", legacy: "POSTHOG_KEY" }, { key: "UI_POSTHOG_HOST", legacy: "POSTHOG_HOST" }, diff --git a/ui/lib/runtime-config.ts b/ui/lib/runtime-config.ts index fca2b088b1..9c149355e5 100644 --- a/ui/lib/runtime-config.ts +++ b/ui/lib/runtime-config.ts @@ -10,36 +10,36 @@ import { readBoolEnv, readEnv } from "@/lib/runtime-env"; // only this allowlist reaches the client. Each migrated key falls back to its // deprecated NEXT_PUBLIC_* name during migration (see readEnv). Gated // integrations (Sentry/GTM/PostHog) resolve to their value only when the -// matching UI_*_ENABLE flag is "true", else null — boot validation +// matching UI_*_ENABLED flag is "true", else null — boot validation // (lib/env.ts) guarantees the value is present whenever the flag is set. export async function getRuntimePublicConfig(): Promise { await connection(); return { sentryDsn: readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ), sentryEnvironment: readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_ENVIRONMENT", "NEXT_PUBLIC_SENTRY_ENVIRONMENT", ), googleTagManagerId: readGatedEnv( - "UI_GOOGLE_TAG_MANAGER_ENABLE", + "UI_GOOGLE_TAG_MANAGER_ENABLED", "UI_GOOGLE_TAG_MANAGER_ID", "NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID", ), apiBaseUrl: readEnv("UI_API_BASE_URL", "NEXT_PUBLIC_API_BASE_URL"), apiDocsUrl: readEnv("UI_API_DOCS_URL", "NEXT_PUBLIC_API_DOCS_URL"), posthogKey: readGatedEnv( - "UI_POSTHOG_ENABLE", + "UI_POSTHOG_ENABLED", "UI_POSTHOG_KEY", "POSTHOG_KEY", ), posthogHost: readGatedEnv( - "UI_POSTHOG_ENABLE", + "UI_POSTHOG_ENABLED", "UI_POSTHOG_HOST", "POSTHOG_HOST", ), diff --git a/ui/lib/runtime-env.test.ts b/ui/lib/runtime-env.test.ts index 723ecfdeb0..7735622c89 100644 --- a/ui/lib/runtime-env.test.ts +++ b/ui/lib/runtime-env.test.ts @@ -81,43 +81,43 @@ describe("readBoolEnv", () => { it('is true only for the exact string "true"', () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); // When / Then - expect(readBoolEnv("UI_SENTRY_ENABLE")).toBe(true); + expect(readBoolEnv("UI_SENTRY_ENABLED")).toBe(true); }); it("trims surrounding whitespace before comparing", () => { // Given - clean() does not trim a non-empty value, so readBoolEnv must - vi.stubEnv("UI_SENTRY_ENABLE", " true "); + vi.stubEnv("UI_SENTRY_ENABLED", " true "); // When / Then - expect(readBoolEnv("UI_SENTRY_ENABLE")).toBe(true); + expect(readBoolEnv("UI_SENTRY_ENABLED")).toBe(true); }); it("is false when unset", () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", undefined); + vi.stubEnv("UI_SENTRY_ENABLED", undefined); // When / Then - expect(readBoolEnv("UI_SENTRY_ENABLE")).toBe(false); + expect(readBoolEnv("UI_SENTRY_ENABLED")).toBe(false); }); it('is false for "false"', () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "false"); + vi.stubEnv("UI_SENTRY_ENABLED", "false"); // When / Then - expect(readBoolEnv("UI_SENTRY_ENABLE")).toBe(false); + expect(readBoolEnv("UI_SENTRY_ENABLED")).toBe(false); }); it('is false for other truthy-looking values ("TRUE", "1", "yes")', () => { for (const value of ["TRUE", "1", "yes"]) { // Given - vi.stubEnv("UI_SENTRY_ENABLE", value); + vi.stubEnv("UI_SENTRY_ENABLED", value); // When / Then - expect(readBoolEnv("UI_SENTRY_ENABLE")).toBe(false); + expect(readBoolEnv("UI_SENTRY_ENABLED")).toBe(false); } }); }); diff --git a/ui/sentry/sentry.edge.config.test.ts b/ui/sentry/sentry.edge.config.test.ts index c0ac2625a3..f831c045ea 100644 --- a/ui/sentry/sentry.edge.config.test.ts +++ b/ui/sentry/sentry.edge.config.test.ts @@ -20,7 +20,7 @@ describe("sentry.edge.config", () => { it("should initialize with the resolved environment and reduced edge sampling", async () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); vi.stubEnv("UI_SENTRY_ENVIRONMENT", "pro"); @@ -46,7 +46,7 @@ describe("sentry.edge.config", () => { expect(initMock).not.toHaveBeenCalled(); }); - it("should not initialize when UI_SENTRY_ENABLE is unset even if a DSN is set", async () => { + it("should not initialize when UI_SENTRY_ENABLED is unset even if a DSN is set", async () => { // Given - DSN configured but the enable flag is not "true" vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); @@ -59,7 +59,7 @@ describe("sentry.edge.config", () => { it("should default to a non-dev environment so an unset UI_SENTRY_ENVIRONMENT does not enable dev sampling", async () => { // Given - enabled with a DSN but environment unset - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); // When diff --git a/ui/sentry/sentry.edge.config.ts b/ui/sentry/sentry.edge.config.ts index 665b5b57b8..f4f10d0566 100644 --- a/ui/sentry/sentry.edge.config.ts +++ b/ui/sentry/sentry.edge.config.ts @@ -3,12 +3,12 @@ import * as Sentry from "@sentry/nextjs"; import { readGatedEnv } from "@/lib/integrations"; const sentryDsn = readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ); const sentryEnvironment = readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_ENVIRONMENT", "NEXT_PUBLIC_SENTRY_ENVIRONMENT", ); diff --git a/ui/sentry/sentry.server.config.test.ts b/ui/sentry/sentry.server.config.test.ts index 77e572827c..a77e7ff5e1 100644 --- a/ui/sentry/sentry.server.config.test.ts +++ b/ui/sentry/sentry.server.config.test.ts @@ -21,7 +21,7 @@ describe("sentry.server.config", () => { it("should initialize with the resolved environment and production sampling", async () => { // Given - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); vi.stubEnv("UI_SENTRY_ENVIRONMENT", "pro"); @@ -48,7 +48,7 @@ describe("sentry.server.config", () => { expect(initMock).not.toHaveBeenCalled(); }); - it("should not initialize when UI_SENTRY_ENABLE is unset even if a DSN is set", async () => { + it("should not initialize when UI_SENTRY_ENABLED is unset even if a DSN is set", async () => { // Given - DSN configured but the enable flag is not "true" vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); @@ -61,7 +61,7 @@ describe("sentry.server.config", () => { it("should default to a non-dev environment so an unset UI_SENTRY_ENVIRONMENT does not enable dev sampling", async () => { // Given - enabled with a DSN but environment unset - vi.stubEnv("UI_SENTRY_ENABLE", "true"); + vi.stubEnv("UI_SENTRY_ENABLED", "true"); vi.stubEnv("UI_SENTRY_DSN", "https://key@o0.ingest.sentry.io/1"); // When diff --git a/ui/sentry/sentry.server.config.ts b/ui/sentry/sentry.server.config.ts index 8ea3b54615..3a3ac491da 100644 --- a/ui/sentry/sentry.server.config.ts +++ b/ui/sentry/sentry.server.config.ts @@ -3,12 +3,12 @@ import * as Sentry from "@sentry/nextjs"; import { readGatedEnv } from "@/lib/integrations"; const sentryDsn = readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_DSN", "NEXT_PUBLIC_SENTRY_DSN", ); const sentryEnvironment = readGatedEnv( - "UI_SENTRY_ENABLE", + "UI_SENTRY_ENABLED", "UI_SENTRY_ENVIRONMENT", "NEXT_PUBLIC_SENTRY_ENVIRONMENT", ); diff --git a/ui/tests/runtime-config/runtime-config.md b/ui/tests/runtime-config/runtime-config.md index 6b4246056c..ddc21457c6 100644 --- a/ui/tests/runtime-config/runtime-config.md +++ b/ui/tests/runtime-config/runtime-config.md @@ -3,7 +3,7 @@ **Suite ID:** `RUNTIME-CONFIG-E2E` **Feature:** Runtime resolution of public client config via an inert JSON data island injected into `` (Sentry, GTM, API base/docs URL, and reserved keys). Each third-party integration -resolves to a value only when its `UI_*_ENABLE` flag is `"true"`, so a disabled +resolves to a value only when its `UI_*_ENABLED` flag is `"true"`, so a disabled integration is exposed as `null`. --- @@ -42,7 +42,7 @@ integration is exposed as `null`. **Preconditions:** -- UI server running. Sentry may be enabled (`UI_SENTRY_ENABLE=true` with `UI_SENTRY_DSN`) or off. +- UI server running. Sentry may be enabled (`UI_SENTRY_ENABLED=true` with `UI_SENTRY_DSN`) or off. ### Flow Steps @@ -70,7 +70,7 @@ integration is exposed as `null`. **Preconditions:** -- UI server running with Sentry and Google Tag Manager disabled — their `UI_SENTRY_ENABLE` and `UI_GOOGLE_TAG_MANAGER_ENABLE` flags unset, the Enterprise default — so the island exposes both as `null` (the test skips when either is enabled and configured). +- UI server running with Sentry and Google Tag Manager disabled — their `UI_SENTRY_ENABLED` and `UI_GOOGLE_TAG_MANAGER_ENABLED` flags unset, the Enterprise default — so the island exposes both as `null` (the test skips when either is enabled and configured). ### Flow Steps diff --git a/ui/types/env.d.ts b/ui/types/env.d.ts index 28b0865455..301a59802d 100644 --- a/ui/types/env.d.ts +++ b/ui/types/env.d.ts @@ -15,12 +15,12 @@ declare global { NEXT_PUBLIC_API_DOCS_URL?: string; UI_API_DOCS_URL?: string; - UI_GOOGLE_TAG_MANAGER_ENABLE?: "true" | "false"; + UI_GOOGLE_TAG_MANAGER_ENABLED?: "true" | "false"; /** @deprecated use UI_GOOGLE_TAG_MANAGER_ID */ NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID?: string; UI_GOOGLE_TAG_MANAGER_ID?: string; - UI_SENTRY_ENABLE?: "true" | "false"; + UI_SENTRY_ENABLED?: "true" | "false"; /** @deprecated use UI_SENTRY_DSN */ NEXT_PUBLIC_SENTRY_DSN?: string; UI_SENTRY_DSN?: string; @@ -46,7 +46,7 @@ declare global { SENTRY_PROJECT?: string; SENTRY_AUTH_TOKEN?: string; - UI_POSTHOG_ENABLE?: "true" | "false"; + UI_POSTHOG_ENABLED?: "true" | "false"; /** @deprecated use UI_POSTHOG_KEY */ POSTHOG_KEY?: string; UI_POSTHOG_KEY?: string;