From 3414896f4103a3d2c3a1d27c6e7f8ce7c71c80c0 Mon Sep 17 00:00:00 2001 From: Kelly Date: Tue, 28 Jul 2026 14:45:11 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20[FFL-2597]=20add=20feature=20flags?= =?UTF-8?q?=20tab=20with=20OAuth=20sign-in?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the Flags tab (gated behind datadogMode) with an OAuth authorization_code + PKCE sign-in against Datadog's first-party OAuth server, the connect screen, and site handling. The selected site is validated against the js-core site allowlist before building any OAuth/API host, and the callback domain is checked against it. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/common/extension.types.ts | 2 + .../src/common/panelTabConstants.ts | 1 + .../src/panel/components/panel.tsx | 11 + .../tabs/flagsTab/connectScreen.tsx | 78 +++++++ .../components/tabs/flagsTab/flagsTab.tsx | 31 +++ .../panel/components/tabs/flagsTab/index.ts | 1 + .../components/tabs/flagsTab/oauth.spec.ts | 75 +++++++ .../panel/components/tabs/flagsTab/oauth.ts | 192 ++++++++++++++++++ .../components/tabs/flagsTab/useFlagAuth.ts | 80 ++++++++ .../src/panel/hooks/useSettings.ts | 1 + developer-extension/wxt.config.ts | 2 +- 11 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 developer-extension/src/panel/components/tabs/flagsTab/connectScreen.tsx create mode 100644 developer-extension/src/panel/components/tabs/flagsTab/flagsTab.tsx create mode 100644 developer-extension/src/panel/components/tabs/flagsTab/index.ts create mode 100644 developer-extension/src/panel/components/tabs/flagsTab/oauth.spec.ts create mode 100644 developer-extension/src/panel/components/tabs/flagsTab/oauth.ts create mode 100644 developer-extension/src/panel/components/tabs/flagsTab/useFlagAuth.ts diff --git a/developer-extension/src/common/extension.types.ts b/developer-extension/src/common/extension.types.ts index aeb15404ae..5a86b64247 100644 --- a/developer-extension/src/common/extension.types.ts +++ b/developer-extension/src/common/extension.types.ts @@ -57,4 +57,6 @@ export interface Settings { logsConfigurationOverride: object | null debugMode: boolean datadogMode: boolean + // Datadog site used for the feature-flag OAuth flow + catalog fetch. + flagsSite: string } diff --git a/developer-extension/src/common/panelTabConstants.ts b/developer-extension/src/common/panelTabConstants.ts index f0fb92b2d7..2041ad3b3e 100644 --- a/developer-extension/src/common/panelTabConstants.ts +++ b/developer-extension/src/common/panelTabConstants.ts @@ -3,6 +3,7 @@ export const enum PanelTabs { Infos = 'infos', Settings = 'settings', Replay = 'replay', + Flags = 'flags', } export const DEFAULT_PANEL_TAB = PanelTabs.Events diff --git a/developer-extension/src/panel/components/panel.tsx b/developer-extension/src/panel/components/panel.tsx index cca7d405d2..6656dd1f8e 100644 --- a/developer-extension/src/panel/components/panel.tsx +++ b/developer-extension/src/panel/components/panel.tsx @@ -13,6 +13,7 @@ import { SettingsTab } from './tabs/settingsTab' import { InfosTab } from './tabs/infosTab' import { EventsTab, DEFAULT_COLUMNS } from './tabs/eventsTab' import { ReplayTab } from './tabs/replayTab' +import { FlagsTab } from './tabs/flagsTab' import * as classes from './panel.module.css' @@ -53,6 +54,11 @@ export function Panel() { Live replay + {settings.datadogMode && ( + + Feature Flags + + )} + {settings.datadogMode && ( + + + + )} diff --git a/developer-extension/src/panel/components/tabs/flagsTab/connectScreen.tsx b/developer-extension/src/panel/components/tabs/flagsTab/connectScreen.tsx new file mode 100644 index 0000000000..83228de118 --- /dev/null +++ b/developer-extension/src/panel/components/tabs/flagsTab/connectScreen.tsx @@ -0,0 +1,78 @@ +import { Anchor, Badge, Button, Center, Group, Select, Stack, Text } from '@mantine/core' +import React, { useState } from 'react' +import { useSettings } from '../../../hooks/useSettings' +import type { FlagAuthState } from './useFlagAuth' +import { FLAG_SITES } from './oauth' + +export function ConnectScreen({ auth }: { auth: FlagAuthState }) { + const [advancedOpen, setAdvancedOpen] = useState(false) + + return ( +
+ + + Authenticate with Datadog to access your feature flags + + + {auth.error && ( + + {auth.error} + + )} + + setAdvancedOpen((open) => !open)}> + {advancedOpen ? '− Hide advanced' : 'Advanced: site'} + + {advancedOpen && ( + + + + )} + +
+ ) +} + +export function ConnectionHeader({ auth }: { auth: FlagAuthState }) { + return ( + + + + + Connected via OAuth + + + {auth.site} + + + + + {/* Surface disconnect failures here too — otherwise a failed Disconnect looks like a no-op. */} + {auth.error && ( + + {auth.error} + + )} + + ) +} + +function SiteField() { + const [{ flagsSite }, setSetting] = useSettings() + + return ( +