refactor(ui): rename integration enable flags to past tense (#11917)

Co-authored-by: Pablo F.G <pablo.fernandez@prowler.com>
This commit is contained in:
Pablo Fernandez Guerra (PFE)
2026-07-09 13:09:35 +02:00
committed by GitHub
parent 9d899ae0e2
commit 80c5363649
17 changed files with 83 additions and 82 deletions
+1 -1
View File
@@ -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=
@@ -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.
<Warning>
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.
</Warning>
## Upcoming Breaking Change
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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",
);
@@ -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
+1 -1
View File
@@ -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",
);
+11 -11
View File
@@ -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");
+24 -24
View File
@@ -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
+4 -4
View File
@@ -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<string, GatedIntegration> = {
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<string, GatedIntegration> = {
},
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<string, GatedIntegration> = {
},
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" },
+6 -6
View File
@@ -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<RuntimePublicConfig> {
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",
),
+10 -10
View File
@@ -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);
}
});
});
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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",
);
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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",
);
+3 -3
View File
@@ -3,7 +3,7 @@
**Suite ID:** `RUNTIME-CONFIG-E2E`
**Feature:** Runtime resolution of public client config via an inert JSON data
island injected into `<head>` (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
+3 -3
View File
@@ -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;