From 2a0306e3895b2cf1f6f1c16e7a9b0b1b9cb96851 Mon Sep 17 00:00:00 2001 From: Santosh Sahu Date: Mon, 7 Sep 2026 21:30:45 +0530 Subject: [PATCH] DC-2870: Respect gen_ai.enabled and config enabled_frameworks allowlist HA_GEN_AI_ENABLED=false (gen_ai.enabled) now disables all AI instrumentation. When enabled_frameworks is set in config YAML (including an empty list), it acts as the authoritative allowlist and HARNESS_ENABLE_AI_* env flags no longer override it. Env flags apply only when enabled_frameworks is omitted. Co-authored-by: Cursor --- src/harness_sdk/config/config.py | 19 ++++++++------- src/harness_sdk/config/default.py | 2 +- .../instrumentation_definitions.py | 21 ++++++++++++---- test/instrumentation/test_opt_in_gating.py | 24 ++++++++++++++----- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/harness_sdk/config/config.py b/src/harness_sdk/config/config.py index b6f828b..8edb1af 100644 --- a/src/harness_sdk/config/config.py +++ b/src/harness_sdk/config/config.py @@ -97,14 +97,17 @@ def build_config(): plugins_config = config_dict.pop('plugins', {}) gen_ai_config = config_dict.get('gen_ai', {}) - enabled_ai_frameworks = gen_ai_config.pop('enabled_frameworks', []) - if not isinstance(enabled_ai_frameworks, list): - enabled_ai_frameworks = [] - enabled_ai_frameworks = [ - str(name).strip() - for name in enabled_ai_frameworks - if str(name).strip() - ] + if 'enabled_frameworks' in gen_ai_config: + enabled_ai_frameworks = gen_ai_config.pop('enabled_frameworks', []) + if not isinstance(enabled_ai_frameworks, list): + enabled_ai_frameworks = [] + enabled_ai_frameworks = [ + str(name).strip() + for name in enabled_ai_frameworks + if str(name).strip() + ] + else: + enabled_ai_frameworks = None enabled_control_plugins = _parse_plugin_env('CONTROL_PLUGINS') if enabled_control_plugins is None: diff --git a/src/harness_sdk/config/default.py b/src/harness_sdk/config/default.py index 00f6379..5068c55 100644 --- a/src/harness_sdk/config/default.py +++ b/src/harness_sdk/config/default.py @@ -42,7 +42,7 @@ 'deployment_name': '', }, 'gen_ai': { - 'enabled_frameworks': [], + 'enabled': True, 'payload_capture_enabled': False, 'payload_evaluation_enabled': True, }, diff --git a/src/harness_sdk/instrumentation/instrumentation_definitions.py b/src/harness_sdk/instrumentation/instrumentation_definitions.py index 57b7419..5d2c496 100644 --- a/src/harness_sdk/instrumentation/instrumentation_definitions.py +++ b/src/harness_sdk/instrumentation/instrumentation_definitions.py @@ -71,17 +71,28 @@ def any_ai_provider_enabled(enabled_ai_frameworks=None): ) +def _is_gen_ai_master_enabled() -> bool: + """Return False when gen_ai.enabled / HA_GEN_AI_ENABLED resolves to disabled.""" + from harness_sdk.config.config import Config # pylint: disable=import-outside-toplevel + + return Config().config.gen_ai.enabled.value + + def is_library_enabled(library_key, enabled_ai_frameworks=None): """Decide whether a supported library should be instrumented based on opt-in env flags.""" if library_key in AI_LIBRARY_ENV_FLAGS: + if not _is_gen_ai_master_enabled(): + return False + if enabled_ai_frameworks is not None: + configured_frameworks = { + _normalize_library_name(name) + for name in enabled_ai_frameworks + } + return _normalize_library_name(library_key) in configured_frameworks env_flag = AI_LIBRARY_ENV_FLAGS[library_key] if is_enable_flag_present(env_flag): return is_harness_flag_enabled(env_flag) - configured_frameworks = { - _normalize_library_name(name) - for name in (enabled_ai_frameworks or []) - } - return _normalize_library_name(library_key) in configured_frameworks + return False if library_key in API_LIBRARIES: return is_api_instrumentation_enabled() return False diff --git a/test/instrumentation/test_opt_in_gating.py b/test/instrumentation/test_opt_in_gating.py index df5f71d..2d3a3f4 100644 --- a/test/instrumentation/test_opt_in_gating.py +++ b/test/instrumentation/test_opt_in_gating.py @@ -55,18 +55,30 @@ def test_config_enables_ai_provider_when_env_is_unset(): assert any_ai_provider_enabled(["openai"]) is True -def test_explicit_ai_env_false_overrides_config(): +def test_explicit_ai_env_false_does_not_disable_configured_allowlist(): os.environ["HARNESS_ENABLE_AI_OPENAI"] = "false" - assert is_library_enabled(OPENAI_KEY, ["openai"]) is False - assert any_ai_provider_enabled(["openai"]) is False + assert is_library_enabled(OPENAI_KEY, ["openai"]) is True + assert any_ai_provider_enabled(["openai"]) is True -def test_explicit_ai_env_true_overrides_config(): +def test_explicit_ai_env_true_does_not_override_empty_config_allowlist(): os.environ["HARNESS_ENABLE_AI_OPENAI"] = "true" - assert is_library_enabled(OPENAI_KEY, []) is True - assert any_ai_provider_enabled([]) is True + assert is_library_enabled(OPENAI_KEY, []) is False + assert any_ai_provider_enabled([]) is False + + +def test_gen_ai_master_switch_disables_all_ai_providers(): + from harness_sdk.config.config import Config + + Config._instance = None + os.environ["HA_GEN_AI_ENABLED"] = "false" + os.environ["HARNESS_ENABLE_AI_OPENAI"] = "true" + Config() + + assert is_library_enabled(OPENAI_KEY) is False + assert any_ai_provider_enabled() is False def test_flag_requires_exact_true_value():